diff --git a/packages/services/src/Domain/Application/WebApplicationInterface.ts b/packages/services/src/Domain/Application/WebApplicationInterface.ts index 3eb41b356..bfd842dac 100644 --- a/packages/services/src/Domain/Application/WebApplicationInterface.ts +++ b/packages/services/src/Domain/Application/WebApplicationInterface.ts @@ -17,4 +17,5 @@ export interface WebApplicationInterface extends ApplicationInterface { mobileDevice(): MobileDeviceInterface handleAndroidBackButtonPressed(): void addAndroidBackHandlerEventListener(listener: () => boolean): (() => void) | undefined + setAndroidBackHandlerFallbackListener(listener: () => boolean): void } diff --git a/packages/web/src/javascripts/Application/Application.ts b/packages/web/src/javascripts/Application/Application.ts index 86f875355..bf2e33d1e 100644 --- a/packages/web/src/javascripts/Application/Application.ts +++ b/packages/web/src/javascripts/Application/Application.ts @@ -369,6 +369,12 @@ export class WebApplication extends SNApplication implements WebApplicationInter return } + setAndroidBackHandlerFallbackListener(listener: () => boolean) { + if (typeof this.androidBackHandler !== 'undefined') { + this.androidBackHandler.setFallbackListener(listener) + } + } + isAuthorizedToRenderItem(item: DecryptedItem): boolean { if (item.protected && this.hasProtectionSources()) { return this.hasUnprotectedAccessSession() diff --git a/packages/web/src/javascripts/Components/ContentListView/FileListItem.tsx b/packages/web/src/javascripts/Components/ContentListView/FileListItem.tsx index 498c59fa1..1b25b33ec 100644 --- a/packages/web/src/javascripts/Components/ContentListView/FileListItem.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/FileListItem.tsx @@ -7,13 +7,13 @@ import ListItemTags from './ListItemTags' import ListItemMetadata from './ListItemMetadata' import { DisplayableListItemProps } from './Types/DisplayableListItemProps' import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider' -import { AppPaneId } from '../Panes/AppPaneMetadata' import { useContextMenuEvent } from '@/Hooks/useContextMenuEvent' import { classNames } from '@standardnotes/utils' import { formatSizeToReadableString } from '@standardnotes/filepicker' import { getIconForFileType } from '@/Utils/Items/Icons/getIconForFileType' import { useApplication } from '../ApplicationProvider' import Icon from '../Icon/Icon' +import { PaneLayout } from '@/Controllers/PaneController/PaneLayout' const FileListItem: FunctionComponent> = ({ filesController, @@ -26,7 +26,7 @@ const FileListItem: FunctionComponent> = ({ sortBy, tags, }) => { - const { toggleAppPane } = useResponsiveAppPane() + const { setPaneLayout } = useResponsiveAppPane() const application = useApplication() const [backupInfo, setBackupInfo] = useState(undefined) @@ -70,9 +70,9 @@ const FileListItem: FunctionComponent> = ({ const onClick = useCallback(async () => { const { didSelect } = await onSelect(file, true) if (didSelect) { - toggleAppPane(AppPaneId.Editor) + setPaneLayout(PaneLayout.Editing) } - }, [file, onSelect, toggleAppPane]) + }, [file, onSelect, setPaneLayout]) const IconComponent = () => getFileIconComponent(getIconForFileType((file as FileItem).mimeType), 'w-10 h-10 flex-shrink-0') diff --git a/packages/web/src/javascripts/Components/Panes/ResponsivePaneProvider.tsx b/packages/web/src/javascripts/Components/Panes/ResponsivePaneProvider.tsx index 51379e4a1..fb727b77e 100644 --- a/packages/web/src/javascripts/Components/Panes/ResponsivePaneProvider.tsx +++ b/packages/web/src/javascripts/Components/Panes/ResponsivePaneProvider.tsx @@ -14,6 +14,7 @@ import { import { AppPaneId } from './AppPaneMetadata' import { PaneController } from '../../Controllers/PaneController/PaneController' import { observer } from 'mobx-react-lite' +import { PaneLayout } from '@/Controllers/PaneController/PaneLayout' type ResponsivePaneData = { selectedPane: AppPaneId @@ -84,7 +85,7 @@ const ResponsivePaneProvider = ({ paneController, children }: ProviderProps) => currentSelectedPaneRef.current === AppPaneId.Editor || currentSelectedPaneRef.current === AppPaneId.Navigation ) { - toggleAppPane(AppPaneId.Items) + paneController.setPaneLayout(PaneLayout.ItemSelection) return true } else { return false @@ -95,7 +96,7 @@ const ResponsivePaneProvider = ({ paneController, children }: ProviderProps) => removeListener() } } - }, [addAndroidBackHandler, currentSelectedPaneRef, toggleAppPane]) + }, [addAndroidBackHandler, currentSelectedPaneRef, paneController]) const contextValue = useMemo( (): ResponsivePaneData => ({ diff --git a/packages/web/src/javascripts/Components/Tags/Navigation.tsx b/packages/web/src/javascripts/Components/Tags/Navigation.tsx index ae680dfab..f7a711998 100644 --- a/packages/web/src/javascripts/Components/Tags/Navigation.tsx +++ b/packages/web/src/javascripts/Components/Tags/Navigation.tsx @@ -4,7 +4,6 @@ import { WebApplication } from '@/Application/Application' import { ApplicationEvent, PrefKey, WebAppEvent } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' import { forwardRef, useEffect, useMemo, useState } from 'react' -import { AppPaneId } from '@/Components/Panes/AppPaneMetadata' import { classNames } from '@standardnotes/utils' import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider' import UpgradeNow from '../Footer/UpgradeNow' @@ -12,6 +11,7 @@ import RoundIconButton from '../Button/RoundIconButton' import { isIOS } from '@/Utils' import { PanelResizedData } from '@/Types/PanelResizedData' import { PANEL_NAME_NAVIGATION } from '@/Constants/Constants' +import { PaneLayout } from '@/Controllers/PaneController/PaneLayout' type Props = { application: WebApplication @@ -22,7 +22,7 @@ type Props = { const Navigation = forwardRef(({ application, className, children, id }, ref) => { const viewControllerManager = useMemo(() => application.getViewControllerManager(), [application]) - const { toggleAppPane } = useResponsiveAppPane() + const { setPaneLayout } = useResponsiveAppPane() const [hasPasscode, setHasPasscode] = useState(() => application.hasPasscode()) useEffect(() => { @@ -56,7 +56,7 @@ const Navigation = forwardRef(({ application, className, { - toggleAppPane(AppPaneId.Items) + setPaneLayout(PaneLayout.ItemSelection) }} label="Go to items list" icon="chevron-left" @@ -101,7 +101,7 @@ const Navigation = forwardRef(({ application, className, /> ) - }, [hasPasscode, application, viewControllerManager, toggleAppPane]) + }, [application, viewControllerManager, hasPasscode, setPaneLayout]) return (
void export class AndroidBackHandler { private listeners = new Set() + private fallbackListener: Listener | undefined + + setFallbackListener(listener: Listener) { + this.fallbackListener = listener + } addEventListener(listener: Listener): RemoveListener { this.listeners.add(listener) @@ -13,10 +18,17 @@ export class AndroidBackHandler { } notifyEvent() { + let handled = false for (const listener of Array.from(this.listeners).reverse()) { if (listener()) { + handled = true return + } else { + handled = false } } + if (!handled && this.fallbackListener) { + this.fallbackListener() + } } } diff --git a/packages/web/src/javascripts/NativeMobileWeb/useAndroidBackHandler.tsx b/packages/web/src/javascripts/NativeMobileWeb/useAndroidBackHandler.tsx index 3ec27d422..be291f478 100644 --- a/packages/web/src/javascripts/NativeMobileWeb/useAndroidBackHandler.tsx +++ b/packages/web/src/javascripts/NativeMobileWeb/useAndroidBackHandler.tsx @@ -34,19 +34,14 @@ const AndroidBackHandlerProvider = ({ application, children }: ProviderProps) => ) useEffect(() => { - const removeListener = addAndroidBackHandler(() => { + application.setAndroidBackHandlerFallbackListener(() => { const shouldConfirm = (application.getValue(AndroidConfirmBeforeExitKey) as boolean) ?? true application.mobileDevice().exitApp(shouldConfirm) return true }) - return () => { - if (removeListener) { - removeListener() - } - } - }, [addAndroidBackHandler, application]) + }, [application]) return (