fix(app): route notification clicks through tabs (#44897)

Co-authored-by: Brendonovich <14191578+Brendonovich@users.noreply.github.com>
This commit is contained in:
opencode-agent[bot] 2026-08-25 14:11:59 +08:00 committed by GitHub
parent 8c126e98da
commit 190f189fbe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 9 deletions

View file

@ -0,0 +1,26 @@
import { expect, test } from "bun:test"
import type { ServerConnection } from "@/runtime/server/registry"
import type { Tab } from "@/shell/tabs/tabs"
import { openNotificationSession } from "./notification"
test("opens notification sessions through the tab router", () => {
const server = "local\nhttp://localhost:4096" as ServerConnection.Key
const tab = { type: "session" as const, server, sessionId: "session-1" }
const calls: string[] = []
const tabs = {
addSessionTab: (input: Omit<typeof tab, "type">) => {
calls.push(`add:${input.sessionId}`)
return tab
},
rememberSessionRoute: (_tab: typeof tab, sessionID: string) => {
calls.push(`route:${sessionID}`)
},
select: (input: Tab) => {
calls.push(`select:${input.type === "session" ? input.sessionId : input.draftID}`)
},
}
openNotificationSession(tabs, server, "session-1")
expect(calls).toEqual(["add:session-1", "route:session-1", "select:session-1"])
})

View file

@ -51,6 +51,19 @@ type NotificationIndex = {
}
}
type NotificationTabs = Pick<ReturnType<typeof useTabs>, "addSessionTab" | "rememberSessionRoute" | "select">
export function openNotificationSession(
tabs: NotificationTabs,
server: ServerConnection.Key,
sessionID: string,
) {
const tab = tabs.addSessionTab({ server, sessionId: sessionID })
if (tab.type !== "session") return
tabs.rememberSessionRoute(tab, sessionID)
tabs.select(tab)
}
const MAX_NOTIFICATIONS = 500
const NOTIFICATION_TTL_MS = 1000 * 60 * 60 * 24 * 30
@ -211,11 +224,6 @@ export function createServerNotificationState(input: { sdk: ServerSDK; data: Dat
return typeof location !== "undefined" && location.pathname === sessionHref(input.key, sessionID)
}
const navigate = (href: string) => {
history.pushState(null, "", href)
dispatchEvent(new PopStateEvent("popstate"))
}
const handleSessionIdle = (sessionID: string, eventID: string, time: number) => {
void lookup(sessionID).then((session) => {
if (meta.disposed) return
@ -237,10 +245,9 @@ export function createServerNotificationState(input: { sdk: ServerSDK; data: Dat
session: sessionID,
})
const href = sessionHref(input.key, sessionID)
if (settings.notifications.agent()) {
void platform.notify(language.t("notification.session.responseReady.title"), session.title ?? sessionID, () =>
navigate(href),
openNotificationSession(tabs, input.key, sessionID),
)
}
})
@ -274,9 +281,10 @@ export function createServerNotificationState(input: { sdk: ServerSDK; data: Dat
const description =
session?.title ??
(typeof error === "string" ? error : language.t("notification.session.error.fallbackDescription"))
const href = sessionHref(input.key, sessionID)
if (settings.notifications.errors()) {
void platform.notify(language.t("notification.session.error.title"), description, () => navigate(href))
void platform.notify(language.t("notification.session.error.title"), description, () =>
openNotificationSession(tabs, input.key, sessionID),
)
}
})
}