diff --git a/packages/gui-extensions/src/details/popover.tsx b/packages/gui-extensions/src/details/popover.tsx index fa5d5e6ffd3..1ed08ffa5a4 100644 --- a/packages/gui-extensions/src/details/popover.tsx +++ b/packages/gui-extensions/src/details/popover.tsx @@ -9,8 +9,12 @@ import { Command, createKeyed, createVisitState, useExtension, type MountedSessi import type Details from "./index" import type { DetailsPanelProps } from "./panel" +/** Every mounted details menu, so a shortcut finds the one on screen. */ +export type DetailsMenus = Set<{ trigger: () => HTMLButtonElement | undefined; toggle: () => void }> + /** The session details menu of one timeline header. Cached timelines each keep their own. */ export function DetailsHeader(props: { + menus: DetailsMenus session: MountedSession screen: SessionScreen active: boolean @@ -49,7 +53,7 @@ export function DetailsHeader(props: { return ( {(project) => ( - + HTMLButtonElement | undefined; toggle: () => void }>() - -function DetailsPopover(props: ParentProps<{ active: boolean; open: boolean; onOpenChange: (open: boolean) => void }>) { +function DetailsPopover( + props: ParentProps<{ menus: DetailsMenus; active: boolean; open: boolean; onOpenChange: (open: boolean) => void }>, +) { const ctx = useExtension() const keybinds = ctx.keybinds @@ -79,8 +82,8 @@ function DetailsPopover(props: ParentProps<{ active: boolean; open: boolean; onO // A shortcut opens the menu without its trigger, so the trigger is named as the anchor. let trigger: HTMLButtonElement | undefined const self = { trigger: () => trigger, toggle: () => props.onOpenChange(!props.open) } - menus.add(self) - onCleanup(() => menus.delete(self)) + props.menus.add(self) + onCleanup(() => props.menus.delete(self)) ctx.add(Command, (): Command | undefined => props.active @@ -91,7 +94,7 @@ function DetailsPopover(props: ParentProps<{ active: boolean; open: boolean; onO section: "session", bind: "mod+shift+y", // A detached timeline can stay active, so the shortcut toggles the menu whose trigger is on screen. - run: () => [...menus].find((menu) => menu.trigger()?.isConnected)?.toggle(), + run: () => [...props.menus].find((menu) => menu.trigger()?.isConnected)?.toggle(), } : undefined, ) diff --git a/packages/gui-extensions/src/details/renderer.tsx b/packages/gui-extensions/src/details/renderer.tsx index 30a6a9404e4..301872dbe66 100644 --- a/packages/gui-extensions/src/details/renderer.tsx +++ b/packages/gui-extensions/src/details/renderer.tsx @@ -2,12 +2,14 @@ import { createMemo, lazy, onCleanup, Show, Suspense } from "solid-js" import { createStore } from "solid-js/store" import { createKeyed, onIdle, Panel, Slot, Style, useDrawer, usePanel, type Setup } from "../sdk" import type Details from "./index" -import { DetailsHeader } from "./popover" +import { DetailsHeader, type DetailsMenus } from "./popover" const setup: Setup = (ctx) => { const sessions = ctx.sessions const changes = ctx.uses.changes + const menus: DetailsMenus = new Set() + const DetailsPanel = lazy(() => Promise.all([import("./panel"), import("./details.css?inline")]).then(([panel, css]) => { ctx.add(Style, css.default) @@ -23,7 +25,13 @@ const setup: Setup = (ctx) => { at: "session.header", order: 20, render: (input) => ( - + ), })