Merge pull request #1288 from bradleypriest/pr/chat-session-url

ui(chat): persist session in URL and stabilize picker
This commit is contained in:
Peter Steinberger
2026-01-20 07:44:33 +00:00
committed by GitHub
2 changed files with 49 additions and 6 deletions

View File

@@ -1,8 +1,10 @@
import { html } from "lit";
import { repeat } from "lit/directives/repeat.js";
import type { AppViewState } from "./app-view-state";
import { iconForTab, pathForTab, titleForTab, type Tab } from "./navigation";
import { loadChatHistory } from "./controllers/chat";
import { syncUrlWithSessionKey } from "./app-settings";
import type { SessionsListResult } from "./types";
import type { ThemeMode } from "./theme";
import type { ThemeTransitionContext } from "./theme-transition";
@@ -64,10 +66,13 @@ export function renderChatControls(state: AppViewState) {
sessionKey: next,
lastActiveSessionKey: next,
});
syncUrlWithSessionKey(state, next, true);
void loadChatHistory(state);
}}
>
${sessionOptions.map(
${repeat(
sessionOptions,
(entry) => entry.key,
(entry) =>
html`<option value=${entry.key}>
${entry.displayName ?? entry.key}
@@ -119,9 +124,11 @@ function resolveSessionOptions(sessionKey: string, sessions: SessionsListResult
const seen = new Set<string>();
const options: Array<{ key: string; displayName?: string }> = [];
const resolvedCurrent = sessions?.sessions?.find((s) => s.key === sessionKey);
// Add current session key first
seen.add(sessionKey);
options.push({ key: sessionKey });
options.push({ key: sessionKey, displayName: resolvedCurrent?.displayName });
// Add sessions from the result
if (sessions?.sessions) {

View File

@@ -85,9 +85,12 @@ export function applySettingsFromUrl(host: SettingsHost) {
const session = sessionRaw.trim();
if (session) {
host.sessionKey = session;
applySettings(host, {
...host.settings,
sessionKey: session,
lastActiveSessionKey: session,
});
}
params.delete("session");
shouldCleanUrl = true;
}
if (!shouldCleanUrl) return;
@@ -225,6 +228,18 @@ export function onPopState(host: SettingsHost) {
if (typeof window === "undefined") return;
const resolved = tabFromPath(window.location.pathname, host.basePath);
if (!resolved) return;
const url = new URL(window.location.href);
const session = url.searchParams.get("session")?.trim();
if (session) {
host.sessionKey = session;
applySettings(host, {
...host.settings,
sessionKey: session,
lastActiveSessionKey: session,
});
}
setTabFromRoute(host, resolved);
}
@@ -241,9 +256,18 @@ export function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) {
if (typeof window === "undefined") return;
const targetPath = normalizePath(pathForTab(tab, host.basePath));
const currentPath = normalizePath(window.location.pathname);
if (currentPath === targetPath) return;
const url = new URL(window.location.href);
url.pathname = targetPath;
if (tab === "chat" && host.sessionKey) {
url.searchParams.set("session", host.sessionKey);
} else {
url.searchParams.delete("session");
}
if (currentPath !== targetPath) {
url.pathname = targetPath;
}
if (replace) {
window.history.replaceState({}, "", url.toString());
} else {
@@ -251,6 +275,18 @@ export function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) {
}
}
export function syncUrlWithSessionKey(
host: SettingsHost,
sessionKey: string,
replace: boolean,
) {
if (typeof window === "undefined") return;
const url = new URL(window.location.href);
url.searchParams.set("session", sessionKey);
if (replace) window.history.replaceState({}, "", url.toString());
else window.history.pushState({}, "", url.toString());
}
export async function loadOverview(host: SettingsHost) {
await Promise.all([
loadChannels(host as unknown as ClawdbotApp, false),