fix: center chat deletion dialog (#22)

* fix: center chat deletion dialog

* fix: clarify archived chat state
This commit is contained in:
732642856
2026-07-21 13:32:25 +08:00
committed by GitHub
parent 5db48e16b3
commit 5b8804d65d
3 changed files with 35 additions and 15 deletions
+5 -3
View File
@@ -707,6 +707,8 @@ input:disabled, select:disabled { color: var(--color-ink-tertiary); background:
.auth-panel h1 { font-size: var(--type-display-sm); }
.admin-section { padding: var(--space-5); }
}
.session-delete-confirmation { position: fixed; inset: auto var(--space-5) var(--space-5) auto; z-index: 100; width: min(360px, calc(100vw - var(--space-10))); padding: var(--space-5); border: 1px solid var(--border); border-radius: 8px; background: var(--background); box-shadow: 0 12px 32px rgb(0 0 0 / 18%); }
.session-delete-confirmation p { margin: 0 0 var(--space-4); }
.session-delete-confirmation div { display: flex; justify-content: flex-end; gap: var(--space-3); }
.session-delete-overlay { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: var(--space-5); background: rgb(0 0 0 / 32%); }
.session-delete-confirmation { width: min(420px, 100%); padding: var(--space-6); border: 1px solid var(--border); border-radius: 8px; background: var(--background); box-shadow: 0 20px 56px rgb(0 0 0 / 24%); }
.session-delete-confirmation h2 { margin: 0 0 var(--space-3); font-size: var(--type-title-lg); }
.session-delete-confirmation p { margin: 0; color: var(--muted-foreground); }
.session-delete-actions { display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: var(--space-6); }
+19 -12
View File
@@ -1268,8 +1268,12 @@ export default function Home() {
}
function toggleArchivedSession(sessionId: string) {
setArchivedSessionIds((current) => current.includes(sessionId) ? current.filter((id) => id !== sessionId) : [sessionId, ...current]);
if (activeSessionId === sessionId) setActiveSessionId(visibleSessions.find((session) => session.id !== sessionId)?.id ?? "");
const restoring = archivedSessionIds.includes(sessionId);
setArchivedSessionIds((current) => restoring ? current.filter((id) => id !== sessionId) : [sessionId, ...current]);
if (!restoring && activeSessionId === sessionId) {
setActiveSessionId(visibleSessions.find((session) => session.id !== sessionId)?.id ?? "");
}
setComposerNotice(restoring ? "已恢复到聊天记录。" : "已归档,可在左侧归档中恢复。");
}
async function shareSession(session: ChatSession) {
@@ -2320,16 +2324,19 @@ export default function Home() {
onOpenLogout={() => openAccountDialog("logout")}
/>
{pendingSessionDeletion ? (
<div className="session-delete-confirmation" role="alertdialog" aria-modal="true" aria-label="确认删除聊天记录">
<p>{pendingSessionDeletion.title}</p>
<div>
<button type="button" onClick={() => setPendingSessionDeletion(null)}></button>
<button className="danger-button" type="button" onClick={() => {
const session = pendingSessionDeletion;
setPendingSessionDeletion(null);
void deleteSession(session);
}}></button>
</div>
<div className="session-delete-overlay" role="presentation" onMouseDown={() => setPendingSessionDeletion(null)}>
<section className="session-delete-confirmation" role="alertdialog" aria-modal="true" aria-label="确认删除聊天记录" onMouseDown={(event) => event.stopPropagation()}>
<h2></h2>
<p>{pendingSessionDeletion.title}</p>
<div className="session-delete-actions">
<button type="button" onClick={() => setPendingSessionDeletion(null)}></button>
<button className="danger-button" type="button" onClick={() => {
const session = pendingSessionDeletion;
setPendingSessionDeletion(null);
void deleteSession(session);
}}></button>
</div>
</section>
</div>
) : null}
<SidebarInset className="chat-panel" inert={activeAccountDialog !== null}>
@@ -15,9 +15,11 @@ def test_chat_history_management_actions_are_exposed() -> None:
"deleteSession",
"pendingSessionDeletion",
"确认删除",
"session-delete-overlay",
"togglePinnedSession",
"toggleArchivedSession",
"showArchivedSessions",
"已归档,可在左侧归档中恢复。",
"shareSession",
"share_payload_version",
"messages.map",
@@ -47,3 +49,12 @@ def test_chat_session_delete_is_server_controlled_and_granted() -> None:
assert 'grant delete on table public.chat_sessions to authenticated' in migration.lower()
assert 'create policy chat_sessions_delete_own' in migration.lower()
assert 'using ((select auth.uid()) = user_id)' in migration.lower()
def test_archiving_never_calls_the_delete_endpoint() -> None:
source = PAGE.read_text(encoding="utf-8")
start = source.index("function toggleArchivedSession")
end = source.index("async function shareSession", start)
archive_action = source[start:end]
assert "setArchivedSessionIds" in archive_action
assert "/api/sessions/" not in archive_action