refactor(web): dependency management (#2386)
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
export const Web_TYPES = {
|
||||
Application: Symbol.for('Application'),
|
||||
|
||||
// Services
|
||||
AndroidBackHandler: Symbol.for('AndroidBackHandler'),
|
||||
ArchiveManager: Symbol.for('ArchiveManager'),
|
||||
AutolockService: Symbol.for('AutolockService'),
|
||||
ChangelogService: Symbol.for('ChangelogService'),
|
||||
DesktopManager: Symbol.for('DesktopManager'),
|
||||
Importer: Symbol.for('Importer'),
|
||||
ItemGroupController: Symbol.for('ItemGroupController'),
|
||||
KeyboardService: Symbol.for('KeyboardService'),
|
||||
MobileWebReceiver: Symbol.for('MobileWebReceiver'),
|
||||
MomentsService: Symbol.for('MomentsService'),
|
||||
PersistenceService: Symbol.for('PersistenceService'),
|
||||
RouteService: Symbol.for('RouteService'),
|
||||
ThemeManager: Symbol.for('ThemeManager'),
|
||||
VaultDisplayService: Symbol.for('VaultDisplayService'),
|
||||
|
||||
// Controllers
|
||||
AccountMenuController: Symbol.for('AccountMenuController'),
|
||||
ActionsMenuController: Symbol.for('ActionsMenuController'),
|
||||
ApplicationEventObserver: Symbol.for('ApplicationEventObserver'),
|
||||
FeaturesController: Symbol.for('FeaturesController'),
|
||||
FilePreviewModalController: Symbol.for('FilePreviewModalController'),
|
||||
FilesController: Symbol.for('FilesController'),
|
||||
HistoryModalController: Symbol.for('HistoryModalController'),
|
||||
ImportModalController: Symbol.for('ImportModalController'),
|
||||
ItemListController: Symbol.for('ItemListController'),
|
||||
LinkingController: Symbol.for('LinkingController'),
|
||||
NavigationController: Symbol.for('NavigationController'),
|
||||
NoAccountWarningController: Symbol.for('NoAccountWarningController'),
|
||||
NotesController: Symbol.for('NotesController'),
|
||||
PaneController: Symbol.for('PaneController'),
|
||||
PreferencesController: Symbol.for('PreferencesController'),
|
||||
PurchaseFlowController: Symbol.for('PurchaseFlowController'),
|
||||
QuickSettingsController: Symbol.for('QuickSettingsController'),
|
||||
SearchOptionsController: Symbol.for('SearchOptionsController'),
|
||||
SubscriptionController: Symbol.for('SubscriptionController'),
|
||||
SyncStatusController: Symbol.for('SyncStatusController'),
|
||||
ToastService: Symbol.for('ToastService'),
|
||||
VaultSelectionMenuController: Symbol.for('VaultSelectionMenuController'),
|
||||
|
||||
// Use cases
|
||||
GetItemTags: Symbol.for('GetItemTags'),
|
||||
GetPurchaseFlowUrl: Symbol.for('GetPurchaseFlowUrl'),
|
||||
IsGlobalSpellcheckEnabled: Symbol.for('IsGlobalSpellcheckEnabled'),
|
||||
IsMobileDevice: Symbol.for('IsMobileDevice'),
|
||||
IsNativeIOS: Symbol.for('IsNativeIOS'),
|
||||
IsNativeMobileWeb: Symbol.for('IsNativeMobileWeb'),
|
||||
IsTabletOrMobileScreen: Symbol.for('IsTabletOrMobileScreen'),
|
||||
LoadPurchaseFlowUrl: Symbol.for('LoadPurchaseFlowUrl'),
|
||||
OpenSubscriptionDashboard: Symbol.for('OpenSubscriptionDashboard'),
|
||||
PanesForLayout: Symbol.for('PanesForLayout'),
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
import {
|
||||
ArchiveManager,
|
||||
AutolockService,
|
||||
ChangelogService,
|
||||
GetItemTags,
|
||||
Importer,
|
||||
IsGlobalSpellcheckEnabled,
|
||||
IsMobileDevice,
|
||||
IsNativeIOS,
|
||||
IsNativeMobileWeb,
|
||||
KeyboardService,
|
||||
RouteService,
|
||||
ThemeManager,
|
||||
ToastService,
|
||||
VaultDisplayService,
|
||||
WebApplicationInterface,
|
||||
} from '@standardnotes/ui-services'
|
||||
import { DependencyContainer } from '@standardnotes/utils'
|
||||
import { Web_TYPES } from './Types'
|
||||
import { BackupServiceInterface, isDesktopDevice } from '@standardnotes/snjs'
|
||||
import { DesktopManager } from '../Device/DesktopManager'
|
||||
import { MomentsService } from '@/Controllers/Moments/MomentsService'
|
||||
import { PersistenceService } from '@/Controllers/Abstract/PersistenceService'
|
||||
import { FilePreviewModalController } from '@/Controllers/FilePreviewModalController'
|
||||
import { QuickSettingsController } from '@/Controllers/QuickSettingsController'
|
||||
import { VaultSelectionMenuController } from '@/Controllers/VaultSelectionMenuController'
|
||||
import { PaneController } from '@/Controllers/PaneController/PaneController'
|
||||
import { PreferencesController } from '@/Controllers/PreferencesController'
|
||||
import { FeaturesController } from '@/Controllers/FeaturesController'
|
||||
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
|
||||
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
||||
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
|
||||
import { NoAccountWarningController } from '@/Controllers/NoAccountWarningController'
|
||||
import { AccountMenuController } from '@/Controllers/AccountMenu/AccountMenuController'
|
||||
import { SubscriptionController } from '@/Controllers/Subscription/SubscriptionController'
|
||||
import { PurchaseFlowController } from '@/Controllers/PurchaseFlow/PurchaseFlowController'
|
||||
import { FilesController } from '@/Controllers/FilesController'
|
||||
import { HistoryModalController } from '@/Controllers/NoteHistory/HistoryModalController'
|
||||
import { ImportModalController } from '@/Controllers/ImportModalController'
|
||||
import { ApplicationEventObserver } from '@/Event/ApplicationEventObserver'
|
||||
import { SearchOptionsController } from '@/Controllers/SearchOptionsController'
|
||||
import { LinkingController } from '@/Controllers/LinkingController'
|
||||
import { SyncStatusController } from '@/Controllers/SyncStatusController'
|
||||
import { ActionsMenuController } from '@/Controllers/ActionsMenuController'
|
||||
import { ItemGroupController } from '@/Components/NoteView/Controller/ItemGroupController'
|
||||
import { MobileWebReceiver } from '@/NativeMobileWeb/MobileWebReceiver'
|
||||
import { AndroidBackHandler } from '@/NativeMobileWeb/AndroidBackHandler'
|
||||
import { IsTabletOrMobileScreen } from '../UseCase/IsTabletOrMobileScreen'
|
||||
import { PanesForLayout } from '../UseCase/PanesForLayout'
|
||||
import { LoadPurchaseFlowUrl } from '../UseCase/LoadPurchaseFlowUrl'
|
||||
import { GetPurchaseFlowUrl } from '../UseCase/GetPurchaseFlowUrl'
|
||||
import { OpenSubscriptionDashboard } from '../UseCase/OpenSubscriptionDashboard'
|
||||
|
||||
export class WebDependencies extends DependencyContainer {
|
||||
constructor(private application: WebApplicationInterface) {
|
||||
super()
|
||||
|
||||
this.bind(Web_TYPES.Importer, () => {
|
||||
return new Importer(application.features, application.mutator, application.items)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.IsNativeIOS, () => {
|
||||
return new IsNativeIOS(application.environment, application.platform)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.OpenSubscriptionDashboard, () => {
|
||||
return new OpenSubscriptionDashboard(application, application.legacyApi)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.IsNativeMobileWeb, () => {
|
||||
return new IsNativeMobileWeb(application.environment)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.IsGlobalSpellcheckEnabled, () => {
|
||||
return new IsGlobalSpellcheckEnabled(application.preferences)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.MobileWebReceiver, () => {
|
||||
if (!application.isNativeMobileWeb()) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return new MobileWebReceiver(application)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.AndroidBackHandler, () => {
|
||||
if (!application.isNativeMobileWeb()) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return new AndroidBackHandler()
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.Application, () => this.application)
|
||||
|
||||
this.bind(Web_TYPES.ItemGroupController, () => {
|
||||
return new ItemGroupController(
|
||||
application.items,
|
||||
application.mutator,
|
||||
application.sync,
|
||||
application.sessions,
|
||||
application.preferences,
|
||||
application.componentManager,
|
||||
application.alerts,
|
||||
this.get<IsNativeMobileWeb>(Web_TYPES.IsNativeMobileWeb),
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.RouteService, () => {
|
||||
return new RouteService(this.application, this.application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.KeyboardService, () => {
|
||||
return new KeyboardService(application.platform, application.environment)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ArchiveManager, () => {
|
||||
return new ArchiveManager(this.get<WebApplicationInterface>(Web_TYPES.Application))
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ThemeManager, () => {
|
||||
return new ThemeManager(application, application.preferences, application.componentManager, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.AutolockService, () => {
|
||||
return application.isNativeMobileWeb() ? undefined : new AutolockService(application, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.DesktopManager, () => {
|
||||
return isDesktopDevice(application.device)
|
||||
? new DesktopManager(application, application.device, application.fileBackups as BackupServiceInterface)
|
||||
: undefined
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ChangelogService, () => {
|
||||
return new ChangelogService(application.environment, application.storage)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.IsMobileDevice, () => {
|
||||
return new IsMobileDevice(this.get<IsNativeMobileWeb>(Web_TYPES.IsNativeMobileWeb))
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.MomentsService, () => {
|
||||
return new MomentsService(
|
||||
this.get<FilesController>(Web_TYPES.FilesController),
|
||||
this.get<LinkingController>(Web_TYPES.LinkingController),
|
||||
application.storage,
|
||||
application.preferences,
|
||||
application.items,
|
||||
application.protections,
|
||||
application.desktopDevice,
|
||||
this.get<IsMobileDevice>(Web_TYPES.IsMobileDevice),
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.VaultDisplayService, () => {
|
||||
return new VaultDisplayService(application, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.PersistenceService, () => {
|
||||
return new PersistenceService(
|
||||
this.get<ItemListController>(Web_TYPES.ItemListController),
|
||||
this.get<NavigationController>(Web_TYPES.NavigationController),
|
||||
application.storage,
|
||||
application.items,
|
||||
application.sync,
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.FilePreviewModalController, () => {
|
||||
return new FilePreviewModalController(application.items)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.QuickSettingsController, () => {
|
||||
return new QuickSettingsController(application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.VaultSelectionMenuController, () => {
|
||||
return new VaultSelectionMenuController(application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.PaneController, () => {
|
||||
return new PaneController(
|
||||
application.preferences,
|
||||
this.get<KeyboardService>(Web_TYPES.KeyboardService),
|
||||
this.get<IsTabletOrMobileScreen>(Web_TYPES.IsTabletOrMobileScreen),
|
||||
this.get<PanesForLayout>(Web_TYPES.PanesForLayout),
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.PanesForLayout, () => {
|
||||
return new PanesForLayout(this.get<IsTabletOrMobileScreen>(Web_TYPES.IsTabletOrMobileScreen))
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.IsTabletOrMobileScreen, () => {
|
||||
return new IsTabletOrMobileScreen(application.environment)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.PreferencesController, () => {
|
||||
return new PreferencesController(this.get<RouteService>(Web_TYPES.RouteService), application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.FeaturesController, () => {
|
||||
return new FeaturesController(application.features, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.NavigationController, () => {
|
||||
return new NavigationController(
|
||||
this.get<FeaturesController>(Web_TYPES.FeaturesController),
|
||||
this.get<VaultDisplayService>(Web_TYPES.VaultDisplayService),
|
||||
this.get<KeyboardService>(Web_TYPES.KeyboardService),
|
||||
this.get<PaneController>(Web_TYPES.PaneController),
|
||||
application.sync,
|
||||
application.mutator,
|
||||
application.items,
|
||||
application.preferences,
|
||||
application.alerts,
|
||||
application.changeAndSaveItem,
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.NotesController, () => {
|
||||
return new NotesController(
|
||||
this.get<ItemListController>(Web_TYPES.ItemListController),
|
||||
this.get<NavigationController>(Web_TYPES.NavigationController),
|
||||
this.get<ItemGroupController>(Web_TYPES.ItemGroupController),
|
||||
this.get<KeyboardService>(Web_TYPES.KeyboardService),
|
||||
application.preferences,
|
||||
application.items,
|
||||
application.mutator,
|
||||
application.sync,
|
||||
application.protections,
|
||||
application.alerts,
|
||||
this.get<IsGlobalSpellcheckEnabled>(Web_TYPES.IsGlobalSpellcheckEnabled),
|
||||
this.get<GetItemTags>(Web_TYPES.GetItemTags),
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.GetItemTags, () => {
|
||||
return new GetItemTags(application.items)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.SearchOptionsController, () => {
|
||||
return new SearchOptionsController(application.protections, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.LinkingController, () => {
|
||||
return new LinkingController(
|
||||
this.get<ItemListController>(Web_TYPES.ItemListController),
|
||||
this.get<FilesController>(Web_TYPES.FilesController),
|
||||
this.get<SubscriptionController>(Web_TYPES.SubscriptionController),
|
||||
this.get<NavigationController>(Web_TYPES.NavigationController),
|
||||
this.get<ItemGroupController>(Web_TYPES.ItemGroupController),
|
||||
this.get<VaultDisplayService>(Web_TYPES.VaultDisplayService),
|
||||
application.preferences,
|
||||
application.items,
|
||||
application.mutator,
|
||||
application.sync,
|
||||
application.vaults,
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ItemListController, () => {
|
||||
return new ItemListController(
|
||||
this.get<KeyboardService>(Web_TYPES.KeyboardService),
|
||||
this.get<PaneController>(Web_TYPES.PaneController),
|
||||
this.get<NavigationController>(Web_TYPES.NavigationController),
|
||||
this.get<SearchOptionsController>(Web_TYPES.SearchOptionsController),
|
||||
application.items,
|
||||
application.preferences,
|
||||
this.get<ItemGroupController>(Web_TYPES.ItemGroupController),
|
||||
this.get<VaultDisplayService>(Web_TYPES.VaultDisplayService),
|
||||
this.get<DesktopManager>(Web_TYPES.DesktopManager),
|
||||
application.protections,
|
||||
application.options,
|
||||
this.get<IsNativeMobileWeb>(Web_TYPES.IsNativeMobileWeb),
|
||||
application.changeAndSaveItem,
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.NoAccountWarningController, () => {
|
||||
return new NoAccountWarningController(application.sessions, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.AccountMenuController, () => {
|
||||
return new AccountMenuController(application.items, application.getHost, application.events)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.SubscriptionController, () => {
|
||||
return new SubscriptionController(
|
||||
application.subscriptions,
|
||||
application.sessions,
|
||||
application.features,
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.PurchaseFlowController, () => {
|
||||
return new PurchaseFlowController(
|
||||
application.sessions,
|
||||
application.subscriptions,
|
||||
application.legacyApi,
|
||||
application.alerts,
|
||||
application.mobileDevice,
|
||||
this.get<LoadPurchaseFlowUrl>(Web_TYPES.LoadPurchaseFlowUrl),
|
||||
this.get<IsNativeIOS>(Web_TYPES.IsNativeIOS),
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.LoadPurchaseFlowUrl, () => {
|
||||
return new LoadPurchaseFlowUrl(application, this.get<GetPurchaseFlowUrl>(Web_TYPES.GetPurchaseFlowUrl))
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.GetPurchaseFlowUrl, () => {
|
||||
return new GetPurchaseFlowUrl(application, application.legacyApi)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.SyncStatusController, () => {
|
||||
return new SyncStatusController()
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ActionsMenuController, () => {
|
||||
return new ActionsMenuController()
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.FilesController, () => {
|
||||
return new FilesController(
|
||||
this.get<NotesController>(Web_TYPES.NotesController),
|
||||
this.get<FilePreviewModalController>(Web_TYPES.FilePreviewModalController),
|
||||
this.get<ArchiveManager>(Web_TYPES.ArchiveManager),
|
||||
this.get<VaultDisplayService>(Web_TYPES.VaultDisplayService),
|
||||
application.items,
|
||||
application.files,
|
||||
application.mutator,
|
||||
application.sync,
|
||||
application.protections,
|
||||
application.alerts,
|
||||
application.platform,
|
||||
application.mobileDevice,
|
||||
this.get<IsNativeMobileWeb>(Web_TYPES.IsNativeMobileWeb),
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.HistoryModalController, () => {
|
||||
return new HistoryModalController(
|
||||
this.get<NotesController>(Web_TYPES.NotesController),
|
||||
this.get<KeyboardService>(Web_TYPES.KeyboardService),
|
||||
application.events,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ImportModalController, () => {
|
||||
return new ImportModalController(
|
||||
this.get<Importer>(Web_TYPES.Importer),
|
||||
this.get<NavigationController>(Web_TYPES.NavigationController),
|
||||
application.items,
|
||||
application.mutator,
|
||||
)
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ToastService, () => {
|
||||
return new ToastService()
|
||||
})
|
||||
|
||||
this.bind(Web_TYPES.ApplicationEventObserver, () => {
|
||||
return new ApplicationEventObserver(
|
||||
application,
|
||||
application.routeService,
|
||||
this.get<PurchaseFlowController>(Web_TYPES.PurchaseFlowController),
|
||||
this.get<AccountMenuController>(Web_TYPES.AccountMenuController),
|
||||
this.get<PreferencesController>(Web_TYPES.PreferencesController),
|
||||
this.get<SyncStatusController>(Web_TYPES.SyncStatusController),
|
||||
application.sync,
|
||||
application.sessions,
|
||||
application.subscriptions,
|
||||
this.get<ToastService>(Web_TYPES.ToastService),
|
||||
application.user,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ export class DevMode {
|
||||
/** Valid only when running a mock event publisher on port 3124 */
|
||||
async purchaseMockSubscription() {
|
||||
const subscriptionId = 2002
|
||||
const email = this.application.getUser()?.email
|
||||
const email = this.application.sessions.getUser()?.email
|
||||
const response = await fetch('http://localhost:3124/events', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
||||
@@ -90,7 +90,7 @@ export class DesktopManager
|
||||
}
|
||||
}
|
||||
|
||||
async saveDesktopBackup() {
|
||||
async saveDesktopBackup(): Promise<void> {
|
||||
this.webApplication.notifyWebEvent(WebAppEvent.BeganBackupDownload)
|
||||
|
||||
const data = await this.getBackupFile()
|
||||
@@ -149,12 +149,12 @@ export class DesktopManager
|
||||
}
|
||||
}
|
||||
|
||||
searchText(text?: string) {
|
||||
searchText(text?: string): void {
|
||||
this.lastSearchedText = text
|
||||
this.device.onSearch(text)
|
||||
}
|
||||
|
||||
redoSearch() {
|
||||
redoSearch(): void {
|
||||
if (this.lastSearchedText) {
|
||||
this.searchText(this.lastSearchedText)
|
||||
}
|
||||
@@ -188,18 +188,20 @@ export class DesktopManager
|
||||
return
|
||||
}
|
||||
|
||||
const updatedComponent = await this.application.changeAndSaveItem(
|
||||
component,
|
||||
(m) => {
|
||||
const mutator = m as ComponentMutator
|
||||
// eslint-disable-next-line camelcase
|
||||
mutator.local_url = componentData.content.local_url as string
|
||||
// eslint-disable-next-line camelcase
|
||||
mutator.package_info = componentData.content.package_info
|
||||
mutator.setAppDataItem(AppDataField.ComponentInstallError, undefined)
|
||||
},
|
||||
undefined,
|
||||
)
|
||||
const updatedComponent = (
|
||||
await this.application.changeAndSaveItem.execute(
|
||||
component,
|
||||
(m) => {
|
||||
const mutator = m as ComponentMutator
|
||||
// eslint-disable-next-line camelcase
|
||||
mutator.local_url = componentData.content.local_url as string
|
||||
// eslint-disable-next-line camelcase
|
||||
mutator.package_info = componentData.content.package_info
|
||||
mutator.setAppDataItem(AppDataField.ComponentInstallError, undefined)
|
||||
},
|
||||
undefined,
|
||||
)
|
||||
).getValue()
|
||||
|
||||
for (const observer of this.updateObservers) {
|
||||
observer.callback(updatedComponent as SNComponent)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { isDesktopApplication } from '@/Utils'
|
||||
import { ApplicationInterface, LegacyApiServiceInterface, Result, UseCaseInterface } from '@standardnotes/snjs'
|
||||
|
||||
export class GetPurchaseFlowUrl implements UseCaseInterface<string> {
|
||||
constructor(
|
||||
private application: ApplicationInterface,
|
||||
private legacyApi: LegacyApiServiceInterface,
|
||||
) {}
|
||||
|
||||
async execute(): Promise<Result<string>> {
|
||||
const currentUrl = window.location.origin
|
||||
const successUrl = isDesktopApplication() ? 'standardnotes://' : currentUrl
|
||||
|
||||
if (this.application.sessions.isSignedOut() || this.application.isThirdPartyHostUsed()) {
|
||||
return Result.ok(`${window.purchaseUrl}/offline?&success_url=${successUrl}`)
|
||||
}
|
||||
|
||||
const token = await this.legacyApi.getNewSubscriptionToken()
|
||||
if (token) {
|
||||
return Result.ok(`${window.purchaseUrl}?subscription_token=${token}&success_url=${successUrl}`)
|
||||
}
|
||||
|
||||
return Result.fail('Could not get purchase flow URL.')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { isMobileScreen, isTabletOrMobileScreen, isTabletScreen } from '@/Utils'
|
||||
import { Environment, Result, SyncUseCaseInterface } from '@standardnotes/snjs'
|
||||
import { IsNativeMobileWeb } from '@standardnotes/ui-services'
|
||||
|
||||
type ReturnType = {
|
||||
isTabletOrMobile: boolean
|
||||
isTablet: boolean
|
||||
isMobile: boolean
|
||||
}
|
||||
|
||||
export class IsTabletOrMobileScreen implements SyncUseCaseInterface<ReturnType> {
|
||||
private _isNativeMobileWeb = new IsNativeMobileWeb(this.environment)
|
||||
|
||||
constructor(private environment: Environment) {}
|
||||
|
||||
execute(): Result<ReturnType> {
|
||||
const isNativeMobile = this._isNativeMobileWeb.execute().getValue()
|
||||
const isTabletOrMobile = isTabletOrMobileScreen() || isNativeMobile
|
||||
const isTablet = isTabletScreen() || (isNativeMobile && !isMobileScreen())
|
||||
const isMobile = isMobileScreen() || (isNativeMobile && !isTablet)
|
||||
|
||||
if (isTablet && isMobile) {
|
||||
throw Error('isTablet and isMobile cannot both be true')
|
||||
}
|
||||
|
||||
return Result.ok({
|
||||
isTabletOrMobile,
|
||||
isTablet,
|
||||
isMobile,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Environment, Result, UseCaseInterface } from '@standardnotes/snjs'
|
||||
import { GetPurchaseFlowUrl } from './GetPurchaseFlowUrl'
|
||||
import { RouteType, WebApplicationInterface } from '@standardnotes/ui-services'
|
||||
|
||||
export class LoadPurchaseFlowUrl implements UseCaseInterface<void> {
|
||||
constructor(
|
||||
private application: WebApplicationInterface,
|
||||
private _getPurchaseFlowUrl: GetPurchaseFlowUrl,
|
||||
) {}
|
||||
|
||||
async execute(): Promise<Result<void>> {
|
||||
const urlResult = await this._getPurchaseFlowUrl.execute()
|
||||
if (urlResult.isFailed()) {
|
||||
return urlResult
|
||||
}
|
||||
|
||||
const url = urlResult.getValue()
|
||||
const route = this.application.routeService.getRoute()
|
||||
const params = route.type === RouteType.Purchase ? route.purchaseParams : { period: null, plan: null }
|
||||
const period = params.period ? `&period=${params.period}` : ''
|
||||
const plan = params.plan ? `&plan=${params.plan}` : ''
|
||||
|
||||
if (url) {
|
||||
const finalUrl = `${url}${period}${plan}`
|
||||
|
||||
if (this.application.isNativeMobileWeb()) {
|
||||
this.application.mobileDevice.openUrl(finalUrl)
|
||||
} else if (this.application.environment === Environment.Desktop) {
|
||||
this.application.desktopDevice?.openUrl(finalUrl)
|
||||
} else {
|
||||
const windowProxy = window.open('', '_blank')
|
||||
;(windowProxy as WindowProxy).location = finalUrl
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
return Result.fail('Could not load purchase flow URL.')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Environment, LegacyApiServiceInterface, Result, UseCaseInterface } from '@standardnotes/snjs'
|
||||
import { WebApplicationInterface } from '@standardnotes/ui-services'
|
||||
|
||||
export class OpenSubscriptionDashboard implements UseCaseInterface<void> {
|
||||
constructor(
|
||||
private application: WebApplicationInterface,
|
||||
private legacyApi: LegacyApiServiceInterface,
|
||||
) {}
|
||||
|
||||
async execute(): Promise<Result<void>> {
|
||||
const token = await this.legacyApi.getNewSubscriptionToken()
|
||||
if (!token) {
|
||||
return Result.fail('Could not get subscription token.')
|
||||
}
|
||||
|
||||
const url = `${window.dashboardUrl}?subscription_token=${token}`
|
||||
|
||||
if (this.application.device.environment === Environment.Mobile) {
|
||||
this.application.device.openUrl(url)
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
if (this.application.device.environment === Environment.Desktop) {
|
||||
window.open(url, '_blank')
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
const windowProxy = window.open('', '_blank')
|
||||
;(windowProxy as WindowProxy).location = url
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { AppPaneId } from './../../Components/Panes/AppPaneMetadata'
|
||||
import { PaneLayout } from './../../Controllers/PaneController/PaneLayout'
|
||||
import { IsTabletOrMobileScreen } from './IsTabletOrMobileScreen'
|
||||
import { Result, SyncUseCaseInterface } from '@standardnotes/snjs'
|
||||
|
||||
export class PanesForLayout implements SyncUseCaseInterface<AppPaneId[]> {
|
||||
constructor(private _isTabletOrMobileScreen: IsTabletOrMobileScreen) {}
|
||||
|
||||
execute(layout: PaneLayout): Result<AppPaneId[]> {
|
||||
const screen = this._isTabletOrMobileScreen.execute().getValue()
|
||||
if (screen.isTablet) {
|
||||
if (layout === PaneLayout.TagSelection || layout === PaneLayout.TableView) {
|
||||
return Result.ok([AppPaneId.Navigation, AppPaneId.Items])
|
||||
} else if (layout === PaneLayout.ItemSelection || layout === PaneLayout.Editing) {
|
||||
return Result.ok([AppPaneId.Items, AppPaneId.Editor])
|
||||
}
|
||||
} else if (screen.isMobile) {
|
||||
if (layout === PaneLayout.TagSelection) {
|
||||
return Result.ok([AppPaneId.Navigation])
|
||||
} else if (layout === PaneLayout.ItemSelection || layout === PaneLayout.TableView) {
|
||||
return Result.ok([AppPaneId.Navigation, AppPaneId.Items])
|
||||
} else if (layout === PaneLayout.Editing) {
|
||||
return Result.ok([AppPaneId.Navigation, AppPaneId.Items, AppPaneId.Editor])
|
||||
}
|
||||
} else {
|
||||
if (layout === PaneLayout.TableView) {
|
||||
return Result.ok([AppPaneId.Navigation, AppPaneId.Items])
|
||||
} else {
|
||||
return Result.ok([AppPaneId.Navigation, AppPaneId.Items, AppPaneId.Editor])
|
||||
}
|
||||
}
|
||||
|
||||
throw Error('Unhandled pane layout')
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
import { WebCrypto } from '@/Application/Crypto'
|
||||
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
|
||||
import { WebOrDesktopDevice } from '@/Application/Device/WebOrDesktopDevice'
|
||||
import {
|
||||
DeinitSource,
|
||||
Platform,
|
||||
SNApplication,
|
||||
removeFromArray,
|
||||
DesktopDeviceInterface,
|
||||
isDesktopDevice,
|
||||
DeinitMode,
|
||||
@@ -19,57 +17,82 @@ import {
|
||||
DecryptedItem,
|
||||
Environment,
|
||||
ApplicationOptionsDefaults,
|
||||
BackupServiceInterface,
|
||||
InternalFeatureService,
|
||||
InternalFeatureServiceInterface,
|
||||
PrefDefaults,
|
||||
NoteContent,
|
||||
SNNote,
|
||||
DesktopManagerInterface,
|
||||
} from '@standardnotes/snjs'
|
||||
import { makeObservable, observable } from 'mobx'
|
||||
import { action, computed, makeObservable, observable } from 'mobx'
|
||||
import { startAuthentication, startRegistration } from '@simplewebauthn/browser'
|
||||
import { PanelResizedData } from '@/Types/PanelResizedData'
|
||||
import { getBlobFromBase64, isAndroid, isDesktopApplication, isDev, isIOS } from '@/Utils'
|
||||
import { DesktopManager } from './Device/DesktopManager'
|
||||
import { getBlobFromBase64, isDesktopApplication, isDev } from '@/Utils'
|
||||
import {
|
||||
ArchiveManager,
|
||||
AutolockService,
|
||||
ChangelogService,
|
||||
Importer,
|
||||
IsGlobalSpellcheckEnabled,
|
||||
IsMobileDevice,
|
||||
IsNativeIOS,
|
||||
IsNativeMobileWeb,
|
||||
KeyboardService,
|
||||
PreferenceId,
|
||||
RouteService,
|
||||
RouteServiceInterface,
|
||||
ThemeManager,
|
||||
VaultDisplayService,
|
||||
VaultDisplayServiceInterface,
|
||||
WebAlertService,
|
||||
WebApplicationInterface,
|
||||
} from '@standardnotes/ui-services'
|
||||
import { MobileWebReceiver, NativeMobileEventListener } from '../NativeMobileWeb/MobileWebReceiver'
|
||||
import { AndroidBackHandler } from '@/NativeMobileWeb/AndroidBackHandler'
|
||||
import { setCustomViewportHeight } from '@/setViewportHeightWithFallback'
|
||||
import { WebServices } from './WebServices'
|
||||
import { FeatureName } from '@/Controllers/FeatureName'
|
||||
import { ItemGroupController } from '@/Components/NoteView/Controller/ItemGroupController'
|
||||
import { VisibilityObserver } from './VisibilityObserver'
|
||||
import { MomentsService } from '@/Controllers/Moments/MomentsService'
|
||||
import { DevMode } from './DevMode'
|
||||
import { ToastType, addToast, dismissToast } from '@standardnotes/toast'
|
||||
import { WebDependencies } from './Dependencies/WebDependencies'
|
||||
import { Web_TYPES } from './Dependencies/Types'
|
||||
import { ApplicationEventObserver } from '@/Event/ApplicationEventObserver'
|
||||
import { PaneController } from '@/Controllers/PaneController/PaneController'
|
||||
import { LinkingController } from '@/Controllers/LinkingController'
|
||||
import { MomentsService } from '@/Controllers/Moments/MomentsService'
|
||||
import { FeaturesController } from '@/Controllers/FeaturesController'
|
||||
import { FilesController } from '@/Controllers/FilesController'
|
||||
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
|
||||
import { AndroidBackHandler } from '@/NativeMobileWeb/AndroidBackHandler'
|
||||
import { SubscriptionController } from '@/Controllers/Subscription/SubscriptionController'
|
||||
import { PurchaseFlowController } from '@/Controllers/PurchaseFlow/PurchaseFlowController'
|
||||
import { AccountMenuController } from '@/Controllers/AccountMenu/AccountMenuController'
|
||||
import { PreferencesController } from '@/Controllers/PreferencesController'
|
||||
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
||||
import { ImportModalController } from '@/Controllers/ImportModalController'
|
||||
import { SyncStatusController } from '@/Controllers/SyncStatusController'
|
||||
import { HistoryModalController } from '@/Controllers/NoteHistory/HistoryModalController'
|
||||
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
|
||||
import { FilePreviewModalController } from '@/Controllers/FilePreviewModalController'
|
||||
import { OpenSubscriptionDashboard } from './UseCase/OpenSubscriptionDashboard'
|
||||
import { QuickSettingsController } from '@/Controllers/QuickSettingsController'
|
||||
import { VaultSelectionMenuController } from '@/Controllers/VaultSelectionMenuController'
|
||||
import { ItemGroupController } from '@/Components/NoteView/Controller/ItemGroupController'
|
||||
import { NoAccountWarningController } from '@/Controllers/NoAccountWarningController'
|
||||
import { SearchOptionsController } from '@/Controllers/SearchOptionsController'
|
||||
import { PersistenceService } from '@/Controllers/Abstract/PersistenceService'
|
||||
import { removeFromArray } from '@standardnotes/utils'
|
||||
|
||||
export type WebEventObserver = (event: WebAppEvent, data?: unknown) => void
|
||||
|
||||
export class WebApplication extends SNApplication implements WebApplicationInterface {
|
||||
public readonly itemControllerGroup: ItemGroupController
|
||||
public readonly routeService: RouteServiceInterface
|
||||
readonly enableUnfinishedFeatures: boolean = window?.enabledUnfinishedFeatures
|
||||
|
||||
private readonly webServices!: WebServices
|
||||
private readonly deps = new WebDependencies(this)
|
||||
|
||||
private visibilityObserver?: VisibilityObserver
|
||||
private readonly webEventObservers: WebEventObserver[] = []
|
||||
private readonly mobileWebReceiver?: MobileWebReceiver
|
||||
private readonly androidBackHandler?: AndroidBackHandler
|
||||
private readonly visibilityObserver?: VisibilityObserver
|
||||
private readonly mobileAppEventObserver?: () => void
|
||||
private disposers: (() => void)[] = []
|
||||
|
||||
public readonly devMode?: DevMode
|
||||
public isSessionsModalVisible = false
|
||||
|
||||
public devMode?: DevMode
|
||||
|
||||
constructor(
|
||||
deviceInterface: WebOrDesktopDevice,
|
||||
@@ -102,48 +125,49 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
) => Promise<Record<string, unknown>>,
|
||||
})
|
||||
|
||||
makeObservable(this, {
|
||||
dealloced: observable,
|
||||
|
||||
preferencesController: computed,
|
||||
|
||||
isSessionsModalVisible: observable,
|
||||
|
||||
openSessionsModal: action,
|
||||
closeSessionsModal: action,
|
||||
})
|
||||
|
||||
this.createBackgroundServices()
|
||||
}
|
||||
|
||||
private createBackgroundServices(): void {
|
||||
void this.mobileWebReceiver
|
||||
void this.autolockService
|
||||
void this.persistence
|
||||
void this.themeManager
|
||||
void this.momentsService
|
||||
void this.routeService
|
||||
|
||||
if (isDev) {
|
||||
this.devMode = new DevMode(this)
|
||||
}
|
||||
|
||||
makeObservable(this, {
|
||||
dealloced: observable,
|
||||
})
|
||||
|
||||
if (!this.isNativeMobileWeb()) {
|
||||
deviceInterface.setApplication(this)
|
||||
this.webOrDesktopDevice.setApplication(this)
|
||||
}
|
||||
|
||||
this.itemControllerGroup = new ItemGroupController(this)
|
||||
this.routeService = new RouteService(this, this.events)
|
||||
|
||||
this.webServices = {} as WebServices
|
||||
this.webServices.keyboardService = new KeyboardService(platform, this.environment)
|
||||
this.webServices.archiveService = new ArchiveManager(this)
|
||||
this.webServices.themeService = new ThemeManager(this, this.preferences, this.componentManager, this.events)
|
||||
this.webServices.autolockService = this.isNativeMobileWeb() ? undefined : new AutolockService(this, this.events)
|
||||
this.webServices.desktopService = isDesktopDevice(deviceInterface)
|
||||
? new DesktopManager(this, deviceInterface, this.fileBackups as BackupServiceInterface)
|
||||
: undefined
|
||||
this.webServices.viewControllerManager = new ViewControllerManager(this, deviceInterface)
|
||||
this.webServices.changelogService = new ChangelogService(this.environment, this.storage)
|
||||
this.webServices.momentsService = new MomentsService(
|
||||
this,
|
||||
this.webServices.viewControllerManager.filesController,
|
||||
this.events,
|
||||
)
|
||||
this.webServices.vaultDisplayService = new VaultDisplayService(this, this.events)
|
||||
const appEventObserver = this.deps.get<ApplicationEventObserver>(Web_TYPES.ApplicationEventObserver)
|
||||
this.disposers.push(this.addEventObserver(appEventObserver.handle.bind(appEventObserver)))
|
||||
|
||||
if (this.isNativeMobileWeb()) {
|
||||
this.mobileWebReceiver = new MobileWebReceiver(this)
|
||||
this.androidBackHandler = new AndroidBackHandler()
|
||||
this.mobileAppEventObserver = this.addEventObserver(async (event) => {
|
||||
this.mobileDevice().notifyApplicationEvent(event)
|
||||
})
|
||||
this.disposers.push(
|
||||
this.addEventObserver(async (event) => {
|
||||
this.mobileDevice.notifyApplicationEvent(event)
|
||||
}),
|
||||
)
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log = (...args) => {
|
||||
this.mobileDevice().consoleLog(...args)
|
||||
this.mobileDevice.consoleLog(...args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,42 +182,23 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
super.deinit(mode, source)
|
||||
|
||||
if (!this.isNativeMobileWeb()) {
|
||||
this.webOrDesktopDevice().removeApplication(this)
|
||||
this.webOrDesktopDevice.removeApplication(this)
|
||||
}
|
||||
|
||||
for (const disposer of this.disposers) {
|
||||
disposer()
|
||||
}
|
||||
this.disposers.length = 0
|
||||
|
||||
this.deps.deinit()
|
||||
|
||||
try {
|
||||
for (const service of Object.values(this.webServices)) {
|
||||
if (!service) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ('deinit' in service) {
|
||||
service.deinit?.(source)
|
||||
}
|
||||
|
||||
;(service as { application?: WebApplication }).application = undefined
|
||||
}
|
||||
|
||||
;(this.webServices as unknown) = undefined
|
||||
|
||||
this.itemControllerGroup.deinit()
|
||||
;(this.itemControllerGroup as unknown) = undefined
|
||||
;(this.mobileWebReceiver as unknown) = undefined
|
||||
|
||||
this.routeService.deinit()
|
||||
;(this.routeService as unknown) = undefined
|
||||
|
||||
this.webEventObservers.length = 0
|
||||
|
||||
if (this.visibilityObserver) {
|
||||
this.visibilityObserver.deinit()
|
||||
;(this.visibilityObserver as unknown) = undefined
|
||||
}
|
||||
|
||||
if (this.mobileAppEventObserver) {
|
||||
this.mobileAppEventObserver()
|
||||
;(this.mobileAppEventObserver as unknown) = undefined
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error while deiniting application', error)
|
||||
}
|
||||
@@ -225,46 +230,6 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
this.notifyWebEvent(WebAppEvent.PanelResized, data)
|
||||
}
|
||||
|
||||
public get vaultDisplayService(): VaultDisplayServiceInterface {
|
||||
return this.webServices.vaultDisplayService
|
||||
}
|
||||
|
||||
public get controllers(): ViewControllerManager {
|
||||
return this.webServices.viewControllerManager
|
||||
}
|
||||
|
||||
public getDesktopService(): DesktopManager | undefined {
|
||||
return this.webServices.desktopService
|
||||
}
|
||||
|
||||
public getAutolockService() {
|
||||
return this.webServices.autolockService
|
||||
}
|
||||
|
||||
public getArchiveService() {
|
||||
return this.webServices.archiveService
|
||||
}
|
||||
|
||||
public get paneController() {
|
||||
return this.webServices.viewControllerManager.paneController
|
||||
}
|
||||
|
||||
public get linkingController() {
|
||||
return this.webServices.viewControllerManager.linkingController
|
||||
}
|
||||
|
||||
public get changelogService() {
|
||||
return this.webServices.changelogService
|
||||
}
|
||||
|
||||
public get momentsService() {
|
||||
return this.webServices.momentsService
|
||||
}
|
||||
|
||||
public get featuresController() {
|
||||
return this.controllers.featuresController
|
||||
}
|
||||
|
||||
public get desktopDevice(): DesktopDeviceInterface | undefined {
|
||||
if (isDesktopDevice(this.device)) {
|
||||
return this.device
|
||||
@@ -277,53 +242,42 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
return InternalFeatureService.get()
|
||||
}
|
||||
|
||||
isNativeIOS() {
|
||||
return this.isNativeMobileWeb() && this.platform === Platform.Ios
|
||||
isNativeIOS(): boolean {
|
||||
return this.deps.get<IsNativeIOS>(Web_TYPES.IsNativeIOS).execute().getValue()
|
||||
}
|
||||
|
||||
get isMobileDevice() {
|
||||
return this.isNativeMobileWeb() || isIOS() || isAndroid()
|
||||
get isMobileDevice(): boolean {
|
||||
return this.deps.get<IsMobileDevice>(Web_TYPES.IsMobileDevice).execute().getValue()
|
||||
}
|
||||
|
||||
get hideOutboundSubscriptionLinks() {
|
||||
return this.isNativeIOS()
|
||||
}
|
||||
|
||||
mobileDevice(): MobileDeviceInterface {
|
||||
if (!this.isNativeMobileWeb()) {
|
||||
throw Error('Attempting to access device as mobile device on non mobile platform')
|
||||
}
|
||||
get mobileDevice(): MobileDeviceInterface {
|
||||
return this.device as MobileDeviceInterface
|
||||
}
|
||||
|
||||
webOrDesktopDevice(): WebOrDesktopDevice {
|
||||
get webOrDesktopDevice(): WebOrDesktopDevice {
|
||||
return this.device as WebOrDesktopDevice
|
||||
}
|
||||
|
||||
public getThemeService() {
|
||||
return this.webServices.themeService
|
||||
}
|
||||
|
||||
public get keyboardService() {
|
||||
return this.webServices.keyboardService
|
||||
}
|
||||
|
||||
async checkForSecurityUpdate() {
|
||||
async checkForSecurityUpdate(): Promise<boolean> {
|
||||
return this.protocolUpgradeAvailable()
|
||||
}
|
||||
|
||||
performDesktopTextBackup(): void | Promise<void> {
|
||||
return this.getDesktopService()?.saveDesktopBackup()
|
||||
return this.desktopManager?.saveDesktopBackup()
|
||||
}
|
||||
|
||||
isGlobalSpellcheckEnabled(): boolean {
|
||||
return this.getPreference(PrefKey.EditorSpellcheck, PrefDefaults[PrefKey.EditorSpellcheck])
|
||||
return this.deps.get<IsGlobalSpellcheckEnabled>(Web_TYPES.IsGlobalSpellcheckEnabled).execute().getValue()
|
||||
}
|
||||
|
||||
public getItemTags(item: DecryptedItemInterface) {
|
||||
return this.items.itemsReferencingItem(item).filter((ref) => {
|
||||
return this.items.itemsReferencingItem<SNTag>(item).filter((ref) => {
|
||||
return ref.content_type === ContentType.TYPES.Tag
|
||||
}) as SNTag[]
|
||||
})
|
||||
}
|
||||
|
||||
public get version(): string {
|
||||
@@ -349,15 +303,15 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
}
|
||||
|
||||
if (this.protections.getMobileScreenshotPrivacyEnabled()) {
|
||||
this.mobileDevice().setAndroidScreenshotPrivacy(true)
|
||||
this.mobileDevice.setAndroidScreenshotPrivacy(true)
|
||||
} else {
|
||||
this.mobileDevice().setAndroidScreenshotPrivacy(false)
|
||||
this.mobileDevice.setAndroidScreenshotPrivacy(false)
|
||||
}
|
||||
}
|
||||
|
||||
async handleMobileLosingFocusEvent(): Promise<void> {
|
||||
if (this.protections.getMobileScreenshotPrivacyEnabled()) {
|
||||
this.mobileDevice().stopHidingMobileInterfaceFromScreenshots()
|
||||
this.mobileDevice.stopHidingMobileInterfaceFromScreenshots()
|
||||
}
|
||||
|
||||
await this.lockApplicationAfterMobileEventIfApplicable()
|
||||
@@ -365,12 +319,20 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
|
||||
async handleMobileResumingFromBackgroundEvent(): Promise<void> {
|
||||
if (this.protections.getMobileScreenshotPrivacyEnabled()) {
|
||||
this.mobileDevice().hideMobileInterfaceFromScreenshots()
|
||||
this.mobileDevice.hideMobileInterfaceFromScreenshots()
|
||||
}
|
||||
}
|
||||
|
||||
handleMobileColorSchemeChangeEvent() {
|
||||
void this.getThemeService().handleMobileColorSchemeChangeEvent()
|
||||
void this.themeManager.handleMobileColorSchemeChangeEvent()
|
||||
}
|
||||
|
||||
openSessionsModal = () => {
|
||||
this.isSessionsModalVisible = true
|
||||
}
|
||||
|
||||
closeSessionsModal = () => {
|
||||
this.isSessionsModalVisible = false
|
||||
}
|
||||
|
||||
handleMobileKeyboardWillChangeFrameEvent(frame: {
|
||||
@@ -392,14 +354,14 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
}
|
||||
|
||||
handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void {
|
||||
const filesController = this.controllers.filesController
|
||||
const filesController = this.filesController
|
||||
const blob = getBlobFromBase64(file.data, file.mimeType)
|
||||
const mappedFile = new File([blob], file.name, { type: file.mimeType })
|
||||
filesController.uploadNewFile(mappedFile, true).catch(console.error)
|
||||
}
|
||||
|
||||
async handleReceivedTextEvent({ text, title }: { text: string; title?: string | undefined }) {
|
||||
const titleForNote = title || this.controllers.itemListController.titleForNewNote()
|
||||
const titleForNote = title || this.itemListController.titleForNewNote()
|
||||
|
||||
const note = this.items.createTemplateItem<NoteContent, SNNote>(ContentType.TYPES.Note, {
|
||||
title: titleForNote,
|
||||
@@ -409,7 +371,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
|
||||
const insertedNote = await this.mutator.insertItem(note)
|
||||
|
||||
this.controllers.selectionController.selectItem(insertedNote.uuid, true).catch(console.error)
|
||||
this.itemListController.selectItem(insertedNote.uuid, true).catch(console.error)
|
||||
|
||||
addToast({
|
||||
type: ToastType.Success,
|
||||
@@ -437,7 +399,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
const file = new File([imgBlob], finalPath, {
|
||||
type: imgBlob.type,
|
||||
})
|
||||
this.controllers.filesController.uploadNewFile(file, true).catch(console.error)
|
||||
this.filesController.uploadNewFile(file, true).catch(console.error)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
@@ -453,7 +415,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
}
|
||||
|
||||
private async lockApplicationAfterMobileEventIfApplicable(): Promise<void> {
|
||||
const isLocked = await this.isLocked()
|
||||
const isLocked = await this.protections.isLocked()
|
||||
if (isLocked) {
|
||||
return
|
||||
}
|
||||
@@ -469,7 +431,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
if (passcodeLockImmediately) {
|
||||
await this.lock()
|
||||
} else if (biometricsLockImmediately) {
|
||||
this.softLockBiometrics()
|
||||
this.protections.softLockBiometrics()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +456,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
|
||||
isAuthorizedToRenderItem(item: DecryptedItem): boolean {
|
||||
if (item.protected && this.hasProtectionSources()) {
|
||||
return this.hasUnprotectedAccessSession()
|
||||
return this.protections.hasUnprotectedAccessSession()
|
||||
}
|
||||
|
||||
return true
|
||||
@@ -505,19 +467,19 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
}
|
||||
|
||||
get entitledToFiles(): boolean {
|
||||
return this.controllers.featuresController.entitledToFiles
|
||||
return this.featuresController.entitledToFiles
|
||||
}
|
||||
|
||||
showPremiumModal(featureName?: FeatureName): void {
|
||||
void this.controllers.featuresController.showPremiumAlert(featureName)
|
||||
void this.featuresController.showPremiumAlert(featureName)
|
||||
}
|
||||
|
||||
hasValidFirstPartySubscription(): boolean {
|
||||
return this.controllers.subscriptionController.hasFirstPartyOnlineOrOfflineSubscription
|
||||
return this.subscriptionController.hasFirstPartyOnlineOrOfflineSubscription
|
||||
}
|
||||
|
||||
async openPurchaseFlow() {
|
||||
await this.controllers.purchaseFlowController.openPurchaseFlow()
|
||||
await this.purchaseFlowController.openPurchaseFlow()
|
||||
}
|
||||
|
||||
addNativeMobileEventListener = (listener: NativeMobileEventListener) => {
|
||||
@@ -529,11 +491,11 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
}
|
||||
|
||||
showAccountMenu(): void {
|
||||
this.controllers.accountMenuController.setShow(true)
|
||||
this.accountMenuController.setShow(true)
|
||||
}
|
||||
|
||||
hideAccountMenu(): void {
|
||||
this.controllers.accountMenuController.setShow(false)
|
||||
this.accountMenuController.setShow(false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,13 +507,158 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
||||
}
|
||||
|
||||
openPreferences(pane?: PreferenceId): void {
|
||||
this.controllers.preferencesController.openPreferences()
|
||||
this.preferencesController.openPreferences()
|
||||
if (pane) {
|
||||
this.controllers.preferencesController.setCurrentPane(pane)
|
||||
this.preferencesController.setCurrentPane(pane)
|
||||
}
|
||||
}
|
||||
|
||||
generateUUID(): string {
|
||||
return this.options.crypto.generateUUID()
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependency
|
||||
* Accessors
|
||||
*/
|
||||
|
||||
get routeService(): RouteServiceInterface {
|
||||
return this.deps.get<RouteServiceInterface>(Web_TYPES.RouteService)
|
||||
}
|
||||
|
||||
get androidBackHandler(): AndroidBackHandler {
|
||||
return this.deps.get<AndroidBackHandler>(Web_TYPES.AndroidBackHandler)
|
||||
}
|
||||
|
||||
get vaultDisplayService(): VaultDisplayServiceInterface {
|
||||
return this.deps.get<VaultDisplayServiceInterface>(Web_TYPES.VaultDisplayService)
|
||||
}
|
||||
|
||||
get desktopManager(): DesktopManagerInterface | undefined {
|
||||
return this.deps.get<DesktopManagerInterface | undefined>(Web_TYPES.DesktopManager)
|
||||
}
|
||||
|
||||
get autolockService(): AutolockService | undefined {
|
||||
return this.deps.get<AutolockService | undefined>(Web_TYPES.AutolockService)
|
||||
}
|
||||
|
||||
get archiveService(): ArchiveManager {
|
||||
return this.deps.get<ArchiveManager>(Web_TYPES.ArchiveManager)
|
||||
}
|
||||
|
||||
get paneController(): PaneController {
|
||||
return this.deps.get<PaneController>(Web_TYPES.PaneController)
|
||||
}
|
||||
|
||||
get linkingController(): LinkingController {
|
||||
return this.deps.get<LinkingController>(Web_TYPES.LinkingController)
|
||||
}
|
||||
|
||||
get changelogService(): ChangelogService {
|
||||
return this.deps.get<ChangelogService>(Web_TYPES.ChangelogService)
|
||||
}
|
||||
|
||||
get momentsService(): MomentsService {
|
||||
return this.deps.get<MomentsService>(Web_TYPES.MomentsService)
|
||||
}
|
||||
|
||||
get themeManager(): ThemeManager {
|
||||
return this.deps.get<ThemeManager>(Web_TYPES.ThemeManager)
|
||||
}
|
||||
|
||||
get keyboardService(): KeyboardService {
|
||||
return this.deps.get<KeyboardService>(Web_TYPES.KeyboardService)
|
||||
}
|
||||
|
||||
get featuresController(): FeaturesController {
|
||||
return this.deps.get<FeaturesController>(Web_TYPES.FeaturesController)
|
||||
}
|
||||
|
||||
get filesController(): FilesController {
|
||||
return this.deps.get<FilesController>(Web_TYPES.FilesController)
|
||||
}
|
||||
|
||||
get filePreviewModalController(): FilePreviewModalController {
|
||||
return this.deps.get<FilePreviewModalController>(Web_TYPES.FilePreviewModalController)
|
||||
}
|
||||
|
||||
get notesController(): NotesController {
|
||||
return this.deps.get<NotesController>(Web_TYPES.NotesController)
|
||||
}
|
||||
|
||||
get importModalController(): ImportModalController {
|
||||
return this.deps.get<ImportModalController>(Web_TYPES.ImportModalController)
|
||||
}
|
||||
|
||||
get navigationController(): NavigationController {
|
||||
return this.deps.get<NavigationController>(Web_TYPES.NavigationController)
|
||||
}
|
||||
|
||||
get historyModalController(): HistoryModalController {
|
||||
return this.deps.get<HistoryModalController>(Web_TYPES.HistoryModalController)
|
||||
}
|
||||
|
||||
get syncStatusController(): SyncStatusController {
|
||||
return this.deps.get<SyncStatusController>(Web_TYPES.SyncStatusController)
|
||||
}
|
||||
|
||||
get itemListController(): ItemListController {
|
||||
return this.deps.get<ItemListController>(Web_TYPES.ItemListController)
|
||||
}
|
||||
|
||||
get importer(): Importer {
|
||||
return this.deps.get<Importer>(Web_TYPES.Importer)
|
||||
}
|
||||
|
||||
get subscriptionController(): SubscriptionController {
|
||||
return this.deps.get<SubscriptionController>(Web_TYPES.SubscriptionController)
|
||||
}
|
||||
|
||||
get purchaseFlowController(): PurchaseFlowController {
|
||||
return this.deps.get<PurchaseFlowController>(Web_TYPES.PurchaseFlowController)
|
||||
}
|
||||
|
||||
get quickSettingsMenuController(): QuickSettingsController {
|
||||
return this.deps.get<QuickSettingsController>(Web_TYPES.QuickSettingsController)
|
||||
}
|
||||
|
||||
get persistence(): PersistenceService {
|
||||
return this.deps.get<PersistenceService>(Web_TYPES.PersistenceService)
|
||||
}
|
||||
|
||||
get itemControllerGroup(): ItemGroupController {
|
||||
return this.deps.get<ItemGroupController>(Web_TYPES.ItemGroupController)
|
||||
}
|
||||
|
||||
get noAccountWarningController(): NoAccountWarningController {
|
||||
return this.deps.get<NoAccountWarningController>(Web_TYPES.NoAccountWarningController)
|
||||
}
|
||||
|
||||
get searchOptionsController(): SearchOptionsController {
|
||||
return this.deps.get<SearchOptionsController>(Web_TYPES.SearchOptionsController)
|
||||
}
|
||||
|
||||
get vaultSelectionController(): VaultSelectionMenuController {
|
||||
return this.deps.get<VaultSelectionMenuController>(Web_TYPES.VaultSelectionMenuController)
|
||||
}
|
||||
|
||||
get openSubscriptionDashboard(): OpenSubscriptionDashboard {
|
||||
return this.deps.get<OpenSubscriptionDashboard>(Web_TYPES.OpenSubscriptionDashboard)
|
||||
}
|
||||
|
||||
get mobileWebReceiver(): MobileWebReceiver | undefined {
|
||||
return this.deps.get<MobileWebReceiver | undefined>(Web_TYPES.MobileWebReceiver)
|
||||
}
|
||||
|
||||
get accountMenuController(): AccountMenuController {
|
||||
return this.deps.get<AccountMenuController>(Web_TYPES.AccountMenuController)
|
||||
}
|
||||
|
||||
get preferencesController(): PreferencesController {
|
||||
return this.deps.get<PreferencesController>(Web_TYPES.PreferencesController)
|
||||
}
|
||||
|
||||
get isNativeMobileWebUseCase(): IsNativeMobileWeb {
|
||||
return this.deps.get<IsNativeMobileWeb>(Web_TYPES.IsNativeMobileWeb)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export class WebApplicationGroup extends SNApplicationGroup<WebOrDesktopDevice>
|
||||
})
|
||||
|
||||
if (isDesktopApplication()) {
|
||||
window.webClient = (this.primaryApplication as WebApplication).getDesktopService()
|
||||
window.webClient = (this.primaryApplication as WebApplication).desktopManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
|
||||
import { DesktopManager } from './Device/DesktopManager'
|
||||
import {
|
||||
ArchiveManager,
|
||||
AutolockService,
|
||||
ChangelogServiceInterface,
|
||||
KeyboardService,
|
||||
ThemeManager,
|
||||
VaultDisplayServiceInterface,
|
||||
} from '@standardnotes/ui-services'
|
||||
import { MomentsService } from '@/Controllers/Moments/MomentsService'
|
||||
|
||||
export type WebServices = {
|
||||
viewControllerManager: ViewControllerManager
|
||||
desktopService?: DesktopManager
|
||||
autolockService?: AutolockService
|
||||
archiveService: ArchiveManager
|
||||
themeService: ThemeManager
|
||||
keyboardService: KeyboardService
|
||||
changelogService: ChangelogServiceInterface
|
||||
momentsService: MomentsService
|
||||
vaultDisplayService: VaultDisplayServiceInterface
|
||||
}
|
||||
Reference in New Issue
Block a user