refactor: pass sub controllers to controllers instead of passing global controller manager (#1061)
This commit is contained in:
@@ -1,14 +1,27 @@
|
||||
import { DeinitSource } from '@standardnotes/snjs'
|
||||
import { CrossControllerEvent } from '../CrossControllerEvent'
|
||||
import { InternalEventBus, InternalEventPublishStrategy } from '@standardnotes/snjs'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
import { Disposer } from '@/Types/Disposer'
|
||||
|
||||
export abstract class AbstractViewController {
|
||||
dealloced = false
|
||||
protected disposers: Disposer[] = []
|
||||
|
||||
constructor(public application: WebApplication, public viewControllerManager?: AbstractViewController) {}
|
||||
constructor(public application: WebApplication, protected eventBus: InternalEventBus) {}
|
||||
|
||||
deinit(_source: DeinitSource): void {
|
||||
protected async publishEventSync(name: CrossControllerEvent): Promise<void> {
|
||||
await this.eventBus.publishSync({ type: name, payload: undefined }, InternalEventPublishStrategy.SEQUENCE)
|
||||
}
|
||||
|
||||
deinit(): void {
|
||||
this.dealloced = true
|
||||
;(this.application as unknown) = undefined
|
||||
;(this.viewControllerManager as unknown) = undefined
|
||||
;(this.eventBus as unknown) = undefined
|
||||
|
||||
for (const disposer of this.disposers) {
|
||||
disposer()
|
||||
}
|
||||
|
||||
;(this.disposers as unknown) = undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { AbstractViewController } from './AbstractViewController'
|
||||
|
||||
export function isControllerDealloced(state: AbstractViewController): boolean {
|
||||
return state.dealloced == undefined || state.dealloced === true
|
||||
export function isControllerDealloced(controller: { dealloced: boolean }): boolean {
|
||||
return controller.dealloced == undefined || controller.dealloced === true
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { destroyAllObjectProperties, isDev } from '@/Utils'
|
||||
import { action, computed, makeObservable, observable, runInAction } from 'mobx'
|
||||
import { ApplicationEvent, ContentType, DeinitSource, SNNote, SNTag } from '@standardnotes/snjs'
|
||||
import { ApplicationEvent, ContentType, InternalEventBus, SNNote, SNTag } from '@standardnotes/snjs'
|
||||
import { WebApplication } from '@/Application/Application'
|
||||
import { AccountMenuPane } from '@/Components/AccountMenu/AccountMenuPane'
|
||||
import { AbstractViewController } from '../Abstract/AbstractViewController'
|
||||
@@ -21,15 +21,16 @@ export class AccountMenuController extends AbstractViewController {
|
||||
shouldAnimateCloseMenu = false
|
||||
currentPane = AccountMenuPane.GeneralMenu
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.notesAndTags as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(application: WebApplication, private appEventListeners: (() => void)[]) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
show: observable,
|
||||
signingOut: observable,
|
||||
@@ -60,12 +61,7 @@ export class AccountMenuController extends AbstractViewController {
|
||||
notesAndTagsCount: computed,
|
||||
})
|
||||
|
||||
this.addAppLaunchedEventObserver()
|
||||
this.streamNotesAndTags()
|
||||
}
|
||||
|
||||
addAppLaunchedEventObserver = (): void => {
|
||||
this.appEventListeners.push(
|
||||
this.disposers.push(
|
||||
this.application.addEventObserver(async () => {
|
||||
runInAction(() => {
|
||||
if (isDev && window.devAccountServer) {
|
||||
@@ -77,10 +73,8 @@ export class AccountMenuController extends AbstractViewController {
|
||||
})
|
||||
}, ApplicationEvent.Launched),
|
||||
)
|
||||
}
|
||||
|
||||
streamNotesAndTags = (): void => {
|
||||
this.appEventListeners.push(
|
||||
this.disposers.push(
|
||||
this.application.streamItems([ContentType.Note, ContentType.Tag], () => {
|
||||
runInAction(() => {
|
||||
this.notesAndTags = this.application.items.getItems([ContentType.Note, ContentType.Tag])
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum CrossControllerEvent {
|
||||
TagChanged = 'TagChanged',
|
||||
ActiveEditorChanged = 'ActiveEditorChanged',
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { WebApplication } from '@/Application/Application'
|
||||
import { destroyAllObjectProperties } from '@/Utils'
|
||||
import { ApplicationEvent, DeinitSource, FeatureIdentifier, FeatureStatus } from '@standardnotes/snjs'
|
||||
import { ApplicationEvent, FeatureIdentifier, FeatureStatus, InternalEventBus } from '@standardnotes/snjs'
|
||||
import { action, makeObservable, observable, runInAction, when } from 'mobx'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
|
||||
@@ -10,8 +10,8 @@ export class FeaturesController extends AbstractViewController {
|
||||
hasFiles: boolean
|
||||
premiumAlertFeatureName: string | undefined
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.showPremiumAlert as unknown) = undefined
|
||||
;(this.closePremiumAlert as unknown) = undefined
|
||||
;(this.hasFolders as unknown) = undefined
|
||||
@@ -22,8 +22,8 @@ export class FeaturesController extends AbstractViewController {
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(application: WebApplication, appObservers: (() => void)[]) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
this.hasFolders = this.isEntitledToFolders()
|
||||
this.hasSmartViews = this.isEntitledToSmartViews()
|
||||
@@ -43,7 +43,7 @@ export class FeaturesController extends AbstractViewController {
|
||||
this.showPremiumAlert = this.showPremiumAlert.bind(this)
|
||||
this.closePremiumAlert = this.closePremiumAlert.bind(this)
|
||||
|
||||
appObservers.push(
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async (event) => {
|
||||
switch (event) {
|
||||
case ApplicationEvent.FeaturesUpdated:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { FilePreviewModalController } from './FilePreviewModalController'
|
||||
import {
|
||||
PopoverFileItemAction,
|
||||
PopoverFileItemActionType,
|
||||
@@ -13,12 +14,13 @@ import {
|
||||
ClassicFileSaver,
|
||||
parseFileName,
|
||||
} from '@standardnotes/filepicker'
|
||||
import { ChallengeReason, ClientDisplayableError, ContentType, FileItem } from '@standardnotes/snjs'
|
||||
import { ChallengeReason, ClientDisplayableError, ContentType, FileItem, InternalEventBus } from '@standardnotes/snjs'
|
||||
import { addToast, dismissToast, ToastType, updateToast } from '@standardnotes/stylekit'
|
||||
import { action, computed, makeObservable, observable, reaction } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
import { ViewControllerManager } from '../Services/ViewControllerManager/ViewControllerManager'
|
||||
import { NotesController } from './NotesController'
|
||||
import { SelectedItemsController } from './SelectedItemsController'
|
||||
|
||||
const UnprotectedFileActions = [PopoverFileItemActionType.ToggleFileProtection]
|
||||
const NonMutatingFileActions = [PopoverFileItemActionType.DownloadFile, PopoverFileItemActionType.PreviewFile]
|
||||
@@ -31,12 +33,21 @@ export class FilesController extends AbstractViewController {
|
||||
showFileContextMenu = false
|
||||
fileContextMenuLocation: FileContextMenuLocation = { x: 0, y: 0 }
|
||||
|
||||
override deinit(): void {
|
||||
super.deinit()
|
||||
;(this.notesController as unknown) = undefined
|
||||
;(this.selectionController as unknown) = undefined
|
||||
;(this.filePreviewModalController as unknown) = undefined
|
||||
}
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
override viewControllerManager: ViewControllerManager,
|
||||
appObservers: (() => void)[],
|
||||
private notesController: NotesController,
|
||||
private selectionController: SelectedItemsController,
|
||||
private filePreviewModalController: FilePreviewModalController,
|
||||
eventBus: InternalEventBus,
|
||||
) {
|
||||
super(application, viewControllerManager)
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
allFiles: observable,
|
||||
@@ -52,13 +63,16 @@ export class FilesController extends AbstractViewController {
|
||||
setFileContextMenuLocation: action,
|
||||
})
|
||||
|
||||
appObservers.push(
|
||||
this.disposers.push(
|
||||
application.streamItems(ContentType.File, () => {
|
||||
this.reloadAllFiles()
|
||||
this.reloadAttachedFiles()
|
||||
}),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
reaction(
|
||||
() => viewControllerManager.notesController.selectedNotes,
|
||||
() => notesController.selectedNotes,
|
||||
() => {
|
||||
this.reloadAttachedFiles()
|
||||
},
|
||||
@@ -67,7 +81,7 @@ export class FilesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
get selectedFiles(): FileItem[] {
|
||||
return this.viewControllerManager.selectionController.getSelectedItems<FileItem>(ContentType.File)
|
||||
return this.selectionController.getSelectedItems<FileItem>(ContentType.File)
|
||||
}
|
||||
|
||||
setShowFileContextMenu = (enabled: boolean) => {
|
||||
@@ -83,7 +97,7 @@ export class FilesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
reloadAttachedFiles = () => {
|
||||
const note = this.viewControllerManager.notesController.firstSelectedNote
|
||||
const note = this.notesController.firstSelectedNote
|
||||
if (note) {
|
||||
this.attachedFiles = this.application.items.getFilesForNote(note)
|
||||
}
|
||||
@@ -109,7 +123,7 @@ export class FilesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
attachFileToNote = async (file: FileItem) => {
|
||||
const note = this.viewControllerManager.notesController.firstSelectedNote
|
||||
const note = this.notesController.firstSelectedNote
|
||||
if (!note) {
|
||||
addToast({
|
||||
type: ToastType.Error,
|
||||
@@ -122,7 +136,7 @@ export class FilesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
detachFileFromNote = async (file: FileItem) => {
|
||||
const note = this.viewControllerManager.notesController.firstSelectedNote
|
||||
const note = this.notesController.firstSelectedNote
|
||||
if (!note) {
|
||||
addToast({
|
||||
type: ToastType.Error,
|
||||
@@ -197,7 +211,7 @@ export class FilesController extends AbstractViewController {
|
||||
await this.renameFile(file, action.payload.name)
|
||||
break
|
||||
case PopoverFileItemActionType.PreviewFile:
|
||||
this.viewControllerManager.filePreviewModalController.activate(
|
||||
this.filePreviewModalController.activate(
|
||||
file,
|
||||
currentTab === PopoverTabs.AllFiles ? this.allFiles : this.attachedFiles,
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
ApplicationEvent,
|
||||
CollectionSort,
|
||||
ContentType,
|
||||
DeinitSource,
|
||||
findInArray,
|
||||
NoteViewController,
|
||||
PrefKey,
|
||||
@@ -13,13 +12,21 @@ import {
|
||||
SNTag,
|
||||
SystemViewId,
|
||||
DisplayOptions,
|
||||
InternalEventBus,
|
||||
InternalEventHandlerInterface,
|
||||
InternalEventInterface,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
import { AbstractViewController } from '../Abstract/AbstractViewController'
|
||||
import { ViewControllerManager } from '../../Services/ViewControllerManager/ViewControllerManager'
|
||||
import { ViewControllerManagerEvent } from '../../Services/ViewControllerManager/ViewControllerManagerEvent'
|
||||
import { WebDisplayOptions } from './WebDisplayOptions'
|
||||
import { NavigationController } from '../Navigation/NavigationController'
|
||||
import { CrossControllerEvent } from '../CrossControllerEvent'
|
||||
import { SearchOptionsController } from '../SearchOptionsController'
|
||||
import { SelectedItemsController } from '../SelectedItemsController'
|
||||
import { NotesController } from '../NotesController'
|
||||
import { NoteTagsController } from '../NoteTagsController'
|
||||
import { WebAppEvent } from '@/Application/WebAppEvent'
|
||||
|
||||
const MinNoteCellHeight = 51.0
|
||||
const DefaultListNumNotes = 20
|
||||
@@ -27,7 +34,7 @@ const ElementIdSearchBar = 'search-bar'
|
||||
const ElementIdScrollContainer = 'notes-scrollable'
|
||||
const SupportsFileSelectionState = false
|
||||
|
||||
export class ItemListController extends AbstractViewController {
|
||||
export class ItemListController extends AbstractViewController implements InternalEventHandlerInterface {
|
||||
completedFullSync = false
|
||||
noteFilterText = ''
|
||||
notes: SNNote[] = []
|
||||
@@ -55,11 +62,16 @@ export class ItemListController extends AbstractViewController {
|
||||
}
|
||||
private reloadItemsPromise?: Promise<unknown>
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.noteFilterText as unknown) = undefined
|
||||
;(this.notes as unknown) = undefined
|
||||
;(this.renderedItems as unknown) = undefined
|
||||
;(this.navigationController as unknown) = undefined
|
||||
;(this.searchOptionsController as unknown) = undefined
|
||||
;(this.selectionController as unknown) = undefined
|
||||
;(this.notesController as unknown) = undefined
|
||||
;(this.noteTagsController as unknown) = undefined
|
||||
;(window.onresize as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
@@ -67,18 +79,27 @@ export class ItemListController extends AbstractViewController {
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
override viewControllerManager: ViewControllerManager,
|
||||
appObservers: (() => void)[],
|
||||
private navigationController: NavigationController,
|
||||
private searchOptionsController: SearchOptionsController,
|
||||
private selectionController: SelectedItemsController,
|
||||
private notesController: NotesController,
|
||||
private noteTagsController: NoteTagsController,
|
||||
eventBus: InternalEventBus,
|
||||
) {
|
||||
super(application, viewControllerManager)
|
||||
super(application, eventBus)
|
||||
|
||||
eventBus.addEventHandler(this, CrossControllerEvent.TagChanged)
|
||||
eventBus.addEventHandler(this, CrossControllerEvent.ActiveEditorChanged)
|
||||
|
||||
this.resetPagination()
|
||||
|
||||
appObservers.push(
|
||||
this.disposers.push(
|
||||
application.streamItems<SNNote>(ContentType.Note, () => {
|
||||
void this.reloadItems()
|
||||
}),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.streamItems<SNTag>([ContentType.Tag], async ({ changed, inserted }) => {
|
||||
const tags = [...changed, ...inserted]
|
||||
|
||||
@@ -87,28 +108,34 @@ export class ItemListController extends AbstractViewController {
|
||||
|
||||
void this.reloadItems()
|
||||
|
||||
if (
|
||||
viewControllerManager.navigationController.selected &&
|
||||
findInArray(tags, 'uuid', viewControllerManager.navigationController.selected.uuid)
|
||||
) {
|
||||
if (this.navigationController.selected && findInArray(tags, 'uuid', this.navigationController.selected.uuid)) {
|
||||
/** Tag title could have changed */
|
||||
this.reloadPanelTitle()
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
void this.reloadPreferences()
|
||||
}, ApplicationEvent.PreferencesChanged),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
this.application.noteControllerGroup.closeAllNoteControllers()
|
||||
void this.selectFirstItem()
|
||||
this.setCompletedFullSync(false)
|
||||
}, ApplicationEvent.SignedIn),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
void this.reloadItems().then(() => {
|
||||
if (
|
||||
this.notes.length === 0 &&
|
||||
viewControllerManager.navigationController.selected instanceof SmartView &&
|
||||
viewControllerManager.navigationController.selected.uuid === SystemViewId.AllNotes &&
|
||||
this.navigationController.selected instanceof SmartView &&
|
||||
this.navigationController.selected.uuid === SystemViewId.AllNotes &&
|
||||
this.noteFilterText === '' &&
|
||||
!this.getActiveNoteController()
|
||||
) {
|
||||
@@ -117,28 +144,28 @@ export class ItemListController extends AbstractViewController {
|
||||
})
|
||||
this.setCompletedFullSync(true)
|
||||
}, ApplicationEvent.CompletedFullSync),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addWebEventObserver((webEvent) => {
|
||||
if (webEvent === WebAppEvent.EditorFocused) {
|
||||
this.setShowDisplayOptionsMenu(false)
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
reaction(
|
||||
() => [
|
||||
viewControllerManager.searchOptionsController.includeProtectedContents,
|
||||
viewControllerManager.searchOptionsController.includeArchived,
|
||||
viewControllerManager.searchOptionsController.includeTrashed,
|
||||
this.searchOptionsController.includeProtectedContents,
|
||||
this.searchOptionsController.includeArchived,
|
||||
this.searchOptionsController.includeTrashed,
|
||||
],
|
||||
() => {
|
||||
this.reloadNotesDisplayOptions()
|
||||
void this.reloadItems()
|
||||
},
|
||||
),
|
||||
|
||||
viewControllerManager.addObserver(async (eventName) => {
|
||||
if (eventName === ViewControllerManagerEvent.TagChanged) {
|
||||
this.handleTagChange()
|
||||
} else if (eventName === ViewControllerManagerEvent.ActiveEditorChanged) {
|
||||
this.handleEditorChange().catch(console.error)
|
||||
} else if (eventName === ViewControllerManagerEvent.EditorFocused) {
|
||||
this.setShowDisplayOptionsMenu(false)
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
makeObservable(this, {
|
||||
@@ -170,6 +197,14 @@ export class ItemListController extends AbstractViewController {
|
||||
}
|
||||
}
|
||||
|
||||
async handleEvent(event: InternalEventInterface): Promise<void> {
|
||||
if (event.type === CrossControllerEvent.TagChanged) {
|
||||
this.handleTagChange()
|
||||
} else if (event.type === CrossControllerEvent.ActiveEditorChanged) {
|
||||
this.handleEditorChange().catch(console.error)
|
||||
}
|
||||
}
|
||||
|
||||
public getActiveNoteController(): NoteViewController | undefined {
|
||||
return this.application.noteControllerGroup.activeNoteViewController
|
||||
}
|
||||
@@ -200,8 +235,8 @@ export class ItemListController extends AbstractViewController {
|
||||
if (this.isFiltering) {
|
||||
const resultCount = this.notes.length
|
||||
title = `${resultCount} search results`
|
||||
} else if (this.viewControllerManager.navigationController.selected) {
|
||||
title = `${this.viewControllerManager.navigationController.selected.title}`
|
||||
} else if (this.navigationController.selected) {
|
||||
title = `${this.navigationController.selected.title}`
|
||||
}
|
||||
|
||||
this.panelTitle = title
|
||||
@@ -218,7 +253,7 @@ export class ItemListController extends AbstractViewController {
|
||||
}
|
||||
|
||||
private async performReloadItems() {
|
||||
const tag = this.viewControllerManager.navigationController.selected
|
||||
const tag = this.navigationController.selected
|
||||
if (!tag) {
|
||||
return
|
||||
}
|
||||
@@ -241,17 +276,16 @@ export class ItemListController extends AbstractViewController {
|
||||
}
|
||||
|
||||
private async recomputeSelectionAfterItemsReload() {
|
||||
const viewControllerManager = this.viewControllerManager
|
||||
const activeController = this.getActiveNoteController()
|
||||
const activeNote = activeController?.note
|
||||
const isSearching = this.noteFilterText.length > 0
|
||||
const hasMultipleItemsSelected = viewControllerManager.selectionController.selectedItemsCount >= 2
|
||||
const hasMultipleItemsSelected = this.selectionController.selectedItemsCount >= 2
|
||||
|
||||
if (hasMultipleItemsSelected) {
|
||||
return
|
||||
}
|
||||
|
||||
const selectedItem = Object.values(viewControllerManager.selectionController.selectedItems)[0]
|
||||
const selectedItem = Object.values(this.selectionController.selectedItems)[0]
|
||||
|
||||
const isSelectedItemFile =
|
||||
this.items.includes(selectedItem) && selectedItem && selectedItem.content_type === ContentType.File
|
||||
@@ -280,25 +314,25 @@ export class ItemListController extends AbstractViewController {
|
||||
}
|
||||
|
||||
const showTrashedNotes =
|
||||
(viewControllerManager.navigationController.selected instanceof SmartView &&
|
||||
viewControllerManager.navigationController.selected?.uuid === SystemViewId.TrashedNotes) ||
|
||||
viewControllerManager?.searchOptionsController.includeTrashed
|
||||
(this.navigationController.selected instanceof SmartView &&
|
||||
this.navigationController.selected?.uuid === SystemViewId.TrashedNotes) ||
|
||||
this.searchOptionsController.includeTrashed
|
||||
|
||||
const showArchivedNotes =
|
||||
(viewControllerManager.navigationController.selected instanceof SmartView &&
|
||||
viewControllerManager.navigationController.selected.uuid === SystemViewId.ArchivedNotes) ||
|
||||
viewControllerManager.searchOptionsController.includeArchived ||
|
||||
(this.navigationController.selected instanceof SmartView &&
|
||||
this.navigationController.selected.uuid === SystemViewId.ArchivedNotes) ||
|
||||
this.searchOptionsController.includeArchived ||
|
||||
this.application.getPreference(PrefKey.NotesShowArchived, false)
|
||||
|
||||
if ((activeNote.trashed && !showTrashedNotes) || (activeNote.archived && !showArchivedNotes)) {
|
||||
await this.selectNextItemOrCreateNewNote()
|
||||
} else if (!this.viewControllerManager.selectionController.selectedItems[activeNote.uuid]) {
|
||||
await this.viewControllerManager.selectionController.selectItem(activeNote.uuid).catch(console.error)
|
||||
} else if (!this.selectionController.selectedItems[activeNote.uuid]) {
|
||||
await this.selectionController.selectItem(activeNote.uuid).catch(console.error)
|
||||
}
|
||||
}
|
||||
|
||||
reloadNotesDisplayOptions = () => {
|
||||
const tag = this.viewControllerManager.navigationController.selected
|
||||
const tag = this.navigationController.selected
|
||||
|
||||
const searchText = this.noteFilterText.toLowerCase()
|
||||
const isSearching = searchText.length
|
||||
@@ -306,8 +340,8 @@ export class ItemListController extends AbstractViewController {
|
||||
let includeTrashed: boolean
|
||||
|
||||
if (isSearching) {
|
||||
includeArchived = this.viewControllerManager.searchOptionsController.includeArchived
|
||||
includeTrashed = this.viewControllerManager.searchOptionsController.includeTrashed
|
||||
includeArchived = this.searchOptionsController.includeArchived
|
||||
includeTrashed = this.searchOptionsController.includeTrashed
|
||||
} else {
|
||||
includeArchived = this.displayOptions.includeArchived ?? false
|
||||
includeTrashed = this.displayOptions.includeTrashed ?? false
|
||||
@@ -324,7 +358,7 @@ export class ItemListController extends AbstractViewController {
|
||||
includeProtected: this.displayOptions.includeProtected,
|
||||
searchQuery: {
|
||||
query: searchText,
|
||||
includeProtectedNoteText: this.viewControllerManager.searchOptionsController.includeProtectedContents,
|
||||
includeProtectedNoteText: this.searchOptionsController.includeProtectedContents,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -387,13 +421,10 @@ export class ItemListController extends AbstractViewController {
|
||||
}
|
||||
|
||||
createNewNote = async () => {
|
||||
this.viewControllerManager.notesController.unselectNotes()
|
||||
this.notesController.unselectNotes()
|
||||
|
||||
if (
|
||||
this.viewControllerManager.navigationController.isInSmartView() &&
|
||||
!this.viewControllerManager.navigationController.isInHomeView()
|
||||
) {
|
||||
await this.viewControllerManager.navigationController.selectHomeNavigationView()
|
||||
if (this.navigationController.isInSmartView() && !this.navigationController.isInHomeView()) {
|
||||
await this.navigationController.selectHomeNavigationView()
|
||||
}
|
||||
|
||||
let title = `Note ${this.notes.length + 1}`
|
||||
@@ -401,16 +432,13 @@ export class ItemListController extends AbstractViewController {
|
||||
title = this.noteFilterText
|
||||
}
|
||||
|
||||
await this.viewControllerManager.notesController.createNewNoteController(title)
|
||||
await this.notesController.createNewNoteController(title)
|
||||
|
||||
this.viewControllerManager.noteTagsController.reloadTagsForCurrentNote()
|
||||
this.noteTagsController.reloadTagsForCurrentNote()
|
||||
}
|
||||
|
||||
createPlaceholderNote = () => {
|
||||
if (
|
||||
this.viewControllerManager.navigationController.isInSmartView() &&
|
||||
!this.viewControllerManager.navigationController.isInHomeView()
|
||||
) {
|
||||
if (this.navigationController.isInSmartView() && !this.navigationController.isInHomeView()) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -487,7 +515,7 @@ export class ItemListController extends AbstractViewController {
|
||||
},
|
||||
{ userTriggered = false, scrollIntoView = true },
|
||||
): Promise<void> => {
|
||||
await this.viewControllerManager.selectionController.selectItem(item.uuid, userTriggered)
|
||||
await this.selectionController.selectItem(item.uuid, userTriggered)
|
||||
|
||||
if (scrollIntoView) {
|
||||
const itemElement = document.getElementById(item.uuid)
|
||||
@@ -514,7 +542,7 @@ export class ItemListController extends AbstractViewController {
|
||||
const displayableItems = this.items
|
||||
|
||||
const currentIndex = displayableItems.findIndex((candidate) => {
|
||||
return candidate.uuid === this.viewControllerManager.selectionController.lastSelectedItem?.uuid
|
||||
return candidate.uuid === this.selectionController.lastSelectedItem?.uuid
|
||||
})
|
||||
|
||||
let nextIndex = currentIndex + 1
|
||||
@@ -554,11 +582,11 @@ export class ItemListController extends AbstractViewController {
|
||||
selectPreviousItem = () => {
|
||||
const displayableItems = this.items
|
||||
|
||||
if (!this.viewControllerManager.selectionController.lastSelectedItem) {
|
||||
if (!this.selectionController.lastSelectedItem) {
|
||||
return
|
||||
}
|
||||
|
||||
const currentIndex = displayableItems.indexOf(this.viewControllerManager.selectionController.lastSelectedItem)
|
||||
const currentIndex = displayableItems.indexOf(this.selectionController.lastSelectedItem)
|
||||
|
||||
let previousIndex = currentIndex - 1
|
||||
|
||||
|
||||
@@ -11,20 +11,20 @@ import {
|
||||
UuidString,
|
||||
isSystemView,
|
||||
FindItem,
|
||||
DeinitSource,
|
||||
SystemViewId,
|
||||
InternalEventBus,
|
||||
InternalEventPublishStrategy,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeAutoObservable, makeObservable, observable, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
import { FeaturesController } from '../FeaturesController'
|
||||
import { AbstractViewController } from '../Abstract/AbstractViewController'
|
||||
import { destroyAllObjectProperties } from '@/Utils'
|
||||
import { ViewControllerManager } from '../../Services/ViewControllerManager/ViewControllerManager'
|
||||
import { ViewControllerManagerEvent } from '../../Services/ViewControllerManager/ViewControllerManagerEvent'
|
||||
import { isValidFutureSiblings, rootTags, tagSiblings } from './Utils'
|
||||
import { AnyTag } from './AnyTagType'
|
||||
import { CrossControllerEvent } from '../CrossControllerEvent'
|
||||
|
||||
export class TagsController extends AbstractViewController {
|
||||
export class NavigationController extends AbstractViewController {
|
||||
tags: SNTag[] = []
|
||||
smartViews: SmartView[] = []
|
||||
allNotesCount_ = 0
|
||||
@@ -43,13 +43,8 @@ export class TagsController extends AbstractViewController {
|
||||
|
||||
private readonly tagsCountsState: TagsCountsState
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
override viewControllerManager: ViewControllerManager,
|
||||
appEventListeners: (() => void)[],
|
||||
private features: FeaturesController,
|
||||
) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, private featuresController: FeaturesController, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
this.tagsCountsState = new TagsCountsState(this.application)
|
||||
|
||||
@@ -99,7 +94,7 @@ export class TagsController extends AbstractViewController {
|
||||
setContextMenuMaxHeight: action,
|
||||
})
|
||||
|
||||
appEventListeners.push(
|
||||
this.disposers.push(
|
||||
this.application.streamItems([ContentType.Tag, ContentType.SmartView], ({ changed, removed }) => {
|
||||
runInAction(() => {
|
||||
this.tags = this.application.items.getDisplayableTags()
|
||||
@@ -131,7 +126,7 @@ export class TagsController extends AbstractViewController {
|
||||
}),
|
||||
)
|
||||
|
||||
appEventListeners.push(
|
||||
this.disposers.push(
|
||||
this.application.items.addNoteCountChangeObserver((tagUuid) => {
|
||||
if (!tagUuid) {
|
||||
this.setAllNotesCount(this.application.items.allCountableNotesCount())
|
||||
@@ -145,15 +140,16 @@ export class TagsController extends AbstractViewController {
|
||||
)
|
||||
}
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
;(this.features as unknown) = undefined
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.featuresController as unknown) = undefined
|
||||
;(this.tags as unknown) = undefined
|
||||
;(this.smartViews as unknown) = undefined
|
||||
;(this.selected_ as unknown) = undefined
|
||||
;(this.previouslySelected_ as unknown) = undefined
|
||||
;(this.editing_ as unknown) = undefined
|
||||
;(this.addingSubtagTo as unknown) = undefined
|
||||
;(this.featuresController as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
@@ -369,10 +365,13 @@ export class TagsController extends AbstractViewController {
|
||||
return
|
||||
}
|
||||
|
||||
await this.viewControllerManager.notifyEvent(ViewControllerManagerEvent.TagChanged, {
|
||||
tag,
|
||||
previousTag: this.previouslySelected_,
|
||||
})
|
||||
await this.eventBus.publishSync(
|
||||
{
|
||||
type: CrossControllerEvent.TagChanged,
|
||||
payload: { tag, previousTag: this.previouslySelected_ },
|
||||
},
|
||||
InternalEventPublishStrategy.SEQUENCE,
|
||||
)
|
||||
}
|
||||
|
||||
public async selectHomeNavigationView(): Promise<void> {
|
||||
@@ -473,8 +472,8 @@ export class TagsController extends AbstractViewController {
|
||||
const isSmartViewTitle = this.application.items.isSmartViewTitle(newTitle)
|
||||
|
||||
if (isSmartViewTitle) {
|
||||
if (!this.features.hasSmartViews) {
|
||||
await this.features.showPremiumAlert(SMART_TAGS_FEATURE_NAME)
|
||||
if (!this.featuresController.hasSmartViews) {
|
||||
await this.featuresController.showPremiumAlert(SMART_TAGS_FEATURE_NAME)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { storage, StorageKey } from '@/Services/LocalStorage'
|
||||
import { ApplicationEvent } from '@standardnotes/snjs'
|
||||
import { ApplicationEvent, InternalEventBus } from '@standardnotes/snjs'
|
||||
import { runInAction, makeObservable, observable, action } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
@@ -7,17 +7,20 @@ import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
export class NoAccountWarningController extends AbstractViewController {
|
||||
show: boolean
|
||||
|
||||
constructor(application: WebApplication, appObservers: (() => void)[]) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
this.show = application.hasAccount() ? false : storage.get(StorageKey.ShowNoAccountWarning) ?? true
|
||||
|
||||
appObservers.push(
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
runInAction(() => {
|
||||
this.show = false
|
||||
})
|
||||
}, ApplicationEvent.SignedIn),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
if (application.hasAccount()) {
|
||||
runInAction(() => {
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
import { ElementIds } from '@/Constants/ElementIDs'
|
||||
import { destroyAllObjectProperties } from '@/Utils'
|
||||
import { ApplicationEvent, ContentType, DeinitSource, PrefKey, SNNote, SNTag, UuidString } from '@standardnotes/snjs'
|
||||
import {
|
||||
ApplicationEvent,
|
||||
ContentType,
|
||||
InternalEventBus,
|
||||
PrefKey,
|
||||
SNNote,
|
||||
SNTag,
|
||||
UuidString,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
import { ViewControllerManager } from '../Services/ViewControllerManager/ViewControllerManager'
|
||||
import { ItemListController } from './ItemList/ItemListController'
|
||||
|
||||
export class NoteTagsController extends AbstractViewController {
|
||||
autocompleteInputFocused = false
|
||||
@@ -16,21 +24,19 @@ export class NoteTagsController extends AbstractViewController {
|
||||
tags: SNTag[] = []
|
||||
tagsContainerMaxWidth: number | 'auto' = 0
|
||||
addNoteToParentFolders: boolean
|
||||
private itemListController!: ItemListController
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.tags as unknown) = undefined
|
||||
;(this.autocompleteTagResults as unknown) = undefined
|
||||
;(this.itemListController as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
override viewControllerManager: ViewControllerManager,
|
||||
appEventListeners: (() => void)[],
|
||||
) {
|
||||
super(application, viewControllerManager)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
autocompleteInputFocused: observable,
|
||||
@@ -55,13 +61,17 @@ export class NoteTagsController extends AbstractViewController {
|
||||
})
|
||||
|
||||
this.addNoteToParentFolders = application.getPreference(PrefKey.NoteAddToParentFolders, true)
|
||||
}
|
||||
|
||||
appEventListeners.push(
|
||||
application.streamItems(ContentType.Tag, () => {
|
||||
public setServicestPostConstruction(itemListController: ItemListController) {
|
||||
this.itemListController = itemListController
|
||||
|
||||
this.disposers.push(
|
||||
this.application.streamItems(ContentType.Tag, () => {
|
||||
this.reloadTagsForCurrentNote()
|
||||
}),
|
||||
application.addSingleEventObserver(ApplicationEvent.PreferencesChanged, async () => {
|
||||
this.addNoteToParentFolders = application.getPreference(PrefKey.NoteAddToParentFolders, true)
|
||||
this.application.addSingleEventObserver(ApplicationEvent.PreferencesChanged, async () => {
|
||||
this.addNoteToParentFolders = this.application.getPreference(PrefKey.NoteAddToParentFolders, true)
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -151,7 +161,7 @@ export class NoteTagsController extends AbstractViewController {
|
||||
searchActiveNoteAutocompleteTags(): void {
|
||||
const newResults = this.application.items.searchTags(
|
||||
this.autocompleteSearchQuery,
|
||||
this.viewControllerManager.contentListController.activeControllerNote,
|
||||
this.itemListController.activeControllerNote,
|
||||
)
|
||||
this.setAutocompleteTagResults(newResults)
|
||||
}
|
||||
@@ -161,7 +171,7 @@ export class NoteTagsController extends AbstractViewController {
|
||||
}
|
||||
|
||||
reloadTagsForCurrentNote(): void {
|
||||
const activeNote = this.viewControllerManager.contentListController.activeControllerNote
|
||||
const activeNote = this.itemListController.activeControllerNote
|
||||
|
||||
if (activeNote) {
|
||||
const tags = this.application.items.getSortedTagsForNote(activeNote)
|
||||
@@ -177,7 +187,7 @@ export class NoteTagsController extends AbstractViewController {
|
||||
}
|
||||
|
||||
async addTagToActiveNote(tag: SNTag): Promise<void> {
|
||||
const activeNote = this.viewControllerManager.contentListController.activeControllerNote
|
||||
const activeNote = this.itemListController.activeControllerNote
|
||||
|
||||
if (activeNote) {
|
||||
await this.application.items.addTagToNote(activeNote, tag, this.addNoteToParentFolders)
|
||||
@@ -187,7 +197,7 @@ export class NoteTagsController extends AbstractViewController {
|
||||
}
|
||||
|
||||
async removeTagFromActiveNote(tag: SNTag): Promise<void> {
|
||||
const activeNote = this.viewControllerManager.contentListController.activeControllerNote
|
||||
const activeNote = this.itemListController.activeControllerNote
|
||||
|
||||
if (activeNote) {
|
||||
await this.application.mutator.changeItem(tag, (mutator) => {
|
||||
|
||||
@@ -2,11 +2,15 @@ import { destroyAllObjectProperties } from '@/Utils'
|
||||
import { confirmDialog } from '@/Services/AlertService'
|
||||
import { StringEmptyTrash, Strings, StringUtils } from '@/Constants/Strings'
|
||||
import { MENU_MARGIN_FROM_APP_BORDER } from '@/Constants/Constants'
|
||||
import { SNNote, NoteMutator, ContentType, SNTag, DeinitSource, TagMutator } from '@standardnotes/snjs'
|
||||
import { SNNote, NoteMutator, ContentType, SNTag, TagMutator, InternalEventBus } from '@standardnotes/snjs'
|
||||
import { makeObservable, observable, action, computed, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
import { ViewControllerManager } from '../Services/ViewControllerManager/ViewControllerManager'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
import { SelectedItemsController } from './SelectedItemsController'
|
||||
import { ItemListController } from './ItemList/ItemListController'
|
||||
import { NoteTagsController } from './NoteTagsController'
|
||||
import { NavigationController } from './Navigation/NavigationController'
|
||||
import { CrossControllerEvent } from './CrossControllerEvent'
|
||||
|
||||
export class NotesController extends AbstractViewController {
|
||||
lastSelectedNote: SNNote | undefined
|
||||
@@ -19,22 +23,27 @@ export class NotesController extends AbstractViewController {
|
||||
contextMenuMaxHeight: number | 'auto' = 'auto'
|
||||
showProtectedWarning = false
|
||||
showRevisionHistoryModal = false
|
||||
private itemListController!: ItemListController
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.lastSelectedNote as unknown) = undefined
|
||||
;(this.onActiveEditorChanged as unknown) = undefined
|
||||
;(this.selectionController as unknown) = undefined
|
||||
;(this.noteTagsController as unknown) = undefined
|
||||
;(this.navigationController as unknown) = undefined
|
||||
;(this.itemListController as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
public override viewControllerManager: ViewControllerManager,
|
||||
private onActiveEditorChanged: () => Promise<void>,
|
||||
appEventListeners: (() => void)[],
|
||||
private selectionController: SelectedItemsController,
|
||||
private noteTagsController: NoteTagsController,
|
||||
private navigationController: NavigationController,
|
||||
eventBus: InternalEventBus,
|
||||
) {
|
||||
super(application, viewControllerManager)
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
contextMenuOpen: observable,
|
||||
@@ -55,17 +64,21 @@ export class NotesController extends AbstractViewController {
|
||||
setShowRevisionHistoryModal: action,
|
||||
unselectNotes: action,
|
||||
})
|
||||
}
|
||||
|
||||
appEventListeners.push(
|
||||
application.streamItems<SNNote>(ContentType.Note, ({ changed, inserted, removed }) => {
|
||||
public setServicestPostConstruction(itemListController: ItemListController) {
|
||||
this.itemListController = itemListController
|
||||
|
||||
this.disposers.push(
|
||||
this.application.streamItems<SNNote>(ContentType.Note, ({ changed, inserted, removed }) => {
|
||||
runInAction(() => {
|
||||
for (const removedNote of removed) {
|
||||
this.viewControllerManager.selectionController.deselectItem(removedNote)
|
||||
this.selectionController.deselectItem(removedNote)
|
||||
}
|
||||
|
||||
for (const note of [...changed, ...inserted]) {
|
||||
if (this.viewControllerManager.selectionController.isItemSelected(note)) {
|
||||
this.viewControllerManager.selectionController.updateReferenceOfSelectedItem(note)
|
||||
if (this.selectionController.isItemSelected(note)) {
|
||||
this.selectionController.updateReferenceOfSelectedItem(note)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -80,7 +93,7 @@ export class NotesController extends AbstractViewController {
|
||||
|
||||
for (const selectedId of selectedUuids) {
|
||||
if (!activeNoteUuids.includes(selectedId)) {
|
||||
this.viewControllerManager.selectionController.deselectItem({ uuid: selectedId })
|
||||
this.selectionController.deselectItem({ uuid: selectedId })
|
||||
}
|
||||
}
|
||||
}),
|
||||
@@ -88,7 +101,7 @@ export class NotesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
public get selectedNotes(): SNNote[] {
|
||||
return this.viewControllerManager.selectionController.getSelectedItems<SNNote>(ContentType.Note)
|
||||
return this.selectionController.getSelectedItems<SNNote>(ContentType.Note)
|
||||
}
|
||||
|
||||
get firstSelectedNote(): SNNote | undefined {
|
||||
@@ -108,7 +121,7 @@ export class NotesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
async openNote(noteUuid: string): Promise<void> {
|
||||
if (this.viewControllerManager.contentListController.activeControllerNote?.uuid === noteUuid) {
|
||||
if (this.itemListController.activeControllerNote?.uuid === noteUuid) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -120,13 +133,13 @@ export class NotesController extends AbstractViewController {
|
||||
|
||||
await this.application.noteControllerGroup.createNoteController(noteUuid)
|
||||
|
||||
this.viewControllerManager.noteTagsController.reloadTagsForCurrentNote()
|
||||
this.noteTagsController.reloadTagsForCurrentNote()
|
||||
|
||||
await this.onActiveEditorChanged()
|
||||
await this.publishEventSync(CrossControllerEvent.ActiveEditorChanged)
|
||||
}
|
||||
|
||||
async createNewNoteController(title?: string) {
|
||||
const selectedTag = this.viewControllerManager.navigationController.selected
|
||||
const selectedTag = this.navigationController.selected
|
||||
|
||||
const activeRegularTagUuid = selectedTag && selectedTag instanceof SNTag ? selectedTag.uuid : undefined
|
||||
|
||||
@@ -262,7 +275,7 @@ export class NotesController extends AbstractViewController {
|
||||
if (permanently) {
|
||||
for (const note of this.getSelectedNotesList()) {
|
||||
await this.application.mutator.deleteItem(note)
|
||||
this.viewControllerManager.selectionController.deselectItem(note)
|
||||
this.selectionController.deselectItem(note)
|
||||
}
|
||||
} else {
|
||||
await this.changeSelectedNotes((mutator) => {
|
||||
@@ -294,7 +307,7 @@ export class NotesController extends AbstractViewController {
|
||||
})
|
||||
|
||||
runInAction(() => {
|
||||
this.viewControllerManager.selectionController.setSelectedItems({})
|
||||
this.selectionController.setSelectedItems({})
|
||||
this.contextMenuOpen = false
|
||||
})
|
||||
}
|
||||
@@ -311,11 +324,11 @@ export class NotesController extends AbstractViewController {
|
||||
}
|
||||
|
||||
unselectNotes(): void {
|
||||
this.viewControllerManager.selectionController.setSelectedItems({})
|
||||
this.selectionController.setSelectedItems({})
|
||||
}
|
||||
|
||||
getSpellcheckStateForNote(note: SNNote) {
|
||||
return note.spellcheck != undefined ? note.spellcheck : this.viewControllerManager.isGlobalSpellcheckEnabled()
|
||||
return note.spellcheck != undefined ? note.spellcheck : this.application.isGlobalSpellcheckEnabled()
|
||||
}
|
||||
|
||||
async toggleGlobalSpellcheckForNote(note: SNNote) {
|
||||
@@ -358,7 +371,7 @@ export class NotesController extends AbstractViewController {
|
||||
isTagInSelectedNotes(tag: SNTag): boolean {
|
||||
const selectedNotes = this.getSelectedNotesList()
|
||||
return selectedNotes.every((note) =>
|
||||
this.viewControllerManager.getItemTags(note).find((noteTag) => noteTag.uuid === tag.uuid),
|
||||
this.application.getItemTags(note).find((noteTag) => noteTag.uuid === tag.uuid),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { loadPurchaseFlowUrl } from '@/Components/PurchaseFlow/PurchaseFlowFunctions'
|
||||
import { InternalEventBus } from '@standardnotes/snjs'
|
||||
import { action, makeObservable, observable } from 'mobx'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
import { AbstractViewController } from '../Abstract/AbstractViewController'
|
||||
@@ -8,8 +9,8 @@ export class PurchaseFlowController extends AbstractViewController {
|
||||
isOpen = false
|
||||
currentPane = PurchaseFlowPane.CreateAccount
|
||||
|
||||
constructor(application: WebApplication) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
isOpen: observable,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ApplicationEvent } from '@standardnotes/snjs'
|
||||
import { ApplicationEvent, InternalEventBus } from '@standardnotes/snjs'
|
||||
import { makeObservable, observable, action, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
@@ -8,8 +8,8 @@ export class SearchOptionsController extends AbstractViewController {
|
||||
includeArchived = false
|
||||
includeTrashed = false
|
||||
|
||||
constructor(application: WebApplication, appObservers: (() => void)[]) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
includeProtectedContents: observable,
|
||||
@@ -22,7 +22,7 @@ export class SearchOptionsController extends AbstractViewController {
|
||||
refreshIncludeProtectedContents: action,
|
||||
})
|
||||
|
||||
appObservers.push(
|
||||
this.disposers.push(
|
||||
this.application.addEventObserver(async () => {
|
||||
this.refreshIncludeProtectedContents()
|
||||
}, ApplicationEvent.UnprotectedSessionBegan),
|
||||
|
||||
@@ -1,22 +1,35 @@
|
||||
import { ListableContentItem } from '@/Components/ContentListView/Types/ListableContentItem'
|
||||
import { ChallengeReason, ContentType, KeyboardModifier, FileItem, SNNote, UuidString } from '@standardnotes/snjs'
|
||||
import {
|
||||
ChallengeReason,
|
||||
ContentType,
|
||||
KeyboardModifier,
|
||||
FileItem,
|
||||
SNNote,
|
||||
UuidString,
|
||||
InternalEventBus,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../Application/Application'
|
||||
import { AbstractViewController } from './Abstract/AbstractViewController'
|
||||
import { ViewControllerManager } from '../Services/ViewControllerManager/ViewControllerManager'
|
||||
import { ItemListController } from './ItemList/ItemListController'
|
||||
import { NotesController } from './NotesController'
|
||||
|
||||
type SelectedItems = Record<UuidString, ListableContentItem>
|
||||
|
||||
export class SelectedItemsController extends AbstractViewController {
|
||||
lastSelectedItem: ListableContentItem | undefined
|
||||
selectedItems: SelectedItems = {}
|
||||
private itemListController!: ItemListController
|
||||
private notesController!: NotesController
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
override viewControllerManager: ViewControllerManager,
|
||||
appObservers: (() => void)[],
|
||||
) {
|
||||
super(application)
|
||||
override deinit(): void {
|
||||
super.deinit()
|
||||
;(this.itemListController as unknown) = undefined
|
||||
;(this.notesController as unknown) = undefined
|
||||
}
|
||||
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
selectedItems: observable,
|
||||
@@ -26,9 +39,14 @@ export class SelectedItemsController extends AbstractViewController {
|
||||
selectItem: action,
|
||||
setSelectedItems: action,
|
||||
})
|
||||
}
|
||||
|
||||
appObservers.push(
|
||||
application.streamItems<SNNote | FileItem>(
|
||||
public setServicestPostConstruction(itemListController: ItemListController, notesController: NotesController) {
|
||||
this.itemListController = itemListController
|
||||
this.notesController = notesController
|
||||
|
||||
this.disposers.push(
|
||||
this.application.streamItems<SNNote | FileItem>(
|
||||
[ContentType.Note, ContentType.File],
|
||||
({ changed, inserted, removed }) => {
|
||||
runInAction(() => {
|
||||
@@ -82,7 +100,7 @@ export class SelectedItemsController extends AbstractViewController {
|
||||
}
|
||||
|
||||
private selectItemsRange = async (selectedItem: ListableContentItem): Promise<void> => {
|
||||
const items = this.viewControllerManager.contentListController.renderedItems
|
||||
const items = this.itemListController.renderedItems
|
||||
|
||||
const lastSelectedItemIndex = items.findIndex((item) => item.uuid == this.lastSelectedItem?.uuid)
|
||||
const selectedItemIndex = items.findIndex((item) => item.uuid == selectedItem.uuid)
|
||||
@@ -171,7 +189,7 @@ export class SelectedItemsController extends AbstractViewController {
|
||||
if (this.selectedItemsCount === 1) {
|
||||
const item = Object.values(this.selectedItems)[0]
|
||||
if (item.content_type === ContentType.Note) {
|
||||
await this.viewControllerManager.notesController.openNote(item.uuid)
|
||||
await this.notesController.openNote(item.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
ApplicationEvent,
|
||||
ClientDisplayableError,
|
||||
convertTimestampToMilliseconds,
|
||||
DeinitSource,
|
||||
InternalEventBus,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable } from 'mobx'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
@@ -15,16 +15,16 @@ export class SubscriptionController extends AbstractViewController {
|
||||
userSubscription: Subscription | undefined = undefined
|
||||
availableSubscriptions: AvailableSubscriptions | undefined = undefined
|
||||
|
||||
override deinit(source: DeinitSource) {
|
||||
super.deinit(source)
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.userSubscription as unknown) = undefined
|
||||
;(this.availableSubscriptions as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(application: WebApplication, appObservers: (() => void)[]) {
|
||||
super(application)
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
userSubscription: observable,
|
||||
@@ -39,15 +39,21 @@ export class SubscriptionController extends AbstractViewController {
|
||||
setAvailableSubscriptions: action,
|
||||
})
|
||||
|
||||
appObservers.push(
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
if (application.hasAccount()) {
|
||||
this.getSubscriptionInfo().catch(console.error)
|
||||
}
|
||||
}, ApplicationEvent.Launched),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
this.getSubscriptionInfo().catch(console.error)
|
||||
}, ApplicationEvent.SignedIn),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
this.getSubscriptionInfo().catch(console.error)
|
||||
}, ApplicationEvent.UserRolesChanged),
|
||||
|
||||
Reference in New Issue
Block a user