feat(mobile): disable swipe back gesture when there is no back in header (#8876)

close AF-1663, AF-1756

- new global `ModalConfigContext`
- new logic to judge whether inside modal
- render `✕` for PageHeader back if inside modal
- only enable `NavigationGesture` when there is `<` in PageHeader
This commit is contained in:
CatsJuice
2024-11-25 03:12:21 +00:00
parent 922db5ced4
commit b369ee0cca
23 changed files with 260 additions and 26 deletions
+15 -5
View File
@@ -1,6 +1,7 @@
import { AffineContext } from '@affine/core/components/context';
import { AppFallback } from '@affine/core/mobile/components/app-fallback';
import { configureMobileModules } from '@affine/core/mobile/modules';
import { NavigationGestureProvider } from '@affine/core/mobile/modules/navigation-gesture';
import { VirtualKeyboardProvider } from '@affine/core/mobile/modules/virtual-keyboard';
import { router } from '@affine/core/mobile/router';
import { configureCommonModules } from '@affine/core/modules';
@@ -32,8 +33,10 @@ import { Suspense } from 'react';
import { RouterProvider } from 'react-router-dom';
import { configureFetchProvider } from './fetch';
import { ModalConfigProvider } from './modal-config';
import { Cookie } from './plugins/cookie';
import { Hashcash } from './plugins/hashcash';
import { NavigationGesture } from './plugins/navigation-gesture';
const future = {
v7_startTransition: true,
@@ -86,6 +89,11 @@ framework.impl(VirtualKeyboardProvider, {
Keyboard.removeAllListeners();
},
});
framework.impl(NavigationGestureProvider, {
isEnabled: () => NavigationGesture.isEnabled(),
enable: () => NavigationGesture.enable(),
disable: () => NavigationGesture.disable(),
});
const frameworkProvider = framework.provider();
// setup application lifecycle events, and emit application start event
@@ -132,11 +140,13 @@ export function App() {
<FrameworkRoot framework={frameworkProvider}>
<I18nProvider>
<AffineContext store={getCurrentStore()}>
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
<ModalConfigProvider>
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
</ModalConfigProvider>
</AffineContext>
</I18nProvider>
</FrameworkRoot>
@@ -0,0 +1,28 @@
import { ModalConfigContext } from '@affine/component';
import { NavigationGestureService } from '@affine/core/mobile/modules/navigation-gesture';
import { useService } from '@toeverything/infra';
import { type PropsWithChildren, useCallback } from 'react';
export const ModalConfigProvider = ({ children }: PropsWithChildren) => {
const navigationGesture = useService(NavigationGestureService);
const onOpenChange = useCallback(
(open: boolean) => {
const prev = navigationGesture.enabled$.value;
if (open && !prev) {
navigationGesture.setEnabled(false);
return () => {
navigationGesture.setEnabled(prev);
};
}
return;
},
[navigationGesture]
);
return (
<ModalConfigContext.Provider value={{ onOpenChange }}>
{children}
</ModalConfigContext.Provider>
);
};
@@ -0,0 +1,5 @@
export interface NavigationGesturePlugin {
isEnabled: () => Promise<boolean>;
enable: () => Promise<void>;
disable: () => Promise<void>;
}
@@ -0,0 +1,9 @@
import { registerPlugin } from '@capacitor/core';
import type { NavigationGesturePlugin } from './definitions';
const NavigationGesture =
registerPlugin<NavigationGesturePlugin>('NavigationGesture');
export * from './definitions';
export { NavigationGesture };