mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-25 05:52:22 +02:00
[eric] dashboard: don't wipe layout mid-drag + never route to a phantom (deleted) dashboard id (dragging cards was silently broken by a spurious layout reset)
This commit is contained in:
@@ -255,7 +255,9 @@ const AppShell: React.FC = () => {
|
||||
dispatch(setPendingBrowserUrl(url));
|
||||
const lastId = (window as any).__openswarm_last_dashboard_id as string | undefined;
|
||||
const firstDashboard = dashboardList[0];
|
||||
const targetId = lastId || firstDashboard?.id;
|
||||
// Only navigate to lastId if it's a REAL dashboard: a stale localStorage id for a deleted dashboard used to route to /dashboard/<phantom>, which 404s and re-fires the layout wipe (drops your cards / breaks a drag).
|
||||
const lastIsReal = !!lastId && dashboardList.some((d) => d.id === lastId);
|
||||
const targetId = (lastIsReal ? lastId : undefined) || firstDashboard?.id;
|
||||
if (targetId) {
|
||||
navigate(`/dashboard/${targetId}`);
|
||||
} else {
|
||||
|
||||
@@ -113,13 +113,16 @@ export function useDashboardLifecycle({
|
||||
|
||||
useEffect(() => {
|
||||
if (!dashboardId) return;
|
||||
hasFittedRef.current = false;
|
||||
restoredExpandedRef.current = false;
|
||||
setOutputsRefetched(false);
|
||||
dispatch(resetLayout({ keepBrowserIds: getKeepAliveBrowserIds() }));
|
||||
// CRITICAL path: these populate the cards the user expects to see on first paint. Don't defer.
|
||||
dispatch(fetchSessions({ dashboardId }));
|
||||
dispatch(fetchLayout({ dashboardId }));
|
||||
// Never wipe+reload the layout while a card drag or marquee is in flight: a spurious mid-gesture nav (e.g. a phantom-dashboard round-trip) would unmount the card under the cursor and the drag silently dies. You can't switch dashboards while holding a drag, so any reset firing now is spurious. The shield class is up for exactly that window. Handlers below still install.
|
||||
if (!document.body.classList.contains('dashboard-marquee-active')) {
|
||||
hasFittedRef.current = false;
|
||||
restoredExpandedRef.current = false;
|
||||
setOutputsRefetched(false);
|
||||
dispatch(resetLayout({ keepBrowserIds: getKeepAliveBrowserIds() }));
|
||||
// CRITICAL path: these populate the cards the user expects to see on first paint. Don't defer.
|
||||
dispatch(fetchSessions({ dashboardId }));
|
||||
dispatch(fetchLayout({ dashboardId }));
|
||||
}
|
||||
const cleanupBrowserHandler = initBrowserCommandHandler();
|
||||
// Global broadcasts (spawned browser cards) skip the replay log, so a socket gap loses them; a reconnect refetch is the only way they return.
|
||||
const unsubReconnect = dashboardWs.on('dashboard:reconnected', () => {
|
||||
|
||||
Reference in New Issue
Block a user