diff --git a/packages/app/src/shell/notifications/notification.test.ts b/packages/app/src/shell/notifications/notification.test.ts new file mode 100644 index 00000000000..1dec4df6dd2 --- /dev/null +++ b/packages/app/src/shell/notifications/notification.test.ts @@ -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) => { + 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"]) +}) diff --git a/packages/app/src/shell/notifications/notification.tsx b/packages/app/src/shell/notifications/notification.tsx index dfc48b6eca4..2232373764c 100644 --- a/packages/app/src/shell/notifications/notification.tsx +++ b/packages/app/src/shell/notifications/notification.tsx @@ -51,6 +51,19 @@ type NotificationIndex = { } } +type NotificationTabs = Pick, "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), + ) } }) }