@todesktop/plugin-recall 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -0
- package/dist/main.d.ts +23 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +694 -0
- package/dist/main.js.map +1 -0
- package/dist/preload.d.ts +136 -0
- package/dist/preload.d.ts.map +1 -0
- package/dist/preload.js +218 -0
- package/dist/preload.js.map +1 -0
- package/dist/shared.d.ts +139 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +35 -0
- package/dist/shared.js.map +1 -0
- package/dist/store.d.ts +128 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +231 -0
- package/dist/store.js.map +1 -0
- package/package.json +71 -0
- package/src/main.ts +474 -0
- package/src/preload.ts +237 -0
- package/src/shared.ts +204 -0
- package/src/store.ts +266 -0
- package/tsconfig.json +11 -0
package/src/main.ts
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToDesktop Recall Desktop SDK Plugin - Main Process
|
|
3
|
+
*
|
|
4
|
+
* This file runs in Electron's main process and handles:
|
|
5
|
+
* - Recall Desktop SDK integration and lifecycle management
|
|
6
|
+
* - IPC communication with renderer processes
|
|
7
|
+
* - Meeting detection and recording management
|
|
8
|
+
* - Event forwarding from SDK to frontend
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { ipcMain, BrowserWindow } from 'electron';
|
|
12
|
+
import {
|
|
13
|
+
IPC_CHANNELS,
|
|
14
|
+
ApiResponse,
|
|
15
|
+
PluginStatus,
|
|
16
|
+
RecallSdkError,
|
|
17
|
+
StartRecordingRequest,
|
|
18
|
+
StopRecordingRequest,
|
|
19
|
+
PauseRecordingRequest,
|
|
20
|
+
ResumeRecordingRequest,
|
|
21
|
+
UploadRecordingRequest,
|
|
22
|
+
PermissionType,
|
|
23
|
+
SdkInitOptions,
|
|
24
|
+
PrepareDesktopAudioResponse,
|
|
25
|
+
RecallSdkConfig,
|
|
26
|
+
RecallSdkEventType
|
|
27
|
+
} from './shared';
|
|
28
|
+
import { recallSdkStore } from './store';
|
|
29
|
+
|
|
30
|
+
// Import Recall SDK, with a dev-friendly fallback mock if the package isn't installed
|
|
31
|
+
type RecallAiSdk = {
|
|
32
|
+
init(options: any): Promise<null> | void;
|
|
33
|
+
shutdown(): Promise<null> | void;
|
|
34
|
+
startRecording(config: { windowId: string; uploadToken: string }): Promise<null> | void;
|
|
35
|
+
stopRecording(config: { windowId: string }): Promise<null> | void;
|
|
36
|
+
pauseRecording(config: { windowId: string }): Promise<null> | void;
|
|
37
|
+
resumeRecording(config: { windowId: string }): Promise<null> | void;
|
|
38
|
+
uploadRecording(config: { windowId: string }): Promise<null> | void;
|
|
39
|
+
prepareDesktopAudioRecording(): Promise<string>;
|
|
40
|
+
requestPermission(permission: PermissionType): Promise<null> | void;
|
|
41
|
+
addEventListener<T extends RecallSdkEventType>(type: T, callback: (event: any) => void): void;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
let RecallAiSdk: RecallAiSdk;
|
|
45
|
+
try {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
47
|
+
const mod = require('@recallai/desktop-sdk');
|
|
48
|
+
RecallAiSdk = (mod && mod.default) ? mod.default : mod;
|
|
49
|
+
} catch {
|
|
50
|
+
RecallAiSdk = {
|
|
51
|
+
init: async (config: any) => { console.log('RecallAiSdk.init called with:', config); return null; },
|
|
52
|
+
shutdown: async () => { console.log('RecallAiSdk.shutdown called'); return null; },
|
|
53
|
+
startRecording: async (params: any) => { console.log('RecallAiSdk.startRecording called with:', params); return null; },
|
|
54
|
+
stopRecording: async (params: any) => { console.log('RecallAiSdk.stopRecording called with:', params); return null; },
|
|
55
|
+
pauseRecording: async (params: any) => { console.log('RecallAiSdk.pauseRecording called with:', params); return null; },
|
|
56
|
+
resumeRecording: async (params: any) => { console.log('RecallAiSdk.resumeRecording called with:', params); return null; },
|
|
57
|
+
uploadRecording: async (params: any) => { console.log('RecallAiSdk.uploadRecording called with:', params); return null; },
|
|
58
|
+
prepareDesktopAudioRecording: async () => { console.log('RecallAiSdk.prepareDesktopAudioRecording called'); return 'mock-window-id'; },
|
|
59
|
+
requestPermission: async (permission: PermissionType) => { console.log(`RecallAiSdk.requestPermission called for: ${permission}`); return null; },
|
|
60
|
+
addEventListener: (_eventType: string) => { /* no-op in mock */ },
|
|
61
|
+
} as RecallAiSdk;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class RecallDesktopMain {
|
|
65
|
+
private version = '1.0.0';
|
|
66
|
+
private isInitialized = false;
|
|
67
|
+
private subscriptions: Map<RecallSdkEventType, Map<number, number>> = new Map();
|
|
68
|
+
private trackedWebContents = new Map<number, Electron.WebContents>();
|
|
69
|
+
|
|
70
|
+
async initialize(): Promise<void> {
|
|
71
|
+
try {
|
|
72
|
+
// Initialize plugin store
|
|
73
|
+
await recallSdkStore.initialize();
|
|
74
|
+
|
|
75
|
+
// Load configuration from ToDesktop preferences
|
|
76
|
+
// In a real implementation, this would integrate with ToDesktop's preference system
|
|
77
|
+
this.loadPreferences();
|
|
78
|
+
|
|
79
|
+
// Register IPC handlers
|
|
80
|
+
this.registerIpcHandlers();
|
|
81
|
+
|
|
82
|
+
// Initialize SDK if plugin is enabled
|
|
83
|
+
if (recallSdkStore.isEnabled()) {
|
|
84
|
+
await this.initializeSdk();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.isInitialized = true;
|
|
88
|
+
console.log('RecallDesktopMain: Main process initialized');
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error('RecallDesktopMain: Failed to initialize main process:', error);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private loadPreferences(): void {
|
|
96
|
+
// In a real implementation, this would load from ToDesktop's preference system
|
|
97
|
+
// For now, we'll use defaults
|
|
98
|
+
const preferences = {
|
|
99
|
+
enabled: true,
|
|
100
|
+
apiUrl: 'https://us-east-1.recall.ai',
|
|
101
|
+
requestPermissionsOnStartup: true,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
recallSdkStore.loadFromPreferences(preferences);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async initializeSdk(): Promise<void> {
|
|
108
|
+
try {
|
|
109
|
+
const config = recallSdkStore.getConfig();
|
|
110
|
+
|
|
111
|
+
const sdkOptions: SdkInitOptions = {
|
|
112
|
+
apiUrl: config.apiUrl,
|
|
113
|
+
acquirePermissionsOnStartup: config.requestPermissionsOnStartup
|
|
114
|
+
? ['accessibility', 'screen-capture', 'microphone', 'system-audio']
|
|
115
|
+
: undefined,
|
|
116
|
+
restartOnError: true,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Initialize the Recall SDK
|
|
120
|
+
await (RecallAiSdk.init as any)(sdkOptions);
|
|
121
|
+
|
|
122
|
+
// Set up event listeners
|
|
123
|
+
this.setupSdkEventListeners();
|
|
124
|
+
|
|
125
|
+
recallSdkStore.setSdkInitialized(true);
|
|
126
|
+
console.log('RecallDesktopMain: SDK initialized successfully');
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error('RecallDesktopMain: Failed to initialize SDK:', error);
|
|
129
|
+
throw new RecallSdkError('SDK initialization failed', 'SDK_INIT_ERROR');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private setupSdkEventListeners(): void {
|
|
134
|
+
const broadcast = (type: RecallSdkEventType, data: any) => {
|
|
135
|
+
const channel = `recall-desktop:event:${type}`;
|
|
136
|
+
const subs = this.subscriptions.get(type);
|
|
137
|
+
if (!subs) return;
|
|
138
|
+
subs.forEach((_count, wcId) => {
|
|
139
|
+
const wc = this.trackedWebContents.get(wcId);
|
|
140
|
+
if (!wc) return;
|
|
141
|
+
try {
|
|
142
|
+
wc.send(channel, data);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
console.error('RecallDesktopMain: Failed to send event to webContents', wcId, err);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Permissions granted
|
|
150
|
+
RecallAiSdk.addEventListener('permissions-granted', (evt) => {
|
|
151
|
+
console.log('RecallDesktopMain: Permissions granted');
|
|
152
|
+
const type: RecallSdkEventType = 'permissions-granted';
|
|
153
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
154
|
+
broadcast(type, evt);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Meeting detected
|
|
158
|
+
RecallAiSdk.addEventListener('meeting-detected', (evt) => {
|
|
159
|
+
console.log('RecallDesktopMain: Meeting detected:', evt);
|
|
160
|
+
const meeting = evt.window;
|
|
161
|
+
recallSdkStore.addMeeting(meeting);
|
|
162
|
+
const type: RecallSdkEventType = 'meeting-detected';
|
|
163
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
164
|
+
broadcast(type, evt);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// SDK state change
|
|
168
|
+
RecallAiSdk.addEventListener('sdk-state-change', (evt) => {
|
|
169
|
+
console.log('RecallDesktopMain: SDK state change:', evt);
|
|
170
|
+
const state = evt.sdk.state.code;
|
|
171
|
+
recallSdkStore.setSdkState(state);
|
|
172
|
+
const type: RecallSdkEventType = 'sdk-state-change';
|
|
173
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
174
|
+
broadcast(type, evt);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Recording started
|
|
178
|
+
RecallAiSdk.addEventListener('recording-started', (evt) => {
|
|
179
|
+
console.log('RecallDesktopMain: Recording started:', evt);
|
|
180
|
+
const type: RecallSdkEventType = 'recording-started';
|
|
181
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
182
|
+
broadcast(type, evt);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Recording ended
|
|
186
|
+
RecallAiSdk.addEventListener('recording-ended', (evt) => {
|
|
187
|
+
console.log('RecallDesktopMain: Recording ended:', evt);
|
|
188
|
+
recallSdkStore.stopRecording(evt.window.id);
|
|
189
|
+
const type: RecallSdkEventType = 'recording-ended';
|
|
190
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
191
|
+
broadcast(type, evt);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Meeting closed
|
|
195
|
+
RecallAiSdk.addEventListener('meeting-closed', (evt) => {
|
|
196
|
+
console.log('RecallDesktopMain: Meeting closed:', evt);
|
|
197
|
+
recallSdkStore.removeMeeting(evt.window.id);
|
|
198
|
+
const type: RecallSdkEventType = 'meeting-closed';
|
|
199
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
200
|
+
broadcast(type, evt);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Upload progress
|
|
204
|
+
RecallAiSdk.addEventListener('upload-progress', (evt) => {
|
|
205
|
+
console.log(`RecallDesktopMain: Upload progress: ${evt.progress}%`);
|
|
206
|
+
const type: RecallSdkEventType = 'upload-progress';
|
|
207
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
208
|
+
broadcast(type, evt);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Other events
|
|
212
|
+
(['realtime-event', 'meeting-updated', 'media-capture-status', 'participant-capture-status'] as RecallSdkEventType[])
|
|
213
|
+
.forEach(eventType => {
|
|
214
|
+
RecallAiSdk.addEventListener(eventType, (evt) => {
|
|
215
|
+
console.log(`RecallDesktopMain: ${eventType}:`, evt);
|
|
216
|
+
recallSdkStore.emitEvent({ type: eventType, data: evt });
|
|
217
|
+
broadcast(eventType, evt);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Permission status
|
|
222
|
+
RecallAiSdk.addEventListener('permission-status', (evt) => {
|
|
223
|
+
console.log('RecallDesktopMain: Permission status:', evt);
|
|
224
|
+
recallSdkStore.setPermissionStatus(evt.permission, evt.status);
|
|
225
|
+
const type: RecallSdkEventType = 'permission-status';
|
|
226
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
227
|
+
broadcast(type, evt);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Error handling
|
|
231
|
+
RecallAiSdk.addEventListener('error', (evt) => {
|
|
232
|
+
console.error('RecallDesktopMain: SDK error:', evt);
|
|
233
|
+
const type: RecallSdkEventType = 'error';
|
|
234
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
235
|
+
broadcast(type, evt);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Shutdown
|
|
239
|
+
RecallAiSdk.addEventListener('shutdown', (evt) => {
|
|
240
|
+
console.log('RecallDesktopMain: SDK shutdown:', evt);
|
|
241
|
+
recallSdkStore.setSdkInitialized(false);
|
|
242
|
+
const type: RecallSdkEventType = 'shutdown';
|
|
243
|
+
recallSdkStore.emitEvent({ type, data: evt });
|
|
244
|
+
broadcast(type, evt);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
private registerIpcHandlers(): void {
|
|
250
|
+
const addDestroyedCleanup = (wc: Electron.WebContents) => {
|
|
251
|
+
const id = wc.id;
|
|
252
|
+
if (this.trackedWebContents.has(id)) return;
|
|
253
|
+
this.trackedWebContents.set(id, wc);
|
|
254
|
+
wc.once('destroyed', () => {
|
|
255
|
+
// Remove this wc from all subscriptions
|
|
256
|
+
this.subscriptions.forEach((map) => {
|
|
257
|
+
map.delete(id);
|
|
258
|
+
});
|
|
259
|
+
this.trackedWebContents.delete(id);
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Subscribe to events
|
|
264
|
+
ipcMain.handle(IPC_CHANNELS.SUBSCRIBE_EVENTS, async (event, eventType: RecallSdkEventType): Promise<ApiResponse> => {
|
|
265
|
+
try {
|
|
266
|
+
const wc = event.sender;
|
|
267
|
+
addDestroyedCleanup(wc);
|
|
268
|
+
let map = this.subscriptions.get(eventType);
|
|
269
|
+
if (!map) {
|
|
270
|
+
map = new Map();
|
|
271
|
+
this.subscriptions.set(eventType, map);
|
|
272
|
+
}
|
|
273
|
+
const id = wc.id;
|
|
274
|
+
const prev = map.get(id) || 0;
|
|
275
|
+
map.set(id, prev + 1);
|
|
276
|
+
return { success: true, message: `Subscribed to ${eventType}` };
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error('RecallDesktopMain: subscribe-events failed', error);
|
|
279
|
+
return { success: false, message: 'Failed to subscribe to events' };
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Unsubscribe from events
|
|
284
|
+
ipcMain.handle(IPC_CHANNELS.UNSUBSCRIBE_EVENTS, async (event, eventType: RecallSdkEventType): Promise<ApiResponse> => {
|
|
285
|
+
try {
|
|
286
|
+
const wc = event.sender;
|
|
287
|
+
const map = this.subscriptions.get(eventType);
|
|
288
|
+
if (map) {
|
|
289
|
+
const id = wc.id;
|
|
290
|
+
const prev = map.get(id) || 0;
|
|
291
|
+
if (prev <= 1) map.delete(id);
|
|
292
|
+
else map.set(id, prev - 1);
|
|
293
|
+
}
|
|
294
|
+
return { success: true, message: `Unsubscribed from ${eventType}` };
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error('RecallDesktopMain: unsubscribe-events failed', error);
|
|
297
|
+
return { success: false, message: 'Failed to unsubscribe from events' };
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
// Initialize SDK
|
|
301
|
+
ipcMain.handle(IPC_CHANNELS.INIT_SDK, async (): Promise<ApiResponse> => {
|
|
302
|
+
try {
|
|
303
|
+
if (!recallSdkStore.isEnabled()) {
|
|
304
|
+
throw new RecallSdkError('Plugin is disabled', 'PLUGIN_DISABLED');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (recallSdkStore.isSdkInitialized()) {
|
|
308
|
+
return { success: true, message: 'SDK already initialized' };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
await this.initializeSdk();
|
|
312
|
+
return { success: true, message: 'SDK initialized successfully' };
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error('RecallDesktopMain: SDK initialization failed:', error);
|
|
315
|
+
return {
|
|
316
|
+
success: false,
|
|
317
|
+
message: error instanceof RecallSdkError ? error.message : 'SDK initialization failed'
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Shutdown SDK
|
|
323
|
+
ipcMain.handle(IPC_CHANNELS.SHUTDOWN_SDK, async (): Promise<ApiResponse> => {
|
|
324
|
+
try {
|
|
325
|
+
await (RecallAiSdk.shutdown as any)();
|
|
326
|
+
recallSdkStore.clearState();
|
|
327
|
+
return { success: true, message: 'SDK shutdown successfully' };
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error('RecallDesktopMain: SDK shutdown failed:', error);
|
|
330
|
+
return { success: false, message: 'SDK shutdown failed' };
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Get plugin status
|
|
335
|
+
ipcMain.handle(IPC_CHANNELS.GET_STATUS, async (): Promise<PluginStatus> => {
|
|
336
|
+
return {
|
|
337
|
+
initialized: this.isInitialized,
|
|
338
|
+
sdkInitialized: recallSdkStore.isSdkInitialized(),
|
|
339
|
+
version: this.version,
|
|
340
|
+
config: recallSdkStore.getConfig(),
|
|
341
|
+
sdkState: recallSdkStore.getSdkState(),
|
|
342
|
+
permissions: recallSdkStore.getPermissions()
|
|
343
|
+
};
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// Start recording
|
|
347
|
+
ipcMain.handle(IPC_CHANNELS.START_RECORDING, async (event, request: StartRecordingRequest): Promise<ApiResponse> => {
|
|
348
|
+
try {
|
|
349
|
+
if (!recallSdkStore.isSdkInitialized()) {
|
|
350
|
+
throw new RecallSdkError('SDK not initialized', 'SDK_NOT_INITIALIZED');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
await (RecallAiSdk.startRecording as any)({
|
|
354
|
+
windowId: request.windowId,
|
|
355
|
+
uploadToken: request.uploadToken
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
recallSdkStore.startRecording(request.windowId, request.uploadToken);
|
|
359
|
+
return { success: true, message: 'Recording started successfully' };
|
|
360
|
+
} catch (error) {
|
|
361
|
+
console.error('RecallDesktopMain: Start recording failed:', error);
|
|
362
|
+
return {
|
|
363
|
+
success: false,
|
|
364
|
+
message: error instanceof RecallSdkError ? error.message : 'Failed to start recording'
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// Stop recording
|
|
370
|
+
ipcMain.handle(IPC_CHANNELS.STOP_RECORDING, async (event, request: StopRecordingRequest): Promise<ApiResponse> => {
|
|
371
|
+
try {
|
|
372
|
+
await (RecallAiSdk.stopRecording as any)({ windowId: request.windowId });
|
|
373
|
+
recallSdkStore.stopRecording(request.windowId);
|
|
374
|
+
return { success: true, message: 'Recording stopped successfully' };
|
|
375
|
+
} catch (error) {
|
|
376
|
+
console.error('RecallDesktopMain: Stop recording failed:', error);
|
|
377
|
+
return { success: false, message: 'Failed to stop recording' };
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Pause recording
|
|
382
|
+
ipcMain.handle(IPC_CHANNELS.PAUSE_RECORDING, async (event, request: PauseRecordingRequest): Promise<ApiResponse> => {
|
|
383
|
+
try {
|
|
384
|
+
await (RecallAiSdk.pauseRecording as any)({ windowId: request.windowId });
|
|
385
|
+
return { success: true, message: 'Recording paused successfully' };
|
|
386
|
+
} catch (error) {
|
|
387
|
+
console.error('RecallDesktopMain: Pause recording failed:', error);
|
|
388
|
+
return { success: false, message: 'Failed to pause recording' };
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// Resume recording
|
|
393
|
+
ipcMain.handle(IPC_CHANNELS.RESUME_RECORDING, async (event, request: ResumeRecordingRequest): Promise<ApiResponse> => {
|
|
394
|
+
try {
|
|
395
|
+
await (RecallAiSdk.resumeRecording as any)({ windowId: request.windowId });
|
|
396
|
+
return { success: true, message: 'Recording resumed successfully' };
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.error('RecallDesktopMain: Resume recording failed:', error);
|
|
399
|
+
return { success: false, message: 'Failed to resume recording' };
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Upload recording
|
|
404
|
+
ipcMain.handle(IPC_CHANNELS.UPLOAD_RECORDING, async (event, request: UploadRecordingRequest): Promise<ApiResponse> => {
|
|
405
|
+
try {
|
|
406
|
+
await (RecallAiSdk.uploadRecording as any)({ windowId: request.windowId });
|
|
407
|
+
return { success: true, message: 'Recording upload started successfully' };
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.error('RecallDesktopMain: Upload recording failed:', error);
|
|
410
|
+
return { success: false, message: 'Failed to upload recording' };
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Prepare desktop audio recording
|
|
415
|
+
ipcMain.handle(IPC_CHANNELS.PREPARE_DESKTOP_AUDIO, async (): Promise<ApiResponse<PrepareDesktopAudioResponse>> => {
|
|
416
|
+
try {
|
|
417
|
+
const windowId = await (RecallAiSdk.prepareDesktopAudioRecording as any)();
|
|
418
|
+
return {
|
|
419
|
+
success: true,
|
|
420
|
+
message: 'Desktop audio recording prepared successfully',
|
|
421
|
+
data: { windowId }
|
|
422
|
+
};
|
|
423
|
+
} catch (error) {
|
|
424
|
+
console.error('RecallDesktopMain: Prepare desktop audio failed:', error);
|
|
425
|
+
return { success: false, message: 'Failed to prepare desktop audio recording' };
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// Request permission
|
|
430
|
+
ipcMain.handle(IPC_CHANNELS.REQUEST_PERMISSION, async (event, permission: PermissionType): Promise<ApiResponse> => {
|
|
431
|
+
try {
|
|
432
|
+
await (RecallAiSdk.requestPermission as any)(permission);
|
|
433
|
+
return { success: true, message: `Permission request sent for ${permission}` };
|
|
434
|
+
} catch (error) {
|
|
435
|
+
console.error('RecallDesktopMain: Request permission failed:', error);
|
|
436
|
+
return { success: false, message: 'Failed to request permission' };
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
// Set configuration
|
|
441
|
+
ipcMain.handle(IPC_CHANNELS.SET_CONFIG, async (event, config: Partial<RecallSdkConfig>): Promise<ApiResponse> => {
|
|
442
|
+
try {
|
|
443
|
+
recallSdkStore.setConfig(config);
|
|
444
|
+
|
|
445
|
+
// If SDK settings changed and SDK is initialized, reinitialize
|
|
446
|
+
if (recallSdkStore.isSdkInitialized() && (config.apiUrl || config.requestPermissionsOnStartup !== undefined)) {
|
|
447
|
+
console.log('RecallDesktopMain: Reinitializing SDK due to configuration change');
|
|
448
|
+
await (RecallAiSdk.shutdown as any)();
|
|
449
|
+
await this.initializeSdk();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return { success: true, message: 'Configuration updated successfully' };
|
|
453
|
+
} catch (error) {
|
|
454
|
+
console.error('RecallDesktopMain: Failed to set configuration:', error);
|
|
455
|
+
return { success: false, message: 'Failed to update configuration' };
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// Get configuration
|
|
460
|
+
ipcMain.handle(IPC_CHANNELS.GET_CONFIG, async (): Promise<ApiResponse<RecallSdkConfig>> => {
|
|
461
|
+
return {
|
|
462
|
+
success: true,
|
|
463
|
+
message: 'Configuration retrieved successfully',
|
|
464
|
+
data: recallSdkStore.getConfig()
|
|
465
|
+
};
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Initialize plugin
|
|
471
|
+
const recallDesktopMain = new RecallDesktopMain();
|
|
472
|
+
recallDesktopMain.initialize().catch(console.error);
|
|
473
|
+
|
|
474
|
+
export default recallDesktopMain;
|