feat(ui): add session reload action
Let users refresh a session transcript from the sidebar without reopening it. Reuse the existing forced message loading path so the reload behavior stays aligned with normal session hydration.
This commit is contained in:
@@ -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<SessionListProps> = (props) => {
|
||||
const normalizedQuery = createMemo(() => (props.enableFilterBar ? filterQuery().trim().toLowerCase() : ""))
|
||||
|
||||
const [selectedSessionIds, setSelectedSessionIds] = createSignal<Set<string>>(new Set())
|
||||
const [reloadingSessionIds, setReloadingSessionIds] = createSignal<Set<string>>(new Set())
|
||||
|
||||
const normalizeSessionLabel = (sessionId: string) => {
|
||||
const session = sessionStateSessions().get(props.instanceId)?.get(sessionId)
|
||||
@@ -213,6 +215,32 @@ const SessionList: Component<SessionListProps> = (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<SessionListProps> = (props) => {
|
||||
>
|
||||
<Copy class="w-3 h-3" />
|
||||
</span>
|
||||
<span
|
||||
class={`session-item-close opacity-80 hover:opacity-100 ${isActive() ? "hover:bg-white/20" : "hover:bg-surface-hover"}`}
|
||||
onClick={(event) => handleReloadSession(event, rowProps.sessionId)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={t("sessionList.actions.reload.ariaLabel")}
|
||||
title={t("sessionList.actions.reload.title")}
|
||||
>
|
||||
<Show
|
||||
when={!isSessionReloading(rowProps.sessionId)}
|
||||
fallback={<RotateCw class="w-3 h-3 animate-spin" />}
|
||||
>
|
||||
<RotateCw class="w-3 h-3" />
|
||||
</Show>
|
||||
</span>
|
||||
<span
|
||||
class={`session-item-close opacity-80 hover:opacity-100 ${isActive() ? "hover:bg-white/20" : "hover:bg-surface-hover"}`}
|
||||
onClick={(event) => {
|
||||
|
||||
Reference in New Issue
Block a user