import { ApplicationGroup } from '@/UIModels/ApplicationGroup' import { getPlatformString, getWindowUrlParams } from '@/Utils' import { AppStateEvent, PanelResizedData } from '@/UIModels/AppState' import { ApplicationEvent, Challenge, PermissionDialog, removeFromArray } from '@standardnotes/snjs' import { PANEL_NAME_NOTES, PANEL_NAME_NAVIGATION } from '@/Constants' import { alertDialog } from '@/Services/AlertService' import { WebAppEvent, WebApplication } from '@/UIModels/Application' import { PureComponent } from '@/Components/Abstract/PureComponent' import { Navigation } from '@/Components/Navigation' import { NotesView } from '@/Components/NotesView' import { NoteGroupView } from '@/Components/NoteGroupView' import { Footer } from '@/Components/Footer' import { SessionsModal } from '@/Components/SessionsModal' import { PreferencesViewWrapper } from '@/Components/Preferences/PreferencesViewWrapper' import { ChallengeModal } from '@/Components/ChallengeModal/ChallengeModal' import { NotesContextMenu } from '@/Components/NotesContextMenu' import { PurchaseFlowWrapper } from '@/Components/PurchaseFlow/PurchaseFlowWrapper' import { render } from 'preact' import { PermissionsModal } from '@/Components/PermissionsModal' import { RevisionHistoryModalWrapper } from '@/Components/RevisionHistoryModal/RevisionHistoryModalWrapper' import { PremiumModalProvider } from '@/Hooks/usePremiumModal' import { ConfirmSignoutContainer } from '@/Components/ConfirmSignoutModal' import { TagsContextMenu } from '@/Components/Tags/TagContextMenu' import { ToastContainer } from '@standardnotes/stylekit' import { FilePreviewModal } from '../Files/FilePreviewModal' type Props = { application: WebApplication mainApplicationGroup: ApplicationGroup } type State = { started?: boolean launched?: boolean needsUnlock?: boolean appClass: string challenges: Challenge[] } export class ApplicationView extends PureComponent { public readonly platformString = getPlatformString() constructor(props: Props) { super(props, props.application) this.state = { appClass: '', challenges: [], } } override deinit() { ;(this.application as unknown) = undefined super.deinit() } override componentDidMount(): void { super.componentDidMount() void this.loadApplication() } async loadApplication() { const desktopService = this.application.getDesktopService() if (desktopService) { this.application.componentManager.setDesktopManager(desktopService) } await this.application.prepareForLaunch({ receiveChallenge: async (challenge) => { const challenges = this.state.challenges.slice() challenges.push(challenge) this.setState({ challenges: challenges }) }, }) await this.application.launch() } public removeChallenge = async (challenge: Challenge) => { const challenges = this.state.challenges.slice() removeFromArray(challenges, challenge) this.setState({ challenges: challenges }) } override async onAppStart() { super.onAppStart().catch(console.error) this.setState({ started: true, needsUnlock: this.application.hasPasscode(), }) this.application.componentManager.presentPermissionsDialog = this.presentPermissionsDialog } override async onAppLaunch() { super.onAppLaunch().catch(console.error) this.setState({ launched: true, needsUnlock: false, }) this.handleDemoSignInFromParams().catch(console.error) } onUpdateAvailable() { this.application.notifyWebEvent(WebAppEvent.NewUpdateAvailable) } override async onAppEvent(eventName: ApplicationEvent) { super.onAppEvent(eventName) switch (eventName) { case ApplicationEvent.LocalDatabaseReadError: alertDialog({ text: 'Unable to load local database. Please restart the app and try again.', }).catch(console.error) break case ApplicationEvent.LocalDatabaseWriteError: alertDialog({ text: 'Unable to write to local database. Please restart the app and try again.', }).catch(console.error) break } } override async onAppStateEvent(eventName: AppStateEvent, data?: unknown) { if (eventName === AppStateEvent.PanelResized) { const { panel, collapsed } = data as PanelResizedData let appClass = '' if (panel === PANEL_NAME_NOTES && collapsed) { appClass += 'collapsed-notes' } if (panel === PANEL_NAME_NAVIGATION && collapsed) { appClass += ' collapsed-navigation' } this.setState({ appClass }) } else if (eventName === AppStateEvent.WindowDidFocus) { if (!(await this.application.isLocked())) { this.application.sync.sync().catch(console.error) } } } async handleDemoSignInFromParams() { const token = getWindowUrlParams().get('demo-token') if (!token || this.application.hasAccount()) { return } await this.application.sessions.populateSessionFromDemoShareToken(token) } presentPermissionsDialog = (dialog: PermissionDialog) => { render( , document.body.appendChild(document.createElement('div')), ) } override render() { if (this.application['dealloced'] === true) { console.error('Attempting to render dealloced application') return
} const renderAppContents = !this.state.needsUnlock && this.state.launched return (
{renderAppContents && (
)} {renderAppContents && ( <>
) } }