cuoral-ionic 0.0.6 → 0.0.8

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.
Files changed (68) hide show
  1. package/android/build/.transforms/bb54161301273cf9b5b94a21c0fb3f23/transformed/classes/classes_dex/classes.dex +0 -0
  2. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$1.dex +0 -0
  3. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$2.dex +0 -0
  4. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$3.dex +0 -0
  5. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$4.dex +0 -0
  6. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$5.dex +0 -0
  7. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$6.dex +0 -0
  8. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$InitiateCallback.dex +0 -0
  9. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$UploadCallback.dex +0 -0
  10. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin.dex +0 -0
  11. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/desugar_graph.bin +0 -0
  12. package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
  13. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$1.class +0 -0
  14. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$2.class +0 -0
  15. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$3.class +0 -0
  16. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$4.class +0 -0
  17. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$5.class +0 -0
  18. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$6.class +0 -0
  19. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$InitiateCallback.class +0 -0
  20. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$UploadCallback.class +0 -0
  21. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin.class +0 -0
  22. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$1.class +0 -0
  23. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$2.class +0 -0
  24. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$3.class +0 -0
  25. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$4.class +0 -0
  26. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$5.class +0 -0
  27. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$6.class +0 -0
  28. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$InitiateCallback.class +0 -0
  29. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$UploadCallback.class +0 -0
  30. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin.class +0 -0
  31. package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
  32. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/{CuoralPlugin$1.class.uniqueId1 → CuoralPlugin$1.class.uniqueId2} +0 -0
  33. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/{CuoralPlugin$2.class.uniqueId2 → CuoralPlugin$2.class.uniqueId5} +0 -0
  34. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$3.class.uniqueId3 +0 -0
  35. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$4.class.uniqueId6 +0 -0
  36. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$5.class.uniqueId4 +0 -0
  37. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$6.class.uniqueId8 +0 -0
  38. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$InitiateCallback.class.uniqueId0 +0 -0
  39. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$UploadCallback.class.uniqueId7 +0 -0
  40. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin.class.uniqueId1 +0 -0
  41. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  42. package/android/build.gradle +1 -0
  43. package/android/src/main/java/com/cuoral/ionic/CuoralPlugin.java +209 -6
  44. package/dist/bridge.d.ts.map +1 -1
  45. package/dist/cuoral.d.ts +15 -1
  46. package/dist/cuoral.d.ts.map +1 -1
  47. package/dist/cuoral.js +141 -12
  48. package/dist/index.esm.js +218 -46
  49. package/dist/index.esm.js.map +1 -1
  50. package/dist/index.js +218 -46
  51. package/dist/index.js.map +1 -1
  52. package/dist/intelligence.d.ts +4 -0
  53. package/dist/intelligence.d.ts.map +1 -1
  54. package/dist/intelligence.js +19 -0
  55. package/dist/plugin.d.ts +16 -3
  56. package/dist/plugin.d.ts.map +1 -1
  57. package/dist/plugin.js +53 -36
  58. package/dist/types.d.ts +4 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/types.js +4 -0
  61. package/ios/Plugin/CuoralPlugin.swift +249 -13
  62. package/package.json +1 -1
  63. package/src/bridge.ts +1 -0
  64. package/src/cuoral.ts +158 -14
  65. package/src/intelligence.ts +23 -0
  66. package/src/plugin.ts +70 -37
  67. package/src/types.ts +4 -0
  68. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin.class.uniqueId0 +0 -0
