fix(chat): reduce user message padding and hide top scroll shadow on mobile (#496)
* fix(chat): reduce user message padding on mobile * fix(mobile): limit drawer swipe gesture to status bar only * fix(chat): hide top scroll shadow on mobile * fix: add mobile edge-swipe drawer fallback and normalize comments - Adds narrow left/right mobile edge swipe zones for drawer gestures - Keeps drawer swipe access even when the mobile status bar is hidden - Replaces remaining non-English comments in touched chat/layout files * fix: remove edge swipe settings and tighten mobile chat spacing --------- Co-authored-by: Jovines <jovines@qq.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Jovines
Bohdan Triapitsyn
parent
c4f6697ee1
commit
fc06a9c499
@@ -523,6 +523,7 @@ export const ChatContainer: React.FC = () => {
|
|||||||
className="absolute inset-0 overflow-y-auto overflow-x-hidden z-0 chat-scroll overlay-scrollbar-target"
|
className="absolute inset-0 overflow-y-auto overflow-x-hidden z-0 chat-scroll overlay-scrollbar-target"
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
observeMutations={false}
|
observeMutations={false}
|
||||||
|
hideTopShadow={isMobile}
|
||||||
data-scroll-shadow="true"
|
data-scroll-shadow="true"
|
||||||
data-scrollbar="chat"
|
data-scrollbar="chat"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2319,7 +2319,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile Session Status Bar - 在输入框上方 */}
|
{/* Mobile Session Status Bar - above input */}
|
||||||
{isMobile && <MobileSessionStatusBar cornerRadius={cornerRadius} />}
|
{isMobile && <MobileSessionStatusBar cornerRadius={cornerRadius} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -909,7 +909,7 @@ const ChatMessage: React.FC<ChatMessageProps> = ({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'group w-full',
|
'group w-full',
|
||||||
shouldShowHeader ? (isMobile ? 'pt-10' : 'pt-6') : 'pt-0',
|
isUser ? (isMobile ? 'pt-2' : 'pt-6') : (shouldShowHeader ? (isMobile ? 'pt-10' : 'pt-6') : 'pt-0'),
|
||||||
isUser ? 'pb-0' : isFollowedByAssistant ? 'pb-0' : 'pb-8'
|
isUser ? 'pb-0' : isFollowedByAssistant ? 'pb-0' : 'pb-8'
|
||||||
)}
|
)}
|
||||||
data-message-id={message.info.id}
|
data-message-id={message.info.id}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { filterSyntheticParts } from '@/lib/messages/synthetic';
|
|||||||
import { detectTurns, type Turn } from './hooks/useTurnGrouping';
|
import { detectTurns, type Turn } from './hooks/useTurnGrouping';
|
||||||
import { TurnGroupingProvider, useMessageNeighbors, useTurnGroupingContextForMessage, useTurnGroupingContextStatic, useLastTurnMessageIds } from './contexts/TurnGroupingContext';
|
import { TurnGroupingProvider, useMessageNeighbors, useTurnGroupingContextForMessage, useTurnGroupingContextStatic, useLastTurnMessageIds } from './contexts/TurnGroupingContext';
|
||||||
import { useSessionStore } from '@/stores/useSessionStore';
|
import { useSessionStore } from '@/stores/useSessionStore';
|
||||||
|
import { useDeviceInfo } from '@/lib/device';
|
||||||
|
|
||||||
interface ChatMessageEntry {
|
interface ChatMessageEntry {
|
||||||
info: Message;
|
info: Message;
|
||||||
@@ -421,6 +422,7 @@ const MessageList: React.FC<MessageListProps> = ({
|
|||||||
onRenderEarlier,
|
onRenderEarlier,
|
||||||
scrollToBottom,
|
scrollToBottom,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { isMobile } = useDeviceInfo();
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (permissions.length === 0 && questions.length === 0) {
|
if (permissions.length === 0 && questions.length === 0) {
|
||||||
return;
|
return;
|
||||||
@@ -641,8 +643,8 @@ const MessageList: React.FC<MessageListProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Bottom spacer - always 10% of viewport height */}
|
{/* Bottom spacer */}
|
||||||
<div className="flex-shrink-0" style={{ height: '10vh' }} aria-hidden="true" />
|
<div className="flex-shrink-0" style={{ height: isMobile ? '8px' : '10vh' }} aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
</TurnGroupingProvider>
|
</TurnGroupingProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,12 +21,11 @@ import { useUIStore } from '@/stores/useUIStore';
|
|||||||
import { useUpdateStore } from '@/stores/useUpdateStore';
|
import { useUpdateStore } from '@/stores/useUpdateStore';
|
||||||
import { useDeviceInfo } from '@/lib/device';
|
import { useDeviceInfo } from '@/lib/device';
|
||||||
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
||||||
import { useDrawerSwipe } from '@/hooks/useDrawerSwipe';
|
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
import { ChatView, PlanView, GitView, DiffView, TerminalView, FilesView, SettingsView, SettingsWindow } from '@/components/views';
|
import { ChatView, PlanView, GitView, DiffView, TerminalView, FilesView, SettingsView, SettingsWindow } from '@/components/views';
|
||||||
|
|
||||||
// 移动端抽屉宽度(占屏幕比例)
|
// Mobile drawer width as screen percentage
|
||||||
const MOBILE_DRAWER_WIDTH_PERCENT = 85;
|
const MOBILE_DRAWER_WIDTH_PERCENT = 85;
|
||||||
|
|
||||||
const normalizeDirectoryKey = (value: string): string => {
|
const normalizeDirectoryKey = (value: string): string => {
|
||||||
@@ -48,26 +47,6 @@ const normalizeDirectoryKey = (value: string): string => {
|
|||||||
return normalized;
|
return normalized;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MobileDrawerGestureSurface: React.FC<{
|
|
||||||
className?: string;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}> = ({ className, style, children }) => {
|
|
||||||
const { handleTouchStart, handleTouchMove, handleTouchEnd } = useDrawerSwipe();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={className}
|
|
||||||
style={style}
|
|
||||||
onTouchStart={handleTouchStart}
|
|
||||||
onTouchMove={handleTouchMove}
|
|
||||||
onTouchEnd={handleTouchEnd}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MainLayout: React.FC = () => {
|
export const MainLayout: React.FC = () => {
|
||||||
const RIGHT_SIDEBAR_AUTO_CLOSE_WIDTH = 1140;
|
const RIGHT_SIDEBAR_AUTO_CLOSE_WIDTH = 1140;
|
||||||
const RIGHT_SIDEBAR_AUTO_OPEN_WIDTH = 1220;
|
const RIGHT_SIDEBAR_AUTO_OPEN_WIDTH = 1220;
|
||||||
@@ -104,19 +83,19 @@ export const MainLayout: React.FC = () => {
|
|||||||
const bottomTerminalAutoClosedRef = React.useRef(false);
|
const bottomTerminalAutoClosedRef = React.useRef(false);
|
||||||
const leftSidebarAutoClosedByContextRef = React.useRef(false);
|
const leftSidebarAutoClosedByContextRef = React.useRef(false);
|
||||||
|
|
||||||
// 移动端抽屉状态
|
// Mobile drawer state
|
||||||
const [mobileLeftDrawerOpen, setMobileLeftDrawerOpen] = React.useState(false);
|
const [mobileLeftDrawerOpen, setMobileLeftDrawerOpen] = React.useState(false);
|
||||||
const mobileRightDrawerOpenRef = React.useRef(false);
|
const mobileRightDrawerOpenRef = React.useRef(false);
|
||||||
|
|
||||||
// 左抽屉 motion value
|
// Left drawer motion value
|
||||||
const leftDrawerX = useMotionValue(0);
|
const leftDrawerX = useMotionValue(0);
|
||||||
const leftDrawerWidth = useRef(0);
|
const leftDrawerWidth = useRef(0);
|
||||||
|
|
||||||
// 右抽屉 motion value
|
// Right drawer motion value
|
||||||
const rightDrawerX = useMotionValue(0);
|
const rightDrawerX = useMotionValue(0);
|
||||||
const rightDrawerWidth = useRef(0);
|
const rightDrawerWidth = useRef(0);
|
||||||
|
|
||||||
// 计算抽屉宽度
|
// Compute drawer width
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
leftDrawerWidth.current = window.innerWidth * (MOBILE_DRAWER_WIDTH_PERCENT / 100);
|
leftDrawerWidth.current = window.innerWidth * (MOBILE_DRAWER_WIDTH_PERCENT / 100);
|
||||||
@@ -124,7 +103,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [isMobile]);
|
}, [isMobile]);
|
||||||
|
|
||||||
// 同步左抽屉 state 和 motion value
|
// Sync left drawer state and motion value
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isMobile) return;
|
if (!isMobile) return;
|
||||||
const targetX = mobileLeftDrawerOpen ? 0 : -leftDrawerWidth.current;
|
const targetX = mobileLeftDrawerOpen ? 0 : -leftDrawerWidth.current;
|
||||||
@@ -136,7 +115,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}, [mobileLeftDrawerOpen, isMobile, leftDrawerX]);
|
}, [mobileLeftDrawerOpen, isMobile, leftDrawerX]);
|
||||||
|
|
||||||
// 同步右抽屉 state 和 motion value
|
// Sync right drawer state and motion value
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isMobile) return;
|
if (!isMobile) return;
|
||||||
mobileRightDrawerOpenRef.current = isRightSidebarOpen;
|
mobileRightDrawerOpenRef.current = isRightSidebarOpen;
|
||||||
@@ -149,14 +128,14 @@ export const MainLayout: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}, [isMobile, isRightSidebarOpen, rightDrawerX]);
|
}, [isMobile, isRightSidebarOpen, rightDrawerX]);
|
||||||
|
|
||||||
// 同步 session switcher 状态到左抽屉 (单向同步,避免循环)
|
// Sync session switcher state to left drawer (one-way)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
setMobileLeftDrawerOpen(isSessionSwitcherOpen);
|
setMobileLeftDrawerOpen(isSessionSwitcherOpen);
|
||||||
}
|
}
|
||||||
}, [isSessionSwitcherOpen, isMobile]);
|
}, [isSessionSwitcherOpen, isMobile]);
|
||||||
|
|
||||||
// 同步右抽屉和 git sidebar 状态
|
// Sync right drawer and git sidebar state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
mobileRightDrawerOpenRef.current = isRightSidebarOpen;
|
mobileRightDrawerOpenRef.current = isRightSidebarOpen;
|
||||||
@@ -607,7 +586,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
setMobileLeftDrawerOpen,
|
setMobileLeftDrawerOpen,
|
||||||
setRightSidebarOpen,
|
setRightSidebarOpen,
|
||||||
}}>
|
}}>
|
||||||
{/* Mobile: Header + Drawer 模式 */}
|
{/* Mobile: header + drawer mode */}
|
||||||
{!(isSettingsDialogOpen || isMultiRunLauncherOpen) && <Header
|
{!(isSettingsDialogOpen || isMultiRunLauncherOpen) && <Header
|
||||||
onToggleLeftDrawer={() => {
|
onToggleLeftDrawer={() => {
|
||||||
if (isRightSidebarOpen) {
|
if (isRightSidebarOpen) {
|
||||||
@@ -625,7 +604,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
rightDrawerOpen={isRightSidebarOpen}
|
rightDrawerOpen={isRightSidebarOpen}
|
||||||
/>}
|
/>}
|
||||||
|
|
||||||
{/* 遮罩层 */}
|
{/* Backdrop */}
|
||||||
<motion.button
|
<motion.button
|
||||||
type="button"
|
type="button"
|
||||||
initial={false}
|
initial={false}
|
||||||
@@ -641,7 +620,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
aria-label="Close drawer"
|
aria-label="Close drawer"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 左抽屉(Session) */}
|
{/* Left drawer (Session) */}
|
||||||
<motion.aside
|
<motion.aside
|
||||||
drag="x"
|
drag="x"
|
||||||
dragElastic={0.08}
|
dragElastic={0.08}
|
||||||
@@ -702,7 +681,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</motion.aside>
|
</motion.aside>
|
||||||
|
|
||||||
{/* 右抽屉(Git) */}
|
{/* Right drawer (Git) */}
|
||||||
<motion.aside
|
<motion.aside
|
||||||
drag="x"
|
drag="x"
|
||||||
dragElastic={0.08}
|
dragElastic={0.08}
|
||||||
@@ -748,8 +727,8 @@ export const MainLayout: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</motion.aside>
|
</motion.aside>
|
||||||
|
|
||||||
{/* 主内容区(固定) */}
|
{/* Main content area (fixed) */}
|
||||||
<MobileDrawerGestureSurface
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-1 overflow-hidden relative',
|
'flex flex-1 overflow-hidden relative',
|
||||||
(isSettingsDialogOpen || isMultiRunLauncherOpen) && 'hidden'
|
(isSettingsDialogOpen || isMultiRunLauncherOpen) && 'hidden'
|
||||||
@@ -766,7 +745,7 @@ export const MainLayout: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
</MobileDrawerGestureSurface>
|
</div>
|
||||||
|
|
||||||
{/* Mobile multi-run launcher: full screen */}
|
{/* Mobile multi-run launcher: full screen */}
|
||||||
{isMultiRunLauncherOpen && (
|
{isMultiRunLauncherOpen && (
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
} = useThemeSystem();
|
} = useThemeSystem();
|
||||||
|
|
||||||
const [themesReloading, setThemesReloading] = React.useState(false);
|
const [themesReloading, setThemesReloading] = React.useState(false);
|
||||||
|
|
||||||
const lightThemes = React.useMemo(
|
const lightThemes = React.useMemo(
|
||||||
() => availableThemes
|
() => availableThemes
|
||||||
.filter((theme) => theme.metadata.variant === 'light')
|
.filter((theme) => theme.metadata.variant === 'light')
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export type ScrollShadowProps = React.HTMLAttributes<HTMLDivElement> & {
|
|||||||
offset?: number;
|
offset?: number;
|
||||||
size?: number;
|
size?: number;
|
||||||
isEnabled?: boolean;
|
isEnabled?: boolean;
|
||||||
|
hideTopShadow?: boolean;
|
||||||
hideBottomShadow?: boolean;
|
hideBottomShadow?: boolean;
|
||||||
observeMutations?: boolean;
|
observeMutations?: boolean;
|
||||||
onVisibilityChange?: (state: "both" | "none" | "top" | "bottom" | "left" | "right") => void;
|
onVisibilityChange?: (state: "both" | "none" | "top" | "bottom" | "left" | "right") => void;
|
||||||
@@ -29,6 +30,7 @@ export const ScrollShadow = React.forwardRef<HTMLDivElement, ScrollShadowProps>(
|
|||||||
offset = 0,
|
offset = 0,
|
||||||
size = 48,
|
size = 48,
|
||||||
isEnabled = true,
|
isEnabled = true,
|
||||||
|
hideTopShadow = false,
|
||||||
hideBottomShadow = false,
|
hideBottomShadow = false,
|
||||||
observeMutations = true,
|
observeMutations = true,
|
||||||
onVisibilityChange,
|
onVisibilityChange,
|
||||||
@@ -91,18 +93,20 @@ export const ScrollShadow = React.forwardRef<HTMLDivElement, ScrollShadowProps>(
|
|||||||
? el.scrollTop + el.clientHeight + offset < el.scrollHeight
|
? el.scrollTop + el.clientHeight + offset < el.scrollHeight
|
||||||
: el.scrollLeft + el.clientWidth + offset < el.scrollWidth;
|
: el.scrollLeft + el.clientWidth + offset < el.scrollWidth;
|
||||||
|
|
||||||
|
const effectiveHasBefore = hideTopShadow && orientation === "vertical" ? false : hasBefore;
|
||||||
|
|
||||||
if (hideBottomShadow && orientation === "vertical") {
|
if (hideBottomShadow && orientation === "vertical") {
|
||||||
hasAfter = false;
|
hasAfter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAttributes(el, hasBefore, hasAfter, orientation === "vertical" ? "top" : "left", orientation === "vertical" ? "bottom" : "right");
|
setAttributes(el, effectiveHasBefore, hasAfter, orientation === "vertical" ? "top" : "left", orientation === "vertical" ? "bottom" : "right");
|
||||||
|
|
||||||
const next = hasBefore && hasAfter ? "both" : hasBefore ? (orientation === "vertical" ? "top" : "left") : hasAfter ? (orientation === "vertical" ? "bottom" : "right") : "none";
|
const next = effectiveHasBefore && hasAfter ? "both" : effectiveHasBefore ? (orientation === "vertical" ? "top" : "left") : hasAfter ? (orientation === "vertical" ? "bottom" : "right") : "none";
|
||||||
if (next !== visibleRef.current) {
|
if (next !== visibleRef.current) {
|
||||||
visibleRef.current = next;
|
visibleRef.current = next;
|
||||||
onVisibilityChange?.(next);
|
onVisibilityChange?.(next);
|
||||||
}
|
}
|
||||||
}, [clearAttributes, hideBottomShadow, isEnabled, offset, onVisibilityChange, orientation, setAttributes]);
|
}, [clearAttributes, hideTopShadow, hideBottomShadow, isEnabled, offset, onVisibilityChange, orientation, setAttributes]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const el = internalRef.current;
|
const el = internalRef.current;
|
||||||
|
|||||||
@@ -2,8 +2,23 @@ import React from 'react';
|
|||||||
import { animate } from 'motion/react';
|
import { animate } from 'motion/react';
|
||||||
import { useDrawer } from '@/contexts/DrawerContext';
|
import { useDrawer } from '@/contexts/DrawerContext';
|
||||||
|
|
||||||
export function useDrawerSwipe() {
|
type DrawerSwipeOptions = {
|
||||||
|
edgeSide?: 'left' | 'right';
|
||||||
|
strictHorizontalIntent?: boolean;
|
||||||
|
horizontalIntentRatio?: number;
|
||||||
|
activationDistance?: number;
|
||||||
|
onlyWhenClosed?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useDrawerSwipe(options: DrawerSwipeOptions = {}) {
|
||||||
const drawer = useDrawer();
|
const drawer = useDrawer();
|
||||||
|
const {
|
||||||
|
edgeSide,
|
||||||
|
strictHorizontalIntent = false,
|
||||||
|
horizontalIntentRatio = 1.35,
|
||||||
|
activationDistance = 30,
|
||||||
|
onlyWhenClosed = false,
|
||||||
|
} = options;
|
||||||
const touchStartXRef = React.useRef(0);
|
const touchStartXRef = React.useRef(0);
|
||||||
const touchStartYRef = React.useRef(0);
|
const touchStartYRef = React.useRef(0);
|
||||||
const isHorizontalSwipeRef = React.useRef<boolean | null>(null);
|
const isHorizontalSwipeRef = React.useRef<boolean | null>(null);
|
||||||
@@ -24,30 +39,50 @@ export function useDrawerSwipe() {
|
|||||||
|
|
||||||
if (isHorizontalSwipeRef.current === null) {
|
if (isHorizontalSwipeRef.current === null) {
|
||||||
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
|
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
|
||||||
isHorizontalSwipeRef.current = Math.abs(deltaX) > Math.abs(deltaY);
|
if (strictHorizontalIntent) {
|
||||||
|
isHorizontalSwipeRef.current = Math.abs(deltaX) > Math.abs(deltaY) * horizontalIntentRatio;
|
||||||
|
} else {
|
||||||
|
isHorizontalSwipeRef.current = Math.abs(deltaX) > Math.abs(deltaY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHorizontalSwipeRef.current === true) {
|
if (isHorizontalSwipeRef.current === true) {
|
||||||
e.preventDefault();
|
if (onlyWhenClosed && (drawer.leftDrawerOpen || drawer.rightDrawerOpen)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const leftDrawerWidthPx = drawer.leftDrawerWidth.current || window.innerWidth * 0.85;
|
const leftDrawerWidthPx = drawer.leftDrawerWidth.current || window.innerWidth * 0.85;
|
||||||
const rightDrawerWidthPx = drawer.rightDrawerWidth.current || window.innerWidth * 0.85;
|
const rightDrawerWidthPx = drawer.rightDrawerWidth.current || window.innerWidth * 0.85;
|
||||||
|
|
||||||
if (isDraggingDrawerRef.current === null) {
|
if (isDraggingDrawerRef.current === null) {
|
||||||
if (drawer.leftDrawerOpen && deltaX > 10) {
|
if (!edgeSide && drawer.leftDrawerOpen && deltaX > 10) {
|
||||||
isDraggingDrawerRef.current = 'left';
|
isDraggingDrawerRef.current = 'left';
|
||||||
} else if (drawer.rightDrawerOpen && deltaX < -10) {
|
} else if (!edgeSide && drawer.rightDrawerOpen && deltaX < -10) {
|
||||||
isDraggingDrawerRef.current = 'right';
|
isDraggingDrawerRef.current = 'right';
|
||||||
} else if (!drawer.leftDrawerOpen && !drawer.rightDrawerOpen) {
|
} else if (!drawer.leftDrawerOpen && !drawer.rightDrawerOpen) {
|
||||||
if (deltaX > 30) {
|
if (edgeSide === 'left') {
|
||||||
|
if (deltaX > activationDistance) {
|
||||||
|
isDraggingDrawerRef.current = 'left';
|
||||||
|
}
|
||||||
|
} else if (edgeSide === 'right') {
|
||||||
|
if (deltaX < -activationDistance) {
|
||||||
|
isDraggingDrawerRef.current = 'right';
|
||||||
|
}
|
||||||
|
} else if (deltaX > activationDistance) {
|
||||||
isDraggingDrawerRef.current = 'left';
|
isDraggingDrawerRef.current = 'left';
|
||||||
} else if (deltaX < -30) {
|
} else if (deltaX < -activationDistance) {
|
||||||
isDraggingDrawerRef.current = 'right';
|
isDraggingDrawerRef.current = 'right';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isDraggingDrawerRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
if (isDraggingDrawerRef.current === 'left') {
|
if (isDraggingDrawerRef.current === 'left') {
|
||||||
if (drawer.leftDrawerOpen) {
|
if (drawer.leftDrawerOpen) {
|
||||||
const progress = Math.max(0, Math.min(1, deltaX / leftDrawerWidthPx));
|
const progress = Math.max(0, Math.min(1, deltaX / leftDrawerWidthPx));
|
||||||
@@ -68,7 +103,7 @@ export function useDrawerSwipe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [drawer]);
|
}, [activationDistance, drawer, edgeSide, horizontalIntentRatio, onlyWhenClosed, strictHorizontalIntent]);
|
||||||
|
|
||||||
const handleTouchEnd = React.useCallback((e: React.TouchEvent) => {
|
const handleTouchEnd = React.useCallback((e: React.TouchEvent) => {
|
||||||
if (isHorizontalSwipeRef.current !== true) return;
|
if (isHorizontalSwipeRef.current !== true) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user