fix(web): leave chat with a document load for chart, ephemeris, and reports
Independent Staging Quality Gate / validate (pull_request) Failing after 9m45s
Independent Staging Quality Gate / publish (pull_request) Skipped
Independent Staging Quality Gate / validate (push) Failing after 9m14s
Independent Staging Quality Gate / publish (push) Skipped
Independent Staging Quality Gate / validate (pull_request) Failing after 9m45s
Independent Staging Quality Gate / publish (pull_request) Skipped
Independent Staging Quality Gate / validate (push) Failing after 9m14s
Independent Staging Quality Gate / publish (push) Skipped
Session URLs are written with history.pushState, so App Router router.push cannot leave the home page. Sidebar destinations now assign the document and stash the current conversation for return.
This commit is contained in:
@@ -18,9 +18,10 @@ import {
|
|||||||
UserRound,
|
UserRound,
|
||||||
Users,
|
Users,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import type { Ref } from "react";
|
import type { Ref } from "react";
|
||||||
|
import { persistLoginSessionReturn } from "@/lib/chat-session-url";
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
@@ -102,7 +103,7 @@ export function AppSidebar({
|
|||||||
sessionControls,
|
sessionControls,
|
||||||
onAccountMenuOpenChange,
|
onAccountMenuOpenChange,
|
||||||
onNewChat,
|
onNewChat,
|
||||||
onOpenReports,
|
onOpenReports: _onOpenReports,
|
||||||
onSelectSession,
|
onSelectSession,
|
||||||
onSelectChart,
|
onSelectChart,
|
||||||
onAddChart,
|
onAddChart,
|
||||||
@@ -113,7 +114,6 @@ export function AppSidebar({
|
|||||||
onOpenLogout,
|
onOpenLogout,
|
||||||
}: AppSidebarProps) {
|
}: AppSidebarProps) {
|
||||||
const { isMobile, setOpen, setOpenMobile, state, viewport } = useSidebar();
|
const { isMobile, setOpen, setOpenMobile, state, viewport } = useSidebar();
|
||||||
const router = useRouter();
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const firstSessionRef = useRef<HTMLButtonElement>(null);
|
const firstSessionRef = useRef<HTMLButtonElement>(null);
|
||||||
const historyHeadingRef = useRef<HTMLElement>(null);
|
const historyHeadingRef = useRef<HTMLElement>(null);
|
||||||
@@ -149,18 +149,23 @@ export function AppSidebar({
|
|||||||
if (isMobile) setOpenMobile(false);
|
if (isMobile) setOpenMobile(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function leaveChat(path: "/chart" | "/ephemeris" | "/reports") {
|
||||||
|
persistLoginSessionReturn();
|
||||||
|
window.location.assign(path);
|
||||||
|
}
|
||||||
|
|
||||||
function handleOpenReports() {
|
function handleOpenReports() {
|
||||||
onOpenReports();
|
leaveChat("/reports");
|
||||||
if (isMobile) setOpenMobile(false);
|
if (isMobile) setOpenMobile(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleOpenChart() {
|
function handleOpenChart() {
|
||||||
router.push("/chart");
|
leaveChat("/chart");
|
||||||
if (isMobile) setOpenMobile(false);
|
if (isMobile) setOpenMobile(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleOpenEphemeris() {
|
function handleOpenEphemeris() {
|
||||||
router.push("/ephemeris");
|
leaveChat("/ephemeris");
|
||||||
if (isMobile) setOpenMobile(false);
|
if (isMobile) setOpenMobile(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,15 +27,15 @@ test("in-app destinations navigate client-side so the chat survives the round tr
|
|||||||
assert.match(pageSource, /const router = useRouter\(\)/);
|
assert.match(pageSource, /const router = useRouter\(\)/);
|
||||||
|
|
||||||
// 原值: 4 条 membershipHref 软跳 /membership
|
// 原值: 4 条 membershipHref 软跳 /membership
|
||||||
// 新值: 账单入口改 openAccountDialog("billing");报告仍 router.push
|
// 新值: 账单入口改 openAccountDialog("billing");离开对话的星盘/星历/报告走 document load
|
||||||
// 原因: 删除 /membership 整页,对话状态不丢
|
// 原因: 对话用 history.pushState 写 ?c=,App Router 的 router.push 无法离开首页
|
||||||
assert.match(pageSource, /onOpenReports=\{\(\) => router\.push\("\/reports"\)\}/);
|
assert.match(pageSource, /onOpenReports=\{\(\) => router\.push\("\/reports"\)\}/);
|
||||||
assert.match(pageSource, /onOpenBilling=\{\(\) => openAccountDialog\("billing", \{ source: "account-menu" \}\)\}/);
|
assert.match(pageSource, /onOpenBilling=\{\(\) => openAccountDialog\("billing", \{ source: "account-menu" \}\)\}/);
|
||||||
assert.match(pageSource, /openAccountDialog\("billing", \{ returnTarget: event\.currentTarget, source: "credits" \}\)/);
|
assert.match(pageSource, /openAccountDialog\("billing", \{ returnTarget: event\.currentTarget, source: "credits" \}\)/);
|
||||||
assert.match(pageSource, /openAccountDialog\("billing", \{ source: "insufficient-credits" \}\)/);
|
assert.match(pageSource, /openAccountDialog\("billing", \{ source: "insufficient-credits" \}\)/);
|
||||||
assert.match(pageSource, /if \(response\.status === 402\) openAccountDialog\("billing", \{ source: "insufficient-credits" \}\)/);
|
assert.match(pageSource, /if \(response\.status === 402\) openAccountDialog\("billing", \{ source: "insufficient-credits" \}\)/);
|
||||||
|
|
||||||
// And: none of them fall back to a document load.
|
// And: membership stays in-page; leaving chat uses a document load in the sidebar.
|
||||||
assert.doesNotMatch(pageSource, /window\.location\.assign\("\/reports"\)/);
|
assert.doesNotMatch(pageSource, /window\.location\.assign\("\/reports"\)/);
|
||||||
assert.doesNotMatch(pageSource, /window\.location\.assign\(membershipHref\(/);
|
assert.doesNotMatch(pageSource, /window\.location\.assign\(membershipHref\(/);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -185,6 +185,18 @@ test("keeps the sidebar brand row free of a duplicate collapse trigger", () => {
|
|||||||
assert.doesNotMatch(appSidebar, /SidebarTrigger/);
|
assert.doesNotMatch(appSidebar, /SidebarTrigger/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("leaves the chat document for chart, ephemeris, and reports", () => {
|
||||||
|
const appSidebar = readProjectFile("src/components/app-sidebar.tsx");
|
||||||
|
// 对话首页用 history.pushState 维护 ?c=,App Router 的 router.push 无法离开。
|
||||||
|
assert.match(appSidebar, /persistLoginSessionReturn\(\);\s*window\.location\.assign\(path\)/);
|
||||||
|
assert.match(appSidebar, /leaveChat\("\/chart"\)/);
|
||||||
|
assert.match(appSidebar, /leaveChat\("\/ephemeris"\)/);
|
||||||
|
assert.match(appSidebar, /leaveChat\("\/reports"\)/);
|
||||||
|
assert.doesNotMatch(appSidebar, /router\.push\("\/chart"\)/);
|
||||||
|
assert.doesNotMatch(appSidebar, /router\.push\("\/ephemeris"\)/);
|
||||||
|
assert.doesNotMatch(appSidebar, /useRouter/);
|
||||||
|
});
|
||||||
|
|
||||||
test("uses one collapsed history action instead of icon-only session rows", () => {
|
test("uses one collapsed history action instead of icon-only session rows", () => {
|
||||||
const appSidebar = readProjectFile("src/components/app-sidebar.tsx");
|
const appSidebar = readProjectFile("src/components/app-sidebar.tsx");
|
||||||
assert.match(appSidebar, /MessageSquareText/);
|
assert.match(appSidebar, /MessageSquareText/);
|
||||||
|
|||||||
Reference in New Issue
Block a user