From 78f39ec85db3d3c38e29e5f8a6d744398d285d6b Mon Sep 17 00:00:00 2001 From: Mo Date: Wed, 1 Jun 2022 09:23:23 -0500 Subject: [PATCH] fix: select home navigation view when creating note inside smart view (#1059) --- .../Components/NoteTags/NoteTag.tsx | 2 +- .../Components/Tags/SmartViewsListItem.tsx | 2 +- .../javascripts/Components/Tags/TagsList.tsx | 2 +- .../Components/Tags/TagsListItem.tsx | 2 +- .../javascripts/UIModels/AppState/AppState.ts | 49 ++---------------- .../UIModels/AppState/ContentListViewState.ts | 9 ++-- .../UIModels/AppState/NoteTagsState.ts | 8 +-- .../UIModels/AppState/NotesState.ts | 2 +- .../UIModels/AppState/TagsState.ts | 51 +++++++++++++++---- 9 files changed, 62 insertions(+), 65 deletions(-) diff --git a/app/assets/javascripts/Components/NoteTags/NoteTag.tsx b/app/assets/javascripts/Components/NoteTags/NoteTag.tsx index 9bd238894..f6f94467c 100644 --- a/app/assets/javascripts/Components/NoteTags/NoteTag.tsx +++ b/app/assets/javascripts/Components/NoteTags/NoteTag.tsx @@ -49,7 +49,7 @@ const NoteTag = ({ appState, tag }: Props) => { (event) => { if (tagClicked && event.target !== deleteTagRef.current) { setTagClicked(false) - appState.tags.selected = tag + void appState.tags.setSelectedTag(tag) } else { setTagClicked(true) } diff --git a/app/assets/javascripts/Components/Tags/SmartViewsListItem.tsx b/app/assets/javascripts/Components/Tags/SmartViewsListItem.tsx index 0c0feea47..f1b4e66b8 100644 --- a/app/assets/javascripts/Components/Tags/SmartViewsListItem.tsx +++ b/app/assets/javascripts/Components/Tags/SmartViewsListItem.tsx @@ -56,7 +56,7 @@ const SmartViewsListItem: FunctionComponent = ({ view, tagsState }) => { }, [setTitle, view]) const selectCurrentTag = useCallback(() => { - tagsState.selected = view + void tagsState.setSelectedTag(view) }, [tagsState, view]) const onBlur = useCallback(() => { diff --git a/app/assets/javascripts/Components/Tags/TagsList.tsx b/app/assets/javascripts/Components/Tags/TagsList.tsx index 3dca17030..d10cd3700 100644 --- a/app/assets/javascripts/Components/Tags/TagsList.tsx +++ b/app/assets/javascripts/Components/Tags/TagsList.tsx @@ -33,7 +33,7 @@ const TagsList: FunctionComponent = ({ appState }: Props) => { const onContextMenu = useCallback( (tag: SNTag, posX: number, posY: number) => { - appState.tags.selected = tag + void appState.tags.setSelectedTag(tag) openTagContextMenu(posX, posY) }, [appState, openTagContextMenu], diff --git a/app/assets/javascripts/Components/Tags/TagsListItem.tsx b/app/assets/javascripts/Components/Tags/TagsListItem.tsx index fd4bd92f4..2cf2ba097 100644 --- a/app/assets/javascripts/Components/Tags/TagsListItem.tsx +++ b/app/assets/javascripts/Components/Tags/TagsListItem.tsx @@ -78,7 +78,7 @@ export const TagsListItem: FunctionComponent = observer(({ tag, features, ) const selectCurrentTag = useCallback(() => { - tagsState.selected = tag + void tagsState.setSelectedTag(tag) }, [tagsState, tag]) const onBlur = useCallback(() => { diff --git a/app/assets/javascripts/UIModels/AppState/AppState.ts b/app/assets/javascripts/UIModels/AppState/AppState.ts index db628fed9..3bf20a9df 100644 --- a/app/assets/javascripts/UIModels/AppState/AppState.ts +++ b/app/assets/javascripts/UIModels/AppState/AppState.ts @@ -11,7 +11,7 @@ import { removeFromArray, WebOrDesktopDeviceInterface, } from '@standardnotes/snjs' -import { action, IReactionDisposer, makeObservable, observable, reaction } from 'mobx' +import { action, makeObservable, observable } from 'mobx' import { ActionsMenuState } from './ActionsMenuState' import { FeaturesState } from './FeaturesState' import { FilesState } from './FilesState' @@ -72,8 +72,6 @@ export class AppState extends AbstractState { private appEventObserverRemovers: (() => void)[] = [] - private readonly tagChangedDisposer: IReactionDisposer - constructor(application: WebApplication, private device: WebOrDesktopDeviceInterface) { super(application) @@ -87,7 +85,7 @@ export class AppState extends AbstractState { this.appEventObserverRemovers, ) this.features = new FeaturesState(application, this.appEventObserverRemovers) - this.tags = new TagsState(application, this.appEventObserverRemovers, this.features) + this.tags = new TagsState(application, this, this.appEventObserverRemovers, this.features) this.searchOptions = new SearchOptionsState(application, this.appEventObserverRemovers) this.contentListView = new ContentListViewState(application, this, this.appEventObserverRemovers) this.noteTags = new NoteTagsState(application, this, this.appEventObserverRemovers) @@ -120,8 +118,6 @@ export class AppState extends AbstractState { openSessionsModal: action, closeSessionsModal: action, }) - - this.tagChangedDisposer = this.tagChangedNotifier() } override deinit(source: DeinitSource): void { @@ -186,9 +182,6 @@ export class AppState extends AbstractState { document.removeEventListener('visibilitychange', this.onVisibilityChange) ;(this.onVisibilityChange as unknown) = undefined - this.tagChangedDisposer() - ;(this.tagChangedDisposer as unknown) = undefined - destroyAllObjectProperties(this) } @@ -223,29 +216,6 @@ export class AppState extends AbstractState { return this.application.setPreference(PrefKey.EditorSpellcheck, !currentValue) } - private tagChangedNotifier(): IReactionDisposer { - return reaction( - () => this.tags.selectedUuid, - () => { - const tag = this.tags.selected - const previousTag = this.tags.previouslySelected - - if (!tag) { - return - } - - if (this.application.items.isTemplateItem(tag)) { - return - } - - this.notifyEvent(AppStateEvent.TagChanged, { - tag, - previousTag, - }).catch(console.error) - }, - ) - } - addAppEventObserver() { this.unsubAppEventObserver = this.application.addEventObserver(async (eventName) => { switch (eventName) { @@ -294,18 +264,9 @@ export class AppState extends AbstractState { } async notifyEvent(eventName: AppStateEvent, data?: unknown) { - /** - * Timeout is particularly important so we can give all initial - * controllers a chance to construct before propogting any events * - */ - return new Promise((resolve) => { - setTimeout(async () => { - for (const callback of this.observers) { - await callback(eventName, data) - } - resolve() - }) - }) + for (const callback of this.observers) { + await callback(eventName, data) + } } /** Returns the tags that are referncing this note */ diff --git a/app/assets/javascripts/UIModels/AppState/ContentListViewState.ts b/app/assets/javascripts/UIModels/AppState/ContentListViewState.ts index 0e9014bb9..b7baa2be6 100644 --- a/app/assets/javascripts/UIModels/AppState/ContentListViewState.ts +++ b/app/assets/javascripts/UIModels/AppState/ContentListViewState.ts @@ -380,6 +380,10 @@ export class ContentListViewState extends AbstractState { createNewNote = async () => { this.appState.notes.unselectNotes() + if (this.appState.tags.isInSmartView() && !this.appState.tags.isInHomeView()) { + await this.appState.tags.selectHomeNavigationView() + } + let title = `Note ${this.notes.length + 1}` if (this.isFiltering) { title = this.noteFilterText @@ -387,12 +391,11 @@ export class ContentListViewState extends AbstractState { await this.appState.notes.createNewNoteController(title) - this.appState.noteTags.reloadTags() + this.appState.noteTags.reloadTagsForCurrentNote() } createPlaceholderNote = () => { - const selectedTag = this.appState.tags.selected - if (selectedTag && selectedTag instanceof SmartView && selectedTag.uuid !== SystemViewId.AllNotes) { + if (this.appState.tags.isInSmartView() && !this.appState.tags.isInHomeView()) { return } diff --git a/app/assets/javascripts/UIModels/AppState/NoteTagsState.ts b/app/assets/javascripts/UIModels/AppState/NoteTagsState.ts index 6219de9bd..6fceed0cc 100644 --- a/app/assets/javascripts/UIModels/AppState/NoteTagsState.ts +++ b/app/assets/javascripts/UIModels/AppState/NoteTagsState.ts @@ -54,7 +54,7 @@ export class NoteTagsState extends AbstractState { appEventListeners.push( application.streamItems(ContentType.Tag, () => { - this.reloadTags() + this.reloadTagsForCurrentNote() }), application.addSingleEventObserver(ApplicationEvent.PreferencesChanged, async () => { this.addNoteToParentFolders = application.getPreference(PrefKey.NoteAddToParentFolders, true) @@ -156,7 +156,7 @@ export class NoteTagsState extends AbstractState { return tagsArr.findIndex((t) => t.uuid === tag.uuid) } - reloadTags(): void { + reloadTagsForCurrentNote(): void { const activeNote = this.appState.contentListView.activeControllerNote if (activeNote) { @@ -178,7 +178,7 @@ export class NoteTagsState extends AbstractState { if (activeNote) { await this.application.items.addTagToNote(activeNote, tag, this.addNoteToParentFolders) this.application.sync.sync().catch(console.error) - this.reloadTags() + this.reloadTagsForCurrentNote() } } @@ -190,7 +190,7 @@ export class NoteTagsState extends AbstractState { mutator.removeItemAsRelationship(activeNote) }) this.application.sync.sync().catch(console.error) - this.reloadTags() + this.reloadTagsForCurrentNote() } } diff --git a/app/assets/javascripts/UIModels/AppState/NotesState.ts b/app/assets/javascripts/UIModels/AppState/NotesState.ts index ef56dc478..360302804 100644 --- a/app/assets/javascripts/UIModels/AppState/NotesState.ts +++ b/app/assets/javascripts/UIModels/AppState/NotesState.ts @@ -120,7 +120,7 @@ export class NotesState extends AbstractState { await this.application.noteControllerGroup.createNoteController(noteUuid) - this.appState.noteTags.reloadTags() + this.appState.noteTags.reloadTagsForCurrentNote() await this.onActiveEditorChanged() } diff --git a/app/assets/javascripts/UIModels/AppState/TagsState.ts b/app/assets/javascripts/UIModels/AppState/TagsState.ts index 32963d9ea..d666cfda6 100644 --- a/app/assets/javascripts/UIModels/AppState/TagsState.ts +++ b/app/assets/javascripts/UIModels/AppState/TagsState.ts @@ -13,12 +13,15 @@ import { isSystemView, FindItem, DeinitSource, + SystemViewId, } from '@standardnotes/snjs' import { action, computed, makeAutoObservable, makeObservable, observable, runInAction } from 'mobx' import { WebApplication } from '../Application' import { FeaturesState } from './FeaturesState' import { AbstractState } from './AbstractState' import { destroyAllObjectProperties } from '@/Utils' +import { AppState } from './AppState' +import { AppStateEvent } from './AppStateEvent' type AnyTag = SNTag | SmartView @@ -78,7 +81,12 @@ export class TagsState extends AbstractState { private readonly tagsCountsState: TagsCountsState - constructor(application: WebApplication, appEventListeners: (() => void)[], private features: FeaturesState) { + constructor( + application: WebApplication, + override appState: AppState, + appEventListeners: (() => void)[], + private features: FeaturesState, + ) { super(application) this.tagsCountsState = new TagsCountsState(this.application) @@ -211,12 +219,20 @@ export class TagsState extends AbstractState { this.application.sync.sync().catch(console.error) runInAction(() => { - this.selected = createdTag as SNTag + void this.setSelectedTag(createdTag as SNTag) }) this.setAddingSubtagTo(undefined) } + public isInSmartView(): boolean { + return this.selected instanceof SmartView + } + + public isInHomeView(): boolean { + return this.selected instanceof SmartView && this.selected.uuid === SystemViewId.AllNotes + } + setAddingSubtagTo(tag: SNTag | undefined): void { this.addingSubtagTo = tag } @@ -368,7 +384,7 @@ export class TagsState extends AbstractState { return this.selected_ } - public set selected(tag: AnyTag | undefined) { + public async setSelectedTag(tag: AnyTag | undefined) { if (tag && tag.conflictOf) { this.application.mutator .changeAndSaveItem(tag, (mutator) => { @@ -386,6 +402,23 @@ export class TagsState extends AbstractState { this.previouslySelected_ = this.selected_ this.setSelectedTagInstance(tag) + + if (tag && this.application.items.isTemplateItem(tag)) { + return + } + + await this.appState.notifyEvent(AppStateEvent.TagChanged, { + tag, + previousTag: this.previouslySelected_, + }) + } + + public async selectHomeNavigationView(): Promise { + await this.setSelectedTag(this.homeNavigationView) + } + + get homeNavigationView(): SmartView { + return this.smartViews[0] } private setSelectedTagInstance(tag: AnyTag | undefined): void { @@ -410,7 +443,7 @@ export class TagsState extends AbstractState { public set editingTag(editingTag: SNTag | SmartView | undefined) { this.editing_ = editingTag - this.selected = editingTag + void this.setSelectedTag(editingTag) } public createNewTemplate() { @@ -430,7 +463,7 @@ export class TagsState extends AbstractState { public undoCreateNewTag() { this.editing_ = undefined const previousTag = this.previouslySelected_ || this.smartViews[0] - this.selected = previousTag + void this.setSelectedTag(previousTag) } public async remove(tag: SNTag | SmartView, userTriggered: boolean) { @@ -443,7 +476,7 @@ export class TagsState extends AbstractState { } if (shouldDelete) { this.application.mutator.deleteItem(tag).catch(console.error) - this.selected = this.smartViews[0] + await this.setSelectedTag(this.smartViews[0]) } } @@ -487,7 +520,7 @@ export class TagsState extends AbstractState { const insertedTag = await this.application.mutator.createTagOrSmartView(newTitle) this.application.sync.sync().catch(console.error) runInAction(() => { - this.selected = insertedTag as SNTag + void this.setSelectedTag(insertedTag as SNTag) }) } else { await this.application.mutator.changeAndSaveItem(tag, (mutator) => { @@ -508,12 +541,12 @@ export class TagsState extends AbstractState { const matchingTag = this.application.items.findItem(item.uuid) if (matchingTag) { - this.selected = matchingTag as AnyTag + void this.setSelectedTag(matchingTag as AnyTag) return } } } else if (action === ComponentAction.ClearSelection) { - this.selected = this.smartViews[0] + void this.setSelectedTag(this.smartViews[0]) } }