From c10db35ebcc2125068b7a49030db13ea380cdb7b Mon Sep 17 00:00:00 2001 From: ciregenz Date: Wed, 29 Jul 2026 20:17:17 -0700 Subject: [PATCH] [eric] history: move chat history from the dock to the top island and make it global (was filtered to the current dashboard) --- .../app/pages/Dashboard/DashboardToolbar.tsx | 8 +++---- .../Dashboard/canvas/DashboardHeader.tsx | 22 +++++++++++++++++++ .../pages/Dashboard/desktop/DesktopDock.tsx | 4 +--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx b/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx index 5f392a20..f8eb1c2d 100644 --- a/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx +++ b/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx @@ -259,9 +259,8 @@ const DashboardToolbar = React.forwardRef( q: historyQuery, limit: HISTORY_PAGE_SIZE, offset: historySearch.results.length, - dashboardId, })); - }, [dispatch, historyQuery, historySearch.loading, historySearch.hasMore, historySearch.results.length, dashboardId]); + }, [dispatch, historyQuery, historySearch.loading, historySearch.hasMore, historySearch.results.length]); const isExpanded = inputOpen || viewPickerOpen || historyOpen; @@ -376,13 +375,14 @@ const DashboardToolbar = React.forwardRef( }; }, [handleOpenViewPicker, handleOpenHistory, onAddBrowser]); + // No dashboardId: chat history is global, so a chat you started on another dashboard is still findable here. useEffect(() => { if (!historyOpen) return; const timer = setTimeout(() => { - dispatch(searchHistory({ q: historyQuery, limit: HISTORY_PAGE_SIZE, offset: 0, dashboardId })); + dispatch(searchHistory({ q: historyQuery, limit: HISTORY_PAGE_SIZE, offset: 0 })); }, 300); return () => clearTimeout(timer); - }, [historyQuery, historyOpen, dispatch, dashboardId]); + }, [historyQuery, historyOpen, dispatch]); useEffect(() => { if (historyOpen && popoverMode === 'runs') { diff --git a/frontend/src/app/pages/Dashboard/canvas/DashboardHeader.tsx b/frontend/src/app/pages/Dashboard/canvas/DashboardHeader.tsx index c11c131e..0df5299d 100644 --- a/frontend/src/app/pages/Dashboard/canvas/DashboardHeader.tsx +++ b/frontend/src/app/pages/Dashboard/canvas/DashboardHeader.tsx @@ -5,6 +5,8 @@ import SmartToyOutlinedIcon from '@mui/icons-material/SmartToyOutlined'; import GridViewRoundedIcon from '@mui/icons-material/GridViewRounded'; import LanguageIcon from '@mui/icons-material/Language'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import HistoryIcon from '@mui/icons-material/History'; +import Tooltip from '@mui/material/Tooltip'; import { useClaudeTokens } from '@/shared/styles/ThemeContext'; import { useAppDispatch } from '@/shared/hooks'; import DashboardGlyph from './DashboardGlyph'; @@ -164,6 +166,26 @@ const DashboardHeader: React.FC = ({ }} /> )} + {/* Chat history lives up here on the island, not in the dock, and it spans every dashboard. */} + + { + e.stopPropagation(); + window.dispatchEvent(new CustomEvent('openswarm:open-history')); + }} + sx={{ + ml: 0.25, + display: 'flex', + alignItems: 'center', + borderRadius: '5px', + p: '2px', + cursor: 'pointer', + '&:hover': { bgcolor: `${c.bg.surface}99` }, + }} + > + + + {dashboardId && ( 0 && ( )} - {/* The og toolbar's actions, dock-resident: browser, workflow, note, history, then settings + apps below their own divider. No New-chat tile; the spawn pill at the bottom is always there. */} + {/* The og toolbar's actions, dock-resident: browser, workflow, note, then settings + apps below their own divider. New-chat lives in the spawn pill, history on the top island. */} {([ { label: 'New browser', icon: , act: onAddBrowser }, { label: 'Workflows', icon: , act: () => dispatch(openWorkflowsApp()) }, { label: 'New note', icon: , act: onAddNote }, - { label: 'History', icon: , act: () => window.dispatchEvent(new CustomEvent('openswarm:open-history')) }, { label: 'Settings', icon: , act: () => dispatch(openSettingsModal(undefined)), divider: true }, { label: 'Applications', icon: , act: onApplications, bg: 'linear-gradient(135deg, #3d3d46, #232329)' }, ] as { label: string; icon: React.ReactNode; act: () => void; divider?: boolean; bg?: string }[]).map((a) => (