feat(meetings): center clock, fullscreen toggle, quick-note tab (#583)
- Replace HeaderClock with richer analog+weekday+digital block, always
centered in the header (both president and normal views). Drop the
PresidentClockBar render from the toolbar; the dead helper is left
in place but unused.
- Lift fullscreen state to ExecutiveMeetingsPageInner with
sessionStorage persistence, Esc handler, auto-exit when the user
leaves the schedule tab. Hide the page header when active and show a
floating "Exit fullscreen" pill. New Maximize/Minimize toggle in the
schedule toolbar portal.
- Add MeetingsQuickNoteTab: a fixed amber vertical pill pinned to the
left edge of the schedule view that navigates to /notes?new=1.
- notes.tsx: detect ?new=1, switch to the Active tab, bump a numeric
openTrigger that the top Composer reacts to by opening + focusing
the textarea, then scrub the query param so navigation doesn't
re-trigger.
- i18n: add executiveMeetings.fullscreen.{enter,exit} and
executiveMeetings.quickNote.label in ar.json and en.json.
tsc clean. Push to Gitea still blocked by Tailscale; user to retry.
This commit is contained in:
@@ -286,14 +286,10 @@ export default function NotesPage() {
|
||||
setView("active");
|
||||
// The top Composer is only mounted when
|
||||
// `view === "active" && folderSelection.kind !== "shared-folder"`.
|
||||
// If the user arrived from /notes?new=1 while sitting inside a
|
||||
// shared folder, leaving the selection alone would mean the
|
||||
// Composer is never rendered and the open trigger would be lost.
|
||||
// Reset to the default "all" folder so the composer is guaranteed
|
||||
// visible regardless of where they were before.
|
||||
setFolderSelection((cur) =>
|
||||
cur.kind === "shared-folder" ? { kind: "all" } : cur,
|
||||
);
|
||||
// Always land on the default "all" folder so /notes?new=1 has a
|
||||
// deterministic landing state and the composer is guaranteed
|
||||
// mounted regardless of where the user was before.
|
||||
setFolderSelection({ kind: "all" });
|
||||
setComposerOpenTrigger((n) => n + 1);
|
||||
if (typeof window !== "undefined") {
|
||||
params.delete("new");
|
||||
@@ -3566,10 +3562,14 @@ function Composer({
|
||||
};
|
||||
|
||||
// External open trigger (e.g. /notes?new=1 from the meetings quick
|
||||
// note tab). Skip the initial mount value (0) and only react to
|
||||
// subsequent bumps, then focus + scroll the textarea into view.
|
||||
const lastOpenTrigger = useRef(openTrigger);
|
||||
// note tab). React both to subsequent bumps AND to the initial mount
|
||||
// when the trigger is already > 0 — this covers the case where the
|
||||
// page resets folder selection and the Composer mounts fresh with a
|
||||
// non-zero trigger (e.g. user was in a shared folder and clicked the
|
||||
// quick-note tab).
|
||||
const lastOpenTrigger = useRef(0);
|
||||
useEffect(() => {
|
||||
if (openTrigger === 0) return;
|
||||
if (openTrigger === lastOpenTrigger.current) return;
|
||||
lastOpenTrigger.current = openTrigger;
|
||||
setOpen(true);
|
||||
|
||||
Reference in New Issue
Block a user