refactor: rename states to view controllers (#1060)

This commit is contained in:
Mo
2022-06-01 10:15:45 -05:00
committed by GitHub
parent 78f39ec85d
commit 54125cec21
177 changed files with 1518 additions and 1365 deletions

View File

@@ -1,12 +1,4 @@
{
"presets": [
"@babel/preset-typescript",
"@babel/preset-env"
],
"plugins": [
["@babel/plugin-transform-react-jsx", {
"pragma": "h",
"pragmaFrag": "Fragment"
}]
]
"presets": ["@babel/preset-typescript", "@babel/preset-env"],
"plugins": [["@babel/plugin-transform-react-jsx"]]
}

View File

@@ -25,9 +25,9 @@ import { DesktopManagerInterface, SNLog } from '@standardnotes/snjs'
import ApplicationGroupView from './Components/ApplicationGroupView/ApplicationGroupView'
import { WebDevice } from './Device/WebDevice'
import { StartApplication } from './Device/StartApplication'
import { ApplicationGroup } from './UIModels/ApplicationGroup'
import { ApplicationGroup } from './Application/ApplicationGroup'
import { WebOrDesktopDevice } from './Device/WebOrDesktopDevice'
import { WebApplication } from './UIModels/Application'
import { WebApplication } from './Application/Application'
import { createRoot, Root } from 'react-dom/client'
let keyCount = 0

View File

@@ -5,7 +5,7 @@ import { AutolockService } from '@/Services/AutolockService'
import { DesktopManager } from '@/Services/DesktopManager'
import { IOService } from '@/Services/IOService'
import { ThemeManager } from '@/Services/ThemeManager'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { WebOrDesktopDevice } from '@/Device/WebOrDesktopDevice'
import {
DeinitSource,
@@ -21,7 +21,7 @@ import {
import { makeObservable, observable } from 'mobx'
type WebServices = {
appState: AppState
viewControllerManager: ViewControllerManager
desktopService?: DesktopManager
autolockService: AutolockService
archiveService: ArchiveManager
@@ -116,8 +116,8 @@ export class WebApplication extends SNApplication {
}
}
public getAppState(): AppState {
return this.webServices.appState
public getViewControllerManager(): ViewControllerManager {
return this.webServices.viewControllerManager
}
public getDesktopService(): DesktopManager | undefined {

View File

@@ -6,7 +6,7 @@ import {
InternalEventBus,
isDesktopDevice,
} from '@standardnotes/snjs'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { getPlatform, isDesktopApplication } from '@/Utils'
import { ArchiveManager } from '@/Services/ArchiveManager'
import { DesktopManager } from '@/Services/DesktopManager'
@@ -32,14 +32,14 @@ const createApplication = (
webSocketUrl,
)
const appState = new AppState(application, device)
const viewControllerManager = new ViewControllerManager(application, device)
const archiveService = new ArchiveManager(application)
const io = new IOService(platform === Platform.MacWeb || platform === Platform.MacDesktop)
const autolockService = new AutolockService(application, new InternalEventBus())
const themeService = new ThemeManager(application)
application.setWebServices({
appState,
viewControllerManager,
archiveService,
desktopService: isDesktopDevice(device) ? new DesktopManager(application, device) : undefined,
io,

View File

@@ -1,8 +1,9 @@
import { ApplicationEvent } from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
import { AppState, AppStateEvent } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager, ViewControllerManagerEvent } from '@/Services/ViewControllerManager'
import { autorun, IReactionDisposer, IReactionPublic } from 'mobx'
import { Component } from 'react'
export type PureComponentState = Partial<Record<string, any>>
export type PureComponentProps = Partial<Record<string, any>>
@@ -17,7 +18,7 @@ export abstract class PureComponent<P = PureComponentProps, S = PureComponentSta
override componentDidMount() {
this.addAppEventObserver()
this.addAppStateObserver()
this.addViewControllerManagerObserver()
}
deinit(): void {
@@ -38,21 +39,21 @@ export abstract class PureComponent<P = PureComponentProps, S = PureComponentSta
this.deinit()
}
public get appState(): AppState {
return this.application.getAppState()
public get viewControllerManager(): ViewControllerManager {
return this.application.getViewControllerManager()
}
autorun(view: (r: IReactionPublic) => void): void {
this.reactionDisposers.push(autorun(view))
}
addAppStateObserver() {
this.unsubState = this.application.getAppState().addObserver(async (eventName, data) => {
this.onAppStateEvent(eventName, data)
addViewControllerManagerObserver() {
this.unsubState = this.application.getViewControllerManager().addObserver(async (eventName, data) => {
this.onViewControllerManagerEvent(eventName, data)
})
}
onAppStateEvent(_eventName: AppStateEvent, _data: unknown) {
onViewControllerManagerEvent(_eventName: ViewControllerManagerEvent, _data: unknown) {
/** Optional override */
}

View File

@@ -1,31 +1,36 @@
import { observer } from 'mobx-react-lite'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/UIModels/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { WebApplication } from '@/Application/Application'
import { useCallback, useRef, FunctionComponent, KeyboardEventHandler } from 'react'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { AccountMenuPane } from './AccountMenuPane'
import MenuPaneSelector from './MenuPaneSelector'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
onClickOutside: () => void
mainApplicationGroup: ApplicationGroup
}
const AccountMenu: FunctionComponent<Props> = ({ application, appState, onClickOutside, mainApplicationGroup }) => {
const { currentPane, shouldAnimateCloseMenu } = appState.accountMenu
const AccountMenu: FunctionComponent<Props> = ({
application,
viewControllerManager,
onClickOutside,
mainApplicationGroup,
}) => {
const { currentPane, shouldAnimateCloseMenu } = viewControllerManager.accountMenuController
const closeAccountMenu = useCallback(() => {
appState.accountMenu.closeAccountMenu()
}, [appState])
viewControllerManager.accountMenuController.closeAccountMenu()
}, [viewControllerManager])
const setCurrentPane = useCallback(
(pane: AccountMenuPane) => {
appState.accountMenu.setCurrentPane(pane)
viewControllerManager.accountMenuController.setCurrentPane(pane)
},
[appState],
[viewControllerManager],
)
const ref = useRef<HTMLDivElement>(null)
@@ -59,7 +64,7 @@ const AccountMenu: FunctionComponent<Props> = ({ application, appState, onClickO
onKeyDown={handleKeyDown}
>
<MenuPaneSelector
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
mainApplicationGroup={mainApplicationGroup}
menuPane={currentPane}

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { ChangeEventHandler, FunctionComponent, useCallback, useEffect, useState } from 'react'
import Checkbox from '@/Components/Checkbox/Checkbox'
@@ -8,21 +8,21 @@ import Icon from '@/Components/Icon/Icon'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
disabled?: boolean
onPrivateWorkspaceChange?: (isPrivate: boolean, identifier?: string) => void
onStrictSignInChange?: (isStrictSignIn: boolean) => void
}
const AdvancedOptions: FunctionComponent<Props> = ({
appState,
viewControllerManager,
application,
disabled = false,
onPrivateWorkspaceChange,
onStrictSignInChange,
children,
}) => {
const { server, setServer, enableServerOption, setEnableServerOption } = appState.accountMenu
const { server, setServer, enableServerOption, setEnableServerOption } = viewControllerManager.accountMenuController
const [showAdvanced, setShowAdvanced] = useState(false)
const [isPrivateWorkspace, setIsPrivateWorkspace] = useState(false)

View File

@@ -1,6 +1,6 @@
import { STRING_NON_MATCHING_PASSWORDS } from '@/Strings'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react'
import { AccountMenuPane } from './AccountMenuPane'
@@ -11,15 +11,21 @@ import Icon from '@/Components/Icon/Icon'
import IconButton from '@/Components/Button/IconButton'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
setMenuPane: (pane: AccountMenuPane) => void
email: string
password: string
}
const ConfirmPassword: FunctionComponent<Props> = ({ application, appState, setMenuPane, email, password }) => {
const { notesAndTagsCount } = appState.accountMenu
const ConfirmPassword: FunctionComponent<Props> = ({
application,
viewControllerManager,
setMenuPane,
email,
password,
}) => {
const { notesAndTagsCount } = viewControllerManager.accountMenuController
const [confirmPassword, setConfirmPassword] = useState('')
const [isRegistering, setIsRegistering] = useState(false)
const [isEphemeral, setIsEphemeral] = useState(false)
@@ -61,8 +67,8 @@ const ConfirmPassword: FunctionComponent<Props> = ({ application, appState, setM
if (res.error) {
throw new Error(res.error.message)
}
appState.accountMenu.closeAccountMenu()
appState.accountMenu.setCurrentPane(AccountMenuPane.GeneralMenu)
viewControllerManager.accountMenuController.closeAccountMenu()
viewControllerManager.accountMenuController.setCurrentPane(AccountMenuPane.GeneralMenu)
})
.catch((err) => {
console.error(err)
@@ -77,7 +83,7 @@ const ConfirmPassword: FunctionComponent<Props> = ({ application, appState, setM
passwordInputRef.current?.focus()
}
},
[appState, application, confirmPassword, email, isEphemeral, password, shouldMergeLocal],
[viewControllerManager, application, confirmPassword, email, isEphemeral, password, shouldMergeLocal],
)
const handleKeyDown: KeyboardEventHandler = useCallback(

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react'
import { AccountMenuPane } from './AccountMenuPane'
@@ -11,7 +11,7 @@ import IconButton from '@/Components/Button/IconButton'
import AdvancedOptions from './AdvancedOptions'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
setMenuPane: (pane: AccountMenuPane) => void
email: string
@@ -21,7 +21,7 @@ type Props = {
}
const CreateAccount: FunctionComponent<Props> = ({
appState,
viewControllerManager,
application,
setMenuPane,
email,
@@ -137,7 +137,7 @@ const CreateAccount: FunctionComponent<Props> = ({
<div className="h-1px my-2 bg-border"></div>
<AdvancedOptions
application={application}
appState={appState}
viewControllerManager={viewControllerManager}
onPrivateWorkspaceChange={onPrivateWorkspaceChange}
/>
</>

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import Icon from '@/Components/Icon/Icon'
import { SyncQueueStrategy } from '@standardnotes/snjs'
@@ -11,11 +11,11 @@ import MenuItem from '@/Components/Menu/MenuItem'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import { MenuItemType } from '@/Components/Menu/MenuItemType'
import WorkspaceSwitcherOption from './WorkspaceSwitcher/WorkspaceSwitcherOption'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { formatLastSyncDate } from '@/Utils/FormatLastSyncDate'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
mainApplicationGroup: ApplicationGroup
setMenuPane: (pane: AccountMenuPane) => void
@@ -26,7 +26,7 @@ const iconClassName = 'color-neutral mr-2'
const GeneralAccountMenu: FunctionComponent<Props> = ({
application,
appState,
viewControllerManager,
setMenuPane,
closeMenu,
mainApplicationGroup,
@@ -60,20 +60,20 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({
const user = useMemo(() => application.getUser(), [application])
const openPreferences = useCallback(() => {
appState.accountMenu.closeAccountMenu()
appState.preferences.setCurrentPane('account')
appState.preferences.openPreferences()
}, [appState])
viewControllerManager.accountMenuController.closeAccountMenu()
viewControllerManager.preferencesController.setCurrentPane('account')
viewControllerManager.preferencesController.openPreferences()
}, [viewControllerManager])
const openHelp = useCallback(() => {
appState.accountMenu.closeAccountMenu()
appState.preferences.setCurrentPane('help-feedback')
appState.preferences.openPreferences()
}, [appState])
viewControllerManager.accountMenuController.closeAccountMenu()
viewControllerManager.preferencesController.setCurrentPane('help-feedback')
viewControllerManager.preferencesController.openPreferences()
}, [viewControllerManager])
const signOut = useCallback(() => {
appState.accountMenu.setSigningOut(true)
}, [appState])
viewControllerManager.accountMenuController.setSigningOut(true)
}, [viewControllerManager])
const activateRegisterPane = useCallback(() => {
setMenuPane(AccountMenuPane.Register)
@@ -136,13 +136,16 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({
</>
)}
<Menu
isOpen={appState.accountMenu.show}
isOpen={viewControllerManager.accountMenuController.show}
a11yLabel="General account menu"
closeMenu={closeMenu}
initialFocus={!application.hasAccount() ? CREATE_ACCOUNT_INDEX : SWITCHER_INDEX}
>
<MenuItemSeparator />
<WorkspaceSwitcherOption mainApplicationGroup={mainApplicationGroup} appState={appState} />
<WorkspaceSwitcherOption
mainApplicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
/>
<MenuItemSeparator />
{user ? (
<MenuItem type={MenuItemType.IconButton} onClick={openPreferences}>
@@ -166,7 +169,7 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({
<Icon type="help" className={iconClassName} />
Help &amp; feedback
</div>
<span className="color-neutral">v{appState.version}</span>
<span className="color-neutral">v{viewControllerManager.version}</span>
</MenuItem>
{user ? (
<>

View File

@@ -1,6 +1,6 @@
import { WebApplication } from '@/UIModels/Application'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useState } from 'react'
import { AccountMenuPane } from './AccountMenuPane'
@@ -10,7 +10,7 @@ import GeneralAccountMenu from './GeneralAccountMenu'
import SignInPane from './SignIn'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
mainApplicationGroup: ApplicationGroup
menuPane: AccountMenuPane
@@ -20,7 +20,7 @@ type Props = {
const MenuPaneSelector: FunctionComponent<Props> = ({
application,
appState,
viewControllerManager,
menuPane,
setMenuPane,
closeMenu,
@@ -33,7 +33,7 @@ const MenuPaneSelector: FunctionComponent<Props> = ({
case AccountMenuPane.GeneralMenu:
return (
<GeneralAccountMenu
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
mainApplicationGroup={mainApplicationGroup}
setMenuPane={setMenuPane}
@@ -41,11 +41,13 @@ const MenuPaneSelector: FunctionComponent<Props> = ({
/>
)
case AccountMenuPane.SignIn:
return <SignInPane appState={appState} application={application} setMenuPane={setMenuPane} />
return (
<SignInPane viewControllerManager={viewControllerManager} application={application} setMenuPane={setMenuPane} />
)
case AccountMenuPane.Register:
return (
<CreateAccount
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
setMenuPane={setMenuPane}
email={email}
@@ -57,7 +59,7 @@ const MenuPaneSelector: FunctionComponent<Props> = ({
case AccountMenuPane.ConfirmPassword:
return (
<ConfirmPassword
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
setMenuPane={setMenuPane}
email={email}

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { isDev } from '@/Utils'
import { observer } from 'mobx-react-lite'
import React, { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react'
@@ -13,13 +13,13 @@ import IconButton from '@/Components/Button/IconButton'
import AdvancedOptions from './AdvancedOptions'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
setMenuPane: (pane: AccountMenuPane) => void
}
const SignInPane: FunctionComponent<Props> = ({ application, appState, setMenuPane }) => {
const { notesAndTagsCount } = appState.accountMenu
const SignInPane: FunctionComponent<Props> = ({ application, viewControllerManager, setMenuPane }) => {
const { notesAndTagsCount } = viewControllerManager.accountMenuController
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('')
@@ -86,7 +86,7 @@ const SignInPane: FunctionComponent<Props> = ({ application, appState, setMenuPa
if (res.error) {
throw new Error(res.error.message)
}
appState.accountMenu.closeAccountMenu()
viewControllerManager.accountMenuController.closeAccountMenu()
})
.catch((err) => {
console.error(err)
@@ -97,7 +97,7 @@ const SignInPane: FunctionComponent<Props> = ({ application, appState, setMenuPa
.finally(() => {
setIsSigningIn(false)
})
}, [appState, application, email, isEphemeral, isStrictSignin, password, shouldMergeLocal])
}, [viewControllerManager, application, email, isEphemeral, isStrictSignin, password, shouldMergeLocal])
const onPrivateWorkspaceChange = useCallback(
(newIsPrivateWorkspace: boolean, privateWorkspaceIdentifier?: string) => {
@@ -201,7 +201,7 @@ const SignInPane: FunctionComponent<Props> = ({ application, appState, setMenuPa
</div>
<div className="h-1px my-2 bg-border"></div>
<AdvancedOptions
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
disabled={isSigningIn}
onPrivateWorkspaceChange={onPrivateWorkspaceChange}

View File

@@ -1,24 +1,25 @@
import { observer } from 'mobx-react-lite'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/UIModels/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { WebApplication } from '@/Application/Application'
import { User as UserType } from '@standardnotes/snjs'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
}
const User = ({ appState, application }: Props) => {
const { server } = appState.accountMenu
const User = ({ viewControllerManager, application }: Props) => {
const { server } = viewControllerManager.accountMenuController
const user = application.getUser() as UserType
return (
<div className="sk-panel-section">
{appState.sync.errorMessage && (
{viewControllerManager.syncStatusController.errorMessage && (
<div className="sk-notification danger">
<div className="sk-notification-title">Sync Unreachable</div>
<div className="sk-notification-text">
Hmm...we can't seem to sync your account. The reason: {appState.sync.errorMessage}
Hmm...we can't seem to sync your account. The reason:{' '}
{viewControllerManager.syncStatusController.errorMessage}
</div>
<a
className="sk-a info-contrast sk-bold sk-panel-row"

View File

@@ -1,5 +1,5 @@
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { ApplicationDescriptor, ApplicationGroupEvent, ButtonType } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useState } from 'react'
@@ -12,14 +12,14 @@ import WorkspaceMenuItem from './WorkspaceMenuItem'
type Props = {
mainApplicationGroup: ApplicationGroup
appState: AppState
viewControllerManager: ViewControllerManager
isOpen: boolean
hideWorkspaceOptions?: boolean
}
const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
mainApplicationGroup,
appState,
viewControllerManager,
isOpen,
hideWorkspaceOptions = false,
}: Props) => {
@@ -42,7 +42,7 @@ const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
}, [mainApplicationGroup])
const signoutAll = useCallback(async () => {
const confirmed = await appState.application.alertService.confirm(
const confirmed = await viewControllerManager.application.alertService.confirm(
'Are you sure you want to sign out of all workspaces on this device?',
undefined,
'Sign out all',
@@ -52,11 +52,11 @@ const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
return
}
mainApplicationGroup.signOutAllWorkspaces().catch(console.error)
}, [mainApplicationGroup, appState])
}, [mainApplicationGroup, viewControllerManager])
const destroyWorkspace = useCallback(() => {
appState.accountMenu.setSigningOut(true)
}, [appState])
viewControllerManager.accountMenuController.setSigningOut(true)
}, [viewControllerManager])
return (
<Menu a11yLabel="Workspace switcher menu" className="px-0 focus:shadow-none" isOpen={isOpen}>

View File

@@ -1,6 +1,6 @@
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
@@ -9,10 +9,10 @@ import WorkspaceSwitcherMenu from './WorkspaceSwitcherMenu'
type Props = {
mainApplicationGroup: ApplicationGroup
appState: AppState
viewControllerManager: ViewControllerManager
}
const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGroup, appState }) => {
const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGroup, viewControllerManager }) => {
const buttonRef = useRef<HTMLButtonElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const [isOpen, setIsOpen] = useState(false)
@@ -58,7 +58,11 @@ const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGrou
</button>
{isOpen && (
<div ref={menuRef} className="sn-dropdown max-h-120 min-w-68 py-2 fixed overflow-y-auto" style={menuStyle}>
<WorkspaceSwitcherMenu mainApplicationGroup={mainApplicationGroup} appState={appState} isOpen={isOpen} />
<WorkspaceSwitcherMenu
mainApplicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
isOpen={isOpen}
/>
</div>
)}
</>

View File

@@ -1,5 +1,5 @@
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { WebApplication } from '@/UIModels/Application'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { WebApplication } from '@/Application/Application'
import { Component } from 'react'
import ApplicationView from '@/Components/ApplicationView/ApplicationView'
import { WebOrDesktopDevice } from '@/Device/WebOrDesktopDevice'

View File

@@ -1,10 +1,10 @@
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { getPlatformString, getWindowUrlParams } from '@/Utils'
import { AppStateEvent, PanelResizedData } from '@/UIModels/AppState'
import { ViewControllerManagerEvent } from '@/Services/ViewControllerManager'
import { ApplicationEvent, Challenge, removeFromArray } from '@standardnotes/snjs'
import { PANEL_NAME_NOTES, PANEL_NAME_NAVIGATION } from '@/Constants'
import { alertDialog } from '@/Services/AlertService'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import Navigation from '@/Components/Navigation/Navigation'
import NoteGroupView from '@/Components/NoteGroupView/NoteGroupView'
import Footer from '@/Components/Footer/Footer'
@@ -23,6 +23,7 @@ import FilePreviewModalWrapper from '@/Components/Files/FilePreviewModal'
import ContentListView from '@/Components/ContentListView/ContentListView'
import FileContextMenuWrapper from '@/Components/FileContextMenu/FileContextMenu'
import PermissionsModalWrapper from '@/Components/PermissionsModal/PermissionsModalWrapper'
import { PanelResizedData } from '@/Typings/PanelResizedData'
type Props = {
application: WebApplication
@@ -36,7 +37,7 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
const [needsUnlock, setNeedsUnlock] = useState(true)
const [challenges, setChallenges] = useState<Challenge[]>([])
const appState = application.getAppState()
const viewControllerManager = application.getViewControllerManager()
useEffect(() => {
const desktopService = application.getDesktopService()
@@ -119,8 +120,8 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
}, [application, onAppLaunch, onAppStart])
useEffect(() => {
const removeObserver = application.getAppState().addObserver(async (eventName, data) => {
if (eventName === AppStateEvent.PanelResized) {
const removeObserver = application.getViewControllerManager().addObserver(async (eventName, data) => {
if (eventName === ViewControllerManagerEvent.PanelResized) {
const { panel, collapsed } = data as PanelResizedData
let appClass = ''
if (panel === PANEL_NAME_NOTES && collapsed) {
@@ -130,7 +131,7 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
appClass += ' collapsed-navigation'
}
setAppClass(appClass)
} else if (eventName === AppStateEvent.WindowDidFocus) {
} else if (eventName === ViewControllerManagerEvent.WindowDidFocus) {
if (!(await application.isLocked())) {
application.sync.sync().catch(console.error)
}
@@ -155,7 +156,7 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
<ChallengeModal
key={`${challenge.id}${application.ephemeralIdentifier}`}
application={application}
appState={appState}
viewControllerManager={viewControllerManager}
mainApplicationGroup={mainApplicationGroup}
challenge={challenge}
onDismiss={removeChallenge}
@@ -165,42 +166,42 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
})}
</>
)
}, [appState, challenges, mainApplicationGroup, removeChallenge, application])
}, [viewControllerManager, challenges, mainApplicationGroup, removeChallenge, application])
if (!renderAppContents) {
return renderChallenges()
}
return (
<PremiumModalProvider application={application} appState={appState}>
<PremiumModalProvider application={application} viewControllerManager={viewControllerManager}>
<div className={platformString + ' main-ui-view sn-component'}>
<div id="app" className={appClass + ' app app-column-container'}>
<Navigation application={application} />
<ContentListView application={application} appState={appState} />
<ContentListView application={application} viewControllerManager={viewControllerManager} />
<NoteGroupView application={application} />
</div>
<>
<Footer application={application} applicationGroup={mainApplicationGroup} />
<SessionsModal application={application} appState={appState} />
<PreferencesViewWrapper appState={appState} application={application} />
<RevisionHistoryModalWrapper application={application} appState={appState} />
<SessionsModal application={application} viewControllerManager={viewControllerManager} />
<PreferencesViewWrapper viewControllerManager={viewControllerManager} application={application} />
<RevisionHistoryModalWrapper application={application} viewControllerManager={viewControllerManager} />
</>
{renderChallenges()}
<>
<NotesContextMenu application={application} appState={appState} />
<TagsContextMenuWrapper appState={appState} />
<FileContextMenuWrapper appState={appState} />
<PurchaseFlowWrapper application={application} appState={appState} />
<NotesContextMenu application={application} viewControllerManager={viewControllerManager} />
<TagsContextMenuWrapper viewControllerManager={viewControllerManager} />
<FileContextMenuWrapper viewControllerManager={viewControllerManager} />
<PurchaseFlowWrapper application={application} viewControllerManager={viewControllerManager} />
<ConfirmSignoutContainer
applicationGroup={mainApplicationGroup}
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
/>
<ToastContainer />
<FilePreviewModalWrapper application={application} appState={appState} />
<FilePreviewModalWrapper application={application} viewControllerManager={viewControllerManager} />
<PermissionsModalWrapper application={application} />
</>
</div>

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { MENU_MARGIN_FROM_APP_BORDER } from '@/Constants'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import VisuallyHidden from '@reach/visually-hidden'
@@ -19,13 +19,17 @@ import { isHandlingFileDrag } from '@/Utils/DragTypeCheck'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
onClickPreprocessing?: () => Promise<void>
}
const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState, onClickPreprocessing }: Props) => {
const AttachedFilesButton: FunctionComponent<Props> = ({
application,
viewControllerManager,
onClickPreprocessing,
}: Props) => {
const premiumModal = usePremiumModal()
const note: SNNote | undefined = appState.notes.firstSelectedNote
const note: SNNote | undefined = viewControllerManager.notesController.firstSelectedNote
const [open, setOpen] = useState(false)
const [position, setPosition] = useState({
@@ -39,12 +43,12 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
const [closeOnBlur, keepMenuOpen] = useCloseOnBlur(containerRef, setOpen)
useEffect(() => {
if (appState.filePreviewModal.isOpen) {
if (viewControllerManager.filePreviewModalController.isOpen) {
keepMenuOpen(true)
} else {
keepMenuOpen(false)
}
}, [appState.filePreviewModal.isOpen, keepMenuOpen])
}, [viewControllerManager.filePreviewModalController.isOpen, keepMenuOpen])
const [currentTab, setCurrentTab] = useState(PopoverTabs.AttachedFiles)
const [allFiles, setAllFiles] = useState<FileItem[]>([])
@@ -90,10 +94,10 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
}, [onClickPreprocessing, open])
const prospectivelyShowFilesPremiumModal = useCallback(() => {
if (!appState.features.hasFiles) {
if (!viewControllerManager.featuresController.hasFiles) {
premiumModal.activate('Files')
}
}, [appState.features.hasFiles, premiumModal])
}, [viewControllerManager.featuresController.hasFiles, premiumModal])
const toggleAttachedFilesMenuWithEntitlementCheck = useCallback(async () => {
prospectivelyShowFilesPremiumModal()
@@ -121,7 +125,7 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
}
const downloadFile = async (file: FileItem) => {
appState.files.downloadFile(file).catch(console.error)
viewControllerManager.filesController.downloadFile(file).catch(console.error)
}
const attachFileToNote = useCallback(
@@ -213,7 +217,7 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
case PopoverFileItemActionType.PreviewFile: {
keepMenuOpen(true)
const otherFiles = currentTab === PopoverTabs.AllFiles ? allFiles : attachedFiles
appState.filePreviewModal.activate(
viewControllerManager.filePreviewModalController.activate(
file,
otherFiles.filter((file) => !file.protected),
)
@@ -305,7 +309,7 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
setIsDraggingFiles(false)
if (!appState.features.hasFiles) {
if (!viewControllerManager.featuresController.hasFiles) {
prospectivelyShowFilesPremiumModal()
return
}
@@ -320,7 +324,7 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
return
}
const uploadedFiles = await appState.files.uploadNewFile(fileOrHandle)
const uploadedFiles = await viewControllerManager.filesController.uploadNewFile(fileOrHandle)
if (!uploadedFiles) {
return
@@ -338,8 +342,8 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
}
},
[
appState.files,
appState.features.hasFiles,
viewControllerManager.filesController,
viewControllerManager.featuresController.hasFiles,
attachFileToNote,
currentTab,
application,
@@ -396,7 +400,7 @@ const AttachedFilesButton: FunctionComponent<Props> = ({ application, appState,
{open && (
<AttachedFilesPopover
application={application}
appState={appState}
viewControllerManager={viewControllerManager}
attachedFiles={attachedFiles}
allFiles={allFiles}
closeOnBlur={closeOnBlur}

View File

@@ -1,6 +1,6 @@
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { FileItem } from '@standardnotes/snjs'
import { FilesIllustration } from '@standardnotes/icons'
import { observer } from 'mobx-react-lite'
@@ -13,7 +13,7 @@ import { PopoverTabs } from './PopoverTabs'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
allFiles: FileItem[]
attachedFiles: FileItem[]
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
@@ -25,7 +25,7 @@ type Props = {
const AttachedFilesPopover: FunctionComponent<Props> = ({
application,
appState,
viewControllerManager,
allFiles,
attachedFiles,
closeOnBlur,
@@ -45,7 +45,7 @@ const AttachedFilesPopover: FunctionComponent<Props> = ({
: filesList
const handleAttachFilesClick = async () => {
const uploadedFiles = await appState.files.uploadNewFile()
const uploadedFiles = await viewControllerManager.filesController.uploadNewFile()
if (!uploadedFiles) {
return
}

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { DialogContent, DialogOverlay } from '@reach/dialog'
import {
ButtonType,
@@ -14,13 +14,13 @@ import Button from '@/Components/Button/Button'
import Icon from '@/Components/Icon/Icon'
import ChallengeModalPrompt from './ChallengePrompt'
import LockscreenWorkspaceSwitcher from './LockscreenWorkspaceSwitcher'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { ChallengeModalValues } from './ChallengeModalValues'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
mainApplicationGroup: ApplicationGroup
challenge: Challenge
onDismiss?: (challenge: Challenge) => void
@@ -44,7 +44,7 @@ const validateValues = (values: ChallengeModalValues, prompts: ChallengePrompt[]
const ChallengeModal: FunctionComponent<Props> = ({
application,
appState,
viewControllerManager,
mainApplicationGroup,
challenge,
onDismiss,
@@ -255,7 +255,10 @@ const ChallengeModal: FunctionComponent<Props> = ({
</Button>
)}
{shouldShowWorkspaceSwitcher && (
<LockscreenWorkspaceSwitcher mainApplicationGroup={mainApplicationGroup} appState={appState} />
<LockscreenWorkspaceSwitcher
mainApplicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
/>
)}
</DialogContent>
</DialogOverlay>

View File

@@ -1,5 +1,5 @@
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import WorkspaceSwitcherMenu from '@/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu'
@@ -9,10 +9,10 @@ import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
type Props = {
mainApplicationGroup: ApplicationGroup
appState: AppState
viewControllerManager: ViewControllerManager
}
const LockscreenWorkspaceSwitcher: FunctionComponent<Props> = ({ mainApplicationGroup, appState }) => {
const LockscreenWorkspaceSwitcher: FunctionComponent<Props> = ({ mainApplicationGroup, viewControllerManager }) => {
const buttonRef = useRef<HTMLButtonElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const containerRef = useRef<HTMLDivElement>(null)
@@ -55,7 +55,7 @@ const LockscreenWorkspaceSwitcher: FunctionComponent<Props> = ({ mainApplication
<div ref={menuRef} className="sn-dropdown max-h-120 min-w-68 py-2 fixed overflow-y-auto" style={menuStyle}>
<WorkspaceSwitcherMenu
mainApplicationGroup={mainApplicationGroup}
appState={appState}
viewControllerManager={viewControllerManager}
isOpen={isOpen}
hideWorkspaceOptions={true}
/>

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { MENU_MARGIN_FROM_APP_BORDER } from '@/Constants'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import VisuallyHidden from '@reach/visually-hidden'
@@ -11,12 +11,16 @@ import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
onClickPreprocessing?: () => Promise<void>
}
const ChangeEditorButton: FunctionComponent<Props> = ({ application, appState, onClickPreprocessing }: Props) => {
const note = appState.notes.firstSelectedNote
const ChangeEditorButton: FunctionComponent<Props> = ({
application,
viewControllerManager,
onClickPreprocessing,
}: Props) => {
const note = viewControllerManager.notesController.firstSelectedNote
const [isOpen, setIsOpen] = useState(false)
const [isVisible, setIsVisible] = useState(false)
const [position, setPosition] = useState({

View File

@@ -4,7 +4,7 @@ import MenuItem from '@/Components/Menu/MenuItem'
import { MenuItemType } from '@/Components/Menu/MenuItemType'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
import { STRING_EDIT_LOCKED_ATTEMPT } from '@/Strings'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import {
ComponentArea,
ItemMutator,
@@ -90,7 +90,7 @@ const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
const transactions: TransactionalMutation[] = []
await application.getAppState().contentListView.insertCurrentIfTemplate()
await application.getViewControllerManager().contentListController.insertCurrentIfTemplate()
if (note.locked) {
application.alertService.alert(STRING_EDIT_LOCKED_ATTEMPT).catch(console.error)

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import {
ContentType,
FeatureStatus,

View File

@@ -7,7 +7,7 @@ import {
ComponentViewerEvent,
ComponentViewerError,
} from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import { observer } from 'mobx-react-lite'
import OfflineRestricted from '@/Components/ComponentView/OfflineRestricted'
@@ -15,12 +15,12 @@ import UrlMissing from '@/Components/ComponentView/UrlMissing'
import IsDeprecated from '@/Components/ComponentView/IsDeprecated'
import IsExpired from '@/Components/ComponentView/IsExpired'
import IssueOnLoading from '@/Components/ComponentView/IssueOnLoading'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { openSubscriptionDashboard } from '@/Utils/ManageSubscription'
interface IProps {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
componentViewer: ComponentViewer
requestReload?: (viewer: ComponentViewer, force?: boolean) => void
onLoad?: (component: SNComponent) => void
@@ -151,7 +151,7 @@ const ComponentView: FunctionComponent<IProps> = ({ application, onLoad, compone
application.io.handleComponentKeyUp(data.keyboardModifier)
break
case ComponentAction.Click:
application.getAppState().notes.setContextMenuOpen(false)
application.getViewControllerManager().notesController.setContextMenuOpen(false)
break
default:
return

View File

@@ -1,31 +1,31 @@
import { FunctionComponent, useEffect, useRef, useState } from 'react'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { STRING_SIGN_OUT_CONFIRMATION } from '@/Strings'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { isDesktopApplication } from '@/Utils'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
applicationGroup: ApplicationGroup
}
const ConfirmSignoutModal: FunctionComponent<Props> = ({ application, appState, applicationGroup }) => {
const ConfirmSignoutModal: FunctionComponent<Props> = ({ application, viewControllerManager, applicationGroup }) => {
const [deleteLocalBackups, setDeleteLocalBackups] = useState(false)
const cancelRef = useRef<HTMLButtonElement>(null)
function closeDialog() {
appState.accountMenu.setSigningOut(false)
viewControllerManager.accountMenuController.setSigningOut(false)
}
const [localBackupsCount, setLocalBackupsCount] = useState(0)
useEffect(() => {
application.desktopDevice?.localBackupsCount().then(setLocalBackupsCount).catch(console.error)
}, [appState.accountMenu.signingOut, application.desktopDevice])
}, [viewControllerManager.accountMenuController.signingOut, application.desktopDevice])
const workspaces = applicationGroup.getDescriptors()
const showWorkspaceWarning = workspaces.length > 1 && isDesktopApplication()
@@ -112,7 +112,7 @@ const ConfirmSignoutModal: FunctionComponent<Props> = ({ application, appState,
ConfirmSignoutModal.displayName = 'ConfirmSignoutModal'
const ConfirmSignoutContainer = (props: Props) => {
if (!props.appState.accountMenu.signingOut) {
if (!props.viewControllerManager.accountMenuController.signingOut) {
return null
}
return <ConfirmSignoutModal {...props} />

View File

@@ -1,6 +1,6 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { KeyboardKey } from '@/Services/IOService'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { UuidString } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, KeyboardEventHandler, UIEventHandler, useCallback } from 'react'
@@ -10,16 +10,23 @@ import ContentListItem from './ContentListItem'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
items: ListableContentItem[]
selectedItems: Record<UuidString, ListableContentItem>
paginate: () => void
}
const ContentList: FunctionComponent<Props> = ({ application, appState, items, selectedItems, paginate }) => {
const { selectPreviousItem, selectNextItem } = appState.contentListView
const { hideTags, hideDate, hideNotePreview, hideEditorIcon } = appState.contentListView.webDisplayOptions
const { sortBy } = appState.contentListView.displayOptions
const ContentList: FunctionComponent<Props> = ({
application,
viewControllerManager,
items,
selectedItems,
paginate,
}) => {
const { selectPreviousItem, selectNextItem } = viewControllerManager.contentListController
const { hideTags, hideDate, hideNotePreview, hideEditorIcon } =
viewControllerManager.contentListController.webDisplayOptions
const { sortBy } = viewControllerManager.contentListController.displayOptions
const onScroll: UIEventHandler = useCallback(
(e) => {
@@ -57,7 +64,7 @@ const ContentList: FunctionComponent<Props> = ({ application, appState, items, s
<ContentListItem
key={item.uuid}
application={application}
appState={appState}
viewControllerManager={viewControllerManager}
item={item}
selected={!!selectedItems[item.uuid]}
hideDate={hideDate}

View File

@@ -10,12 +10,12 @@ const ContentListItem: FunctionComponent<AbstractListItemProps> = (props) => {
return []
}
const selectedTag = props.appState.tags.selected
const selectedTag = props.viewControllerManager.navigationController.selected
if (!selectedTag) {
return []
}
const tags = props.appState.getItemTags(props.item)
const tags = props.viewControllerManager.getItemTags(props.item)
const isNavigatingOnlyTag = selectedTag instanceof SNTag && tags.length === 1
if (isNavigatingOnlyTag) {

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { CollectionSort, CollectionSortProperty, PrefKey, SystemViewId } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useState } from 'react'
@@ -7,11 +7,11 @@ import Menu from '@/Components/Menu/Menu'
import MenuItem from '@/Components/Menu/MenuItem'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import { MenuItemType } from '@/Components/Menu/MenuItemType'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
closeDisplayOptionsMenu: () => void
isOpen: boolean
@@ -21,7 +21,7 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
closeDisplayOptionsMenu,
closeOnBlur,
application,
appState,
viewControllerManager,
isOpen,
}) => {
const [sortBy, setSortBy] = useState(() => application.getPreference(PrefKey.SortNotesBy, CollectionSort.CreatedAt))
@@ -174,7 +174,7 @@ const ContentListOptionsMenu: FunctionComponent<Props> = ({
</MenuItem>
<MenuItemSeparator />
<div className="px-3 py-1 text-xs font-semibold color-text uppercase">View</div>
{appState.tags.selectedUuid !== SystemViewId.Files && (
{viewControllerManager.navigationController.selectedUuid !== SystemViewId.Files && (
<MenuItem
type={MenuItemType.SwitchButton}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"

View File

@@ -1,6 +1,6 @@
import { KeyboardKey, KeyboardModifier } from '@/Services/IOService'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { PANEL_NAME_NOTES } from '@/Constants'
import { PrefKey, SystemViewId } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
@@ -24,10 +24,10 @@ import ContentListOptionsMenu from './ContentListOptionsMenu'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const ContentListView: FunctionComponent<Props> = ({ application, appState }) => {
const ContentListView: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
const itemsViewPanelRef = useRef<HTMLDivElement>(null)
const displayOptionsMenuRef = useRef<HTMLDivElement>(null)
@@ -46,9 +46,9 @@ const ContentListView: FunctionComponent<Props> = ({ application, appState }) =>
paginate,
panelWidth,
createNewNote,
} = appState.contentListView
} = viewControllerManager.contentListController
const { selectedItems } = appState.selectedItems
const { selectedItems } = viewControllerManager.selectionController
const [showDisplayOptionsMenu, setShowDisplayOptionsMenu] = useState(false)
const [focusedSearch, setFocusedSearch] = useState(false)
@@ -56,17 +56,17 @@ const ContentListView: FunctionComponent<Props> = ({ application, appState }) =>
const [closeDisplayOptMenuOnBlur] = useCloseOnBlur(displayOptionsMenuRef, setShowDisplayOptionsMenu)
const isFilesSmartView = useMemo(
() => appState.tags.selected?.uuid === SystemViewId.Files,
[appState.tags.selected?.uuid],
() => viewControllerManager.navigationController.selected?.uuid === SystemViewId.Files,
[viewControllerManager.navigationController.selected?.uuid],
)
const addNewItem = useCallback(() => {
if (isFilesSmartView) {
void appState.files.uploadNewFile()
void viewControllerManager.filesController.uploadNewFile()
} else {
void createNewNote()
}
}, [appState.files, createNewNote, isFilesSmartView])
}, [viewControllerManager.filesController, createNewNote, isFilesSmartView])
useEffect(() => {
/**
@@ -142,15 +142,15 @@ const ContentListView: FunctionComponent<Props> = ({ application, appState }) =>
const panelResizeFinishCallback: ResizeFinishCallback = useCallback(
(width, _lastLeft, _isMaxWidth, isCollapsed) => {
application.setPreference(PrefKey.NotesPanelWidth, width).catch(console.error)
appState.noteTags.reloadTagsContainerMaxWidth()
appState.panelDidResize(PANEL_NAME_NOTES, isCollapsed)
viewControllerManager.noteTagsController.reloadTagsContainerMaxWidth()
viewControllerManager.panelDidResize(PANEL_NAME_NOTES, isCollapsed)
},
[appState, application],
[viewControllerManager, application],
)
const panelWidthEventCallback = useCallback(() => {
appState.noteTags.reloadTagsContainerMaxWidth()
}, [appState])
viewControllerManager.noteTagsController.reloadTagsContainerMaxWidth()
}, [viewControllerManager])
const toggleDisplayOptionsMenu = useCallback(() => {
setShowDisplayOptionsMenu(!showDisplayOptionsMenu)
@@ -208,11 +208,11 @@ const ContentListView: FunctionComponent<Props> = ({ application, appState }) =>
{(focusedSearch || noteFilterText) && (
<div className="animate-fade-from-top">
<SearchOptions application={application} appState={appState} />
<SearchOptions application={application} viewControllerManager={viewControllerManager} />
</div>
)}
</div>
<NoAccountWarningWrapper appState={appState} />
<NoAccountWarningWrapper viewControllerManager={viewControllerManager} />
</div>
<div id="items-menu-bar" className="sn-component" ref={displayOptionsMenuRef}>
<div className="sk-app-bar no-edges">
@@ -235,7 +235,7 @@ const ContentListView: FunctionComponent<Props> = ({ application, appState }) =>
{showDisplayOptionsMenu && (
<ContentListOptionsMenu
application={application}
appState={appState}
viewControllerManager={viewControllerManager}
closeDisplayOptionsMenu={toggleDisplayOptionsMenu}
closeOnBlur={closeDisplayOptMenuOnBlur}
isOpen={showDisplayOptionsMenu}
@@ -254,7 +254,7 @@ const ContentListView: FunctionComponent<Props> = ({ application, appState }) =>
items={renderedItems}
selectedItems={selectedItems}
application={application}
appState={appState}
viewControllerManager={viewControllerManager}
paginate={paginate}
/>
) : null}

View File

@@ -10,7 +10,7 @@ import { DisplayableListItemProps } from './Types/DisplayableListItemProps'
const FileListItem: FunctionComponent<DisplayableListItemProps> = ({
application,
appState,
viewControllerManager,
hideDate,
hideIcon,
hideTags,
@@ -21,32 +21,40 @@ const FileListItem: FunctionComponent<DisplayableListItemProps> = ({
}) => {
const openFileContextMenu = useCallback(
(posX: number, posY: number) => {
appState.files.setFileContextMenuLocation({
viewControllerManager.filesController.setFileContextMenuLocation({
x: posX,
y: posY,
})
appState.files.setShowFileContextMenu(true)
viewControllerManager.filesController.setShowFileContextMenu(true)
},
[appState.files],
[viewControllerManager.filesController],
)
const openContextMenu = useCallback(
async (posX: number, posY: number) => {
const { didSelect } = await appState.selectedItems.selectItem(item.uuid)
const { didSelect } = await viewControllerManager.selectionController.selectItem(item.uuid)
if (didSelect) {
openFileContextMenu(posX, posY)
}
},
[appState.selectedItems, item.uuid, openFileContextMenu],
[viewControllerManager.selectionController, item.uuid, openFileContextMenu],
)
const onClick = useCallback(() => {
void appState.selectedItems.selectItem(item.uuid, true).then(({ didSelect }) => {
if (didSelect && appState.selectedItems.selectedItemsCount < 2) {
appState.filePreviewModal.activate(item as FileItem, appState.files.allFiles)
void viewControllerManager.selectionController.selectItem(item.uuid, true).then(({ didSelect }) => {
if (didSelect && viewControllerManager.selectionController.selectedItemsCount < 2) {
viewControllerManager.filePreviewModalController.activate(
item as FileItem,
viewControllerManager.filesController.allFiles,
)
}
})
}, [appState.filePreviewModal, appState.files.allFiles, appState.selectedItems, item])
}, [
viewControllerManager.filePreviewModalController,
viewControllerManager.filesController.allFiles,
viewControllerManager.selectionController,
item,
])
const IconComponent = () =>
getFileIconComponent(

View File

@@ -11,7 +11,7 @@ import { DisplayableListItemProps } from './Types/DisplayableListItemProps'
const NoteListItem: FunctionComponent<DisplayableListItemProps> = ({
application,
appState,
viewControllerManager,
hideDate,
hideIcon,
hideTags,
@@ -27,16 +27,16 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps> = ({
const hasFiles = application.items.getFilesForNote(item as SNNote).length > 0
const openNoteContextMenu = (posX: number, posY: number) => {
appState.notes.setContextMenuClickLocation({
viewControllerManager.notesController.setContextMenuClickLocation({
x: posX,
y: posY,
})
appState.notes.reloadContextMenuLayout()
appState.notes.setContextMenuOpen(true)
viewControllerManager.notesController.reloadContextMenuLayout()
viewControllerManager.notesController.setContextMenuOpen(true)
}
const openContextMenu = async (posX: number, posY: number) => {
const { didSelect } = await appState.selectedItems.selectItem(item.uuid, true)
const { didSelect } = await viewControllerManager.selectionController.selectItem(item.uuid, true)
if (didSelect) {
openNoteContextMenu(posX, posY)
}
@@ -49,7 +49,7 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps> = ({
}`}
id={item.uuid}
onClick={() => {
void appState.selectedItems.selectItem(item.uuid, true)
void viewControllerManager.selectionController.selectItem(item.uuid, true)
}}
onContextMenu={(event) => {
event.preventDefault()

View File

@@ -1,11 +1,11 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { SortableItem } from '@standardnotes/snjs'
import { ListableContentItem } from './ListableContentItem'
export type AbstractListItemProps = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
hideDate: boolean
hideIcon: boolean
hideTags: boolean

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'

View File

@@ -1,7 +1,7 @@
import { MAX_MENU_SIZE_MULTIPLIER, MENU_MARGIN_FROM_APP_BORDER } from '@/Constants'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import { PopoverFileItemAction } from '../AttachedFilesPopover/PopoverFileItemAction'
@@ -9,11 +9,12 @@ import { PopoverTabs } from '../AttachedFilesPopover/PopoverTabs'
import FileMenuOptions from './FileMenuOptions'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
}
const FileContextMenu: FunctionComponent<Props> = observer(({ appState }) => {
const { selectedFiles, showFileContextMenu, setShowFileContextMenu, fileContextMenuLocation } = appState.files
const FileContextMenu: FunctionComponent<Props> = observer(({ viewControllerManager }) => {
const { selectedFiles, showFileContextMenu, setShowFileContextMenu, fileContextMenuLocation } =
viewControllerManager.filesController
const [contextMenuStyle, setContextMenuStyle] = useState<React.CSSProperties>({
top: 0,
@@ -23,7 +24,7 @@ const FileContextMenu: FunctionComponent<Props> = observer(({ appState }) => {
const [contextMenuMaxHeight, setContextMenuMaxHeight] = useState<number | 'auto'>('auto')
const contextMenuRef = useRef<HTMLDivElement>(null)
const [closeOnBlur] = useCloseOnBlur(contextMenuRef, (open: boolean) => setShowFileContextMenu(open))
useCloseOnClickOutside(contextMenuRef, () => appState.files.setShowFileContextMenu(false))
useCloseOnClickOutside(contextMenuRef, () => viewControllerManager.filesController.setShowFileContextMenu(false))
const selectedFile = selectedFiles[0]
@@ -87,10 +88,13 @@ const FileContextMenu: FunctionComponent<Props> = observer(({ appState }) => {
const handleFileAction = useCallback(
async (action: PopoverFileItemAction) => {
const { didHandleAction } = await appState.files.handleFileAction(action, PopoverTabs.AllFiles)
const { didHandleAction } = await viewControllerManager.filesController.handleFileAction(
action,
PopoverTabs.AllFiles,
)
return didHandleAction
},
[appState.files],
[viewControllerManager.filesController],
)
return (
@@ -116,8 +120,8 @@ const FileContextMenu: FunctionComponent<Props> = observer(({ appState }) => {
FileContextMenu.displayName = 'FileContextMenu'
const FileContextMenuWrapper: FunctionComponent<Props> = ({ appState }) => {
const { selectedFiles, showFileContextMenu } = appState.files
const FileContextMenuWrapper: FunctionComponent<Props> = ({ viewControllerManager }) => {
const { selectedFiles, showFileContextMenu } = viewControllerManager.filesController
const selectedFile = selectedFiles[0]
@@ -125,7 +129,7 @@ const FileContextMenuWrapper: FunctionComponent<Props> = ({ appState }) => {
return null
}
return <FileContextMenu appState={appState} />
return <FileContextMenu viewControllerManager={viewControllerManager} />
}
export default observer(FileContextMenuWrapper)

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays'
import { DialogContent, DialogOverlay } from '@reach/dialog'
import { addToast, ToastType } from '@standardnotes/stylekit'
@@ -12,16 +12,16 @@ import { isFileTypePreviewable } from './isFilePreviewable'
import PreviewComponent from './PreviewComponent'
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
import { KeyboardKey } from '@/Services/IOService'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const FilePreviewModal: FunctionComponent<Props> = observer(({ application, appState }) => {
const { currentFile, setCurrentFile, otherFiles, dismiss } = appState.filePreviewModal
const FilePreviewModal: FunctionComponent<Props> = observer(({ application, viewControllerManager }) => {
const { currentFile, setCurrentFile, otherFiles, dismiss } = viewControllerManager.filePreviewModalController
if (!currentFile) {
return null
@@ -221,7 +221,10 @@ const FilePreviewModal: FunctionComponent<Props> = observer(({ application, appS
<Button
variant="normal"
onClick={() => {
application.getAppState().files.downloadFile(currentFile).catch(console.error)
application
.getViewControllerManager()
.filesController.downloadFile(currentFile)
.catch(console.error)
}}
>
Download
@@ -236,7 +239,10 @@ const FilePreviewModal: FunctionComponent<Props> = observer(({ application, appS
<Button
variant="primary"
onClick={() => {
application.getAppState().files.downloadFile(currentFile).catch(console.error)
application
.getViewControllerManager()
.filesController.downloadFile(currentFile)
.catch(console.error)
}}
>
Download
@@ -255,8 +261,10 @@ const FilePreviewModal: FunctionComponent<Props> = observer(({ application, appS
FilePreviewModal.displayName = 'FilePreviewModal'
const FilePreviewModalWrapper: FunctionComponent<Props> = ({ application, appState }) => {
return appState.filePreviewModal.isOpen ? <FilePreviewModal application={application} appState={appState} /> : null
const FilePreviewModalWrapper: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
return viewControllerManager.filePreviewModalController.isOpen ? (
<FilePreviewModal application={application} viewControllerManager={viewControllerManager} />
) : null
}
export default observer(FilePreviewModalWrapper)

View File

@@ -1,5 +1,5 @@
import { WebAppEvent, WebApplication } from '@/UIModels/Application'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { WebAppEvent, WebApplication } from '@/Application/Application'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { PureComponent } from '@/Components/Abstract/PureComponent'
import { destroyAllObjectProperties, preventRefreshing } from '@/Utils'
import { ApplicationEvent, ApplicationDescriptor } from '@standardnotes/snjs'
@@ -12,12 +12,13 @@ import {
} from '@/Strings'
import { alertDialog, confirmDialog } from '@/Services/AlertService'
import AccountMenu from '@/Components/AccountMenu/AccountMenu'
import { AppStateEvent, EventSource } from '@/UIModels/AppState'
import { ViewControllerManagerEvent } from '@/Services/ViewControllerManager'
import Icon from '@/Components/Icon/Icon'
import QuickSettingsMenu from '@/Components/QuickSettingsMenu/QuickSettingsMenu'
import SyncResolutionMenu from '@/Components/SyncResolutionMenu/SyncResolutionMenu'
import { Fragment } from 'react'
import { AccountMenuPane } from '../AccountMenu/AccountMenuPane'
import { EditorEventSource } from '@/Typings/EditorEventSource'
type Props = {
application: WebApplication
@@ -92,11 +93,11 @@ class Footer extends PureComponent<Props, State> {
})
this.autorun(() => {
const showBetaWarning = this.appState.showBetaWarning
const showBetaWarning = this.viewControllerManager.showBetaWarning
this.setState({
showBetaWarning: showBetaWarning,
showAccountMenu: this.appState.accountMenu.show,
showQuickSettingsMenu: this.appState.quickSettingsMenu.open,
showAccountMenu: this.viewControllerManager.accountMenuController.show,
showQuickSettingsMenu: this.viewControllerManager.quickSettingsMenuController.open,
})
})
}
@@ -132,18 +133,18 @@ class Footer extends PureComponent<Props, State> {
})
}
override onAppStateEvent(eventName: AppStateEvent, data: any) {
override onViewControllerManagerEvent(eventName: ViewControllerManagerEvent, data: any) {
const statusService = this.application.status
switch (eventName) {
case AppStateEvent.EditorFocused:
if (data.eventSource === EventSource.UserInteraction) {
case ViewControllerManagerEvent.EditorFocused:
if (data.eventSource === EditorEventSource.UserInteraction) {
this.closeAccountMenu()
}
break
case AppStateEvent.BeganBackupDownload:
case ViewControllerManagerEvent.BeganBackupDownload:
statusService.setMessage('Saving local backup…')
break
case AppStateEvent.EndedBackupDownload: {
case ViewControllerManagerEvent.EndedBackupDownload: {
const successMessage = 'Successfully saved backup.'
const errorMessage = 'Unable to save local backup.'
statusService.setMessage(data.success ? successMessage : errorMessage)
@@ -187,7 +188,7 @@ class Footer extends PureComponent<Props, State> {
if (!this.didCheckForOffline) {
this.didCheckForOffline = true
if (this.state.offline && this.application.items.getNoteCount() === 0) {
this.appState.accountMenu.setShow(true)
this.viewControllerManager.accountMenuController.setShow(true)
}
}
this.findErrors()
@@ -288,13 +289,13 @@ class Footer extends PureComponent<Props, State> {
}
accountMenuClickHandler = () => {
this.appState.quickSettingsMenu.closeQuickSettingsMenu()
this.appState.accountMenu.toggleShow()
this.viewControllerManager.quickSettingsMenuController.closeQuickSettingsMenu()
this.viewControllerManager.accountMenuController.toggleShow()
}
quickSettingsClickHandler = () => {
this.appState.accountMenu.closeAccountMenu()
this.appState.quickSettingsMenu.toggle()
this.viewControllerManager.accountMenuController.closeAccountMenu()
this.viewControllerManager.quickSettingsMenuController.toggle()
}
syncResolutionClickHandler = () => {
@@ -304,8 +305,8 @@ class Footer extends PureComponent<Props, State> {
}
closeAccountMenu = () => {
this.appState.accountMenu.setShow(false)
this.appState.accountMenu.setCurrentPane(AccountMenuPane.GeneralMenu)
this.viewControllerManager.accountMenuController.setShow(false)
this.viewControllerManager.accountMenuController.setCurrentPane(AccountMenuPane.GeneralMenu)
}
lockClickHandler = () => {
@@ -333,11 +334,11 @@ class Footer extends PureComponent<Props, State> {
}
clickOutsideAccountMenu = () => {
this.appState.accountMenu.closeAccountMenu()
this.viewControllerManager.accountMenuController.closeAccountMenu()
}
clickOutsideQuickSettingsMenu = () => {
this.appState.quickSettingsMenu.closeQuickSettingsMenu()
this.viewControllerManager.quickSettingsMenuController.closeQuickSettingsMenu()
}
override render() {
@@ -360,7 +361,7 @@ class Footer extends PureComponent<Props, State> {
{this.state.showAccountMenu && (
<AccountMenu
onClickOutside={this.clickOutsideAccountMenu}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
application={this.application}
mainApplicationGroup={this.props.applicationGroup}
/>
@@ -381,7 +382,7 @@ class Footer extends PureComponent<Props, State> {
{this.state.showQuickSettingsMenu && (
<QuickSettingsMenu
onClickOutside={this.clickOutsideQuickSettingsMenu}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
application={this.application}
/>
)}

View File

@@ -1,23 +1,23 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { IlNotesIcon } from '@standardnotes/icons'
import { observer } from 'mobx-react-lite'
import NotesOptionsPanel from '@/Components/NotesOptions/NotesOptionsPanel'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import PinNoteButton from '@/Components/PinNoteButton/PinNoteButton'
import Button from '../Button/Button'
import { useCallback } from 'react'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const MultipleSelectedNotes = ({ application, appState }: Props) => {
const count = appState.notes.selectedNotesCount
const MultipleSelectedNotes = ({ application, viewControllerManager }: Props) => {
const count = viewControllerManager.notesController.selectedNotesCount
const cancelMultipleSelection = useCallback(() => {
appState.selectedItems.cancelMultipleSelection()
}, [appState])
viewControllerManager.selectionController.cancelMultipleSelection()
}, [viewControllerManager])
return (
<div className="flex flex-col h-full items-center">
@@ -25,9 +25,9 @@ const MultipleSelectedNotes = ({ application, appState }: Props) => {
<h1 className="sk-h1 font-bold m-0">{count} selected notes</h1>
<div className="flex">
<div className="mr-3">
<PinNoteButton appState={appState} />
<PinNoteButton viewControllerManager={viewControllerManager} />
</div>
<NotesOptionsPanel application={application} appState={appState} />
<NotesOptionsPanel application={application} viewControllerManager={viewControllerManager} />
</div>
</div>
<div className="flex-grow flex flex-col justify-center items-center w-full max-w-md">

View File

@@ -1,6 +1,6 @@
import SmartViewsSection from '@/Components/Tags/SmartViewsSection'
import TagsSection from '@/Components/Tags/TagsSection'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { PANEL_NAME_NAVIGATION } from '@/Constants'
import { ApplicationEvent, PrefKey } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
@@ -12,7 +12,7 @@ type Props = {
}
const Navigation: FunctionComponent<Props> = ({ application }) => {
const appState = useMemo(() => application.getAppState(), [application])
const viewControllerManager = useMemo(() => application.getViewControllerManager(), [application])
const [ref, setRef] = useState<HTMLDivElement | null>()
const [panelWidth, setPanelWidth] = useState<number>(0)
@@ -32,15 +32,15 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
const panelResizeFinishCallback: ResizeFinishCallback = useCallback(
(width, _lastLeft, _isMaxWidth, isCollapsed) => {
application.setPreference(PrefKey.TagsPanelWidth, width).catch(console.error)
appState.noteTags.reloadTagsContainerMaxWidth()
appState.panelDidResize(PANEL_NAME_NAVIGATION, isCollapsed)
viewControllerManager.noteTagsController.reloadTagsContainerMaxWidth()
viewControllerManager.panelDidResize(PANEL_NAME_NAVIGATION, isCollapsed)
},
[application, appState],
[application, viewControllerManager],
)
const panelWidthEventCallback = useCallback(() => {
appState.noteTags.reloadTagsContainerMaxWidth()
}, [appState])
viewControllerManager.noteTagsController.reloadTagsContainerMaxWidth()
}, [viewControllerManager])
return (
<div
@@ -58,8 +58,8 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
</div>
</div>
<div className="scrollable">
<SmartViewsSection appState={appState} />
<TagsSection appState={appState} />
<SmartViewsSection viewControllerManager={viewControllerManager} />
<TagsSection viewControllerManager={viewControllerManager} />
</div>
</div>
{ref && (

View File

@@ -1,22 +1,22 @@
import Icon from '@/Components/Icon/Icon'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { MouseEventHandler, useCallback } from 'react'
type Props = { appState: AppState }
type Props = { viewControllerManager: ViewControllerManager }
const NoAccountWarning = observer(({ appState }: Props) => {
const NoAccountWarning = observer(({ viewControllerManager }: Props) => {
const showAccountMenu: MouseEventHandler = useCallback(
(event) => {
event.stopPropagation()
appState.accountMenu.setShow(true)
viewControllerManager.accountMenuController.setShow(true)
},
[appState],
[viewControllerManager],
)
const hideWarning = useCallback(() => {
appState.noAccountWarning.hide()
}, [appState])
viewControllerManager.noAccountWarningController.hide()
}, [viewControllerManager])
return (
<div className="mt-4 p-4 rounded-md shadow-sm grid grid-template-cols-1fr">
@@ -40,10 +40,10 @@ const NoAccountWarning = observer(({ appState }: Props) => {
NoAccountWarning.displayName = 'NoAccountWarning'
const NoAccountWarningWrapper = ({ appState }: Props) => {
const canShow = appState.noAccountWarning.show
const NoAccountWarningWrapper = ({ viewControllerManager }: Props) => {
const canShow = viewControllerManager.noAccountWarningController.show
return canShow ? <NoAccountWarning appState={appState} /> : null
return canShow ? <NoAccountWarning viewControllerManager={viewControllerManager} /> : null
}
export default observer(NoAccountWarningWrapper)

View File

@@ -1,6 +1,6 @@
import { NoteViewController } from '@standardnotes/snjs'
import { PureComponent } from '@/Components/Abstract/PureComponent'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import MultipleSelectedNotes from '@/Components/MultipleSelectedNotes/MultipleSelectedNotes'
import NoteView from '@/Components/NoteView/NoteView'
import { ElementIds } from '@/ElementIDs'
@@ -37,9 +37,9 @@ class NoteGroupView extends PureComponent<Props, State> {
})
this.autorun(() => {
if (this.appState && this.appState.notes) {
if (this.viewControllerManager && this.viewControllerManager.notesController) {
this.setState({
showMultipleSelectedNotes: this.appState.notes.selectedNotesCount > 1,
showMultipleSelectedNotes: this.viewControllerManager.notesController.selectedNotesCount > 1,
})
}
})
@@ -56,7 +56,7 @@ class NoteGroupView extends PureComponent<Props, State> {
return (
<div id={ElementIds.EditorColumn} className="h-full app-column app-column-third">
{this.state.showMultipleSelectedNotes && (
<MultipleSelectedNotes application={this.application} appState={this.appState} />
<MultipleSelectedNotes application={this.application} viewControllerManager={this.viewControllerManager} />
)}
{!this.state.showMultipleSelectedNotes && (

View File

@@ -8,17 +8,17 @@ import {
useRef,
useState,
} from 'react'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { SNTag } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
tag: SNTag
}
const NoteTag = ({ appState, tag }: Props) => {
const noteTags = appState.noteTags
const NoteTag = ({ viewControllerManager, tag }: Props) => {
const noteTags = viewControllerManager.noteTagsController
const { autocompleteInputFocused, focusedTagUuid, tags } = noteTags
@@ -33,9 +33,9 @@ const NoteTag = ({ appState, tag }: Props) => {
const longTitle = noteTags.getLongTitle(tag)
const deleteTag = useCallback(() => {
appState.noteTags.focusPreviousTag(tag)
appState.noteTags.removeTagFromActiveNote(tag).catch(console.error)
}, [appState, tag])
viewControllerManager.noteTagsController.focusPreviousTag(tag)
viewControllerManager.noteTagsController.removeTagFromActiveNote(tag).catch(console.error)
}, [viewControllerManager, tag])
const onDeleteTagClick: MouseEventHandler = useCallback(
(event) => {
@@ -49,28 +49,28 @@ const NoteTag = ({ appState, tag }: Props) => {
(event) => {
if (tagClicked && event.target !== deleteTagRef.current) {
setTagClicked(false)
void appState.tags.setSelectedTag(tag)
void viewControllerManager.navigationController.setSelectedTag(tag)
} else {
setTagClicked(true)
}
},
[appState, tagClicked, tag],
[viewControllerManager, tagClicked, tag],
)
const onFocus = useCallback(() => {
appState.noteTags.setFocusedTagUuid(tag.uuid)
viewControllerManager.noteTagsController.setFocusedTagUuid(tag.uuid)
setShowDeleteButton(true)
}, [appState, tag])
}, [viewControllerManager, tag])
const onBlur: FocusEventHandler = useCallback(
(event) => {
const relatedTarget = event.relatedTarget as Node
if (relatedTarget !== deleteTagRef.current) {
appState.noteTags.setFocusedTagUuid(undefined)
viewControllerManager.noteTagsController.setFocusedTagUuid(undefined)
setShowDeleteButton(false)
}
},
[appState],
[viewControllerManager],
)
const getTabIndex = useCallback(() => {
@@ -85,33 +85,33 @@ const NoteTag = ({ appState, tag }: Props) => {
const onKeyDown: KeyboardEventHandler = useCallback(
(event) => {
const tagIndex = appState.noteTags.getTagIndex(tag, tags)
const tagIndex = viewControllerManager.noteTagsController.getTagIndex(tag, tags)
switch (event.key) {
case 'Backspace':
deleteTag()
break
case 'ArrowLeft':
appState.noteTags.focusPreviousTag(tag)
viewControllerManager.noteTagsController.focusPreviousTag(tag)
break
case 'ArrowRight':
if (tagIndex === tags.length - 1) {
appState.noteTags.setAutocompleteInputFocused(true)
viewControllerManager.noteTagsController.setAutocompleteInputFocused(true)
} else {
appState.noteTags.focusNextTag(tag)
viewControllerManager.noteTagsController.focusNextTag(tag)
}
break
default:
return
}
},
[appState, deleteTag, tag, tags],
[viewControllerManager, deleteTag, tag, tags],
)
useEffect(() => {
if (focusedTagUuid === tag.uuid) {
tagRef.current?.focus()
}
}, [appState, focusedTagUuid, tag])
}, [viewControllerManager, focusedTagUuid, tag])
return (
<button

View File

@@ -1,19 +1,19 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import AutocompleteTagInput from '@/Components/TagAutocomplete/AutocompleteTagInput'
import NoteTag from './NoteTag'
import { useEffect } from 'react'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
}
const NoteTagsContainer = ({ appState }: Props) => {
const { tags, tagsContainerMaxWidth } = appState.noteTags
const NoteTagsContainer = ({ viewControllerManager }: Props) => {
const { tags, tagsContainerMaxWidth } = viewControllerManager.noteTagsController
useEffect(() => {
appState.noteTags.reloadTagsContainerMaxWidth()
}, [appState])
viewControllerManager.noteTagsController.reloadTagsContainerMaxWidth()
}, [viewControllerManager])
return (
<div
@@ -23,9 +23,9 @@ const NoteTagsContainer = ({ appState }: Props) => {
}}
>
{tags.map((tag) => (
<NoteTag key={tag.uuid} appState={appState} tag={tag} />
<NoteTag key={tag.uuid} viewControllerManager={viewControllerManager} tag={tag} />
))}
<AutocompleteTagInput appState={appState} />
<AutocompleteTagInput viewControllerManager={viewControllerManager} />
</div>
)
}

View File

@@ -2,9 +2,9 @@
* @jest-environment jsdom
*/
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { NotesState } from '@/UIModels/AppState/NotesState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { NotesController } from '@/Controllers/NotesController'
import {
ApplicationEvent,
ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction,
@@ -17,8 +17,8 @@ import NoteView from './NoteView'
describe('NoteView', () => {
let noteViewController: NoteViewController
let application: WebApplication
let appState: AppState
let notesState: NotesState
let viewControllerManager: ViewControllerManager
let notesState: NotesController
const createNoteView = () =>
new NoteView({
@@ -31,15 +31,15 @@ describe('NoteView', () => {
noteViewController = {} as jest.Mocked<NoteViewController>
notesState = {} as jest.Mocked<NotesState>
notesState = {} as jest.Mocked<NotesController>
notesState.setShowProtectedWarning = jest.fn()
appState = {
notes: notesState,
} as jest.Mocked<AppState>
viewControllerManager = {
notesController: notesState,
} as jest.Mocked<ViewControllerManager>
application = {} as jest.Mocked<WebApplication>
application.getAppState = jest.fn().mockReturnValue(appState)
application.getViewControllerManager = jest.fn().mockReturnValue(viewControllerManager)
application.hasProtectionSources = jest.fn().mockReturnValue(true)
application.authorizeNoteAccess = jest.fn()
})

View File

@@ -14,7 +14,7 @@ import {
PayloadEmitSource,
} from '@standardnotes/snjs'
import { debounce, isDesktopApplication } from '@/Utils'
import { EventSource } from '../../UIModels/AppState/EventSource'
import { EditorEventSource } from '../../Typings/EditorEventSource'
import { KeyboardModifier, KeyboardKey } from '@/Services/IOService'
import { STRING_DELETE_PLACEHOLDER_ATTEMPT, STRING_DELETE_LOCKED_ATTEMPT, StringDeleteNote } from '@/Strings'
import { confirmDialog } from '@/Services/AlertService'
@@ -82,7 +82,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
readonly controller!: NoteViewController
private statusTimeout?: NodeJS.Timeout
private lastEditorFocusEventSource?: EventSource
private lastEditorFocusEventSource?: EditorEventSource
onEditorComponentLoad?: () => void
private scrollPosition = 0
@@ -193,7 +193,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
this.autorun(() => {
this.setState({
showProtectedWarning: this.appState.notes.showProtectedWarning,
showProtectedWarning: this.viewControllerManager.notesController.showProtectedWarning,
})
})
@@ -577,7 +577,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
focusEditor() {
const element = document.getElementById(ElementIds.NoteTextEditor)
if (element) {
this.lastEditorFocusEventSource = EventSource.Script
this.lastEditorFocusEventSource = EditorEventSource.Script
element.focus()
}
}
@@ -588,13 +588,13 @@ class NoteView extends PureComponent<NoteViewProps, State> {
onContentFocus = () => {
if (this.lastEditorFocusEventSource) {
this.application.getAppState().editorDidFocus(this.lastEditorFocusEventSource)
this.application.getViewControllerManager().editorDidFocus(this.lastEditorFocusEventSource)
}
this.lastEditorFocusEventSource = undefined
}
setShowProtectedOverlay(show: boolean) {
this.appState.notes.setShowProtectedWarning(show)
this.viewControllerManager.notesController.setShowProtectedWarning(show)
}
async deleteNote(permanently: boolean) {
@@ -653,7 +653,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
}
async reloadSpellcheck() {
const spellcheck = this.appState.notes.getSpellcheckStateForNote(this.note)
const spellcheck = this.viewControllerManager.notesController.getSpellcheckStateForNote(this.note)
if (spellcheck !== this.state.spellcheck) {
this.setState({ textareaUnloading: true })
@@ -871,7 +871,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
{this.state.showProtectedWarning && (
<div className="h-full flex justify-center items-center">
<ProtectedNoteOverlay
appState={this.appState}
viewControllerManager={this.viewControllerManager}
hasProtectionSources={this.application.hasProtectionSources()}
onViewNote={this.dismissProtectedWarning}
/>
@@ -898,7 +898,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
showLockedIcon: false,
})
}}
onClick={() => this.appState.notes.setLockSelectedNotes(!this.state.noteLocked)}
onClick={() => this.viewControllerManager.notesController.setLockSelectedNotes(!this.state.noteLocked)}
showLockedIcon={this.state.showLockedIcon}
lockText={this.state.lockText}
/>
@@ -942,31 +942,31 @@ class NoteView extends PureComponent<NoteViewProps, State> {
<div className="mr-3">
<AttachedFilesButton
application={this.application}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</div>
<div className="mr-3">
<ChangeEditorButton
application={this.application}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</div>
<div className="mr-3">
<PinNoteButton
appState={this.appState}
viewControllerManager={this.viewControllerManager}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</div>
<NotesOptionsPanel
application={this.application}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</div>
</div>
<NoteTagsContainer appState={this.appState} />
<NoteTagsContainer viewControllerManager={this.viewControllerManager} />
</div>
)}
@@ -993,7 +993,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
onLoad={this.onEditorComponentLoad}
requestReload={this.editorComponentViewerRequestsReload}
application={this.application}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
/>
</div>
)}
@@ -1068,7 +1068,7 @@ class NoteView extends PureComponent<NoteViewProps, State> {
key={viewer.identifier}
componentViewer={viewer}
application={this.application}
appState={this.appState}
viewControllerManager={this.viewControllerManager}
/>
</div>
)

View File

@@ -1,6 +1,6 @@
import { NoteViewController } from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
export interface NoteViewProps {
application: WebApplication

View File

@@ -1,27 +1,29 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { observer } from 'mobx-react-lite'
import NotesOptions from '@/Components/NotesOptions/NotesOptions'
import { useCallback, useEffect, useRef } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const NotesContextMenu = ({ application, appState }: Props) => {
const { contextMenuOpen, contextMenuPosition, contextMenuMaxHeight } = appState.notes
const NotesContextMenu = ({ application, viewControllerManager }: Props) => {
const { contextMenuOpen, contextMenuPosition, contextMenuMaxHeight } = viewControllerManager.notesController
const contextMenuRef = useRef<HTMLDivElement>(null)
const [closeOnBlur] = useCloseOnBlur(contextMenuRef, (open: boolean) => appState.notes.setContextMenuOpen(open))
const [closeOnBlur] = useCloseOnBlur(contextMenuRef, (open: boolean) =>
viewControllerManager.notesController.setContextMenuOpen(open),
)
useCloseOnClickOutside(contextMenuRef, () => appState.notes.setContextMenuOpen(false))
useCloseOnClickOutside(contextMenuRef, () => viewControllerManager.notesController.setContextMenuOpen(false))
const reloadContextMenuLayout = useCallback(() => {
appState.notes.reloadContextMenuLayout()
}, [appState])
viewControllerManager.notesController.reloadContextMenuLayout()
}, [viewControllerManager])
useEffect(() => {
window.addEventListener('resize', reloadContextMenuLayout)
@@ -39,7 +41,7 @@ const NotesContextMenu = ({ application, appState }: Props) => {
maxHeight: contextMenuMaxHeight,
}}
>
<NotesOptions application={application} appState={appState} closeOnBlur={closeOnBlur} />
<NotesOptions application={application} viewControllerManager={viewControllerManager} closeOnBlur={closeOnBlur} />
</div>
) : null
}

View File

@@ -1,4 +1,4 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { observer } from 'mobx-react-lite'
@@ -7,10 +7,10 @@ import Icon from '@/Components/Icon/Icon'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
}
const AddTagOption: FunctionComponent<Props> = ({ appState }) => {
const AddTagOption: FunctionComponent<Props> = ({ viewControllerManager }) => {
const menuContainerRef = useRef<HTMLDivElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const menuButtonRef = useRef<HTMLButtonElement>(null)
@@ -84,22 +84,22 @@ const AddTagOption: FunctionComponent<Props> = ({ appState }) => {
}}
className="sn-dropdown min-w-80 flex flex-col py-2 max-h-120 max-w-xs fixed overflow-y-auto"
>
{appState.tags.tags.map((tag) => (
{viewControllerManager.navigationController.tags.map((tag) => (
<button
key={tag.uuid}
className="sn-dropdown-item sn-dropdown-item--no-icon max-w-80"
onBlur={closeOnBlur}
onClick={() => {
appState.notes.isTagInSelectedNotes(tag)
? appState.notes.removeTagFromSelectedNotes(tag).catch(console.error)
: appState.notes.addTagToSelectedNotes(tag).catch(console.error)
viewControllerManager.notesController.isTagInSelectedNotes(tag)
? viewControllerManager.notesController.removeTagFromSelectedNotes(tag).catch(console.error)
: viewControllerManager.notesController.addTagToSelectedNotes(tag).catch(console.error)
}}
>
<span
className={`whitespace-nowrap overflow-hidden overflow-ellipsis
${appState.notes.isTagInSelectedNotes(tag) ? 'font-bold' : ''}`}
${viewControllerManager.notesController.isTagInSelectedNotes(tag) ? 'font-bold' : ''}`}
>
{appState.noteTags.getLongTitle(tag)}
{viewControllerManager.noteTagsController.getLongTitle(tag)}
</span>
</button>
))}

View File

@@ -1,6 +1,6 @@
import { KeyboardKey } from '@/Services/IOService'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { SNNote } from '@standardnotes/snjs'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
@@ -10,7 +10,7 @@ import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuSty
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
type ChangeEditorOptionProps = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
note: SNNote
}

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { Action, ListedAccount, SNNote } from '@standardnotes/snjs'

View File

@@ -1,4 +1,4 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import Icon from '@/Components/Icon/Icon'
import Switch from '@/Components/Switch/Switch'
import { observer } from 'mobx-react-lite'
@@ -121,15 +121,15 @@ const NoteAttributes: FunctionComponent<{
}
const SpellcheckOptions: FunctionComponent<{
appState: AppState
viewControllerManager: ViewControllerManager
note: SNNote
}> = ({ appState, note }) => {
const editor = appState.application.componentManager.editorForNote(note)
}> = ({ viewControllerManager, note }) => {
const editor = viewControllerManager.application.componentManager.editorForNote(note)
const spellcheckControllable = Boolean(!editor || editor.package_info.spellcheckControl)
const noteSpellcheck = !spellcheckControllable
? true
: note
? appState.notes.getSpellcheckStateForNote(note)
? viewControllerManager.notesController.getSpellcheckStateForNote(note)
: undefined
return (
@@ -137,7 +137,7 @@ const SpellcheckOptions: FunctionComponent<{
<button
className="sn-dropdown-item justify-between px-3 py-1"
onClick={() => {
appState.notes.toggleGlobalSpellcheckForNote(note).catch(console.error)
viewControllerManager.notesController.toggleGlobalSpellcheckForNote(note).catch(console.error)
}}
disabled={!spellcheckControllable}
>
@@ -169,7 +169,7 @@ const NoteSizeWarning: FunctionComponent<{
) : null
}
const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps) => {
const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: NotesOptionsProps) => {
const [altKeyDown, setAltKeyDown] = useState(false)
const toggleOn = (condition: (note: SNNote) => boolean) => {
@@ -178,7 +178,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
return notesMatchingAttribute.length > notesNotMatchingAttribute.length
}
const notes = appState.notes.selectedNotes
const notes = viewControllerManager.notesController.selectedNotes
const hidePreviews = toggleOn((note) => note.hidePreview)
const locked = toggleOn((note) => note.locked)
const protect = toggleOn((note) => note.protected)
@@ -248,8 +248,8 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
}, [application, notes])
const openRevisionHistoryModal = useCallback(() => {
appState.notes.setShowRevisionHistoryModal(true)
}, [appState])
viewControllerManager.notesController.setShowRevisionHistoryModal(true)
}, [viewControllerManager])
return (
<>
@@ -265,7 +265,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
<button
className="sn-dropdown-item justify-between"
onClick={() => {
appState.notes.setLockSelectedNotes(!locked)
viewControllerManager.notesController.setLockSelectedNotes(!locked)
}}
onBlur={closeOnBlur}
>
@@ -278,7 +278,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
<button
className="sn-dropdown-item justify-between"
onClick={() => {
appState.notes.setHideSelectedNotePreviews(!hidePreviews)
viewControllerManager.notesController.setHideSelectedNotePreviews(!hidePreviews)
}}
onBlur={closeOnBlur}
>
@@ -291,7 +291,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
<button
className="sn-dropdown-item justify-between"
onClick={() => {
appState.notes.setProtectSelectedNotes(!protect).catch(console.error)
viewControllerManager.notesController.setProtectSelectedNotes(!protect).catch(console.error)
}}
onBlur={closeOnBlur}
>
@@ -304,17 +304,19 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
{notes.length === 1 && (
<>
<div className="min-h-1px my-2 bg-border"></div>
<ChangeEditorOption appState={appState} application={application} note={notes[0]} />
<ChangeEditorOption viewControllerManager={viewControllerManager} application={application} note={notes[0]} />
</>
)}
<div className="min-h-1px my-2 bg-border"></div>
{appState.tags.tagsCount > 0 && <AddTagOption appState={appState} />}
{viewControllerManager.navigationController.tagsCount > 0 && (
<AddTagOption viewControllerManager={viewControllerManager} />
)}
{unpinned && (
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
appState.notes.setPinSelectedNotes(true)
viewControllerManager.notesController.setPinSelectedNotes(true)
}}
>
<Icon type="pin" className={iconClass} />
@@ -326,7 +328,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
appState.notes.setPinSelectedNotes(false)
viewControllerManager.notesController.setPinSelectedNotes(false)
}}
>
<Icon type="unpin" className={iconClass} />
@@ -346,7 +348,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
appState.notes.setArchiveSelectedNotes(true).catch(console.error)
viewControllerManager.notesController.setArchiveSelectedNotes(true).catch(console.error)
}}
>
<Icon type="archive" className={iconClassWarning} />
@@ -358,7 +360,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
appState.notes.setArchiveSelectedNotes(false).catch(console.error)
viewControllerManager.notesController.setArchiveSelectedNotes(false).catch(console.error)
}}
>
<Icon type="unarchive" className={iconClassWarning} />
@@ -370,7 +372,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
<DeletePermanentlyButton
closeOnBlur={closeOnBlur}
onClick={async () => {
await appState.notes.deleteNotesPermanently()
await viewControllerManager.notesController.deleteNotesPermanently()
}}
/>
) : (
@@ -378,7 +380,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await appState.notes.setTrashSelectedNotes(true)
await viewControllerManager.notesController.setTrashSelectedNotes(true)
}}
>
<Icon type="trash" className={iconClassDanger} />
@@ -391,7 +393,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await appState.notes.setTrashSelectedNotes(false)
await viewControllerManager.notesController.setTrashSelectedNotes(false)
}}
>
<Icon type="restore" className={iconClassSuccess} />
@@ -400,21 +402,21 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
<DeletePermanentlyButton
closeOnBlur={closeOnBlur}
onClick={async () => {
await appState.notes.deleteNotesPermanently()
await viewControllerManager.notesController.deleteNotesPermanently()
}}
/>
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await appState.notes.emptyTrash()
await viewControllerManager.notesController.emptyTrash()
}}
>
<div className="flex items-start">
<Icon type="trash-sweep" className="color-danger mr-2" />
<div className="flex-row">
<div className="color-danger">Empty Trash</div>
<div className="text-xs">{appState.notes.trashedNotesCount} notes in Trash</div>
<div className="text-xs">{viewControllerManager.notesController.trashedNotesCount} notes in Trash</div>
</div>
</div>
</button>
@@ -425,7 +427,7 @@ const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps)
<div className="min-h-1px my-2 bg-border"></div>
<ListedActionsOption application={application} note={notes[0]} />
<div className="min-h-1px my-2 bg-border"></div>
<SpellcheckOptions appState={appState} note={notes[0]} />
<SpellcheckOptions viewControllerManager={viewControllerManager} note={notes[0]} />
<div className="min-h-1px my-2 bg-border"></div>
<NoteAttributes application={application} note={notes[0]} />
<NoteSizeWarning note={notes[0]} />

View File

@@ -1,4 +1,4 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import Icon from '@/Components/Icon/Icon'
import VisuallyHidden from '@reach/visually-hidden'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
@@ -6,16 +6,16 @@ import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure
import { useRef, useState } from 'react'
import { observer } from 'mobx-react-lite'
import NotesOptions from './NotesOptions'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
onClickPreprocessing?: () => Promise<void>
}
const NotesOptionsPanel = ({ application, appState, onClickPreprocessing }: Props) => {
const NotesOptionsPanel = ({ application, viewControllerManager, onClickPreprocessing }: Props) => {
const [open, setOpen] = useState(false)
const [position, setPosition] = useState({
top: 0,
@@ -79,7 +79,13 @@ const NotesOptionsPanel = ({ application, appState, onClickPreprocessing }: Prop
onBlur={closeOnBlur}
tabIndex={FOCUSABLE_BUT_NOT_TABBABLE}
>
{open && <NotesOptions application={application} appState={appState} closeOnBlur={closeOnBlur} />}
{open && (
<NotesOptions
application={application}
viewControllerManager={viewControllerManager}
closeOnBlur={closeOnBlur}
/>
)}
</DisclosurePanel>
</Disclosure>
)

View File

@@ -1,8 +1,8 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
export type NotesOptionsProps = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
}

View File

@@ -1,20 +1,20 @@
import { useCallback, useRef } from 'react'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const ConfirmOtherSessionsSignOut = observer(({ application, appState }: Props) => {
const ConfirmOtherSessionsSignOut = observer(({ application, viewControllerManager }: Props) => {
const cancelRef = useRef<HTMLButtonElement>(null)
const closeDialog = useCallback(() => {
appState.accountMenu.setOtherSessionsSignOut(false)
}, [appState])
viewControllerManager.accountMenuController.setOtherSessionsSignOut(false)
}, [viewControllerManager])
return (
<AlertDialog onDismiss={closeDialog} leastDestructiveRef={cancelRef}>
@@ -62,7 +62,7 @@ const ConfirmOtherSessionsSignOut = observer(({ application, appState }: Props)
ConfirmOtherSessionsSignOut.displayName = 'ConfirmOtherSessionsSignOut'
const OtherSessionsSignOutContainer = (props: Props) => {
if (!props.appState.accountMenu.otherSessionsSignOut) {
if (!props.viewControllerManager.accountMenuController.otherSessionsSignOut) {
return null
}
return <ConfirmOtherSessionsSignOut {...props} />

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ChangeEventHandler, createRef } from 'react'
import { PureComponent } from '@/Components/Abstract/PureComponent'

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { SNComponent } from '@standardnotes/snjs'
import { Component } from 'react'

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ApplicationEvent, PermissionDialog } from '@standardnotes/snjs'
import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import PermissionsModal from './PermissionsModal'

View File

@@ -1,17 +1,21 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import VisuallyHidden from '@reach/visually-hidden'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback } from 'react'
import Icon from '@/Components/Icon/Icon'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
className?: string
onClickPreprocessing?: () => Promise<void>
}
const PinNoteButton: FunctionComponent<Props> = ({ appState, className = '', onClickPreprocessing }: Props) => {
const notes = appState.notes.selectedNotes
const PinNoteButton: FunctionComponent<Props> = ({
viewControllerManager,
className = '',
onClickPreprocessing,
}: Props) => {
const notes = viewControllerManager.notesController.selectedNotes
const pinned = notes.some((note) => note.pinned)
const togglePinned = useCallback(async () => {
@@ -19,11 +23,11 @@ const PinNoteButton: FunctionComponent<Props> = ({ appState, className = '', onC
await onClickPreprocessing()
}
if (!pinned) {
appState.notes.setPinSelectedNotes(true)
viewControllerManager.notesController.setPinSelectedNotes(true)
} else {
appState.notes.setPinSelectedNotes(false)
viewControllerManager.notesController.setPinSelectedNotes(false)
}
}, [appState, onClickPreprocessing, pinned])
}, [viewControllerManager, onClickPreprocessing, pinned])
return (
<button className={`sn-icon-button border-contrast ${pinned ? 'toggled' : ''} ${className}`} onClick={togglePinned}>

View File

@@ -12,7 +12,7 @@ import { PreferencesProps } from './PreferencesProps'
const PaneSelector: FunctionComponent<PreferencesProps & { menu: PreferencesMenu }> = ({
menu,
appState,
viewControllerManager,
application,
mfaProvider,
userProvider,
@@ -21,21 +21,26 @@ const PaneSelector: FunctionComponent<PreferencesProps & { menu: PreferencesMenu
case 'general':
return (
<General
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
extensionsLatestVersions={menu.extensionsLatestVersions}
/>
)
case 'account':
return <AccountPreferences application={application} appState={appState} />
return <AccountPreferences application={application} viewControllerManager={viewControllerManager} />
case 'appearance':
return <Appearance application={application} />
case 'security':
return (
<Security mfaProvider={mfaProvider} userProvider={userProvider} appState={appState} application={application} />
<Security
mfaProvider={mfaProvider}
userProvider={userProvider}
viewControllerManager={viewControllerManager}
application={application}
/>
)
case 'backups':
return <Backups application={application} appState={appState} />
return <Backups application={application} viewControllerManager={viewControllerManager} />
case 'listed':
return <Listed application={application} />
case 'shortcuts':
@@ -49,7 +54,7 @@ const PaneSelector: FunctionComponent<PreferencesProps & { menu: PreferencesMenu
default:
return (
<General
appState={appState}
viewControllerManager={viewControllerManager}
application={application}
extensionsLatestVersions={menu.extensionsLatestVersions}
/>

View File

@@ -1,6 +1,6 @@
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import Authentication from './Authentication'
import Credentials from './Credentials'
import Sync from './Sync'
@@ -11,22 +11,24 @@ import PreferencesPane from '../../PreferencesComponents/PreferencesPane'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const AccountPreferences = ({ application, appState }: Props) => (
const AccountPreferences = ({ application, viewControllerManager }: Props) => (
<PreferencesPane>
{!application.hasAccount() ? (
<Authentication application={application} appState={appState} />
<Authentication application={application} viewControllerManager={viewControllerManager} />
) : (
<>
<Credentials application={application} appState={appState} />
<Credentials application={application} viewControllerManager={viewControllerManager} />
<Sync application={application} />
</>
)}
<Subscription application={application} appState={appState} />
{application.hasAccount() && appState.features.hasFiles && <FilesSection application={application} />}
<SignOutWrapper application={application} appState={appState} />
<Subscription application={application} viewControllerManager={viewControllerManager} />
{application.hasAccount() && viewControllerManager.featuresController.hasFiles && (
<FilesSection application={application} />
)}
<SignOutWrapper application={application} viewControllerManager={viewControllerManager} />
</PreferencesPane>
)

View File

@@ -1,8 +1,8 @@
import { FunctionComponent } from 'react'
import OfflineSubscription from '@/Components/Preferences/Panes/Account/OfflineSubscription'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { observer } from 'mobx-react-lite'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import Extensions from '@/Components/Preferences/Panes/Extensions/Extensions'
import { ExtensionsLatestVersions } from '@/Components/Preferences/Panes/Extensions/ExtensionsLatestVersions'
import AccordionItem from '@/Components/Shared/AccordionItem'
@@ -11,18 +11,18 @@ import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
extensionsLatestVersions: ExtensionsLatestVersions
}
const Advanced: FunctionComponent<Props> = ({ application, appState, extensionsLatestVersions }) => {
const Advanced: FunctionComponent<Props> = ({ application, viewControllerManager, extensionsLatestVersions }) => {
return (
<PreferencesGroup>
<PreferencesSegment>
<AccordionItem title={'Advanced Settings'}>
<div className="flex flex-row items-center">
<div className="flex-grow flex flex-col">
<OfflineSubscription application={application} appState={appState} />
<OfflineSubscription application={application} viewControllerManager={viewControllerManager} />
<Extensions
className={'mt-3'}
application={application}

View File

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

View File

@@ -4,7 +4,7 @@ import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription'
import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel'
import Button from '@/Components/Button/Button'
import { FunctionComponent, useState } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { useBeforeUnload } from '@/Hooks/useBeforeUnload'
import ChangeEmailForm from './ChangeEmailForm'
import ChangeEmailSuccess from './ChangeEmailSuccess'

View File

@@ -1,5 +1,5 @@
import Button from '@/Components/Button/Button'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { Title, Text } from '../../PreferencesComponents/Content'
@@ -7,8 +7,8 @@ import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
const ClearSessionDataView: FunctionComponent<{
appState: AppState
}> = ({ appState }) => {
viewControllerManager: ViewControllerManager
}> = ({ viewControllerManager }) => {
return (
<PreferencesGroup>
<PreferencesSegment>
@@ -19,7 +19,7 @@ const ClearSessionDataView: FunctionComponent<{
dangerStyle={true}
label="Clear workspace"
onClick={() => {
appState.accountMenu.setSigningOut(true)
viewControllerManager.accountMenuController.setSigningOut(true)
}}
/>
</PreferencesSegment>

View File

@@ -1,19 +1,19 @@
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { observer } from '@node_modules/mobx-react-lite'
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 { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import PasswordWizard from '@/Components/PasswordWizard/PasswordWizard'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const Credentials: FunctionComponent<Props> = ({ application }: Props) => {

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { SubscriptionSettingName } from '@standardnotes/snjs'
import { FunctionComponent, useEffect, useState } from 'react'

View File

@@ -2,8 +2,8 @@ import React, { FunctionComponent, useEffect, useState } from 'react'
import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import DecoratedInput from '@/Components/Input/DecoratedInput'
import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { STRING_REMOVE_OFFLINE_KEY_CONFIRMATION } from '@/Strings'
import { ButtonType, ClientDisplayableError } from '@standardnotes/snjs'
@@ -11,7 +11,7 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const OfflineSubscription: FunctionComponent<Props> = ({ application }) => {

View File

@@ -1,8 +1,8 @@
import Button from '@/Components/Button/Button'
import OtherSessionsSignOutContainer from '@/Components/OtherSessionsSignOut/OtherSessionsSignOut'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { Subtitle, Title, Text } from '../../PreferencesComponents/Content'
@@ -12,10 +12,10 @@ import ClearSessionDataView from './ClearSessionDataView'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const SignOutView: FunctionComponent<Props> = observer(({ application, appState }) => {
const SignOutView: FunctionComponent<Props> = observer(({ application, viewControllerManager }) => {
return (
<>
<PreferencesGroup>
@@ -30,10 +30,14 @@ const SignOutView: FunctionComponent<Props> = observer(({ application, appState
variant="normal"
label="Sign out other sessions"
onClick={() => {
appState.accountMenu.setOtherSessionsSignOut(true)
viewControllerManager.accountMenuController.setOtherSessionsSignOut(true)
}}
/>
<Button variant="normal" label="Manage sessions" onClick={() => appState.openSessionsModal()} />
<Button
variant="normal"
label="Manage sessions"
onClick={() => viewControllerManager.openSessionsModal()}
/>
</div>
</PreferencesSegment>
<HorizontalSeparator classes="my-4" />
@@ -45,23 +49,23 @@ const SignOutView: FunctionComponent<Props> = observer(({ application, appState
dangerStyle={true}
label="Sign out workspace"
onClick={() => {
appState.accountMenu.setSigningOut(true)
viewControllerManager.accountMenuController.setSigningOut(true)
}}
/>
</PreferencesSegment>
</PreferencesGroup>
<OtherSessionsSignOutContainer appState={appState} application={application} />
<OtherSessionsSignOutContainer viewControllerManager={viewControllerManager} application={application} />
</>
)
})
SignOutView.displayName = 'SignOutView'
const SignOutWrapper: FunctionComponent<Props> = ({ application, appState }) => {
const SignOutWrapper: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
if (!application.hasAccount()) {
return <ClearSessionDataView appState={appState} />
return <ClearSessionDataView viewControllerManager={viewControllerManager} />
}
return <SignOutView appState={appState} application={application} />
return <SignOutView viewControllerManager={viewControllerManager} application={application} />
}
export default observer(SignOutWrapper)

View File

@@ -1,7 +1,7 @@
import { FunctionComponent, useState } from 'react'
import { LinkButton, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { loadPurchaseFlowUrl } from '@/Components/PurchaseFlow/PurchaseFlowFunctions'
type Props = {

View File

@@ -1,8 +1,8 @@
import { SubscriptionState } from '@/UIModels/AppState/SubscriptionState'
import { SubscriptionController } from '@/Controllers/Subscription/SubscriptionController'
import { observer } from 'mobx-react-lite'
import { Text } from '@/Components/Preferences/PreferencesComponents/Content'
type Props = { subscriptionState: SubscriptionState }
type Props = { subscriptionState: SubscriptionController }
const StatusText = ({ subscriptionState }: Props) => {
const {

View File

@@ -1,20 +1,20 @@
import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import SubscriptionInformation from './SubscriptionInformation'
import NoSubscription from './NoSubscription'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const Subscription: FunctionComponent<Props> = ({ application, appState }: Props) => {
const subscriptionState = appState.subscription
const Subscription: FunctionComponent<Props> = ({ application, viewControllerManager }: Props) => {
const subscriptionState = viewControllerManager.subscriptionController
const { userSubscription } = subscriptionState
const now = new Date().getTime()

View File

@@ -1,12 +1,12 @@
import { observer } from 'mobx-react-lite'
import { SubscriptionState } from '@/UIModels/AppState/SubscriptionState'
import { SubscriptionController } from '@/Controllers/Subscription/SubscriptionController'
import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { openSubscriptionDashboard } from '@/Utils/ManageSubscription'
import StatusText from './StatusText'
type Props = {
subscriptionState: SubscriptionState
subscriptionState: SubscriptionController
application: WebApplication
}

View File

@@ -3,7 +3,7 @@ import Button from '@/Components/Button/Button'
import { SyncQueueStrategy } from '@standardnotes/snjs'
import { STRING_GENERIC_SYNC_ERROR } from '@/Strings'
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FunctionComponent, useState } from 'react'
import { formatLastSyncDate } from '@/Utils/FormatLastSyncDate'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'

View File

@@ -3,7 +3,7 @@ import { DropdownItem } from '@/Components/Dropdown/DropdownItem'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Switch from '@/Components/Switch/Switch'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ContentType, FeatureIdentifier, FeatureStatus, PrefKey, GetFeatures, SNTheme } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useEffect, useState } from 'react'

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { FunctionComponent } from 'react'
import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane'
import CloudLink from './CloudBackups/CloudBackups'
@@ -9,14 +9,14 @@ import FileBackupsCrossPlatform from './Files/FileBackupsCrossPlatform'
import { observer } from 'mobx-react-lite'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
}
const Backups: FunctionComponent<Props> = ({ application, appState }) => {
const Backups: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
return (
<PreferencesPane>
<DataBackups application={application} appState={appState} />
<DataBackups application={application} viewControllerManager={viewControllerManager} />
<FileBackupsCrossPlatform application={application} />
<EmailBackups application={application} />
<CloudLink application={application} />

View File

@@ -15,7 +15,7 @@ import {
GoogleDriveBackupFrequency,
OneDriveBackupFrequency,
} from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import Button from '@/Components/Button/Button'
import { isDev, openInNewTab } from '@/Utils'
import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'

View File

@@ -1,6 +1,6 @@
import CloudBackupProvider from './CloudBackupProvider'
import { useCallback, useEffect, useState, FunctionComponent, Fragment } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import {

View File

@@ -12,8 +12,8 @@ import {
} from '@/Strings'
import { BackupFile } from '@standardnotes/snjs'
import { ChangeEventHandler, MouseEventHandler, useCallback, useEffect, useRef, useState } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
@@ -23,10 +23,10 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const DataBackups = ({ application, appState }: Props) => {
const DataBackups = ({ application, viewControllerManager }: Props) => {
const fileInputRef = useRef<HTMLInputElement>(null)
const [isImportDataLoading, setIsImportDataLoading] = useState(false)
const {
@@ -35,7 +35,7 @@ const DataBackups = ({ application, appState }: Props) => {
setIsBackupEncrypted,
setIsEncryptionEnabled,
setEncryptionStatusString,
} = appState.accountMenu
} = viewControllerManager.accountMenuController
const refreshEncryptionStatus = useCallback(() => {
const hasUser = application.hasAccount()

View File

@@ -1,7 +1,7 @@
import { convertStringifiedBooleanToBoolean, isDesktopApplication } from '@/Utils'
import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Strings'
import { useCallback, useEffect, useState } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { observer } from 'mobx-react-lite'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import Dropdown from '@/Components/Dropdown/Dropdown'

View File

@@ -6,7 +6,7 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Icon from '@/Components/Icon/Icon'
import { StreamingFileApi } from '@standardnotes/filepicker'
import { isHandlingBackupDrag } from '@/Utils/DragTypeCheck'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import EncryptionStatusItem from '../../Security/EncryptionStatusItem'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'

View File

@@ -1,7 +1,7 @@
import { Subtitle, Title, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { useMemo } from 'react'
import BackupsDropZone from './BackupsDropZone'
import FileBackupsDesktop from './FileBackupsDesktop'

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { observer } from 'mobx-react-lite'
import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { useCallback, useEffect, useState } from 'react'

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { AnyExtension } from './AnyExtension'
export interface ExtensionItemProps {

View File

@@ -1,7 +1,7 @@
import { ButtonType, ContentType, SNComponent } from '@standardnotes/snjs'
import Button from '@/Components/Button/Button'
import DecoratedInput from '@/Components/Input/DecoratedInput'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FunctionComponent, useEffect, useRef, useState } from 'react'
import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { observer } from 'mobx-react-lite'

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ClientDisplayableError, FeatureDescription } from '@standardnotes/snjs'
import { makeAutoObservable, observable } from 'mobx'
import { AnyExtension } from './AnyExtension'

View File

@@ -2,7 +2,7 @@ import Dropdown from '@/Components/Dropdown/Dropdown'
import { DropdownItem } from '@/Components/Dropdown/DropdownItem'
import { FeatureIdentifier, PrefKey, ComponentArea, ComponentMutator, SNComponent } from '@standardnotes/snjs'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FunctionComponent, useEffect, useState } from 'react'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Switch from '@/Components/Switch/Switch'
@@ -57,7 +57,7 @@ const Defaults: FunctionComponent<Props> = ({ application }) => {
const toggleSpellcheck = () => {
setSpellcheck(!spellcheck)
application.getAppState().toggleGlobalSpellcheck().catch(console.error)
application.getViewControllerManager().toggleGlobalSpellcheck().catch(console.error)
}
useEffect(() => {

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { FunctionComponent } from 'react'
import { ExtensionsLatestVersions } from '@/Components/Preferences/Panes/Extensions/ExtensionsLatestVersions'
import { observer } from 'mobx-react-lite'
@@ -10,17 +10,21 @@ import Advanced from '@/Components/Preferences/Panes/Account/Advanced'
import PreferencesPane from '../../PreferencesComponents/PreferencesPane'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
extensionsLatestVersions: ExtensionsLatestVersions
}
const General: FunctionComponent<Props> = ({ appState, application, extensionsLatestVersions }) => (
const General: FunctionComponent<Props> = ({ viewControllerManager, application, extensionsLatestVersions }) => (
<PreferencesPane>
<Tools application={application} />
<Defaults application={application} />
<LabsPane application={application} />
<Advanced application={application} appState={appState} extensionsLatestVersions={extensionsLatestVersions} />
<Advanced
application={application}
viewControllerManager={viewControllerManager}
extensionsLatestVersions={extensionsLatestVersions}
/>
</PreferencesPane>
)

View File

@@ -1,6 +1,6 @@
import Switch from '@/Components/Switch/Switch'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FeatureIdentifier, FeatureStatus, FindNativeFeature } from '@standardnotes/snjs'
import { Fragment, FunctionComponent, useCallback, useEffect, useState } from 'react'
import { usePremiumModal } from '@/Hooks/usePremiumModal'

View File

@@ -1,7 +1,7 @@
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Switch from '@/Components/Switch/Switch'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { PrefKey } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useState } from 'react'

View File

@@ -1,6 +1,6 @@
import { Title, Subtitle, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ButtonType, ListedAccount } from '@standardnotes/snjs'
import { useCallback, useEffect, useState } from 'react'
import ListedAccountItem from './ListedAccountItem'

View File

@@ -1,6 +1,6 @@
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import { LinkButton, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ListedAccount, ListedAccountInfo } from '@standardnotes/snjs'
import { FunctionComponent, useEffect, useState } from 'react'

View File

@@ -1,5 +1,5 @@
import { STRING_E2E_ENABLED, STRING_ENC_NOT_ENABLED, STRING_LOCAL_ENC_ENABLED } from '@/Strings'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { Title, Text } from '../../PreferencesComponents/Content'
@@ -7,10 +7,10 @@ import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
import EncryptionEnabled from './EncryptionEnabled'
type Props = { appState: AppState }
type Props = { viewControllerManager: ViewControllerManager }
const Encryption: FunctionComponent<Props> = ({ appState }) => {
const app = appState.application
const Encryption: FunctionComponent<Props> = ({ viewControllerManager }) => {
const app = viewControllerManager.application
const hasUser = app.hasAccount()
const hasPasscode = app.hasPasscode()
const isEncryptionEnabled = app.isEncryptionAvailable()
@@ -27,7 +27,7 @@ const Encryption: FunctionComponent<Props> = ({ appState }) => {
<Title>Encryption</Title>
<Text>{encryptionStatusString}</Text>
{isEncryptionEnabled && <EncryptionEnabled appState={appState} />}
{isEncryptionEnabled && <EncryptionEnabled viewControllerManager={viewControllerManager} />}
</PreferencesSegment>
</PreferencesGroup>
)

View File

@@ -1,16 +1,16 @@
import Icon from '@/Components/Icon/Icon'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import EncryptionStatusItem from './EncryptionStatusItem'
import { formatCount } from './formatCount'
type Props = {
appState: AppState
viewControllerManager: ViewControllerManager
}
const EncryptionEnabled: FunctionComponent<Props> = ({ appState }) => {
const count = appState.accountMenu.structuredNotesAndTagsCount
const EncryptionEnabled: FunctionComponent<Props> = ({ viewControllerManager }) => {
const count = viewControllerManager.accountMenuController.structuredNotesAndTagsCount
const notes = formatCount(count.notes, 'notes')
const tags = formatCount(count.tags, 'tags')
const archived = formatCount(count.archived, 'archived notes')

View File

@@ -1,4 +1,4 @@
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import { Fragment, FunctionComponent, useState } from 'react'
import { Text, Title, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
@@ -13,10 +13,10 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
type Props = { appState: AppState }
type Props = { viewControllerManager: ViewControllerManager }
const ErroredItems: FunctionComponent<Props> = ({ appState }: Props) => {
const app = appState.application
const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props) => {
const app = viewControllerManager.application
const [erroredItems, setErroredItems] = useState(app.items.invalidItems)

View File

@@ -8,13 +8,13 @@ import {
StringUtils,
Strings,
} from '@/Strings'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { preventRefreshing } from '@/Utils'
import { alertDialog } from '@/Services/AlertService'
import { ChangeEventHandler, FormEvent, useCallback, useEffect, useRef, useState } from 'react'
import { ApplicationEvent } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { AppState } from '@/UIModels/AppState'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { Title, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import Button from '@/Components/Button/Button'
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
@@ -22,14 +22,15 @@ import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
viewControllerManager: ViewControllerManager
}
const PasscodeLock = ({ application, appState }: Props) => {
const PasscodeLock = ({ application, viewControllerManager }: Props) => {
const keyStorageInfo = StringUtils.keyStorageInfo(application)
const passcodeAutoLockOptions = application.getAutolockService().getAutoLockIntervalOptions()
const { setIsEncryptionEnabled, setIsBackupEncrypted, setEncryptionStatusString } = appState.accountMenu
const { setIsEncryptionEnabled, setIsBackupEncrypted, setEncryptionStatusString } =
viewControllerManager.accountMenuController
const passcodeInputRef = useRef<HTMLInputElement>(null)

View File

@@ -1,7 +1,7 @@
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Switch from '@/Components/Switch/Switch'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { MuteSignInEmailsOption, LogSessionUserAgentOption, SettingName } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useState } from 'react'

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { FunctionComponent, useCallback, useState, useEffect } from 'react'
import { ApplicationEvent } from '@standardnotes/snjs'
import { isSameDay } from '@/Utils'

View File

@@ -1,5 +1,5 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { FunctionComponent } from 'react'
import TwoFactorAuthWrapper from '../TwoFactorAuth/TwoFactorAuthWrapper'
import { MfaProps } from '../TwoFactorAuth/MfaProps'
@@ -11,17 +11,19 @@ import ErroredItems from './ErroredItems'
import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane'
interface SecurityProps extends MfaProps {
appState: AppState
viewControllerManager: ViewControllerManager
application: WebApplication
}
const Security: FunctionComponent<SecurityProps> = (props) => (
<PreferencesPane>
<Encryption appState={props.appState} />
{props.application.items.invalidItems.length > 0 && <ErroredItems appState={props.appState} />}
<Encryption viewControllerManager={props.viewControllerManager} />
{props.application.items.invalidItems.length > 0 && (
<ErroredItems viewControllerManager={props.viewControllerManager} />
)}
<Protections application={props.application} />
<TwoFactorAuthWrapper mfaProvider={props.mfaProvider} userProvider={props.userProvider} />
<PasscodeLock appState={props.appState} application={props.application} />
<PasscodeLock viewControllerManager={props.viewControllerManager} application={props.application} />
{props.application.getUser() && <Privacy application={props.application} />}
</PreferencesPane>
)

View File

@@ -1,4 +1,4 @@
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
export const securityPrefsHasBubble = (application: WebApplication): boolean => {
return application.items.invalidItems.length > 0

View File

@@ -1,6 +1,6 @@
import { action, makeAutoObservable, observable } from 'mobx'
import { IconType } from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
import { WebApplication } from '@/Application/Application'
import { ExtensionsLatestVersions } from './Panes/Extensions/ExtensionsLatestVersions'
import { securityPrefsHasBubble } from './Panes/Security/securityPrefsHasBubble'

Some files were not shown because too many files have changed in this diff Show More