diff --git a/common/src/constants.ts b/common/src/constants.ts
index 8d1b773f..e7b4e0ce 100644
--- a/common/src/constants.ts
+++ b/common/src/constants.ts
@@ -19,7 +19,7 @@ export const xLink = "https://x.com/compassmeet"
export const formLink = "https://forms.gle/tKnXUMAbEreMK6FC6"
export const ANDROID_APP_URL = 'https://play.google.com/store/apps/details?id=com.compassconnections.app'
-export const IS_MAINTENANCE = false // set to true to enable the maintenance mode banner
+export const IS_MAINTENANCE = true // set to true to enable the maintenance mode banner
export const MIN_BIO_LENGTH = 250
diff --git a/web/components/nav/bottom-nav-bar.tsx b/web/components/nav/bottom-nav-bar.tsx
index 4aab84a7..9a1d3b94 100644
--- a/web/components/nav/bottom-nav-bar.tsx
+++ b/web/components/nav/bottom-nav-bar.tsx
@@ -2,7 +2,7 @@ import Link from 'next/link'
import clsx from 'clsx'
import {MenuAlt3Icon} from '@heroicons/react/solid'
import {Dialog, Transition} from '@headlessui/react'
-import {Fragment, useState} from 'react'
+import {Fragment, useState, useRef, useEffect} from 'react'
import {useRouter} from 'next/router'
import Sidebar from './sidebar'
import {Item} from './sidebar-item'
@@ -13,6 +13,7 @@ import {trackCallback} from 'web/lib/service/analytics'
import {User} from 'common/user'
import {Col} from 'web/components/layout/col'
import {useProfile} from 'web/hooks/use-profile'
+import {useIsMobile} from "web/hooks/use-is-mobile"
const itemClass =
'sm:hover:bg-ink-200 block w-full py-1 px-3 text-center sm:hover:text-primary-700 transition-colors'
@@ -38,37 +39,37 @@ export function BottomNavBar(props: {
}
return (
-
+ {navigationOptions.map((item) => (
+
+ ))}
+ setSidebarOpen(true)}
+ >
+
+ More
+
+
+
(null)
+ const touchStartY = useRef
(null)
+ const gestureHandled = useRef(false)
+ const isMobile = useIsMobile(1024) // for lg threshold, like in BottomNavBar vs Sidebar
+
+ const HORIZONTAL_THRESHOLD = 50 // px required to count as swipe
+ // const EDGE_START_MAX = 30 // px from left edge to allow open gesture
+
+ // Prefer global pointer events so gestures work even if a child intercepts touches
+ useEffect(() => {
+ if (!isMobile) return
+
+ const onPointerDown = (e: PointerEvent) => {
+ // console.log("onPointerDown")
+ if (!['touch', 'mouse'].includes(e.pointerType)) return
+ touchStartX.current = e.clientX
+ touchStartY.current = e.clientY
+ gestureHandled.current = false
+ }
+
+ const onPointerMove = (e: PointerEvent) => {
+ // console.log("onPointerMove")
+ if (!['touch', 'mouse'].includes(e.pointerType)) return
+ if (gestureHandled.current) return
+ if (touchStartX.current == null) return
+ const deltaX = e.clientX - touchStartX.current
+ const deltaY = e.clientY - (touchStartY.current ?? 0)
+
+ // Ignore primarily vertical gestures
+ if (Math.abs(deltaY) > Math.abs(deltaX)) return
+
+ if (!sidebarOpen) {
+ // console.log("checking opening")
+ // Open gesture: swipe right starting from the very left edge
+ if (deltaX > HORIZONTAL_THRESHOLD) {
+ gestureHandled.current = true
+ setSidebarOpen(true)
+ }
+ } else {
+ // Close gesture: swipe left anywhere
+ if (deltaX < -HORIZONTAL_THRESHOLD) {
+ gestureHandled.current = true
+ setSidebarOpen(false)
+ }
+ }
+ }
+
+ const onPointerUp = (_e: PointerEvent) => {
+ // console.log("onPointerUp")
+ touchStartX.current = null
+ touchStartY.current = null
+ gestureHandled.current = false
+ }
+
+ window.addEventListener('pointerdown', onPointerDown, {passive: true})
+ window.addEventListener('pointermove', onPointerMove, {passive: true})
+ window.addEventListener('pointerup', onPointerUp, {passive: true})
+
+ return () => {
+ window.removeEventListener('pointerdown', onPointerDown)
+ window.removeEventListener('pointermove', onPointerMove)
+ window.removeEventListener('pointerup', onPointerUp)
+ }
+ }, [isMobile, sidebarOpen])
+
return (