diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b760184..497af69 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "remoteterm-meshcore-frontend", - "version": "2.7.9", + "version": "3.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "remoteterm-meshcore-frontend", - "version": "2.7.9", + "version": "3.6.0", "dependencies": { "@codemirror/lang-python": "^6.2.1", "@codemirror/theme-one-dark": "^6.1.3", @@ -29,6 +29,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-leaflet": "^4.2.1", + "react-swipeable": "^7.0.2", "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss-animate": "^1.0.7", @@ -5695,6 +5696,15 @@ } } }, + "node_modules/react-swipeable": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/react-swipeable/-/react-swipeable-7.0.2.tgz", + "integrity": "sha512-v1Qx1l+aC2fdxKa9aKJiaU/ZxmJ5o98RMoFwUqAAzVWUcxgfHFXDDruCKXhw6zIYXm6V64JiHgP9f6mlME5l8w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 6aeaae4..bbb596c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -37,6 +37,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-leaflet": "^4.2.1", + "react-swipeable": "^7.0.2", "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss-animate": "^1.0.7", diff --git a/frontend/src/components/AppShell.tsx b/frontend/src/components/AppShell.tsx index 84b6ed2..e72ede6 100644 --- a/frontend/src/components/AppShell.tsx +++ b/frontend/src/components/AppShell.tsx @@ -1,4 +1,5 @@ import { lazy, Suspense, useRef, type ComponentProps } from 'react'; +import { useSwipeable } from 'react-swipeable'; import { StatusBar } from './StatusBar'; import { Sidebar } from './Sidebar'; @@ -89,6 +90,24 @@ export function AppShell({ contactInfoPaneProps, channelInfoPaneProps, }: AppShellProps) { + const swipeHandlers = useSwipeable({ + onSwipedRight: ({ initial }) => { + if (initial[0] < 30 && !sidebarOpen && window.innerWidth < 768) { + onSidebarOpenChange(true); + } + }, + trackTouch: true, + trackMouse: false, + preventScrollOnSwipe: true, + }); + + const closeSwipeHandlers = useSwipeable({ + onSwipedLeft: () => onSidebarOpenChange(false), + trackTouch: true, + trackMouse: false, + preventScrollOnSwipe: false, + }); + const searchMounted = useRef(false); if (conversationPaneProps.activeConversation?.type === 'search') { searchMounted.current = true; @@ -153,7 +172,7 @@ export function AppShell({ ); return ( -