Browse Source

fix opening and closig of drawers and panels

imwald
Silberengel 3 months ago
parent
commit
21646d9b8a
  1. 45
      src/PageManager.tsx
  2. 33
      src/components/NoteDrawer/index.tsx

45
src/PageManager.tsx

@ -672,11 +672,11 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -672,11 +672,11 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
setDrawerOpen(true)
}, [])
const closeDrawer = () => {
const closeDrawer = useCallback(() => {
if (!drawerOpen) return // Already closed
setDrawerOpen(false)
// Clear noteId after animation completes (Sheet animation is 300ms)
setTimeout(() => setDrawerNoteId(null), 300)
}
// Don't clear noteId here - let onOpenChange handle it when animation completes
}, [drawerOpen])
const ignorePopStateRef = useRef(false)
// Handle browser back button for primary note view
@ -983,9 +983,10 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -983,9 +983,10 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
closeDrawer()
}
// DO NOT update URL when closing panel - closing should NEVER affect the main page
} else {
} else if (newStack.length > 0) {
// Stack still has items - update drawer to show the top item's note (for mobile/single-pane)
if (isSmallScreen || panelMode === 'single') {
// Only update drawer if drawer is currently open (not in the process of closing)
if ((isSmallScreen || panelMode === 'single') && drawerOpen && drawerNoteId) {
// Extract noteId from top item's URL or from state.url
const topItemUrl = newStack[newStack.length - 1]?.url || state?.url
if (topItemUrl) {
@ -993,16 +994,20 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -993,16 +994,20 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
topItemUrl.match(/\/notes\/(.+)$/)
if (topNoteUrlMatch) {
const topNoteId = topNoteUrlMatch[topNoteUrlMatch.length - 1].split('?')[0].split('#')[0]
if (topNoteId) {
if (topNoteId && topNoteId !== drawerNoteId) {
// Use setTimeout to ensure drawer update happens after stack state is committed
setTimeout(() => {
// Double-check drawer is still open before updating
if (drawerOpen) {
openDrawer(topNoteId)
}
}, 0)
}
}
}
}
}
// If newStack.length === 0, we're closing - don't reopen the drawer
return newStack
})
}
@ -1220,14 +1225,16 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -1220,14 +1225,16 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
// Single-pane mode or mobile: check if drawer is open and stack is empty - close drawer instead
if (drawerOpen && secondaryStack.length === 0) {
// Close drawer and reveal the background page
closeDrawer()
setDrawerOpen(false)
setTimeout(() => setDrawerNoteId(null), 350)
return
}
// On mobile or single-pane: if stack has 1 item and drawer is open, close drawer and clear stack
if ((isSmallScreen || panelMode === 'single') && secondaryStack.length === 1 && drawerOpen) {
// Close drawer (this will restore the URL to the correct primary page)
closeDrawer()
setDrawerOpen(false)
setTimeout(() => setDrawerNoteId(null), 350)
// Clear stack
setSecondaryStack([])
@ -1415,10 +1422,14 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -1415,10 +1422,14 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
<NoteDrawer
open={drawerOpen}
onOpenChange={(open) => {
if (!open) {
closeDrawer()
} else {
setDrawerOpen(open)
// Only clear noteId when Sheet is fully closed (after animation completes)
// Use 350ms to ensure animation is fully done (animation is 300ms)
if (!open) {
// Restore URL to current primary page
const pageUrl = currentPrimaryPage === 'home' ? '/' : `/${currentPrimaryPage}`
window.history.replaceState(null, '', pageUrl)
setTimeout(() => setDrawerNoteId(null), 350)
}
}}
noteId={drawerNoteId}
@ -1522,10 +1533,14 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -1522,10 +1533,14 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
<NoteDrawer
open={drawerOpen}
onOpenChange={(open) => {
if (!open) {
closeDrawer()
} else {
setDrawerOpen(open)
// Only clear noteId when Sheet is fully closed (after animation completes)
// Use 350ms to ensure animation is fully done (animation is 300ms)
if (!open) {
// Restore URL to current primary page
const pageUrl = currentPrimaryPage === 'home' ? '/' : `/${currentPrimaryPage}`
window.history.replaceState(null, '', pageUrl)
setTimeout(() => setDrawerNoteId(null), 350)
}
}}
noteId={drawerNoteId}

33
src/components/NoteDrawer/index.tsx

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
import { useState, useEffect, useRef } from 'react'
import { Sheet, SheetContent } from '@/components/ui/sheet'
import NotePage from '@/pages/secondary/NotePage'
@ -8,13 +9,41 @@ interface NoteDrawerProps { @@ -8,13 +9,41 @@ interface NoteDrawerProps {
}
export default function NoteDrawer({ open, onOpenChange, noteId }: NoteDrawerProps) {
if (!noteId) return null
const [displayNoteId, setDisplayNoteId] = useState<string | null>(noteId)
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
useEffect(() => {
// Clear any pending timeout
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
timeoutRef.current = null
}
if (noteId) {
// New noteId - show immediately
setDisplayNoteId(noteId)
} else if (!open && displayNoteId) {
// Closing - keep content visible during animation (350ms)
timeoutRef.current = setTimeout(() => {
setDisplayNoteId(null)
timeoutRef.current = null
}, 350)
}
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
}
}, [noteId, open])
if (!displayNoteId) return null
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="right" className="w-full sm:max-w-[1042px] overflow-y-auto p-0">
<div className="h-full">
<NotePage id={noteId} index={0} hideTitlebar={false} />
<NotePage id={displayNoteId} index={0} hideTitlebar={false} />
</div>
</SheetContent>
</Sheet>

Loading…
Cancel
Save