mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
fix(mobile): disable navigation gesture for swipe-dialog (#8993)
This commit is contained in:
@@ -17,6 +17,7 @@ export interface NavigationBackButtonProps extends IconButtonProps {
|
||||
* A button to control the back behavior of the mobile app, as well as manage navigation gesture
|
||||
*/
|
||||
export const NavigationBackButton = ({
|
||||
icon,
|
||||
backAction,
|
||||
style: propsStyle,
|
||||
...otherProps
|
||||
@@ -46,7 +47,7 @@ export const NavigationBackButton = ({
|
||||
size={24}
|
||||
style={style}
|
||||
onClick={handleRouteBack}
|
||||
icon={isInsideModal ? <CloseIcon /> : <ArrowLeftSmallIcon />}
|
||||
icon={icon ?? (isInsideModal ? <CloseIcon /> : <ArrowLeftSmallIcon />)}
|
||||
data-testid="page-header-back"
|
||||
{...otherProps}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SafeArea } from '@affine/component';
|
||||
import clsx from 'clsx';
|
||||
import { forwardRef, type HtmlHTMLAttributes, type ReactNode } from 'react';
|
||||
import type { HtmlHTMLAttributes, ReactElement, ReactNode } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
import { NavigationBackButton } from '../navigation-back';
|
||||
import * as styles from './styles.css';
|
||||
@@ -11,6 +12,7 @@ export interface PageHeaderProps
|
||||
* whether to show back button
|
||||
*/
|
||||
back?: boolean;
|
||||
backIcon?: ReactElement;
|
||||
/**
|
||||
* Override back button action
|
||||
*/
|
||||
@@ -51,6 +53,7 @@ export const PageHeader = forwardRef<HTMLDivElement, PageHeaderProps>(
|
||||
function PageHeader(
|
||||
{
|
||||
back,
|
||||
backIcon,
|
||||
backAction,
|
||||
prefix,
|
||||
suffix,
|
||||
@@ -82,7 +85,9 @@ export const PageHeader = forwardRef<HTMLDivElement, PageHeaderProps>(
|
||||
className={clsx(styles.prefix, prefixClassName)}
|
||||
style={prefixStyle}
|
||||
>
|
||||
{back ? <NavigationBackButton backAction={backAction} /> : null}
|
||||
{back ? (
|
||||
<NavigationBackButton icon={backIcon} backAction={backAction} />
|
||||
) : null}
|
||||
{prefix}
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { Scrollable } from '@affine/component';
|
||||
import {
|
||||
InsideModalContext,
|
||||
ModalConfigContext,
|
||||
Scrollable,
|
||||
} from '@affine/component';
|
||||
import { PageHeader } from '@affine/core/mobile/components';
|
||||
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
|
||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||
import anime from 'animejs';
|
||||
import {
|
||||
@@ -146,6 +151,8 @@ export const SwipeDialog = ({
|
||||
triggerSize = 10,
|
||||
onOpenChange,
|
||||
}: SwipeDialogProps) => {
|
||||
const insideModal = useContext(InsideModalContext);
|
||||
const { onOpen: globalOnOpen } = useContext(ModalConfigContext);
|
||||
const swiperTriggerRef = useRef<HTMLDivElement>(null);
|
||||
const overlayRef = useRef<HTMLDivElement>(null);
|
||||
const dialogRef = useRef<HTMLDivElement>(null);
|
||||
@@ -202,39 +209,47 @@ export const SwipeDialog = ({
|
||||
}
|
||||
}, [open, prev]);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) return globalOnOpen?.();
|
||||
return;
|
||||
}, [globalOnOpen, open]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<SwipeDialogContext.Provider value={{ stack: [...stack, dialogRef] }}>
|
||||
{createPortal(
|
||||
<div className={styles.root}>
|
||||
<div className={styles.overlay} ref={overlayRef} />
|
||||
<div role="dialog" className={styles.dialog} ref={dialogRef}>
|
||||
<div className={styles.content}>
|
||||
<PageHeader
|
||||
back
|
||||
backAction={animateClose}
|
||||
className={styles.header}
|
||||
>
|
||||
<span className={styles.dialogTitle}>{title}</span>
|
||||
</PageHeader>
|
||||
<InsideModalContext.Provider value={insideModal + 1}>
|
||||
{createPortal(
|
||||
<div className={styles.root}>
|
||||
<div className={styles.overlay} ref={overlayRef} />
|
||||
<div role="dialog" className={styles.dialog} ref={dialogRef}>
|
||||
<div className={styles.content}>
|
||||
<PageHeader
|
||||
back
|
||||
backIcon={<ArrowLeftSmallIcon />}
|
||||
backAction={animateClose}
|
||||
className={styles.header}
|
||||
>
|
||||
<span className={styles.dialogTitle}>{title}</span>
|
||||
</PageHeader>
|
||||
|
||||
<Scrollable.Root className={styles.scrollArea}>
|
||||
<Scrollable.Viewport>{children}</Scrollable.Viewport>
|
||||
<Scrollable.Scrollbar orientation="vertical" />
|
||||
</Scrollable.Root>
|
||||
<Scrollable.Root className={styles.scrollArea}>
|
||||
<Scrollable.Viewport>{children}</Scrollable.Viewport>
|
||||
<Scrollable.Scrollbar orientation="vertical" />
|
||||
</Scrollable.Root>
|
||||
</div>
|
||||
<div
|
||||
ref={swiperTriggerRef}
|
||||
className={styles.swipeBackTrigger}
|
||||
style={assignInlineVars({
|
||||
[styles.triggerSizeVar]: `${triggerSize}px`,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
ref={swiperTriggerRef}
|
||||
className={styles.swipeBackTrigger}
|
||||
style={assignInlineVars({
|
||||
[styles.triggerSizeVar]: `${triggerSize}px`,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</InsideModalContext.Provider>
|
||||
</SwipeDialogContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user