feat: display number of files for 'Files' view (#2065)
* feat: display number of files for 'Files' view * feat: include files count in Preferences > Security
This commit is contained in:
@@ -583,7 +583,7 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: 48289402952f4f7a4e235de70a9a590aa0b79ef4
|
||||
FBReactNativeSpec: dd1186fd05255e3457baa2f4ca65e94c2cd1e3ac
|
||||
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
|
||||
@@ -596,7 +596,7 @@ SPEC CHECKSUMS:
|
||||
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
|
||||
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: 85ecdd10ee8d8ec362ef519a6a45ff9aa27b2e85
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
hermes-engine: 2af7b7a59128f250adfd86f15aa1d5a2ecd39995
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { isNote } from './../../../Syncable/Note/Note'
|
||||
import { removeFromArray } from '@standardnotes/utils'
|
||||
import { ContentType, Uuid } from '@standardnotes/common'
|
||||
import { isTag, SNTag } from '../../../Syncable/Tag/Tag'
|
||||
@@ -13,7 +12,7 @@ export type TagItemCountChangeObserver = (tagUuid: Uuid | AllNotesUuidSignifier)
|
||||
export class TagItemsIndex implements SNIndex {
|
||||
private tagToItemsMap: Partial<Record<Uuid, Set<Uuid>>> = {}
|
||||
private allCountableItems = new Set<Uuid>()
|
||||
private allCountableNotes = new Set<Uuid>()
|
||||
private countableItemsByType = new Map<ContentType, Set<Uuid>>()
|
||||
|
||||
constructor(private collection: ItemCollection, public observers: TagItemCountChangeObserver[] = []) {}
|
||||
|
||||
@@ -44,7 +43,11 @@ export class TagItemsIndex implements SNIndex {
|
||||
}
|
||||
|
||||
public allCountableNotesCount(): number {
|
||||
return this.allCountableNotes.size
|
||||
return this.countableItemsByType.get(ContentType.Note)?.size || 0
|
||||
}
|
||||
|
||||
public allCountableFilesCount(): number {
|
||||
return this.countableItemsByType.get(ContentType.File)?.size || 0
|
||||
}
|
||||
|
||||
public countableItemsForTag(tag: SNTag): number {
|
||||
@@ -85,15 +88,14 @@ export class TagItemsIndex implements SNIndex {
|
||||
if (isCountable) {
|
||||
this.allCountableItems.add(item.uuid)
|
||||
|
||||
if (isNote(item)) {
|
||||
this.allCountableNotes.add(item.uuid)
|
||||
if (!this.countableItemsByType.has(item.content_type)) {
|
||||
this.countableItemsByType.set(item.content_type, new Set())
|
||||
}
|
||||
|
||||
this.countableItemsByType.get(item.content_type)?.add(item.uuid)
|
||||
} else {
|
||||
this.allCountableItems.delete(item.uuid)
|
||||
|
||||
if (isNote(item)) {
|
||||
this.allCountableNotes.delete(item.uuid)
|
||||
}
|
||||
this.countableItemsByType.get(item.content_type)?.delete(item.uuid)
|
||||
}
|
||||
|
||||
const associatedTagUuids = this.collection.uuidsThatReferenceUuid(item.uuid)
|
||||
|
||||
@@ -12,10 +12,7 @@ import { PayloadTimestampDefaults } from '../../Abstract/Payload'
|
||||
import { FilterDisplayOptions } from '../../Runtime/Display'
|
||||
import { FileItem } from '../File'
|
||||
|
||||
export function BuildSmartViews(
|
||||
options: FilterDisplayOptions,
|
||||
{ supportsFileNavigation = false }: { supportsFileNavigation: boolean },
|
||||
): SmartView[] {
|
||||
export function BuildSmartViews(options: FilterDisplayOptions): SmartView[] {
|
||||
const notes = new SmartView(
|
||||
new DecryptedPayload({
|
||||
uuid: SystemViewId.AllNotes,
|
||||
@@ -88,11 +85,7 @@ export function BuildSmartViews(
|
||||
}),
|
||||
)
|
||||
|
||||
if (supportsFileNavigation) {
|
||||
return [notes, starred, files, archived, trash, untagged]
|
||||
} else {
|
||||
return [notes, starred, archived, trash, untagged]
|
||||
}
|
||||
return [notes, files, starred, archived, trash, untagged]
|
||||
}
|
||||
|
||||
function allNotesPredicate(options: FilterDisplayOptions) {
|
||||
|
||||
@@ -60,6 +60,7 @@ export interface ItemsClientInterface {
|
||||
addNoteCountChangeObserver(observer: TagItemCountChangeObserver): () => void
|
||||
|
||||
allCountableNotesCount(): number
|
||||
allCountableFilesCount(): number
|
||||
|
||||
countableNotesForTag(tag: SNTag | SmartView): number
|
||||
|
||||
|
||||
@@ -1383,7 +1383,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
}
|
||||
|
||||
private createItemManager() {
|
||||
this.itemManager = new InternalServices.ItemManager(this.payloadManager, this.options, this.internalEventBus)
|
||||
this.itemManager = new InternalServices.ItemManager(this.payloadManager, this.internalEventBus)
|
||||
this.services.push(this.itemManager)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { ApplicationDisplayOptions, ApplicationSyncOptions } from './OptionalOptions'
|
||||
import { ApplicationSyncOptions } from './OptionalOptions'
|
||||
|
||||
export interface ApplicationOptionsWhichHaveDefaults {
|
||||
loadBatchSize: ApplicationSyncOptions['loadBatchSize']
|
||||
supportsFileNavigation: ApplicationDisplayOptions['supportsFileNavigation']
|
||||
}
|
||||
|
||||
export const ApplicationOptionsDefaults: ApplicationOptionsWhichHaveDefaults = {
|
||||
loadBatchSize: 700,
|
||||
supportsFileNavigation: false,
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@ export interface ApplicationSyncOptions {
|
||||
loadBatchSize: number
|
||||
}
|
||||
|
||||
export interface ApplicationDisplayOptions {
|
||||
supportsFileNavigation: boolean
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface ApplicationDisplayOptions {}
|
||||
|
||||
export interface ApplicationOptionalConfiguratioOptions {
|
||||
/**
|
||||
|
||||
@@ -83,6 +83,7 @@ export class SNActionsService extends AbstractService {
|
||||
;(this.challengeService as unknown) = undefined
|
||||
;(this.protocolService as unknown) = undefined
|
||||
;(this.syncService as unknown) = undefined
|
||||
this.payloadRequestHandlers.length = 0
|
||||
this.previousPasswords.length = 0
|
||||
super.deinit()
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('itemManager', () => {
|
||||
let internalEventBus: InternalEventBusInterface
|
||||
|
||||
const createService = () => {
|
||||
return new ItemManager(payloadManager, { supportsFileNavigation: false }, internalEventBus)
|
||||
return new ItemManager(payloadManager, internalEventBus)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -8,7 +8,6 @@ import * as Models from '@standardnotes/models'
|
||||
import * as Services from '@standardnotes/services'
|
||||
import { PayloadManagerChangeData } from '../Payloads'
|
||||
import { DiagnosticInfo, ItemsClientInterface, ItemRelationshipDirection } from '@standardnotes/services'
|
||||
import { ApplicationDisplayOptions } from '@Lib/Application/Options/OptionalOptions'
|
||||
import { CollectionSort, DecryptedItemInterface, ItemContent, SmartViewDefaultIconName } from '@standardnotes/models'
|
||||
|
||||
type ItemsChangeObserver<I extends Models.DecryptedItemInterface = Models.DecryptedItemInterface> = {
|
||||
@@ -44,7 +43,6 @@ export class ItemManager
|
||||
|
||||
constructor(
|
||||
private payloadManager: PayloadManager,
|
||||
private readonly options: ApplicationDisplayOptions = { supportsFileNavigation: false },
|
||||
protected override internalEventBus: Services.InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
@@ -55,7 +53,7 @@ export class ItemManager
|
||||
}
|
||||
|
||||
private rebuildSystemSmartViews(criteria: Models.FilterDisplayOptions): Models.SmartView[] {
|
||||
this.systemSmartViews = Models.BuildSmartViews(criteria, this.options)
|
||||
this.systemSmartViews = Models.BuildSmartViews(criteria)
|
||||
return this.systemSmartViews
|
||||
}
|
||||
|
||||
@@ -68,7 +66,7 @@ export class ItemManager
|
||||
{
|
||||
sortBy: 'created_at',
|
||||
sortDirection: 'dsc',
|
||||
hiddenContentTypes: !this.options.supportsFileNavigation ? [ContentType.File] : [],
|
||||
hiddenContentTypes: [],
|
||||
},
|
||||
)
|
||||
this.tagDisplayController = new Models.ItemDisplayController(this.collection, [ContentType.Tag], {
|
||||
@@ -184,12 +182,7 @@ export class ItemManager
|
||||
public getDisplayableNotes(): Models.SNNote[] {
|
||||
assert(this.navigationDisplayController.contentTypes.length === 2)
|
||||
|
||||
const fileContentTypeHidden = !this.options.supportsFileNavigation
|
||||
if (fileContentTypeHidden) {
|
||||
return this.navigationDisplayController.items() as Models.SNNote[]
|
||||
} else {
|
||||
return this.navigationDisplayController.items().filter(Models.isNote)
|
||||
}
|
||||
return this.navigationDisplayController.items().filter(Models.isNote)
|
||||
}
|
||||
|
||||
public getDisplayableFiles(): Models.FileItem[] {
|
||||
@@ -197,7 +190,6 @@ export class ItemManager
|
||||
}
|
||||
|
||||
public getDisplayableNotesAndFiles(): (Models.SNNote | Models.FileItem)[] {
|
||||
assert(this.options.supportsFileNavigation)
|
||||
return this.navigationDisplayController.items()
|
||||
}
|
||||
|
||||
@@ -215,7 +207,6 @@ export class ItemManager
|
||||
|
||||
public override deinit(): void {
|
||||
this.unsubChangeObserver()
|
||||
;(this.options as unknown) = undefined
|
||||
;(this.unsubChangeObserver as unknown) = undefined
|
||||
;(this.payloadManager as unknown) = undefined
|
||||
;(this.collection as unknown) = undefined
|
||||
@@ -292,6 +283,10 @@ export class ItemManager
|
||||
return this.tagItemsIndex.allCountableNotesCount()
|
||||
}
|
||||
|
||||
public allCountableFilesCount(): number {
|
||||
return this.tagItemsIndex.allCountableFilesCount()
|
||||
}
|
||||
|
||||
public countableNotesForTag(tag: Models.SNTag | Models.SmartView): number {
|
||||
if (tag instanceof Models.SmartView) {
|
||||
if (tag.uuid === Models.SystemViewId.AllNotes) {
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('mutator service', () => {
|
||||
internalEventBus.publish = jest.fn()
|
||||
|
||||
payloadManager = new PayloadManager(internalEventBus)
|
||||
itemManager = new ItemManager(payloadManager, { supportsFileNavigation: false }, internalEventBus)
|
||||
itemManager = new ItemManager(payloadManager, internalEventBus)
|
||||
|
||||
mutatorService = new MutatorService(
|
||||
itemManager,
|
||||
|
||||
@@ -7,7 +7,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Only autofocus super notes when creating new note ([#2063](https://github.com/standardnotes/app/issues/2063)) ([96e8dfd](https://github.com/standardnotes/app/commit/96e8dfdd310fad88a360c4ac984b376b51a618d1))
|
||||
* Only autofocus Super notes when creating new note ([#2063](https://github.com/standardnotes/app/issues/2063)) ([96e8dfd](https://github.com/standardnotes/app/commit/96e8dfdd310fad88a360c4ac984b376b51a618d1))
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
@@ -74,7 +74,6 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
defaultHost: defaultSyncServerHost,
|
||||
appVersion: deviceInterface.appVersion,
|
||||
webSocketUrl: webSocketUrl,
|
||||
supportsFileNavigation: true,
|
||||
})
|
||||
|
||||
makeObservable(this, {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { WebApplication } from '@/Application/Application'
|
||||
import { FeaturesController } from '@/Controllers/FeaturesController'
|
||||
import { SubscriptionController } from '@/Controllers/Subscription/SubscriptionController'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
@@ -13,13 +14,13 @@ const UpgradeNow = ({ application, featuresController, subscriptionContoller }:
|
||||
const shouldShowCTA = !featuresController.hasFolders
|
||||
const hasAccount = subscriptionContoller.hasAccount
|
||||
|
||||
const onClick = () => {
|
||||
if (application.isNativeIOS()) {
|
||||
const onClick = useCallback(() => {
|
||||
if (hasAccount && application.isNativeIOS()) {
|
||||
application.showPremiumModal()
|
||||
} else {
|
||||
application.openPurchaseFlow()
|
||||
}
|
||||
}
|
||||
}, [application, hasAccount])
|
||||
|
||||
return shouldShowCTA ? (
|
||||
<div className="flex h-full items-center px-2">
|
||||
|
||||
@@ -27,7 +27,7 @@ const Encryption: FunctionComponent<Props> = ({ viewControllerManager }) => {
|
||||
<Title>Encryption</Title>
|
||||
<Text>{encryptionStatusString}</Text>
|
||||
|
||||
{isEncryptionEnabled && <EncryptionEnabled viewControllerManager={viewControllerManager} />}
|
||||
{isEncryptionEnabled && <EncryptionEnabled />}
|
||||
</PreferencesSegment>
|
||||
</PreferencesGroup>
|
||||
)
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
import { useApplication } from '@/Components/ApplicationView/ApplicationProvider'
|
||||
import Icon from '@/Components/Icon/Icon'
|
||||
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
|
||||
import { ContentType, ItemCounter } from '@standardnotes/snjs'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { FunctionComponent } from 'react'
|
||||
import EncryptionStatusItem from './EncryptionStatusItem'
|
||||
import { formatCount } from './formatCount'
|
||||
|
||||
type Props = {
|
||||
viewControllerManager: ViewControllerManager
|
||||
}
|
||||
|
||||
const EncryptionEnabled: FunctionComponent<Props> = ({ viewControllerManager }) => {
|
||||
const count = viewControllerManager.accountMenuController.structuredNotesAndTagsCount
|
||||
const EncryptionEnabled: FunctionComponent = () => {
|
||||
const application = useApplication()
|
||||
const itemCounter = new ItemCounter()
|
||||
const count = itemCounter.countNotesAndTags(application.items.getItems([ContentType.Note, ContentType.Tag]))
|
||||
const files = application.items.getItems([ContentType.File])
|
||||
const notes = formatCount(count.notes, 'notes')
|
||||
const tags = formatCount(count.tags, 'tags')
|
||||
const archived = formatCount(count.archived, 'archived notes')
|
||||
const deleted = formatCount(count.deleted, 'trashed notes')
|
||||
const filesCount = formatCount(files.length, 'files')
|
||||
|
||||
const noteIcon = <Icon type="rich-text" className="min-h-5 min-w-5" />
|
||||
const tagIcon = <Icon type="hashtag" className="min-h-5 min-w-5" />
|
||||
const archiveIcon = <Icon type="archive" className="min-h-5 min-w-5" />
|
||||
const trashIcon = <Icon type="trash" className="min-h-5 min-w-5" />
|
||||
const filesIcon = <Icon type="folder" className="min-h-5 min-w-5" />
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row flex-wrap items-start pt-1.5 md:pb-1">
|
||||
<EncryptionStatusItem status={notes} icon={noteIcon} />
|
||||
<div className="min-w-3" />
|
||||
<EncryptionStatusItem status={filesCount} icon={filesIcon} />
|
||||
<div className="min-w-3" />
|
||||
<EncryptionStatusItem status={tags} icon={tagIcon} />
|
||||
</div>
|
||||
<div className="flex flex-row flex-wrap items-start">
|
||||
<div className="min-w-3" />
|
||||
<EncryptionStatusItem status={archived} icon={archiveIcon} />
|
||||
<div className="min-w-3" />
|
||||
<EncryptionStatusItem status={deleted} icon={trashIcon} />
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const formatCount = (count: number, itemType: string) => `${count} / ${count} ${itemType}`
|
||||
export const formatCount = (count: number, itemType: string) => `${count} ${itemType}`
|
||||
|
||||
@@ -10,7 +10,6 @@ type Props = {
|
||||
application: WebApplication
|
||||
featureName?: FeatureName | string
|
||||
hasSubscription: boolean
|
||||
hasAccount: boolean
|
||||
onClose: () => void
|
||||
showModal: boolean
|
||||
type: PremiumFeatureModalType
|
||||
@@ -20,7 +19,6 @@ const PremiumFeaturesModal: FunctionComponent<Props> = ({
|
||||
application,
|
||||
featureName,
|
||||
hasSubscription,
|
||||
hasAccount,
|
||||
onClose,
|
||||
showModal,
|
||||
type = PremiumFeatureModalType.UpgradePrompt,
|
||||
@@ -40,7 +38,6 @@ const PremiumFeaturesModal: FunctionComponent<Props> = ({
|
||||
featureName={featureName}
|
||||
ctaRef={ctaButtonRef}
|
||||
application={application}
|
||||
hasAccount={hasAccount}
|
||||
hasSubscription={hasSubscription}
|
||||
onClose={onClose}
|
||||
/>
|
||||
|
||||
@@ -10,26 +10,22 @@ export const UpgradePrompt = ({
|
||||
ctaRef,
|
||||
application,
|
||||
hasSubscription,
|
||||
hasAccount,
|
||||
onClose,
|
||||
}: {
|
||||
featureName?: string
|
||||
ctaRef: React.RefObject<HTMLButtonElement>
|
||||
application: WebApplication
|
||||
hasSubscription: boolean
|
||||
hasAccount: boolean
|
||||
onClose: () => void
|
||||
}) => {
|
||||
const handleClick = useCallback(() => {
|
||||
if (hasSubscription) {
|
||||
void openSubscriptionDashboard(application)
|
||||
} else if (hasAccount) {
|
||||
} else {
|
||||
void application.openPurchaseFlow()
|
||||
} else if (window.plansUrl) {
|
||||
window.location.assign(window.plansUrl)
|
||||
}
|
||||
onClose()
|
||||
}, [application, hasSubscription, hasAccount, onClose])
|
||||
}, [application, hasSubscription, onClose])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -140,6 +140,7 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState, setEdit
|
||||
)}
|
||||
<div className={'count text-base lg:text-sm'}>
|
||||
{view.uuid === SystemViewId.AllNotes && tagsState.allNotesCount}
|
||||
{view.uuid === SystemViewId.Files && tagsState.allFilesCount}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export const STRING_DEFAULT_FILE_ERROR =
|
||||
'Please use FileSafe or the Bold Editor to attach images and files. Learn more at standardnotes.com/filesafe.'
|
||||
export const STRING_GENERIC_SYNC_ERROR =
|
||||
'There was an error syncing. Please try again. If all else fails, try signing out and signing back in.'
|
||||
export function StringSyncException(data: any) {
|
||||
export function StringSyncException(data: unknown) {
|
||||
return `There was an error while trying to save your items. Please contact support and share this message: ${JSON.stringify(
|
||||
data,
|
||||
)}.`
|
||||
@@ -108,7 +108,6 @@ export const STRING_FAILED_TO_UPDATE_USER_SETTING =
|
||||
export const Strings = {
|
||||
protectingNoteWithoutProtectionSources:
|
||||
'Access to this note will not be restricted until you set up a passcode or account.',
|
||||
openAccountMenu: 'Open Account Menu',
|
||||
trashItemsTitle: 'Move to Trash',
|
||||
trashNotesText: 'Are you sure you want to move these notes to the trash?',
|
||||
trashFilesText: 'Are you sure you want to move these files to the trash?',
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import { destroyAllObjectProperties, isDev } from '@/Utils'
|
||||
import { action, computed, makeObservable, observable, runInAction } from 'mobx'
|
||||
import {
|
||||
ApplicationEvent,
|
||||
ContentType,
|
||||
InternalEventBus,
|
||||
SNNote,
|
||||
SNTag,
|
||||
ItemCounterInterface,
|
||||
ItemCounts,
|
||||
} 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'
|
||||
@@ -36,7 +28,7 @@ export class AccountMenuController extends AbstractViewController {
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus, private itemCounter: ItemCounterInterface) {
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
@@ -165,8 +157,4 @@ export class AccountMenuController extends AbstractViewController {
|
||||
get notesAndTagsCount(): number {
|
||||
return this.notesAndTags.length
|
||||
}
|
||||
|
||||
get structuredNotesAndTagsCount(): ItemCounts {
|
||||
return this.itemCounter.countNotesAndTags(this.notesAndTags)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export class NavigationController
|
||||
smartViews: SmartView[] = []
|
||||
starredTags: SNTag[] = []
|
||||
allNotesCount_ = 0
|
||||
allFilesCount_ = 0
|
||||
selectedUuid: AnyTag['uuid'] | undefined = undefined
|
||||
selected_: AnyTag | undefined = undefined
|
||||
selectedLocation: TagListSectionType | undefined = undefined
|
||||
@@ -62,8 +63,11 @@ export class NavigationController
|
||||
starredTags: observable,
|
||||
smartViews: observable.ref,
|
||||
allNotesCount_: observable,
|
||||
allFilesCount_: observable,
|
||||
allNotesCount: computed,
|
||||
allFilesCount: computed,
|
||||
setAllNotesCount: action,
|
||||
setAllFilesCount: action,
|
||||
|
||||
selected_: observable,
|
||||
selectedLocation: observable,
|
||||
@@ -135,6 +139,7 @@ export class NavigationController
|
||||
this.application.items.addNoteCountChangeObserver((tagUuid) => {
|
||||
if (!tagUuid) {
|
||||
this.setAllNotesCount(this.application.items.allCountableNotesCount())
|
||||
this.setAllFilesCount(this.application.items.allCountableFilesCount())
|
||||
} else {
|
||||
const tag = this.application.items.findItem<SNTag>(tagUuid)
|
||||
if (tag) {
|
||||
@@ -411,6 +416,14 @@ export class NavigationController
|
||||
this.allNotesCount_ = allNotesCount
|
||||
}
|
||||
|
||||
setAllFilesCount(allFilesCount: number) {
|
||||
this.allFilesCount_ = allFilesCount
|
||||
}
|
||||
|
||||
public get allFilesCount(): number {
|
||||
return this.allFilesCount_
|
||||
}
|
||||
|
||||
public get allNotesCount(): number {
|
||||
return this.allNotesCount_
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@ import {
|
||||
DeinitSource,
|
||||
WebOrDesktopDeviceInterface,
|
||||
InternalEventBus,
|
||||
ItemCounterInterface,
|
||||
ItemCounter,
|
||||
SubscriptionClientInterface,
|
||||
InternalEventHandlerInterface,
|
||||
InternalEventInterface,
|
||||
@@ -74,7 +72,6 @@ export class ViewControllerManager implements InternalEventHandlerInterface {
|
||||
|
||||
private appEventObserverRemovers: (() => void)[] = []
|
||||
private eventBus: InternalEventBus
|
||||
private itemCounter: ItemCounterInterface
|
||||
private subscriptionManager: SubscriptionClientInterface
|
||||
private persistenceService: PersistenceService
|
||||
private applicationEventObserver: EventObserverInterface
|
||||
@@ -88,8 +85,6 @@ export class ViewControllerManager implements InternalEventHandlerInterface {
|
||||
this.eventBus.addEventHandler(this, CrossControllerEvent.HydrateFromPersistedValues)
|
||||
this.eventBus.addEventHandler(this, CrossControllerEvent.RequestValuePersistence)
|
||||
|
||||
this.itemCounter = new ItemCounter()
|
||||
|
||||
this.subscriptionManager = application.subscriptions
|
||||
|
||||
this.quickSettingsMenuController = new QuickSettingsController(application, this.eventBus)
|
||||
@@ -135,7 +130,7 @@ export class ViewControllerManager implements InternalEventHandlerInterface {
|
||||
|
||||
this.noAccountWarningController = new NoAccountWarningController(application, this.eventBus)
|
||||
|
||||
this.accountMenuController = new AccountMenuController(application, this.eventBus, this.itemCounter)
|
||||
this.accountMenuController = new AccountMenuController(application, this.eventBus)
|
||||
|
||||
this.subscriptionController = new SubscriptionController(application, this.eventBus, this.subscriptionManager)
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ const PremiumModalProvider: FunctionComponent<Props> = observer(
|
||||
|
||||
const hasSubscription = application.hasValidSubscription()
|
||||
|
||||
const hasAccount = application.hasAccount()
|
||||
|
||||
const activate = useCallback(
|
||||
(feature: string) => {
|
||||
featuresController.showPremiumAlert(feature).catch(console.error)
|
||||
@@ -54,7 +52,6 @@ const PremiumModalProvider: FunctionComponent<Props> = observer(
|
||||
application={application}
|
||||
featureName={featureName}
|
||||
hasSubscription={hasSubscription}
|
||||
hasAccount={hasAccount}
|
||||
onClose={close}
|
||||
showModal={featuresController.premiumAlertType != undefined}
|
||||
type={featuresController.premiumAlertType}
|
||||
|
||||
Reference in New Issue
Block a user