cuoral-ionic 0.0.7 → 0.0.9
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/CuoralIonic.podspec +17 -0
- package/README.md +22 -0
- package/android/build/.transforms/bb54161301273cf9b5b94a21c0fb3f23/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$4.dex +0 -0
- package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$5.dex +0 -0
- package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$6.dex +0 -0
- package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin.dex +0 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$4.class +0 -0
- package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$5.class +0 -0
- package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$6.class +0 -0
- package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$4.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$5.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$6.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/{CuoralPlugin$1.class.uniqueId1 → CuoralPlugin$1.class.uniqueId2} +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/{CuoralPlugin$2.class.uniqueId2 → CuoralPlugin$2.class.uniqueId5} +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$3.class.uniqueId3 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$4.class.uniqueId6 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$5.class.uniqueId4 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$6.class.uniqueId8 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$InitiateCallback.class.uniqueId0 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin$UploadCallback.class.uniqueId7 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin.class.uniqueId1 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/src/main/java/com/cuoral/ionic/CuoralPlugin.java +38 -35
- package/dist/bridge.d.ts.map +1 -1
- package/dist/cuoral.d.ts.map +1 -1
- package/dist/cuoral.js +31 -6
- package/dist/index.esm.js +75 -43
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +75 -43
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +43 -39
- package/ios/Plugin/CuoralPlugin.swift +3 -3
- package/package.json +3 -2
- package/src/bridge.ts +1 -0
- package/src/cuoral.ts +33 -6
- package/src/plugin.ts +43 -38
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/CuoralPlugin.class.uniqueId0 +0 -0
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ class CuoralRecorder {
|
|
|
65
65
|
/**
|
|
66
66
|
* Start recording with automatic permission handling
|
|
67
67
|
*/
|
|
68
|
-
async startRecording(options) {
|
|
68
|
+
async startRecording(options, sendMessages = true) {
|
|
69
69
|
try {
|
|
70
70
|
// Check if already recording
|
|
71
71
|
if (this.isRecording) {
|
|
@@ -87,20 +87,24 @@ class CuoralRecorder {
|
|
|
87
87
|
if (result.success) {
|
|
88
88
|
this.isRecording = true;
|
|
89
89
|
this.recordingStartTime = Date.now();
|
|
90
|
-
// Post message to widget
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
// Post message to widget only if enabled (disabled when called from widget handler)
|
|
91
|
+
if (sendMessages) {
|
|
92
|
+
this.postMessage({
|
|
93
|
+
type: exports.CuoralMessageType.RECORDING_STARTED,
|
|
94
|
+
payload: { timestamp: this.recordingStartTime },
|
|
95
|
+
});
|
|
96
|
+
}
|
|
95
97
|
}
|
|
96
98
|
else {
|
|
97
99
|
// Recording failed - reset state and notify widget
|
|
98
100
|
this.isRecording = false;
|
|
99
101
|
this.recordingStartTime = undefined;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
if (sendMessages) {
|
|
103
|
+
this.postMessage({
|
|
104
|
+
type: exports.CuoralMessageType.RECORDING_ERROR,
|
|
105
|
+
payload: { error: 'Failed to start recording' },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
104
108
|
}
|
|
105
109
|
return result.success;
|
|
106
110
|
}
|
|
@@ -108,24 +112,28 @@ class CuoralRecorder {
|
|
|
108
112
|
// Exception occurred - reset state and notify widget
|
|
109
113
|
this.isRecording = false;
|
|
110
114
|
this.recordingStartTime = undefined;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
if (sendMessages) {
|
|
116
|
+
this.postMessage({
|
|
117
|
+
type: exports.CuoralMessageType.RECORDING_ERROR,
|
|
118
|
+
payload: { error: error.message },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
115
121
|
return false;
|
|
116
122
|
}
|
|
117
123
|
}
|
|
118
124
|
/**
|
|
119
125
|
* Stop recording
|
|
120
126
|
*/
|
|
121
|
-
async stopRecording(options) {
|
|
127
|
+
async stopRecording(options, sendMessages = true) {
|
|
122
128
|
try {
|
|
123
129
|
if (!this.isRecording) {
|
|
124
130
|
// Send error message to widget so it can exit "stopping" state
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
if (sendMessages) {
|
|
132
|
+
this.postMessage({
|
|
133
|
+
type: exports.CuoralMessageType.RECORDING_ERROR,
|
|
134
|
+
payload: { error: 'Not recording' },
|
|
135
|
+
});
|
|
136
|
+
}
|
|
129
137
|
return null;
|
|
130
138
|
}
|
|
131
139
|
const result = await CuoralPlugin$1.stopRecording(options);
|
|
@@ -134,23 +142,15 @@ class CuoralRecorder {
|
|
|
134
142
|
const duration = this.recordingStartTime
|
|
135
143
|
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
136
144
|
: 0;
|
|
137
|
-
//
|
|
138
|
-
if (
|
|
139
|
-
this.postMessage({
|
|
140
|
-
type: exports.CuoralMessageType.RECORDING_UPLOADED,
|
|
141
|
-
payload: {
|
|
142
|
-
duration: result.duration || duration,
|
|
143
|
-
uploaded: true
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
// Post message to widget (old behavior)
|
|
145
|
+
// Send RECORDING_STOPPED message only if enabled
|
|
146
|
+
if (sendMessages) {
|
|
149
147
|
this.postMessage({
|
|
150
148
|
type: exports.CuoralMessageType.RECORDING_STOPPED,
|
|
151
149
|
payload: {
|
|
152
150
|
filePath: result.filePath,
|
|
153
151
|
duration: result.duration || duration,
|
|
152
|
+
uploaded: result.uploaded,
|
|
153
|
+
uploadedToBackend: result.uploaded,
|
|
154
154
|
},
|
|
155
155
|
});
|
|
156
156
|
}
|
|
@@ -161,18 +161,22 @@ class CuoralRecorder {
|
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
163
|
// If result.success is false, send error to widget
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
if (sendMessages) {
|
|
165
|
+
this.postMessage({
|
|
166
|
+
type: exports.CuoralMessageType.RECORDING_ERROR,
|
|
167
|
+
payload: { error: 'Failed to stop recording' },
|
|
168
|
+
});
|
|
169
|
+
}
|
|
168
170
|
return null;
|
|
169
171
|
}
|
|
170
172
|
catch (error) {
|
|
171
173
|
console.error('[Cuoral] Failed to stop recording:', error);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
if (sendMessages) {
|
|
175
|
+
this.postMessage({
|
|
176
|
+
type: exports.CuoralMessageType.RECORDING_ERROR,
|
|
177
|
+
payload: { error: error.message },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
176
180
|
return null;
|
|
177
181
|
}
|
|
178
182
|
}
|
|
@@ -1451,6 +1455,7 @@ class CuoralIntelligence {
|
|
|
1451
1455
|
*/
|
|
1452
1456
|
class Cuoral {
|
|
1453
1457
|
constructor(options) {
|
|
1458
|
+
console.log('[Cuoral] Constructor called with options:', options);
|
|
1454
1459
|
// Check if running on a mobile platform
|
|
1455
1460
|
if (!core.Capacitor.isNativePlatform()) {
|
|
1456
1461
|
throw new Error('Cuoral Ionic library only works on native mobile platforms (iOS/Android). Web is not supported.');
|
|
@@ -1460,6 +1465,7 @@ class Cuoral {
|
|
|
1460
1465
|
useModal: true,
|
|
1461
1466
|
...options
|
|
1462
1467
|
};
|
|
1468
|
+
console.log('[Cuoral] Merged options:', this.options);
|
|
1463
1469
|
// Determine widget base URL
|
|
1464
1470
|
const baseUrl = options.widgetBaseUrl || Cuoral.PRODUCTION_WIDGET_URL;
|
|
1465
1471
|
const params = new URLSearchParams({
|
|
@@ -1489,8 +1495,14 @@ class Cuoral {
|
|
|
1489
1495
|
debug: options.debug || false
|
|
1490
1496
|
});
|
|
1491
1497
|
this.recorder = new CuoralRecorder();
|
|
1498
|
+
// Expose bridge on window for widget detection and debugging
|
|
1499
|
+
window.CuoralCapacitorBridge = true;
|
|
1500
|
+
window.__cuoralBridge = this.bridge; // For debugging
|
|
1501
|
+
window.__cuoralRecorder = this.recorder; // For debugging
|
|
1502
|
+
console.log('[Cuoral] Bridge and recorder created, exposed on window');
|
|
1492
1503
|
// Setup automatic message handlers
|
|
1493
1504
|
this.setupMessageHandlers();
|
|
1505
|
+
console.log('[Cuoral] Constructor complete');
|
|
1494
1506
|
}
|
|
1495
1507
|
/**
|
|
1496
1508
|
* Initialize Cuoral
|
|
@@ -1885,25 +1897,45 @@ class Cuoral {
|
|
|
1885
1897
|
setupMessageHandlers() {
|
|
1886
1898
|
// Handle start recording requests from widget
|
|
1887
1899
|
this.bridge.on(exports.CuoralMessageType.START_RECORDING, async () => {
|
|
1888
|
-
|
|
1900
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
1901
|
+
const success = await this.recorder.startRecording(undefined, false);
|
|
1902
|
+
if (success) {
|
|
1903
|
+
// Send RECORDING_STARTED back to widget
|
|
1904
|
+
this.bridge.sendToWidget({
|
|
1905
|
+
type: exports.CuoralMessageType.RECORDING_STARTED,
|
|
1906
|
+
payload: {
|
|
1907
|
+
timestamp: Date.now()
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
else {
|
|
1912
|
+
this.bridge.sendToWidget({
|
|
1913
|
+
type: exports.CuoralMessageType.RECORDING_ERROR,
|
|
1914
|
+
payload: {
|
|
1915
|
+
error: 'Failed to start recording'
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1889
1919
|
});
|
|
1890
1920
|
// Handle stop recording requests from widget
|
|
1891
1921
|
this.bridge.on(exports.CuoralMessageType.STOP_RECORDING, async () => {
|
|
1892
1922
|
const sessionId = localStorage.getItem('__x_loadID');
|
|
1893
1923
|
const customerId = localStorage.getItem('cuoralCustomerId');
|
|
1924
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
1894
1925
|
const result = await this.recorder.stopRecording({
|
|
1895
1926
|
autoUpload: true,
|
|
1896
1927
|
sessionId: sessionId || undefined,
|
|
1897
1928
|
publicKey: this.options.publicKey,
|
|
1898
1929
|
customerId: customerId || undefined,
|
|
1899
|
-
});
|
|
1930
|
+
}, false);
|
|
1900
1931
|
if (result && result.uploaded) {
|
|
1901
|
-
// Video was automatically uploaded,
|
|
1932
|
+
// Video was automatically uploaded, notify widget with RECORDING_STOPPED
|
|
1902
1933
|
this.bridge.sendToWidget({
|
|
1903
|
-
type: exports.CuoralMessageType.
|
|
1934
|
+
type: exports.CuoralMessageType.RECORDING_STOPPED,
|
|
1904
1935
|
payload: {
|
|
1905
1936
|
duration: result.duration,
|
|
1906
1937
|
uploaded: true,
|
|
1938
|
+
uploadedToBackend: true,
|
|
1907
1939
|
timestamp: Date.now()
|
|
1908
1940
|
}
|
|
1909
1941
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -59,7 +59,7 @@ export declare class CuoralRecorder {
|
|
|
59
59
|
/**
|
|
60
60
|
* Start recording with automatic permission handling
|
|
61
61
|
*/
|
|
62
|
-
startRecording(options?: RecordingOptions): Promise<boolean>;
|
|
62
|
+
startRecording(options?: RecordingOptions, sendMessages?: boolean): Promise<boolean>;
|
|
63
63
|
/**
|
|
64
64
|
* Stop recording
|
|
65
65
|
*/
|
|
@@ -68,7 +68,7 @@ export declare class CuoralRecorder {
|
|
|
68
68
|
sessionId?: string;
|
|
69
69
|
publicKey?: string;
|
|
70
70
|
customerId?: string;
|
|
71
|
-
}): Promise<{
|
|
71
|
+
}, sendMessages?: boolean): Promise<{
|
|
72
72
|
filePath?: string;
|
|
73
73
|
duration?: number;
|
|
74
74
|
uploaded?: boolean;
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE1E;;OAEG;IACH,aAAa,CAAC,OAAO,CAAC,EAAE;QACtB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QACV,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IAEH;;OAEG;IACH,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAE7C;;OAEG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAErE;;OAEG;IACH,oBAAoB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAExD;;OAEG;IACH,kBAAkB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;GAEG;AACH,QAAA,MAAM,YAAY,uBAAwD,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,kBAAkB,CAAC,CAAS;IAEpC;;OAEG;IACG,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE1E;;OAEG;IACH,aAAa,CAAC,OAAO,CAAC,EAAE;QACtB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QACV,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IAEH;;OAEG;IACH,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAE7C;;OAEG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAErE;;OAEG;IACH,oBAAoB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAExD;;OAEG;IACH,kBAAkB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;GAEG;AACH,QAAA,MAAM,YAAY,uBAAwD,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,kBAAkB,CAAC,CAAS;IAEpC;;OAEG;IACG,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,YAAY,GAAE,OAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IA+DhG;;OAEG;IACG,aAAa,CAAC,OAAO,CAAC,EAAE;QAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,EAAE,YAAY,GAAE,OAAc,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IA4D9G;;OAEG;IACG,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAqBjF;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAIzC;;OAEG;IACH,OAAO,CAAC,WAAW;CAKpB"}
|
package/dist/plugin.js
CHANGED
|
@@ -15,7 +15,7 @@ export class CuoralRecorder {
|
|
|
15
15
|
/**
|
|
16
16
|
* Start recording with automatic permission handling
|
|
17
17
|
*/
|
|
18
|
-
async startRecording(options) {
|
|
18
|
+
async startRecording(options, sendMessages = true) {
|
|
19
19
|
try {
|
|
20
20
|
// Check if already recording
|
|
21
21
|
if (this.isRecording) {
|
|
@@ -37,20 +37,24 @@ export class CuoralRecorder {
|
|
|
37
37
|
if (result.success) {
|
|
38
38
|
this.isRecording = true;
|
|
39
39
|
this.recordingStartTime = Date.now();
|
|
40
|
-
// Post message to widget
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
// Post message to widget only if enabled (disabled when called from widget handler)
|
|
41
|
+
if (sendMessages) {
|
|
42
|
+
this.postMessage({
|
|
43
|
+
type: CuoralMessageType.RECORDING_STARTED,
|
|
44
|
+
payload: { timestamp: this.recordingStartTime },
|
|
45
|
+
});
|
|
46
|
+
}
|
|
45
47
|
}
|
|
46
48
|
else {
|
|
47
49
|
// Recording failed - reset state and notify widget
|
|
48
50
|
this.isRecording = false;
|
|
49
51
|
this.recordingStartTime = undefined;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
if (sendMessages) {
|
|
53
|
+
this.postMessage({
|
|
54
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
55
|
+
payload: { error: 'Failed to start recording' },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
54
58
|
}
|
|
55
59
|
return result.success;
|
|
56
60
|
}
|
|
@@ -58,24 +62,28 @@ export class CuoralRecorder {
|
|
|
58
62
|
// Exception occurred - reset state and notify widget
|
|
59
63
|
this.isRecording = false;
|
|
60
64
|
this.recordingStartTime = undefined;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
if (sendMessages) {
|
|
66
|
+
this.postMessage({
|
|
67
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
68
|
+
payload: { error: error.message },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
65
71
|
return false;
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
/**
|
|
69
75
|
* Stop recording
|
|
70
76
|
*/
|
|
71
|
-
async stopRecording(options) {
|
|
77
|
+
async stopRecording(options, sendMessages = true) {
|
|
72
78
|
try {
|
|
73
79
|
if (!this.isRecording) {
|
|
74
80
|
// Send error message to widget so it can exit "stopping" state
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
if (sendMessages) {
|
|
82
|
+
this.postMessage({
|
|
83
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
84
|
+
payload: { error: 'Not recording' },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
79
87
|
return null;
|
|
80
88
|
}
|
|
81
89
|
const result = await CuoralPlugin.stopRecording(options);
|
|
@@ -84,23 +92,15 @@ export class CuoralRecorder {
|
|
|
84
92
|
const duration = this.recordingStartTime
|
|
85
93
|
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
86
94
|
: 0;
|
|
87
|
-
//
|
|
88
|
-
if (
|
|
89
|
-
this.postMessage({
|
|
90
|
-
type: CuoralMessageType.RECORDING_UPLOADED,
|
|
91
|
-
payload: {
|
|
92
|
-
duration: result.duration || duration,
|
|
93
|
-
uploaded: true
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// Post message to widget (old behavior)
|
|
95
|
+
// Send RECORDING_STOPPED message only if enabled
|
|
96
|
+
if (sendMessages) {
|
|
99
97
|
this.postMessage({
|
|
100
98
|
type: CuoralMessageType.RECORDING_STOPPED,
|
|
101
99
|
payload: {
|
|
102
100
|
filePath: result.filePath,
|
|
103
101
|
duration: result.duration || duration,
|
|
102
|
+
uploaded: result.uploaded,
|
|
103
|
+
uploadedToBackend: result.uploaded,
|
|
104
104
|
},
|
|
105
105
|
});
|
|
106
106
|
}
|
|
@@ -111,18 +111,22 @@ export class CuoralRecorder {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
// If result.success is false, send error to widget
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
if (sendMessages) {
|
|
115
|
+
this.postMessage({
|
|
116
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
117
|
+
payload: { error: 'Failed to stop recording' },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
118
120
|
return null;
|
|
119
121
|
}
|
|
120
122
|
catch (error) {
|
|
121
123
|
console.error('[Cuoral] Failed to stop recording:', error);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
if (sendMessages) {
|
|
125
|
+
this.postMessage({
|
|
126
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
127
|
+
payload: { error: error.message },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
126
130
|
return null;
|
|
127
131
|
}
|
|
128
132
|
}
|
|
@@ -110,10 +110,10 @@ public class CuoralPlugin: CAPPlugin {
|
|
|
110
110
|
do {
|
|
111
111
|
assetWriter = try AVAssetWriter(url: outputURL, fileType: .mp4)
|
|
112
112
|
|
|
113
|
-
//
|
|
114
|
-
//
|
|
113
|
+
// Optimized quality settings for screen recordings
|
|
114
|
+
// 1.5 Mbps bitrate = ~11MB per minute (~54MB for 5 min)
|
|
115
115
|
let compressionProperties: [String: Any] = [
|
|
116
|
-
AVVideoAverageBitRateKey:
|
|
116
|
+
AVVideoAverageBitRateKey: 1_500_000, // 1.5 Mbps
|
|
117
117
|
AVVideoMaxKeyFrameIntervalKey: 30,
|
|
118
118
|
AVVideoProfileLevelKey: AVVideoProfileLevelH264BaselineAutoLevel
|
|
119
119
|
]
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cuoral-ionic",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Cuoral Ionic Framework Library -
|
|
3
|
+
"version": "0.0.9",
|
|
4
|
+
"description": "Cuoral Ionic Framework Library - silent churn prevention platform for Ionic apps. Provides screen recording, user interaction capture, and support widget integration for enhanced customer support experiences.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.esm.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"assets",
|
|
13
13
|
"ios",
|
|
14
14
|
"android",
|
|
15
|
+
"CuoralIonic.podspec",
|
|
15
16
|
"README.md"
|
|
16
17
|
],
|
|
17
18
|
"scripts": {
|
package/src/bridge.ts
CHANGED
|
@@ -129,6 +129,7 @@ export class CuoralBridge {
|
|
|
129
129
|
window.addEventListener('message', (event: MessageEvent) => {
|
|
130
130
|
// Only process messages FROM the iframe
|
|
131
131
|
const widgetFrame = document.querySelector('iframe[src*="mobile.html"]') as HTMLIFrameElement;
|
|
132
|
+
|
|
132
133
|
if (widgetFrame && event.source === widgetFrame.contentWindow) {
|
|
133
134
|
this.widgetIframe = widgetFrame;
|
|
134
135
|
} else if (widgetFrame) {
|
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({
|
|
@@ -86,8 +90,15 @@ export class Cuoral {
|
|
|
86
90
|
|
|
87
91
|
this.recorder = new CuoralRecorder();
|
|
88
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
|
+
|
|
89
99
|
// Setup automatic message handlers
|
|
90
100
|
this.setupMessageHandlers();
|
|
101
|
+
console.log('[Cuoral] Constructor complete');
|
|
91
102
|
}
|
|
92
103
|
|
|
93
104
|
/**
|
|
@@ -530,9 +541,23 @@ export class Cuoral {
|
|
|
530
541
|
private setupMessageHandlers(): void {
|
|
531
542
|
// Handle start recording requests from widget
|
|
532
543
|
this.bridge.on(CuoralMessageType.START_RECORDING, async () => {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
+
});
|
|
536
561
|
}
|
|
537
562
|
});
|
|
538
563
|
|
|
@@ -541,20 +566,22 @@ export class Cuoral {
|
|
|
541
566
|
const sessionId = localStorage.getItem('__x_loadID');
|
|
542
567
|
const customerId = localStorage.getItem('cuoralCustomerId');
|
|
543
568
|
|
|
569
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
544
570
|
const result = await this.recorder.stopRecording({
|
|
545
571
|
autoUpload: true,
|
|
546
572
|
sessionId: sessionId || undefined,
|
|
547
573
|
publicKey: this.options.publicKey,
|
|
548
574
|
customerId: customerId || undefined,
|
|
549
|
-
});
|
|
575
|
+
}, false);
|
|
550
576
|
|
|
551
577
|
if (result && result.uploaded) {
|
|
552
|
-
// Video was automatically uploaded,
|
|
578
|
+
// Video was automatically uploaded, notify widget with RECORDING_STOPPED
|
|
553
579
|
this.bridge.sendToWidget({
|
|
554
|
-
type: CuoralMessageType.
|
|
580
|
+
type: CuoralMessageType.RECORDING_STOPPED,
|
|
555
581
|
payload: {
|
|
556
582
|
duration: result.duration,
|
|
557
583
|
uploaded: true,
|
|
584
|
+
uploadedToBackend: true,
|
|
558
585
|
timestamp: Date.now()
|
|
559
586
|
}
|
|
560
587
|
});
|