fix(webui): polish automation layout and session updates

This commit is contained in:
chengyongru
2026-06-15 17:30:06 +08:00
parent d7e73609d3
commit cbb4c0bad2
17 changed files with 340 additions and 149 deletions
+34 -18
View File
@@ -65,7 +65,8 @@ type BootState =
};
const SIDEBAR_STORAGE_KEY = "nanobot-webui.sidebar";
const COMPLETED_RUNS_STORAGE_KEY = "nanobot-webui.sidebar.completed-runs.v1";
const SESSION_UPDATES_STORAGE_KEY = "nanobot-webui.sidebar.session-updates.v1";
const LEGACY_COMPLETED_RUNS_STORAGE_KEY = "nanobot-webui.sidebar.completed-runs.v1";
const RESTART_STARTED_KEY = "nanobot-webui.restartStartedAt";
const SIDEBAR_WIDTH = 272;
const SIDEBAR_RAIL_WIDTH = 56;
@@ -258,10 +259,12 @@ function readSidebarOpen(): boolean {
}
}
function readCompletedRunChatIds(): Set<string> {
function readSessionUpdateChatIds(): Set<string> {
if (typeof window === "undefined") return new Set();
try {
const raw = window.localStorage.getItem(COMPLETED_RUNS_STORAGE_KEY);
const raw =
window.localStorage.getItem(SESSION_UPDATES_STORAGE_KEY)
?? window.localStorage.getItem(LEGACY_COMPLETED_RUNS_STORAGE_KEY);
const parsed = raw ? JSON.parse(raw) : [];
if (!Array.isArray(parsed)) return new Set();
return new Set(parsed.filter((item): item is string => typeof item === "string"));
@@ -270,10 +273,10 @@ function readCompletedRunChatIds(): Set<string> {
}
}
function writeCompletedRunChatIds(chatIds: Set<string>): void {
function writeSessionUpdateChatIds(chatIds: Set<string>): void {
try {
window.localStorage.setItem(
COMPLETED_RUNS_STORAGE_KEY,
SESSION_UPDATES_STORAGE_KEY,
JSON.stringify(Array.from(chatIds)),
);
} catch {
@@ -573,7 +576,7 @@ function Shell({
const [restartToast, setRestartToast] = useState<string | null>(null);
const [isRestarting, setIsRestarting] = useState(false);
const [runningChatIds, setRunningChatIds] = useState<Set<string>>(() => new Set());
const [completedChatIds, setCompletedChatIds] = useState<Set<string>>(readCompletedRunChatIds);
const [updatedChatIds, setUpdatedChatIds] = useState<Set<string>>(readSessionUpdateChatIds);
const [workspaces, setWorkspaces] = useState<WorkspacesPayload | null>(null);
const skills = useSkills(token);
const [settingsSnapshot, setSettingsSnapshot] = useState<SettingsPayload | null>(null);
@@ -641,20 +644,20 @@ function Shell({
}, [hostSidebarOpen]);
useEffect(() => {
writeCompletedRunChatIds(completedChatIds);
}, [completedChatIds]);
writeSessionUpdateChatIds(updatedChatIds);
}, [updatedChatIds]);
const activeSession = useMemo<ChatSummary | null>(() => {
if (!activeKey) return null;
return sessions.find((s) => s.key === activeKey) ?? null;
}, [sessions, activeKey]);
const runningChatIdList = useMemo(() => Array.from(runningChatIds), [runningChatIds]);
const completedChatIdList = useMemo(() => Array.from(completedChatIds), [completedChatIds]);
const updatedChatIdList = useMemo(() => Array.from(updatedChatIds), [updatedChatIds]);
const activeChatId = activeSession?.chatId ?? null;
useEffect(() => {
activeChatIdRef.current = activeChatId;
if (!activeChatId) return;
setCompletedChatIds((current) => {
setUpdatedChatIds((current) => {
if (!current.has(activeChatId)) return current;
const next = new Set(current);
next.delete(activeChatId);
@@ -694,7 +697,7 @@ function Shell({
useEffect(() => {
if (loading) return;
const knownChatIds = new Set(sessions.map((session) => session.chatId));
setCompletedChatIds((current) => {
setUpdatedChatIds((current) => {
const next = new Set(
Array.from(current).filter((chatId) => knownChatIds.has(chatId)),
);
@@ -722,12 +725,25 @@ function Shell({
}, [activeKey, loading, navigate, sessions]);
useEffect(() => {
return client.onSessionUpdate((_chatId, _scope, workspaceScope) => {
return client.onSessionUpdate((chatId, scope, workspaceScope) => {
if (scope === "thread") {
setUpdatedChatIds((current) => {
const next = new Set(current);
if (activeChatIdRef.current === chatId) {
next.delete(chatId);
} else {
next.add(chatId);
}
return next.size === current.size && next.has(chatId) === current.has(chatId)
? current
: next;
});
}
if (!workspaceScope) return;
const next = normalizeWorkspaceScope(workspaceScope);
setWorkspaceOverrides((current) => ({
...current,
[_chatId]: next,
[chatId]: next,
}));
setDraftWorkspaceScope(next);
setWorkspaceError(null);
@@ -764,7 +780,7 @@ function Shell({
runningChatIdsRef.current = next;
return next;
});
setCompletedChatIds((current) => {
setUpdatedChatIds((current) => {
let changed = false;
const next = new Set(current);
for (const chatId of activeRunIds) {
@@ -961,7 +977,7 @@ function Shell({
const selected = sessions.find((session) => session.key === key);
const selectedChatId = selected?.chatId;
if (selectedChatId) {
setCompletedChatIds((current) => {
setUpdatedChatIds((current) => {
if (!current.has(selectedChatId)) return current;
const next = new Set(current);
next.delete(selectedChatId);
@@ -1232,7 +1248,7 @@ function Shell({
nextRunning.add(chatId);
runningChatIdsRef.current = nextRunning;
setRunningChatIds(nextRunning);
setCompletedChatIds((current) => {
setUpdatedChatIds((current) => {
if (!current.has(chatId)) return current;
const next = new Set(current);
next.delete(chatId);
@@ -1246,7 +1262,7 @@ function Shell({
nextRunning.delete(chatId);
runningChatIdsRef.current = nextRunning;
setRunningChatIds(nextRunning);
setCompletedChatIds((current) => {
setUpdatedChatIds((current) => {
const next = new Set(current);
if (activeChatIdRef.current === chatId) {
next.delete(chatId);
@@ -1393,7 +1409,7 @@ function Shell({
projectNameOverrides: sidebarState.project_name_overrides,
collapsedGroups: sidebarState.collapsed_groups,
runningChatIds: runningChatIdList,
completedChatIds: completedChatIdList,
updatedChatIds: updatedChatIdList,
viewState: sidebarState.view,
showArchived: sidebarState.view.show_archived,
archivedCount: sidebarState.archived_keys.length,