fix(nav): Back steps through sub-views and closes modals before leaving a page
In-app history only tracked the top-level page, so Back from a module sub-view (e.g. a Messages thread) or with a modal open jumped straight to the previous module. Add two history primitives: useHistorySubview (a module's sub-view rides in history.state, so Back returns to its root first) and useBackToClose (a mounted overlay occupies one history entry; Back closes the topmost, nesting-safe so a button-close doesn't trip the modals underneath). Apply to the Messages page views and to PlayerModal + the shared Modal. setPage now pushes a clean entry so each page starts at its root.
This commit is contained in:
parent
ad77a1751e
commit
71f79fc73d
5 changed files with 93 additions and 6 deletions
|
|
@ -6,6 +6,7 @@ import { api, type Conversation, type MessageUser } from "../lib/api";
|
|||
import { useLiveQuery } from "../lib/useLiveQuery";
|
||||
import { relativeTime } from "../lib/format";
|
||||
import { partnerPub, SYSTEM_ID, useKeyState } from "../lib/messaging";
|
||||
import { useHistorySubview } from "../lib/history";
|
||||
import { openChat } from "../lib/chatDock";
|
||||
import * as e2ee from "../lib/e2ee";
|
||||
import Avatar from "./Avatar";
|
||||
|
|
@ -17,7 +18,9 @@ const POLL_MS = 20000;
|
|||
type View = "list" | "new" | { partnerId: number; name?: string; avatar?: string | null; system?: boolean };
|
||||
|
||||
export default function Messages({ meId }: { meId: number }) {
|
||||
const [view, setView] = useState<View>("list");
|
||||
// Sub-views live in browser history, so Back returns to the conversation list before leaving
|
||||
// the module (open() pushes an entry; back() = history.back()).
|
||||
const { view, open, back } = useHistorySubview<View>("list");
|
||||
|
||||
if (typeof view === "object") {
|
||||
return (
|
||||
|
|
@ -27,18 +30,18 @@ export default function Messages({ meId }: { meId: number }) {
|
|||
isSystem={!!view.system}
|
||||
seedName={view.name}
|
||||
seedAvatar={view.avatar}
|
||||
onBack={() => setView("list")}
|
||||
onBack={back}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (view === "new") {
|
||||
return <Directory onPick={(u) => setView({ partnerId: u.id, name: u.name, avatar: u.avatar_url })} onBack={() => setView("list")} />;
|
||||
return <Directory onPick={(u) => open({ partnerId: u.id, name: u.name, avatar: u.avatar_url })} onBack={back} />;
|
||||
}
|
||||
return (
|
||||
<ConversationList
|
||||
meId={meId}
|
||||
onOpen={(c) => setView({ partnerId: c.partner.id, name: c.partner.name, avatar: c.partner.avatar_url, system: c.partner.id === SYSTEM_ID })}
|
||||
onNew={() => setView("new")}
|
||||
onOpen={(c) => open({ partnerId: c.partner.id, name: c.partner.name, avatar: c.partner.avatar_url, system: c.partner.id === SYSTEM_ID })}
|
||||
onNew={() => open("new")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue