refactor: store refs in components
This commit is contained in:
@@ -12,12 +12,10 @@ type Props = {
|
|||||||
|
|
||||||
export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
||||||
const {
|
const {
|
||||||
|
autocompleteInputFocused,
|
||||||
autocompleteSearchQuery,
|
autocompleteSearchQuery,
|
||||||
autocompleteTagHintVisible,
|
autocompleteTagHintVisible,
|
||||||
autocompleteTagResults,
|
autocompleteTagResults,
|
||||||
autocompleteTagResultElements,
|
|
||||||
autocompleteInputElement,
|
|
||||||
tagElements,
|
|
||||||
tags,
|
tags,
|
||||||
} = appState.noteTags;
|
} = appState.noteTags;
|
||||||
|
|
||||||
@@ -26,6 +24,7 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
|||||||
useState<number | 'auto'>('auto');
|
useState<number | 'auto'>('auto');
|
||||||
|
|
||||||
const dropdownRef = useRef<HTMLDivElement>();
|
const dropdownRef = useRef<HTMLDivElement>();
|
||||||
|
const inputRef = useRef<HTMLInputElement>();
|
||||||
|
|
||||||
const [closeOnBlur] = useCloseOnBlur(dropdownRef, (visible: boolean) => {
|
const [closeOnBlur] = useCloseOnBlur(dropdownRef, (visible: boolean) => {
|
||||||
setDropdownVisible(visible);
|
setDropdownVisible(visible);
|
||||||
@@ -33,11 +32,9 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const showDropdown = () => {
|
const showDropdown = () => {
|
||||||
if (autocompleteInputElement) {
|
const { clientHeight } = document.documentElement;
|
||||||
const { clientHeight } = document.documentElement;
|
const inputRect = inputRef.current.getBoundingClientRect();
|
||||||
const inputRect = autocompleteInputElement.getBoundingClientRect();
|
setDropdownMaxHeight(clientHeight - inputRect.bottom - 32 * 2);
|
||||||
setDropdownMaxHeight(clientHeight - inputRect.bottom - 32 * 2);
|
|
||||||
}
|
|
||||||
setDropdownVisible(true);
|
setDropdownVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,14 +52,15 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
|||||||
const onKeyDown = (event: KeyboardEvent) => {
|
const onKeyDown = (event: KeyboardEvent) => {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'Backspace':
|
case 'Backspace':
|
||||||
if (autocompleteSearchQuery === '' && tagElements.length > 0) {
|
case 'ArrowLeft':
|
||||||
tagElements[tagElements.length - 1]?.focus();
|
if (autocompleteSearchQuery === '' && tags.length > 0) {
|
||||||
|
appState.noteTags.setFocusedTagUuid(tags[tags.length - 1].uuid);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (autocompleteTagResultElements.length > 0) {
|
if (autocompleteTagResults.length > 0) {
|
||||||
autocompleteTagResultElements[0]?.focus();
|
appState.noteTags.setFocusedTagResultUuid(autocompleteTagResults[0].uuid);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -70,10 +68,27 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
showDropdown();
|
||||||
|
appState.noteTags.setAutocompleteInputFocused(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBlur = (event: FocusEvent) => {
|
||||||
|
closeOnBlur(event);
|
||||||
|
appState.noteTags.setAutocompleteInputFocused(false);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
appState.noteTags.searchActiveNoteAutocompleteTags();
|
appState.noteTags.searchActiveNoteAutocompleteTags();
|
||||||
}, [appState.noteTags]);
|
}, [appState.noteTags]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (autocompleteInputFocused) {
|
||||||
|
inputRef.current.focus();
|
||||||
|
appState.noteTags.setAutocompleteInputFocused(false);
|
||||||
|
}
|
||||||
|
}, [appState.noteTags, autocompleteInputFocused]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={onFormSubmit}
|
onSubmit={onFormSubmit}
|
||||||
@@ -81,18 +96,14 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => {
|
|||||||
>
|
>
|
||||||
<Disclosure open={dropdownVisible} onChange={showDropdown}>
|
<Disclosure open={dropdownVisible} onChange={showDropdown}>
|
||||||
<input
|
<input
|
||||||
ref={(element) => {
|
ref={inputRef}
|
||||||
if (element) {
|
|
||||||
appState.noteTags.setAutocompleteInputElement(element);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="w-80 bg-default text-xs color-text no-border h-7 focus:outline-none focus:shadow-none focus:border-bottom"
|
className="w-80 bg-default text-xs color-text no-border h-7 focus:outline-none focus:shadow-none focus:border-bottom"
|
||||||
value={autocompleteSearchQuery}
|
value={autocompleteSearchQuery}
|
||||||
onChange={onSearchQueryChange}
|
onChange={onSearchQueryChange}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Add tag"
|
placeholder="Add tag"
|
||||||
onBlur={closeOnBlur}
|
onBlur={onBlur}
|
||||||
onFocus={showDropdown}
|
onFocus={onFocus}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
{dropdownVisible && (
|
{dropdownVisible && (
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { AppState } from '@/ui_models/app_state';
|
import { AppState } from '@/ui_models/app_state';
|
||||||
import { SNTag } from '@standardnotes/snjs';
|
import { SNTag } from '@standardnotes/snjs';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { useEffect, useRef } from 'preact/hooks';
|
||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -11,7 +12,9 @@ type Props = {
|
|||||||
|
|
||||||
export const AutocompleteTagResult = observer(
|
export const AutocompleteTagResult = observer(
|
||||||
({ appState, tagResult, closeOnBlur }: Props) => {
|
({ appState, tagResult, closeOnBlur }: Props) => {
|
||||||
const { autocompleteInputElement, autocompleteSearchQuery, autocompleteTagResults } = appState.noteTags;
|
const { autocompleteSearchQuery, autocompleteTagResults, focusedTagResultUuid } = appState.noteTags;
|
||||||
|
|
||||||
|
const tagResultRef = useRef<HTMLButtonElement>();
|
||||||
|
|
||||||
const onTagOptionClick = async (tag: SNTag) => {
|
const onTagOptionClick = async (tag: SNTag) => {
|
||||||
await appState.noteTags.addTagToActiveNote(tag);
|
await appState.noteTags.addTagToActiveNote(tag);
|
||||||
@@ -24,34 +27,44 @@ export const AutocompleteTagResult = observer(
|
|||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (tagResultIndex === 0) {
|
if (tagResultIndex === 0) {
|
||||||
autocompleteInputElement?.focus();
|
appState.noteTags.setAutocompleteInputFocused(true);
|
||||||
} else {
|
} else {
|
||||||
appState.noteTags.getPreviousAutocompleteTagResultElement(tagResult)?.focus();
|
appState.noteTags.focusPreviousTagResult(tagResult);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
appState.noteTags.getNextAutocompleteTagResultElement(tagResult)?.focus();
|
appState.noteTags.focusNextTagResult(tagResult);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
appState.noteTags.setFocusedTagResultUuid(tagResult.uuid);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBlur = (event: FocusEvent) => {
|
||||||
|
closeOnBlur(event);
|
||||||
|
appState.noteTags.setFocusedTagResultUuid(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (focusedTagResultUuid === tagResult.uuid) {
|
||||||
|
tagResultRef.current.focus();
|
||||||
|
appState.noteTags.setFocusedTagResultUuid(undefined);
|
||||||
|
}
|
||||||
|
}, [appState.noteTags, focusedTagResultUuid, tagResult]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
ref={(element) => {
|
ref={tagResultRef}
|
||||||
if (element) {
|
|
||||||
appState.noteTags.setAutocompleteTagResultElement(
|
|
||||||
tagResult,
|
|
||||||
element
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
className="sn-dropdown-item"
|
className="sn-dropdown-item"
|
||||||
onClick={() => onTagOptionClick(tagResult)}
|
onClick={() => onTagOptionClick(tagResult)}
|
||||||
onBlur={closeOnBlur}
|
onFocus={onFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
>
|
>
|
||||||
<Icon type="hashtag" className="color-neutral mr-2 min-h-5 min-w-5" />
|
<Icon type="hashtag" className="color-neutral mr-2 min-h-5 min-w-5" />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
import { useRef, useState } from 'preact/hooks';
|
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||||
import { AppState } from '@/ui_models/app_state';
|
import { AppState } from '@/ui_models/app_state';
|
||||||
import { SNTag } from '@standardnotes/snjs/dist/@types';
|
import { SNTag } from '@standardnotes/snjs/dist/@types';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
@@ -10,11 +10,16 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const NoteTag = observer(({ appState, tag }: Props) => {
|
export const NoteTag = observer(({ appState, tag }: Props) => {
|
||||||
|
const { focusedTagUuid, tags } = appState.noteTags;
|
||||||
|
|
||||||
const [showDeleteButton, setShowDeleteButton] = useState(false);
|
const [showDeleteButton, setShowDeleteButton] = useState(false);
|
||||||
const [tagClicked, setTagClicked] = useState(false);
|
const [tagClicked, setTagClicked] = useState(false);
|
||||||
const deleteTagRef = useRef<HTMLButtonElement>();
|
const deleteTagRef = useRef<HTMLButtonElement>();
|
||||||
|
|
||||||
|
const tagRef = useRef<HTMLButtonElement>();
|
||||||
|
|
||||||
const deleteTag = () => {
|
const deleteTag = () => {
|
||||||
|
appState.noteTags.focusPreviousTag(tag);
|
||||||
appState.noteTags.removeTagFromActiveNote(tag);
|
appState.noteTags.removeTagFromActiveNote(tag);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,39 +39,49 @@ export const NoteTag = observer(({ appState, tag }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onFocus = () => {
|
const onFocus = () => {
|
||||||
|
appState.noteTags.setFocusedTagUuid(tag.uuid);
|
||||||
setShowDeleteButton(true);
|
setShowDeleteButton(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onBlur = (event: FocusEvent) => {
|
const onBlur = (event: FocusEvent) => {
|
||||||
const relatedTarget = event.relatedTarget as Node;
|
const relatedTarget = event.relatedTarget as Node;
|
||||||
if (relatedTarget !== deleteTagRef.current) {
|
if (relatedTarget !== deleteTagRef.current) {
|
||||||
|
appState.noteTags.setFocusedTagUuid(undefined);
|
||||||
setShowDeleteButton(false);
|
setShowDeleteButton(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onKeyDown = (event: KeyboardEvent) => {
|
const onKeyDown = (event: KeyboardEvent) => {
|
||||||
|
const tagIndex = appState.noteTags.getTagIndex(tag, tags);
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'Backspace':
|
case 'Backspace':
|
||||||
deleteTag();
|
deleteTag();
|
||||||
break;
|
break;
|
||||||
case 'ArrowLeft':
|
case 'ArrowLeft':
|
||||||
appState.noteTags.getPreviousTagElement(tag)?.focus();
|
appState.noteTags.focusPreviousTag(tag);
|
||||||
break;
|
break;
|
||||||
case 'ArrowRight':
|
case 'ArrowRight':
|
||||||
appState.noteTags.getNextTagElement(tag)?.focus();
|
if (tagIndex === tags.length - 1) {
|
||||||
|
appState.noteTags.setAutocompleteInputFocused(true);
|
||||||
|
} else {
|
||||||
|
appState.noteTags.focusNextTag(tag);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (focusedTagUuid === tag.uuid) {
|
||||||
|
tagRef.current.focus();
|
||||||
|
appState.noteTags.setFocusedTagUuid(undefined);
|
||||||
|
}
|
||||||
|
}, [appState.noteTags, focusedTagUuid, tag]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
ref={(element) => {
|
ref={tagRef}
|
||||||
if (element) {
|
|
||||||
appState.noteTags.setTagElement(tag, element);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="sn-tag pl-1 pr-2 mr-2"
|
className="sn-tag pl-1 pr-2 mr-2"
|
||||||
onClick={onTagClick}
|
onClick={onTagClick}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { SNNote, ContentType, SNTag } from '@standardnotes/snjs';
|
import { SNNote, ContentType, SNTag, UuidString } from '@standardnotes/snjs';
|
||||||
import { action, computed, makeObservable, observable } from 'mobx';
|
import { action, computed, makeObservable, observable } from 'mobx';
|
||||||
import { WebApplication } from '../application';
|
import { WebApplication } from '../application';
|
||||||
import { AppState } from './app_state';
|
import { AppState } from './app_state';
|
||||||
|
|
||||||
export class NoteTagsState {
|
export class NoteTagsState {
|
||||||
autocompleteInputElement: HTMLInputElement | undefined = undefined;
|
autocompleteInputFocused = false;
|
||||||
autocompleteSearchQuery = '';
|
autocompleteSearchQuery = '';
|
||||||
autocompleteTagResultElements: (HTMLButtonElement | undefined)[] = [];
|
|
||||||
autocompleteTagResults: SNTag[] = [];
|
autocompleteTagResults: SNTag[] = [];
|
||||||
tagElements: (HTMLButtonElement | undefined)[] = [];
|
focusedTagResultUuid: UuidString | undefined = undefined;
|
||||||
|
focusedTagUuid: UuidString | undefined = undefined;
|
||||||
tags: SNTag[] = [];
|
tags: SNTag[] = [];
|
||||||
tagsContainerMaxWidth: number | 'auto' = 0;
|
tagsContainerMaxWidth: number | 'auto' = 0;
|
||||||
|
|
||||||
@@ -18,24 +18,24 @@ export class NoteTagsState {
|
|||||||
appEventListeners: (() => void)[]
|
appEventListeners: (() => void)[]
|
||||||
) {
|
) {
|
||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
autocompleteInputElement: observable,
|
autocompleteInputFocused: observable,
|
||||||
autocompleteSearchQuery: observable,
|
autocompleteSearchQuery: observable,
|
||||||
autocompleteTagResultElements: observable,
|
|
||||||
autocompleteTagResults: observable,
|
autocompleteTagResults: observable,
|
||||||
tagElements: observable,
|
focusedTagUuid: observable,
|
||||||
|
focusedTagResultUuid: observable,
|
||||||
tags: observable,
|
tags: observable,
|
||||||
tagsContainerMaxWidth: observable,
|
tagsContainerMaxWidth: observable,
|
||||||
|
|
||||||
autocompleteTagHintVisible: computed,
|
autocompleteTagHintVisible: computed,
|
||||||
|
|
||||||
clearAutocompleteSearch: action,
|
clearAutocompleteSearch: action,
|
||||||
setAutocompleteInputElement: action,
|
focusNextTag: action,
|
||||||
|
focusPreviousTag: action,
|
||||||
|
setAutocompleteInputFocused: action,
|
||||||
setAutocompleteSearchQuery: action,
|
setAutocompleteSearchQuery: action,
|
||||||
setAutocompleteTagResultElement: action,
|
|
||||||
setAutocompleteTagResultElements: action,
|
|
||||||
setAutocompleteTagResults: action,
|
setAutocompleteTagResults: action,
|
||||||
setTagElement: action,
|
setFocusedTagResultUuid: action,
|
||||||
setTagElements: action,
|
setFocusedTagUuid: action,
|
||||||
setTags: action,
|
setTags: action,
|
||||||
setTagsContainerMaxWidth: action,
|
setTagsContainerMaxWidth: action,
|
||||||
reloadTags: action,
|
reloadTags: action,
|
||||||
@@ -61,43 +61,25 @@ export class NoteTagsState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAutocompleteInputElement(element: HTMLInputElement | undefined): void {
|
setAutocompleteInputFocused(focused: boolean): void {
|
||||||
this.autocompleteInputElement = element;
|
console.log('set focused', focused);
|
||||||
|
this.autocompleteInputFocused = focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAutocompleteSearchQuery(query: string): void {
|
setAutocompleteSearchQuery(query: string): void {
|
||||||
this.autocompleteSearchQuery = query;
|
this.autocompleteSearchQuery = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAutocompleteTagResultElement(
|
|
||||||
tagResult: SNTag,
|
|
||||||
element: HTMLButtonElement
|
|
||||||
): void {
|
|
||||||
const tagIndex = this.getTagIndex(tagResult, this.autocompleteTagResults);
|
|
||||||
if (tagIndex > -1) {
|
|
||||||
this.autocompleteTagResultElements.splice(tagIndex, 1, element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setAutocompleteTagResultElements(
|
|
||||||
elements: (HTMLButtonElement | undefined)[]
|
|
||||||
): void {
|
|
||||||
this.autocompleteTagResultElements = elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAutocompleteTagResults(results: SNTag[]): void {
|
setAutocompleteTagResults(results: SNTag[]): void {
|
||||||
this.autocompleteTagResults = results;
|
this.autocompleteTagResults = results;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTagElement(tag: SNTag, element: HTMLButtonElement): void {
|
setFocusedTagUuid(tagUuid: UuidString | undefined): void {
|
||||||
const tagIndex = this.getTagIndex(tag, this.tags);
|
this.focusedTagUuid = tagUuid;
|
||||||
if (tagIndex > -1) {
|
|
||||||
this.tagElements.splice(tagIndex, 1, element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setTagElements(elements: (HTMLButtonElement | undefined)[]): void {
|
setFocusedTagResultUuid(tagUuid: UuidString | undefined): void {
|
||||||
this.tagElements = elements;
|
this.focusedTagResultUuid = tagUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTags(tags: SNTag[]): void {
|
setTags(tags: SNTag[]): void {
|
||||||
@@ -121,6 +103,47 @@ export class NoteTagsState {
|
|||||||
this.clearAutocompleteSearch();
|
this.clearAutocompleteSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focusNextTag(tag: SNTag): void {
|
||||||
|
const nextTagIndex = this.getTagIndex(tag, this.tags) + 1;
|
||||||
|
if (nextTagIndex > -1 && this.tags.length > nextTagIndex) {
|
||||||
|
const nextTag = this.tags[nextTagIndex];
|
||||||
|
this.setFocusedTagUuid(nextTag.uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focusNextTagResult(tagResult: SNTag): void {
|
||||||
|
const nextTagResultIndex =
|
||||||
|
this.getTagIndex(tagResult, this.autocompleteTagResults) + 1;
|
||||||
|
if (
|
||||||
|
nextTagResultIndex > -1 &&
|
||||||
|
this.autocompleteTagResults.length > nextTagResultIndex
|
||||||
|
) {
|
||||||
|
const nextTagResult = this.autocompleteTagResults[nextTagResultIndex];
|
||||||
|
this.setFocusedTagResultUuid(nextTagResult.uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focusPreviousTag(tag: SNTag): void {
|
||||||
|
const previousTagIndex = this.getTagIndex(tag, this.tags) - 1;
|
||||||
|
if (previousTagIndex > -1 && this.tags.length > previousTagIndex) {
|
||||||
|
const previousTag = this.tags[previousTagIndex];
|
||||||
|
this.setFocusedTagUuid(previousTag.uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focusPreviousTagResult(tagResult: SNTag): void {
|
||||||
|
const previousTagResultIndex =
|
||||||
|
this.getTagIndex(tagResult, this.autocompleteTagResults) - 1;
|
||||||
|
if (
|
||||||
|
previousTagResultIndex > -1 &&
|
||||||
|
this.autocompleteTagResults.length > previousTagResultIndex
|
||||||
|
) {
|
||||||
|
const previousTagResult =
|
||||||
|
this.autocompleteTagResults[previousTagResultIndex];
|
||||||
|
this.setFocusedTagResultUuid(previousTagResult.uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
searchActiveNoteAutocompleteTags(): void {
|
searchActiveNoteAutocompleteTags(): void {
|
||||||
const newResults = this.application.searchTags(
|
const newResults = this.application.searchTags(
|
||||||
this.autocompleteSearchQuery,
|
this.autocompleteSearchQuery,
|
||||||
@@ -133,53 +156,11 @@ export class NoteTagsState {
|
|||||||
return tagsArr.findIndex((t) => t.uuid === tag.uuid);
|
return tagsArr.findIndex((t) => t.uuid === tag.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreviousTagElement(tag: SNTag): HTMLButtonElement | undefined {
|
|
||||||
const previousTagIndex = this.getTagIndex(tag, this.tags) - 1;
|
|
||||||
if (previousTagIndex > -1 && this.tagElements.length > previousTagIndex) {
|
|
||||||
return this.tagElements[previousTagIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getNextTagElement(tag: SNTag): HTMLButtonElement | undefined {
|
|
||||||
const nextTagIndex = this.getTagIndex(tag, this.tags) + 1;
|
|
||||||
if (nextTagIndex > -1 && this.tagElements.length > nextTagIndex) {
|
|
||||||
return this.tagElements[nextTagIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreviousAutocompleteTagResultElement(
|
|
||||||
tagResult: SNTag
|
|
||||||
): HTMLButtonElement | undefined {
|
|
||||||
const previousTagIndex =
|
|
||||||
this.getTagIndex(tagResult, this.autocompleteTagResults) - 1;
|
|
||||||
if (
|
|
||||||
previousTagIndex > -1 &&
|
|
||||||
this.autocompleteTagResultElements.length > previousTagIndex
|
|
||||||
) {
|
|
||||||
return this.autocompleteTagResultElements[previousTagIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getNextAutocompleteTagResultElement(
|
|
||||||
tagResult: SNTag
|
|
||||||
): HTMLButtonElement | undefined {
|
|
||||||
const nextTagIndex =
|
|
||||||
this.getTagIndex(tagResult, this.autocompleteTagResults) + 1;
|
|
||||||
if (
|
|
||||||
nextTagIndex > -1 &&
|
|
||||||
this.autocompleteTagResultElements.length > nextTagIndex
|
|
||||||
) {
|
|
||||||
return this.autocompleteTagResultElements[nextTagIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reloadTags(): void {
|
reloadTags(): void {
|
||||||
const { activeNote } = this;
|
const { activeNote } = this;
|
||||||
if (activeNote) {
|
if (activeNote) {
|
||||||
const tags = this.application.getSortedTagsForNote(activeNote);
|
const tags = this.application.getSortedTagsForNote(activeNote);
|
||||||
const tagElements: (HTMLButtonElement | undefined)[] = [];
|
|
||||||
this.setTags(tags);
|
this.setTags(tags);
|
||||||
this.setTagElements(tagElements.fill(undefined, tags.length));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,12 +186,10 @@ export class NoteTagsState {
|
|||||||
async removeTagFromActiveNote(tag: SNTag): Promise<void> {
|
async removeTagFromActiveNote(tag: SNTag): Promise<void> {
|
||||||
const { activeNote } = this;
|
const { activeNote } = this;
|
||||||
if (activeNote) {
|
if (activeNote) {
|
||||||
const previousTagElement = this.getPreviousTagElement(tag);
|
|
||||||
await this.application.changeItem(tag.uuid, (mutator) => {
|
await this.application.changeItem(tag.uuid, (mutator) => {
|
||||||
mutator.removeItemAsRelationship(activeNote);
|
mutator.removeItemAsRelationship(activeNote);
|
||||||
});
|
});
|
||||||
this.application.sync();
|
this.application.sync();
|
||||||
previousTagElement?.focus();
|
|
||||||
this.reloadTags();
|
this.reloadTags();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user