Meeting notes2 (#454)

Improve meeting transcription: screen recording permissions, collapsible transcript block
This commit is contained in:
arkml 2026-03-30 22:31:49 +05:30 committed by GitHub
parent 30e1785fe2
commit 86cc2aaf73
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 885 additions and 116 deletions

View file

@ -11,6 +11,9 @@ module.exports = {
icon: './icons/icon', // .icns extension added automatically
appBundleId: 'com.rowboat.app',
appCategoryType: 'public.app-category.productivity',
extendInfo: {
NSAudioCaptureUsageDescription: 'Rowboat needs access to system audio to transcribe meetings from other apps (Zoom, Meet, etc.)',
},
osxSign: {
batchCodesignCalls: true,
optionsForFile: () => ({

View file

@ -1,4 +1,4 @@
import { ipcMain, BrowserWindow, shell, dialog } from 'electron';
import { ipcMain, BrowserWindow, shell, dialog, systemPreferences, desktopCapturer } from 'electron';
import { ipc } from '@x/shared';
import path from 'node:path';
import os from 'node:os';
@ -719,6 +719,24 @@ export function setupIpcHandlers() {
return { success: false, error: 'Unknown format' };
},
'meeting:checkScreenPermission': async () => {
if (process.platform !== 'darwin') return { granted: true };
const status = systemPreferences.getMediaAccessStatus('screen');
console.log('[meeting] Screen recording permission status:', status);
if (status === 'granted') return { granted: true };
// Not granted — call desktopCapturer.getSources() to register the app
// in the macOS Screen Recording list. On first call this shows the
// native permission prompt (signed apps are remembered across restarts).
try { await desktopCapturer.getSources({ types: ['screen'] }); } catch { /* ignore */ }
// Re-check after the native prompt was dismissed
const statusAfter = systemPreferences.getMediaAccessStatus('screen');
console.log('[meeting] Screen recording permission status after prompt:', statusAfter);
return { granted: statusAfter === 'granted' };
},
'meeting:openScreenRecordingSettings': async () => {
await shell.openExternal('x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture');
return { success: true };
},
'meeting:summarize': async (_event, args) => {
const notes = await summarizeMeeting(args.transcript, args.meetingStartTime, args.calendarEventJson);
return { notes };