refactor: refactor autocomplete tag input in separate components and move shared logic to state
This commit is contained in:
@@ -1,17 +1,12 @@
|
||||
import {
|
||||
SNNote,
|
||||
ContentType,
|
||||
SNTag,
|
||||
} from '@standardnotes/snjs';
|
||||
import {
|
||||
action,
|
||||
makeObservable,
|
||||
observable,
|
||||
} from 'mobx';
|
||||
import { SNNote, ContentType, SNTag } from '@standardnotes/snjs';
|
||||
import { action, computed, makeObservable, observable } from 'mobx';
|
||||
import { WebApplication } from '../application';
|
||||
import { AppState } from './app_state';
|
||||
|
||||
export class ActiveNoteState {
|
||||
autocompleteSearchQuery = '';
|
||||
autocompleteTagResultElements: (HTMLButtonElement | undefined)[] = [];
|
||||
autocompleteTagResults: SNTag[] = [];
|
||||
tagElements: (HTMLButtonElement | undefined)[] = [];
|
||||
tags: SNTag[] = [];
|
||||
tagsContainerMaxWidth: number | 'auto' = 0;
|
||||
@@ -22,11 +17,22 @@ export class ActiveNoteState {
|
||||
appEventListeners: (() => void)[]
|
||||
) {
|
||||
makeObservable(this, {
|
||||
autocompleteSearchQuery: observable,
|
||||
autocompleteTagResultElements: observable,
|
||||
autocompleteTagResults: observable,
|
||||
tagElements: observable,
|
||||
tags: observable,
|
||||
tagsContainerMaxWidth: observable,
|
||||
|
||||
autocompleteTagHintVisible: computed,
|
||||
|
||||
clearAutocompleteSearch: action,
|
||||
setAutocompleteSearchQuery: action,
|
||||
setAutocompleteTagResultElement: action,
|
||||
setAutocompleteTagResultElements: action,
|
||||
setAutocompleteTagResults: action,
|
||||
setTagElement: action,
|
||||
setTagElements: action,
|
||||
setTags: action,
|
||||
setTagsContainerMaxWidth: action,
|
||||
reloadTags: action,
|
||||
@@ -43,8 +49,41 @@ export class ActiveNoteState {
|
||||
return this.appState.notes.activeEditor?.note;
|
||||
}
|
||||
|
||||
get autocompleteTagHintVisible(): boolean {
|
||||
return (
|
||||
this.autocompleteSearchQuery !== '' &&
|
||||
!this.autocompleteTagResults.some(
|
||||
(tagResult) => tagResult.title === this.autocompleteSearchQuery
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setAutocompleteSearchQuery(query: string): void {
|
||||
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 {
|
||||
this.autocompleteTagResults = results;
|
||||
}
|
||||
|
||||
setTagElement(tag: SNTag, element: HTMLButtonElement): void {
|
||||
const tagIndex = this.getTagIndex(tag);
|
||||
const tagIndex = this.getTagIndex(tag, this.tags);
|
||||
if (tagIndex > -1) {
|
||||
this.tagElements.splice(tagIndex, 1, element);
|
||||
}
|
||||
@@ -62,19 +101,38 @@ export class ActiveNoteState {
|
||||
this.tagsContainerMaxWidth = width;
|
||||
}
|
||||
|
||||
getTagIndex(tag: SNTag): number {
|
||||
return this.tags.findIndex(t => t.uuid === tag.uuid);
|
||||
clearAutocompleteSearch(): void {
|
||||
this.setAutocompleteSearchQuery('');
|
||||
this.searchActiveNoteAutocompleteTags();
|
||||
}
|
||||
|
||||
async createAndAddNewTag(): Promise<void> {
|
||||
const newTag = await this.application.findOrCreateTag(this.autocompleteSearchQuery);
|
||||
await this.addTagToActiveNote(newTag);
|
||||
this.clearAutocompleteSearch();
|
||||
}
|
||||
|
||||
searchActiveNoteAutocompleteTags(): void {
|
||||
const newResults = this.application.searchTags(
|
||||
this.autocompleteSearchQuery,
|
||||
this.activeNote
|
||||
);
|
||||
this.setAutocompleteTagResults(newResults);
|
||||
}
|
||||
|
||||
getTagIndex(tag: SNTag, tagsArr: SNTag[]): number {
|
||||
return tagsArr.findIndex((t) => t.uuid === tag.uuid);
|
||||
}
|
||||
|
||||
getPreviousTagElement(tag: SNTag): HTMLButtonElement | undefined {
|
||||
const previousTagIndex = this.getTagIndex(tag) - 1;
|
||||
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) + 1;
|
||||
const nextTagIndex = this.getTagIndex(tag, this.tags) + 1;
|
||||
if (nextTagIndex > -1 && this.tagElements.length > nextTagIndex) {
|
||||
return this.tagElements[nextTagIndex];
|
||||
}
|
||||
@@ -94,9 +152,7 @@ export class ActiveNoteState {
|
||||
const EDITOR_ELEMENT_ID = 'editor-column';
|
||||
const editorWidth = document.getElementById(EDITOR_ELEMENT_ID)?.clientWidth;
|
||||
if (editorWidth) {
|
||||
this.appState.activeNote.setTagsContainerMaxWidth(
|
||||
editorWidth
|
||||
);
|
||||
this.setTagsContainerMaxWidth(editorWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user