refactor: extract shared logic to active note state

This commit is contained in:
Antonella Sgarlatta
2021-06-02 17:57:37 -03:00
parent 3db87099e0
commit 6fb68d2255
8 changed files with 184 additions and 164 deletions

View File

@@ -14,10 +14,12 @@ import { AppState } from './app_state';
export class ActiveNoteState {
inputOverflowed = false;
overflowCountPosition = 0;
overflowedTagsCount = 0;
tagElements: (HTMLButtonElement | undefined)[] = [];
tagFocused = false;
tags: SNTag[] = [];
tagsContainerMaxWidth: number | 'auto' = 0;
tagFocused = false;
tagsContainerExpanded = false;
constructor(
@@ -27,29 +29,31 @@ export class ActiveNoteState {
) {
makeObservable(this, {
inputOverflowed: observable,
overflowCountPosition: observable,
overflowedTagsCount: observable,
tags: observable,
tagElements: observable,
tagFocused: observable,
tags: observable,
tagsContainerExpanded: observable,
tagsContainerMaxWidth: observable,
tagsOverflowed: computed,
setInputOverflowed: action,
setOverflowCountPosition: action,
setOverflowedTagsCount: action,
setTagElement: action,
setTagFocused: action,
setTags: action,
setTagsContainerExpanded: action,
setTagsContainerMaxWidth: action,
reloadTags: action,
});
appEventListeners.push(
application.streamItems(
ContentType.Tag,
() => {
this.reloadTags();
}
)
application.streamItems(ContentType.Tag, () => {
this.reloadTags();
})
);
}
@@ -65,14 +69,33 @@ export class ActiveNoteState {
this.inputOverflowed = overflowed;
}
setOverflowCountPosition(position: number): void {
this.overflowCountPosition = position;
}
setOverflowedTagsCount(count: number): void {
this.overflowedTagsCount = count;
}
setTagElement(tag: SNTag, element: HTMLButtonElement): void {
const tagIndex = this.getTagIndex(tag);
if (tagIndex > -1) {
this.tagElements.splice(tagIndex, 1, element);
}
}
setTagFocused(focused: boolean): void {
this.tagFocused = focused;
}
setTagElements(elements: (HTMLButtonElement | undefined)[]): void {
this.tagElements = elements;
}
setTags(tags: SNTag[]): void {
this.tags = tags;
}
setTagsContainerExpanded(expanded: boolean): void {
this.tagsContainerExpanded = expanded;
}
@@ -81,28 +104,86 @@ export class ActiveNoteState {
this.tagsContainerMaxWidth = width;
}
getTagElement(tag: SNTag): HTMLButtonElement | undefined {
const tagIndex = this.getTagIndex(tag);
if (tagIndex > -1 && this.tagElements.length > tagIndex) {
return this.tagElements[tagIndex];
}
}
getTagIndex(tag: SNTag): number {
return this.tags.findIndex(t => t.uuid === tag.uuid);
}
getPreviousTag(tag: SNTag): SNTag | undefined {
const previousTagIndex = this.getTagIndex(tag) - 1;
if (previousTagIndex > -1 && this.tags.length > previousTagIndex) {
return this.tags[previousTagIndex];
}
}
isElementOverflowed(element: HTMLElement): boolean {
if (
this.tagElements.length === 0 ||
!this.tagElements[0]
) {
return false;
}
const firstTagTop = this.tagElements[0].offsetTop;
return element.offsetTop > firstTagTop;
}
isTagOverflowed(tag: SNTag): boolean {
const tagElement = this.getTagElement(tag);
return tagElement ? this.isElementOverflowed(tagElement) : false;
}
reloadTags(): void {
const { activeNote } = this;
if (activeNote) {
this.tags = this.application.getSortedTagsForNote(activeNote);
}
const tags = this.application.getSortedTagsForNote(activeNote);
const tagElements: (HTMLButtonElement | undefined)[] = [];
this.setTags(tags);
this.setTagElements(tagElements.fill(undefined, tags.length));
}
}
reloadOverflowCountPosition(): void {
const lastVisibleTagIndex = this.tagElements.findIndex(tagElement => tagElement && this.isElementOverflowed(tagElement)) - 1;
if (lastVisibleTagIndex > -1 && this.tagElements.length > lastVisibleTagIndex) {
const lastVisibleTagElement = this.tagElements[lastVisibleTagIndex];
if (lastVisibleTagElement) {
const { offsetLeft, offsetWidth } = lastVisibleTagElement;
this.setOverflowCountPosition(offsetLeft + offsetWidth);
}
}
}
reloadOverflowedTagsCount(): void {
const count = this.tagElements.filter((tagElement) =>
tagElement && this.isElementOverflowed(tagElement)
).length;
this.setOverflowedTagsCount(count);
}
reloadTagsContainerMaxWidth(): void {
const EDITOR_ELEMENT_ID = 'editor-column';
const defaultFontSize = parseFloat(window.getComputedStyle(
document.documentElement
).fontSize);
const overflowMargin = defaultFontSize * 5;
const editorWidth = document.getElementById(EDITOR_ELEMENT_ID)?.clientWidth;
if (editorWidth) {
this.appState.activeNote.setTagsContainerMaxWidth(
editorWidth - overflowMargin
);
}
}
reloadTagsContainerLayout(): void {
const EDITOR_ELEMENT_ID = 'editor-column';
const defaultFontSize = window.getComputedStyle(
document.documentElement
).fontSize;
const containerMargins = parseFloat(defaultFontSize) * 6;
const deleteButtonMargin = this.tagFocused ? parseFloat(defaultFontSize) * 1.25 : 0;
const editorWidth =
document.getElementById(EDITOR_ELEMENT_ID)?.clientWidth;
if (editorWidth) {
this.appState.activeNote.setTagsContainerMaxWidth(
editorWidth - containerMargins + deleteButtonMargin
);
}
this.reloadTagsContainerMaxWidth();
this.reloadOverflowedTagsCount();
this.reloadOverflowCountPosition();
}
async addTagToActiveNote(tag: SNTag): Promise<void> {