diff --git a/packages/ui/src/components/session-list.tsx b/packages/ui/src/components/session-list.tsx index 74bc0cfc..58e52196 100644 --- a/packages/ui/src/components/session-list.tsx +++ b/packages/ui/src/components/session-list.tsx @@ -2,7 +2,7 @@ import { Component, For, Show, createSignal, createMemo, createEffect, JSX, onCl import type { SessionStatus } from "../types/session" import type { SessionThread } from "../stores/session-state" import { getSessionStatus } from "../stores/session-status" -import { Bot, User, Copy, Trash2, Pencil, ShieldAlert, ChevronDown, Search, Square, CheckSquare, MinusSquare, Split } from "lucide-solid" +import { Bot, User, Copy, Trash2, Pencil, ShieldAlert, ChevronDown, Search, Square, CheckSquare, MinusSquare, Split, RotateCw } from "lucide-solid" import KeyboardHint from "./keyboard-hint" import SessionRenameDialog from "./session-rename-dialog" import { keyboardRegistry } from "../lib/keyboard-registry" @@ -14,6 +14,7 @@ import { ensureSessionParentExpanded, getVisibleSessionIds, isSessionParentExpanded, + loadMessages, loading, renameSession, sessions as sessionStateSessions, @@ -53,6 +54,7 @@ const SessionList: Component = (props) => { const normalizedQuery = createMemo(() => (props.enableFilterBar ? filterQuery().trim().toLowerCase() : "")) const [selectedSessionIds, setSelectedSessionIds] = createSignal>(new Set()) + const [reloadingSessionIds, setReloadingSessionIds] = createSignal>(new Set()) const normalizeSessionLabel = (sessionId: string) => { const session = sessionStateSessions().get(props.instanceId)?.get(sessionId) @@ -213,6 +215,32 @@ const SessionList: Component = (props) => { setRenameTarget({ id: sessionId, title: session.title ?? "", label }) } + const isSessionReloading = (sessionId: string) => reloadingSessionIds().has(sessionId) + + const handleReloadSession = async (event: MouseEvent, sessionId: string) => { + event.stopPropagation() + if (isSessionReloading(sessionId)) return + + setReloadingSessionIds((prev) => { + const next = new Set(prev) + next.add(sessionId) + return next + }) + + try { + await loadMessages(props.instanceId, sessionId, true) + } catch (error) { + log.error(`Failed to reload session ${sessionId}:`, error) + showToastNotification({ message: t("sessionList.reload.error"), variant: "error" }) + } finally { + setReloadingSessionIds((prev) => { + const next = new Set(prev) + next.delete(sessionId) + return next + }) + } + } + const closeRenameDialog = () => { setRenameTarget(null) } @@ -493,6 +521,21 @@ const SessionList: Component = (props) => { > + handleReloadSession(event, rowProps.sessionId)} + role="button" + tabIndex={0} + aria-label={t("sessionList.actions.reload.ariaLabel")} + title={t("sessionList.actions.reload.title")} + > + } + > + + + { diff --git a/packages/ui/src/lib/i18n/messages/en/session.ts b/packages/ui/src/lib/i18n/messages/en/session.ts index d5db91b0..63874bf7 100644 --- a/packages/ui/src/lib/i18n/messages/en/session.ts +++ b/packages/ui/src/lib/i18n/messages/en/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "New session", "sessionList.actions.copyId.ariaLabel": "Copy session ID", "sessionList.actions.copyId.title": "Copy session ID", + "sessionList.actions.reload.ariaLabel": "Reload session", + "sessionList.actions.reload.title": "Reload session", "sessionList.actions.rename.ariaLabel": "Rename session", "sessionList.actions.rename.title": "Rename session", "sessionList.actions.delete.ariaLabel": "Delete session", "sessionList.actions.delete.title": "Delete session", "sessionList.copyId.success": "Session ID copied", "sessionList.copyId.error": "Unable to copy session ID", + "sessionList.reload.error": "Unable to reload session", "sessionList.delete.error": "Unable to delete session", "sessionList.delete.title": "Delete session", "sessionList.delete.confirmMessage": "Delete \"{label}\"? This cannot be undone.", diff --git a/packages/ui/src/lib/i18n/messages/es/session.ts b/packages/ui/src/lib/i18n/messages/es/session.ts index 313bcadb..53f918aa 100644 --- a/packages/ui/src/lib/i18n/messages/es/session.ts +++ b/packages/ui/src/lib/i18n/messages/es/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "Nueva sesión", "sessionList.actions.copyId.ariaLabel": "Copiar ID de sesión", "sessionList.actions.copyId.title": "Copiar ID de sesión", + "sessionList.actions.reload.ariaLabel": "Recargar sesión", + "sessionList.actions.reload.title": "Recargar sesión", "sessionList.actions.rename.ariaLabel": "Renombrar sesión", "sessionList.actions.rename.title": "Renombrar sesión", "sessionList.actions.delete.ariaLabel": "Eliminar sesión", "sessionList.actions.delete.title": "Eliminar sesión", "sessionList.copyId.success": "ID de sesión copiado", "sessionList.copyId.error": "No se pudo copiar el ID de sesión", + "sessionList.reload.error": "No se pudo recargar la sesión", "sessionList.delete.error": "No se pudo eliminar la sesión", "sessionList.delete.title": "Eliminar sesión", "sessionList.delete.confirmMessage": "¿Eliminar \"{label}\"? Esto no se puede deshacer.", diff --git a/packages/ui/src/lib/i18n/messages/fr/session.ts b/packages/ui/src/lib/i18n/messages/fr/session.ts index 96c13c30..72e24c9a 100644 --- a/packages/ui/src/lib/i18n/messages/fr/session.ts +++ b/packages/ui/src/lib/i18n/messages/fr/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "Nouvelle session", "sessionList.actions.copyId.ariaLabel": "Copier l'ID de session", "sessionList.actions.copyId.title": "Copier l'ID de session", + "sessionList.actions.reload.ariaLabel": "Recharger la session", + "sessionList.actions.reload.title": "Recharger la session", "sessionList.actions.rename.ariaLabel": "Renommer la session", "sessionList.actions.rename.title": "Renommer la session", "sessionList.actions.delete.ariaLabel": "Supprimer la session", "sessionList.actions.delete.title": "Supprimer la session", "sessionList.copyId.success": "ID de session copié", "sessionList.copyId.error": "Impossible de copier l'ID de session", + "sessionList.reload.error": "Impossible de recharger la session", "sessionList.delete.error": "Impossible de supprimer la session", "sessionList.delete.title": "Supprimer la session", "sessionList.delete.confirmMessage": "Supprimer \"{label}\" ? Cette action est irréversible.", diff --git a/packages/ui/src/lib/i18n/messages/he/session.ts b/packages/ui/src/lib/i18n/messages/he/session.ts index 6ff5035a..ae104cfa 100644 --- a/packages/ui/src/lib/i18n/messages/he/session.ts +++ b/packages/ui/src/lib/i18n/messages/he/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "סשן חדש", "sessionList.actions.copyId.ariaLabel": "העתק מזהה סשן", "sessionList.actions.copyId.title": "העתק מזהה סשן", + "sessionList.actions.reload.ariaLabel": "טען מחדש סשן", + "sessionList.actions.reload.title": "טען מחדש סשן", "sessionList.actions.rename.ariaLabel": "שנה שם סשן", "sessionList.actions.rename.title": "שנה שם סשן", "sessionList.actions.delete.ariaLabel": "מחק סשן", "sessionList.actions.delete.title": "מחק סשן", "sessionList.copyId.success": "מזהה סשן הועתק", "sessionList.copyId.error": "לא ניתן להעתיק מזהה סשן", + "sessionList.reload.error": "לא ניתן לטעון מחדש את הסשן", "sessionList.delete.error": "לא ניתן למחוק סשן", "sessionList.delete.title": "מחק סשן", "sessionList.delete.confirmMessage": "למחוק את \"{label}\"? לא ניתן לבטל פעולה זו.", diff --git a/packages/ui/src/lib/i18n/messages/ja/session.ts b/packages/ui/src/lib/i18n/messages/ja/session.ts index c7e33291..c8d72f92 100644 --- a/packages/ui/src/lib/i18n/messages/ja/session.ts +++ b/packages/ui/src/lib/i18n/messages/ja/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "新しいセッション", "sessionList.actions.copyId.ariaLabel": "セッション ID をコピー", "sessionList.actions.copyId.title": "セッション ID をコピー", + "sessionList.actions.reload.ariaLabel": "セッションを再読み込み", + "sessionList.actions.reload.title": "セッションを再読み込み", "sessionList.actions.rename.ariaLabel": "セッション名を変更", "sessionList.actions.rename.title": "セッション名を変更", "sessionList.actions.delete.ariaLabel": "セッションを削除", "sessionList.actions.delete.title": "セッションを削除", "sessionList.copyId.success": "セッション ID をコピーしました", "sessionList.copyId.error": "セッション ID をコピーできません", + "sessionList.reload.error": "セッションを再読み込みできません", "sessionList.delete.error": "セッションを削除できません", "sessionList.delete.title": "セッションを削除", "sessionList.delete.confirmMessage": "\"{label}\" を削除しますか?この操作は元に戻せません。", diff --git a/packages/ui/src/lib/i18n/messages/ru/session.ts b/packages/ui/src/lib/i18n/messages/ru/session.ts index 5a17fd7e..bf36bdeb 100644 --- a/packages/ui/src/lib/i18n/messages/ru/session.ts +++ b/packages/ui/src/lib/i18n/messages/ru/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "Новая сессия", "sessionList.actions.copyId.ariaLabel": "Скопировать ID сессии", "sessionList.actions.copyId.title": "Скопировать ID сессии", + "sessionList.actions.reload.ariaLabel": "Обновить сессию", + "sessionList.actions.reload.title": "Обновить сессию", "sessionList.actions.rename.ariaLabel": "Переименовать сессию", "sessionList.actions.rename.title": "Переименовать сессию", "sessionList.actions.delete.ariaLabel": "Удалить сессию", "sessionList.actions.delete.title": "Удалить сессию", "sessionList.copyId.success": "ID сессии скопирован", "sessionList.copyId.error": "Не удалось скопировать ID сессии", + "sessionList.reload.error": "Не удалось обновить сессию", "sessionList.delete.error": "Не удалось удалить сессию", "sessionList.delete.title": "Удалить сессию", "sessionList.delete.confirmMessage": "Удалить \"{label}\"? Это действие нельзя отменить.", diff --git a/packages/ui/src/lib/i18n/messages/zh-Hans/session.ts b/packages/ui/src/lib/i18n/messages/zh-Hans/session.ts index d58554e1..1aa5fcb6 100644 --- a/packages/ui/src/lib/i18n/messages/zh-Hans/session.ts +++ b/packages/ui/src/lib/i18n/messages/zh-Hans/session.ts @@ -25,12 +25,15 @@ export const sessionMessages = { "sessionList.actions.newSession.title": "新建会话", "sessionList.actions.copyId.ariaLabel": "复制会话 ID", "sessionList.actions.copyId.title": "复制会话 ID", + "sessionList.actions.reload.ariaLabel": "重新加载会话", + "sessionList.actions.reload.title": "重新加载会话", "sessionList.actions.rename.ariaLabel": "重命名会话", "sessionList.actions.rename.title": "重命名会话", "sessionList.actions.delete.ariaLabel": "删除会话", "sessionList.actions.delete.title": "删除会话", "sessionList.copyId.success": "已复制会话 ID", "sessionList.copyId.error": "无法复制会话 ID", + "sessionList.reload.error": "无法重新加载会话", "sessionList.delete.error": "无法删除会话", "sessionList.delete.title": "删除会话", "sessionList.delete.confirmMessage": "删除“{label}”?此操作无法撤销。",