mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
Highlight the rail entry whose tool is open (#7723)
This commit is contained in:
@@ -22,6 +22,7 @@ export interface QuickNavHostBridgeProps {
|
||||
requestNavigation?: (go: () => void) => void;
|
||||
onGoToDefaultState?: () => void;
|
||||
onSelectTool?: (toolId: ToolId) => void;
|
||||
activeTool?: ToolId | null;
|
||||
/** Merged over the reasons worked out here, for what only the app can see. */
|
||||
toolReasons?: QuickNavToolReasons;
|
||||
}
|
||||
@@ -34,6 +35,7 @@ export function QuickNavHostBridge({
|
||||
onOpenSettings,
|
||||
requestNavigation,
|
||||
onSelectTool,
|
||||
activeTool = null,
|
||||
onGoToDefaultState,
|
||||
toolReasons,
|
||||
}: QuickNavHostBridgeProps) {
|
||||
@@ -59,6 +61,7 @@ export function QuickNavHostBridge({
|
||||
signingBadge,
|
||||
portalAccess,
|
||||
readerMode,
|
||||
activeTool,
|
||||
notificationsOpen,
|
||||
toolReasons: mergedToolReasons,
|
||||
},
|
||||
|
||||
@@ -48,6 +48,8 @@ export function QuickNavRailHost() {
|
||||
else go(route);
|
||||
};
|
||||
|
||||
const openingTool = (id: ToolId) => ({ current: host?.activeTool === id });
|
||||
|
||||
const unusable = (id: ToolId) => {
|
||||
const reason = host?.toolReasons?.[id];
|
||||
return { disabled: Boolean(reason), reason };
|
||||
@@ -135,6 +137,7 @@ export function QuickNavRailHost() {
|
||||
icon: (
|
||||
<LocalIcon icon="rebase-outline-rounded" width={SIZE} height={SIZE} />
|
||||
),
|
||||
...openingTool("automate"),
|
||||
...unusable("automate"),
|
||||
onClick: () => openTool("automate", "/automate"),
|
||||
},
|
||||
@@ -146,6 +149,7 @@ export function QuickNavRailHost() {
|
||||
),
|
||||
badge: host?.signingBadge,
|
||||
badgeTone: "warning",
|
||||
...openingTool("sharedSign"),
|
||||
...unusable("sharedSign"),
|
||||
onClick: () => openTool("sharedSign", "/shared-sign"),
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ function Probe({ onRead }: { onRead: (value: unknown) => void }) {
|
||||
appMounted: host?.appMounted,
|
||||
chromeless: host?.chromeless,
|
||||
identity: host?.identity,
|
||||
activeTool: host?.activeTool,
|
||||
openSettings: Boolean(host?.actions.current?.openSettings),
|
||||
});
|
||||
return null;
|
||||
@@ -26,6 +27,11 @@ function App() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function AppWithTool({ tool }: { tool: "automate" | null }) {
|
||||
useRegisterQuickNavHost({ activeTool: tool }, {});
|
||||
return null;
|
||||
}
|
||||
|
||||
function LoginRoute() {
|
||||
useSuppressQuickNavRail();
|
||||
return null;
|
||||
@@ -71,6 +77,31 @@ describe("QuickNavHostContext", () => {
|
||||
expect(after.openSettings).toBe(false);
|
||||
});
|
||||
|
||||
it("clears the open tool when the next app registers without one", () => {
|
||||
let latest: Record<string, unknown> = {};
|
||||
const view = render(
|
||||
<QuickNavHostProvider>
|
||||
<Probe
|
||||
onRead={(value) => (latest = value as Record<string, unknown>)}
|
||||
/>
|
||||
<AppWithTool tool="automate" />
|
||||
</QuickNavHostProvider>,
|
||||
);
|
||||
expect(latest.activeTool).toBe("automate");
|
||||
|
||||
act(() => {
|
||||
view.rerender(
|
||||
<QuickNavHostProvider>
|
||||
<Probe
|
||||
onRead={(value) => (latest = value as Record<string, unknown>)}
|
||||
/>
|
||||
<AppWithTool tool={null} />
|
||||
</QuickNavHostProvider>,
|
||||
);
|
||||
});
|
||||
expect(latest.activeTool).toBe(null);
|
||||
});
|
||||
|
||||
it("hides the bar while a route with no app chrome is on screen", () => {
|
||||
// appMounted is sticky, so it can't answer "is an app on screen now".
|
||||
const { view, read } = setup();
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface QuickNavHostData {
|
||||
signingBadge: number;
|
||||
portalAccess: boolean;
|
||||
readerMode: boolean;
|
||||
activeTool: ToolId | null;
|
||||
/** The app owns the panel; the rail's bell only reports its state. */
|
||||
notificationsOpen: boolean;
|
||||
/** Translated; absent means usable. */
|
||||
@@ -61,6 +62,7 @@ const EMPTY_DATA: QuickNavHostData = {
|
||||
signingBadge: 0,
|
||||
portalAccess: false,
|
||||
readerMode: false,
|
||||
activeTool: null,
|
||||
notificationsOpen: false,
|
||||
hasSettings: false,
|
||||
};
|
||||
@@ -90,6 +92,7 @@ export function QuickNavHostProvider({ children }: { children: ReactNode }) {
|
||||
merged.signingBadge === prev.signingBadge &&
|
||||
merged.portalAccess === prev.portalAccess &&
|
||||
merged.readerMode === prev.readerMode &&
|
||||
merged.activeTool === prev.activeTool &&
|
||||
merged.notificationsOpen === prev.notificationsOpen &&
|
||||
merged.hasSettings === prev.hasSettings &&
|
||||
merged.identity?.displayName === prev.identity?.displayName &&
|
||||
@@ -143,6 +146,7 @@ export function useRegisterQuickNavHost(
|
||||
signingBadge,
|
||||
portalAccess,
|
||||
readerMode,
|
||||
activeTool,
|
||||
notificationsOpen,
|
||||
toolReasons,
|
||||
} = data;
|
||||
@@ -155,6 +159,8 @@ export function useRegisterQuickNavHost(
|
||||
signingBadge: signingBadge ?? 0,
|
||||
portalAccess: portalAccess ?? false,
|
||||
readerMode: readerMode ?? false,
|
||||
// Cleared, not omitted as toolReasons is: a stale tool marks an entry.
|
||||
activeTool: activeTool ?? null,
|
||||
notificationsOpen: notificationsOpen ?? false,
|
||||
// Omitted when unknown, so the last answer survives a re-fetch.
|
||||
...(toolReasons ? { toolReasons } : {}),
|
||||
@@ -168,6 +174,7 @@ export function useRegisterQuickNavHost(
|
||||
signingBadge,
|
||||
portalAccess,
|
||||
readerMode,
|
||||
activeTool,
|
||||
notificationsOpen,
|
||||
toolReasons,
|
||||
hasSettings,
|
||||
|
||||
@@ -525,6 +525,7 @@ export default function HomePage() {
|
||||
onSetReaderMode={setReaderMode}
|
||||
onGoToDefaultState={goToDefaultState}
|
||||
onSelectTool={handleToolSelect}
|
||||
activeTool={selectedToolKey}
|
||||
toolReasons={quickNavToolReasons}
|
||||
/>
|
||||
<FilesPageProvider>
|
||||
|
||||
Reference in New Issue
Block a user