Files
standardnotes-app-web/packages/web/src/javascripts/Components/NoteView/Controller/ItemGroupController.ts

161 lines
4.4 KiB
TypeScript

import { removeFromArray } from '@standardnotes/utils'
import {
AlertService,
ComponentManagerInterface,
FileItem,
ItemManagerInterface,
MutatorClientInterface,
PreferenceServiceInterface,
SNNote,
SessionsClientInterface,
SyncServiceInterface,
} from '@standardnotes/snjs'
import { NoteViewController } from './NoteViewController'
import { FileViewController } from './FileViewController'
import { TemplateNoteViewControllerOptions } from './TemplateNoteViewControllerOptions'
import { IsNativeMobileWeb } from '@standardnotes/ui-services'
type ItemControllerGroupChangeCallback = (activeController: NoteViewController | FileViewController | undefined) => void
export class ItemGroupController {
public itemControllers: (NoteViewController | FileViewController)[] = []
changeObservers: ItemControllerGroupChangeCallback[] = []
eventObservers: (() => void)[] = []
constructor(
private items: ItemManagerInterface,
private mutator: MutatorClientInterface,
private sync: SyncServiceInterface,
private sessions: SessionsClientInterface,
private preferences: PreferenceServiceInterface,
private components: ComponentManagerInterface,
private alerts: AlertService,
private _isNativeMobileWeb: IsNativeMobileWeb,
) {}
public deinit(): void {
;(this.items as unknown) = undefined
this.eventObservers.forEach((removeObserver) => {
removeObserver()
})
this.changeObservers.length = 0
for (const controller of this.itemControllers) {
this.closeItemController(controller, { notify: false })
}
this.itemControllers.length = 0
}
async createItemController(context: {
file?: FileItem
note?: SNNote
templateOptions?: TemplateNoteViewControllerOptions
}): Promise<NoteViewController | FileViewController> {
if (this.activeItemViewController) {
this.closeItemController(this.activeItemViewController, { notify: false })
}
let controller!: NoteViewController | FileViewController
if (context.file) {
controller = new FileViewController(context.file, this.items)
} else if (context.note) {
controller = new NoteViewController(
context.note,
this.items,
this.mutator,
this.sync,
this.sessions,
this.preferences,
this.components,
this.alerts,
this._isNativeMobileWeb,
)
} else if (context.templateOptions) {
controller = new NoteViewController(
undefined,
this.items,
this.mutator,
this.sync,
this.sessions,
this.preferences,
this.components,
this.alerts,
this._isNativeMobileWeb,
context.templateOptions,
)
} else {
throw Error('Invalid input to createItemController')
}
this.itemControllers.push(controller)
await controller.initialize()
this.notifyObservers()
return controller
}
public closeItemController(
controller: NoteViewController | FileViewController,
{ notify = true }: { notify: boolean } = { notify: true },
): void {
if (controller instanceof NoteViewController) {
controller.syncOnlyIfLargeNote()
}
controller.deinit()
removeFromArray(this.itemControllers, controller)
if (notify) {
this.notifyObservers()
}
}
closeActiveItemController(): void {
const activeController = this.activeItemViewController
if (activeController) {
this.closeItemController(activeController, { notify: true })
}
}
closeAllItemControllers(): void {
for (const controller of this.itemControllers) {
this.closeItemController(controller, { notify: false })
}
this.notifyObservers()
}
get activeItemViewController(): NoteViewController | FileViewController | undefined {
return this.itemControllers[0]
}
/**
* Notifies observer when the active controller has changed.
*/
public addActiveControllerChangeObserver(callback: ItemControllerGroupChangeCallback): () => void {
this.changeObservers.push(callback)
if (this.activeItemViewController) {
callback(this.activeItemViewController)
}
const thislessChangeObservers = this.changeObservers
return () => {
removeFromArray(thislessChangeObservers, callback)
}
}
private notifyObservers(): void {
for (const observer of this.changeObservers) {
observer(this.activeItemViewController)
}
}
}