@capgo/camera-preview 8.3.6 → 8.3.8-beta.pr356.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/plugin.js CHANGED
@@ -54,6 +54,10 @@ var capacitorCapacitorCameraView = (function (exports, core) {
54
54
  this.orientationListenerBound = false;
55
55
  this.mediaRecorder = null;
56
56
  this.recordedChunks = [];
57
+ this.currentAspectRatio = '4:3';
58
+ this.barcodeDetector = null;
59
+ this.barcodeScannerTimer = null;
60
+ this.barcodeScannerBusy = false;
57
61
  }
58
62
  async checkPermissions(options) {
59
63
  const result = {
@@ -241,6 +245,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
241
245
  // Default to 4:3 if no aspect ratio or size specified
242
246
  const useDefaultAspectRatio = !options.aspectRatio && !options.width && !options.height;
243
247
  const effectiveAspectRatio = options.aspectRatio || (useDefaultAspectRatio ? '4:3' : null);
248
+ this.currentAspectRatio = effectiveAspectRatio || '4:3';
244
249
  if (options.width) {
245
250
  this.videoElement.width = options.width;
246
251
  this.videoElement.style.width = `${options.width}px`;
@@ -392,16 +397,24 @@ var capacitorCapacitorCameraView = (function (exports, core) {
392
397
  }
393
398
  else if (effectiveAspectRatio) {
394
399
  // Aspect ratio specified but no size
395
- const [widthRatio, heightRatio] = effectiveAspectRatio.split(':').map(Number);
396
- const targetRatio = widthRatio / heightRatio;
397
400
  const viewportWidth = window.innerWidth;
398
401
  const viewportHeight = window.innerHeight;
399
- let targetWidth = viewportWidth;
400
- let targetHeight = targetWidth / targetRatio;
401
- // If height exceeds viewport, fit to height instead
402
- if (targetHeight > viewportHeight) {
403
- targetHeight = viewportHeight;
404
- targetWidth = targetHeight * targetRatio;
402
+ let targetWidth;
403
+ let targetHeight;
404
+ if (effectiveAspectRatio === 'fill') {
405
+ targetWidth = containerWidth;
406
+ targetHeight = containerHeight;
407
+ }
408
+ else {
409
+ const [widthRatio, heightRatio] = effectiveAspectRatio.split(':').map(Number);
410
+ const targetRatio = widthRatio / heightRatio;
411
+ targetWidth = viewportWidth;
412
+ targetHeight = targetWidth / targetRatio;
413
+ // If height exceeds viewport, fit to height instead
414
+ if (targetHeight > viewportHeight) {
415
+ targetHeight = viewportHeight;
416
+ targetWidth = targetHeight * targetRatio;
417
+ }
405
418
  }
406
419
  this.videoElement.width = targetWidth;
407
420
  this.videoElement.height = targetHeight;
@@ -529,12 +542,23 @@ var capacitorCapacitorCameraView = (function (exports, core) {
529
542
  height: computedStyle.height,
530
543
  },
531
544
  });
532
- return {
545
+ const result = {
533
546
  width: Math.round(rect.width),
534
547
  height: Math.round(rect.height),
535
548
  x: Math.round(rect.x),
536
549
  y: Math.round(rect.y),
537
550
  };
551
+ const barcodeScannerOptions = this.getStartBarcodeScannerOptions(options);
552
+ if (barcodeScannerOptions) {
553
+ try {
554
+ await this.startBarcodeScanner(barcodeScannerOptions);
555
+ }
556
+ catch (error) {
557
+ await this.stop({ force: true });
558
+ throw error;
559
+ }
560
+ }
561
+ return result;
538
562
  }
539
563
  stopStream(stream) {
540
564
  if (stream) {
@@ -544,6 +568,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
544
568
  }
545
569
  }
546
570
  async stop(_options) {
571
+ await this.stopBarcodeScanner();
547
572
  const video = document.getElementById(DEFAULT_VIDEO_ID);
548
573
  if (video) {
549
574
  video.pause();
@@ -631,6 +656,116 @@ var capacitorCapacitorCameraView = (function (exports, core) {
631
656
  async captureSample(_options) {
632
657
  return this.capture(_options);
633
658
  }
659
+ async startBarcodeScanner(options) {
660
+ var _a, _b;
661
+ if (!this.isStarted || !((_a = this.videoElement) === null || _a === void 0 ? void 0 : _a.srcObject)) {
662
+ throw new Error('camera is not running');
663
+ }
664
+ const Detector = window.BarcodeDetector;
665
+ if (!Detector) {
666
+ throw new Error('BarcodeDetector API is not available in this browser');
667
+ }
668
+ await this.stopBarcodeScanner();
669
+ const formats = ((options === null || options === void 0 ? void 0 : options.formats) || [])
670
+ .map((format) => this.toWebBarcodeFormat(format))
671
+ .filter((format) => !!format);
672
+ this.barcodeDetector = new Detector(formats.length > 0 ? { formats } : undefined);
673
+ const detectionInterval = Math.max(100, (_b = options === null || options === void 0 ? void 0 : options.detectionInterval) !== null && _b !== void 0 ? _b : 500);
674
+ const detect = async () => {
675
+ var _a;
676
+ if (this.barcodeScannerBusy || !this.barcodeDetector || !((_a = this.videoElement) === null || _a === void 0 ? void 0 : _a.srcObject)) {
677
+ return;
678
+ }
679
+ this.barcodeScannerBusy = true;
680
+ try {
681
+ const results = (await this.barcodeDetector.detect(this.videoElement));
682
+ const barcodes = results
683
+ .map((result) => this.toBarcodeScanResult(result))
684
+ .filter((barcode) => !!barcode);
685
+ if (barcodes.length > 0) {
686
+ this.notifyListeners('barcodeScanned', { barcodes });
687
+ }
688
+ }
689
+ catch (error) {
690
+ const message = error instanceof Error ? error.message : String(error);
691
+ console.error('Barcode detection failed:', error);
692
+ this.notifyListeners('barcodeScanError', { message });
693
+ }
694
+ finally {
695
+ this.barcodeScannerBusy = false;
696
+ }
697
+ };
698
+ this.barcodeScannerTimer = window.setInterval(() => {
699
+ void detect();
700
+ }, detectionInterval);
701
+ void detect();
702
+ }
703
+ async stopBarcodeScanner() {
704
+ if (this.barcodeScannerTimer !== null) {
705
+ window.clearInterval(this.barcodeScannerTimer);
706
+ this.barcodeScannerTimer = null;
707
+ }
708
+ this.barcodeDetector = null;
709
+ this.barcodeScannerBusy = false;
710
+ }
711
+ getStartBarcodeScannerOptions(options) {
712
+ if (options.barcodeScanner === true) {
713
+ return {};
714
+ }
715
+ if (options.barcodeScanner && typeof options.barcodeScanner === 'object') {
716
+ return options.barcodeScanner;
717
+ }
718
+ return null;
719
+ }
720
+ toWebBarcodeFormat(format) {
721
+ switch (format) {
722
+ case 'aztec':
723
+ case 'codabar':
724
+ case 'code_39':
725
+ case 'code_93':
726
+ case 'code_128':
727
+ case 'data_matrix':
728
+ case 'ean_8':
729
+ case 'ean_13':
730
+ case 'itf':
731
+ case 'pdf417':
732
+ case 'qr_code':
733
+ case 'upc_a':
734
+ case 'upc_e':
735
+ return format;
736
+ default:
737
+ return null;
738
+ }
739
+ }
740
+ toBarcodeScanResult(result) {
741
+ if (!result.rawValue) {
742
+ return null;
743
+ }
744
+ return {
745
+ value: result.rawValue,
746
+ format: this.fromWebBarcodeFormat(result.format),
747
+ };
748
+ }
749
+ fromWebBarcodeFormat(format) {
750
+ switch (format) {
751
+ case 'aztec':
752
+ case 'codabar':
753
+ case 'code_39':
754
+ case 'code_93':
755
+ case 'code_128':
756
+ case 'data_matrix':
757
+ case 'ean_8':
758
+ case 'ean_13':
759
+ case 'itf':
760
+ case 'pdf417':
761
+ case 'qr_code':
762
+ case 'upc_a':
763
+ case 'upc_e':
764
+ return format;
765
+ default:
766
+ return 'unknown';
767
+ }
768
+ }
634
769
  async stopRecordVideo() {
635
770
  if (!this.mediaRecorder) {
636
771
  throw new Error('video recording is not running');
@@ -948,6 +1083,9 @@ var capacitorCapacitorCameraView = (function (exports, core) {
948
1083
  if (!video) {
949
1084
  throw new Error('camera is not running');
950
1085
  }
1086
+ if (this.currentAspectRatio === 'fill') {
1087
+ return { aspectRatio: 'fill' };
1088
+ }
951
1089
  const width = video.offsetWidth;
952
1090
  const height = video.offsetHeight;
953
1091
  if (width && height) {
@@ -964,10 +1102,32 @@ var capacitorCapacitorCameraView = (function (exports, core) {
964
1102
  return { aspectRatio: '4:3' };
965
1103
  }
966
1104
  async setAspectRatio(options) {
1105
+ var _a, _b;
967
1106
  const video = document.getElementById(DEFAULT_VIDEO_ID);
968
1107
  if (!video) {
969
1108
  throw new Error('camera is not running');
970
1109
  }
1110
+ this.currentAspectRatio = options.aspectRatio;
1111
+ if (options.aspectRatio === 'fill') {
1112
+ const parent = video.parentElement || document.body;
1113
+ const targetWidth = parent.clientWidth || window.innerWidth;
1114
+ const targetHeight = parent.clientHeight || window.innerHeight;
1115
+ const x = (_a = options.x) !== null && _a !== void 0 ? _a : 0;
1116
+ const y = (_b = options.y) !== null && _b !== void 0 ? _b : 0;
1117
+ video.style.width = `${targetWidth}px`;
1118
+ video.style.height = `${targetHeight}px`;
1119
+ video.style.left = `${x}px`;
1120
+ video.style.top = `${y}px`;
1121
+ video.style.position = 'absolute';
1122
+ const offsetX = targetWidth / 8;
1123
+ const offsetY = targetHeight / 8;
1124
+ return {
1125
+ width: Math.round(targetWidth),
1126
+ height: Math.round(targetHeight),
1127
+ x: Math.round(x + offsetX),
1128
+ y: Math.round(y + offsetY),
1129
+ };
1130
+ }
971
1131
  if (options.aspectRatio) {
972
1132
  const [widthRatio, heightRatio] = options.aspectRatio.split(':').map(Number);
973
1133
  // For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16