diff --git a/apps/x/apps/renderer/src/App.tsx b/apps/x/apps/renderer/src/App.tsx index 305599cd..d66ce23b 100644 --- a/apps/x/apps/renderer/src/App.tsx +++ b/apps/x/apps/renderer/src/App.tsx @@ -4567,12 +4567,14 @@ function App() { const pendingCalendarEventRef = useRef(undefined) const [meetingSummarizing, setMeetingSummarizing] = useState(false) const [showMeetingPermissions, setShowMeetingPermissions] = useState(false) + const [recordingMeetingSource, setRecordingMeetingSource] = useState(null) const [checkingPermission, setCheckingPermission] = useState(false) const startMeetingNow = useCallback(async () => { const calEvent = pendingCalendarEventRef.current pendingCalendarEventRef.current = undefined + setRecordingMeetingSource(calEvent?.source ?? null) const notePath = await meetingTranscription.start(calEvent) if (notePath) { meetingNotePathRef.current = notePath @@ -4600,6 +4602,7 @@ function App() { const handleToggleMeeting = useCallback(async () => { if (meetingTranscription.state === 'recording') { await meetingTranscription.stop() + setRecordingMeetingSource(null) // Read the final transcript and generate meeting notes via LLM const notePath = meetingNotePathRef.current @@ -5119,6 +5122,9 @@ function App() { isSuggestedTopicsOpen={isSuggestedTopicsOpen} onOpenSuggestedTopics={() => void navigateToView({ type: 'suggested-topics' })} onOpenMeetings={openMeetingsView} + meetingRecordingState={meetingTranscription.state} + recordingMeetingSource={recordingMeetingSource} + onToggleMeetingRecording={() => { void handleToggleMeeting() }} onOpenBgTasks={() => { setBgTaskInitialSlug(null); setBgTaskSlugVersion((v) => v + 1); openBgTasksView() }} isEmailOpen={isEmailOpen} onOpenEmail={openEmailView} diff --git a/apps/x/apps/renderer/src/components/sidebar-content.tsx b/apps/x/apps/renderer/src/components/sidebar-content.tsx index 63adf25c..c2b45dd1 100644 --- a/apps/x/apps/renderer/src/components/sidebar-content.tsx +++ b/apps/x/apps/renderer/src/components/sidebar-content.tsx @@ -196,6 +196,9 @@ type SidebarContentPanelProps = { isSuggestedTopicsOpen?: boolean onOpenSuggestedTopics?: () => void onOpenMeetings?: () => void + meetingRecordingState?: 'idle' | 'connecting' | 'recording' | 'stopping' + recordingMeetingSource?: string | null + onToggleMeetingRecording?: () => void onOpenBgTasks?: () => void isEmailOpen?: boolean onOpenEmail?: () => void @@ -443,6 +446,9 @@ export function SidebarContentPanel({ isSuggestedTopicsOpen = false, onOpenSuggestedTopics, onOpenMeetings, + meetingRecordingState, + recordingMeetingSource, + onToggleMeetingRecording, onOpenBgTasks, isEmailOpen = false, onOpenEmail, @@ -542,7 +548,12 @@ export function SidebarContentPanel({ - + void + recordingState: 'idle' | 'connecting' | 'recording' | 'stopping' + recordingSource: string | null + onToggleRecording?: () => void }) { const [meetings, setMeetings] = useState([]) @@ -1268,53 +1285,86 @@ function MeetingsSidebarSection({ {meetings.map((m) => { const hasConference = Boolean(m.conferenceLink) + const isThisRecording = recordingSource === m.source && (recordingState === 'recording' || recordingState === 'connecting' || recordingState === 'stopping') + const isBusy = isThisRecording && (recordingState === 'connecting' || recordingState === 'stopping') return ( {m.summary} - - {formatMeetingTime(m)} + + {isThisRecording ? null : formatMeetingTime(m)} -
- - - - - Take notes - - {hasConference && ( + {isThisRecording ? ( +
+ + + + + + + {recordingState === 'connecting' ? 'Starting…' : recordingState === 'stopping' ? 'Stopping…' : 'Stop recording'} + + +
+ ) : ( +
+ + + - Join & take notes + Take notes - )} -
+ {hasConference && ( + + + + + Join & take notes + + )} +
+ )}
) })}