diff --git a/src/app/components/DefaultErrorPage.tsx b/src/app/components/DefaultErrorPage.tsx index 62042cef1..045b1ea50 100644 --- a/src/app/components/DefaultErrorPage.tsx +++ b/src/app/components/DefaultErrorPage.tsx @@ -1,7 +1,6 @@ import { Box, Button, Dialog, Icon, Icons, Text, color, config } from 'folds'; import * as Sentry from '@sentry/react'; import { SplashScreen } from '$components/splash-screen'; -import { buildGitHubUrl } from '$features/bug-report/BugReportModal'; type ErrorPageProps = { error: Error; @@ -25,7 +24,9 @@ ${error.message} ${stacktrace} \`\`\``; - return buildGitHubUrl('bug', `Error: ${error.message}`, { context: automatedBugReport }); + const title = encodeURIComponent(`Error: ${error.message}`); + const body = encodeURIComponent(automatedBugReport); + return `https://github.com/SableClient/Sable/issues/new?template=bug_report.yml&title=${title}&description=${body}`; } // This component is used as the fallback for the ErrorBoundary in App.tsx, which means it will be rendered whenever an uncaught error is thrown in any of the child components and not handled locally. diff --git a/src/app/components/RoomNotificationSwitcher.test.tsx b/src/app/components/RoomNotificationSwitcher.test.tsx index bd0b7c04c..28bf44808 100644 --- a/src/app/components/RoomNotificationSwitcher.test.tsx +++ b/src/app/components/RoomNotificationSwitcher.test.tsx @@ -56,7 +56,7 @@ describe('RoomNotificationModeSwitcher', () => { RoomNotificationMode.SpecialMessages, RoomNotificationMode.Unset ); - }); + }, 15000); it('disables interaction while the room mode is changing', () => { modeStateStatus.current = 'loading'; diff --git a/src/app/components/SwipeableChatWrapper.tsx b/src/app/components/SwipeableChatWrapper.tsx index d4a547298..4035d70b0 100644 --- a/src/app/components/SwipeableChatWrapper.tsx +++ b/src/app/components/SwipeableChatWrapper.tsx @@ -1,10 +1,13 @@ -import type { ReactNode } from 'react'; -import { motion, useMotionValue, useSpring } from 'framer-motion'; -import { useDrag } from '@use-gesture/react'; +import { lazy, Suspense, type ReactNode } from 'react'; import { useAtomValue } from 'jotai'; -import { settingsAtom, RightSwipeAction } from '$state/settings'; +import { settingsAtom } from '$state/settings'; import { mobileOrTablet } from '$utils/user-agent'; +const SwipeableChatWrapperActive = lazy(async () => { + const mod = await import('./SwipeableChatWrapperActive'); + return { default: mod.SwipeableChatWrapperActive }; +}); + interface SwipeableChatWrapperProps { children: ReactNode; onOpenSidebar?: () => void; @@ -19,76 +22,10 @@ export function SwipeableChatWrapper({ onReply, }: SwipeableChatWrapperProps) { const settings = useAtomValue(settingsAtom); - const x = useMotionValue(0); - const springX = useSpring(x, { stiffness: 400, damping: 40 }); - - const bind = useDrag( - ({ active, movement: [mx], velocity: [vx], direction: [dx], event: e }) => { - if (e && 'target' in e && e.target instanceof HTMLElement) { - if (e.target.closest('[data-gestures="ignore"]')) { - return; - } - } - - if (!settings.mobileGestures || !mobileOrTablet()) return; - - let val = mx; - - const canSwipeRight = !!onOpenSidebar; - const canSwipeLeft = - settings.rightSwipeAction === RightSwipeAction.Members ? !!onOpenMembers : !!onReply; - - if (!canSwipeRight && val > 0) val = 0; - if (!canSwipeLeft && val < 0) val = 0; - if (active) { - x.set(val); - } else { - const swipeThreshold = 120; - const velocityThreshold = 0.5; - - if (val > swipeThreshold || (vx > velocityThreshold && dx > 0 && val > 0)) { - onOpenSidebar?.(); - } else if (val < -swipeThreshold || (vx > velocityThreshold && dx < 0 && val < 0)) { - if (settings.rightSwipeAction === RightSwipeAction.Members) { - onOpenMembers?.(); - } else { - onReply?.(); - } - } - x.set(0); - } - }, - { - axis: 'x', - bounds: { left: -200, right: 200 }, - rubberband: true, - filterTaps: true, - } - ); - - if (!settings.mobileGestures || !mobileOrTablet()) { - return ( -