cuoral-ionic 0.0.7 → 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.
- 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 +1 -1
- 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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$4.class
CHANGED
|
Binary file
|
package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$5.class
CHANGED
|
Binary file
|
package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$6.class
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -409,7 +409,7 @@ public class CuoralPlugin extends Plugin {
|
|
|
409
409
|
if (autoUpload && !sessionId.isEmpty() && !publicKey.isEmpty()) {
|
|
410
410
|
final String filePath = videoFilePath;
|
|
411
411
|
final long finalDuration = duration;
|
|
412
|
-
|
|
412
|
+
|
|
413
413
|
uploadRecording(filePath, sessionId, publicKey, customerId, (int) finalDuration, new UploadCallback() {
|
|
414
414
|
@Override
|
|
415
415
|
public void onSuccess() {
|
|
@@ -551,7 +551,9 @@ public class CuoralPlugin extends Plugin {
|
|
|
551
551
|
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
|
|
552
552
|
mediaRecorder.setOutputFile(videoFilePath);
|
|
553
553
|
|
|
554
|
-
|
|
554
|
+
// Optimized bitrate for screen recordings - 1.5 Mbps = ~11MB per minute
|
|
555
|
+
// 5 minutes = ~54MB (good quality, small size)
|
|
556
|
+
int bitRate = 1500000; // 1.5 Mbps (matches iOS settings)
|
|
555
557
|
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
|
|
556
558
|
mediaRecorder.setVideoSize(metrics.widthPixels, metrics.heightPixels);
|
|
557
559
|
mediaRecorder.setVideoFrameRate(30);
|
|
@@ -596,14 +598,15 @@ public class CuoralPlugin extends Plugin {
|
|
|
596
598
|
// Upload callback interface
|
|
597
599
|
private interface UploadCallback {
|
|
598
600
|
void onSuccess();
|
|
601
|
+
|
|
599
602
|
void onFailure(String error);
|
|
600
603
|
}
|
|
601
604
|
|
|
602
605
|
/**
|
|
603
606
|
* Upload recording to Cuoral backend
|
|
604
607
|
*/
|
|
605
|
-
private void uploadRecording(String filePath, String sessionId, String publicKey,
|
|
606
|
-
|
|
608
|
+
private void uploadRecording(String filePath, String sessionId, String publicKey,
|
|
609
|
+
String customerId, int duration, UploadCallback callback) {
|
|
607
610
|
File videoFile = new File(filePath);
|
|
608
611
|
if (!videoFile.exists()) {
|
|
609
612
|
callback.onFailure("File not found");
|
|
@@ -627,14 +630,15 @@ public class CuoralPlugin extends Plugin {
|
|
|
627
630
|
|
|
628
631
|
private interface InitiateCallback {
|
|
629
632
|
void onSuccess(String recordId);
|
|
633
|
+
|
|
630
634
|
void onFailure(String error);
|
|
631
635
|
}
|
|
632
636
|
|
|
633
637
|
/**
|
|
634
638
|
* Step 1: Initiate recording session
|
|
635
639
|
*/
|
|
636
|
-
private void initiateRecording(String sessionId, String customerId, String publicKey,
|
|
637
|
-
|
|
640
|
+
private void initiateRecording(String sessionId, String customerId, String publicKey,
|
|
641
|
+
InitiateCallback callback) {
|
|
638
642
|
OkHttpClient client = new OkHttpClient();
|
|
639
643
|
|
|
640
644
|
try {
|
|
@@ -643,17 +647,16 @@ public class CuoralPlugin extends Plugin {
|
|
|
643
647
|
json.put("customer_id", customerId);
|
|
644
648
|
|
|
645
649
|
RequestBody body = RequestBody.create(
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
);
|
|
650
|
+
json.toString(),
|
|
651
|
+
MediaType.parse("application/json"));
|
|
649
652
|
|
|
650
653
|
Request request = new Request.Builder()
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
654
|
+
.url("https://api.cuoral.com/customer-intelligence/initiate/record")
|
|
655
|
+
.post(body)
|
|
656
|
+
.addHeader("Content-Type", "application/json")
|
|
657
|
+
.addHeader("Accept", "*/*")
|
|
658
|
+
.addHeader("x-org-id", publicKey)
|
|
659
|
+
.build();
|
|
657
660
|
|
|
658
661
|
client.newCall(request).enqueue(new Callback() {
|
|
659
662
|
@Override
|
|
@@ -672,7 +675,7 @@ public class CuoralPlugin extends Plugin {
|
|
|
672
675
|
String responseBody = response.body().string();
|
|
673
676
|
JSONObject json = new JSONObject(responseBody);
|
|
674
677
|
String status = json.getString("status");
|
|
675
|
-
|
|
678
|
+
|
|
676
679
|
if ("success".equals(status)) {
|
|
677
680
|
String recordId = json.getString("record_id");
|
|
678
681
|
callback.onSuccess(recordId);
|
|
@@ -692,29 +695,29 @@ public class CuoralPlugin extends Plugin {
|
|
|
692
695
|
/**
|
|
693
696
|
* Step 2: Upload video to the initiated recording
|
|
694
697
|
*/
|
|
695
|
-
private void uploadVideo(File videoFile, String recordId, String publicKey,
|
|
696
|
-
|
|
698
|
+
private void uploadVideo(File videoFile, String recordId, String publicKey,
|
|
699
|
+
String customerId, int duration, UploadCallback callback) {
|
|
697
700
|
OkHttpClient client = new OkHttpClient.Builder()
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
701
|
+
.connectTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
|
|
702
|
+
.writeTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
|
|
703
|
+
.readTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
|
|
704
|
+
.build();
|
|
702
705
|
|
|
703
706
|
RequestBody requestBody = new MultipartBody.Builder()
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
707
|
+
.setType(MultipartBody.FORM)
|
|
708
|
+
.addFormDataPart("record_id", recordId)
|
|
709
|
+
.addFormDataPart("console_error", "[]")
|
|
710
|
+
.addFormDataPart("api_response_log", "[]")
|
|
711
|
+
.addFormDataPart("page_view", "[]")
|
|
712
|
+
.addFormDataPart("record_media", "recording.mp4",
|
|
713
|
+
RequestBody.create(videoFile, MediaType.parse("video/mp4")))
|
|
714
|
+
.build();
|
|
712
715
|
|
|
713
716
|
Request request = new Request.Builder()
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
717
|
+
.url("https://api.cuoral.com/customer-intelligence/update/record")
|
|
718
|
+
.post(requestBody)
|
|
719
|
+
.addHeader("Accept", "*/*")
|
|
720
|
+
.build();
|
|
718
721
|
|
|
719
722
|
client.newCall(request).enqueue(new Callback() {
|
|
720
723
|
@Override
|
|
@@ -733,7 +736,7 @@ public class CuoralPlugin extends Plugin {
|
|
|
733
736
|
String responseBody = response.body().string();
|
|
734
737
|
JSONObject json = new JSONObject(responseBody);
|
|
735
738
|
String status = json.getString("status");
|
|
736
|
-
|
|
739
|
+
|
|
737
740
|
if ("success".equals(status)) {
|
|
738
741
|
callback.onSuccess();
|
|
739
742
|
} else {
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEzE;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAAoE;IAC3F,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,YAAY,CAAkC;gBAE1C,MAAM,EAAE,YAAY;IAKhC;;OAEG;IACI,UAAU,IAAI,IAAI;IAgBzB;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAoBjD;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAyCjD;;OAEG;IACI,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI;IAmB/E;;OAEG;IACH,OAAO,CAAC,oBAAoB;
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEzE;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAAoE;IAC3F,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,YAAY,CAAkC;gBAE1C,MAAM,EAAE,YAAY;IAKhC;;OAEG;IACI,UAAU,IAAI,IAAI;IAgBzB;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAoBjD;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAyCjD;;OAEG;IACI,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI;IAmB/E;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAsC5B;;OAEG;IACH,OAAO,CAAC,GAAG;IAMX;;OAEG;IACI,OAAO,IAAI,IAAI;CAKvB;AAGD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,CAAC,EAAE;YACP,eAAe,CAAC,EAAE;gBAChB,MAAM,CAAC,EAAE;oBACP,WAAW,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;iBACrC,CAAC;aACH,CAAC;SACH,CAAC;KACH;CACF"}
|
package/dist/cuoral.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cuoral.d.ts","sourceRoot":"","sources":["../src/cuoral.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAeD;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAqB;IAC1C,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAuC;IACpF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAwB;gBAElD,OAAO,EAAE,aAAa;
|
|
1
|
+
{"version":3,"file":"cuoral.d.ts","sourceRoot":"","sources":["../src/cuoral.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAeD;;GAEG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAqB;IAC1C,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAuC;IACpF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAwB;gBAElD,OAAO,EAAE,aAAa;IA4DlC;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBxC;;OAEG;YACW,sBAAsB;IA2CpC;;OAEG;YACW,yBAAyB;IAoCvC;;OAEG;IACI,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,IAAI;IAM1D;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,IAAI;IAM7E;;;;;OAKG;IACU,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0C7E;;;OAGG;IACU,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/C;;;;OAIG;IACU,aAAa,IAAI,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAC,GAAG,IAAI,CAAC;IAiBxG;;OAEG;IACI,SAAS,IAAI,IAAI;IASxB;;OAEG;IACI,UAAU,IAAI,IAAI;IAMzB;;OAEG;IACI,WAAW,IAAI,OAAO;IAI7B;;OAEG;IACI,YAAY,IAAI,MAAM;IAuB7B;;OAEG;IACU,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA6C1C;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;OAEG;IACI,OAAO,IAAI,IAAI;IActB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;OAEG;YACW,eAAe;IAkC7B;;OAEG;YACW,UAAU;IAmBxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAyG7B"}
|
package/dist/cuoral.js
CHANGED
|
@@ -9,6 +9,7 @@ import { Capacitor } from '@capacitor/core';
|
|
|
9
9
|
*/
|
|
10
10
|
export class Cuoral {
|
|
11
11
|
constructor(options) {
|
|
12
|
+
console.log('[Cuoral] Constructor called with options:', options);
|
|
12
13
|
// Check if running on a mobile platform
|
|
13
14
|
if (!Capacitor.isNativePlatform()) {
|
|
14
15
|
throw new Error('Cuoral Ionic library only works on native mobile platforms (iOS/Android). Web is not supported.');
|
|
@@ -18,6 +19,7 @@ export class Cuoral {
|
|
|
18
19
|
useModal: true,
|
|
19
20
|
...options
|
|
20
21
|
};
|
|
22
|
+
console.log('[Cuoral] Merged options:', this.options);
|
|
21
23
|
// Determine widget base URL
|
|
22
24
|
const baseUrl = options.widgetBaseUrl || Cuoral.PRODUCTION_WIDGET_URL;
|
|
23
25
|
const params = new URLSearchParams({
|
|
@@ -47,8 +49,14 @@ export class Cuoral {
|
|
|
47
49
|
debug: options.debug || false
|
|
48
50
|
});
|
|
49
51
|
this.recorder = new CuoralRecorder();
|
|
52
|
+
// Expose bridge on window for widget detection and debugging
|
|
53
|
+
window.CuoralCapacitorBridge = true;
|
|
54
|
+
window.__cuoralBridge = this.bridge; // For debugging
|
|
55
|
+
window.__cuoralRecorder = this.recorder; // For debugging
|
|
56
|
+
console.log('[Cuoral] Bridge and recorder created, exposed on window');
|
|
50
57
|
// Setup automatic message handlers
|
|
51
58
|
this.setupMessageHandlers();
|
|
59
|
+
console.log('[Cuoral] Constructor complete');
|
|
52
60
|
}
|
|
53
61
|
/**
|
|
54
62
|
* Initialize Cuoral
|
|
@@ -443,28 +451,45 @@ export class Cuoral {
|
|
|
443
451
|
setupMessageHandlers() {
|
|
444
452
|
// Handle start recording requests from widget
|
|
445
453
|
this.bridge.on(CuoralMessageType.START_RECORDING, async () => {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
454
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
455
|
+
const success = await this.recorder.startRecording(undefined, false);
|
|
456
|
+
if (success) {
|
|
457
|
+
// Send RECORDING_STARTED back to widget
|
|
458
|
+
this.bridge.sendToWidget({
|
|
459
|
+
type: CuoralMessageType.RECORDING_STARTED,
|
|
460
|
+
payload: {
|
|
461
|
+
timestamp: Date.now()
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
this.bridge.sendToWidget({
|
|
467
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
468
|
+
payload: {
|
|
469
|
+
error: 'Failed to start recording'
|
|
470
|
+
}
|
|
471
|
+
});
|
|
449
472
|
}
|
|
450
473
|
});
|
|
451
474
|
// Handle stop recording requests from widget
|
|
452
475
|
this.bridge.on(CuoralMessageType.STOP_RECORDING, async () => {
|
|
453
476
|
const sessionId = localStorage.getItem('__x_loadID');
|
|
454
477
|
const customerId = localStorage.getItem('cuoralCustomerId');
|
|
478
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
455
479
|
const result = await this.recorder.stopRecording({
|
|
456
480
|
autoUpload: true,
|
|
457
481
|
sessionId: sessionId || undefined,
|
|
458
482
|
publicKey: this.options.publicKey,
|
|
459
483
|
customerId: customerId || undefined,
|
|
460
|
-
});
|
|
484
|
+
}, false);
|
|
461
485
|
if (result && result.uploaded) {
|
|
462
|
-
// Video was automatically uploaded,
|
|
486
|
+
// Video was automatically uploaded, notify widget with RECORDING_STOPPED
|
|
463
487
|
this.bridge.sendToWidget({
|
|
464
|
-
type: CuoralMessageType.
|
|
488
|
+
type: CuoralMessageType.RECORDING_STOPPED,
|
|
465
489
|
payload: {
|
|
466
490
|
duration: result.duration,
|
|
467
491
|
uploaded: true,
|
|
492
|
+
uploadedToBackend: true,
|
|
468
493
|
timestamp: Date.now()
|
|
469
494
|
}
|
|
470
495
|
});
|
package/dist/index.esm.js
CHANGED
|
@@ -44,7 +44,7 @@ class CuoralRecorder {
|
|
|
44
44
|
/**
|
|
45
45
|
* Start recording with automatic permission handling
|
|
46
46
|
*/
|
|
47
|
-
async startRecording(options) {
|
|
47
|
+
async startRecording(options, sendMessages = true) {
|
|
48
48
|
try {
|
|
49
49
|
// Check if already recording
|
|
50
50
|
if (this.isRecording) {
|
|
@@ -66,20 +66,24 @@ class CuoralRecorder {
|
|
|
66
66
|
if (result.success) {
|
|
67
67
|
this.isRecording = true;
|
|
68
68
|
this.recordingStartTime = Date.now();
|
|
69
|
-
// Post message to widget
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
// Post message to widget only if enabled (disabled when called from widget handler)
|
|
70
|
+
if (sendMessages) {
|
|
71
|
+
this.postMessage({
|
|
72
|
+
type: CuoralMessageType.RECORDING_STARTED,
|
|
73
|
+
payload: { timestamp: this.recordingStartTime },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
74
76
|
}
|
|
75
77
|
else {
|
|
76
78
|
// Recording failed - reset state and notify widget
|
|
77
79
|
this.isRecording = false;
|
|
78
80
|
this.recordingStartTime = undefined;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
if (sendMessages) {
|
|
82
|
+
this.postMessage({
|
|
83
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
84
|
+
payload: { error: 'Failed to start recording' },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
83
87
|
}
|
|
84
88
|
return result.success;
|
|
85
89
|
}
|
|
@@ -87,24 +91,28 @@ class CuoralRecorder {
|
|
|
87
91
|
// Exception occurred - reset state and notify widget
|
|
88
92
|
this.isRecording = false;
|
|
89
93
|
this.recordingStartTime = undefined;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
if (sendMessages) {
|
|
95
|
+
this.postMessage({
|
|
96
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
97
|
+
payload: { error: error.message },
|
|
98
|
+
});
|
|
99
|
+
}
|
|
94
100
|
return false;
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
/**
|
|
98
104
|
* Stop recording
|
|
99
105
|
*/
|
|
100
|
-
async stopRecording(options) {
|
|
106
|
+
async stopRecording(options, sendMessages = true) {
|
|
101
107
|
try {
|
|
102
108
|
if (!this.isRecording) {
|
|
103
109
|
// Send error message to widget so it can exit "stopping" state
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
if (sendMessages) {
|
|
111
|
+
this.postMessage({
|
|
112
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
113
|
+
payload: { error: 'Not recording' },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
108
116
|
return null;
|
|
109
117
|
}
|
|
110
118
|
const result = await CuoralPlugin$1.stopRecording(options);
|
|
@@ -113,23 +121,15 @@ class CuoralRecorder {
|
|
|
113
121
|
const duration = this.recordingStartTime
|
|
114
122
|
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
115
123
|
: 0;
|
|
116
|
-
//
|
|
117
|
-
if (
|
|
118
|
-
this.postMessage({
|
|
119
|
-
type: CuoralMessageType.RECORDING_UPLOADED,
|
|
120
|
-
payload: {
|
|
121
|
-
duration: result.duration || duration,
|
|
122
|
-
uploaded: true
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
// Post message to widget (old behavior)
|
|
124
|
+
// Send RECORDING_STOPPED message only if enabled
|
|
125
|
+
if (sendMessages) {
|
|
128
126
|
this.postMessage({
|
|
129
127
|
type: CuoralMessageType.RECORDING_STOPPED,
|
|
130
128
|
payload: {
|
|
131
129
|
filePath: result.filePath,
|
|
132
130
|
duration: result.duration || duration,
|
|
131
|
+
uploaded: result.uploaded,
|
|
132
|
+
uploadedToBackend: result.uploaded,
|
|
133
133
|
},
|
|
134
134
|
});
|
|
135
135
|
}
|
|
@@ -140,18 +140,22 @@ class CuoralRecorder {
|
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
142
|
// If result.success is false, send error to widget
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
if (sendMessages) {
|
|
144
|
+
this.postMessage({
|
|
145
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
146
|
+
payload: { error: 'Failed to stop recording' },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
147
149
|
return null;
|
|
148
150
|
}
|
|
149
151
|
catch (error) {
|
|
150
152
|
console.error('[Cuoral] Failed to stop recording:', error);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
if (sendMessages) {
|
|
154
|
+
this.postMessage({
|
|
155
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
156
|
+
payload: { error: error.message },
|
|
157
|
+
});
|
|
158
|
+
}
|
|
155
159
|
return null;
|
|
156
160
|
}
|
|
157
161
|
}
|
|
@@ -1430,6 +1434,7 @@ class CuoralIntelligence {
|
|
|
1430
1434
|
*/
|
|
1431
1435
|
class Cuoral {
|
|
1432
1436
|
constructor(options) {
|
|
1437
|
+
console.log('[Cuoral] Constructor called with options:', options);
|
|
1433
1438
|
// Check if running on a mobile platform
|
|
1434
1439
|
if (!Capacitor.isNativePlatform()) {
|
|
1435
1440
|
throw new Error('Cuoral Ionic library only works on native mobile platforms (iOS/Android). Web is not supported.');
|
|
@@ -1439,6 +1444,7 @@ class Cuoral {
|
|
|
1439
1444
|
useModal: true,
|
|
1440
1445
|
...options
|
|
1441
1446
|
};
|
|
1447
|
+
console.log('[Cuoral] Merged options:', this.options);
|
|
1442
1448
|
// Determine widget base URL
|
|
1443
1449
|
const baseUrl = options.widgetBaseUrl || Cuoral.PRODUCTION_WIDGET_URL;
|
|
1444
1450
|
const params = new URLSearchParams({
|
|
@@ -1468,8 +1474,14 @@ class Cuoral {
|
|
|
1468
1474
|
debug: options.debug || false
|
|
1469
1475
|
});
|
|
1470
1476
|
this.recorder = new CuoralRecorder();
|
|
1477
|
+
// Expose bridge on window for widget detection and debugging
|
|
1478
|
+
window.CuoralCapacitorBridge = true;
|
|
1479
|
+
window.__cuoralBridge = this.bridge; // For debugging
|
|
1480
|
+
window.__cuoralRecorder = this.recorder; // For debugging
|
|
1481
|
+
console.log('[Cuoral] Bridge and recorder created, exposed on window');
|
|
1471
1482
|
// Setup automatic message handlers
|
|
1472
1483
|
this.setupMessageHandlers();
|
|
1484
|
+
console.log('[Cuoral] Constructor complete');
|
|
1473
1485
|
}
|
|
1474
1486
|
/**
|
|
1475
1487
|
* Initialize Cuoral
|
|
@@ -1864,25 +1876,45 @@ class Cuoral {
|
|
|
1864
1876
|
setupMessageHandlers() {
|
|
1865
1877
|
// Handle start recording requests from widget
|
|
1866
1878
|
this.bridge.on(CuoralMessageType.START_RECORDING, async () => {
|
|
1867
|
-
|
|
1879
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
1880
|
+
const success = await this.recorder.startRecording(undefined, false);
|
|
1881
|
+
if (success) {
|
|
1882
|
+
// Send RECORDING_STARTED back to widget
|
|
1883
|
+
this.bridge.sendToWidget({
|
|
1884
|
+
type: CuoralMessageType.RECORDING_STARTED,
|
|
1885
|
+
payload: {
|
|
1886
|
+
timestamp: Date.now()
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
else {
|
|
1891
|
+
this.bridge.sendToWidget({
|
|
1892
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
1893
|
+
payload: {
|
|
1894
|
+
error: 'Failed to start recording'
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1868
1898
|
});
|
|
1869
1899
|
// Handle stop recording requests from widget
|
|
1870
1900
|
this.bridge.on(CuoralMessageType.STOP_RECORDING, async () => {
|
|
1871
1901
|
const sessionId = localStorage.getItem('__x_loadID');
|
|
1872
1902
|
const customerId = localStorage.getItem('cuoralCustomerId');
|
|
1903
|
+
// Pass sendMessages: false to prevent duplicate messages
|
|
1873
1904
|
const result = await this.recorder.stopRecording({
|
|
1874
1905
|
autoUpload: true,
|
|
1875
1906
|
sessionId: sessionId || undefined,
|
|
1876
1907
|
publicKey: this.options.publicKey,
|
|
1877
1908
|
customerId: customerId || undefined,
|
|
1878
|
-
});
|
|
1909
|
+
}, false);
|
|
1879
1910
|
if (result && result.uploaded) {
|
|
1880
|
-
// Video was automatically uploaded,
|
|
1911
|
+
// Video was automatically uploaded, notify widget with RECORDING_STOPPED
|
|
1881
1912
|
this.bridge.sendToWidget({
|
|
1882
|
-
type: CuoralMessageType.
|
|
1913
|
+
type: CuoralMessageType.RECORDING_STOPPED,
|
|
1883
1914
|
payload: {
|
|
1884
1915
|
duration: result.duration,
|
|
1885
1916
|
uploaded: true,
|
|
1917
|
+
uploadedToBackend: true,
|
|
1886
1918
|
timestamp: Date.now()
|
|
1887
1919
|
}
|
|
1888
1920
|
});
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cuoral-ionic",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Cuoral Ionic Framework Library - Proactive customer success platform with support ticketing, customer intelligence, screen recording, and engagement tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
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
|
});
|
package/src/plugin.ts
CHANGED
|
@@ -70,7 +70,7 @@ export class CuoralRecorder {
|
|
|
70
70
|
/**
|
|
71
71
|
* Start recording with automatic permission handling
|
|
72
72
|
*/
|
|
73
|
-
async startRecording(options?: RecordingOptions): Promise<boolean> {
|
|
73
|
+
async startRecording(options?: RecordingOptions, sendMessages: boolean = true): Promise<boolean> {
|
|
74
74
|
try {
|
|
75
75
|
// Check if already recording
|
|
76
76
|
if (this.isRecording) {
|
|
@@ -97,20 +97,24 @@ export class CuoralRecorder {
|
|
|
97
97
|
this.isRecording = true;
|
|
98
98
|
this.recordingStartTime = Date.now();
|
|
99
99
|
|
|
100
|
-
// Post message to widget
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
+
}
|
|
105
107
|
} else {
|
|
106
108
|
// Recording failed - reset state and notify widget
|
|
107
109
|
this.isRecording = false;
|
|
108
110
|
this.recordingStartTime = undefined;
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
if (sendMessages) {
|
|
113
|
+
this.postMessage({
|
|
114
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
115
|
+
payload: { error: 'Failed to start recording' },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
return result.success;
|
|
@@ -119,10 +123,12 @@ export class CuoralRecorder {
|
|
|
119
123
|
this.isRecording = false;
|
|
120
124
|
this.recordingStartTime = undefined;
|
|
121
125
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
if (sendMessages) {
|
|
127
|
+
this.postMessage({
|
|
128
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
129
|
+
payload: { error: (error as Error).message },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
126
132
|
return false;
|
|
127
133
|
}
|
|
128
134
|
}
|
|
@@ -135,14 +141,16 @@ export class CuoralRecorder {
|
|
|
135
141
|
sessionId?: string;
|
|
136
142
|
publicKey?: string;
|
|
137
143
|
customerId?: string;
|
|
138
|
-
}): Promise<{ filePath?: string; duration?: number; uploaded?: boolean } | null> {
|
|
144
|
+
}, sendMessages: boolean = true): Promise<{ filePath?: string; duration?: number; uploaded?: boolean } | null> {
|
|
139
145
|
try {
|
|
140
146
|
if (!this.isRecording) {
|
|
141
147
|
// Send error message to widget so it can exit "stopping" state
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
148
|
+
if (sendMessages) {
|
|
149
|
+
this.postMessage({
|
|
150
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
151
|
+
payload: { error: 'Not recording' },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
146
154
|
return null;
|
|
147
155
|
}
|
|
148
156
|
|
|
@@ -153,22 +161,15 @@ export class CuoralRecorder {
|
|
|
153
161
|
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
154
162
|
: 0;
|
|
155
163
|
|
|
156
|
-
//
|
|
157
|
-
if (
|
|
158
|
-
this.postMessage({
|
|
159
|
-
type: CuoralMessageType.RECORDING_UPLOADED,
|
|
160
|
-
payload: {
|
|
161
|
-
duration: result.duration || duration,
|
|
162
|
-
uploaded: true
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
} else {
|
|
166
|
-
// Post message to widget (old behavior)
|
|
164
|
+
// Send RECORDING_STOPPED message only if enabled
|
|
165
|
+
if (sendMessages) {
|
|
167
166
|
this.postMessage({
|
|
168
167
|
type: CuoralMessageType.RECORDING_STOPPED,
|
|
169
168
|
payload: {
|
|
170
169
|
filePath: result.filePath,
|
|
171
170
|
duration: result.duration || duration,
|
|
171
|
+
uploaded: result.uploaded,
|
|
172
|
+
uploadedToBackend: result.uploaded,
|
|
172
173
|
},
|
|
173
174
|
});
|
|
174
175
|
}
|
|
@@ -181,17 +182,21 @@ export class CuoralRecorder {
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
// If result.success is false, send error to widget
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
if (sendMessages) {
|
|
186
|
+
this.postMessage({
|
|
187
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
188
|
+
payload: { error: 'Failed to stop recording' },
|
|
189
|
+
});
|
|
190
|
+
}
|
|
188
191
|
return null;
|
|
189
192
|
} catch (error) {
|
|
190
193
|
console.error('[Cuoral] Failed to stop recording:', error);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
if (sendMessages) {
|
|
195
|
+
this.postMessage({
|
|
196
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
197
|
+
payload: { error: (error as Error).message },
|
|
198
|
+
});
|
|
199
|
+
}
|
|
195
200
|
return null;
|
|
196
201
|
}
|
|
197
202
|
}
|