refactor(web): dependency management (#2386)
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import {
|
||||
confirmDialog,
|
||||
CREATE_NEW_TAG_COMMAND,
|
||||
KeyboardService,
|
||||
NavigationControllerPersistableValue,
|
||||
VaultDisplayService,
|
||||
VaultDisplayServiceEvent,
|
||||
} from '@standardnotes/ui-services'
|
||||
import { STRING_DELETE_TAG } from '@/Constants/Strings'
|
||||
@@ -22,9 +24,14 @@ import {
|
||||
InternalEventBusInterface,
|
||||
InternalEventHandlerInterface,
|
||||
InternalEventInterface,
|
||||
ItemManagerInterface,
|
||||
SyncServiceInterface,
|
||||
MutatorClientInterface,
|
||||
AlertService,
|
||||
PreferenceServiceInterface,
|
||||
ChangeAndSaveItem,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../../Application/WebApplication'
|
||||
import { FeaturesController } from '../FeaturesController'
|
||||
import { destroyAllObjectProperties } from '@/Utils'
|
||||
import { isValidFutureSiblings, rootTags, tagSiblings } from './Utils'
|
||||
@@ -35,6 +42,7 @@ import { Persistable } from '../Abstract/Persistable'
|
||||
import { TagListSectionType } from '@/Components/Tags/TagListSection'
|
||||
import { PaneLayout } from '../PaneController/PaneLayout'
|
||||
import { TagsCountsState } from './TagsCountsState'
|
||||
import { PaneController } from '../PaneController/PaneController'
|
||||
|
||||
export class NavigationController
|
||||
extends AbstractViewController
|
||||
@@ -63,16 +71,24 @@ export class NavigationController
|
||||
private readonly tagsCountsState: TagsCountsState
|
||||
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
private featuresController: FeaturesController,
|
||||
private vaultDisplayService: VaultDisplayService,
|
||||
private keyboardService: KeyboardService,
|
||||
private paneController: PaneController,
|
||||
private sync: SyncServiceInterface,
|
||||
private mutator: MutatorClientInterface,
|
||||
private items: ItemManagerInterface,
|
||||
private preferences: PreferenceServiceInterface,
|
||||
private alerts: AlertService,
|
||||
private _changeAndSaveItem: ChangeAndSaveItem,
|
||||
eventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(application, eventBus)
|
||||
super(eventBus)
|
||||
|
||||
eventBus.addEventHandler(this, VaultDisplayServiceEvent.VaultDisplayOptionsChanged)
|
||||
|
||||
this.tagsCountsState = new TagsCountsState(this.application)
|
||||
this.smartViews = this.application.items.getSmartViews()
|
||||
this.tagsCountsState = new TagsCountsState(items)
|
||||
this.smartViews = items.getSmartViews()
|
||||
|
||||
makeObservable(this, {
|
||||
tags: observable,
|
||||
@@ -122,7 +138,7 @@ export class NavigationController
|
||||
})
|
||||
|
||||
this.disposers.push(
|
||||
this.application.streamItems([ContentType.TYPES.Tag, ContentType.TYPES.SmartView], ({ changed, removed }) => {
|
||||
this.items.streamItems([ContentType.TYPES.Tag, ContentType.TYPES.SmartView], ({ changed, removed }) => {
|
||||
this.reloadTags()
|
||||
|
||||
runInAction(() => {
|
||||
@@ -150,12 +166,12 @@ export class NavigationController
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
this.application.items.addNoteCountChangeObserver((tagUuid) => {
|
||||
this.items.addNoteCountChangeObserver((tagUuid) => {
|
||||
if (!tagUuid) {
|
||||
this.setAllNotesCount(this.application.items.allCountableNotesCount())
|
||||
this.setAllFilesCount(this.application.items.allCountableFilesCount())
|
||||
this.setAllNotesCount(this.items.allCountableNotesCount())
|
||||
this.setAllFilesCount(this.items.allCountableFilesCount())
|
||||
} else {
|
||||
const tag = this.application.items.findItem<SNTag>(tagUuid)
|
||||
const tag = this.items.findItem<SNTag>(tagUuid)
|
||||
if (tag) {
|
||||
this.tagsCountsState.update([tag])
|
||||
}
|
||||
@@ -176,7 +192,7 @@ export class NavigationController
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
this.application.keyboardService.addCommandHandler({
|
||||
this.keyboardService.addCommandHandler({
|
||||
command: CREATE_NEW_TAG_COMMAND,
|
||||
onKeyDown: () => {
|
||||
this.createNewTemplate()
|
||||
@@ -187,9 +203,9 @@ export class NavigationController
|
||||
|
||||
private reloadTags(): void {
|
||||
runInAction(() => {
|
||||
this.tags = this.application.items.getDisplayableTags()
|
||||
this.tags = this.items.getDisplayableTags()
|
||||
this.starredTags = this.tags.filter((tag) => tag.starred)
|
||||
this.smartViews = this.application.items.getSmartViews()
|
||||
this.smartViews = this.items.getSmartViews()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -258,14 +274,14 @@ export class NavigationController
|
||||
return
|
||||
}
|
||||
|
||||
const createdTag = await this.application.mutator.createTagOrSmartView<SNTag>(
|
||||
const createdTag = await this.mutator.createTagOrSmartView<SNTag>(
|
||||
title,
|
||||
this.application.vaultDisplayService.exclusivelyShownVault,
|
||||
this.vaultDisplayService.exclusivelyShownVault,
|
||||
)
|
||||
|
||||
const futureSiblings = this.application.items.getTagChildren(parent)
|
||||
const futureSiblings = this.items.getTagChildren(parent)
|
||||
|
||||
if (!isValidFutureSiblings(this.application, futureSiblings, createdTag)) {
|
||||
if (!isValidFutureSiblings(this.alerts, futureSiblings, createdTag)) {
|
||||
this.setAddingSubtagTo(undefined)
|
||||
this.remove(createdTag, false).catch(console.error)
|
||||
return
|
||||
@@ -273,7 +289,7 @@ export class NavigationController
|
||||
|
||||
this.assignParent(createdTag.uuid, parent.uuid).catch(console.error)
|
||||
|
||||
this.application.sync.sync().catch(console.error)
|
||||
this.sync.sync().catch(console.error)
|
||||
|
||||
runInAction(() => {
|
||||
void this.setSelectedTag(createdTag as SNTag, 'all')
|
||||
@@ -301,7 +317,7 @@ export class NavigationController
|
||||
tagUsesTableView(tag: AnyTag): boolean {
|
||||
const isSystemView = tag instanceof SmartView && Object.values(SystemViewId).includes(tag.uuid as SystemViewId)
|
||||
const useTableView = isSystemView
|
||||
? this.application.getPreference(PrefKey.SystemViewPreferences)?.[tag.uuid as SystemViewId]
|
||||
? this.preferences.getValue(PrefKey.SystemViewPreferences)?.[tag.uuid as SystemViewId]
|
||||
: tag?.preferences
|
||||
return Boolean(useTableView)
|
||||
}
|
||||
@@ -390,7 +406,7 @@ export class NavigationController
|
||||
}
|
||||
|
||||
public get allLocalRootTags(): SNTag[] {
|
||||
if (this.editing_ instanceof SNTag && this.application.items.isTemplateItem(this.editing_)) {
|
||||
if (this.editing_ instanceof SNTag && this.items.isTemplateItem(this.editing_)) {
|
||||
return [this.editing_, ...this.rootTags]
|
||||
}
|
||||
return this.rootTags
|
||||
@@ -401,11 +417,11 @@ export class NavigationController
|
||||
}
|
||||
|
||||
getChildren(tag: SNTag): SNTag[] {
|
||||
if (this.application.items.isTemplateItem(tag)) {
|
||||
if (this.items.isTemplateItem(tag)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const children = this.application.items.getTagChildren(tag)
|
||||
const children = this.items.getTagChildren(tag)
|
||||
|
||||
const childrenUuids = children.map((childTag) => childTag.uuid)
|
||||
const childrenTags = this.tags.filter((tag) => childrenUuids.includes(tag.uuid))
|
||||
@@ -413,45 +429,45 @@ export class NavigationController
|
||||
}
|
||||
|
||||
isValidTagParent(parent: SNTag, tag: SNTag): boolean {
|
||||
return this.application.items.isValidTagParent(parent, tag)
|
||||
return this.items.isValidTagParent(parent, tag)
|
||||
}
|
||||
|
||||
public hasParent(tagUuid: UuidString): boolean {
|
||||
const item = this.application.items.findItem(tagUuid)
|
||||
const item = this.items.findItem(tagUuid)
|
||||
return !!item && !!(item as SNTag).parentId
|
||||
}
|
||||
|
||||
public async assignParent(tagUuid: string, futureParentUuid: string | undefined): Promise<void> {
|
||||
const tag = this.application.items.findItem(tagUuid) as SNTag
|
||||
const tag = this.items.findItem(tagUuid) as SNTag
|
||||
|
||||
const currentParent = this.application.items.getTagParent(tag)
|
||||
const currentParent = this.items.getTagParent(tag)
|
||||
const currentParentUuid = currentParent?.uuid
|
||||
|
||||
if (currentParentUuid === futureParentUuid) {
|
||||
return
|
||||
}
|
||||
|
||||
const futureParent = futureParentUuid && (this.application.items.findItem(futureParentUuid) as SNTag)
|
||||
const futureParent = futureParentUuid && (this.items.findItem(futureParentUuid) as SNTag)
|
||||
|
||||
if (!futureParent) {
|
||||
const futureSiblings = rootTags(this.application)
|
||||
if (!isValidFutureSiblings(this.application, futureSiblings, tag)) {
|
||||
const futureSiblings = rootTags(this.items)
|
||||
if (!isValidFutureSiblings(this.alerts, futureSiblings, tag)) {
|
||||
return
|
||||
}
|
||||
await this.application.mutator.unsetTagParent(tag)
|
||||
await this.mutator.unsetTagParent(tag)
|
||||
} else {
|
||||
const futureSiblings = this.application.items.getTagChildren(futureParent)
|
||||
if (!isValidFutureSiblings(this.application, futureSiblings, tag)) {
|
||||
const futureSiblings = this.items.getTagChildren(futureParent)
|
||||
if (!isValidFutureSiblings(this.alerts, futureSiblings, tag)) {
|
||||
return
|
||||
}
|
||||
await this.application.mutator.setTagParent(futureParent, tag)
|
||||
await this.mutator.setTagParent(futureParent, tag)
|
||||
}
|
||||
|
||||
await this.application.sync.sync()
|
||||
await this.sync.sync()
|
||||
}
|
||||
|
||||
get rootTags(): SNTag[] {
|
||||
return this.tags.filter((tag) => !this.application.items.getTagParent(tag))
|
||||
return this.tags.filter((tag) => !this.items.getTagParent(tag))
|
||||
}
|
||||
|
||||
get tagsCount(): number {
|
||||
@@ -483,7 +499,7 @@ export class NavigationController
|
||||
}
|
||||
|
||||
public async setPanelWidthForTag(tag: SNTag, width: number): Promise<void> {
|
||||
await this.application.changeAndSaveItem<TagMutator>(tag, (mutator) => {
|
||||
await this._changeAndSaveItem.execute<TagMutator>(tag, (mutator) => {
|
||||
mutator.preferences = {
|
||||
...mutator.preferences,
|
||||
panelWidth: width,
|
||||
@@ -497,17 +513,17 @@ export class NavigationController
|
||||
{ userTriggered } = { userTriggered: false },
|
||||
) {
|
||||
if (tag && tag.conflictOf) {
|
||||
this.application
|
||||
.changeAndSaveItem(tag, (mutator) => {
|
||||
this._changeAndSaveItem
|
||||
.execute(tag, (mutator) => {
|
||||
mutator.conflictOf = undefined
|
||||
})
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
if (tag && (this.isTagFilesView(tag) || this.tagUsesTableView(tag))) {
|
||||
this.application.paneController.setPaneLayout(PaneLayout.TableView)
|
||||
this.paneController.setPaneLayout(PaneLayout.TableView)
|
||||
} else if (userTriggered) {
|
||||
this.application.paneController.setPaneLayout(PaneLayout.ItemSelection)
|
||||
this.paneController.setPaneLayout(PaneLayout.ItemSelection)
|
||||
}
|
||||
|
||||
this.previouslySelected_ = this.selected_
|
||||
@@ -516,7 +532,7 @@ export class NavigationController
|
||||
this.setSelectedTagInstance(tag)
|
||||
this.selectedLocation = location
|
||||
|
||||
if (tag && this.application.items.isTemplateItem(tag)) {
|
||||
if (tag && this.items.isTemplateItem(tag)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -558,24 +574,24 @@ export class NavigationController
|
||||
return
|
||||
}
|
||||
|
||||
this.application
|
||||
.changeAndSaveItem<TagMutator>(tag, (mutator) => {
|
||||
this._changeAndSaveItem
|
||||
.execute<TagMutator>(tag, (mutator) => {
|
||||
mutator.expanded = expanded
|
||||
})
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
public async setFavorite(tag: SNTag, favorite: boolean) {
|
||||
return this.application
|
||||
.changeAndSaveItem<TagMutator>(tag, (mutator) => {
|
||||
return this._changeAndSaveItem
|
||||
.execute<TagMutator>(tag, (mutator) => {
|
||||
mutator.starred = favorite
|
||||
})
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
public setIcon(tag: SNTag, icon: VectorIconNameOrEmoji) {
|
||||
this.application
|
||||
.changeAndSaveItem<TagMutator>(tag, (mutator) => {
|
||||
this._changeAndSaveItem
|
||||
.execute<TagMutator>(tag, (mutator) => {
|
||||
mutator.iconString = icon as string
|
||||
})
|
||||
.catch(console.error)
|
||||
@@ -593,13 +609,13 @@ export class NavigationController
|
||||
}
|
||||
|
||||
public createNewTemplate() {
|
||||
const isAlreadyEditingATemplate = this.editing_ && this.application.items.isTemplateItem(this.editing_)
|
||||
const isAlreadyEditingATemplate = this.editing_ && this.items.isTemplateItem(this.editing_)
|
||||
|
||||
if (isAlreadyEditingATemplate) {
|
||||
return
|
||||
}
|
||||
|
||||
const newTag = this.application.items.createTemplateItem(ContentType.TYPES.Tag) as SNTag
|
||||
const newTag = this.items.createTemplateItem(ContentType.TYPES.Tag) as SNTag
|
||||
|
||||
runInAction(() => {
|
||||
this.selectedLocation = 'all'
|
||||
@@ -622,9 +638,9 @@ export class NavigationController
|
||||
})
|
||||
}
|
||||
if (shouldDelete) {
|
||||
this.application.mutator
|
||||
this.mutator
|
||||
.deleteItem(tag)
|
||||
.then(() => this.application.sync.sync())
|
||||
.then(() => this.sync.sync())
|
||||
.catch(console.error)
|
||||
await this.setSelectedTag(this.smartViews[0], 'views')
|
||||
}
|
||||
@@ -633,9 +649,9 @@ export class NavigationController
|
||||
public async save(tag: SNTag | SmartView, newTitle: string) {
|
||||
const hasEmptyTitle = newTitle.length === 0
|
||||
const hasNotChangedTitle = newTitle === tag.title
|
||||
const isTemplateChange = this.application.items.isTemplateItem(tag)
|
||||
const isTemplateChange = this.items.isTemplateItem(tag)
|
||||
|
||||
const siblings = tag instanceof SNTag ? tagSiblings(this.application, tag) : []
|
||||
const siblings = tag instanceof SNTag ? tagSiblings(this.items, tag) : []
|
||||
const hasDuplicatedTitle = siblings.some((other) => other.title.toLowerCase() === newTitle.toLowerCase())
|
||||
|
||||
runInAction(() => {
|
||||
@@ -653,12 +669,12 @@ export class NavigationController
|
||||
if (isTemplateChange) {
|
||||
this.undoCreateNewTag()
|
||||
}
|
||||
this.application.alerts?.alert('A tag with this name already exists.').catch(console.error)
|
||||
this.alerts.alert('A tag with this name already exists.').catch(console.error)
|
||||
return
|
||||
}
|
||||
|
||||
if (isTemplateChange) {
|
||||
const isSmartViewTitle = this.application.items.isSmartViewTitle(newTitle)
|
||||
const isSmartViewTitle = this.items.isSmartViewTitle(newTitle)
|
||||
|
||||
if (isSmartViewTitle) {
|
||||
if (!this.featuresController.hasSmartViews) {
|
||||
@@ -667,16 +683,16 @@ export class NavigationController
|
||||
}
|
||||
}
|
||||
|
||||
const insertedTag = await this.application.mutator.createTagOrSmartView<SNTag>(
|
||||
const insertedTag = await this.mutator.createTagOrSmartView<SNTag>(
|
||||
newTitle,
|
||||
this.application.vaultDisplayService.exclusivelyShownVault,
|
||||
this.vaultDisplayService.exclusivelyShownVault,
|
||||
)
|
||||
this.application.sync.sync().catch(console.error)
|
||||
this.sync.sync().catch(console.error)
|
||||
runInAction(() => {
|
||||
void this.setSelectedTag(insertedTag, this.selectedLocation || 'views')
|
||||
})
|
||||
} else {
|
||||
await this.application.changeAndSaveItem<TagMutator>(tag, (mutator) => {
|
||||
await this._changeAndSaveItem.execute<TagMutator>(tag, (mutator) => {
|
||||
mutator.title = newTitle
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { SNTag } from '@standardnotes/snjs'
|
||||
import { ItemManagerInterface, SNTag } from '@standardnotes/snjs'
|
||||
import { action, makeAutoObservable, observable } from 'mobx'
|
||||
import { WebApplication } from '../../Application/WebApplication'
|
||||
|
||||
export class TagsCountsState {
|
||||
public counts: { [uuid: string]: number } = {}
|
||||
|
||||
public constructor(private application: WebApplication) {
|
||||
public constructor(private items: ItemManagerInterface) {
|
||||
makeAutoObservable(this, {
|
||||
counts: observable.ref,
|
||||
update: action,
|
||||
@@ -16,7 +15,7 @@ export class TagsCountsState {
|
||||
const newCounts: { [uuid: string]: number } = Object.assign({}, this.counts)
|
||||
|
||||
tags.forEach((tag) => {
|
||||
newCounts[tag.uuid] = this.application.items.countableNotesForTag(tag)
|
||||
newCounts[tag.uuid] = this.items.countableNotesForTag(tag)
|
||||
})
|
||||
|
||||
this.counts = newCounts
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
import { SNApplication, SNTag } from '@standardnotes/snjs'
|
||||
import { AlertService, ItemManagerInterface, SNTag } from '@standardnotes/snjs'
|
||||
|
||||
export const rootTags = (application: SNApplication): SNTag[] => {
|
||||
const hasNoParent = (tag: SNTag) => !application.items.getTagParent(tag)
|
||||
export const rootTags = (items: ItemManagerInterface): SNTag[] => {
|
||||
const hasNoParent = (tag: SNTag) => !items.getTagParent(tag)
|
||||
|
||||
const allTags = application.items.getDisplayableTags()
|
||||
const allTags = items.getDisplayableTags()
|
||||
const rootTags = allTags.filter(hasNoParent)
|
||||
|
||||
return rootTags
|
||||
}
|
||||
|
||||
export const tagSiblings = (application: SNApplication, tag: SNTag): SNTag[] => {
|
||||
export const tagSiblings = (items: ItemManagerInterface, tag: SNTag): SNTag[] => {
|
||||
const withoutCurrentTag = (tags: SNTag[]) => tags.filter((other) => other.uuid !== tag.uuid)
|
||||
|
||||
const isTemplateTag = application.items.isTemplateItem(tag)
|
||||
const parentTag = !isTemplateTag && application.items.getTagParent(tag)
|
||||
const isTemplateTag = items.isTemplateItem(tag)
|
||||
const parentTag = !isTemplateTag && items.getTagParent(tag)
|
||||
|
||||
if (parentTag) {
|
||||
const siblingsAndTag = application.items.getTagChildren(parentTag)
|
||||
const siblingsAndTag = items.getTagChildren(parentTag)
|
||||
return withoutCurrentTag(siblingsAndTag)
|
||||
}
|
||||
|
||||
return withoutCurrentTag(rootTags(application))
|
||||
return withoutCurrentTag(rootTags(items))
|
||||
}
|
||||
|
||||
export const isValidFutureSiblings = (application: SNApplication, futureSiblings: SNTag[], tag: SNTag): boolean => {
|
||||
export const isValidFutureSiblings = (alerts: AlertService, futureSiblings: SNTag[], tag: SNTag): boolean => {
|
||||
const siblingWithSameName = futureSiblings.find((otherTag) => otherTag.title === tag.title)
|
||||
|
||||
if (siblingWithSameName) {
|
||||
application.alerts
|
||||
alerts
|
||||
?.alert(
|
||||
`A tag with the name ${tag.title} already exists at this destination. Please rename this tag before moving and try again.`,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user