diff --git a/src/pages/AppFrame.tsx b/src/pages/AppFrame.tsx index fb27799..c99704c 100644 --- a/src/pages/AppFrame.tsx +++ b/src/pages/AppFrame.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { ChevronRight } from 'lucide-react' import { Sidebar } from '../components/Sidebar' @@ -9,6 +9,19 @@ export function AppFrame({ user }: { user: User }) { const navigate = useNavigate() const app = user.apps.find(a => a.slug === slug) const [menuOpen, setMenuOpen] = useState(false) + const iframeRef = useRef(null) + + // Capture hash once at mount — before iframe navigation overwrites it + const [initialSrc] = useState(() => { + if (!app) return '' + const sub = window.location.hash.slice(1) + return sub && sub !== '/' ? `${app.base_path}${sub}` : `${app.base_path}/` + }) + + // Clear hash when switching apps + useEffect(() => { + return () => { history.replaceState(null, '', window.location.pathname) } + }, [slug]) // Auto-close when user clicks into / navigates within the iframe useEffect(() => { @@ -18,6 +31,18 @@ export function AppFrame({ user }: { user: User }) { return () => window.removeEventListener('blur', close) }, [menuOpen]) + function handleIframeLoad() { + try { + const iframePath = iframeRef.current?.contentWindow?.location.pathname ?? '' + const relative = iframePath.replace(app!.base_path, '') || '/' + if (relative !== '/') { + history.replaceState(null, '', `/app/${slug}#${relative}`) + } + } catch { + // cross-origin guard — won't trigger in this same-origin stack + } + } + if (!app) { return (
@@ -75,10 +100,12 @@ export function AppFrame({ user }: { user: User }) {