fix(web): preserve memo scope across global navigation

This commit is contained in:
johnnyjoygh 2026-08-05 09:32:41 +08:00
parent 4d2667983f
commit 83eab44695
2 changed files with 30 additions and 7 deletions

View file

@ -522,15 +522,15 @@ const GlobalNavigation = () => {
render={
<button
type="button"
aria-label={scopeItems[0].label}
aria-label={activeScopeItem.label}
className="flex size-[30px] items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-sidebar-accent/65 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
onClick={() => navigateToScope("home")}
onClick={() => navigateToScope(resolvedScope)}
/>
}
>
<HouseIcon className="size-4" strokeWidth={1.8} />
<ActiveScopeIcon className="size-4" strokeWidth={1.8} />
</TooltipTrigger>
<TooltipContent side="bottom">{scopeItems[0].label}</TooltipContent>
<TooltipContent side="bottom">{activeScopeItem.label}</TooltipContent>
</Tooltip>
)}
</>

View file

@ -4,7 +4,10 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import AppSidebar, { MobileAppHeader } from "@/components/AppSidebar";
const authState = vi.hoisted(() => ({ currentUser: { name: "users/test" } as { name: string } | undefined }));
const sidebarState = vi.hoisted(() => ({ setAboutOpen: vi.fn() }));
const sidebarState = vi.hoisted(() => ({
memoScope: "home" as "home" | "explore" | "archived",
setAboutOpen: vi.fn(),
}));
vi.mock("@/components/MemosLogo", () => ({
default: () => <span>Memos logo</span>,
@ -36,7 +39,7 @@ vi.mock("@/contexts/AppSidebarContext", () => ({
setMobileOpen: vi.fn(),
quickFindOpen: false,
setQuickFindOpen: vi.fn(),
memoScope: "home",
memoScope: sidebarState.memoScope,
setMemoScope: vi.fn(),
}),
}));
@ -90,6 +93,7 @@ vi.mock("@/utils/i18n", () => ({
describe("App sidebar logo", () => {
beforeEach(() => {
authState.currentUser = { name: "users/test" };
sidebarState.memoScope = "home";
sidebarState.setAboutOpen.mockReset();
});
@ -141,7 +145,7 @@ describe("App sidebar logo", () => {
expect(screen.getByRole("menuitem", { name: "common.archived" })).toBeInTheDocument();
});
it("collapses inactive global destinations and sends the scope icon to Home", async () => {
it("collapses inactive global destinations and defaults the scope icon to Home", async () => {
render(
<MemoryRouter initialEntries={["/attachments"]}>
<AppSidebar />
@ -166,6 +170,25 @@ describe("App sidebar logo", () => {
expect(screen.queryByRole("menuitem", { name: "common.explore" })).not.toBeInTheDocument();
});
it.each([
["explore", "common.explore", "/inbox"],
["archived", "common.archived", "/attachments"],
] as const)("keeps the %s scope available from a global destination", async (scope, label, destination) => {
sidebarState.memoScope = scope;
render(
<MemoryRouter initialEntries={[destination]}>
<AppSidebar />
</MemoryRouter>,
);
const scopeTrigger = screen.getByRole("button", { name: label });
expect(scopeTrigger).toHaveClass("size-[30px]");
expect(scopeTrigger).not.toHaveTextContent(label);
fireEvent.click(scopeTrigger);
expect(await screen.findByRole("button", { name: label })).toHaveTextContent(label);
});
it("keeps the mobile brand beside navigation without a duplicate search action", () => {
render(
<MemoryRouter initialEntries={["/"]}>