refactor(web): dependency management (#2386)

This commit is contained in:
Mo
2023-08-05 12:48:39 -05:00
committed by GitHub
parent b07da5b663
commit d8d4052a52
274 changed files with 4065 additions and 3873 deletions

View File

@@ -15,39 +15,23 @@ import Vaults from './Panes/Vaults/Vaults'
const PaneSelector: FunctionComponent<PreferencesProps & { menu: PreferencesSessionController }> = ({
menu,
viewControllerManager,
application,
mfaProvider,
userProvider,
}) => {
switch (menu.selectedPaneId) {
case 'general':
return (
<General
viewControllerManager={viewControllerManager}
application={application}
extensionsLatestVersions={menu.extensionsLatestVersions}
/>
)
return <General application={application} extensionsLatestVersions={menu.extensionsLatestVersions} />
case 'account':
return <AccountPreferences application={application} viewControllerManager={viewControllerManager} />
return <AccountPreferences application={application} />
case 'appearance':
return <Appearance application={application} />
case 'home-server':
return <HomeServer />
case 'security':
return (
<Security
mfaProvider={mfaProvider}
userProvider={userProvider}
viewControllerManager={viewControllerManager}
application={application}
/>
)
return <Security application={application} />
case 'vaults':
return <Vaults />
case 'backups':
return <Backups application={application} viewControllerManager={viewControllerManager} />
return <Backups application={application} />
case 'listed':
return <Listed application={application} />
case 'shortcuts':
@@ -61,13 +45,7 @@ const PaneSelector: FunctionComponent<PreferencesProps & { menu: PreferencesSess
case 'whats-new':
return <WhatsNew application={application} />
default:
return (
<General
viewControllerManager={viewControllerManager}
application={application}
extensionsLatestVersions={menu.extensionsLatestVersions}
/>
)
return <General application={application} extensionsLatestVersions={menu.extensionsLatestVersions} />
}
}

View File

@@ -1,7 +1,6 @@
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import Authentication from './Authentication'
import Credentials from './Credentials'
import Sync from './Sync'
@@ -15,30 +14,29 @@ import DeleteAccount from '@/Components/Preferences/Panes/Account/DeleteAccount'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const AccountPreferences = ({ application, viewControllerManager }: Props) => {
const AccountPreferences = ({ application }: Props) => {
const isUsingThirdPartyServer = application.isThirdPartyHostUsed()
return (
<PreferencesPane>
{!application.hasAccount() ? (
<Authentication application={application} viewControllerManager={viewControllerManager} />
<Authentication application={application} />
) : (
<>
<Credentials application={application} viewControllerManager={viewControllerManager} />
<Credentials application={application} />
<Sync application={application} />
</>
)}
<Subscription />
<SubscriptionSharing application={application} viewControllerManager={viewControllerManager} />
{application.hasAccount() && viewControllerManager.featuresController.entitledToFiles && (
<SubscriptionSharing application={application} />
{application.hasAccount() && application.featuresController.entitledToFiles && (
<FilesSection application={application} />
)}
{application.hasAccount() && !isUsingThirdPartyServer && <Email application={application} />}
<SignOutWrapper application={application} viewControllerManager={viewControllerManager} />
<DeleteAccount application={application} viewControllerManager={viewControllerManager} />
<SignOutWrapper application={application} />
<DeleteAccount application={application} />
</PreferencesPane>
)
}

View File

@@ -1,7 +1,6 @@
import Button from '@/Components/Button/Button'
import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { AccountIllustration } from '@standardnotes/icons'
@@ -11,20 +10,19 @@ import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const Authentication: FunctionComponent<Props> = ({ viewControllerManager }) => {
const Authentication: FunctionComponent<Props> = ({ application }) => {
const clickSignIn = () => {
viewControllerManager.preferencesController.closePreferences()
viewControllerManager.accountMenuController.setCurrentPane(AccountMenuPane.SignIn)
viewControllerManager.accountMenuController.setShow(true)
application.preferencesController.closePreferences()
application.accountMenuController.setCurrentPane(AccountMenuPane.SignIn)
application.accountMenuController.setShow(true)
}
const clickRegister = () => {
viewControllerManager.preferencesController.closePreferences()
viewControllerManager.accountMenuController.setCurrentPane(AccountMenuPane.Register)
viewControllerManager.accountMenuController.setShow(true)
application.preferencesController.closePreferences()
application.accountMenuController.setCurrentPane(AccountMenuPane.Register)
application.accountMenuController.setShow(true)
}
return (

View File

@@ -1,14 +1,14 @@
import Button from '@/Components/Button/Button'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { Title, Text } from '../../PreferencesComponents/Content'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
import { useApplication } from '@/Components/ApplicationProvider'
const ClearSessionDataView: FunctionComponent = () => {
const application = useApplication()
const ClearSessionDataView: FunctionComponent<{
viewControllerManager: ViewControllerManager
}> = ({ viewControllerManager }) => {
return (
<PreferencesGroup>
<PreferencesSegment>
@@ -18,7 +18,7 @@ const ClearSessionDataView: FunctionComponent<{
colorStyle="danger"
label="Clear workspace"
onClick={() => {
viewControllerManager.accountMenuController.setSigningOut(true)
application.accountMenuController.setSigningOut(true)
}}
/>
</PreferencesSegment>

View File

@@ -6,7 +6,6 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import { dateToLocalizedString } from '@standardnotes/snjs'
import { useCallback, useState, FunctionComponent } from 'react'
import ChangeEmail from '@/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import PasswordWizard from '@/Components/PasswordWizard/PasswordWizard'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
@@ -14,14 +13,13 @@ import ModalOverlay from '@/Components/Modal/ModalOverlay'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const Credentials: FunctionComponent<Props> = ({ application }: Props) => {
const [isChangeEmailDialogOpen, setIsChangeEmailDialogOpen] = useState(false)
const [shouldShowPasswordWizard, setShouldShowPasswordWizard] = useState(false)
const user = application.getUser()
const user = application.sessions.getUser()
const passwordCreatedAtTimestamp = application.getUserPasswordCreationDate() as Date
const passwordCreatedOn = dateToLocalizedString(passwordCreatedAtTimestamp)

View File

@@ -3,15 +3,13 @@ import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/P
import { Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import { ViewControllerManager } from '@Controllers/ViewControllerManager'
import { WebApplication } from '@/Application/WebApplication'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const DeleteAccount = ({ application, viewControllerManager }: Props) => {
const DeleteAccount = ({ application }: Props) => {
if (!application.hasAccount()) {
return null
}
@@ -25,7 +23,7 @@ const DeleteAccount = ({ application, viewControllerManager }: Props) => {
colorStyle="danger"
label="Delete my account"
onClick={() => {
viewControllerManager.accountMenuController.setDeletingAccount(true)
application.accountMenuController.setDeletingAccount(true)
}}
/>
</div>

View File

@@ -43,7 +43,7 @@ const Email: FunctionComponent<Props> = ({ application }: Props) => {
}
const loadSettings = useCallback(async () => {
if (!application.getUser()) {
if (!application.sessions.getUser()) {
return
}
setIsLoading(true)

View File

@@ -2,7 +2,6 @@ import Button from '@/Components/Button/Button'
import OtherSessionsSignOutContainer from '@/Components/OtherSessionsSignOut/OtherSessionsSignOut'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { Subtitle, Title, Text } from '../../PreferencesComponents/Content'
@@ -12,10 +11,9 @@ import ClearSessionDataView from './ClearSessionDataView'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const SignOutView: FunctionComponent<Props> = observer(({ application, viewControllerManager }) => {
const SignOutView: FunctionComponent<Props> = observer(({ application }) => {
return (
<>
<PreferencesGroup>
@@ -27,10 +25,10 @@ const SignOutView: FunctionComponent<Props> = observer(({ application, viewContr
<Button
label="Sign out other sessions"
onClick={() => {
viewControllerManager.accountMenuController.setOtherSessionsSignOut(true)
application.accountMenuController.setOtherSessionsSignOut(true)
}}
/>
<Button label="Manage sessions" onClick={() => viewControllerManager.openSessionsModal()} />
<Button label="Manage sessions" onClick={() => application.openSessionsModal()} />
</div>
</PreferencesSegment>
<HorizontalSeparator classes="my-4" />
@@ -42,23 +40,23 @@ const SignOutView: FunctionComponent<Props> = observer(({ application, viewContr
colorStyle="danger"
label="Sign out workspace"
onClick={() => {
viewControllerManager.accountMenuController.setSigningOut(true)
application.accountMenuController.setSigningOut(true)
}}
/>
</PreferencesSegment>
</PreferencesGroup>
<OtherSessionsSignOutContainer viewControllerManager={viewControllerManager} application={application} />
<OtherSessionsSignOutContainer application={application} />
</>
)
})
SignOutView.displayName = 'SignOutView'
const SignOutWrapper: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
const SignOutWrapper: FunctionComponent<Props> = ({ application }) => {
if (!application.hasAccount()) {
return <ClearSessionDataView viewControllerManager={viewControllerManager} />
return <ClearSessionDataView />
}
return <SignOutView viewControllerManager={viewControllerManager} application={application} />
return <SignOutView application={application} />
}
export default observer(SignOutWrapper)

View File

@@ -12,16 +12,16 @@ const Subscription: FunctionComponent = () => {
const application = useApplication()
const [onlineSubscription, setOnlineSubscription] = useState<Subscription | undefined>(
application.controllers.subscriptionController.onlineSubscription,
application.subscriptionController.onlineSubscription,
)
useEffect(() => {
return application.subscriptions.addEventObserver((event) => {
if (event === SubscriptionManagerEvent.DidFetchSubscription) {
setOnlineSubscription(application.controllers.subscriptionController.onlineSubscription)
setOnlineSubscription(application.subscriptionController.onlineSubscription)
}
})
}, [application.subscriptions, application.controllers.subscriptionController])
}, [application.subscriptions, application.subscriptionController])
useEffect(() => {
void application.subscriptions.fetchOnlineSubscription()

View File

@@ -1,6 +1,5 @@
import { observer } from 'mobx-react-lite'
import Button from '@/Components/Button/Button'
import { openSubscriptionDashboard } from '@/Utils/ManageSubscription'
import SubscriptionStatusText from './SubscriptionStatusText'
import { useApplication } from '@/Components/ApplicationProvider'
@@ -8,7 +7,7 @@ const SubscriptionInformation = () => {
const application = useApplication()
const manageSubscription = async () => {
void openSubscriptionDashboard(application)
void application.openSubscriptionDashboard.execute()
}
return (

View File

@@ -1,10 +1,8 @@
import { FeatureStatus, NativeFeatureIdentifier } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useState } from 'react'
import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
@@ -18,13 +16,12 @@ import ModalOverlay from '@/Components/Modal/ModalOverlay'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const SubscriptionSharing: FunctionComponent<Props> = ({ application, viewControllerManager }: Props) => {
const SubscriptionSharing: FunctionComponent<Props> = ({ application }: Props) => {
const [isInviteDialogOpen, setIsInviteDialogOpen] = useState(false)
const subscriptionState = viewControllerManager.subscriptionController
const subscriptionState = application.subscriptionController
const isReadOnlySession = application.sessions.isCurrentSessionReadOnly()

View File

@@ -1,5 +1,4 @@
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { FunctionComponent } from 'react'
import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane'
import DataBackups from './DataBackups'
@@ -10,16 +9,15 @@ import TextBackupsCrossPlatform from './TextBackups/TextBackupsCrossPlatform'
import PlaintextBackupsCrossPlatform from './PlaintextBackups/PlaintextBackupsCrossPlatform'
type Props = {
viewControllerManager: ViewControllerManager
application: WebApplication
}
const Backups: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
const Backups: FunctionComponent<Props> = ({ application }) => {
const isUsingThirdPartyServer = application.isThirdPartyHostUsed()
return (
<PreferencesPane>
<DataBackups application={application} viewControllerManager={viewControllerManager} />
<DataBackups application={application} />
<TextBackupsCrossPlatform application={application} />
<PlaintextBackupsCrossPlatform />
<FileBackupsCrossPlatform application={application} />

View File

@@ -12,7 +12,6 @@ import {
import { BackupFile } from '@standardnotes/snjs'
import { ChangeEventHandler, MouseEventHandler, useCallback, useEffect, useRef, useState } from 'react'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { Title, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
@@ -24,10 +23,9 @@ import { downloadOrShareBlobBasedOnPlatform } from '@/Utils/DownloadOrShareBased
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const DataBackups = ({ application, viewControllerManager }: Props) => {
const DataBackups = ({ application }: Props) => {
const fileInputRef = useRef<HTMLInputElement>(null)
const [isImportDataLoading, setIsImportDataLoading] = useState(false)
const {
@@ -36,7 +34,7 @@ const DataBackups = ({ application, viewControllerManager }: Props) => {
setIsBackupEncrypted,
setIsEncryptionEnabled,
setEncryptionStatusString,
} = viewControllerManager.accountMenuController
} = application.accountMenuController
const refreshEncryptionStatus = useCallback(() => {
const hasUser = application.hasAccount()
@@ -73,16 +71,30 @@ const DataBackups = ({ application, viewControllerManager }: Props) => {
})
if (isBackupEncrypted) {
const filename = `Standard Notes Encrypted Backup and Import File - ${application
.getArchiveService()
.formattedDateForExports()}`
const filename = `Standard Notes Encrypted Backup and Import File - ${application.archiveService.formattedDateForExports()}`
const sanitizedFilename = sanitizeFileName(filename) + '.txt'
void downloadOrShareBlobBasedOnPlatform(application, blobData, sanitizedFilename)
void downloadOrShareBlobBasedOnPlatform({
archiveService: application.archiveService,
platform: application.platform,
mobileDevice: application.mobileDevice,
blob: blobData,
filename: sanitizedFilename,
isNativeMobileWeb: application.isNativeMobileWeb(),
showToastOnAndroid: undefined,
})
} else {
const zippedDecryptedItemsBlob = await application.getArchiveService().getZippedDecryptedItemsBlob(data)
const filename = `Standard Notes Backup - ${application.getArchiveService().formattedDateForExports()}`
const zippedDecryptedItemsBlob = await application.archiveService.getZippedDecryptedItemsBlob(data)
const filename = `Standard Notes Backup - ${application.archiveService.formattedDateForExports()}`
const sanitizedFilename = sanitizeFileName(filename) + '.zip'
void downloadOrShareBlobBasedOnPlatform(application, zippedDecryptedItemsBlob, sanitizedFilename)
void downloadOrShareBlobBasedOnPlatform({
archiveService: application.archiveService,
platform: application.platform,
mobileDevice: application.mobileDevice,
blob: zippedDecryptedItemsBlob,
filename: sanitizedFilename,
isNativeMobileWeb: application.isNativeMobileWeb(),
showToastOnAndroid: undefined,
})
}
}

View File

@@ -25,7 +25,7 @@ const EmailBackups = ({ application }: Props) => {
const hasAccount = application.hasAccount()
const loadEmailFrequencySetting = useCallback(async () => {
if (!application.getUser()) {
if (!application.sessions.getUser()) {
return
}
setIsLoading(true)

View File

@@ -41,7 +41,7 @@ const TextBackupsDesktop = ({ backupsService }: Props) => {
}, [backupsEnabled, backupsService])
const performBackup = useCallback(async () => {
void application.getDesktopService()?.saveDesktopBackup()
void application.desktopManager?.saveDesktopBackup()
}, [application])
return (

View File

@@ -2,7 +2,6 @@ import { FunctionComponent } from 'react'
import OfflineSubscription from '@/Components/Preferences/Panes/General/Advanced/OfflineSubscription'
import { WebApplication } from '@/Application/WebApplication'
import { observer } from 'mobx-react-lite'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import PackagesPreferencesSection from '@/Components/Preferences/Panes/General/Advanced/Packages/Section'
import { PackageProvider } from '@/Components/Preferences/Panes/General/Advanced/Packages/Provider/PackageProvider'
import AccordionItem from '@/Components/Shared/AccordionItem'
@@ -11,18 +10,17 @@ import PreferencesSegment from '../../../PreferencesComponents/PreferencesSegmen
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
extensionsLatestVersions: PackageProvider
}
const Advanced: FunctionComponent<Props> = ({ application, viewControllerManager, extensionsLatestVersions }) => {
const Advanced: FunctionComponent<Props> = ({ application, extensionsLatestVersions }) => {
return (
<PreferencesGroup>
<PreferencesSegment>
<AccordionItem title={'Advanced options'}>
<div className="flex flex-row items-center">
<div className="flex max-w-full flex-grow flex-col">
<OfflineSubscription application={application} viewControllerManager={viewControllerManager} />
<OfflineSubscription application={application} />
<PackagesPreferencesSection
className={'mt-3'}
application={application}

View File

@@ -3,7 +3,6 @@ import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content
import DecoratedInput from '@/Components/Input/DecoratedInput'
import Button from '@/Components/Button/Button'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { STRING_REMOVE_OFFLINE_KEY_CONFIRMATION } from '@/Constants/Strings'
import { ButtonType, ClientDisplayableError } from '@standardnotes/snjs'
@@ -11,7 +10,6 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
onSuccess?: () => void
}
@@ -46,7 +44,7 @@ const OfflineSubscription: FunctionComponent<Props> = ({ application, onSuccess
return
}
const signedInUser = application.getUser()
const signedInUser = application.sessions.getUser()
if (!signedInUser) {
return
}

View File

@@ -34,12 +34,12 @@ const PackageEntry: FunctionComponent<PackageEntryProps> = ({ application, exten
const toggleOfflineOnly = () => {
const newOfflineOnly = !offlineOnly
setOfflineOnly(newOfflineOnly)
application
.changeAndSaveItem<ComponentMutator>(extension, (mutator) => {
application.changeAndSaveItem
.execute<ComponentMutator>(extension, (mutator) => {
mutator.offlineOnly = newOfflineOnly
})
.then((item) => {
const component = item as ComponentInterface
.then((result) => {
const component = result.getValue() as ComponentInterface
setOfflineOnly(component.offlineOnly)
})
.catch((e) => {
@@ -49,12 +49,12 @@ const PackageEntry: FunctionComponent<PackageEntryProps> = ({ application, exten
const changeExtensionName = (newName: string) => {
setExtensionName(newName)
application
.changeAndSaveItem<ComponentMutator>(extension, (mutator) => {
application.changeAndSaveItem
.execute<ComponentMutator>(extension, (mutator) => {
mutator.name = newName
})
.then((item) => {
const component = item as ComponentInterface
.then((result) => {
const component = result.getValue() as ComponentInterface
setExtensionName(component.name)
})
.catch(console.error)

View File

@@ -1,5 +1,4 @@
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { FunctionComponent } from 'react'
import { PackageProvider } from '@/Components/Preferences/Panes/General/Advanced/Packages/Provider/PackageProvider'
import { observer } from 'mobx-react-lite'
@@ -13,24 +12,19 @@ import SmartViews from './SmartViews/SmartViews'
import Moments from './Moments'
type Props = {
viewControllerManager: ViewControllerManager
application: WebApplication
extensionsLatestVersions: PackageProvider
}
const General: FunctionComponent<Props> = ({ viewControllerManager, application, extensionsLatestVersions }) => (
const General: FunctionComponent<Props> = ({ application, extensionsLatestVersions }) => (
<PreferencesPane>
<Persistence application={application} />
<Defaults application={application} />
<Tools application={application} />
<SmartViews application={application} featuresController={viewControllerManager.featuresController} />
<SmartViews application={application} featuresController={application.featuresController} />
<Moments application={application} />
<LabsPane application={application} />
<Advanced
application={application}
viewControllerManager={viewControllerManager}
extensionsLatestVersions={extensionsLatestVersions}
/>
<Advanced application={application} extensionsLatestVersions={extensionsLatestVersions} />
</PreferencesPane>
)

View File

@@ -21,9 +21,9 @@ const Persistence = ({ application }: Props) => {
setShouldPersistNoteState(shouldPersist)
if (shouldPersist) {
application.controllers.persistValues()
application.persistence.persistCurrentState()
} else {
application.controllers.clearPersistedValues()
application.persistence.clearPersistedValues()
}
}

View File

@@ -88,7 +88,7 @@ export class EditSmartViewModalController {
this.setIsSaving(true)
await this.application.changeAndSaveItem<SmartViewMutator>(this.view, (mutator) => {
await this.application.changeAndSaveItem.execute<SmartViewMutator>(this.view, (mutator) => {
mutator.title = this.title
mutator.iconString = (this.icon as string) || SmartViewDefaultIconName
mutator.predicate = JSON.parse(this.predicateJson) as PredicateJsonForm

View File

@@ -33,7 +33,7 @@ const SmartViews = ({ application, featuresController }: Props) => {
)
useEffect(() => {
const disposeItemStream = application.streamItems([ContentType.TYPES.SmartView], () => {
const disposeItemStream = application.items.streamItems([ContentType.TYPES.SmartView], () => {
setSmartViews(application.items.getSmartViews().filter((view) => !isSystemView(view)))
})

View File

@@ -9,7 +9,7 @@ import { MouseEventHandler } from 'react'
const HelpAndFeedback = ({ application }: { application: WebApplication }) => {
const openLinkOnMobile = (link: string) => {
if (application.isNativeMobileWeb()) {
application.mobileDevice().openUrl(link)
application.mobileDevice.openUrl(link)
}
}

View File

@@ -25,7 +25,6 @@ const HomeServerSettings = () => {
const homeServerService = application.homeServer as HomeServerServiceInterface
const featuresService = application.features
const sessionsService = application.sessions
const viewControllerManager = application.controllers
const logsTextarea = useRef<HTMLTextAreaElement>(null)
@@ -392,7 +391,6 @@ const HomeServerSettings = () => {
{showOfflineSubscriptionActivation && (
<OfflineSubscription
application={application}
viewControllerManager={viewControllerManager}
onSuccess={() => {
setIsAPremiumUser(true)
setShowOfflineSubscriptionActivation(false)

View File

@@ -39,7 +39,7 @@ const StatusIndicator = ({ status, className, homeServerService }: Props) => {
useEffect(() => {
async function updateSignedInStatus() {
const signedInUser = application.getUser()
const signedInUser = application.sessions.getUser()
if (signedInUser) {
const isUsingHomeServer = await application.isUsingHomeServer()
if (isUsingHomeServer) {

View File

@@ -84,13 +84,14 @@ const Listed = ({ application }: Props) => {
<Subtitle>What is Listed?</Subtitle>
<Text>
Listed is a free blogging platform that allows you to create a public journal published directly from your
notes. {!application.getUser() && 'To get started, sign in or register for a Standard Notes account.'}
notes.{' '}
{!application.sessions.getUser() && 'To get started, sign in or register for a Standard Notes account.'}
</Text>
<a className="mt-2 text-info" target="_blank" href="https://listed.to" rel="noreferrer noopener">
Learn more
</a>
</PreferencesSegment>
{application.getUser() && (
{application.sessions.getUser() && (
<>
<HorizontalSeparator classes="my-4" />
<PreferencesSegment>

View File

@@ -1,16 +1,15 @@
import { STRING_E2E_ENABLED, STRING_ENC_NOT_ENABLED, STRING_LOCAL_ENC_ENABLED } from '@/Constants/Strings'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { Title, Text } from '../../PreferencesComponents/Content'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
import EncryptionEnabled from './EncryptionEnabled'
import { useApplication } from '@/Components/ApplicationProvider'
type Props = { viewControllerManager: ViewControllerManager }
const Encryption: FunctionComponent = () => {
const app = useApplication()
const Encryption: FunctionComponent<Props> = ({ viewControllerManager }) => {
const app = viewControllerManager.application
const hasUser = app.hasAccount()
const hasPasscode = app.hasPasscode()
const isEncryptionEnabled = app.isEncryptionAvailable()

View File

@@ -14,7 +14,7 @@ const ErroredItems: FunctionComponent = () => {
const [erroredItems, setErroredItems] = useState(application.items.invalidNonVaultedItems)
useEffect(() => {
return application.streamItems(ContentType.TYPES.Any, () => {
return application.items.streamItems(ContentType.TYPES.Any, () => {
setErroredItems(application.items.invalidNonVaultedItems)
})
}, [application])
@@ -83,7 +83,7 @@ const ErroredItems: FunctionComponent = () => {
className="mr-2 mt-3 min-w-20"
label="Export all"
onClick={() => {
void application.getArchiveService().downloadEncryptedItems(erroredItems)
void application.archiveService.downloadEncryptedItems(erroredItems)
}}
/>
<Button
@@ -117,7 +117,7 @@ const ErroredItems: FunctionComponent = () => {
className="mr-2 mt-3 min-w-20"
label="Export"
onClick={() => {
void application.getArchiveService().downloadEncryptedItem(item)
void application.archiveService.downloadEncryptedItem(item)
}}
/>
<Button

View File

@@ -1,12 +1,12 @@
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/Application/WebApplication'
import { isIOS } from '@/Utils'
import { useEffect, useState } from 'react'
import { MobileDeviceInterface } from '@standardnotes/services'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import { isIOS } from '@standardnotes/ui-services'
type Props = {
application: WebApplication

View File

@@ -14,7 +14,6 @@ import { alertDialog } from '@standardnotes/ui-services'
import { FormEvent, useCallback, useEffect, useRef, useState } from 'react'
import { ApplicationEvent, MobileUnlockTiming } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { Title, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
@@ -24,15 +23,13 @@ import { classNames } from '@standardnotes/utils'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
}
const PasscodeLock = ({ application, viewControllerManager }: Props) => {
const PasscodeLock = ({ application }: Props) => {
const isNativeMobileWeb = application.isNativeMobileWeb()
const keyStorageInfo = StringUtils.keyStorageInfo(application)
const { setIsEncryptionEnabled, setIsBackupEncrypted, setEncryptionStatusString } =
viewControllerManager.accountMenuController
const { setIsEncryptionEnabled, setIsBackupEncrypted, setEncryptionStatusString } = application.accountMenuController
const passcodeInputRef = useRef<HTMLInputElement>(null)
@@ -58,7 +55,7 @@ const PasscodeLock = ({ application, viewControllerManager }: Props) => {
}
const reloadDesktopAutoLockInterval = useCallback(async () => {
const interval = await application.getAutolockService()?.getAutoLockInterval()
const interval = await application.autolockService?.getAutoLockInterval()
setSelectedAutoLockInterval(interval)
}, [application])
@@ -86,7 +83,7 @@ const PasscodeLock = ({ application, viewControllerManager }: Props) => {
return
}
await application.getAutolockService()?.setAutoLockInterval(interval)
await application.autolockService?.setAutoLockInterval(interval)
reloadDesktopAutoLockInterval().catch(console.error)
}
@@ -99,7 +96,7 @@ const PasscodeLock = ({ application, viewControllerManager }: Props) => {
await preventRefreshing(STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, async () => {
if (await application.removePasscode()) {
if (!isNativeMobileWeb) {
await application.getAutolockService()?.deleteAutolockPreference()
await application.autolockService?.deleteAutolockPreference()
await reloadDesktopAutoLockInterval()
}
refreshEncryptionStatus()
@@ -184,7 +181,7 @@ const PasscodeLock = ({ application, viewControllerManager }: Props) => {
setPasscodeConfirmation(undefined)
}
const autolockService = application.getAutolockService()
const autolockService = application.autolockService
return (
<>

View File

@@ -30,7 +30,7 @@ const Privacy: FunctionComponent<Props> = ({ application }: Props) => {
}
const loadSettings = useCallback(async () => {
if (!application.getUser()) {
if (!application.sessions.getUser()) {
return
}
setIsLoading(true)

View File

@@ -1,7 +1,6 @@
import { NativeFeatureIdentifier, FeatureStatus } from '@standardnotes/snjs'
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { FunctionComponent } from 'react'
import TwoFactorAuthWrapper from './TwoFactorAuth/TwoFactorAuthWrapper'
import { MfaProps } from './TwoFactorAuth/MfaProps'
@@ -16,7 +15,6 @@ import MultitaskingPrivacy from '@/Components/Preferences/Panes/Security/Multita
import U2FWrapper from './U2F/U2FWrapper'
interface SecurityProps extends MfaProps {
viewControllerManager: ViewControllerManager
application: WebApplication
}
@@ -26,23 +24,19 @@ const Security: FunctionComponent<SecurityProps> = (props) => {
const isU2FFeatureAvailable =
props.application.features.getFeatureStatus(
NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.UniversalSecondFactor).getValue(),
) === FeatureStatus.Entitled && props.userProvider.getUser() !== undefined
) === FeatureStatus.Entitled && props.application.sessions.getUser() !== undefined
return (
<PreferencesPane>
<Encryption viewControllerManager={props.viewControllerManager} />
<Encryption />
{props.application.items.invalidNonVaultedItems.length > 0 && <ErroredItems />}
<Protections application={props.application} />
<TwoFactorAuthWrapper
mfaProvider={props.mfaProvider}
userProvider={props.userProvider}
application={props.application}
/>
{isU2FFeatureAvailable && <U2FWrapper userProvider={props.userProvider} application={props.application} />}
<TwoFactorAuthWrapper application={props.application} />
{isU2FFeatureAvailable && <U2FWrapper application={props.application} />}
{isNativeMobileWeb && <MultitaskingPrivacy application={props.application} />}
<PasscodeLock viewControllerManager={props.viewControllerManager} application={props.application} />
<PasscodeLock application={props.application} />
{isNativeMobileWeb && <BiometricsLock application={props.application} />}
{props.application.getUser() && <Privacy application={props.application} />}
{props.application.sessions.getUser() && <Privacy application={props.application} />}
</PreferencesPane>
)
}

View File

@@ -1,8 +1,5 @@
import { WebApplication } from '@/Application/WebApplication'
import { MfaProvider, UserProvider } from '@/Components/Preferences/Providers'
export interface MfaProps {
userProvider: UserProvider
mfaProvider: MfaProvider
application: WebApplication
}

View File

@@ -1,4 +1,4 @@
import { MfaProvider } from '@/Components/Preferences/Providers'
import { MfaServiceInterface } from '@standardnotes/snjs'
import { action, makeAutoObservable, observable } from 'mobx'
type ActivationStep = 'scan-qr-code' | 'save-secret-key' | 'verification' | 'success'
@@ -15,7 +15,7 @@ export class TwoFactorActivation {
private inputOtpToken = ''
constructor(
private mfaProvider: MfaProvider,
private mfa: MfaServiceInterface,
private readonly email: string,
private readonly _secretKey: string,
private _cancelActivation: () => void,
@@ -102,7 +102,7 @@ export class TwoFactorActivation {
return
}
this.mfaProvider
this.mfa
.enableMfa(this.inputSecretKey, this.inputOtpToken)
.then(
action(() => {

View File

@@ -1,6 +1,6 @@
import { MfaProvider, UserProvider } from '@/Components/Preferences/Providers'
import { action, makeAutoObservable, observable } from 'mobx'
import { TwoFactorActivation } from './TwoFactorActivation'
import { MfaServiceInterface, SessionsClientInterface } from '@standardnotes/snjs'
type TwoFactorStatus = 'two-factor-enabled' | TwoFactorActivation | 'two-factor-disabled'
@@ -17,8 +17,8 @@ export class TwoFactorAuth {
private _errorMessage: string | null
constructor(
private readonly mfaProvider: MfaProvider,
private readonly userProvider: UserProvider,
private readonly sessions: SessionsClientInterface,
private readonly mfa: MfaServiceInterface,
) {
this._errorMessage = null
@@ -40,13 +40,13 @@ export class TwoFactorAuth {
this._status = 'two-factor-enabled'
this.fetchStatus()
})
this.mfaProvider
this.mfa
.generateMfaSecret()
.then(
action((secret) => {
this._status = new TwoFactorActivation(
this.mfaProvider,
this.userProvider.getUser()?.email as string,
this.mfa,
this.sessions.getUser()?.email as string,
secret,
setDisabled,
setEnabled,
@@ -61,7 +61,7 @@ export class TwoFactorAuth {
}
private deactivate2FA(): void {
this.mfaProvider
this.mfa
.disableMfa()
.then(
action(() => {
@@ -76,7 +76,7 @@ export class TwoFactorAuth {
}
isLoggedIn(): boolean {
return this.userProvider.getUser() != undefined
return this.sessions.getUser() != undefined
}
fetchStatus(): void {
@@ -84,7 +84,7 @@ export class TwoFactorAuth {
return
}
this.mfaProvider
this.mfa
.isMfaActivated()
.then(
action((active) => {

View File

@@ -4,7 +4,7 @@ import { TwoFactorAuth } from './TwoFactorAuth'
import TwoFactorAuthView from './TwoFactorAuthView/TwoFactorAuthView'
const TwoFactorAuthWrapper: FunctionComponent<MfaProps> = (props) => {
const [auth] = useState(() => new TwoFactorAuth(props.mfaProvider, props.userProvider))
const [auth] = useState(() => new TwoFactorAuth(props.application.sessions, props.application.mfa))
auth.fetchStatus()
return <TwoFactorAuthView auth={auth} application={props.application} />
}

View File

@@ -3,23 +3,19 @@ import { observer } from 'mobx-react-lite'
import { AddAuthenticator } from '@standardnotes/snjs'
import DecoratedInput from '@/Components/Input/DecoratedInput'
import { UserProvider } from '@/Components/Preferences/Providers'
import Modal from '@/Components/Modal/Modal'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import { useApplication } from '@/Components/ApplicationProvider'
type Props = {
userProvider: UserProvider
addAuthenticator: AddAuthenticator
onDeviceAddingModalToggle: (show: boolean) => void
onDeviceAdded: () => Promise<void>
}
const U2FAddDeviceView: FunctionComponent<Props> = ({
userProvider,
addAuthenticator,
onDeviceAddingModalToggle,
onDeviceAdded,
}) => {
const U2FAddDeviceView: FunctionComponent<Props> = ({ addAuthenticator, onDeviceAddingModalToggle, onDeviceAdded }) => {
const application = useApplication()
const [deviceName, setDeviceName] = useState('')
const [errorMessage, setErrorMessage] = useState('')
@@ -33,7 +29,7 @@ const U2FAddDeviceView: FunctionComponent<Props> = ({
return
}
const user = userProvider.getUser()
const user = application.sessions.getUser()
if (user === undefined) {
setErrorMessage('User not found')
return
@@ -50,7 +46,7 @@ const U2FAddDeviceView: FunctionComponent<Props> = ({
onDeviceAddingModalToggle(false)
await onDeviceAdded()
}, [deviceName, setErrorMessage, userProvider, addAuthenticator, onDeviceAddingModalToggle, onDeviceAdded])
}, [deviceName, setErrorMessage, application, addAuthenticator, onDeviceAddingModalToggle, onDeviceAdded])
const closeModal = () => {
onDeviceAddingModalToggle(false)

View File

@@ -1,7 +1,5 @@
import { WebApplication } from '@/Application/WebApplication'
import { UserProvider } from '@/Components/Preferences/Providers'
export interface U2FProps {
userProvider: UserProvider
application: WebApplication
}

View File

@@ -2,17 +2,12 @@ import { FunctionComponent } from 'react'
import { observer } from 'mobx-react-lite'
import { Text } from '@/Components/Preferences/PreferencesComponents/Content'
import { UserProvider } from '@/Components/Preferences/Providers'
import { useApplication } from '@/Components/ApplicationProvider'
type Props = {
userProvider: UserProvider
}
const U2FDescription: FunctionComponent<Props> = ({ userProvider }) => {
const U2FDescription: FunctionComponent = () => {
const application = useApplication()
if (userProvider.getUser() === undefined) {
if (application.sessions.getUser() === undefined) {
return <Text>Sign in or register for an account to configure hardware security keys.</Text>
}

View File

@@ -2,14 +2,12 @@ import { FunctionComponent } from 'react'
import { observer } from 'mobx-react-lite'
import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { UserProvider } from '@/Components/Preferences/Providers'
import { useApplication } from '@/Components/ApplicationProvider'
type Props = {
userProvider: UserProvider
}
const U2FTitle: FunctionComponent = () => {
const application = useApplication()
const U2FTitle: FunctionComponent<Props> = ({ userProvider }) => {
if (userProvider.getUser() === undefined) {
if (application.sessions.getUser() === undefined) {
return <Title>Hardware security key authentication not available</Title>
}

View File

@@ -4,7 +4,6 @@ import { observer } from 'mobx-react-lite'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
import { WebApplication } from '@/Application/WebApplication'
import { UserProvider } from '@/Components/Preferences/Providers'
import U2FTitle from './U2FTitle'
import U2FDescription from './U2FDescription'
@@ -16,10 +15,9 @@ import RecoveryCodeBanner from '@/Components/RecoveryCodeBanner/RecoveryCodeBann
type Props = {
application: WebApplication
userProvider: UserProvider
}
const U2FView: FunctionComponent<Props> = ({ application, userProvider }) => {
const U2FView: FunctionComponent<Props> = ({ application }) => {
const [showDeviceAddingModal, setShowDeviceAddingModal] = useState(false)
const [devices, setDevices] = useState<Array<{ id: string; name: string }>>([])
const [error, setError] = useState('')
@@ -48,8 +46,8 @@ const U2FView: FunctionComponent<Props> = ({ application, userProvider }) => {
<PreferencesGroup>
<PreferencesSegment>
<div className="flex flex-col">
<U2FTitle userProvider={userProvider} />
<U2FDescription userProvider={userProvider} />
<U2FTitle />
<U2FDescription />
</div>
</PreferencesSegment>
<PreferencesSegment classes="mt-2">
@@ -80,7 +78,6 @@ const U2FView: FunctionComponent<Props> = ({ application, userProvider }) => {
<U2FAddDeviceView
onDeviceAddingModalToggle={setShowDeviceAddingModal}
onDeviceAdded={loadAuthenticatorDevices}
userProvider={userProvider}
addAuthenticator={application.addAuthenticator}
/>
</ModalOverlay>

View File

@@ -4,7 +4,7 @@ import { U2FProps } from './U2FProps'
import U2FView from './U2FView/U2FView'
const U2FWrapper: FunctionComponent<U2FProps> = (props) => {
return <U2FView application={props.application} userProvider={props.userProvider} />
return <U2FView application={props.application} />
}
export default U2FWrapper

View File

@@ -75,7 +75,7 @@ const Vaults = () => {
}, [application.vaultInvites, updateAllData])
useEffect(() => {
return application.streamItems([ContentType.TYPES.VaultListing, ContentType.TYPES.TrustedContact], () => {
return application.items.streamItems([ContentType.TYPES.VaultListing, ContentType.TYPES.TrustedContact], () => {
void updateAllData()
})
}, [application, updateAllData])

View File

@@ -1,9 +1,7 @@
import { WebApplication } from '@/Application/WebApplication'
import { MfaProps } from './Panes/Security/TwoFactorAuth/MfaProps'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
export interface PreferencesProps extends MfaProps {
application: WebApplication
viewControllerManager: ViewControllerManager
closePreferences: () => void
}

View File

@@ -11,21 +11,15 @@ import { useAvailableSafeAreaPadding } from '@/Hooks/useSafeAreaPadding'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import Icon from '../Icon/Icon'
const PreferencesView: FunctionComponent<PreferencesProps> = ({
application,
viewControllerManager,
closePreferences,
userProvider,
mfaProvider,
}) => {
const PreferencesView: FunctionComponent<PreferencesProps> = ({ application, closePreferences }) => {
const menu = useMemo(
() => new PreferencesSessionController(application, viewControllerManager.enableUnfinishedFeatures),
[viewControllerManager.enableUnfinishedFeatures, application],
() => new PreferencesSessionController(application, application.enableUnfinishedFeatures),
[application],
)
useEffect(() => {
menu.selectPane(viewControllerManager.preferencesController.currentPane)
}, [menu, viewControllerManager.preferencesController.currentPane])
menu.selectPane(application.preferencesController.currentPane)
}, [menu, application.preferencesController.currentPane])
const isMobileScreen = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
@@ -92,14 +86,7 @@ const PreferencesView: FunctionComponent<PreferencesProps> = ({
actions={modalActions}
customFooter={<></>}
>
<PreferencesCanvas
menu={menu}
application={application}
viewControllerManager={viewControllerManager}
closePreferences={closePreferences}
userProvider={userProvider}
mfaProvider={mfaProvider}
/>
<PreferencesCanvas menu={menu} application={application} closePreferences={closePreferences} />
</Modal>
)
}

View File

@@ -9,18 +9,15 @@ import { usePaneSwipeGesture } from '../Panes/usePaneGesture'
import { performSafariAnimationFix } from '../Panes/PaneAnimator'
import { IosModalAnimationEasing } from '../Modal/useModalAnimation'
const PreferencesViewWrapper: FunctionComponent<PreferencesViewWrapperProps> = ({
viewControllerManager,
application,
}) => {
const PreferencesViewWrapper: FunctionComponent<PreferencesViewWrapperProps> = ({ application }) => {
const commandService = useCommandService()
useEffect(() => {
return commandService.addCommandHandler({
command: OPEN_PREFERENCES_COMMAND,
onKeyDown: () => viewControllerManager.preferencesController.openPreferences(),
onKeyDown: () => application.preferencesController.openPreferences(),
})
}, [commandService, viewControllerManager])
}, [commandService, application])
const [setElement] = usePaneSwipeGesture('right', async (element) => {
const animation = element.animate(
@@ -43,22 +40,19 @@ const PreferencesViewWrapper: FunctionComponent<PreferencesViewWrapperProps> = (
animation.finish()
viewControllerManager.preferencesController.closePreferences()
application.preferencesController.closePreferences()
})
return (
<ModalOverlay
isOpen={viewControllerManager.preferencesController.isOpen}
isOpen={application.preferencesController.isOpen}
ref={setElement}
animationVariant="horizontal"
close={viewControllerManager.preferencesController.closePreferences}
close={application.preferencesController.closePreferences}
>
<PreferencesView
closePreferences={viewControllerManager.preferencesController.closePreferences}
closePreferences={application.preferencesController.closePreferences}
application={application}
viewControllerManager={viewControllerManager}
mfaProvider={application}
userProvider={application}
/>
</ModalOverlay>
)

View File

@@ -1,7 +1,5 @@
import { WebApplication } from '@/Application/WebApplication'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
export interface PreferencesViewWrapperProps {
viewControllerManager: ViewControllerManager
application: WebApplication
}

View File

@@ -1,11 +0,0 @@
export interface MfaProvider {
isMfaActivated(): Promise<boolean>
generateMfaSecret(): Promise<string>
getOtpToken(secret: string): Promise<string>
enableMfa(secret: string, otpToken: string): Promise<void>
disableMfa(): Promise<void>
}

View File

@@ -1,3 +0,0 @@
export interface UserProvider {
getUser(): { uuid: string; email: string } | undefined
}

View File

@@ -1,2 +0,0 @@
export * from './MfaProvider'
export * from './UserProvider'