From 229a49bfdc2567d1240bdc86738b94910e0e0f0e Mon Sep 17 00:00:00 2001 From: Zane <75694352+zanesq@users.noreply.github.com> Date: Wed, 23 Jul 2025 12:52:37 -0700 Subject: [PATCH] fix: loading shared sessions (#3607) --- ui/desktop/src/App.tsx | 62 +++++------- .../components/sessions/SharedSessionView.tsx | 94 +++++++++++-------- 2 files changed, 79 insertions(+), 77 deletions(-) diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 8d178487..5b239a3b 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -535,17 +535,18 @@ const SharedSessionRouteWrapper = ({ const location = useLocation(); const navigate = useNavigate(); - const sessionDetails = location.state?.sessionDetails as SharedSessionDetails | null; - const error = location.state?.error || sharedSessionError; - const shareToken = location.state?.shareToken; - const baseUrl = location.state?.baseUrl; + const historyState = window.history.state; + const sessionDetails = (location.state?.sessionDetails || + historyState?.sessionDetails) as SharedSessionDetails | null; + const error = location.state?.error || historyState?.error || sharedSessionError; + const shareToken = location.state?.shareToken || historyState?.shareToken; + const baseUrl = location.state?.baseUrl || historyState?.baseUrl; return ( navigate('/sessions')} onRetry={async () => { if (shareToken && baseUrl) { setIsLoadingSharedSession(true); @@ -1024,51 +1025,32 @@ export default function App() { const handleOpenSharedSession = async (_event: IpcRendererEvent, ...args: unknown[]) => { const link = args[0] as string; window.electron.logInfo(`Opening shared session from deep link ${link}`); - setIsLoadingSession(true); + setIsLoadingSharedSession(true); setSharedSessionError(null); try { await openSharedSessionFromDeepLink( link, - (view: View, _options?: SessionLinksViewOptions) => { - // Convert view to route navigation - switch (view) { - case 'chat': - window.history.replaceState({}, '', '/'); - break; - case 'settings': - window.history.replaceState({}, '', '/settings'); - break; - case 'sessions': - window.history.replaceState({}, '', '/sessions'); - break; - case 'schedules': - window.history.replaceState({}, '', '/schedules'); - break; - case 'recipes': - window.history.replaceState({}, '', '/recipes'); - break; - case 'permission': - window.history.replaceState({}, '', '/permission'); - break; - case 'ConfigureProviders': - window.history.replaceState({}, '', '/configure-providers'); - break; - case 'sharedSession': - window.history.replaceState({}, '', '/shared-session'); - break; - case 'recipeEditor': - window.history.replaceState({}, '', '/recipe-editor'); - break; - default: - window.history.replaceState({}, '', '/'); + (_view: View, _options?: SessionLinksViewOptions) => { + // Navigate to shared session view with the session data + window.location.hash = '#/shared-session'; + if (_options) { + window.history.replaceState(_options, '', '#/shared-session'); } } ); } catch (error) { console.error('Unexpected error opening shared session:', error); - window.history.replaceState({}, '', '/sessions'); + // Navigate to shared session view with error + window.location.hash = '#/shared-session'; + const shareToken = link.replace('goose://sessions/', ''); + const options = { + sessionDetails: null, + error: error instanceof Error ? error.message : 'Unknown error', + shareToken, + }; + window.history.replaceState(options, '', '#/shared-session'); } finally { - setIsLoadingSession(false); + setIsLoadingSharedSession(false); } }; window.electron.on('open-shared-session', handleOpenSharedSession); diff --git a/ui/desktop/src/components/sessions/SharedSessionView.tsx b/ui/desktop/src/components/sessions/SharedSessionView.tsx index 2225880a..1f39d5cd 100644 --- a/ui/desktop/src/components/sessions/SharedSessionView.tsx +++ b/ui/desktop/src/components/sessions/SharedSessionView.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { Calendar, MessageSquareText, Folder, Target } from 'lucide-react'; +import { Calendar, MessageSquareText, Folder, Target, LoaderCircle, Share2 } from 'lucide-react'; import { type SharedSessionDetails } from '../../sharedSessions'; -import { SessionHeaderCard, SessionMessages } from './SessionViewComponents'; +import { SessionMessages } from './SessionViewComponents'; import { formatMessageTimestamp } from '../../utils/timeUtils'; import { MainPanelLayout } from '../Layout/MainPanelLayout'; @@ -9,53 +9,73 @@ interface SharedSessionViewProps { session: SharedSessionDetails | null; isLoading: boolean; error: string | null; - onBack: () => void; onRetry: () => void; } +// Custom SessionHeader component matching SessionHistoryView style +const SessionHeader: React.FC<{ + children: React.ReactNode; + title: string; +}> = ({ children, title }) => { + return ( +
+

{title}

+
{children}
+
+ ); +}; + const SharedSessionView: React.FC = ({ session, isLoading, error, - onBack, onRetry, }) => { return ( -
-
- - {/* Top Row - back, info (fixed) */} - - {/* Session info row */} -
-

- {session ? session.description : 'Shared Session'} -

-
- - - {session ? formatMessageTimestamp(session.messages[0]?.created) : 'Unknown'} - - - - {session ? session.message_count : 0} - - {session && session.total_tokens !== null && ( - - - {session.total_tokens.toLocaleString()} - - )} -
-
- - - {session ? session.working_dir : 'Unknown'} - -
+
+
+
+ + Shared Session
- +
+ + +
+ {!isLoading && session && session.messages.length > 0 ? ( + <> +
+ + + {formatMessageTimestamp(session.messages[0]?.created)} + + + + {session.message_count} + + {session.total_tokens !== null && ( + + + {session.total_tokens.toLocaleString()} + + )} +
+
+ + + {session.working_dir} + +
+ + ) : ( +
+ + Loading session details... +
+ )} +
+