fix: session deletion persistence and action button overlap
- Fix blacklist reconciliation logic that was removing blacklisted keys for sessions still on the gateway (inverted filter condition) - Move message action buttons (copy, bookmark, metadata, retry) above the message bubble (-top-3) to prevent overlapping text content Closes #73, #74
This commit is contained in:
12
FEEDBACK.md
12
FEEDBACK.md
@@ -788,3 +788,15 @@
|
||||
- **Completed:** 2026-02-14 — commit `70d29dc`, tagged `v1.47.0`
|
||||
- **Source:** Josh (Bardak)
|
||||
- **Description:** After OpenClaw compaction, all previous messages disappear from the chat UI. This is a bad UX — the user loses their message history visually even though the conversation continues. Ideally PinchChat should keep a local cache/history of previous messages (IndexedDB or localStorage) so the user can still scroll back and see/copy-paste old messages even after compaction. The compaction boundary could be shown with a visual separator ("— context compacted —") but old messages should remain visible above it. This is critical for usability — users need to be able to reference what they said earlier.
|
||||
|
||||
## Item #73
|
||||
- **Date:** 2026-02-14
|
||||
- **Priority:** medium
|
||||
- **Status:** open
|
||||
- **Description:** Message action buttons (copy, view source, etc.) are misaligned when hovering over message text. The buttons overlay/overlap the text content incorrectly. They should be properly positioned outside the text area or in a consistent location that doesn't interfere with reading. (Feedback from Bardak, screenshot: https://i.imgur.com/O9CwAix.png)
|
||||
|
||||
## Item #74
|
||||
- **Date:** 2026-02-14
|
||||
- **Priority:** high
|
||||
- **Status:** open
|
||||
- **Description:** Session deletion doesn't persist — when deleting a session from the sidebar, it disappears visually but comes back on page reload. The deletion is only client-side/cosmetic and doesn't actually delete the session from the OpenClaw backend. Need to call the proper API endpoint to actually delete/archive the session server-side. (Feedback from Bardak)
|
||||
|
||||
@@ -281,7 +281,7 @@ function CopyButton({ text }: { text: string }) {
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="absolute top-2 right-2 h-7 w-7 rounded-lg border border-pc-border bg-pc-elevated/80 backdrop-blur-sm flex items-center justify-center text-pc-text-secondary hover:text-pc-accent-light hover:border-[var(--pc-accent-dim)] transition-all opacity-0 group-hover:opacity-100"
|
||||
className="absolute -top-3 right-2 h-7 w-7 rounded-lg border border-pc-border bg-pc-elevated/80 backdrop-blur-sm flex items-center justify-center text-pc-text-secondary hover:text-pc-accent-light hover:border-[var(--pc-accent-dim)] transition-all opacity-0 group-hover:opacity-100"
|
||||
title={copied ? t('message.copied') : t('message.copy')}
|
||||
aria-label={t('message.copy')}
|
||||
>
|
||||
@@ -490,7 +490,7 @@ export const ChatMessageComponent = memo(function ChatMessageComponent({ message
|
||||
{!isUser && !message.isStreaming && getPlainText(message).trim() && (
|
||||
<CopyButton text={getPlainText(message)} />
|
||||
)}
|
||||
<div className={`absolute top-2 ${isUser ? 'left-2' : 'right-10'} flex gap-1 opacity-0 group-hover:opacity-100 transition-all z-10`}>
|
||||
<div className={`absolute -top-3 ${isUser ? 'left-2' : 'right-10'} flex gap-1 opacity-0 group-hover:opacity-100 transition-all z-10`}>
|
||||
{onToggleBookmark && (
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); onToggleBookmark(); }}
|
||||
@@ -508,7 +508,7 @@ export const ChatMessageComponent = memo(function ChatMessageComponent({ message
|
||||
{isUser && onRetry && (
|
||||
<button
|
||||
onClick={() => onRetry(getPlainText(message))}
|
||||
className={`absolute top-2 right-2 h-7 w-7 rounded-lg border border-pc-border bg-pc-elevated/80 backdrop-blur-sm flex items-center justify-center text-pc-text-secondary hover:text-pc-accent-light hover:border-[var(--pc-accent-dim)] transition-all ${message.sendStatus === 'error' ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}`}
|
||||
className={`absolute -top-3 right-2 h-7 w-7 rounded-lg border border-pc-border bg-pc-elevated/80 backdrop-blur-sm flex items-center justify-center text-pc-text-secondary hover:text-pc-accent-light hover:border-[var(--pc-accent-dim)] transition-all ${message.sendStatus === 'error' ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}`}
|
||||
title={t('message.retry')}
|
||||
aria-label={t('message.retry')}
|
||||
>
|
||||
|
||||
@@ -130,14 +130,14 @@ export function useGateway() {
|
||||
const sessionList = res?.sessions as Array<Record<string, unknown>> | undefined;
|
||||
if (sessionList) {
|
||||
const deleted = getDeletedSessions();
|
||||
// Reconcile: remove blacklisted keys that still exist on the gateway
|
||||
// (e.g. permanent sessions like agent:main:main that can't actually be deleted)
|
||||
// Reconcile: remove blacklisted keys for sessions that no longer exist on the gateway
|
||||
// (they were successfully deleted, so no need to keep hiding them)
|
||||
const activeKeys = new Set(sessionList.map((s) => (s.key || s.sessionKey) as string));
|
||||
const reconciled = new Set([...deleted].filter((k) => !activeKeys.has(k)));
|
||||
const reconciled = new Set([...deleted].filter((k) => activeKeys.has(k)));
|
||||
if (reconciled.size !== deleted.size) {
|
||||
localStorage.setItem('pinchchat-deleted-sessions', JSON.stringify([...reconciled]));
|
||||
}
|
||||
setSessions(sessionList.filter((s) => !reconciled.has((s.key || s.sessionKey) as string)).map((s) => ({
|
||||
setSessions(sessionList.filter((s) => !deleted.has((s.key || s.sessionKey) as string)).map((s) => ({
|
||||
key: (s.key || s.sessionKey) as string,
|
||||
label: (s.label || s.key || s.sessionKey) as string,
|
||||
messageCount: s.messageCount as number | undefined,
|
||||
|
||||
Reference in New Issue
Block a user