package/src/cuoral.ts CHANGED
@@ -42,6 +42,8 @@ export class Cuoral {
42
42
  private static readonly DEV_WIDGET_URL = 'assets/mobile.html';
43
43
 
44
44
  constructor(options: CuoralOptions) {
45
+ console.log('[Cuoral] Constructor called with options:', options);
46
+
45
47
  // Check if running on a mobile platform
46
48
  if (!Capacitor.isNativePlatform()) {
47
49
  throw new Error('Cuoral Ionic library only works on native mobile platforms (iOS/Android). Web is not supported.');
@@ -53,6 +55,8 @@ export class Cuoral {
53
55
  ...options
54
56
  };
55
57
 
58
+ console.log('[Cuoral] Merged options:', this.options);
59
+
56
60
  // Determine widget base URL
57
61
  const baseUrl = options.widgetBaseUrl || Cuoral.PRODUCTION_WIDGET_URL;
58
62
  const params = new URLSearchParams({
@@ -61,6 +65,12 @@ export class Cuoral {
61
65
  _t: Date.now().toString(),
62
66
  });
63
67
 
68
+ // Add session_id if available (for widget to use existing session)
69
+ const existingSessionId = localStorage.getItem('__x_loadID');
70
+ if (existingSessionId) {
71
+ params.set('cuoral_mobile_session_id', existingSessionId);
72
+ }
73
+
64
74
  if (options.email) params.set('email', options.email);
65
75
  if (options.firstName) params.set('first_name', options.firstName);
66
76
  if (options.lastName) params.set('last_name', options.lastName);
@@ -80,14 +90,29 @@ export class Cuoral {
80
90
 
81
91
  this.recorder = new CuoralRecorder();
82
92
 
93
+ // Expose bridge on window for widget detection and debugging
94
+ (window as any).CuoralCapacitorBridge = true;
95
+ (window as any).__cuoralBridge = this.bridge; // For debugging
96
+ (window as any).__cuoralRecorder = this.recorder; // For debugging
97
+ console.log('[Cuoral] Bridge and recorder created, exposed on window');
98
+
83
99
  // Setup automatic message handlers
84
100
  this.setupMessageHandlers();
101
+ console.log('[Cuoral] Constructor complete');
85
102
  }
86
103
 
87
104
  /**
88
105
  * Initialize Cuoral
89
106
  */
90
107
  public async initialize(): Promise<void> {
108
+ // Fetch session configuration and initialize intelligence if enabled by backend
109
+ await this.initializeIntelligence();
110
+
111
+ console.log('[Cuoral] Initialize - Session ID:', localStorage.getItem('__x_loadID'));
112
+
113
+ // Setup localStorage listener to detect when widget changes session
114
+ this.setupStorageListener();
115
+
91
116
  this.bridge.initialize();
92
117
 
93
118
  // Recreate modal if it was destroyed (e.g., after clearSession)
@@ -96,13 +121,12 @@ export class Cuoral {
96
121
  this.modal = new CuoralModal(widgetUrl, this.options.showFloatingButton);
97
122
  }
98
123
 
99
- // Initialize modal if enabled
124
+ // Update modal URL with session ID
100
125
  if (this.modal) {
126
+ const widgetUrl = this.getWidgetUrl();
127
+ this.modal.updateWidgetUrl(widgetUrl);
101
128
  this.modal.initialize();
102
129
  }
103
-
104
- // Fetch session configuration and initialize intelligence if enabled by backend
105
- await this.initializeIntelligence();
106
130
  }
107
131
 
108
132
  /**
@@ -139,8 +163,11 @@ export class Cuoral {
139
163
 
140
164
  // Only initialize intelligence if customer_intelligence is enabled in backend
141
165
  if (config && config.customer_intelligence === true) {
166
+ console.log('[Cuoral] Initializing intelligence with session:', sessionId);
142
167
  this.intelligence = new CuoralIntelligence(sessionId);
143
168
  this.intelligence.init();
169
+ } else {
170
+ console.log('[Cuoral] Intelligence not enabled or no config for session:', sessionId);
144
171
  }
145
172
  } catch (error) {
146
173
  console.warn('[Cuoral] Failed to initialize intelligence:', error);
@@ -205,6 +232,54 @@ export class Cuoral {
205
232
  }
206
233
  }
207
234
 
235
+ /**
236
+ * Update user profile for the current session
237
+ * Call this after user logs in to update the intelligence session with their profile
238
+ * @param email - User's email address
239
+ * @param name - User's full name
240
+ */
241
+ public async updateUserProfile(email: string, name: string): Promise<boolean> {
242
+ try {
243
+ const sessionId = localStorage.getItem('__x_loadID');
244
+ if (!sessionId) {
245
+ console.warn('[Cuoral] No session ID found, cannot update profile');
246
+ return false;
247
+ }
248
+
249
+ console.log('[Cuoral] Updating user profile for session:', sessionId);
250
+
251
+ const response = await fetch('https://api.cuoral.com/conversation/set-profile', {
252
+ method: 'POST',
253
+ headers: { 'Content-Type': 'application/json' },
254
+ body: JSON.stringify({
255
+ session_id: sessionId,
256
+ email: email,
257
+ name: name,
258
+ }),
259
+ });
260
+
261
+ if (!response.ok) {
262
+ console.error('[Cuoral] Failed to update profile:', response.statusText);
263
+ return false;
264
+ }
265
+
266
+ console.log('[Cuoral] ✓ User profile updated successfully for session:', sessionId);
267
+
268
+ // Store user info locally
269
+ this.options.email = email;
270
+ const nameParts = name.split(' ');
271
+ if (nameParts.length > 0) {
272
+ this.options.firstName = nameParts[0];
273
+ this.options.lastName = nameParts.slice(1).join(' ');
274
+ }
275
+
276
+ return true;
277
+ } catch (error) {
278
+ console.error('[Cuoral] Error updating user profile:', error);
279
+ return false;
280
+ }
281
+ }
282
+
208
283
  /**
209
284
  * Start native screen recording programmatically
210
285
  * @returns Promise<boolean> - true if recording started successfully
@@ -220,11 +295,20 @@ export class Cuoral {
220
295
 
221
296
  /**
222
297
  * Stop native screen recording programmatically
223
- * @returns Promise<{filePath?: string; duration?: number} | null> - Recording result or null if failed
298
+ * Recording will be automatically uploaded to the portal
299
+ * @returns Promise<{filePath?: string; duration?: number; uploaded?: boolean} | null> - Recording result or null if failed
224
300
  */
225
- public async stopRecording(): Promise<{filePath?: string; duration?: number} | null> {
301
+ public async stopRecording(): Promise<{filePath?: string; duration?: number; uploaded?: boolean} | null> {
226
302
  try {
227
- return await this.recorder.stopRecording();
303
+ const sessionId = localStorage.getItem('__x_loadID');
304
+ const customerId = localStorage.getItem('cuoralCustomerId');
305
+
306
+ return await this.recorder.stopRecording({
307
+ autoUpload: true,
308
+ sessionId: sessionId || undefined,
309
+ publicKey: this.options.publicKey,
310
+ customerId: customerId || undefined,
311
+ });
228
312
  } catch (error) {
229
313
  console.error('[Cuoral] Failed to stop recording:', error);
230
314
  return null;
@@ -274,7 +358,7 @@ export class Cuoral {
274
358
  // Add session_id if available
275
359
  const sessionId = localStorage.getItem('__x_loadID');
276
360
  if (sessionId) {
277
- params.set('session_id', sessionId);
361
+ params.set('cuoral_mobile_session_id', sessionId);
278
362
  }
279
363
 
280
364
  if (this.options.email) params.set('email', this.options.email);
@@ -333,6 +417,32 @@ export class Cuoral {
333
417
  }
334
418
  }
335
419
 
420
+ /**
421
+ * Setup localStorage listener for session changes
422
+ * Widget updates localStorage when creating new session, SDK detects and syncs
423
+ */
424
+ private setupStorageListener(): void {
425
+ // Poll localStorage every 2 seconds to detect session changes
426
+ // (storage event doesn't fire for same-window changes)
427
+ let lastKnownSession = localStorage.getItem('__x_loadID');
428
+
429
+ setInterval(() => {
430
+ const currentSession = localStorage.getItem('__x_loadID');
431
+ if (currentSession && currentSession !== lastKnownSession) {
432
+ console.log('[Cuoral] 🔄 Session changed in localStorage');
433
+ console.log('[Cuoral] Old session:', lastKnownSession);
434
+ console.log('[Cuoral] New session:', currentSession);
435
+
436
+ lastKnownSession = currentSession;
437
+
438
+ // Update intelligence to use new session
439
+ if (this.intelligence) {
440
+ this.intelligence.updateSessionId(currentSession);
441
+ }
442
+ }
443
+ }, 2000);
444
+ }
445
+
336
446
  /**
337
447
  * Clean up resources
338
448
  */
@@ -431,18 +541,52 @@ export class Cuoral {
431
541
  private setupMessageHandlers(): void {
432
542
  // Handle start recording requests from widget
433
543
  this.bridge.on(CuoralMessageType.START_RECORDING, async () => {
434
- const success = await this.recorder.startRecording();
435
- if (!success) {
436
- // Error already handled by recorder
544
+ // Pass sendMessages: false to prevent duplicate messages
545
+ const success = await this.recorder.startRecording(undefined, false);
546
+ if (success) {
547
+ // Send RECORDING_STARTED back to widget
548
+ this.bridge.sendToWidget({
549
+ type: CuoralMessageType.RECORDING_STARTED,
550
+ payload: {
551
+ timestamp: Date.now()
552
+ }
553
+ });
554
+ } else {
555
+ this.bridge.sendToWidget({
556
+ type: CuoralMessageType.RECORDING_ERROR,
557
+ payload: {
558
+ error: 'Failed to start recording'
559
+ }
560
+ });
437
561
  }
438
562
  });
439
563
 
440
564
  // Handle stop recording requests from widget
441
565
  this.bridge.on(CuoralMessageType.STOP_RECORDING, async () => {
442
- const result = await this.recorder.stopRecording();
566
+ const sessionId = localStorage.getItem('__x_loadID');
567
+ const customerId = localStorage.getItem('cuoralCustomerId');
443
568
 
444
- if (result) {
445
- // Convert file path to web-accessible URL
569
+ // Pass sendMessages: false to prevent duplicate messages
570
+ const result = await this.recorder.stopRecording({
571
+ autoUpload: true,
572
+ sessionId: sessionId || undefined,
573
+ publicKey: this.options.publicKey,
574
+ customerId: customerId || undefined,
575
+ }, false);
576
+
577
+ if (result && result.uploaded) {
578
+ // Video was automatically uploaded, notify widget with RECORDING_STOPPED
579
+ this.bridge.sendToWidget({
580
+ type: CuoralMessageType.RECORDING_STOPPED,
581
+ payload: {
582
+ duration: result.duration,
583
+ uploaded: true,
584
+ uploadedToBackend: true,
585
+ timestamp: Date.now()
586
+ }
587
+ });
588
+ } else if (result) {
589
+ // Upload failed or was disabled, send video data to widget (old behavior)
446
590
  const capacitorUrl = result.filePath ? Capacitor.convertFileSrc(result.filePath) : '';
447
591
 
448
592
  try {
@@ -117,6 +117,27 @@ export class CuoralIntelligence {
117
117
  this.sessionId = sessionId;
118
118
  }
119
119
 
120
+ /**
121
+ * Update the session ID (e.g., when user logs in)
122
+ */
123
+ public updateSessionId(newSessionId: string): void {
124
+ console.log('[Cuoral Intelligence] Updating session ID from', this.sessionId, 'to', newSessionId);
125
+ this.sessionId = newSessionId;
126
+
127
+ // Flush any pending events with the old session before switching
128
+ this.flush();
129
+
130
+ // Update native error capture with new session ID
131
+ if (Capacitor.isNativePlatform()) {
132
+ CuoralPlugin.setupNativeErrorCapture({
133
+ backendUrl: this.config.consoleErrorBackendUrl,
134
+ sessionId: newSessionId
135
+ }).catch(error => {
136
+ console.warn('[Cuoral Intelligence] Failed to update native error capture:', error);
137
+ });
138
+ }
139
+ }
140
+
120
141
  /**
121
142
  * Initialize intelligence tracking
122
143
  */
@@ -482,6 +503,7 @@ export class CuoralIntelligence {
482
503
  data,
483
504
  };
484
505
 
506
+ console.log(`[Intelligence] Enqueuing ${type} event with session:`, this.sessionId);
485
507
  queue.push(event);
486
508
 
487
509
  // Flush immediately for critical errors
@@ -506,6 +528,7 @@ export class CuoralIntelligence {
506
528
  return;
507
529
  }
508
530
 
531
+
509
532
  // Clear timer
510
533
  if (this.batchTimers[eventType]) {
511
534
  clearTimeout(this.batchTimers[eventType]);
package/src/plugin.ts CHANGED
@@ -19,7 +19,18 @@ export interface CuoralPluginInterface {
19
19
  /**
20
20
  * Stop screen recording
21
21
  */
22
- stopRecording(): Promise<{ success: boolean; filePath?: string; duration?: number }>;
22
+ stopRecording(options?: {
23
+ autoUpload?: boolean;
24
+ sessionId?: string;
25
+ publicKey?: string;
26
+ customerId?: string;
27
+ }): Promise<{
28
+ success: boolean;
29
+ filePath?: string;
30
+ duration?: number;
31
+ uploaded?: boolean;
32
+ uploadError?: string;
33
+ }>;
23
34
 
24
35
  /**
25
36
  * Get recording state
@@ -59,7 +70,7 @@ export class CuoralRecorder {
59
70
  /**
60
71
  * Start recording with automatic permission handling
61
72
  */
62
- async startRecording(options?: RecordingOptions): Promise<boolean> {
73
+ async startRecording(options?: RecordingOptions, sendMessages: boolean = true): Promise<boolean> {
63
74
  try {
64
75
  // Check if already recording
65
76
  if (this.isRecording) {
@@ -86,20 +97,24 @@ export class CuoralRecorder {
86
97
  this.isRecording = true;
87
98
  this.recordingStartTime = Date.now();
88
99
 
89
- // Post message to widget
90
- this.postMessage({
91
- type: CuoralMessageType.RECORDING_STARTED,
92
- payload: { timestamp: this.recordingStartTime },
93
- });
100
+ // Post message to widget only if enabled (disabled when called from widget handler)
101
+ if (sendMessages) {
102
+ this.postMessage({
103
+ type: CuoralMessageType.RECORDING_STARTED,
104
+ payload: { timestamp: this.recordingStartTime },
105
+ });
106
+ }
94
107
  } else {
95
108
  // Recording failed - reset state and notify widget
96
109
  this.isRecording = false;
97
110
  this.recordingStartTime = undefined;
98
111
 
99
- this.postMessage({
100
- type: CuoralMessageType.RECORDING_ERROR,
101
- payload: { error: 'Failed to start recording' },
102
- });
112
+ if (sendMessages) {
113
+ this.postMessage({
114
+ type: CuoralMessageType.RECORDING_ERROR,
115
+ payload: { error: 'Failed to start recording' },
116
+ });
117
+ }
103
118
  }
104
119
 
105
120
  return result.success;
@@ -108,10 +123,12 @@ export class CuoralRecorder {
108
123
  this.isRecording = false;
109
124
  this.recordingStartTime = undefined;
110
125
 
111
- this.postMessage({
112
- type: CuoralMessageType.RECORDING_ERROR,
113
- payload: { error: (error as Error).message },
114
- });
126
+ if (sendMessages) {
127
+ this.postMessage({
128
+ type: CuoralMessageType.RECORDING_ERROR,
129
+ payload: { error: (error as Error).message },
130
+ });
131
+ }
115
132
  return false;
116
133
  }
117
134
  }
@@ -119,51 +136,67 @@ export class CuoralRecorder {
119
136
  /**
120
137
  * Stop recording
121
138
  */
122
- async stopRecording(): Promise<{ filePath?: string; duration?: number } | null> {
139
+ async stopRecording(options?: {
140
+ autoUpload?: boolean;
141
+ sessionId?: string;
142
+ publicKey?: string;
143
+ customerId?: string;
144
+ }, sendMessages: boolean = true): Promise<{ filePath?: string; duration?: number; uploaded?: boolean } | null> {
123
145
  try {
124
146
  if (!this.isRecording) {
125
147
  // Send error message to widget so it can exit "stopping" state
126
- this.postMessage({
127
- type: CuoralMessageType.RECORDING_ERROR,
128
- payload: { error: 'Not recording' },
129
- });
148
+ if (sendMessages) {
149
+ this.postMessage({
150
+ type: CuoralMessageType.RECORDING_ERROR,
151
+ payload: { error: 'Not recording' },
152
+ });
153
+ }
130
154
  return null;
131
155
  }
132
156
 
133
- const result = await CuoralPlugin.stopRecording();
157
+ const result = await CuoralPlugin.stopRecording(options);
134
158
  if (result.success) {
135
159
  this.isRecording = false;
136
160
  const duration = this.recordingStartTime
137
161
  ? Math.floor((Date.now() - this.recordingStartTime) / 1000)
138
162
  : 0;
139
163
 
140
- // Post message to widget
141
- this.postMessage({
142
- type: CuoralMessageType.RECORDING_STOPPED,
143
- payload: {
144
- filePath: result.filePath,
145
- duration: result.duration || duration,
146
- },
147
- });
164
+ // Send RECORDING_STOPPED message only if enabled
165
+ if (sendMessages) {
166
+ this.postMessage({
167
+ type: CuoralMessageType.RECORDING_STOPPED,
168
+ payload: {
169
+ filePath: result.filePath,
170
+ duration: result.duration || duration,
171
+ uploaded: result.uploaded,
172
+ uploadedToBackend: result.uploaded,
173
+ },
174
+ });
175
+ }
148
176
 
149
177
  return {
150
178
  filePath: result.filePath,
151
179
  duration: result.duration || duration,
180
+ uploaded: result.uploaded,
152
181
  };
153
182
  }
154
183
 
155
184
  // If result.success is false, send error to widget
156
- this.postMessage({
157
- type: CuoralMessageType.RECORDING_ERROR,
158
- payload: { error: 'Failed to stop recording' },
159
- });
185
+ if (sendMessages) {
186
+ this.postMessage({
187
+ type: CuoralMessageType.RECORDING_ERROR,
188
+ payload: { error: 'Failed to stop recording' },
189
+ });
190
+ }
160
191
  return null;
161
192
  } catch (error) {
162
193
  console.error('[Cuoral] Failed to stop recording:', error);
163
- this.postMessage({
164
- type: CuoralMessageType.RECORDING_ERROR,
165
- payload: { error: (error as Error).message },
166
- });
194
+ if (sendMessages) {
195
+ this.postMessage({
196
+ type: CuoralMessageType.RECORDING_ERROR,
197
+ payload: { error: (error as Error).message },
198
+ });
199
+ }
167
200
  return null;
168
201
  }
169
202
  }
package/src/types.ts CHANGED
@@ -7,6 +7,7 @@ export enum CuoralMessageType {
7
7
  STOP_RECORDING = 'CUORAL_STOP_RECORDING',
8
8
  RECORDING_STARTED = 'CUORAL_RECORDING_STARTED',
9
9
  RECORDING_STOPPED = 'CUORAL_RECORDING_STOPPED',
10
+ RECORDING_UPLOADED = 'CUORAL_RECORDING_UPLOADED',
10
11
  RECORDING_ERROR = 'CUORAL_RECORDING_ERROR',
11
12
 
12
13
  // Screenshot
@@ -17,6 +18,9 @@ export enum CuoralMessageType {
17
18
  // Widget Communication
18
19
  WIDGET_READY = 'CUORAL_WIDGET_READY',
19
20
  WIDGET_CLOSED = 'CUORAL_WIDGET_CLOSED',
21
+ SESSION_UPDATED = 'CUORAL_SESSION_UPDATED',
22
+ REQUEST_SESSION_ID = 'CUORAL_REQUEST_SESSION_ID',
23
+ SESSION_ID_RESPONSE = 'CUORAL_SESSION_ID_RESPONSE',
20
24
 
21
25
  // File Upload
22
26
  UPLOAD_FILE = 'CUORAL_UPLOAD_FILE',