Compare commits

...

14 Commits

Author SHA1 Message Date
Lorenz Hilpert
a27a0c8b9c Zxing ask for camera permission 2022-05-31 15:55:04 +02:00
Lorenz Hilpert
acb76c1384 zxing scanner poc 2022-05-31 13:22:31 +02:00
Lorenz Hilpert
5882655862 Scanner performance update 2022-05-16 17:36:49 +02:00
Lorenz Hilpert
5b440da557 Scandit aktiviert 2022-05-16 16:11:29 +02:00
Lorenz Hilpert
be91a0f1b4 Scan performance test 2022-05-16 15:53:57 +02:00
Lorenz Hilpert
65e3d5d4f1 Update Gitignore 2022-05-16 15:28:02 +02:00
Lorenz Hilpert
a0e7614fa0 Remove Scandit Folder Content 2022-05-16 15:25:25 +02:00
Lorenz Hilpert
094c881e7f Scanner Performance Update 2022-05-16 15:20:10 +02:00
Lorenz Hilpert
d3cd6f415b Ipad 6 fix scandit 2022-04-19 20:39:58 +02:00
Lorenz Hilpert
e733396c63 Fix Engine Location 2022-04-19 19:08:02 +02:00
Lorenz Hilpert
e88795f96b Fix Reader 2022-04-19 15:56:35 +02:00
Lorenz Hilpert
fd276b6553 scandit typo 2022-04-19 15:21:21 +02:00
Lorenz Hilpert
22c3b057d7 scandit licence 2022-04-19 15:20:14 +02:00
Lorenz Hilpert
b7feea46f7 scandit implementation 2022-04-19 14:58:15 +02:00
304 changed files with 63162 additions and 20 deletions

2
.gitignore vendored
View File

@@ -46,4 +46,4 @@ testem.log
.DS_Store
Thumbs.db
libs/swagger/src/lib/*
libs/swagger/src/lib/*

View File

@@ -5,6 +5,7 @@
/helmvalues
/apps/swagger
/ng-swagger-gen
/apps/isa-app/src/assets
*.json
*.yml

View File

@@ -3845,6 +3845,6 @@
}
}
}
},
},
"defaultProject": "isa-app"
}

View File

@@ -18,7 +18,7 @@ export class NativeScanAdapter implements ScanAdapter {
isReady(): boolean {
// TODO: Fix Login Keycard Dauerschleife
return this.nativeContainerService.isUiWebview().isNative || this.nativeContainerService.isIpadMini6();
return this.nativeContainerService.isUiWebview().isNative;
// return false;
}

View File

@@ -1,14 +1,24 @@
import { NgModule } from '@angular/core';
import { DevScanAdapter } from './dev.scan-adapter';
import { NativeScanAdapter } from './native.scan-adapter';
import { ScanditModalModule } from './scandit-modal';
import { ScanditScanAdapter } from './scandit.scan-adapter';
import { SCAN_ADAPTER } from './tokens';
import { ZxingModalModule } from './zxing-modal';
import { ZxingScanAdapter } from './zxing.scan-adapter';
@NgModule({})
@NgModule({
imports: [ScanditModalModule, ZxingModalModule],
})
export class ScanAdapterModule {
static forRoot(dev?: boolean) {
return {
ngModule: ScanAdapterModule,
providers: [{ provide: SCAN_ADAPTER, useClass: NativeScanAdapter, multi: true }],
providers: [
{ provide: SCAN_ADAPTER, useClass: NativeScanAdapter, multi: true },
// { provide: SCAN_ADAPTER, useClass: ScanditScanAdapter, multi: true },
{ provide: SCAN_ADAPTER, useClass: ZxingScanAdapter, multi: true },
],
// Use for testing:
// providers: [{ provide: SCAN_ADAPTER, useClass: dev ? DevScanAdapter : NativeScanAdapter, multi: true }],
};

View File

@@ -0,0 +1,2 @@
export * from './scandit-modal.component';
export * from './scandit-modal.module';

View File

@@ -0,0 +1 @@
<div class="scanner-container" #scanContainer></div>

View File

@@ -0,0 +1,4 @@
.scanner-container {
@apply mt-8;
max-height: calc(100vh - 10rem);
}

View File

@@ -0,0 +1,86 @@
import { Component, ChangeDetectionStrategy, ViewChild, ElementRef, AfterViewInit, NgZone, Inject, OnDestroy } from '@angular/core';
import { UiMessageModalComponent, UiModalRef, UiModalService } from '@ui/modal';
import { Barcode, BarcodePicker, ScanSettings } from 'scandit-sdk';
@Component({
selector: 'scandit-modal',
templateUrl: 'scandit-modal.component.html',
styleUrls: ['scandit-modal.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ScanditModalComponent implements AfterViewInit, OnDestroy {
private _barcodePicker: BarcodePicker;
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
constructor(private _modalRef: UiModalRef, private readonly _zone: NgZone, private readonly _modal: UiModalService) {}
ngAfterViewInit(): void {
this._zone.runOutsideAngular(() => {
BarcodePicker.create(this.scanContainer.nativeElement, {
playSoundOnScan: true,
vibrateOnScan: true,
})
.then(async (picker) => {
this._barcodePicker = picker;
var scanSettings = new ScanSettings({
blurryRecognition: false,
enabledSymbologies: [
Barcode.Symbology.EAN8,
Barcode.Symbology.EAN13,
Barcode.Symbology.UPCA,
Barcode.Symbology.UPCE,
Barcode.Symbology.CODE128,
Barcode.Symbology.CODE39,
Barcode.Symbology.CODE93,
Barcode.Symbology.INTERLEAVED_2_OF_5,
Barcode.Symbology.QR,
],
codeDuplicateFilter: 1000,
});
picker.applyScanSettings(scanSettings);
picker.on('scan', (barcode) => {
this._zone.run(() => {
if (barcode.barcodes.length) {
this._modalRef.close(barcode.barcodes[0].data);
} else if (barcode.texts.length) {
this._modalRef.close(barcode.texts[0].value);
}
});
});
})
.catch((err) => {
this._zone.run(() => {
this.cancel();
this._modal
.open({
content: UiMessageModalComponent,
data: {
message: `
Scanner kann nicht aktiviert werden.
Bitte stellen Sie sicher, dass der zugriff auf die Kamera erlaubt ist.
`,
},
})
.afterClosed$.subscribe(() => {
this.cancel();
});
});
});
});
}
cancel() {
this._modalRef.close();
}
ngOnDestroy(): void {
this._zone.runOutsideAngular(() => {
this._barcodePicker?.destroy(true);
});
}
}

View File

@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ScanditModalComponent } from './scandit-modal.component';
@NgModule({
imports: [CommonModule],
exports: [ScanditModalComponent],
declarations: [ScanditModalComponent],
})
export class ScanditModalModule {}

View File

@@ -0,0 +1,49 @@
import { Injectable } from '@angular/core';
import { UiModalService } from '@ui/modal';
import { Observable } from 'rxjs';
import { ScanAdapter } from './scan-adapter';
import { configure } from 'scandit-sdk';
import { ScanditModalComponent } from './scandit-modal';
import { filter, map } from 'rxjs/operators';
import { Config } from '@core/config';
@Injectable()
export class ScanditScanAdapter implements ScanAdapter {
private _isReady = false;
constructor(private readonly _modal: UiModalService, private readonly _config: Config) {
this.configure();
}
private async configure() {
await configure(this._config.get('licence.scandit'), {
engineLocation: '/assets/scandit/',
});
this._isReady = true;
}
getName(): string {
return 'Scandit';
}
isPrimary(): boolean {
return false;
}
isReady(): boolean {
return this._isReady;
}
scan(): Observable<string> {
return this._modal
.open({
content: ScanditModalComponent,
})
.afterClosed$.pipe(
map((result) => result.data),
filter((result) => !!result)
);
}
}

View File

@@ -0,0 +1,2 @@
export * from './zxing-modal.component';
export * from './zxing-modal.module';

View File

@@ -0,0 +1,17 @@
<!-- <select>
<options [value]="dev.deviceId" *ngFor="let dev in devices$ | async">
{{ dev.label }}
</options>
</select> -->
<div class="device-container">
<button
[class.selected]="(selectedDevice$ | async) === dev.deviceId"
*ngFor="let dev of devices$ | async"
(click)="setSelectedDevice(dev.deviceId)"
>
{{ dev.label }}
</button>
</div>
<video class="scanner-container" #scanContainer></video>

View File

@@ -0,0 +1,17 @@
.scanner-container {
// @apply mt-8;
max-height: calc(100vh - 10rem);
width: 100%;
}
button {
@apply bg-white text-brand px-3 py-2;
&.selected {
@apply bg-brand text-white;
}
}
.device-container {
@apply flex flex-row items-center justify-center my-4;
}

View File

@@ -0,0 +1,104 @@
import { Component, ChangeDetectionStrategy, ViewChild, ElementRef, AfterViewInit, NgZone, Inject, OnDestroy, OnInit } from '@angular/core';
import { UiMessageModalComponent, UiModalRef, UiModalService } from '@ui/modal';
import { BarcodeFormat, DecodeHintType, BrowserMultiFormatReader } from '@zxing/library';
import { BehaviorSubject, from, ReplaySubject, Subject } from 'rxjs';
import { filter, takeUntil, tap } from 'rxjs/operators';
@Component({
selector: 'zxing-modal',
templateUrl: 'zxing-modal.component.html',
styleUrls: ['zxing-modal.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZxingModalComponent implements OnInit, OnDestroy {
private _reader: BrowserMultiFormatReader;
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
devices$ = new ReplaySubject<MediaDeviceInfo[]>();
selectedDevice$ = new BehaviorSubject<string>(null);
get selectedDevice() {
return this.selectedDevice$.value;
}
private _onDestroy$ = new Subject<void>();
constructor(private _modalRef: UiModalRef, private readonly _zone: NgZone, private readonly _modal: UiModalService) {}
async ngOnInit() {
try {
const mediaStream: MediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
mediaStream.getVideoTracks().forEach((track) => track.stop());
const hints = new Map<DecodeHintType, any>();
const formats = [
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.UPC_A,
BarcodeFormat.UPC_E,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_93,
BarcodeFormat.ITF,
BarcodeFormat.QR_CODE,
];
hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);
this._reader = new BrowserMultiFormatReader(hints, 1000);
from(this._reader.listVideoInputDevices()).subscribe((devices) => {
this.devices$.next(devices);
this.selectedDevice$.next(devices[0].deviceId);
});
this.selectedDevice$
.pipe(
takeUntil(this._onDestroy$),
filter((v) => !!v),
tap(() => {
this._reader?.reset();
})
)
.subscribe((device) => {
this._reader.decodeFromVideoDevice(device, this.scanContainer.nativeElement, (result) => {
if (result) {
this._modalRef.close(result.getText());
}
});
});
} catch (error) {
this.cancel();
this._modal
.open({
content: UiMessageModalComponent,
data: {
message: `
Scanner kann nicht aktiviert werden.
Bitte stellen Sie sicher, dass der zugriff auf die Kamera erlaubt ist.
`,
},
})
.afterClosed$.subscribe(() => {
this.cancel();
});
}
}
cancel() {
this._modalRef.close();
}
ngOnDestroy(): void {
this._onDestroy$.next();
this._reader?.reset();
}
setSelectedDevice(id: string) {
this.selectedDevice$.next(id);
}
}

View File

@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ZxingModalComponent } from './zxing-modal.component';
@NgModule({
imports: [CommonModule],
exports: [ZxingModalComponent],
declarations: [ZxingModalComponent],
})
export class ZxingModalModule {}

View File

@@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { UiModalService } from '@ui/modal';
import { Observable } from 'rxjs';
import { ScanAdapter } from './scan-adapter';
import { filter, map } from 'rxjs/operators';
import { Config } from '@core/config';
import { ZxingModalComponent } from './zxing-modal/zxing-modal.component';
@Injectable()
export class ZxingScanAdapter implements ScanAdapter {
private _isReady = true;
constructor(private readonly _modal: UiModalService, private readonly _config: Config) {}
getName(): string {
return 'Zxing';
}
isPrimary(): boolean {
return false;
}
isReady(): boolean {
return this._isReady;
}
scan(): Observable<string> {
return this._modal
.open({
content: ZxingModalComponent,
})
.afterClosed$.pipe(
map((result) => result.data),
filter((result) => !!result)
);
}
}

View File

@@ -18,11 +18,11 @@ export class IsAuthenticatedGuard implements CanActivate {
const authenticated = await this._authService.isAuthenticated();
if (!authenticated) {
const token = await this.scanAndGetToken();
// const token = await this.scanAndGetToken();
if (token) {
this._authService.setKeyCardToken(token);
}
// if (token) {
// this._authService.setKeyCardToken(token);
// }
this._authService.login();
}

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,197 @@
import "objectFitPolyfill";
import { BlurryRecognitionPreloader } from "./lib/blurryRecognitionPreloader";
import { DataCaptureLoader } from "./lib/dataCaptureLoader";
import { Logger } from "./lib/logger";
import "./styles/styles.scss";
/**
* @hidden
*/
declare global {
interface Window {
MediaStreamTrack?: {
getSources?(callback: (devices: MediaDeviceInfo[]) => void): void;
};
Worker: Function;
WebAssembly: object;
OffscreenCanvas: Function;
WebGLRenderingContext: Function;
objectFitPolyfill(elements?: HTMLElement | HTMLElement[]): void;
}
interface Navigator {
mozVibrate?: Navigator["vibrate"];
msVibrate?: Navigator["vibrate"];
webkitVibrate?: Navigator["vibrate"];
enumerateDevices?(): Promise<MediaDeviceInfo[]>;
}
}
export * from "./lib/barcodePicker/barcodePicker";
export * from "./lib/barcode";
export * from "./lib/barcodeEncodingRange";
export * from "./lib/browserCompatibility";
export * from "./lib/browserHelper";
export * from "./lib/camera";
export * from "./lib/cameraAccess";
export * from "./lib/cameraSettings";
export * from "./lib/customError";
export * from "./lib/imageSettings";
export * from "./lib/logger";
export * from "./lib/point";
export * from "./lib/quadrilateral";
export * from "./lib/parser";
export * from "./lib/parserField";
export * from "./lib/parserResult";
export * from "./lib/recognizedText";
export * from "./lib/scanResult";
export * from "./lib/scanner";
export * from "./lib/scanSettings";
export * from "./lib/singleImageModeSettings";
export * from "./lib/searchArea";
export * from "./lib/symbologySettings";
export * from "./lib/textRecognitionSettings";
export * from "./lib/workers/dataCaptureWorker";
/**
* @hidden
*/
export declare type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
/**
* @hidden
*/
export declare const deviceId: string;
/**
* @hidden
*/
export declare let userLicenseKey: string | undefined;
/**
* @hidden
*/
export declare let scanditDataCaptureLocation: string;
/**
* @hidden
*/
export declare let blurryRecognitionPreloader: BlurryRecognitionPreloader;
/**
* @hidden
*/
export declare let highEndBlurryRecognition: boolean;
/**
* @hidden
*/
export declare let textRecognition: boolean;
/**
* @hidden
*/
export declare let dataCaptureLoader: DataCaptureLoader;
/**
* @hidden
*
* Flag describing if configure() was called and if it could execute in its entirety.
*/
export declare let configurePhase: "unconfigured" | "started" | "done";
/**
* @hidden
*/
export declare let configurePromise: Promise<void> | undefined;
/**
* @hidden
*
* Mainly used by tests.
*/
export declare function resetConfigure(): void;
/**
* Initialize and configure the Scandit Barcode Scanner SDK library. This function must be called (once) before
* instantiating the main library components (`BarcodePicker` and `Scanner` objects) and returns a promise. In case this
* is called again after a successful call, parameters from subsequent calls are ignored and the same promise returned
* from the successful call will be returned.
*
* Depending on parameters and browser features, any of the following errors could be the rejected result of the
* returned promise:
* - `NoLicenseKeyError`
* - `UnsupportedBrowserError`
*
* The external external Scandit Data Capture library and data needed for barcode blurry recognition are preloaded
* asynchronously eagerly by default after library configuration to ensure the best performance. If needed this
* behaviour can be changed via the *preloadEngine* and *preloadBlurryRecognition* options.
*
* For optimal performance, it is recommended to call this function as soon as possible to ensure needed components are
* preloaded and initialized ahead of time.
*
* Camera access requests are done lazily only when needed by a [[BarcodePicker]] (or [[Scanner]]) object. You can also
* eagerly ask only for camera access permissions by calling the [[CameraAccess.getCameras]] function.
*
* Ideally, to make the scanning process faster, it is recommended depending on the use case to create in
* advance a (hidden and paused) [[BarcodePicker]] or [[Scanner]] object, to later show and unpause it when needed.
* Depending on the options this can also be used to correctly ask for camera access permissions whenever preferred.
*
* @param licenseKey The Scandit license key to be used by the library.
* @param logLevel <div class="tsd-signature-symbol">Default =&nbsp;Logger.Level.DEBUG</div>
* The console log level to be used by the library.
* @param engineLocation <div class="tsd-signature-symbol">Default =&nbsp;"/"</div>
* The location of the folder containing the external scandit-engine-sdk.min.js and
* scandit-engine-sdk.wasm files (external Scandit Data Capture library).
* By default they are retrieved from the root of the web application.
* Can be a full URL to folder or an absolute folder path.
* @param highQualityBlurryRecognition <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether to generate and use high quality barcode blurry recognition data, resulting in improved localization and
* scanning performance of extremely challenging 1D codes. If enabled, more time is spent to initialize (load or
* generate if needed) the needed data - at a time depending on the <em>preloadBlurryRecognition</em> option - and for
* the processing of each video frame.
*
* Enabling this option is not recommended unless really needed due to its high performance impact.
* @param loadTextRecognition <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether to load a version of the external Scandit Data Capture library providing support for text recognition (OCR).
* If enabled, a larger version of the library is loaded, unlocking [[ScanSettings]] options to enable text recognition
* in addition or as an alternative to barcode scanning. This also requires more time to load (download if needed,
* compile/instantiate WebAssembly code and initialize) the external Scandit Data Capture library, used by
* [[BarcodePicker]] and [[Scanner]] objects to perform scan operations, at a time depending on the
* <em>preloadEngine</em> option.
*
* In case barcode scanning is not needed, the <em>preloadBlurryRecognition</em> option should be disabled for better
* initialization performance.
* @param preloadBlurryRecognition <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to preload (load or generate if needed) data needed for barcode blurry recognition as soon as possible via a
* separate asynchronous WebWorker thread running the external Scandit Data Capture library. Data for all symbologies is
* generated over time.
*
* If enabled, any [[BarcodePicker]] or [[Scanner]] object will be able to start processing video frames much faster, as
* it won't need to generate barcode blurry recognition data lazily only when needed. If necessary, depending on given
* [[ScanSettings]] options and on readiness of the data, processing is also initially performed without blurry
* recognition until this data becomes available, at which point the new data will be loaded and used.
*
* If disabled, [[BarcodePicker]] or [[Scanner]] objects will load or generate barcode blurry recognition data lazily
* when needed to process the first frame, depending on given [[ScanSettings]] options, and will thus require more time
* the first time the library is actively used with the given active symbologies. As this needs to be done in the same
* WebWorker, the processing of the frame will then be blocked until the needed data is loaded or generated.
*
* Note that in either case the data for barcode blurry recognition will be cached for later successive uses of the
* library.
*
* Note that preloading does not trigger a device activation for licensing purposes.
* @param preloadEngine <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to preload (download if needed, compile/instantiate WebAssembly code and initialize) the external Scandit
* Data Capture library, used by [[BarcodePicker]] and [[Scanner]] objects to perform scan operations.
*
* If enabled, any [[BarcodePicker]] or [[Scanner]] object will be ready to start processing video frames much faster,
* as the needed external Scandit Data Capture library will already be in a partially or fully initialized state thanks
* to it being preloaded now.
*
* If disabled, [[BarcodePicker]] and [[Scanner]] objects will load the external Scandit Data Capture library on
* creation (if it wasn't already loaded before by a previously created object), and will thus require more time to be
* initialized and ready.
*
* Note that in either case the loaded external Scandit Data Capture library will be reused whenever possible for later
* successive uses of the library.
*
* Note that preloading does not trigger a device activation for licensing purposes.
*
* @returns A promise resolving when the library has been configured (preloading is done independently asynchronously).
*/
export declare function configure(licenseKey: string, { logLevel, engineLocation, highQualityBlurryRecognition, loadTextRecognition, preloadBlurryRecognition, preloadEngine, }?: {
logLevel?: Logger.Level;
engineLocation?: string;
highQualityBlurryRecognition?: boolean;
loadTextRecognition?: boolean;
preloadBlurryRecognition?: boolean;
preloadEngine?: boolean;
}): Promise<void>;

View File

@@ -0,0 +1,235 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.configure = exports.resetConfigure = exports.configurePromise = exports.configurePhase = exports.dataCaptureLoader = exports.textRecognition = exports.highEndBlurryRecognition = exports.blurryRecognitionPreloader = exports.scanditDataCaptureLocation = exports.userLicenseKey = exports.deviceId = void 0;
var tslib_1 = require("tslib");
require("objectFitPolyfill");
var blurryRecognitionPreloader_1 = require("./lib/blurryRecognitionPreloader");
var browserHelper_1 = require("./lib/browserHelper");
var customError_1 = require("./lib/customError");
var dataCaptureLoader_1 = require("./lib/dataCaptureLoader");
var logger_1 = require("./lib/logger");
var unsupportedBrowserError_1 = require("./lib/unsupportedBrowserError");
require("./styles/styles.scss");
tslib_1.__exportStar(require("./lib/barcodePicker/barcodePicker"), exports);
tslib_1.__exportStar(require("./lib/barcode"), exports);
tslib_1.__exportStar(require("./lib/barcodeEncodingRange"), exports);
tslib_1.__exportStar(require("./lib/browserCompatibility"), exports);
tslib_1.__exportStar(require("./lib/browserHelper"), exports);
tslib_1.__exportStar(require("./lib/camera"), exports);
tslib_1.__exportStar(require("./lib/cameraAccess"), exports);
tslib_1.__exportStar(require("./lib/cameraSettings"), exports);
tslib_1.__exportStar(require("./lib/customError"), exports);
tslib_1.__exportStar(require("./lib/imageSettings"), exports);
tslib_1.__exportStar(require("./lib/logger"), exports);
tslib_1.__exportStar(require("./lib/point"), exports);
tslib_1.__exportStar(require("./lib/quadrilateral"), exports);
tslib_1.__exportStar(require("./lib/parser"), exports);
tslib_1.__exportStar(require("./lib/parserField"), exports);
tslib_1.__exportStar(require("./lib/parserResult"), exports);
tslib_1.__exportStar(require("./lib/recognizedText"), exports);
tslib_1.__exportStar(require("./lib/scanResult"), exports);
tslib_1.__exportStar(require("./lib/scanner"), exports);
tslib_1.__exportStar(require("./lib/scanSettings"), exports);
tslib_1.__exportStar(require("./lib/singleImageModeSettings"), exports);
tslib_1.__exportStar(require("./lib/searchArea"), exports);
tslib_1.__exportStar(require("./lib/symbologySettings"), exports);
tslib_1.__exportStar(require("./lib/textRecognitionSettings"), exports);
tslib_1.__exportStar(require("./lib/workers/dataCaptureWorker"), exports);
var webComponent_1 = require("./webComponent");
webComponent_1.ScanditBarcodePicker.registerComponent();
/**
* @hidden
*/
exports.deviceId = browserHelper_1.BrowserHelper.getDeviceId();
/**
* @hidden
*
* Flag describing if configure() was called and if it could execute in its entirety.
*/
exports.configurePhase = "unconfigured";
/**
* @hidden
*
* Mainly used by tests.
*/
function resetConfigure() {
exports.configurePhase = "unconfigured";
}
exports.resetConfigure = resetConfigure;
/**
* Initialize and configure the Scandit Barcode Scanner SDK library. This function must be called (once) before
* instantiating the main library components (`BarcodePicker` and `Scanner` objects) and returns a promise. In case this
* is called again after a successful call, parameters from subsequent calls are ignored and the same promise returned
* from the successful call will be returned.
*
* Depending on parameters and browser features, any of the following errors could be the rejected result of the
* returned promise:
* - `NoLicenseKeyError`
* - `UnsupportedBrowserError`
*
* The external external Scandit Data Capture library and data needed for barcode blurry recognition are preloaded
* asynchronously eagerly by default after library configuration to ensure the best performance. If needed this
* behaviour can be changed via the *preloadEngine* and *preloadBlurryRecognition* options.
*
* For optimal performance, it is recommended to call this function as soon as possible to ensure needed components are
* preloaded and initialized ahead of time.
*
* Camera access requests are done lazily only when needed by a [[BarcodePicker]] (or [[Scanner]]) object. You can also
* eagerly ask only for camera access permissions by calling the [[CameraAccess.getCameras]] function.
*
* Ideally, to make the scanning process faster, it is recommended depending on the use case to create in
* advance a (hidden and paused) [[BarcodePicker]] or [[Scanner]] object, to later show and unpause it when needed.
* Depending on the options this can also be used to correctly ask for camera access permissions whenever preferred.
*
* @param licenseKey The Scandit license key to be used by the library.
* @param logLevel <div class="tsd-signature-symbol">Default =&nbsp;Logger.Level.DEBUG</div>
* The console log level to be used by the library.
* @param engineLocation <div class="tsd-signature-symbol">Default =&nbsp;"/"</div>
* The location of the folder containing the external scandit-engine-sdk.min.js and
* scandit-engine-sdk.wasm files (external Scandit Data Capture library).
* By default they are retrieved from the root of the web application.
* Can be a full URL to folder or an absolute folder path.
* @param highQualityBlurryRecognition <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether to generate and use high quality barcode blurry recognition data, resulting in improved localization and
* scanning performance of extremely challenging 1D codes. If enabled, more time is spent to initialize (load or
* generate if needed) the needed data - at a time depending on the <em>preloadBlurryRecognition</em> option - and for
* the processing of each video frame.
*
* Enabling this option is not recommended unless really needed due to its high performance impact.
* @param loadTextRecognition <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether to load a version of the external Scandit Data Capture library providing support for text recognition (OCR).
* If enabled, a larger version of the library is loaded, unlocking [[ScanSettings]] options to enable text recognition
* in addition or as an alternative to barcode scanning. This also requires more time to load (download if needed,
* compile/instantiate WebAssembly code and initialize) the external Scandit Data Capture library, used by
* [[BarcodePicker]] and [[Scanner]] objects to perform scan operations, at a time depending on the
* <em>preloadEngine</em> option.
*
* In case barcode scanning is not needed, the <em>preloadBlurryRecognition</em> option should be disabled for better
* initialization performance.
* @param preloadBlurryRecognition <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to preload (load or generate if needed) data needed for barcode blurry recognition as soon as possible via a
* separate asynchronous WebWorker thread running the external Scandit Data Capture library. Data for all symbologies is
* generated over time.
*
* If enabled, any [[BarcodePicker]] or [[Scanner]] object will be able to start processing video frames much faster, as
* it won't need to generate barcode blurry recognition data lazily only when needed. If necessary, depending on given
* [[ScanSettings]] options and on readiness of the data, processing is also initially performed without blurry
* recognition until this data becomes available, at which point the new data will be loaded and used.
*
* If disabled, [[BarcodePicker]] or [[Scanner]] objects will load or generate barcode blurry recognition data lazily
* when needed to process the first frame, depending on given [[ScanSettings]] options, and will thus require more time
* the first time the library is actively used with the given active symbologies. As this needs to be done in the same
* WebWorker, the processing of the frame will then be blocked until the needed data is loaded or generated.
*
* Note that in either case the data for barcode blurry recognition will be cached for later successive uses of the
* library.
*
* Note that preloading does not trigger a device activation for licensing purposes.
* @param preloadEngine <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to preload (download if needed, compile/instantiate WebAssembly code and initialize) the external Scandit
* Data Capture library, used by [[BarcodePicker]] and [[Scanner]] objects to perform scan operations.
*
* If enabled, any [[BarcodePicker]] or [[Scanner]] object will be ready to start processing video frames much faster,
* as the needed external Scandit Data Capture library will already be in a partially or fully initialized state thanks
* to it being preloaded now.
*
* If disabled, [[BarcodePicker]] and [[Scanner]] objects will load the external Scandit Data Capture library on
* creation (if it wasn't already loaded before by a previously created object), and will thus require more time to be
* initialized and ready.
*
* Note that in either case the loaded external Scandit Data Capture library will be reused whenever possible for later
* successive uses of the library.
*
* Note that preloading does not trigger a device activation for licensing purposes.
*
* @returns A promise resolving when the library has been configured (preloading is done independently asynchronously).
*/
function configure(licenseKey, _a) {
var _this = this;
var _b = _a === void 0 ? {} : _a, _c = _b.logLevel, logLevel = _c === void 0 ? logger_1.Logger.Level.DEBUG : _c, _d = _b.engineLocation, engineLocation = _d === void 0 ? "/" : _d, _e = _b.highQualityBlurryRecognition, highQualityBlurryRecognition = _e === void 0 ? false : _e, _f = _b.loadTextRecognition, loadTextRecognition = _f === void 0 ? false : _f, _g = _b.preloadBlurryRecognition, preloadBlurryRecognition = _g === void 0 ? true : _g, _h = _b.preloadEngine, preloadEngine = _h === void 0 ? true : _h;
if (exports.configurePhase !== "unconfigured" && exports.configurePromise != null) {
return exports.configurePromise;
}
logger_1.Logger.setLevel(logLevel);
exports.configurePromise = new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var browserCompatibility, browserName, osName, indexedDBStatusCheckInterval_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
logger_1.Logger.log(logger_1.Logger.Level.INFO, "Scandit Web SDK version: 5.11.0");
exports.configurePhase = "started";
browserCompatibility = browserHelper_1.BrowserHelper.checkBrowserCompatibility();
if (!browserCompatibility.fullSupport && !browserCompatibility.scannerSupport) {
return [2 /*return*/, reject(new unsupportedBrowserError_1.UnsupportedBrowserError(browserCompatibility))];
}
if (licenseKey == null || licenseKey.trim().length < 64) {
return [2 /*return*/, reject(new customError_1.CustomError({ name: "NoLicenseKeyError", message: "No license key provided" }))];
}
exports.userLicenseKey = licenseKey;
engineLocation += engineLocation.slice(-1) === "/" ? "" : "/";
if (/^https?:\/\//.test(engineLocation)) {
exports.scanditDataCaptureLocation = "".concat(engineLocation);
}
else {
engineLocation = engineLocation
.split("/")
.filter(function (s) {
return s.length > 0;
})
.join("/");
if (engineLocation === "") {
engineLocation = "/";
}
else {
engineLocation = "/".concat(engineLocation, "/");
}
if (location.protocol === "file:" || location.origin === "null") {
exports.scanditDataCaptureLocation = "".concat(location.href.split("/").slice(0, -1).join("/")).concat(engineLocation);
}
else {
exports.scanditDataCaptureLocation = "".concat(location.origin).concat(engineLocation);
}
}
browserName = browserHelper_1.BrowserHelper.userAgentInfo.getBrowser().name;
osName = browserHelper_1.BrowserHelper.userAgentInfo.getOS().name;
if (!((browserName == null || browserName.includes("Safari") || osName == null || osName === "iOS") &&
window.indexedDB != null &&
"databases" in indexedDB)) return [3 /*break*/, 2];
return [4 /*yield*/, new Promise(function (resolveCheck) {
function checkIndexedDBStatus() {
indexedDB
.databases()
.then(resolveCheck)
.catch(
/* istanbul ignore next */ function () {
// Ignored
});
}
indexedDBStatusCheckInterval_1 = window.setInterval(checkIndexedDBStatus, 50);
checkIndexedDBStatus();
}).then(function () { return clearInterval(indexedDBStatusCheckInterval_1); })];
case 1:
_a.sent();
_a.label = 2;
case 2:
exports.highEndBlurryRecognition = highQualityBlurryRecognition;
exports.textRecognition = loadTextRecognition;
return [4 /*yield*/, blurryRecognitionPreloader_1.BlurryRecognitionPreloader.create(preloadBlurryRecognition)];
case 3:
exports.blurryRecognitionPreloader = _a.sent();
return [4 /*yield*/, exports.blurryRecognitionPreloader.prepareBlurryTables()];
case 4:
_a.sent();
exports.dataCaptureLoader = new dataCaptureLoader_1.DataCaptureLoader(preloadEngine);
exports.configurePhase = "done";
return [2 /*return*/, resolve()];
}
});
}); }).catch(function (e) {
resetConfigure();
throw e;
});
return exports.configurePromise;
}
exports.configure = configure;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;AAAA,6BAA2B;AAE3B,+EAA8E;AAE9E,qDAAoD;AACpD,iDAAgD;AAChD,6DAA4D;AAC5D,uCAAsC;AACtC,yEAAwE;AAExE,gCAA8B;AAyB9B,4EAAkD;AAClD,wDAA8B;AAC9B,qEAA2C;AAC3C,qEAA2C;AAC3C,8DAAoC;AACpC,uDAA6B;AAC7B,6DAAmC;AACnC,+DAAqC;AACrC,4DAAkC;AAClC,8DAAoC;AACpC,uDAA6B;AAC7B,sDAA4B;AAC5B,8DAAoC;AACpC,uDAA6B;AAC7B,4DAAkC;AAClC,6DAAmC;AACnC,+DAAqC;AACrC,2DAAiC;AACjC,wDAA8B;AAC9B,6DAAmC;AACnC,wEAA8C;AAC9C,2DAAiC;AACjC,kEAAwC;AACxC,wEAA8C;AAE9C,0EAAgD;AAEhD,+CAAsD;AACtD,mCAAoB,CAAC,iBAAiB,EAAE,CAAC;AAOzC;;GAEG;AACU,QAAA,QAAQ,GAAW,6BAAa,CAAC,WAAW,EAAE,CAAC;AAyB5D;;;;GAIG;AACQ,QAAA,cAAc,GAAwC,cAAc,CAAC;AAOhF;;;;GAIG;AACH,SAAgB,cAAc;IAC5B,sBAAc,GAAG,cAAc,CAAC;AAClC,CAAC;AAFD,wCAEC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,SAAgB,SAAS,CACvB,UAAkB,EAClB,EAcM;IAhBR,iBAsGC;QApGC,qBAcI,EAAE,KAAA,EAbJ,gBAA6B,EAA7B,QAAQ,mBAAG,eAAM,CAAC,KAAK,CAAC,KAAK,KAAA,EAC7B,sBAAoB,EAApB,cAAc,mBAAG,GAAG,KAAA,EACpB,oCAAoC,EAApC,4BAA4B,mBAAG,KAAK,KAAA,EACpC,2BAA2B,EAA3B,mBAAmB,mBAAG,KAAK,KAAA,EAC3B,gCAA+B,EAA/B,wBAAwB,mBAAG,IAAI,KAAA,EAC/B,qBAAoB,EAApB,aAAa,mBAAG,IAAI,KAAA;IAUtB,IAAI,sBAAc,KAAK,cAAc,IAAI,wBAAgB,IAAI,IAAI,EAAE;QACjE,OAAO,wBAAgB,CAAC;KACzB;IAED,eAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE1B,wBAAgB,GAAG,IAAI,OAAO,CAAO,UAAO,OAAO,EAAE,MAAM;;;;;oBACzD,eAAM,CAAC,GAAG,CAAC,eAAM,CAAC,KAAK,CAAC,IAAI,EAAE,oCAAoC,CAAC,CAAC;oBACpE,sBAAc,GAAG,SAAS,CAAC;oBAErB,oBAAoB,GAAyB,6BAAa,CAAC,yBAAyB,EAAE,CAAC;oBAC7F,IAAI,CAAC,oBAAoB,CAAC,WAAW,IAAI,CAAC,oBAAoB,CAAC,cAAc,EAAE;wBAC7E,sBAAO,MAAM,CAAC,IAAI,iDAAuB,CAAC,oBAAoB,CAAC,CAAC,EAAC;qBAClE;oBAED,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE;wBACvD,sBAAO,MAAM,CAAC,IAAI,yBAAW,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC,EAAC;qBACnG;oBACD,sBAAc,GAAG,UAAU,CAAC;oBAE5B,cAAc,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;oBAC9D,IAAI,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE;wBACvC,kCAA0B,GAAG,UAAG,cAAc,CAAE,CAAC;qBAClD;yBAAM;wBACL,cAAc,GAAG,cAAc;6BAC5B,KAAK,CAAC,GAAG,CAAC;6BACV,MAAM,CAAC,UAAC,CAAC;4BACR,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;wBACtB,CAAC,CAAC;6BACD,IAAI,CAAC,GAAG,CAAC,CAAC;wBACb,IAAI,cAAc,KAAK,EAAE,EAAE;4BACzB,cAAc,GAAG,GAAG,CAAC;yBACtB;6BAAM;4BACL,cAAc,GAAG,WAAI,cAAc,MAAG,CAAC;yBACxC;wBACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,EAAE;4BAC/D,kCAA0B,GAAG,UAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAG,cAAc,CAAE,CAAC;yBACpG;6BAAM;4BACL,kCAA0B,GAAG,UAAG,QAAQ,CAAC,MAAM,SAAG,cAAc,CAAE,CAAC;yBACpE;qBACF;oBAIK,WAAW,GAAuB,6BAAa,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC;oBAChF,MAAM,GAAuB,6BAAa,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC;yBAE1E,CAAA,CAAC,WAAW,IAAI,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,KAAK,CAAC;wBAC7F,MAAM,CAAC,SAAS,IAAI,IAAI;wBACxB,WAAW,IAAI,SAAS,CAAA,EAFxB,wBAEwB;oBAGxB,qBAAM,IAAI,OAAO,CAAO,UAAC,YAAwB;4BAC/C,SAAS,oBAAoB;gCAC3B,SAAS;qCACN,SAAS,EAAE;qCACX,IAAI,CAAC,YAAY,CAAC;qCAClB,KAAK;gCACJ,0BAA0B,CAAC;oCACzB,UAAU;gCACZ,CAAC,CACF,CAAC;4BACN,CAAC;4BAED,8BAA4B,GAAG,MAAM,CAAC,WAAW,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;4BAC5E,oBAAoB,EAAE,CAAC;wBACzB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAM,OAAA,aAAa,CAAC,8BAA4B,CAAC,EAA3C,CAA2C,CAAC,EAAA;;oBAd1D,SAc0D,CAAC;;;oBAG7D,gCAAwB,GAAG,4BAA4B,CAAC;oBACxD,uBAAe,GAAG,mBAAmB,CAAC;oBACT,qBAAM,uDAA0B,CAAC,MAAM,CAAC,wBAAwB,CAAC,EAAA;;oBAA9F,kCAA0B,GAAG,SAAiE,CAAC;oBAC/F,qBAAM,kCAA0B,CAAC,mBAAmB,EAAE,EAAA;;oBAAtD,SAAsD,CAAC;oBACvD,yBAAiB,GAAG,IAAI,qCAAiB,CAAC,aAAa,CAAC,CAAC;oBAEzD,sBAAc,GAAG,MAAM,CAAC;oBAExB,sBAAO,OAAO,EAAE,EAAC;;;SAClB,CAAC,CAAC,KAAK,CAAC,UAAC,CAAC;QACT,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IAEH,OAAO,wBAAgB,CAAC;AAC1B,CAAC;AAtGD,8BAsGC"}

View File

@@ -0,0 +1,8 @@
export declare const beepSound: string;
export declare const scanditLogoImage: string;
export declare const laserActiveImage: string;
export declare const laserPausedImage: string;
export declare const cameraImage: string;
export declare const folderImage: string;
export declare const switchCameraImage: string;
export declare const toggleTorchImage: string;

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"base64assets.js","sourceRoot":"","sources":["../../../../src/lib/assets/base64assets.ts"],"names":[],"mappings":";;;AAAA,+DAA+D;AAClD,QAAA,SAAS;AACpB,2CAA2C;AAC3C,g7JAAg7J,CAAC;AACt6J,QAAA,gBAAgB;AAC3B,2CAA2C;AAC3C,4mIAA4mI,CAAC;AAClmI,QAAA,gBAAgB;AAC3B,2CAA2C;AAC3C,w2GAAw2G,CAAC;AAC91G,QAAA,gBAAgB;AAC3B,2CAA2C;AAC3C,w4FAAw4F,CAAC;AAC93F,QAAA,WAAW;AACtB,2CAA2C;AAC3C,8gCAA8gC,CAAC;AACpgC,QAAA,WAAW;AACtB,2CAA2C;AAC3C,09BAA09B,CAAC;AACh9B,QAAA,iBAAiB;AAC5B,2CAA2C;AAC3C,4oEAA4oE,CAAC;AACloE,QAAA,gBAAgB;AAC3B,2CAA2C;AAC3C,ooEAAooE,CAAC"}

View File

@@ -0,0 +1,146 @@
import { BarcodeEncodingRange } from "./barcodeEncodingRange";
import { Quadrilateral } from "./quadrilateral";
/**
* A barcode result.
*/
export interface Barcode {
/**
* The symbology type.
*/
readonly symbology: Barcode.Symbology;
/**
* The data encoded in the barcode interpreted as a UTF-8 string.
* If the raw data is not a valid UTF-8 string, this field will be an empty string; information from [[rawData]]
* and [[encodingArray]] can be used to reconstruct a string.
*/
readonly data: string;
/**
* The raw data encoded in the barcode, given as an array of bytes.
* To interpret this correctly you may have to use the information contained in [[encodingArray]].
*/
readonly rawData: Uint8Array;
/**
* The location of the barcode.
*/
readonly location: Quadrilateral;
/**
* Whether the barcode is part of a composite code.
*/
readonly compositeFlag: Barcode.CompositeFlag;
/**
* Whether the barcode is a GS1 data carrier.
*/
readonly isGs1DataCarrier: boolean;
/**
* The data encoding of the data in the barcode, given as an array of encoding ranges.
*/
readonly encodingArray: BarcodeEncodingRange[];
}
/**
* @hidden
*/
export declare type BarcodeWASMResult = {
readonly symbology: Barcode.Symbology;
readonly rawData: number[];
readonly location: number[][];
readonly compositeFlag: Barcode.CompositeFlag;
readonly isGs1DataCarrier: boolean;
readonly encodingArray: BarcodeEncodingRange[];
readonly isRecognized: boolean;
};
export declare namespace Barcode {
/**
* @hidden
*
* Create a [[Barcode]] object from a partial object returned by the external Scandit Data Capture library.
* The *rawData* and *data* fields are computed and stored.
*
* @param result The barcode result coming from the external Scandit Data Capture library.
* @returns The generated [[Barcode]] object.
*/
function createFromWASMResult(result: BarcodeWASMResult): Barcode;
/**
* Barcode symbology type.
*/
enum Symbology {
AZTEC = "aztec",
CODABAR = "codabar",
CODE11 = "code11",
CODE128 = "code128",
CODE25 = "code25",
CODE32 = "code32",
CODE39 = "code39",
CODE93 = "code93",
DATA_MATRIX = "data-matrix",
DOTCODE = "dotcode",
EAN13 = "ean13",
EAN8 = "ean8",
FIVE_DIGIT_ADD_ON = "five-digit-add-on",
GS1_DATABAR = "databar",
GS1_DATABAR_EXPANDED = "databar-expanded",
GS1_DATABAR_LIMITED = "databar-limited",
IATA_2_OF_5 = "iata2of5",
INTERLEAVED_2_OF_5 = "itf",
KIX = "kix",
LAPA4SC = "lapa4sc",
MATRIX_2_OF_5 = "matrix2of5",
MAXICODE = "maxicode",
MICRO_PDF417 = "micropdf417",
MICRO_QR = "microqr",
MSI_PLESSEY = "msi-plessey",
PDF417 = "pdf417",
QR = "qr",
RM4SCC = "rm4scc",
TWO_DIGIT_ADD_ON = "two-digit-add-on",
UPCA = "upca",
UPCE = "upce",
USPS_INTELLIGENT_MAIL = "usps-intelligent-mail"
}
/**
* Flags to hint that two codes form a composite code.
*/
enum CompositeFlag {
/**
* Code is not part of a composite code.
*/
NONE = 0,
/**
* Code could be part of a composite code. This flag is set by linear (1D) symbologies that have
* no composite flag support but can be part of a composite code like the EAN/UPC symbology family.
*/
UNKNOWN = 1,
/**
* Code is the linear component of a composite code. This flag can be set by GS1 DataBar or GS1-128 (Code 128).
*/
LINKED = 2,
/**
* Code is a GS1 Composite Code Type A (CC - A).This flag can be set by MicroPDF417 codes.
*/
GS1_A = 4,
/**
* Code is a GS1 Composite Code Type B (CC-B). This flag can be set by MicroPDF417 codes.
*/
GS1_B = 8,
/**
* Code is a GS1 Composite Code Type C (CC-C). This flag can be set by PDF417 codes.
*/
GS1_C = 16
}
namespace Symbology {
/**
* Get the humanized name of a symbology.
*
* @param symbology The symbology for which to retrieve the name.
* @returns The humanized name of the symbology.
*/
function toHumanizedName(symbology: Symbology): string;
/**
* Get the JSON key name of a symbology, used for JSON-formatted ScanSettings and the external Scandit Data Capture
* library.
*
* @param symbology The symbology for which to retrieve the name.
* @returns The json key name of the symbology.
*/
function toJSONName(symbology: Symbology): string;
}
}

View File

@@ -0,0 +1,211 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Barcode = void 0;
var Barcode;
(function (Barcode) {
/**
* @hidden
*
* Create a [[Barcode]] object from a partial object returned by the external Scandit Data Capture library.
* The *rawData* and *data* fields are computed and stored.
*
* @param result The barcode result coming from the external Scandit Data Capture library.
* @returns The generated [[Barcode]] object.
*/
function createFromWASMResult(result) {
var decodedData;
try {
decodedData = decodeURIComponent(escape(String.fromCharCode.apply(null, result.rawData)));
}
catch (_a) {
decodedData = "";
}
return {
symbology: result.symbology,
data: decodedData,
rawData: new Uint8Array(result.rawData),
location: {
topLeft: { x: result.location[0][0], y: result.location[0][1] },
topRight: { x: result.location[1][0], y: result.location[1][1] },
bottomRight: { x: result.location[2][0], y: result.location[2][1] },
bottomLeft: { x: result.location[3][0], y: result.location[3][1] },
},
compositeFlag: result.compositeFlag,
isGs1DataCarrier: result.isGs1DataCarrier,
encodingArray: result.encodingArray,
};
}
Barcode.createFromWASMResult = createFromWASMResult;
/**
* Barcode symbology type.
*/
var Symbology;
(function (Symbology) {
Symbology["AZTEC"] = "aztec";
Symbology["CODABAR"] = "codabar";
Symbology["CODE11"] = "code11";
Symbology["CODE128"] = "code128";
Symbology["CODE25"] = "code25";
Symbology["CODE32"] = "code32";
Symbology["CODE39"] = "code39";
Symbology["CODE93"] = "code93";
Symbology["DATA_MATRIX"] = "data-matrix";
Symbology["DOTCODE"] = "dotcode";
Symbology["EAN13"] = "ean13";
Symbology["EAN8"] = "ean8";
Symbology["FIVE_DIGIT_ADD_ON"] = "five-digit-add-on";
Symbology["GS1_DATABAR"] = "databar";
Symbology["GS1_DATABAR_EXPANDED"] = "databar-expanded";
Symbology["GS1_DATABAR_LIMITED"] = "databar-limited";
Symbology["IATA_2_OF_5"] = "iata2of5";
Symbology["INTERLEAVED_2_OF_5"] = "itf";
Symbology["KIX"] = "kix";
Symbology["LAPA4SC"] = "lapa4sc";
Symbology["MATRIX_2_OF_5"] = "matrix2of5";
Symbology["MAXICODE"] = "maxicode";
Symbology["MICRO_PDF417"] = "micropdf417";
Symbology["MICRO_QR"] = "microqr";
Symbology["MSI_PLESSEY"] = "msi-plessey";
Symbology["PDF417"] = "pdf417";
Symbology["QR"] = "qr";
Symbology["RM4SCC"] = "rm4scc";
Symbology["TWO_DIGIT_ADD_ON"] = "two-digit-add-on";
Symbology["UPCA"] = "upca";
Symbology["UPCE"] = "upce";
Symbology["USPS_INTELLIGENT_MAIL"] = "usps-intelligent-mail";
})(Symbology = Barcode.Symbology || (Barcode.Symbology = {}));
/**
* Flags to hint that two codes form a composite code.
*/
var CompositeFlag;
(function (CompositeFlag) {
/**
* Code is not part of a composite code.
*/
CompositeFlag[CompositeFlag["NONE"] = 0] = "NONE";
/**
* Code could be part of a composite code. This flag is set by linear (1D) symbologies that have
* no composite flag support but can be part of a composite code like the EAN/UPC symbology family.
*/
CompositeFlag[CompositeFlag["UNKNOWN"] = 1] = "UNKNOWN";
/**
* Code is the linear component of a composite code. This flag can be set by GS1 DataBar or GS1-128 (Code 128).
*/
CompositeFlag[CompositeFlag["LINKED"] = 2] = "LINKED";
/**
* Code is a GS1 Composite Code Type A (CC - A).This flag can be set by MicroPDF417 codes.
*/
CompositeFlag[CompositeFlag["GS1_A"] = 4] = "GS1_A";
/**
* Code is a GS1 Composite Code Type B (CC-B). This flag can be set by MicroPDF417 codes.
*/
CompositeFlag[CompositeFlag["GS1_B"] = 8] = "GS1_B";
/**
* Code is a GS1 Composite Code Type C (CC-C). This flag can be set by PDF417 codes.
*/
CompositeFlag[CompositeFlag["GS1_C"] = 16] = "GS1_C";
})(CompositeFlag = Barcode.CompositeFlag || (Barcode.CompositeFlag = {}));
// istanbul ignore next
(function (Symbology) {
/**
* @hidden
*/
// tslint:disable:no-unnecessary-qualifier
var humanizedSymbologyNames = new Map([
[Symbology.AZTEC, "Aztec"],
[Symbology.CODABAR, "Codabar"],
[Symbology.CODE11, "Code 11"],
[Symbology.CODE128, "Code 128"],
[Symbology.CODE25, "Code 25"],
[Symbology.CODE32, "Code 32"],
[Symbology.CODE39, "Code 39"],
[Symbology.CODE93, "Code 93"],
[Symbology.DATA_MATRIX, "Data Matrix"],
[Symbology.DOTCODE, "DotCode"],
[Symbology.EAN13, "EAN-13"],
[Symbology.EAN8, "EAN-8"],
[Symbology.FIVE_DIGIT_ADD_ON, "Five-Digit Add-On"],
[Symbology.GS1_DATABAR_EXPANDED, "GS1 DataBar Expanded"],
[Symbology.GS1_DATABAR_LIMITED, "GS1 DataBar Limited"],
[Symbology.GS1_DATABAR, "GS1 DataBar 14"],
[Symbology.IATA_2_OF_5, "IATA 2 of 5"],
[Symbology.INTERLEAVED_2_OF_5, "Interleaved 2 of 5"],
[Symbology.KIX, "KIX"],
[Symbology.LAPA4SC, "LAPA4SC"],
[Symbology.MATRIX_2_OF_5, "Matrix 2 of 5"],
[Symbology.MAXICODE, "MaxiCode"],
[Symbology.MICRO_PDF417, "MicroPDF417"],
[Symbology.MICRO_QR, "Micro QR"],
[Symbology.MSI_PLESSEY, "MSI-Plessey"],
[Symbology.PDF417, "PDF417"],
[Symbology.QR, "QR"],
[Symbology.RM4SCC, "RM4SCC"],
[Symbology.TWO_DIGIT_ADD_ON, "Two-Digit Add-On"],
[Symbology.UPCA, "UPC-A"],
[Symbology.UPCE, "UPC-E"],
[Symbology.USPS_INTELLIGENT_MAIL, "USPS Intelligent Mail"],
]);
/**
* @hidden
*/
var jsonSymbologyNames = new Map([
[Symbology.AZTEC, "aztec"],
[Symbology.CODABAR, "codabar"],
[Symbology.CODE11, "code11"],
[Symbology.CODE128, "code128"],
[Symbology.CODE25, "code25"],
[Symbology.CODE32, "code32"],
[Symbology.CODE39, "code39"],
[Symbology.CODE93, "code93"],
[Symbology.DATA_MATRIX, "data-matrix"],
[Symbology.DOTCODE, "dotcode"],
[Symbology.EAN13, "ean13"],
[Symbology.EAN8, "ean8"],
[Symbology.FIVE_DIGIT_ADD_ON, "five-digit-add-on"],
[Symbology.GS1_DATABAR_EXPANDED, "databar-expanded"],
[Symbology.GS1_DATABAR_LIMITED, "databar-limited"],
[Symbology.GS1_DATABAR, "databar"],
[Symbology.IATA_2_OF_5, "iata2of5"],
[Symbology.INTERLEAVED_2_OF_5, "itf"],
[Symbology.KIX, "kix"],
[Symbology.LAPA4SC, "lapa4sc"],
[Symbology.MATRIX_2_OF_5, "matrix2of5"],
[Symbology.MAXICODE, "maxicode"],
[Symbology.MICRO_PDF417, "micropdf417"],
[Symbology.MICRO_QR, "microqr"],
[Symbology.MSI_PLESSEY, "msi-plessey"],
[Symbology.PDF417, "pdf417"],
[Symbology.QR, "qr"],
[Symbology.RM4SCC, "rm4scc"],
[Symbology.TWO_DIGIT_ADD_ON, "two-digit-add-on"],
[Symbology.UPCA, "upca"],
[Symbology.UPCE, "upce"],
[Symbology.USPS_INTELLIGENT_MAIL, "usps-intelligent-mail"],
]);
// tslint:enable:no-unnecessary-qualifier
/**
* Get the humanized name of a symbology.
*
* @param symbology The symbology for which to retrieve the name.
* @returns The humanized name of the symbology.
*/
function toHumanizedName(symbology) {
var _a;
return (_a = humanizedSymbologyNames.get(symbology.toLowerCase())) !== null && _a !== void 0 ? _a : "Unknown";
}
Symbology.toHumanizedName = toHumanizedName;
/**
* Get the JSON key name of a symbology, used for JSON-formatted ScanSettings and the external Scandit Data Capture
* library.
*
* @param symbology The symbology for which to retrieve the name.
* @returns The json key name of the symbology.
*/
function toJSONName(symbology) {
var _a;
return (_a = jsonSymbologyNames.get(symbology.toLowerCase())) !== null && _a !== void 0 ? _a : "unknown";
}
Symbology.toJSONName = toJSONName;
})(Symbology = Barcode.Symbology || (Barcode.Symbology = {}));
})(Barcode = exports.Barcode || (exports.Barcode = {}));
//# sourceMappingURL=barcode.js.map

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
/**
* A character encoding of a range of bytes.
*/
export interface BarcodeEncodingRange {
/**
* The encoding name for the range (http://www.iana.org/assignments/character-sets/character-sets.xhtml).
*/
readonly encoding: string;
/**
* The index of the first element of the encoded data range.
*/
readonly startIndex: number;
/**
* The index after the last element of the encoded data range.
*/
readonly endIndex: number;
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=barcodeEncodingRange.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"barcodeEncodingRange.js","sourceRoot":"","sources":["../../../src/lib/barcodeEncodingRange.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,803 @@
import { ListenerFn } from "eventemitter3";
import { Camera } from "../camera";
import { CameraSettings } from "../cameraSettings";
import { Parser } from "../parser";
import { Scanner } from "../scanner";
import { ScanResult } from "../scanResult";
import { ScanSettings } from "../scanSettings";
import { SearchArea } from "../searchArea";
import { SingleImageModeSettings } from "../singleImageModeSettings";
/**
* @hidden
*/
declare type EventName = "ready" | "submitFrame" | "processFrame" | "scan" | "scanError" | "cameraAccessError";
/**
* A barcode picker element used to get and show camera input and perform scanning operations.
*
* The barcode picker will automatically fit and scale inside the given *originElement*.
*
* Each barcode picker internally contains a [[Scanner]] object with its own WebWorker thread running a
* separate copy of the external Scandit Data Capture library. To optimize loading times and performance it's
* recommended to reuse the same picker and to already create the picker in advance (hidden) and just
* display it when needed whenever possible.
*
* As the loading of the external Scandit Data Capture library can take some time, the picker always starts inactive
* (but showing GUI and video) and then activates, if not paused, as soon as the library is ready to scan.
* The [[on]] method targeting the [[ready]] event can be used to set up a listener function to be called when the
* library is loaded. The picker will be ready to start scanning when the library is fully loaded.
*
* By default the external Scandit Data Capture library is preloaded in order to reduce the initialization time as much
* as possible.
*
* The picker can also operate in Single Image Mode: letting the user click/tap to take a single image to be scanned
* via the camera (mobile) or a file select dialog (desktop). This is provided automatically as fallback by
* default when the OS/browser only supports part of the needed features and cannot provide direct access to the camera
* for video streaming and continuous scanning, or can also be forced on/off. This behaviour can be set up on creation
* via the *singleImageModeSettings* option. Note that in this mode some of the functions provided by the picker will
* have no effect.
*
* By default an alert is shown if an internal error during scanning is encountered which prevents the scanning
* procedure from continuing when running on a local IP address. As this uses the built-in [[scanError]] event
* functionality, if unwanted it can be disabled by calling [[removeAllListeners]] on the BarcodePicker
* instance (right after creation).
*
* In accordance with our license terms, the Scandit logo displayed in the bottom right corner of the barcode picker
* must be displayed and cannot be hidden by any method. Workarounds are not allowed.
*/
export declare class BarcodePicker {
private readonly cameraManager;
private readonly gui;
private readonly eventEmitter;
private readonly scanner;
private readonly beepSound;
private readonly vibrateFunction?;
private readonly scannerReadyEventListener;
private playSoundOnScan;
private vibrateOnScan;
private scanningPaused;
private latestVideoTimeProcessed;
private destroyed;
private isReadyToWork;
private cameraAccess;
private targetScanningFPS;
private averageProcessingTime;
private externalImageData;
private internalImageData?;
private constructor();
/**
* Fired when the external Scandit Data Capture library has been loaded and the barcode picker can thus start to scan
* barcodes or texts.
*
* @asMemberOf BarcodePicker
* @event
*/
static ready(): void;
/**
* Fired when a new frame is submitted to the external Scandit Data Capture library to be processed. As the frame is
* not processed yet, the [[ScanResult.barcodes]] property will always be empty (no results yet).
*
* @asMemberOf BarcodePicker
* @event
* @param scanResult The result of the scanning operation on the image.
*/
static submitFrame(scanResult: ScanResult): void;
/**
* Fired when a new frame is processed by the external Scandit Data Capture library. This event is fired on every
* frame, independently from the number of recognized barcodes or texts (can both be none). The returned barcodes and
* texts are affected by [[ScanSettings]]'s *codeDuplicateFilter* and [[TextRecognitionSettings]]'s
* *textDuplicateFilter* options.
*
* @asMemberOf BarcodePicker
* @event
* @param scanResult The result of the scanning operation on the image.
*/
static processFrame(scanResult: ScanResult): void;
/**
* Fired when new barcodes or texts are recognized in the image frame. The returned barcodes and texts are affected by
* [[ScanSettings]]'s *codeDuplicateFilter* and [[TextRecognitionSettings]]'s *textDuplicateFilter* options.
*
* @asMemberOf BarcodePicker
* @event
* @param scanResult The result of the scanning operation on the image.
*/
static scan(scanResult: ScanResult): void;
/**
* Fired when an error occurs during scanning initialization and execution. The barcode picker will be automatically
* paused when this happens.
*
* @asMemberOf BarcodePicker
* @event
* @param error The ScanditEngineError that was triggered.
*/
static scanError(error: Error): void;
/**
* Fired when an error occurs during camera access.
*
* @asMemberOf BarcodePicker
* @event
* @param error The Error that was triggered.
*/
static cameraAccessError(error: Error): void;
/**
* Create a [[BarcodePicker]] instance, creating the needed HTML in the given origin element.
* If the *accessCamera* option is enabled (active by default) and the picker is not in Single Image Mode,
* the available cameras are accessed and camera access permission is requested to the user if needed.
* This object expects that at least a camera is available. The active camera is accessed and kept active during the
* lifetime of the picker (also when hidden or scanning is paused), and is only released when [[destroy]] is called.
*
* It is required to having configured the library via [[configure]] before this object can be created.
*
* Depending on library configuration, parameters, device/browser features and user permissions for camera access, any
* of the following errors could be the rejected result of the returned promise:
* - `AbortError`
* - `LibraryNotConfiguredError`
* - `NoCameraAvailableError`
* - `NoOriginElementError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
* - `UnsupportedBrowserError`
*
* @param originElement The HTMLElement inside which all the necessary elements for the picker will be added.
* @param visible <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether the picker starts in a visible state.
* @param singleImageModeSettings <div class="tsd-signature-symbol">Default =&nbsp;</div>
* <pre><code>{
* desktop: {
* usageStrategy: SingleImageModeSettings.UsageStrategy.FALLBACK,
* informationElement: &lt;HTMLElement&gt;,
* buttonElement: &lt;SVGElement&gt;,
* containerStyle: { backgroundColor: "#333333" },
* informationStyle: { color: "#FFFFFF" },
* buttonStyle: { borderColor: "#FFFFFF", color: "#FFFFFF", fill: "#FFFFFF" }
* },
* mobile: {
* usageStrategy: SingleImageModeSettings.UsageStrategy.FALLBACK,
* informationElement: &lt;HTMLElement&gt;,
* buttonElement: &lt;SVGElement&gt;,
* containerStyle: { backgroundColor: "#333333" },
* informationStyle: { color: "#FFFFFF" },
* buttonStyle: { borderColor: "#FFFFFF", color: "#FFFFFF", fill: "#FFFFFF" }
* }
* }</code></pre>
* Settings for Single Image Mode: an alternative/fallback mode for a barcode picker to provide single camera
* pictures to be scanned instead of continuous camera video stream access. In Single Image Mode users click/tap to
* directly take a picture with the camera (mobile) or upload a file (desktop). Its usage depends on the given
* settings and the camera video stream features provided by the OS/browser.
* @param playSoundOnScan <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether a sound is played on barcode/text recognition (iOS requires user input).
* @param vibrateOnScan <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the device vibrates on barcode/text recognition (only Chrome & Firefox, requires user input).
* @param scanningPaused <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the picker starts in a paused scanning state.
* @param guiStyle <div class="tsd-signature-symbol">Default =&nbsp;GuiStyle.LASER</div>
* The GUI style for the picker.
* @param videoFit <div class="tsd-signature-symbol">Default =&nbsp;ObjectFit.CONTAIN</div>
* The fit type for the video element of the picker.
* @param cameraRecoveryText <div class="tsd-signature-symbol">Default =&nbsp;"Tap/click to resume scanning"</div>
* The text to display to indicate to the user a necessary tap/click action on the picker to recover camera access.
* @param laserArea <div class="tsd-signature-symbol">Default =&nbsp;undefined</div>
* The area of the laser displayed when the GUI style is set to <em>laser</em> (the laser will match the width and be
* vertically centered), by default the area will match the current [[ScanSettings]]'s <em>searchArea</em> option.
* @param viewfinderArea <div class="tsd-signature-symbol">Default =&nbsp;undefined</div>
* The area of the viewfinder displayed when the GUI style is set to <em>viewfinder</em>, by default the area will
* match the current [[ScanSettings]]'s <em>searchArea</em> option.
* @param enableCameraSwitcher <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to show a GUI button to switch between different cameras (when available).
* @param enableTorchToggle <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to show a GUI button to toggle device torch on/off (when available, only Chrome).
* @param enableTapToFocus <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to trigger a manual focus of the camera when clicking/tapping on the video (when available, only Chrome).
* @param enablePinchToZoom <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to control the zoom of the camera when doing a pinching gesture on the video (when available, only Chrome).
* @param accessCamera <div class="tsd-signature-symbol">Default =&nbsp;true</div>
* Whether to immediately access the camera (and requesting user permissions if needed) on picker creation.
* @param camera <div class="tsd-signature-symbol">Default =&nbsp;undefined</div>
* The initial camera to be used for video input, if not specified the camera automatically selected depending on
* the <em>cameraType</em> option will be used.
* @param cameraType <div class="tsd-signature-symbol">Default =&nbsp;Camera.Type.BACK</div>
* The preferred initial camera type (facing mode/direction) to be used for video input and Single Image Mode
* (when available), by default the back or only camera will be used. If the <em>camera</em> option is provided then
* <em>cameraType</em> is ignored.
* @param cameraSettings <div class="tsd-signature-symbol">Default =&nbsp;undefined</div>
* The camera options used when accessing the camera, by default <code>hd</code> resolution is used.
* @param scanner <div class="tsd-signature-symbol">Default =&nbsp;undefined</div>
* The scanner object responsible for scanning via the external Scandit Data Capture library
* (a new scanner will be created and initialized if not provided).
* @param scanSettings <div class="tsd-signature-symbol">Default =&nbsp;new ScanSettings()</div>
* The configuration object for scanning options to be applied to the scanner (all symbologies disabled by default).
* @param targetScanningFPS <div class="tsd-signature-symbol">Default =&nbsp;30</div>
* The target frames per second to be processed, the final speed is limited by the camera framerate (usually 30 FPS)
* and the frame processing time of the device. By setting this to lower numbers devices can save power by performing
* less work during scanning operations, depending on device speed (faster devices can "sleep" for longer periods).
* Must be a number bigger than 0.
* @returns A promise resolving to the created ready [[BarcodePicker]] object.
*/
static create(originElement: HTMLElement, { visible, singleImageModeSettings, playSoundOnScan, vibrateOnScan, scanningPaused, guiStyle, videoFit, cameraRecoveryText, laserArea, viewfinderArea, scanner, scanSettings, enableCameraSwitcher, enableTorchToggle, enableTapToFocus, enablePinchToZoom, accessCamera, camera, cameraType, cameraSettings, targetScanningFPS,
/**
* @hidden
*/
hideLogo, }?: {
visible?: boolean;
singleImageModeSettings?: SingleImageModeSettings;
playSoundOnScan?: boolean;
vibrateOnScan?: boolean;
scanningPaused?: boolean;
guiStyle?: BarcodePicker.GuiStyle;
videoFit?: BarcodePicker.ObjectFit;
cameraRecoveryText?: string;
laserArea?: SearchArea;
viewfinderArea?: SearchArea;
scanner?: Scanner;
scanSettings?: ScanSettings;
enableCameraSwitcher?: boolean;
enableTorchToggle?: boolean;
enableTapToFocus?: boolean;
enablePinchToZoom?: boolean;
accessCamera?: boolean;
camera?: Camera;
cameraType?: Camera.Type;
cameraSettings?: CameraSettings;
targetScanningFPS?: number;
/**
* @hidden
*/
hideLogo?: boolean;
}): Promise<BarcodePicker>;
/**
* Stop scanning and displaying video output, remove HTML elements added to the page,
* destroy the internal [[Scanner]] (by default) and destroy the barcode picker itself; ensuring complete cleanup.
*
* This method should be called after you don't plan to use the picker anymore,
* before the object is automatically cleaned up by JavaScript.
* The barcode picker must not be used in any way after this call.
*
* If the [[Scanner]] is or will be in use for other purposes, the relative option can be passed to prevent
* its destruction.
*
* @param destroyScanner Whether to destroy the internally used [[Scanner]] or not.
*/
destroy(destroyScanner?: boolean): void;
/**
* Apply a new set of scan settings to the internal scanner (replacing old settings).
*
* @param scanSettings The scan configuration object to be applied to the scanner.
* @returns The updated [[BarcodePicker]] object.
*/
applyScanSettings(scanSettings: ScanSettings): BarcodePicker;
/**
* @returns Whether the scanning is currently paused.
*/
isScanningPaused(): boolean;
/**
* Pause the recognition of codes/texts in the input image.
*
* By default video from the camera is still shown, if the *pauseCamera* option is enabled the camera stream
* is paused (camera access is fully interrupted) and will be resumed when calling [[resumeScanning]],
* [[setActiveCamera]], [[setCameraType]] or [[accessCamera]], possibly requesting user permissions if needed.
*
* In Single Image Mode the input for submitting a picture is disabled.
*
* @param pauseCamera Whether to also pause the camera stream.
* @returns The updated [[BarcodePicker]] object.
*/
pauseScanning(pauseCamera?: boolean): BarcodePicker;
/**
* Resume the recognition of codes/texts in the input image.
*
* If the camera stream was stopped when calling [[pauseScanning]], the camera stream is also resumed and
* user permissions are requested if needed to resume video input.
*
* In Single Image Mode the input for submitting a picture is enabled.
*
* @returns The updated [[BarcodePicker]] object.
*/
resumeScanning(): Promise<BarcodePicker>;
/**
* @returns The currently active camera.
*/
getActiveCamera(): Camera | undefined;
/**
* Select a camera to be used for video input, if no camera is passed, the default one (based on *cameraType*) is
* selected.
*
* If camera access is enabled, the camera is enabled and accessed. If not, the camera is stored and used for the
* future initial camera access.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `AbortError`
* - `NoCameraAvailableError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
*
* In Single Image Mode this method has no effect.
*
* @param camera The new camera to be used, by default the automatically detected back camera is used.
* @param cameraSettings The camera options used when accessing the camera, by default `hd` resolution is used.
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is set
* (and accessed, if camera access is currently enabled).
*/
setActiveCamera(camera?: Camera, cameraSettings?: CameraSettings): Promise<BarcodePicker>;
/**
* Select a camera to be used for video input by specifying the wanted camera type (facing mode/direction): the main
* camera detected for the given camera type will be used.
*
* If camera access is enabled, the camera is enabled and accessed. If not, the camera type is stored and used for the
* future initial camera access.
*
* If the target camera is already in use or no camera with the given type is found this method has no effect.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `AbortError`
* - `NoCameraAvailableError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
*
* @param cameraType The new camera type (facing mode/direction) to be used for video input and Single Image Mode
* (when available).
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is updated
* (and accessed, if camera access is currently enabled).
*/
setCameraType(cameraType: Camera.Type): Promise<BarcodePicker>;
/**
* Try to apply new settings to the currently used camera for video input,
* if no settings are passed the default ones are set.
*
* If camera access is enabled, the camera is updated and accessed with the new settings. If not, the camera settings
* are stored and used for the future initial camera access.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `AbortError`
* - `NoCameraAvailableError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
*
* In Single Image Mode this method has no effect.
*
* @param cameraSettings The new camera options used when accessing the camera, by default `hd` resolution is used.
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is updated
* (and accessed, if camera access is currently enabled).
*/
applyCameraSettings(cameraSettings?: CameraSettings): Promise<BarcodePicker>;
/**
* @returns Whether the picker is in a visible state or not.
*/
isVisible(): boolean;
/**
* Enable or disable picker visibility.
*
* Note that this does not affect camera access, frame processing or any other picker logic.
*
* @param visible Whether the picker is in a visible state or not.
* @returns The updated [[BarcodePicker]] object.
*/
setVisible(visible: boolean): BarcodePicker;
/**
* @returns Whether the currently selected camera's video is mirrored along the vertical axis.
*/
isMirrorImageEnabled(): boolean;
/**
* Enable or disable camera video mirroring along the vertical axis.
* By default front cameras are automatically mirrored.
* This setting is applied per camera and the method has no effect if no camera is currently selected.
*
* In Single Image Mode this method has no effect.
*
* @param enabled Whether the camera video is mirrored along the vertical axis.
* @returns The updated [[BarcodePicker]] object.
*/
setMirrorImageEnabled(enabled: boolean): BarcodePicker;
/**
* @returns Whether a sound should be played on barcode/text recognition (iOS requires user input).
* Note that the sound is played if there's at least a barcode or text not rejected via [[ScanResult.rejectCode]] or
* [[ScanResult.rejectText]].
*/
isPlaySoundOnScanEnabled(): boolean;
/**
* Enable or disable playing a sound on barcode/text recognition (iOS requires user input).
*
* The sound is played if there's at least a barcode or text not rejected via [[ScanResult.rejectCode]] or
* [[ScanResult.rejectText]].
*
* @param enabled Whether a sound should be played on barcode/text recognition.
* @returns The updated [[BarcodePicker]] object.
*/
setPlaySoundOnScanEnabled(enabled: boolean): BarcodePicker;
/**
* @returns Whether the device should vibrate on barcode/text recognition (only Chrome & Firefox, requires user
* input).
* Note that the vibration is triggered if there's at least a barcode or text not rejected via
* [[ScanResult.rejectCode]] or [[ScanResult.rejectText]].
*/
isVibrateOnScanEnabled(): boolean;
/**
* Enable or disable vibrating the device on barcode/text recognition (only Chrome & Firefox, requires user input).
*
* The vibration is triggered if there's at least a barcode or text not rejected via [[ScanResult.rejectCode]] or
* [[ScanResult.rejectText]].
*
* @param enabled Whether the device should vibrate on barcode/text recognition.
* @returns The updated [[BarcodePicker]] object.
*/
setVibrateOnScanEnabled(enabled: boolean): BarcodePicker;
/**
* @returns Whether a GUI button to switch between different cameras is shown (when available).
*/
isCameraSwitcherEnabled(): boolean;
/**
* Show or hide a GUI button to switch between different cameras (when available).
*
* In Single Image Mode this method has no effect.
*
* @param enabled Whether to show a GUI button to switch between different cameras.
* @returns The updated [[BarcodePicker]] object.
*/
setCameraSwitcherEnabled(enabled: boolean): BarcodePicker;
/**
* @returns Whether a GUI button to toggle device torch on/off is shown (when available, only Chrome).
*/
isTorchToggleEnabled(): boolean;
/**
* Show or hide a GUI button to toggle device torch on/off (when available, only Chrome).
*
* In Single Image Mode this method has no effect.
*
* @param enabled Whether to show a GUI button to toggle device torch on/off.
* @returns The updated [[BarcodePicker]] object.
*/
setTorchToggleEnabled(enabled: boolean): BarcodePicker;
/**
* @returns Whether manual camera focus when clicking/tapping on the video is enabled (when available, only Chrome).
*/
isTapToFocusEnabled(): boolean;
/**
* Enable or disable manual camera focus when clicking/tapping on the video (when available, only Chrome).
*
* In Single Image Mode this method has no effect.
*
* @param enabled Whether to enable manual camera focus when clicking/tapping on the video.
* @returns The updated [[BarcodePicker]] object.
*/
setTapToFocusEnabled(enabled: boolean): BarcodePicker;
/**
* @returns Whether camera zoom control via pinching gesture on the video is enabled (when available, only Chrome).
*/
isPinchToZoomEnabled(): boolean;
/**
* Enable or disable camera zoom control via pinching gesture on the video (when available, only Chrome).
*
* In Single Image Mode this method has no effect.
*
* @param enabled Whether to enable camera zoom control via pinching gesture on the video.
* @returns The updated [[BarcodePicker]] object.
*/
setPinchToZoomEnabled(enabled: boolean): BarcodePicker;
/**
* Enable or disable the torch/flashlight of the device (when available, only Chrome).
* Changing active camera or camera settings will cause the torch to become disabled.
*
* A button on the [[BarcodePicker]] GUI to let the user toggle this functionality can also be set
* on creation via the *enableTorchToggle* option (enabled by default, when available).
*
* In Single Image Mode this method has no effect.
*
* @param enabled Whether the torch should be enabled or disabled.
* @returns A promise resolving to the updated [[BarcodePicker]] object when the torch is enabled/disabled.
*/
setTorchEnabled(enabled: boolean): Promise<BarcodePicker>;
/**
* Set the zoom level of the device (when available, only Chrome).
* Changing active camera or camera settings will cause the zoom to be reset.
*
* In Single Image Mode this method has no effect.
*
* @param zoomPercentage The percentage of the max zoom (between 0 and 1).
* @returns The updated [[BarcodePicker]] object.
*/
setZoom(zoomPercentage: number): Promise<BarcodePicker>;
/**
* @returns Whether the barcode picker has loaded the external Scandit Data Capture library and is ready to scan.
*/
isReady(): boolean;
/**
* Add the listener function to the listeners array for an event.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: EventName, listener: ListenerFn, once?: boolean): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[ready]] event, fired when the external
* Scandit Data Capture library has been loaded and the barcode picker can thus start to scan barcodes or texts.
* If the library has already been loaded the listener is called immediately.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: "ready", listener: () => void): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[submitFrame]] event, fired when a new frame is submitted
* to the external Scandit Data Capture library to be processed. As the frame is not processed yet, the
* [[ScanResult.barcodes]] and [[ScanResult.texts]] properties will always be empty (no results yet).
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: "submitFrame", listener: (scanResult: ScanResult) => void, once?: boolean): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[processFrame]] event, fired when a new frame is
* processed. This event is fired on every frame, independently from the number of recognized barcodes or texts (can
* both be none). The returned barcodes and texts are affected by [[ScanSettings]]'s *codeDuplicateFilter* and
* [[TextRecognitionSettings]]'s *textDuplicateFilter* options.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: "processFrame", listener: (scanResult: ScanResult) => void, once?: boolean): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[scan]] event, fired when new barcodes or texts
* are recognized in the image frame. The returned barcodes and texts are affected by [[ScanSettings]]'s
* *codeDuplicateFilter* and [[TextRecognitionSettings]]'s *textDuplicateFilter* options.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with a [[ScanResult]] object.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: "scan", listener: (scanResult: ScanResult) => void, once?: boolean): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[scanError]] event, fired when an error occurs
* during scanning initialization and execution. The barcode picker will be automatically paused when this happens.
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with an `ScanditEngineError` object.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: "scanError", listener: (error: Error) => void, once?: boolean): BarcodePicker;
/**
* Add the listener function to the listeners array for the [[cameraAccessError]] event, fired when an error occurs
* during camera access..
*
* No checks are made to see if the listener has already been added.
* Multiple calls passing the same listener will result in the listener being added, and called, multiple times.
*
* @param eventName The name of the event to listen to.
* @param listener The listener function, which will be invoked with an `Error` object.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
on(eventName: "cameraAccessError", listener: (error: Error) => void, once?: boolean): BarcodePicker;
/**
* Remove the specified listener from the given event's listener array.
*
* @param eventName The name of the event from which to remove the listener.
* @param listener The listener function to be removed.
* @returns The updated [[BarcodePicker]] object.
*/
removeListener(eventName: EventName, listener: ListenerFn): BarcodePicker;
/**
* Remove all listeners from the given event's listener array.
*
* @param eventName The name of the event from which to remove all listeners.
* @returns The updated [[BarcodePicker]] object.
*/
removeAllListeners(eventName: EventName): BarcodePicker;
/**
* *See the [[on]] method.*
*
* @param eventName The name of the event to listen to.
* @param listener The listener function.
* @param once <div class="tsd-signature-symbol">Default =&nbsp;false</div>
* Whether the listener should just be triggered only once and then discarded.
* @returns The updated [[BarcodePicker]] object.
*/
addListener(eventName: EventName, listener: ListenerFn, once?: boolean): BarcodePicker;
/**
* Set the GUI style for the picker.
*
* In Single Image Mode this method has no effect.
*
* When the GUI style is set to *laser* or *viewfinder*, the GUI will flash on barcode/text recognition.
* Note that the GUI will flash if there's at least a barcode or text not rejected via [[ScanResult.rejectCode]] or
* [[ScanResult.rejectText]].
*
* @param guiStyle The new GUI style to be applied.
* @returns The updated [[BarcodePicker]] object.
*/
setGuiStyle(guiStyle: BarcodePicker.GuiStyle): BarcodePicker;
/**
* Set the fit type for the video element of the picker.
*
* If the "cover" type is selected the maximum available search area for barcode/text detection is (continuously)
* adjusted automatically according to the visible area of the picker.
*
* In Single Image Mode this method has no effect.
*
* @param objectFit The new fit type to be applied.
* @returns The updated [[BarcodePicker]] object.
*/
setVideoFit(objectFit: BarcodePicker.ObjectFit): BarcodePicker;
/**
* Access the currently set or default camera, requesting user permissions if needed.
* This method is meant to be used after the picker has been initialized with disabled camera access
* (*accessCamera*=false) or after [[pauseScanning]] has been called with the pause camera stream option.
* Calling this doesn't do anything if the camera is already being accessed.
*
* Depending on device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `AbortError`
* - `NoCameraAvailableError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
*
* In Single Image Mode this method has no effect.
*
* @returns A promise resolving to the updated [[BarcodePicker]] object when the camera is accessed.
*/
accessCamera(): Promise<BarcodePicker>;
/**
* Create a new parser object.
*
* @param dataFormat The format of the input data for the parser.
* @returns The newly created parser.
*/
createParserForFormat(dataFormat: Parser.DataFormat): Parser;
/**
* Reassign the barcode picker to a different HTML element.
*
* All the barcode picker elements inside the current origin element will be moved to the new given one.
*
* If an invalid element is given, a `NoOriginElementError` error is thrown.
*
* @param originElement The HTMLElement into which all the necessary elements for the picker will be moved.
* @returns The updated [[BarcodePicker]] object.
*/
reassignOriginElement(originElement: HTMLElement): BarcodePicker;
/**
* Set the target frames per second to be processed by the external Scandit Data Capture library.
*
* The final speed is limited by the camera framerate (usually 30 FPS) and the frame processing time of the device.
* By setting this to lower numbers devices can save power by performing less work during scanning operations,
* depending on device speed (faster devices can "sleep" for longer periods).
*
* In Single Image Mode this method has no effect.
*
* @param targetScanningFPS The target frames per second to be processed.
* Must be a number bigger than 0, by default set to 30.
* @returns The updated [[BarcodePicker]] object.
*/
setTargetScanningFPS(targetScanningFPS: number): BarcodePicker;
/**
* @returns The internally used initialized (and possibly configured) [[Scanner]] object instance.
*/
getScanner(): Scanner;
/**
* Clear the internal scanner session.
*
* This removes all recognized barcodes/texts from the scanner session and allows them to be scanned again in case a
* custom *codeDuplicateFilter* and/or *textDuplicateFilter* option was set in [[ScanSettings]] or
* [[TextRecognitionSettings]].
*
* @returns The updated [[BarcodePicker]] object.
*/
clearSession(): BarcodePicker;
/**
* Set the area of the laser displayed when the GUI style is set to *laser* (the laser will match the width and be
* vertically centered).
* Note that this functionality affects UI only and doesn't change the actual *searchArea* option set via
* [[ScanSettings]]. If no area is passed, the default automatic size behaviour is set, where the laser will match
* the current area of the image in which barcodes/texts are searched, controlled via the *searchArea* option in
* [[ScanSettings]].
*
* @param area The new search area, by default the area will match [[ScanSettings]]'s *searchArea* option.
* @returns The updated [[BarcodePicker]] object.
*/
setLaserArea(area?: SearchArea): BarcodePicker;
/**
* Set the area of the viewfinder displayed when the GUI style is set to *viewfinder*.
* Note that this functionality affects UI only and doesn't change the actual search area set via [[ScanSettings]].
* If no area is passed, the default automatic size behaviour is set, where the viewfinder will match the current area
* of the image in which barcodes/texts are searched, controlled via the *searchArea* option in [[ScanSettings]].
*
* @param area The new search area, by default the area will match the [[ScanSettings]]'s *searchArea*.
* @returns The updated [[BarcodePicker]] object.
*/
setViewfinderArea(area?: SearchArea): BarcodePicker;
/**
* @hidden
*
* Pause the camera stream (camera access is fully interrupted).
*
* @returns The updated [[BarcodePicker]] object.
*/
pauseCameraAccess(): BarcodePicker;
private triggerCameraAccessError;
private handleScanResult;
private scheduleVideoProcessing;
private scheduleNextVideoProcessing;
private processVideoFrame;
private videoProcessing;
private handleScannerReady;
}
export declare namespace BarcodePicker {
/**
* GUI style to be used by a barcode picker, used to hint barcode/text placement in the frame.
*/
enum GuiStyle {
/**
* No GUI is shown to indicate where the barcode/text should be placed.
* Be aware that the Scandit logo continues to be displayed as showing it is part of the license agreement.
*/
NONE = "none",
/**
* A laser line is shown.
*/
LASER = "laser",
/**
* A rectangular viewfinder with rounded corners is shown.
*/
VIEWFINDER = "viewfinder"
}
/**
* Fit type used to control the resizing (scale) of the barcode picker to fit in its container *originElement*.
*/
enum ObjectFit {
/**
* Scale to maintain aspect ratio while fitting within the *originElement*'s content box.
* Aspect ratio is preserved, so the barcode picker will be "letterboxed" if its aspect ratio
* does not match the aspect ratio of the box.
*/
CONTAIN = "contain",
/**
* Scale to maintain aspect ratio while filling the *originElement*'s entire content box.
* Aspect ratio is preserved, so the barcode picker will be clipped to fit if its aspect ratio
* does not match the aspect ratio of the box.
*/
COVER = "cover"
}
}
export {};

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,131 @@
import { Camera } from "../camera";
import { CameraSettings } from "../cameraSettings";
import { Scanner } from "../scanner";
import { GUI } from "./gui";
export declare enum MeteringMode {
CONTINUOUS = "continuous",
MANUAL = "manual",
NONE = "none",
SINGLE_SHOT = "single-shot"
}
export declare enum CameraResolutionConstraint {
ULTRA_HD = 0,
FULL_HD = 1,
HD = 2,
SD = 3,
NONE = 4
}
export interface ExtendedMediaTrackCapabilities extends MediaTrackCapabilities {
focusMode?: MeteringMode[];
torch?: boolean;
zoom?: {
max: number;
min: number;
step: number;
};
}
export interface ExtendedMediaTrackConstraintSet extends MediaTrackConstraintSet {
focusMode?: MeteringMode;
torch?: boolean;
zoom?: number;
}
/**
* A barcode picker utility class used to handle camera interaction.
*/
export declare class CameraManager {
private static readonly cameraAccessTimeoutMs;
private static readonly videoMetadataCheckTimeoutMs;
private static readonly videoMetadataCheckIntervalMs;
private static readonly getCapabilitiesTimeoutMs;
private static readonly autofocusIntervalMs;
private static readonly manualToAutofocusResumeTimeoutMs;
private static readonly manualFocusWaitTimeoutMs;
private static readonly noCameraErrorParameters;
private static readonly notReadableErrorParameters;
selectedCamera?: Camera;
activeCamera?: Camera;
activeCameraSettings?: CameraSettings;
private readonly scanner;
private readonly triggerCameraAccessError;
private readonly gui;
private readonly postStreamInitializationListener;
private readonly videoResizeListener;
private readonly videoTrackEndedListener;
private readonly videoTrackMuteListener;
private readonly triggerManualFocusListener;
private readonly triggerZoomStartListener;
private readonly triggerZoomMoveListener;
private cameraType;
private selectedCameraSettings?;
private mediaStream?;
private mediaTrackCapabilities?;
private cameraAccessTimeout;
private cameraAccessRejectCallback?;
private videoMetadataCheckInterval;
private getCapabilitiesTimeout;
private autofocusInterval;
private manualToAutofocusResumeTimeout;
private manualFocusWaitTimeout;
private cameraSwitcherEnabled;
private torchToggleEnabled;
private tapToFocusEnabled;
private pinchToZoomEnabled;
private pinchToZoomDistance?;
private pinchToZoomInitialZoom;
private torchEnabled;
private cameraInitializationPromise?;
private abortedCameraInitializationResolveCallback?;
private cameraSetupPromise?;
constructor(scanner: Scanner, triggerCameraAccessError: (error: Error) => void, gui: GUI);
setInteractionOptions(cameraSwitcherEnabled: boolean, torchToggleEnabled: boolean, tapToFocusEnabled: boolean, pinchToZoomEnabled: boolean): void;
isCameraSwitcherEnabled(): boolean;
setCameraSwitcherEnabled(enabled: boolean): Promise<void>;
isTorchToggleEnabled(): boolean;
setTorchToggleEnabled(enabled: boolean): void;
isTapToFocusEnabled(): boolean;
setTapToFocusEnabled(enabled: boolean): void;
isPinchToZoomEnabled(): boolean;
setPinchToZoomEnabled(enabled: boolean): void;
setInitialCameraType(cameraType: Camera.Type): void;
setCameraType(cameraType: Camera.Type): Promise<void>;
setSelectedCamera(camera?: Camera): void;
setSelectedCameraSettings(cameraSettings?: CameraSettings): void;
setupCameras(): Promise<void>;
stopStream(cameraInitializationFailure?: boolean): Promise<void>;
applyCameraSettings(cameraSettings?: CameraSettings): Promise<void>;
reinitializeCamera(): Promise<void>;
initializeCameraWithSettings(camera: Camera, cameraSettings?: CameraSettings): Promise<void>;
setTorchEnabled(enabled: boolean): Promise<void>;
toggleTorch(): Promise<void>;
setZoom(zoomPercentage: number, currentZoom?: number): Promise<void>;
private recoverStreamIfNeeded;
private setupCamerasAndStream;
private getInitialCameraResolutionConstraint;
private accessAutoselectedCamera;
private accessInitialCamera;
private updateActiveCameraCurrentResolution;
private postStreamInitialization;
private videoResizeHandle;
private videoTrackEndedRecovery;
private videoTrackMuteRecovery;
private triggerManualFocusForContinuous;
private triggerManualFocusForSingleShot;
private triggerManualFocus;
private triggerZoomStart;
private triggerZoomMove;
private storeStreamCapabilities;
private setupAutofocus;
private triggerAutoFocus;
private triggerFocusMode;
private enableTapToFocusListeners;
private enablePinchToZoomListeners;
private disableTapToFocusListeners;
private disablePinchToZoomListeners;
private initializeCameraAndCheckUpdatedSettings;
private handleCameraInitializationError;
private initializeCamera;
private setCameraAccessTimeout;
private checkCameraAccess;
private checkVideoMetadata;
private setupCameraStreamVideo;
}

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,29 @@
import { Camera } from "../camera";
import { CameraSettings } from "../cameraSettings";
import { CameraManager } from "./cameraManager";
/**
* A dummy barcode picker utility class used to (not) handle camera interaction.
*/
export declare class DummyCameraManager extends CameraManager {
setInteractionOptions(_1: boolean, _2: boolean, _3: boolean, _4: boolean): void;
isCameraSwitcherEnabled(): boolean;
setCameraSwitcherEnabled(_1: boolean): Promise<void>;
isTorchToggleEnabled(): boolean;
setTorchToggleEnabled(_1: boolean): void;
isTapToFocusEnabled(): boolean;
setTapToFocusEnabled(_1: boolean): void;
isPinchToZoomEnabled(): boolean;
setPinchToZoomEnabled(_1: boolean): void;
setInitialCameraType(_1?: Camera.Type): void;
setCameraType(_1?: Camera.Type): Promise<void>;
setSelectedCamera(_1?: Camera): void;
setSelectedCameraSettings(_1?: CameraSettings): void;
setupCameras(): Promise<void>;
stopStream(): Promise<void>;
applyCameraSettings(_1?: CameraSettings): Promise<void>;
reinitializeCamera(): Promise<void>;
initializeCameraWithSettings(_1: Camera, _2?: CameraSettings): Promise<void>;
setTorchEnabled(_1: boolean): Promise<void>;
toggleTorch(): Promise<void>;
setZoom(_1: number, _2?: number): Promise<void>;
}

View File

@@ -0,0 +1,121 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DummyCameraManager = void 0;
var tslib_1 = require("tslib");
var cameraManager_1 = require("./cameraManager");
/**
* A dummy barcode picker utility class used to (not) handle camera interaction.
*/
// istanbul ignore next
var DummyCameraManager = /** @class */ (function (_super) {
tslib_1.__extends(DummyCameraManager, _super);
function DummyCameraManager() {
return _super !== null && _super.apply(this, arguments) || this;
}
DummyCameraManager.prototype.setInteractionOptions = function (_1, _2, _3, _4) {
return;
};
DummyCameraManager.prototype.isCameraSwitcherEnabled = function () {
return false;
};
DummyCameraManager.prototype.setCameraSwitcherEnabled = function (_1) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.isTorchToggleEnabled = function () {
return false;
};
DummyCameraManager.prototype.setTorchToggleEnabled = function (_1) {
return;
};
DummyCameraManager.prototype.isTapToFocusEnabled = function () {
return false;
};
DummyCameraManager.prototype.setTapToFocusEnabled = function (_1) {
return;
};
DummyCameraManager.prototype.isPinchToZoomEnabled = function () {
return false;
};
DummyCameraManager.prototype.setPinchToZoomEnabled = function (_1) {
return;
};
DummyCameraManager.prototype.setInitialCameraType = function (_1) {
return;
};
DummyCameraManager.prototype.setCameraType = function (_1) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.setSelectedCamera = function (_1) {
return;
};
DummyCameraManager.prototype.setSelectedCameraSettings = function (_1) {
return;
};
DummyCameraManager.prototype.setupCameras = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.stopStream = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.applyCameraSettings = function (_1) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.reinitializeCamera = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.initializeCameraWithSettings = function (_1, _2) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.setTorchEnabled = function (_1) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.toggleTorch = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
DummyCameraManager.prototype.setZoom = function (_1, _2) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/];
});
});
};
return DummyCameraManager;
}(cameraManager_1.CameraManager));
exports.DummyCameraManager = DummyCameraManager;
//# sourceMappingURL=dummyCameraManager.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"dummyCameraManager.js","sourceRoot":"","sources":["../../../../src/lib/barcodePicker/dummyCameraManager.ts"],"names":[],"mappings":";;;;AAEA,iDAAgD;AAEhD;;GAEG;AACH,uBAAuB;AACvB;IAAwC,8CAAa;IAArD;;IAoFA,CAAC;IAnFQ,kDAAqB,GAA5B,UAA6B,EAAW,EAAE,EAAW,EAAE,EAAW,EAAE,EAAW;QAC7E,OAAO;IACT,CAAC;IAEM,oDAAuB,GAA9B;QACE,OAAO,KAAK,CAAC;IACf,CAAC;IAEY,qDAAwB,GAArC,UAAsC,EAAW;;;gBAC/C,sBAAO;;;KACR;IAEM,iDAAoB,GAA3B;QACE,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,kDAAqB,GAA5B,UAA6B,EAAW;QACtC,OAAO;IACT,CAAC;IAEM,gDAAmB,GAA1B;QACE,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,iDAAoB,GAA3B,UAA4B,EAAW;QACrC,OAAO;IACT,CAAC;IAEM,iDAAoB,GAA3B;QACE,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,kDAAqB,GAA5B,UAA6B,EAAW;QACtC,OAAO;IACT,CAAC;IAEM,iDAAoB,GAA3B,UAA4B,EAAgB;QAC1C,OAAO;IACT,CAAC;IAEY,0CAAa,GAA1B,UAA2B,EAAgB;;;gBACzC,sBAAO;;;KACR;IAEM,8CAAiB,GAAxB,UAAyB,EAAW;QAClC,OAAO;IACT,CAAC;IAEM,sDAAyB,GAAhC,UAAiC,EAAmB;QAClD,OAAO;IACT,CAAC;IAEY,yCAAY,GAAzB;;;gBACE,sBAAO;;;KACR;IAEY,uCAAU,GAAvB;;;gBACE,sBAAO;;;KACR;IAEY,gDAAmB,GAAhC,UAAiC,EAAmB;;;gBAClD,sBAAO;;;KACR;IAEY,+CAAkB,GAA/B;;;gBACE,sBAAO;;;KACR;IAEY,yDAA4B,GAAzC,UAA0C,EAAU,EAAE,EAAmB;;;gBACvE,sBAAO;;;KACR;IAEY,4CAAe,GAA5B,UAA6B,EAAW;;;gBACtC,sBAAO;;;KACR;IAEY,wCAAW,GAAxB;;;gBACE,sBAAO;;;KACR;IAEY,oCAAO,GAApB,UAAqB,EAAU,EAAE,EAAW;;;gBAC1C,sBAAO;;;KACR;IACH,yBAAC;AAAD,CAAC,AApFD,CAAwC,6BAAa,GAoFpD;AApFY,gDAAkB"}

View File

@@ -0,0 +1,133 @@
import { Camera } from "../camera";
import { Scanner } from "../scanner";
import { SearchArea } from "../searchArea";
import { SingleImageModePlatformSettings } from "../singleImageModeSettings";
import { BarcodePicker } from "./barcodePicker";
import { CameraManager } from "./cameraManager";
export declare class GUI {
static readonly grandParentElementClassName: string;
static readonly parentElementClassName: string;
static readonly hiddenClassName: string;
static readonly hiddenOpacityClassName: string;
static readonly videoElementClassName: string;
static readonly scanditLogoImageElementClassName: string;
static readonly laserContainerElementClassName: string;
static readonly viewfinderElementClassName: string;
static readonly cameraSwitcherElementClassName: string;
static readonly cameraRecoveryElementClassName: string;
static readonly torchTogglerElementClassName: string;
static readonly cameraUploadElementClassName: string;
static readonly flashColorClassName: string;
static readonly flashWhiteClassName: string;
static readonly flashInsetClassName: string;
static readonly opacityPulseClassName: string;
static readonly mirroredClassName: string;
static readonly pausedClassName: string;
readonly videoElement: HTMLVideoElement;
private readonly cameraSwitcherElement;
private readonly torchTogglerElement;
private readonly cameraRecoveryElement;
private readonly scanner;
private readonly singleImageModeEnabled;
private readonly singleImageModeSettings;
private readonly grandParentElement;
private readonly parentElement;
private readonly laserContainerElement;
private readonly laserActiveImageElement;
private readonly laserPausedImageElement;
private readonly viewfinderElement;
private readonly cameraUploadElement;
private readonly cameraUploadLabelElement;
private readonly cameraUploadInputElement;
private readonly cameraUploadProgressElement;
private readonly visibilityListener;
private readonly videoPauseListener;
private readonly videoResizeListener;
private readonly webGLContextLostListener;
private readonly newScanSettingsListener;
private readonly contextCreatedShowLogoListener;
private readonly contextCreatedActivateGUIListener;
private readonly resizeObserver;
private readonly cameraUploadCallback;
private readonly mirrorImageOverrides;
private contextWebGL?;
private context2d?;
private cameraManager?;
private originElement;
private scanningPaused;
private visible;
private guiStyle;
private videoFit;
private customLaserArea?;
private customViewfinderArea?;
private cameraUploadInProgress;
private cameraSwitchInProgress;
private dataCaptureContextCreated;
private isVideoElementDetached;
constructor(options: {
scanner: Scanner;
originElement: HTMLElement;
singleImageModeEnabled: boolean;
singleImageModeSettings: SingleImageModePlatformSettings;
scanningPaused: boolean;
visible: boolean;
guiStyle: BarcodePicker.GuiStyle;
videoFit: BarcodePicker.ObjectFit;
hideLogo: boolean;
cameraRecoveryText: string;
laserArea?: SearchArea;
viewfinderArea?: SearchArea;
cameraUploadCallback(): Promise<void>;
});
destroy(): void;
setCameraManager(cameraManager: CameraManager): void;
pauseScanning(): void;
resumeScanning(): void;
isVisible(): boolean;
setVisible(visible: boolean): void;
isMirrorImageEnabled(): boolean;
setMirrorImageEnabled(enabled: boolean, override: boolean): void;
setGuiStyle(guiStyle: BarcodePicker.GuiStyle): void;
setLaserArea(area?: SearchArea): void;
setViewfinderArea(area?: SearchArea): void;
setVideoFit(objectFit: BarcodePicker.ObjectFit): void;
reassignOriginElement(originElement: HTMLElement): void;
flashGUI(): void;
getImageData(imageData?: Uint8Array): Uint8Array | undefined;
getVideoCurrentTime(): number;
setCameraSwitcherVisible(visible: boolean): void;
isCameraRecoveryVisible(): boolean;
setCameraRecoveryVisible(visible: boolean): void;
setTorchTogglerVisible(visible: boolean): void;
playVideo(): void;
setVideoVisible(visible: boolean): void;
setCameraType(cameraType: Camera.Type): void;
private setCameraUploadGuiBusyScanning;
private setupContext;
private setupWebGL;
private setupVideoElement;
private setupCameraUploadGuiAssets;
private setupFullGuiAssets;
private flashLaser;
private flashViewfinder;
private resize;
private resizeCameraUpload;
private resizeVideo;
private checkAndRecoverPlayback;
private updateCameraUploadProgress;
private cameraUploadImageLoad;
private cameraUploadFileProcess;
private cameraUploadFile;
private cameraSwitcherListener;
private cameraRecoveryListener;
private setupCameraSwitcher;
private setupCameraRecovery;
private setupTorchToggler;
private showScanditLogo;
private activateGUI;
private handleNewScanSettings;
private handleVideoDisplay;
private handleVideoPause;
private handleVideoResize;
private handleWebGLContextLost;
}

View File

@@ -0,0 +1,893 @@
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GUI = void 0;
var tslib_1 = require("tslib");
var resize_observer_1 = require("@juggle/resize-observer");
/**
* @hidden
*/
// tslint:disable-next-line: variable-name no-any
var ResizeObserver = (_a = window.ResizeObserver) !== null && _a !== void 0 ? _a : resize_observer_1.ResizeObserver;
var base64assets_1 = require("../assets/base64assets");
var browserHelper_1 = require("../browserHelper");
var camera_1 = require("../camera");
var cameraAccess_1 = require("../cameraAccess");
var imageSettings_1 = require("../imageSettings");
var logger_1 = require("../logger");
var singleImageModeSettings_1 = require("../singleImageModeSettings");
var barcodePicker_1 = require("./barcodePicker");
var GUI = /** @class */ (function () {
function GUI(options) {
var _this = this;
// This property was introduced because testing videoElement.offsetParent in Safari
// proved to be unreliable.
this.isVideoElementDetached = false;
this.scanner = options.scanner;
this.originElement = options.originElement;
this.singleImageModeEnabled = options.singleImageModeEnabled;
this.singleImageModeSettings = options.singleImageModeSettings;
this.scanningPaused = options.scanningPaused;
this.cameraUploadCallback = options.cameraUploadCallback;
this.mirrorImageOverrides = new Map();
this.cameraUploadInProgress = false;
this.cameraSwitchInProgress = false;
this.dataCaptureContextCreated = false;
this.grandParentElement = document.createElement("div");
this.grandParentElement.className = GUI.grandParentElementClassName;
this.originElement.appendChild(this.grandParentElement);
this.parentElement = document.createElement("div");
this.parentElement.className = GUI.parentElementClassName;
this.grandParentElement.appendChild(this.parentElement);
this.videoElement = document.createElement("video");
this.cameraSwitcherElement = document.createElement("img");
this.torchTogglerElement = document.createElement("img");
this.laserContainerElement = document.createElement("div");
this.laserActiveImageElement = document.createElement("img");
this.laserPausedImageElement = document.createElement("img");
this.cameraRecoveryElement = document.createElement("div");
this.viewfinderElement = document.createElement("div");
var canvas = document.createElement("canvas");
this.webGLContextLostListener = this.handleWebGLContextLost.bind(this);
if (options.singleImageModeEnabled) {
this.context2d = canvas.getContext("2d");
this.cameraUploadElement = document.createElement("div");
this.cameraUploadLabelElement = document.createElement("label");
this.cameraUploadInputElement = document.createElement("input");
this.cameraUploadProgressElement = document.createElement("div");
this.setupCameraUploadGuiAssets();
this.guiStyle = barcodePicker_1.BarcodePicker.GuiStyle.NONE;
}
else {
this.setupContext(canvas);
this.setupVideoElement();
this.setupCameraSwitcher();
this.setupTorchToggler();
this.setupCameraRecovery(options.cameraRecoveryText);
this.setupFullGuiAssets();
this.setGuiStyle(options.guiStyle);
this.setVideoFit(options.videoFit);
this.setLaserArea(options.laserArea);
this.setViewfinderArea(options.viewfinderArea);
// Ensure the camera is accessed and the video plays again correctly when visibility changes
this.visibilityListener = this.checkAndRecoverPlayback.bind(this);
document.addEventListener("visibilitychange", this.visibilityListener);
this.newScanSettingsListener = this.handleNewScanSettings.bind(this);
this.scanner.on("newScanSettings", this.newScanSettingsListener);
this.handleNewScanSettings();
this.videoPauseListener = this.handleVideoPause.bind(this);
this.videoElement.addEventListener("pause", this.videoPauseListener);
this.videoResizeListener = this.handleVideoResize.bind(this);
this.videoElement.addEventListener("resize", this.videoResizeListener);
}
if (options.hideLogo) {
this.contextCreatedShowLogoListener = this.showScanditLogo.bind(this, options.hideLogo);
this.scanner.on("contextCreated", this.contextCreatedShowLogoListener);
}
else {
this.showScanditLogo(options.hideLogo);
}
this.contextCreatedActivateGUIListener = this.activateGUI.bind(this);
this.scanner.on("contextCreated", this.contextCreatedActivateGUIListener);
this.resize();
this.resizeObserver = new ResizeObserver(
/* istanbul ignore next */ function () {
_this.resize();
});
this.resizeObserver.observe(this.originElement);
this.setVisible(options.visible);
}
GUI.prototype.destroy = function () {
var _a, _b, _c, _d;
if (this.visibilityListener != null) {
document.removeEventListener("visibilitychange", this.visibilityListener);
}
if (this.newScanSettingsListener != null) {
this.scanner.removeListener("newScanSettings", this.newScanSettingsListener);
}
if (this.videoPauseListener != null) {
this.videoElement.removeEventListener("pause", this.videoPauseListener);
}
if (this.videoResizeListener != null) {
this.videoElement.removeEventListener("resize", this.videoResizeListener);
}
if (this.contextCreatedShowLogoListener != null) {
this.scanner.removeListener("contextCreated", this.contextCreatedShowLogoListener);
}
if (this.contextCreatedActivateGUIListener != null) {
this.scanner.removeListener("contextCreated", this.contextCreatedActivateGUIListener);
}
this.resizeObserver.disconnect();
this.grandParentElement.remove();
this.videoElement.remove();
(_b = (_a = this.contextWebGL) === null || _a === void 0 ? void 0 : _a.canvas) === null || _b === void 0 ? void 0 : _b.removeEventListener("webglcontextlost", this.webGLContextLostListener);
(_d = (_c = this.contextWebGL) === null || _c === void 0 ? void 0 : _c.getExtension("WEBGL_lose_context")) === null || _d === void 0 ? void 0 : _d.loseContext();
this.contextWebGL = undefined;
this.context2d = undefined;
this.originElement.classList.remove(GUI.hiddenClassName);
};
GUI.prototype.setCameraManager = function (cameraManager) {
this.cameraManager = cameraManager;
};
GUI.prototype.pauseScanning = function () {
this.scanningPaused = true;
this.laserActiveImageElement.classList.add(GUI.hiddenOpacityClassName);
this.laserPausedImageElement.classList.remove(GUI.hiddenOpacityClassName);
this.viewfinderElement.classList.add(GUI.pausedClassName);
};
GUI.prototype.resumeScanning = function () {
this.scanningPaused = false;
if (this.dataCaptureContextCreated) {
this.laserPausedImageElement.classList.add(GUI.hiddenOpacityClassName);
this.laserActiveImageElement.classList.remove(GUI.hiddenOpacityClassName);
this.viewfinderElement.classList.remove(GUI.pausedClassName);
}
};
GUI.prototype.isVisible = function () {
return this.visible;
};
GUI.prototype.setVisible = function (visible) {
this.visible = visible;
if (visible) {
this.originElement.classList.remove(GUI.hiddenClassName);
if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.LASER) {
this.laserActiveImageElement.classList.remove(GUI.flashColorClassName);
}
else if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.VIEWFINDER) {
this.viewfinderElement.classList.remove(GUI.flashWhiteClassName);
}
}
else {
this.originElement.classList.add(GUI.hiddenClassName);
}
};
GUI.prototype.isMirrorImageEnabled = function () {
var _a, _b;
if (((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.selectedCamera) != null && ((_b = this.cameraManager) === null || _b === void 0 ? void 0 : _b.activeCamera) != null) {
var mirrorImageOverride = this.mirrorImageOverrides.get(this.cameraManager.activeCamera);
return mirrorImageOverride !== null && mirrorImageOverride !== void 0 ? mirrorImageOverride : this.cameraManager.activeCamera.cameraType === camera_1.Camera.Type.FRONT;
}
else {
return false;
}
};
GUI.prototype.setMirrorImageEnabled = function (enabled, override) {
var _a;
if (((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.selectedCamera) != null) {
if (enabled) {
this.videoElement.classList.add(GUI.mirroredClassName);
}
else {
this.videoElement.classList.remove(GUI.mirroredClassName);
}
if (override) {
this.mirrorImageOverrides.set(this.cameraManager.selectedCamera, enabled);
}
}
};
GUI.prototype.setGuiStyle = function (guiStyle) {
if (this.singleImageModeEnabled) {
return;
}
switch (guiStyle) {
case barcodePicker_1.BarcodePicker.GuiStyle.LASER:
this.guiStyle = guiStyle;
this.laserContainerElement.classList.remove(GUI.hiddenClassName);
this.viewfinderElement.classList.add(GUI.hiddenClassName);
break;
case barcodePicker_1.BarcodePicker.GuiStyle.VIEWFINDER:
this.guiStyle = guiStyle;
this.laserContainerElement.classList.add(GUI.hiddenClassName);
this.viewfinderElement.classList.remove(GUI.hiddenClassName);
break;
case barcodePicker_1.BarcodePicker.GuiStyle.NONE:
default:
this.guiStyle = barcodePicker_1.BarcodePicker.GuiStyle.NONE;
this.laserContainerElement.classList.add(GUI.hiddenClassName);
this.viewfinderElement.classList.add(GUI.hiddenClassName);
break;
}
};
GUI.prototype.setLaserArea = function (area) {
this.customLaserArea = area;
if (area == null) {
area = this.scanner.getScanSettings().getSearchArea();
}
var borderPercentage = 0.025;
var usablePercentage = 1 - borderPercentage * 2;
this.laserContainerElement.style.left = "".concat((borderPercentage + area.x * usablePercentage) * 100, "%");
this.laserContainerElement.style.width = "".concat(area.width * usablePercentage * 100, "%");
this.laserContainerElement.style.top = "".concat((borderPercentage + area.y * usablePercentage) * 100, "%");
this.laserContainerElement.style.height = "".concat(area.height * usablePercentage * 100, "%");
};
GUI.prototype.setViewfinderArea = function (area) {
this.customViewfinderArea = area;
if (area == null) {
area = this.scanner.getScanSettings().getSearchArea();
}
var borderPercentage = 0.025;
var usablePercentage = 1 - borderPercentage * 2;
this.viewfinderElement.style.left = "".concat((borderPercentage + area.x * usablePercentage) * 100, "%");
this.viewfinderElement.style.width = "".concat(area.width * usablePercentage * 100, "%");
this.viewfinderElement.style.top = "".concat((borderPercentage + area.y * usablePercentage) * 100, "%");
this.viewfinderElement.style.height = "".concat(area.height * usablePercentage * 100, "%");
};
GUI.prototype.setVideoFit = function (objectFit) {
if (this.singleImageModeEnabled) {
return;
}
this.videoFit = objectFit;
if (objectFit === barcodePicker_1.BarcodePicker.ObjectFit.COVER) {
this.videoElement.style.objectFit = "cover";
this.videoElement.dataset.objectFit = "cover"; // used by "objectFitPolyfill" library
}
else {
this.videoElement.style.objectFit = "contain";
this.videoElement.dataset.objectFit = "contain"; // used by "objectFitPolyfill" library
this.scanner.applyScanSettings(this.scanner.getScanSettings().setBaseSearchArea({ x: 0, y: 0, width: 1.0, height: 1.0 }));
}
this.resize();
};
GUI.prototype.reassignOriginElement = function (originElement) {
if (!this.visible) {
this.originElement.classList.remove(GUI.hiddenClassName);
originElement.classList.add(GUI.hiddenClassName);
}
originElement.appendChild(this.grandParentElement);
this.checkAndRecoverPlayback().catch(
/* istanbul ignore next */ function () {
// Ignored
});
this.resize();
this.resizeObserver.disconnect();
this.resizeObserver.observe(originElement);
this.originElement = originElement;
};
GUI.prototype.flashGUI = function () {
if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.LASER) {
this.flashLaser();
}
else if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.VIEWFINDER) {
this.flashViewfinder();
}
};
GUI.prototype.getImageData = function (imageData) {
function isVideoAndContextStateValid(videoElement, context) {
// This could happen in unexpected situations and should be temporary
return (videoElement.readyState === 4 &&
videoElement.videoWidth > 2 &&
videoElement.videoHeight > 2 &&
context.canvas.width > 2 &&
context.canvas.height > 2);
}
if (this.singleImageModeEnabled && this.context2d != null) {
return new Uint8Array(this.context2d.getImageData(0, 0, this.context2d.canvas.width, this.context2d.canvas.height).data.buffer);
}
// istanbul ignore else
if (!this.singleImageModeEnabled) {
if (this.contextWebGL != null) {
if (!isVideoAndContextStateValid(this.videoElement, this.contextWebGL) ||
this.contextWebGL.drawingBufferWidth <= 2 ||
this.contextWebGL.drawingBufferHeight <= 2) {
return;
}
var imageDataLength = this.contextWebGL.drawingBufferWidth * this.contextWebGL.drawingBufferHeight * 4;
if (imageData == null || imageData.byteLength === 0 || imageData.byteLength !== imageDataLength) {
imageData = new Uint8Array(imageDataLength);
}
this.contextWebGL.texImage2D(this.contextWebGL.TEXTURE_2D, 0, this.contextWebGL.RGBA, this.contextWebGL.RGBA, this.contextWebGL.UNSIGNED_BYTE, this.videoElement);
this.contextWebGL.readPixels(0, 0, this.contextWebGL.drawingBufferWidth, this.contextWebGL.drawingBufferHeight, this.contextWebGL.RGBA, this.contextWebGL.UNSIGNED_BYTE, imageData);
// Detect incorrect GPU accelerated WebGL image processing by checking for incorrect alpha channel data
if (imageData[3] !== 255) {
logger_1.Logger.log(logger_1.Logger.Level.WARN, "Detected incorrect GPU accelerated WebGL image processing, switching to canvas mode");
this.contextWebGL = undefined;
this.setupContext(document.createElement("canvas"), true);
this.handleVideoResize();
return this.getImageData(imageData);
}
return imageData;
}
// istanbul ignore else
if (this.context2d != null) {
if (!isVideoAndContextStateValid(this.videoElement, this.context2d)) {
return;
}
this.context2d.drawImage(this.videoElement, 0, 0);
return new Uint8Array(this.context2d.getImageData(0, 0, this.context2d.canvas.width, this.context2d.canvas.height).data.buffer);
}
}
// istanbul ignore next
return;
};
GUI.prototype.getVideoCurrentTime = function () {
return this.videoElement.currentTime;
};
GUI.prototype.setCameraSwitcherVisible = function (visible) {
if (visible) {
this.cameraSwitcherElement.classList.remove(GUI.hiddenClassName);
}
else {
this.cameraSwitcherElement.classList.add(GUI.hiddenClassName);
}
};
GUI.prototype.isCameraRecoveryVisible = function () {
return !this.cameraRecoveryElement.classList.contains(GUI.hiddenClassName);
};
GUI.prototype.setCameraRecoveryVisible = function (visible) {
if (visible) {
this.cameraRecoveryElement.classList.remove(GUI.hiddenClassName);
}
else {
this.cameraRecoveryElement.classList.add(GUI.hiddenClassName);
}
};
GUI.prototype.setTorchTogglerVisible = function (visible) {
if (visible) {
this.torchTogglerElement.classList.remove(GUI.hiddenClassName);
}
else {
this.torchTogglerElement.classList.add(GUI.hiddenClassName);
}
};
GUI.prototype.playVideo = function () {
var playPromise = this.videoElement.play();
playPromise === null || playPromise === void 0 ? void 0 : playPromise.catch(
/* istanbul ignore next */ function () {
// Can sometimes cause an incorrect rejection (all is good, ignore).
});
};
GUI.prototype.setVideoVisible = function (visible) {
this.videoElement.style.visibility = visible ? "visible" : "hidden";
};
GUI.prototype.setCameraType = function (cameraType) {
var _a;
(_a = this.cameraUploadInputElement) === null || _a === void 0 ? void 0 : _a.setAttribute("capture", cameraType === camera_1.Camera.Type.FRONT ? "user" : "environment");
};
GUI.prototype.setCameraUploadGuiBusyScanning = function (busyScanning) {
if (busyScanning) {
this.cameraUploadProgressElement.classList.remove(GUI.flashInsetClassName);
this.cameraUploadElement.classList.add(GUI.opacityPulseClassName);
}
else {
this.cameraUploadProgressElement.classList.add(GUI.flashInsetClassName);
this.cameraUploadElement.classList.remove(GUI.opacityPulseClassName);
}
};
GUI.prototype.setupContext = function (canvas, force2d) {
if (force2d === void 0) { force2d = false; }
if (force2d) {
this.context2d = canvas.getContext("2d");
return;
}
var context = canvas.getContext("webgl", { alpha: false, antialias: false });
// istanbul ignore if
if (context == null) {
context = canvas.getContext("experimental-webgl", { alpha: false, antialias: false });
}
if (context != null) {
this.setupWebGL(context);
canvas.addEventListener("webglcontextlost", this.webGLContextLostListener);
}
else {
this.context2d = canvas.getContext("2d");
}
};
GUI.prototype.setupWebGL = function (contextWebGL) {
var texture = contextWebGL.createTexture();
contextWebGL.bindTexture(contextWebGL.TEXTURE_2D, texture);
var frameBuffer = contextWebGL.createFramebuffer();
contextWebGL.bindFramebuffer(contextWebGL.FRAMEBUFFER, frameBuffer);
contextWebGL.framebufferTexture2D(contextWebGL.FRAMEBUFFER, contextWebGL.COLOR_ATTACHMENT0, contextWebGL.TEXTURE_2D, texture, 0);
contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_WRAP_S, contextWebGL.CLAMP_TO_EDGE);
contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_WRAP_T, contextWebGL.CLAMP_TO_EDGE);
contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_MIN_FILTER, contextWebGL.NEAREST);
contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_MAG_FILTER, contextWebGL.NEAREST);
this.contextWebGL = contextWebGL;
};
GUI.prototype.setupVideoElement = function () {
this.videoElement.setAttribute("autoplay", "autoplay");
this.videoElement.setAttribute("playsinline", "true");
this.videoElement.setAttribute("muted", "muted");
this.videoElement.className = GUI.videoElementClassName;
this.parentElement.appendChild(this.videoElement);
};
GUI.prototype.setupCameraUploadGuiAssets = function () {
var _this = this;
var _a, _b;
var deviceType = browserHelper_1.BrowserHelper.userAgentInfo.getDevice().type;
var defaultSettings = deviceType === "mobile" || deviceType === "tablet"
? singleImageModeSettings_1.SingleImageModeSettings.defaultMobile
: singleImageModeSettings_1.SingleImageModeSettings.defaultDesktop;
this.cameraUploadElement.className = GUI.cameraUploadElementClassName;
Object.assign(this.cameraUploadElement.style, defaultSettings.containerStyle, this.singleImageModeSettings.containerStyle);
this.parentElement.appendChild(this.cameraUploadElement);
var informationElement = (_a = this.singleImageModeSettings.informationElement) !== null && _a !== void 0 ? _a : defaultSettings.informationElement;
Object.assign(informationElement.style, defaultSettings.informationStyle, this.singleImageModeSettings.informationStyle);
this.cameraUploadElement.appendChild(informationElement);
this.cameraUploadInputElement.type = "file";
this.cameraUploadInputElement.accept = "image/*";
this.cameraUploadInputElement.addEventListener("change", this.cameraUploadFile.bind(this));
var cameraUploadInputCheckFunction = function (event) {
// istanbul ignore next
if (_this.scanningPaused || _this.cameraUploadInProgress) {
event.preventDefault();
}
};
this.cameraUploadInputElement.addEventListener("click", cameraUploadInputCheckFunction);
this.cameraUploadInputElement.addEventListener("keydown", cameraUploadInputCheckFunction);
this.cameraUploadLabelElement.appendChild(this.cameraUploadInputElement);
var cameraUploadButtonIconElement = (_b = this.singleImageModeSettings.buttonElement) !== null && _b !== void 0 ? _b : defaultSettings.buttonElement;
[this.cameraUploadProgressElement.style, cameraUploadButtonIconElement.style].forEach(function (style) {
Object.assign(style, defaultSettings.buttonStyle, _this.singleImageModeSettings.buttonStyle);
});
cameraUploadButtonIconElement.style.maxWidth = "100px";
cameraUploadButtonIconElement.style.maxHeight = "100px";
this.cameraUploadLabelElement.appendChild(cameraUploadButtonIconElement);
this.cameraUploadProgressElement.classList.add("radial-progress");
this.cameraUploadLabelElement.appendChild(this.cameraUploadProgressElement);
this.cameraUploadElement.appendChild(this.cameraUploadLabelElement);
};
GUI.prototype.setupFullGuiAssets = function () {
this.laserActiveImageElement.src = base64assets_1.laserActiveImage;
this.laserContainerElement.appendChild(this.laserActiveImageElement);
this.laserPausedImageElement.src = base64assets_1.laserPausedImage;
this.laserContainerElement.appendChild(this.laserPausedImageElement);
this.laserContainerElement.className = GUI.laserContainerElementClassName;
this.parentElement.appendChild(this.laserContainerElement);
this.viewfinderElement.className = GUI.viewfinderElementClassName;
this.parentElement.appendChild(this.viewfinderElement);
// Show inactive GUI, as for now the scanner isn't ready yet
this.laserActiveImageElement.classList.add(GUI.hiddenOpacityClassName);
this.laserPausedImageElement.classList.remove(GUI.hiddenOpacityClassName);
this.viewfinderElement.classList.add(GUI.pausedClassName);
};
GUI.prototype.flashLaser = function () {
this.laserActiveImageElement.classList.remove(GUI.flashColorClassName);
// tslint:disable-next-line:no-unused-expression
this.laserActiveImageElement.offsetHeight; // NOSONAR // Trigger reflow to restart animation
this.laserActiveImageElement.classList.add(GUI.flashColorClassName);
};
GUI.prototype.flashViewfinder = function () {
this.viewfinderElement.classList.remove(GUI.flashWhiteClassName);
// tslint:disable-next-line:no-unused-expression
this.viewfinderElement.offsetHeight; // NOSONAR // Trigger reflow to restart animation
this.viewfinderElement.classList.add(GUI.flashWhiteClassName);
};
GUI.prototype.resize = function () {
this.parentElement.style.maxWidth = "";
this.parentElement.style.maxHeight = "";
var width = this.originElement.clientWidth;
var height = this.originElement.clientHeight;
if (width === 0 || height === 0) {
if (!this.singleImageModeEnabled) {
this.handleVideoDisplay(true);
}
return;
}
if (this.singleImageModeEnabled) {
this.resizeCameraUpload(width, height);
}
else {
this.resizeVideo(width, height);
this.handleVideoDisplay(false);
}
};
GUI.prototype.resizeCameraUpload = function (width, height) {
this.cameraUploadLabelElement.style.transform = "scale(".concat(Math.min(1, width / 300, height / 300), ")");
};
GUI.prototype.resizeVideo = function (width, height) {
if (this.videoElement.videoWidth <= 2 || this.videoElement.videoHeight <= 2) {
return;
}
var videoRatio = this.videoElement.videoWidth / this.videoElement.videoHeight;
if (this.videoFit === barcodePicker_1.BarcodePicker.ObjectFit.COVER) {
var widthPercentage = 1;
var heightPercentage = 1;
if (videoRatio < width / height) {
heightPercentage = Math.min(1, height / (width / videoRatio));
}
else {
widthPercentage = Math.min(1, width / (height * videoRatio));
}
this.scanner.applyScanSettings(this.scanner.getScanSettings().setBaseSearchArea({
x: (1 - widthPercentage) / 2,
y: (1 - heightPercentage) / 2,
width: widthPercentage,
height: heightPercentage,
}));
return;
}
if (videoRatio > width / height) {
height = width / videoRatio;
}
else {
width = height * videoRatio;
}
this.parentElement.style.maxWidth = "".concat(Math.ceil(width), "px");
this.parentElement.style.maxHeight = "".concat(Math.ceil(height), "px");
window.objectFitPolyfill(this.videoElement);
};
GUI.prototype.checkAndRecoverPlayback = function () {
var _a, _b, _c;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var srcObject, _d;
return tslib_1.__generator(this, function (_e) {
switch (_e.label) {
case 0:
srcObject = this.videoElement.srcObject;
if (!(document.visibilityState === "visible" &&
((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.activeCamera) != null &&
((_b = this.videoElement) === null || _b === void 0 ? void 0 : _b.srcObject) != null)) return [3 /*break*/, 6];
if (!(!srcObject.active || ((_c = srcObject.getVideoTracks()[0]) === null || _c === void 0 ? void 0 : _c.muted) !== false)) return [3 /*break*/, 5];
_e.label = 1;
case 1:
_e.trys.push([1, 3, , 4]);
logger_1.Logger.log(logger_1.Logger.Level.DEBUG, 'Detected visibility change ("visible") event with inactive video source, try to reinitialize camera');
return [4 /*yield*/, this.cameraManager.reinitializeCamera()];
case 2:
_e.sent();
return [3 /*break*/, 4];
case 3:
_d = _e.sent();
return [3 /*break*/, 4];
case 4: return [3 /*break*/, 6];
case 5:
logger_1.Logger.log(logger_1.Logger.Level.DEBUG, 'Detected visibility change ("visible") event with active video source, replay video');
this.playVideo();
_e.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
GUI.prototype.updateCameraUploadProgress = function (progressPercentageValue) {
this.cameraUploadProgressElement.setAttribute("data-progress", progressPercentageValue);
};
GUI.prototype.cameraUploadImageLoad = function (image) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var resizedImageWidth, resizedImageHeight, resizedImageSizeLimit;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.updateCameraUploadProgress("100");
resizedImageSizeLimit = 1440;
if (image.naturalWidth <= resizedImageSizeLimit && image.naturalHeight <= resizedImageSizeLimit) {
resizedImageWidth = image.naturalWidth;
resizedImageHeight = image.naturalHeight;
}
else {
if (image.naturalWidth > image.naturalHeight) {
resizedImageWidth = resizedImageSizeLimit;
resizedImageHeight = Math.round((image.naturalHeight / image.naturalWidth) * resizedImageSizeLimit);
}
else {
resizedImageWidth = Math.round((image.naturalWidth / image.naturalHeight) * resizedImageSizeLimit);
resizedImageHeight = resizedImageSizeLimit;
}
}
return [4 /*yield*/, this.cameraUploadFileProcess(image, resizedImageWidth, resizedImageHeight)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
GUI.prototype.cameraUploadFileProcess = function (image, width, height) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
// istanbul ignore else
if (this.context2d != null) {
this.context2d.canvas.width = width;
this.context2d.canvas.height = height;
this.context2d.drawImage(image, 0, 0, width, height);
this.scanner.applyImageSettings({
width: width,
height: height,
format: imageSettings_1.ImageSettings.Format.RGBA_8U,
});
}
this.setCameraUploadGuiBusyScanning(true);
return [4 /*yield*/, this.cameraUploadCallback()];
case 1:
_a.sent();
this.setCameraUploadGuiBusyScanning(false);
this.cameraUploadInProgress = false;
return [2 /*return*/];
}
});
});
};
GUI.prototype.cameraUploadFile = function () {
var _this = this;
var files = this.cameraUploadInputElement.files;
if (files != null && files.length !== 0) {
this.cameraUploadInProgress = true;
var image_1 = new Image();
var fileReader_1 = new FileReader();
fileReader_1.onload = function () {
_this.cameraUploadInputElement.value = "";
// istanbul ignore else
if (fileReader_1.result != null) {
image_1.onload = _this.cameraUploadImageLoad.bind(_this, image_1);
// istanbul ignore next
image_1.onprogress = function (event2) {
if (event2.lengthComputable) {
var progress = Math.round((event2.loaded / event2.total) * 20) * 5;
if (progress <= 100) {
_this.updateCameraUploadProgress(progress.toString());
}
}
};
// istanbul ignore next
image_1.onerror = function () {
_this.cameraUploadInProgress = false;
logger_1.Logger.log(logger_1.Logger.Level.WARN, "Could not load image from selected file");
};
image_1.src = fileReader_1.result;
}
};
// istanbul ignore next
fileReader_1.onerror = function () {
var _a;
_this.cameraUploadInProgress = false;
logger_1.Logger.log(logger_1.Logger.Level.WARN, "Error while reading the file: ".concat((_a = fileReader_1.error) === null || _a === void 0 ? void 0 : _a.toString()));
};
this.updateCameraUploadProgress("0");
fileReader_1.readAsDataURL(files[0]);
}
};
GUI.prototype.cameraSwitcherListener = function (event) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var cameraManager, cameras, currentCameraIndex, newCameraIndex, error_1, error_2;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(!this.cameraSwitchInProgress && this.cameraManager != null)) return [3 /*break*/, 12];
cameraManager = this.cameraManager;
event.preventDefault();
_a.label = 1;
case 1:
_a.trys.push([1, 11, , 12]);
return [4 /*yield*/, cameraAccess_1.CameraAccess.getCameras()];
case 2:
cameras = _a.sent();
if (cameraManager.activeCamera == null) {
return [2 /*return*/];
}
if (cameras.length <= 1) {
this.setCameraSwitcherVisible(false);
return [2 /*return*/];
}
this.cameraSwitchInProgress = true;
currentCameraIndex = cameras.indexOf(cameraManager.activeCamera);
newCameraIndex = (currentCameraIndex + 1) % cameras.length;
_a.label = 3;
case 3:
if (!(newCameraIndex !== currentCameraIndex)) return [3 /*break*/, 10];
_a.label = 4;
case 4:
_a.trys.push([4, 6, , 9]);
return [4 /*yield*/, cameraManager.initializeCameraWithSettings(cameras[newCameraIndex], cameraManager.activeCameraSettings)];
case 5:
_a.sent();
return [3 /*break*/, 9];
case 6:
error_1 = _a.sent();
logger_1.Logger.log(logger_1.Logger.Level.WARN, "Couldn't access camera:", cameras[newCameraIndex], error_1);
newCameraIndex = (newCameraIndex + 1) % cameras.length;
if (!(newCameraIndex === currentCameraIndex)) return [3 /*break*/, 8];
this.setCameraSwitcherVisible(false);
return [4 /*yield*/, cameraManager.initializeCameraWithSettings(cameras[newCameraIndex], cameraManager.activeCameraSettings)];
case 7:
_a.sent();
_a.label = 8;
case 8: return [3 /*break*/, 3];
case 9: return [3 /*break*/, 10];
case 10:
this.cameraSwitchInProgress = false;
return [3 /*break*/, 12];
case 11:
error_2 = _a.sent();
logger_1.Logger.log(logger_1.Logger.Level.ERROR, error_2);
this.cameraSwitchInProgress = false;
return [3 /*break*/, 12];
case 12: return [2 /*return*/];
}
});
});
};
GUI.prototype.cameraRecoveryListener = function (event) {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
event.preventDefault();
if (!(this.cameraManager != null)) return [3 /*break*/, 2];
this.cameraManager.activeCamera = this.cameraManager.selectedCamera;
return [4 /*yield*/, ((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.reinitializeCamera())];
case 1:
_b.sent();
_b.label = 2;
case 2: return [2 /*return*/];
}
});
});
};
GUI.prototype.setupCameraSwitcher = function () {
var _this = this;
this.cameraSwitcherElement.src = base64assets_1.switchCameraImage;
this.cameraSwitcherElement.className = GUI.cameraSwitcherElementClassName;
this.cameraSwitcherElement.classList.add(GUI.hiddenClassName);
this.parentElement.appendChild(this.cameraSwitcherElement);
["touchstart", "mousedown"].forEach(function (eventName) {
_this.cameraSwitcherElement.addEventListener(eventName, _this.cameraSwitcherListener.bind(_this));
});
};
GUI.prototype.setupCameraRecovery = function (cameraRecoveryText) {
var _this = this;
this.cameraRecoveryElement.textContent = cameraRecoveryText;
this.cameraRecoveryElement.className = GUI.cameraRecoveryElementClassName;
this.cameraRecoveryElement.classList.add(GUI.hiddenClassName);
this.parentElement.appendChild(this.cameraRecoveryElement);
["touchstart", "mousedown"].forEach(function (eventName) {
_this.cameraRecoveryElement.addEventListener(eventName, _this.cameraRecoveryListener.bind(_this));
});
};
GUI.prototype.setupTorchToggler = function () {
var _this = this;
this.torchTogglerElement.src = base64assets_1.toggleTorchImage;
this.torchTogglerElement.className = GUI.torchTogglerElementClassName;
this.torchTogglerElement.classList.add(GUI.hiddenClassName);
this.parentElement.appendChild(this.torchTogglerElement);
["touchstart", "mousedown"].forEach(function (eventName) {
_this.torchTogglerElement.addEventListener(eventName, function (event) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(this.cameraManager != null)) return [3 /*break*/, 2];
event.preventDefault();
return [4 /*yield*/, this.cameraManager.toggleTorch()];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/];
}
});
}); });
});
};
GUI.prototype.showScanditLogo = function (hideLogo, licenseKeyFeatures) {
if (hideLogo && (licenseKeyFeatures === null || licenseKeyFeatures === void 0 ? void 0 : licenseKeyFeatures.hiddenScanditLogoAllowed) === true) {
return;
}
var scanditLogoImageElement = document.createElement("img");
scanditLogoImageElement.src = base64assets_1.scanditLogoImage;
scanditLogoImageElement.className = GUI.scanditLogoImageElementClassName;
this.parentElement.appendChild(scanditLogoImageElement);
};
GUI.prototype.activateGUI = function () {
this.dataCaptureContextCreated = true;
if (!this.scanningPaused) {
this.resumeScanning();
}
};
GUI.prototype.handleNewScanSettings = function () {
if (this.customLaserArea == null) {
this.setLaserArea();
}
if (this.customViewfinderArea == null) {
this.setViewfinderArea();
}
};
GUI.prototype.handleVideoDisplay = function (hidden) {
// Safari on iOS 14 behaves weirdly when hiding the video element:
// it stops camera access after a few seconds if the related video element is not "visible".
// We do the following to maintain the video element "visible" but actually hidden.
if (hidden && !this.isVideoElementDetached) {
this.videoElement.width = this.videoElement.height = 0;
this.videoElement.style.opacity = "0";
document.body.appendChild(this.videoElement);
this.isVideoElementDetached = true;
}
else if (!hidden && this.isVideoElementDetached) {
this.parentElement.insertAdjacentElement("afterbegin", this.videoElement);
this.isVideoElementDetached = false;
this.videoElement.removeAttribute("width");
this.videoElement.removeAttribute("height");
this.videoElement.style.removeProperty("opacity");
this.resize();
}
};
GUI.prototype.handleVideoPause = function () {
// Safari behaves weirdly when displaying the video element again after hiding it:
// it pauses the video on hide and resumes it on show, then reusing video frames "buffered" from the video just
// before it was hidden. We do the following to avoid processing old data.
this.playVideo();
};
GUI.prototype.handleVideoResize = function () {
this.resize();
if (this.videoElement.videoWidth <= 2 || this.videoElement.videoHeight <= 2) {
return;
}
if (this.contextWebGL != null) {
if (this.contextWebGL.canvas.width === this.videoElement.videoWidth &&
this.contextWebGL.canvas.height === this.videoElement.videoHeight) {
return;
}
this.contextWebGL.canvas.width = this.videoElement.videoWidth;
this.contextWebGL.canvas.height = this.videoElement.videoHeight;
this.contextWebGL.viewport(0, 0, this.contextWebGL.drawingBufferWidth, this.contextWebGL.drawingBufferHeight);
this.scanner.applyImageSettings({
width: this.contextWebGL.drawingBufferWidth,
height: this.contextWebGL.drawingBufferHeight,
format: imageSettings_1.ImageSettings.Format.RGBA_8U,
});
}
else if (this.context2d != null) {
if (this.context2d.canvas.width === this.videoElement.videoWidth &&
this.context2d.canvas.height === this.videoElement.videoHeight) {
return;
}
this.context2d.canvas.width = this.videoElement.videoWidth;
this.context2d.canvas.height = this.videoElement.videoHeight;
this.scanner.applyImageSettings({
width: this.videoElement.videoWidth,
height: this.videoElement.videoHeight,
format: imageSettings_1.ImageSettings.Format.RGBA_8U,
});
}
};
GUI.prototype.handleWebGLContextLost = function () {
// We recreate instead of waiting for restore via the webglcontextrestored event as restore might never happen
logger_1.Logger.log(logger_1.Logger.Level.WARN, "WebGL context has been lost, restoring...");
this.contextWebGL = undefined;
this.setupContext(document.createElement("canvas"));
this.handleVideoResize();
logger_1.Logger.log(logger_1.Logger.Level.WARN, "WebGL context restored");
};
GUI.grandParentElementClassName = "scandit scandit-container";
GUI.parentElementClassName = "scandit scandit-barcode-picker";
GUI.hiddenClassName = "scandit-hidden";
GUI.hiddenOpacityClassName = "scandit-hidden-opacity";
GUI.videoElementClassName = "scandit-video";
GUI.scanditLogoImageElementClassName = "scandit-logo";
GUI.laserContainerElementClassName = "scandit-laser";
GUI.viewfinderElementClassName = "scandit-viewfinder";
GUI.cameraSwitcherElementClassName = "scandit-camera-switcher";
GUI.cameraRecoveryElementClassName = "scandit-camera-recovery";
GUI.torchTogglerElementClassName = "scandit-torch-toggle";
GUI.cameraUploadElementClassName = "scandit-camera-upload";
GUI.flashColorClassName = "scandit-flash-color";
GUI.flashWhiteClassName = "scandit-flash-white";
GUI.flashInsetClassName = "scandit-flash-inset";
GUI.opacityPulseClassName = "scandit-opacity-pulse";
GUI.mirroredClassName = "mirrored";
GUI.pausedClassName = "paused";
return GUI;
}());
exports.GUI = GUI;
//# sourceMappingURL=gui.js.map

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
import { ListenerFn } from "eventemitter3";
import { Barcode } from "./barcode";
import { ScanSettings } from "./scanSettings";
declare type EventName = "blurryTablesUpdate";
export declare class BlurryRecognitionPreloader {
private static readonly writableDataPath;
private static readonly fsObjectStoreName;
private static readonly defaultBlurryTableFiles;
private static readonly highEndBlurryTableFiles;
private static readonly availableBlurryRecognitionSymbologies;
private readonly eventEmitter;
private readonly preload;
private queuedBlurryRecognitionSymbologies;
private readyBlurryRecognitionSymbologies;
private dataCaptureWorker;
private constructor();
static create(preload: boolean): Promise<BlurryRecognitionPreloader>;
private static workerIndexedDBSupportTestFunction;
prepareBlurryTables(): Promise<void>;
on(eventName: EventName, listener: ListenerFn): void;
updateBlurryRecognitionPriority(scanSettings: ScanSettings): void;
isBlurryRecognitionAvailable(scanSettings: ScanSettings): boolean;
getEnabledSymbologies(scanSettings: ScanSettings): Barcode.Symbology[];
private createNextBlurryTableSymbology;
private checkBlurryTablesAlreadyAvailable;
private dataCaptureWorkerOnMessage;
}
export {};

View File

@@ -0,0 +1,320 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlurryRecognitionPreloader = void 0;
var tslib_1 = require("tslib");
var eventemitter3_1 = require("eventemitter3");
var __1 = require("..");
var barcode_1 = require("./barcode");
var browserHelper_1 = require("./browserHelper");
var dataCaptureLoader_1 = require("./dataCaptureLoader");
var logger_1 = require("./logger");
var dataCaptureWorker_1 = require("./workers/dataCaptureWorker");
var BlurryRecognitionPreloaderEventEmitter = /** @class */ (function (_super) {
tslib_1.__extends(BlurryRecognitionPreloaderEventEmitter, _super);
function BlurryRecognitionPreloaderEventEmitter() {
return _super !== null && _super.apply(this, arguments) || this;
}
return BlurryRecognitionPreloaderEventEmitter;
}(eventemitter3_1.EventEmitter));
var BlurryRecognitionPreloader = /** @class */ (function () {
function BlurryRecognitionPreloader(preload) {
this.eventEmitter = new eventemitter3_1.EventEmitter();
this.queuedBlurryRecognitionSymbologies = Array.from(BlurryRecognitionPreloader.availableBlurryRecognitionSymbologies.values());
this.readyBlurryRecognitionSymbologies = new Set();
this.preload = preload;
}
BlurryRecognitionPreloader.create = function (preload) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var browserName, worker_1;
return tslib_1.__generator(this, function (_a) {
if (preload) {
browserName = browserHelper_1.BrowserHelper.userAgentInfo.getBrowser().name;
if (browserName != null && browserName.includes("Edge")) {
worker_1 = new Worker(URL.createObjectURL(new Blob(["(".concat(BlurryRecognitionPreloader.workerIndexedDBSupportTestFunction.toString(), ")()")], {
type: "text/javascript",
})));
return [2 /*return*/, new Promise(function (resolve) {
worker_1.onmessage = function (message) {
worker_1.terminate();
resolve(new BlurryRecognitionPreloader(message.data));
};
})];
}
}
return [2 /*return*/, new BlurryRecognitionPreloader(preload)];
});
});
};
// istanbul ignore next
BlurryRecognitionPreloader.workerIndexedDBSupportTestFunction = function () {
try {
indexedDB.deleteDatabase("scandit_indexeddb_support_test");
// @ts-ignore
postMessage(true);
}
catch (error) {
// @ts-ignore
postMessage(false);
}
};
BlurryRecognitionPreloader.prototype.prepareBlurryTables = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var alreadyAvailable, error_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
alreadyAvailable = true;
if (!this.preload) return [3 /*break*/, 4];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.checkBlurryTablesAlreadyAvailable()];
case 2:
alreadyAvailable = _a.sent();
return [3 /*break*/, 4];
case 3:
error_1 = _a.sent();
// istanbul ignore next
logger_1.Logger.log(logger_1.Logger.Level.ERROR, error_1);
return [3 /*break*/, 4];
case 4:
if (alreadyAvailable) {
this.queuedBlurryRecognitionSymbologies = [];
this.readyBlurryRecognitionSymbologies = new Set(BlurryRecognitionPreloader.availableBlurryRecognitionSymbologies);
this.eventEmitter.emit("blurryTablesUpdate", new Set(this.readyBlurryRecognitionSymbologies));
}
else {
this.dataCaptureWorker = new Worker(URL.createObjectURL(dataCaptureWorker_1.dataCaptureWorkerBlob));
this.dataCaptureWorker.onmessage = this.dataCaptureWorkerOnMessage.bind(this);
dataCaptureLoader_1.DataCaptureLoader.load(this.dataCaptureWorker, true, true);
}
return [2 /*return*/];
}
});
});
};
BlurryRecognitionPreloader.prototype.on = function (eventName, listener) {
// istanbul ignore else
if (eventName === "blurryTablesUpdate") {
if (this.readyBlurryRecognitionSymbologies.size ===
BlurryRecognitionPreloader.availableBlurryRecognitionSymbologies.size) {
listener(this.readyBlurryRecognitionSymbologies);
}
else {
this.eventEmitter.on(eventName, listener);
}
}
};
BlurryRecognitionPreloader.prototype.updateBlurryRecognitionPriority = function (scanSettings) {
var newQueuedBlurryRecognitionSymbologies = this.queuedBlurryRecognitionSymbologies.slice();
this.getEnabledSymbologies(scanSettings).forEach(function (symbology) {
var symbologyQueuePosition = newQueuedBlurryRecognitionSymbologies.indexOf(symbology);
if (symbologyQueuePosition !== -1) {
newQueuedBlurryRecognitionSymbologies.unshift(newQueuedBlurryRecognitionSymbologies.splice(symbologyQueuePosition, 1)[0]);
}
});
this.queuedBlurryRecognitionSymbologies = newQueuedBlurryRecognitionSymbologies;
};
BlurryRecognitionPreloader.prototype.isBlurryRecognitionAvailable = function (scanSettings) {
var _this = this;
var enabledBlurryRecognitionSymbologies = this.getEnabledSymbologies(scanSettings);
return enabledBlurryRecognitionSymbologies.every(function (symbology) {
return _this.readyBlurryRecognitionSymbologies.has(symbology);
});
};
BlurryRecognitionPreloader.prototype.getEnabledSymbologies = function (scanSettings) {
return Array.from(BlurryRecognitionPreloader.availableBlurryRecognitionSymbologies.values()).filter(function (symbology) {
return scanSettings.isSymbologyEnabled(symbology);
});
};
BlurryRecognitionPreloader.prototype.createNextBlurryTableSymbology = function () {
var symbology;
do {
symbology = this.queuedBlurryRecognitionSymbologies.shift();
} while (symbology != null && this.readyBlurryRecognitionSymbologies.has(symbology));
// istanbul ignore else
if (symbology != null) {
this.dataCaptureWorker.postMessage({
type: "create-blurry-table",
symbology: symbology,
});
}
};
BlurryRecognitionPreloader.prototype.checkBlurryTablesAlreadyAvailable = function () {
return new Promise(function (resolve) {
var openDbRequest = indexedDB.open(BlurryRecognitionPreloader.writableDataPath);
function handleErrorOrNew() {
var _a;
(_a = openDbRequest === null || openDbRequest === void 0 ? void 0 : openDbRequest.result) === null || _a === void 0 ? void 0 : _a.close();
// this.error
resolve(false);
}
openDbRequest.onupgradeneeded = function () {
try {
openDbRequest.result.createObjectStore(BlurryRecognitionPreloader.fsObjectStoreName);
}
catch (error) {
// Ignored
}
};
openDbRequest.onsuccess = function () {
try {
var transaction = openDbRequest.result.transaction(BlurryRecognitionPreloader.fsObjectStoreName, "readonly");
transaction.onerror = handleErrorOrNew;
var storeKeysRequest_1 = transaction
.objectStore(BlurryRecognitionPreloader.fsObjectStoreName)
.getAllKeys();
storeKeysRequest_1.onsuccess = function () {
openDbRequest.result.close();
if ((__1.highEndBlurryRecognition
? BlurryRecognitionPreloader.highEndBlurryTableFiles
: BlurryRecognitionPreloader.defaultBlurryTableFiles).every(function (file) {
return storeKeysRequest_1.result.indexOf(file) !== -1;
})) {
return resolve(true);
}
else {
return resolve(false);
}
};
storeKeysRequest_1.onerror = handleErrorOrNew;
}
catch (error) {
handleErrorOrNew.call({ error: error });
}
};
openDbRequest.onblocked = openDbRequest.onerror = handleErrorOrNew;
});
};
BlurryRecognitionPreloader.prototype.dataCaptureWorkerOnMessage = function (ev) {
var _this = this;
var data = ev.data;
// istanbul ignore else
if (data[1] != null) {
switch (data[0]) {
case "context-created":
this.createNextBlurryTableSymbology();
break;
case "create-blurry-table-result":
this.readyBlurryRecognitionSymbologies.add(data[1]);
if ([barcode_1.Barcode.Symbology.EAN8, barcode_1.Barcode.Symbology.EAN13, barcode_1.Barcode.Symbology.UPCA, barcode_1.Barcode.Symbology.UPCE].includes(data[1])) {
this.readyBlurryRecognitionSymbologies.add(barcode_1.Barcode.Symbology.EAN13);
this.readyBlurryRecognitionSymbologies.add(barcode_1.Barcode.Symbology.EAN8);
this.readyBlurryRecognitionSymbologies.add(barcode_1.Barcode.Symbology.UPCA);
this.readyBlurryRecognitionSymbologies.add(barcode_1.Barcode.Symbology.UPCE);
}
else if ([barcode_1.Barcode.Symbology.CODE32, barcode_1.Barcode.Symbology.CODE39].includes(data[1])) {
this.readyBlurryRecognitionSymbologies.add(barcode_1.Barcode.Symbology.CODE32);
this.readyBlurryRecognitionSymbologies.add(barcode_1.Barcode.Symbology.CODE39);
}
this.eventEmitter.emit("blurryTablesUpdate", new Set(this.readyBlurryRecognitionSymbologies));
if (this.readyBlurryRecognitionSymbologies.size ===
BlurryRecognitionPreloader.availableBlurryRecognitionSymbologies.size) {
// Avoid data not being persisted if IndexedDB operations in WebWorker are slow
setTimeout(function () {
_this.dataCaptureWorker.terminate();
}, 250);
}
else {
this.createNextBlurryTableSymbology();
}
break;
// istanbul ignore next
default:
break;
}
}
};
BlurryRecognitionPreloader.writableDataPath = "/scandit_sync_folder_preload";
BlurryRecognitionPreloader.fsObjectStoreName = "FILE_DATA";
// From AndroidLowEnd
BlurryRecognitionPreloader.defaultBlurryTableFiles = [
"/20919bc5228479679a264521447f9c87.scandit",
"/855b1fdf70718074e40e97328ea23039.scandit",
"/92038ea8367cfcdfebed31e0ad1c5c6d.scandit",
"/1c02d3aa478da28ebf5756c342565017.scandit",
"/ce00c525c9f8160b0cd12b09fa739fbf.scandit",
"/e5e60e4cc82ecb0f1b7f7bfaabfe7a8c.scandit",
"/3a63262b342a4f603b3626a98565e174.scandit",
"/e9bb1a0e5ec3ddd037a91497c09d8daa.scandit",
"/f6f53a0c00683f6b349f29ff76107662.scandit",
"/41db165d92b2369b4e7c841e29ced06a.scandit",
"/4571aa251af4c3d3bd63f47a0b54d30d.scandit",
"/94c3ff79d8c922c01f048c1deac9d89b.scandit",
"/7a1d15cb731e1a8fd146427bb7920922.scandit",
"/b874f8f9aa42b909b68c8cb59db5b2aa.scandit",
"/f867458021a0bd9b2bd2448958e98d9b.scandit",
"/828281aceea050a47657fab7fc470b2c.scandit",
"/9e06fc65990c496de0da6c71376758b3.scandit",
"/ef939d962bc030919393e822be1ba6f7.scandit",
"/04c912268484e863833dcf31c8ad7898.scandit",
"/401b20aa6d4551f9d001c20581ece64e.scandit",
"/b8f73417d6947f4c4fc205329703804c.scandit", // msi-plessey
].map(function (path) {
return "".concat(BlurryRecognitionPreloader.writableDataPath).concat(path);
});
// From AndroidGeneric
BlurryRecognitionPreloader.highEndBlurryTableFiles = [
"/9acb7e350bb910f2a1309b31214f9a4e.scandit",
"/b2dc1168d2bb679c233068f078944e41.scandit",
"/4b93e8f2d0a529874f5737e04b9784c1.scandit",
"/4e9821a5898a46445b8beed46626581f.scandit",
"/260b8a8fdf8e5fbf2526e138c7c0bbb5.scandit",
"/8c561caef1b9c4b852811f5c2374bb8e.scandit",
"/f63809050de2702c9527eb1891b337e5.scandit",
"/576639d5aa0b5f5d19bfe3864eab749a.scandit",
"/e645b5549783972888fc1cf69163de27.scandit",
"/9dd619e2ae39d75ecbc1cb9391b04aad.scandit",
"/0fa0b08a89e9ce63edc91beab6206461.scandit",
"/c0a273dbcef08a1e4a9cc387752b4c0e.scandit",
"/00caaf030fbdfcec26df3f8d3a400f2e.scandit",
"/b53f643fcc542977ffe8ce30d1f8beb0.scandit",
"/825a85c14ca9e19e2bc211c8e82c1e53.scandit",
"/23b2c91f549629488800b671406ed399.scandit",
"/7c43295d738875ce8265ecf037fa1b12.scandit",
"/3f9b28270bc4a077fde6b547574d5780.scandit",
"/814cf529041339e4f6598e6b69b7c608.scandit",
"/ddc7990e91e2293216c98e6bb1ac024a.scandit",
"/75e3eaabf7987fdb433be1d1fe92032a.scandit",
"/497112cbe8674c21c4c8bd7f0e957b71.scandit",
"/94ae9b357c6061d489c10d7ac73e3139.scandit",
"/df4383c06c7a85a8e8c2a1d86b61e6bc.scandit",
"/5aee7e2ea252b3b05145493721caa9b1.scandit",
"/aeb733f6d7a86c4115826b2c89df2720.scandit",
"/c22f49a08f466b877208c4a31569bd9d.scandit",
"/1524b7b4fa54aee57369c54b86bd65f4.scandit",
"/cf3110c18bec369705b94e50aae077ab.scandit",
"/bb7b0c63371cfa0787a90b19c3650587.scandit",
"/6e4454c7a20910115e6653b1cd607e12.scandit",
"/492339332477a5c9efa2cb6701f754d3.scandit",
"/50919ffed0c9a78f19ff465bdfd4f2b8.scandit",
"/c0795f18a2ebfd0b6835be5ad787a040.scandit",
"/1e0a5fb89be9e843b96174b0c182727b.scandit",
"/14126c0d924e0128f6caca76ecdceb6d.scandit",
"/5f43256a6a2032966dd44c6a3eef53eb.scandit",
"/83bb18bb71dead54a013fe2cc85ad4f7.scandit",
"/6ee5a2338030d3282516040607182b26.scandit",
"/7a341c4ba35f02335fd3200ec02ff205.scandit",
"/6ebdbff2f3739b35ba8f68517451eb37.scandit",
"/a5ba033b43d4a2c80dab49eaa2d90162.scandit", // msi-plessey
].map(function (path) {
return "".concat(BlurryRecognitionPreloader.writableDataPath).concat(path);
});
// Roughly ordered by priority
BlurryRecognitionPreloader.availableBlurryRecognitionSymbologies = new Set([
barcode_1.Barcode.Symbology.EAN13,
barcode_1.Barcode.Symbology.EAN8,
barcode_1.Barcode.Symbology.CODE32,
barcode_1.Barcode.Symbology.CODE39,
barcode_1.Barcode.Symbology.CODE128,
barcode_1.Barcode.Symbology.CODE93,
barcode_1.Barcode.Symbology.INTERLEAVED_2_OF_5,
barcode_1.Barcode.Symbology.MSI_PLESSEY,
barcode_1.Barcode.Symbology.CODABAR,
barcode_1.Barcode.Symbology.UPCA,
barcode_1.Barcode.Symbology.UPCE, // Shared with EAN8, EAN13, UPCA
]);
return BlurryRecognitionPreloader;
}());
exports.BlurryRecognitionPreloader = BlurryRecognitionPreloader;
//# sourceMappingURL=blurryRecognitionPreloader.js.map

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,72 @@
/**
* An object containing details about the support level of the used OS/browser combination regarding
* the features needed by this library.
*/
export interface BrowserCompatibility {
/**
* Whether the full set of features required to have continuous camera video streaming are supported.
*/
readonly fullSupport: boolean;
/**
* Whether the set of features required to use a [[Scanner]] to perform scans (Single Image Mode) are supported.
*/
readonly scannerSupport: boolean;
/**
* The list of features that are missing.
*/
readonly missingFeatures: BrowserCompatibility.Feature[];
}
export declare namespace BrowserCompatibility {
/**
* Browser feature.
*/
enum Feature {
/**
* [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) -
* [current support?](https://caniuse.com/#feat=blobbuilder)
*/
BLOB = "blob",
/**
* [MediaDevices/getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) -
* [current support?](https://caniuse.com/#feat=stream)
*/
MEDIA_DEVICES = "mediaDevices",
/**
* [OffscreenCanvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas) -
* [current support?](https://caniuse.com/#feat=offscreencanvas)
*/
OFFSCREEN_CANVAS = "offscreenCanvas",
/**
* [Http/Https protocol](https://wiki.developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#Scheme_or_protocol)
*/
HTTP_PROTOCOL = "httpProtocol",
/**
* [Secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)
*/
SECURE_CONTEXT = "secureContext",
/**
* [URL/createObjectURL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL) -
* [current support?](https://caniuse.com/#feat=bloburls)
*/
URL_OBJECT = "urlObject",
/**
* [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) -
* [current support?](https://caniuse.com/#feat=webworkers)
*/
WEB_WORKERS = "webWorkers",
/**
* [WebAssembly](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/WebAssembly) -
* [current support?](https://caniuse.com/#feat=wasm)
*/
WEB_ASSEMBLY = "webAssembly",
/**
* WebAssembly without memory corruption (specific iOS version 11.2.2/11.2.5/11.2.6 bug)
*/
WEB_ASSEMBLY_ERROR_FREE = "webAssemblyErrorFree",
/**
* [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API) -
* [current support?](https://caniuse.com/#feat=webgl)
*/
WEBGL = "webgl"
}
}

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserCompatibility = void 0;
var BrowserCompatibility;
(function (BrowserCompatibility) {
/**
* Browser feature.
*/
var Feature;
(function (Feature) {
/**
* [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) -
* [current support?](https://caniuse.com/#feat=blobbuilder)
*/
Feature["BLOB"] = "blob";
/**
* [MediaDevices/getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) -
* [current support?](https://caniuse.com/#feat=stream)
*/
Feature["MEDIA_DEVICES"] = "mediaDevices";
/**
* [OffscreenCanvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas) -
* [current support?](https://caniuse.com/#feat=offscreencanvas)
*/
Feature["OFFSCREEN_CANVAS"] = "offscreenCanvas";
// tslint:disable: max-line-length
/**
* [Http/Https protocol](https://wiki.developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#Scheme_or_protocol)
*/
Feature["HTTP_PROTOCOL"] = "httpProtocol";
/**
* [Secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)
*/
Feature["SECURE_CONTEXT"] = "secureContext";
/**
* [URL/createObjectURL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL) -
* [current support?](https://caniuse.com/#feat=bloburls)
*/
Feature["URL_OBJECT"] = "urlObject";
/**
* [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) -
* [current support?](https://caniuse.com/#feat=webworkers)
*/
Feature["WEB_WORKERS"] = "webWorkers";
/**
* [WebAssembly](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/WebAssembly) -
* [current support?](https://caniuse.com/#feat=wasm)
*/
Feature["WEB_ASSEMBLY"] = "webAssembly";
/**
* WebAssembly without memory corruption (specific iOS version 11.2.2/11.2.5/11.2.6 bug)
*/
Feature["WEB_ASSEMBLY_ERROR_FREE"] = "webAssemblyErrorFree";
/**
* [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API) -
* [current support?](https://caniuse.com/#feat=webgl)
*/
Feature["WEBGL"] = "webgl";
})(Feature = BrowserCompatibility.Feature || (BrowserCompatibility.Feature = {}));
})(BrowserCompatibility = exports.BrowserCompatibility || (exports.BrowserCompatibility = {}));
//# sourceMappingURL=browserCompatibility.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"browserCompatibility.js","sourceRoot":"","sources":["../../../src/lib/browserCompatibility.ts"],"names":[],"mappings":";;;AAmBA,IAAiB,oBAAoB,CAsDpC;AAtDD,WAAiB,oBAAoB;IACnC;;OAEG;IACH,IAAY,OAiDX;IAjDD,WAAY,OAAO;QACjB;;;WAGG;QACH,wBAAa,CAAA;QACb;;;WAGG;QACH,yCAA8B,CAAA;QAC9B;;;WAGG;QACH,+CAAoC,CAAA;QACpC,kCAAkC;QAClC;;WAEG;QACH,yCAA8B,CAAA;QAC9B;;WAEG;QACH,2CAAgC,CAAA;QAChC;;;WAGG;QACH,mCAAwB,CAAA;QACxB;;;WAGG;QACH,qCAA0B,CAAA;QAC1B;;;WAGG;QACH,uCAA4B,CAAA;QAC5B;;WAEG;QACH,2DAAgD,CAAA;QAChD;;;WAGG;QACH,0BAAe,CAAA;IACjB,CAAC,EAjDW,OAAO,GAAP,4BAAO,KAAP,4BAAO,QAiDlB;AACH,CAAC,EAtDgB,oBAAoB,GAApB,4BAAoB,KAApB,4BAAoB,QAsDpC"}

View File

@@ -0,0 +1,87 @@
import UAParser from "ua-parser-js";
export { UAParser };
import { BrowserCompatibility } from "./browserCompatibility";
export declare namespace BrowserHelper {
/**
* @hidden
*/
interface Browser {
name?: string;
version?: string;
}
/**
* @hidden
*/
interface CPU {
architecture?: string;
}
/**
* @hidden
*/
interface Device {
model?: string;
vendor?: string;
type?: string;
}
/**
* @hidden
*/
interface Engine {
name?: string;
version?: string;
}
/**
* @hidden
*/
interface OS {
name?: string;
version?: string;
}
/**
* @hidden
*/
export const userAgentInfo: {
getBrowser(): Browser;
getOS(): OS;
getEngine(): Engine;
getDevice(): Device;
getCPU(): CPU;
getUA(): string;
setUA(uastring: string): void;
};
/**
* @hidden
*/
export const canvas: HTMLCanvasElement;
/**
* @hidden
*
* @returns Whether the device is a desktop/laptop for sure.
*/
export function isDesktopDevice(): boolean;
/**
* @returns The built [[BrowserCompatibility]] object representing the current OS/Browser's support for features.
*/
export function checkBrowserCompatibility(): BrowserCompatibility;
/**
* @hidden
*
* Get a device id for the current browser.
*
* When available it's retrieved from localStorage, as fallback from cookies (used by older library versions),
* when not available it's randomly generated and stored in localStorage to be retrieved by later calls and returned.
*
* @returns The device id for the current browser.
*/
export function getDeviceId(): string;
/**
* @hidden
*
* Check if a given object is a valid HTMLElement
*
* @param object The object to check.
* @returns Whether the given object is a valid HTMLElement.
*/
export function isValidHTMLElement(object: any): boolean;
export {};
}

View File

@@ -0,0 +1,170 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserHelper = exports.UAParser = void 0;
var tslib_1 = require("tslib");
var js_cookie_1 = tslib_1.__importDefault(require("js-cookie"));
var ua_parser_js_1 = tslib_1.__importDefault(require("ua-parser-js"));
exports.UAParser = ua_parser_js_1.default;
var browserCompatibility_1 = require("./browserCompatibility");
var BrowserHelper;
(function (BrowserHelper) {
/**
* @hidden
*/
BrowserHelper.userAgentInfo = new ua_parser_js_1.default(navigator.userAgent);
/**
* @hidden
*/
BrowserHelper.canvas = document.createElement("canvas"); // For some reason, export is needed!
/**
* @hidden
*
* @returns Whether the device is a desktop/laptop for sure.
*/
function isDesktopDevice() {
var _a;
if ("orientation" in window) {
// Only mobile browsers have this (deprecated but still available) property
return false;
}
else {
// Query for no "coarse" pointing device available (finger, touchscreen)
var query = "(any-pointer: coarse)"; // Spaces matter!
var mediaQueryList = (_a = window.matchMedia) === null || _a === void 0 ? void 0 : _a.call(window, query);
// If the device doesn't have a touchscreen, it's a computer
if (navigator.maxTouchPoints === 0 || ((mediaQueryList === null || mediaQueryList === void 0 ? void 0 : mediaQueryList.media) === query && (mediaQueryList === null || mediaQueryList === void 0 ? void 0 : mediaQueryList.matches) === false)) {
return true;
}
else {
return false;
}
}
}
BrowserHelper.isDesktopDevice = isDesktopDevice;
/**
* @returns The built [[BrowserCompatibility]] object representing the current OS/Browser's support for features.
*/
function checkBrowserCompatibility() {
function objectHasPropertyWithType(object, propertyNames, propertyType) {
// tslint:disable-next-line:no-any
var objectProperty = object[propertyNames[0]];
if (objectProperty == null) {
return false;
}
if (propertyNames.length === 1) {
return typeof objectProperty === propertyType;
}
else {
return ((typeof objectProperty === "function" || typeof objectProperty === "object") &&
objectHasPropertyWithType(objectProperty, propertyNames.slice(1), propertyType));
}
}
function isBrokenWebAssemblyOS(os) {
return os.name === "iOS" && os.version != null && ["11.2.2", "11.2.5", "11.2.6"].includes(os.version);
}
var fullSupport = true;
var scannerSupport = true;
var missingFeatures = [];
if (!location.protocol.startsWith("http")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.HTTP_PROTOCOL);
fullSupport = scannerSupport = false;
}
if (objectHasPropertyWithType(window, ["isSecureContext"], "boolean") && window.isSecureContext === false) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.SECURE_CONTEXT);
// Don't disable full support in case browser is set to allow camera video streaming access in insecure contexts
}
if (!objectHasPropertyWithType(navigator, ["mediaDevices", "getUserMedia"], "function") &&
!objectHasPropertyWithType(navigator, ["enumerateDevices"], "function") &&
!objectHasPropertyWithType(window, ["MediaStreamTrack", "getSources"], "function")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.MEDIA_DEVICES);
fullSupport = false;
}
if (!objectHasPropertyWithType(window, ["Worker"], "function")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.WEB_WORKERS);
fullSupport = scannerSupport = false;
}
if (!objectHasPropertyWithType(window, ["WebAssembly"], "object")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.WEB_ASSEMBLY);
fullSupport = scannerSupport = false;
}
if (!objectHasPropertyWithType(window, ["Blob"], "function")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.BLOB);
fullSupport = scannerSupport = false;
}
if (!objectHasPropertyWithType(window, ["URL", "createObjectURL"], "function")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.URL_OBJECT);
fullSupport = scannerSupport = false;
}
if (!objectHasPropertyWithType(window, ["OffscreenCanvas"], "function")) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.OFFSCREEN_CANVAS);
}
try {
if (!objectHasPropertyWithType(window, ["WebGLRenderingContext"], "function") ||
(BrowserHelper.canvas.getContext("webgl") == null && BrowserHelper.canvas.getContext("experimental-webgl") == null)) {
throw new Error();
}
}
catch (_a) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.WEBGL);
}
var userAgentOS = BrowserHelper.userAgentInfo.getOS();
if (isBrokenWebAssemblyOS(userAgentOS)) {
missingFeatures.push(browserCompatibility_1.BrowserCompatibility.Feature.WEB_ASSEMBLY_ERROR_FREE);
fullSupport = scannerSupport = false;
}
return {
fullSupport: fullSupport,
scannerSupport: scannerSupport,
missingFeatures: missingFeatures,
};
}
BrowserHelper.checkBrowserCompatibility = checkBrowserCompatibility;
/**
* @hidden
*
* Get a device id for the current browser.
*
* When available it's retrieved from localStorage, as fallback from cookies (used by older library versions),
* when not available it's randomly generated and stored in localStorage to be retrieved by later calls and returned.
*
* @returns The device id for the current browser.
*/
function getDeviceId() {
var devideIdKey = "scandit-device-id";
var deviceId = localStorage.getItem(devideIdKey);
if (deviceId != null && deviceId !== "") {
return deviceId;
}
deviceId = js_cookie_1.default.get(devideIdKey);
if (deviceId != null && deviceId !== "") {
localStorage.setItem(devideIdKey, deviceId);
return deviceId;
}
var randomDeviceIdBytes = new Uint8Array(20);
crypto.getRandomValues(randomDeviceIdBytes);
deviceId = Array.from(randomDeviceIdBytes)
.map(function (byteNumber) {
var byteHex = byteNumber.toString(16);
return byteHex.length === 1 ? /* istanbul ignore next */ "0".concat(byteHex) : byteHex;
})
.join("");
localStorage.setItem(devideIdKey, deviceId);
return deviceId;
}
BrowserHelper.getDeviceId = getDeviceId;
/**
* @hidden
*
* Check if a given object is a valid HTMLElement
*
* @param object The object to check.
* @returns Whether the given object is a valid HTMLElement.
*/
// tslint:disable-next-line:no-any
function isValidHTMLElement(object) {
return (object instanceof HTMLElement ||
(object != null && typeof object === "object" && typeof object.tagName === "string"));
}
BrowserHelper.isValidHTMLElement = isValidHTMLElement;
})(BrowserHelper = exports.BrowserHelper || (exports.BrowserHelper = {}));
//# sourceMappingURL=browserHelper.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"browserHelper.js","sourceRoot":"","sources":["../../../src/lib/browserHelper.ts"],"names":[],"mappings":";;;;AAAA,gEAAgC;AAChC,sEAAoC;AAC3B,mBADF,sBAAQ,CACE;AAEjB,+DAA8D;AAE9D,IAAiB,aAAa,CAuO7B;AAvOD,WAAiB,aAAa;IA0C5B;;OAEG;IACU,2BAAa,GAQtB,IAAI,sBAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEtC;;OAEG;IACU,oBAAM,GAAsB,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,qCAAqC;IAEhH;;;;OAIG;IACH,SAAgB,eAAe;;QAC7B,IAAI,aAAa,IAAI,MAAM,EAAE;YAC3B,2EAA2E;YAC3E,OAAO,KAAK,CAAC;SACd;aAAM;YACL,wEAAwE;YACxE,IAAM,KAAK,GAAW,uBAAuB,CAAC,CAAC,iBAAiB;YAChE,IAAM,cAAc,GAA+B,MAAA,MAAM,CAAC,UAAU,uDAAG,KAAK,CAAC,CAAC;YAC9E,4DAA4D;YAC5D,IAAI,SAAS,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,CAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,KAAK,MAAK,KAAK,IAAI,CAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,OAAO,MAAK,KAAK,CAAC,EAAE;gBAC5G,OAAO,IAAI,CAAC;aACb;iBAAM;gBACL,OAAO,KAAK,CAAC;aACd;SACF;IACH,CAAC;IAfe,6BAAe,kBAe9B,CAAA;IAED;;OAEG;IACH,SAAgB,yBAAyB;QACvC,SAAS,yBAAyB,CAAC,MAAc,EAAE,aAAuB,EAAE,YAAoB;YAC9F,kCAAkC;YAClC,IAAM,cAAc,GAAc,MAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,IAAI,cAAc,IAAI,IAAI,EAAE;gBAC1B,OAAO,KAAK,CAAC;aACd;YACD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC9B,OAAO,OAAO,cAAc,KAAK,YAAY,CAAC;aAC/C;iBAAM;gBACL,OAAO,CACL,CAAC,OAAO,cAAc,KAAK,UAAU,IAAI,OAAO,cAAc,KAAK,QAAQ,CAAC;oBAC5E,yBAAyB,CAAC,cAAc,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAChF,CAAC;aACH;QACH,CAAC;QAED,SAAS,qBAAqB,CAAC,EAAM;YACnC,OAAO,EAAE,CAAC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QACxG,CAAC;QAED,IAAI,WAAW,GAAY,IAAI,CAAC;QAChC,IAAI,cAAc,GAAY,IAAI,CAAC;QACnC,IAAM,eAAe,GAAmC,EAAE,CAAC;QAE3D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;YACzC,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YACjE,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;SACtC;QAED,IAAI,yBAAyB,CAAC,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,eAAe,KAAK,KAAK,EAAE;YACzG,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAClE,gHAAgH;SACjH;QAED,IACE,CAAC,yBAAyB,CAAC,SAAS,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE,UAAU,CAAC;YACnF,CAAC,yBAAyB,CAAC,SAAS,EAAE,CAAC,kBAAkB,CAAC,EAAE,UAAU,CAAC;YACvE,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,kBAAkB,EAAE,YAAY,CAAC,EAAE,UAAU,CAAC,EAClF;YACA,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YACjE,WAAW,GAAG,KAAK,CAAC;SACrB;QAED,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,EAAE;YAC9D,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAC/D,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;SACtC;QAED,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,EAAE;YACjE,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAChE,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;SACtC;QAED,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,EAAE;YAC5D,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxD,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;SACtC;QAED,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,EAAE,UAAU,CAAC,EAAE;YAC9E,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC9D,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;SACtC;QAED,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC,EAAE;YACvE,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;SACrE;QAED,IAAI;YACF,IACE,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,uBAAuB,CAAC,EAAE,UAAU,CAAC;gBACzE,CAAC,cAAA,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,cAAA,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC,EACvF;gBACA,MAAM,IAAI,KAAK,EAAE,CAAC;aACnB;SACF;QAAC,WAAM;YACN,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SAC1D;QAED,IAAM,WAAW,GAAO,cAAA,aAAa,CAAC,KAAK,EAAE,CAAC;QAC9C,IAAI,qBAAqB,CAAC,WAAW,CAAC,EAAE;YACtC,eAAe,CAAC,IAAI,CAAC,2CAAoB,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;YAC3E,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;SACtC;QAED,OAAO;YACL,WAAW,aAAA;YACX,cAAc,gBAAA;YACd,eAAe,iBAAA;SAChB,CAAC;IACJ,CAAC;IA1Fe,uCAAyB,4BA0FxC,CAAA;IAED;;;;;;;;;OASG;IACH,SAAgB,WAAW;QACzB,IAAM,WAAW,GAAW,mBAAmB,CAAC;QAChD,IAAI,QAAQ,GAA8B,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC5E,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,EAAE,EAAE;YACvC,OAAO,QAAQ,CAAC;SACjB;QAED,QAAQ,GAAG,mBAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACpC,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,EAAE,EAAE;YACvC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAE5C,OAAO,QAAQ,CAAC;SACjB;QAED,IAAM,mBAAmB,GAAe,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC;QAC5C,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;aACvC,GAAG,CAAC,UAAC,UAAU;YACd,IAAM,OAAO,GAAW,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAEhD,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,WAAI,OAAO,CAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACnF,CAAC,CAAC;aACD,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAE5C,OAAO,QAAQ,CAAC;IAClB,CAAC;IA3Be,yBAAW,cA2B1B,CAAA;IAED;;;;;;;OAOG;IACH,kCAAkC;IAClC,SAAgB,kBAAkB,CAAC,MAAW;QAC5C,OAAO,CACL,MAAM,YAAY,WAAW;YAC7B,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CACrF,CAAC;IACJ,CAAC;IALe,gCAAkB,qBAKjC,CAAA;AACH,CAAC,EAvOgB,aAAa,GAAb,qBAAa,KAAb,qBAAa,QAuO7B"}

View File

@@ -0,0 +1,45 @@
/**
* A camera for video input available to be used on the device.
*/
export interface Camera {
/**
* The unique identifier for the device, can change between page loads.
*/
readonly deviceId: string;
/**
* The label describing the device.
*/
readonly label: string;
/**
* The type (facing mode/direction) of camera: back (environment) or front (user).
*
* Not guaranteed to be correct: depending on device, browser and camera it could not correspond to the camera's real
* type.
*/
readonly cameraType: Camera.Type;
/**
* The current video resolution if and when the camera is in use, given as width and height in pixels.
*/
currentResolution?: {
width: number;
height: number;
};
}
export declare namespace Camera {
/**
* Camera type (facing mode/direction).
*
* Not guaranteed to be correct: depending on device, browser and camera it could not correspond to the camera's real
* type.
*/
enum Type {
/**
* Front (user) facing camera.
*/
FRONT = "front",
/**
* Back (environment) facing camera.
*/
BACK = "back"
}
}

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Camera = void 0;
var Camera;
(function (Camera) {
/**
* Camera type (facing mode/direction).
*
* Not guaranteed to be correct: depending on device, browser and camera it could not correspond to the camera's real
* type.
*/
var Type;
(function (Type) {
/**
* Front (user) facing camera.
*/
Type["FRONT"] = "front";
/**
* Back (environment) facing camera.
*/
Type["BACK"] = "back";
})(Type = Camera.Type || (Camera.Type = {}));
})(Camera = exports.Camera || (exports.Camera = {}));
//# sourceMappingURL=camera.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../../../src/lib/camera.ts"],"names":[],"mappings":";;;AAyBA,IAAiB,MAAM,CAiBtB;AAjBD,WAAiB,MAAM;IACrB;;;;;OAKG;IACH,IAAY,IASX;IATD,WAAY,IAAI;QACd;;WAEG;QACH,uBAAe,CAAA;QACf;;WAEG;QACH,qBAAa,CAAA;IACf,CAAC,EATW,IAAI,GAAJ,WAAI,KAAJ,WAAI,QASf;AACH,CAAC,EAjBgB,MAAM,GAAN,cAAM,KAAN,cAAM,QAiBtB"}

View File

@@ -0,0 +1,107 @@
import { CameraResolutionConstraint } from "./barcodePicker/cameraManager";
import { Camera } from "./camera";
/**
* A helper object to interact with cameras.
*/
export declare namespace CameraAccess {
/**
* @hidden
*
* Overrides for main camera for a given camera type on a desktop/laptop device, set when accessing an initial camera.
*/
const mainCameraForTypeOverridesOnDesktop: Map<Camera.Type, Camera>;
/**
* @hidden
*
* To be accessed directly only for tests.
*
* The mapping from deviceIds to camera objects.
*/
const deviceIdToCameraObjects: Map<string, Camera>;
/**
* @hidden
*
* To be accessed directly only for tests.
*
* The list of inaccessible deviceIds.
*/
const inaccessibleDeviceIds: Set<string>;
/**
* @hidden
*
* Get the main camera for the given camera type.
*
* @param cameras The array of available [[Camera]] objects.
* @param cameraType The wanted camera type.
* @returns The main camera matching the wanted camera type.
*/
function getMainCameraForType(cameras: Camera[], cameraType: Camera.Type): Camera | undefined;
/**
* @hidden
*
* Sort the given cameras in order of priority of access based on the given camera type.
*
* @param cameras The array of available [[Camera]] objects.
* @param cameraType The preferred camera type.
* @returns The sorted cameras.
*/
function sortCamerasForCameraType(cameras: Camera[], cameraType: Camera.Type): Camera[];
/**
* @hidden
*
* Adjusts the camera's information based on the given currently active video stream.
*
* @param mediaStream The currently active `MediaStream` object.
* @param camera The currently active [[Camera]] object associated with the video stream.
*/
function adjustCameraFromMediaStream(mediaStream: MediaStream, camera: Camera): void;
/**
* Get a list of cameras (if any) available on the device, a camera access permission is requested to the user
* the first time this method is called if needed.
*
* If the browser is incompatible the returned promise is rejected with a `UnsupportedBrowserError` error.
*
* When refreshing available devices, if updated deviceId information is detected, cameras' deviceId are updated
* accordingly. This could happen after a camera access and stop in some situations.
*
* @param refreshDevices Force a call to refresh available video devices even when information is already available.
* @param cameraAlreadyAccessed Hint that a camera has already been accessed before, avoiding a possible initial
* camera access permission request on the first call, in cases this cannot be already reliably detected.
* @returns A promise resolving to the array of available [[Camera]] objects (could be empty).
*/
function getCameras(refreshDevices?: boolean, cameraAlreadyAccessed?: boolean): Promise<Camera[]>;
/**
* @hidden
*
* Try to access a given camera for video input at the given resolution level.
*
* If a camera is inaccessible because of errors, then it's added to the inaccessible device list. If the specific
* error is of type `OverconstrainedError` or `NotReadableError` however, this procedure is done later on via a
* separate external logic; also, in case of an error of type `NotAllowedError` (permission denied) this procedure is
* not executed, in order to possibly recover if and when the user allows the camera to be accessed again.
* This is done to allow checking if the camera can still be accessed via an updated deviceId when deviceId
* information changes, or if it should then be confirmed to be considered inaccessible.
*
* Depending on parameters, device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `AbortError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
* - `OverconstrainedError`
*
* @param cameraResolutionConstraint The resolution constraint.
* @param camera The camera to try to access for video input.
* @returns A promise resolving to the `MediaStream` object coming from the accessed camera.
*/
function accessCameraStream(cameraResolutionConstraint: CameraResolutionConstraint, camera: Camera): Promise<MediaStream>;
/**
* @hidden
*
* Mark a camera to be inaccessible and thus excluded from the camera list returned by [[getCameras]].
*
* @param camera The camera to mark to be inaccessible.
*/
function markCameraAsInaccessible(camera: Camera): void;
}

View File

@@ -0,0 +1,719 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CameraAccess = void 0;
var tslib_1 = require("tslib");
var cameraManager_1 = require("./barcodePicker/cameraManager");
var browserCompatibility_1 = require("./browserCompatibility");
var browserHelper_1 = require("./browserHelper");
var camera_1 = require("./camera");
var customError_1 = require("./customError");
var logger_1 = require("./logger");
var unsupportedBrowserError_1 = require("./unsupportedBrowserError");
/**
* A helper object to interact with cameras.
*/
var CameraAccess;
(function (CameraAccess) {
/**
* @hidden
*
* Standard error names mapping.
*/
var standardErrorNamesMapping = new Map([
["DeviceCaptureError", "AbortError"],
["NotSupportedError", "AbortError"],
["ScreenCaptureError", "AbortError"],
["TabCaptureError", "AbortError"],
["TypeError", "AbortError"],
["InvalidStateError", "NotAllowedError"],
["MediaDeviceFailedDueToShutdown", "NotAllowedError"],
["MediaDeviceKillSwitchOn", "NotAllowedError"],
["PermissionDeniedError", "NotAllowedError"],
["PermissionDismissedError", "NotAllowedError"],
["DevicesNotFoundError", "NotFoundError"],
["SourceUnavailableError", "NotReadableError"],
["TrackStartError", "NotReadableError"],
["ConstraintNotSatisfiedError", "OverconstrainedError"],
]);
/**
* @hidden
*
* Handle localized camera labels. Supported languages:
* English, German, French, Spanish (spain), Portuguese (brasil), Portuguese (portugal), Italian,
* Chinese (simplified), Chinese (traditional), Japanese, Russian, Turkish, Dutch, Arabic, Thai, Swedish,
* Danish, Vietnamese, Norwegian, Polish, Finnish, Indonesian, Hebrew, Greek, Romanian, Hungarian, Czech,
* Catalan, Slovak, Ukraininan, Croatian, Malay, Hindi.
*/
var backCameraKeywords = [
"rear",
"back",
"rück",
"arrière",
"trasera",
"trás",
"traseira",
"posteriore",
"后面",
"後面",
"背面",
"后置",
"後置",
"背置",
"задней",
"الخلفية",
"후",
"arka",
"achterzijde",
"หลัง",
"baksidan",
"bagside",
"sau",
"bak",
"tylny",
"takakamera",
"belakang",
"אחורית",
"πίσω",
"spate",
"hátsó",
"zadní",
"darrere",
"zadná",
"задня",
"stražnja",
"belakang",
"बैक",
];
/**
* @hidden
*
* The (cached) list of available video devices, updated when [[getCameras]] is called for the first time and after
* subsequent calls with the *refreshDevices* parameter enabled. The contained devices' order never changes, howver
* their deviceIds could change when they are retrieved again after a camera access and stop in some situations.
*/
var availableVideoDevices;
/**
* @hidden
*
* Whether the currently cached available devices are out of date because of a `devicechange` event.
*/
var outdatedDevices = false;
/**
* @hidden
*
* Overrides for main camera for a given camera type on a desktop/laptop device, set when accessing an initial camera.
*/
CameraAccess.mainCameraForTypeOverridesOnDesktop = new Map();
/**
* @hidden
*
* To be accessed directly only for tests.
*
* The mapping from deviceIds to camera objects.
*/
CameraAccess.deviceIdToCameraObjects = new Map();
/**
* @hidden
*
* To be accessed directly only for tests.
*
* The list of inaccessible deviceIds.
*/
CameraAccess.inaccessibleDeviceIds = new Set();
/**
* @hidden
*
* Listen to `devicechange` events.
*/
function deviceChangeListener() {
outdatedDevices = true;
}
/**
* @hidden
*
* @param label The camera label.
* @returns Whether the label mentions the camera being a back-facing one.
*/
function isBackCameraLabel(label) {
var lowercaseLabel = label.toLowerCase();
return backCameraKeywords.some(function (keyword) {
return lowercaseLabel.includes(keyword);
});
}
/**
* @hidden
*
* Map non-standard error names to standard ones.
*
* @param error The error object.
*/
function mapNonStandardErrorName(error) {
var _a;
var name;
if (error.message === "Invalid constraint") {
name = "OverconstrainedError";
}
else {
name = (_a = standardErrorNamesMapping.get(error.name)) !== null && _a !== void 0 ? _a : error.name;
}
Object.defineProperty(error, "name", {
value: name,
});
}
/**
* @hidden
*
* Get the main camera for the given camera type.
*
* @param cameras The array of available [[Camera]] objects.
* @param cameraType The wanted camera type.
* @returns The main camera matching the wanted camera type.
*/
function getMainCameraForType(cameras, cameraType) {
var mainCameraForType;
if (browserHelper_1.BrowserHelper.isDesktopDevice()) {
// When the device is a desktop/laptop, the overridden camera for the given type or, if not present, the first
// camera of the given type is the main one.
if (CameraAccess.mainCameraForTypeOverridesOnDesktop.has(cameraType)) {
mainCameraForType = CameraAccess.mainCameraForTypeOverridesOnDesktop.get(cameraType);
}
else {
// Note that if the device is a desktop/laptop, with no labels all cameras are assumed to be front ones,
// so this will return the first camera as the main front one and none for the back one.
mainCameraForType = cameras.filter(function (camera) {
return camera.cameraType === cameraType;
})[0];
}
}
else {
var allHaveBlankLabel = cameras.every(function (camera) {
return camera.label === "";
});
var allHaveNonEmptyLabel = cameras.every(function (camera) {
return camera.label !== "";
});
var someHaveLabel = cameras.length > 1 && !allHaveBlankLabel && !allHaveNonEmptyLabel;
if (allHaveBlankLabel) {
// When no camera label is available cameras are already in front to back order, assume main front camera is the
// first one and main back camera is the last one.
mainCameraForType = cameras[cameraType === camera_1.Camera.Type.FRONT ? 0 : cameras.length - 1];
}
else if (someHaveLabel) {
// When only a few cameras have labels, we may be in a webview where only labels from accessed stream are
// available.
var cameraOfType = cameras.filter(function (camera) {
return camera.cameraType === cameraType;
});
if (cameraOfType.length === 1) {
mainCameraForType = cameraOfType[0];
}
else if (cameraOfType.length > 1) {
// Assume main front camera is the first one and main back camera is the last one.
mainCameraForType = cameraOfType[cameraType === camera_1.Camera.Type.FRONT ? 0 : cameraOfType.length - 1];
}
}
else {
mainCameraForType = cameras
.filter(function (camera) {
return camera.cameraType === cameraType;
})
// sort so that camera list looks like ['camera1 0', 'camera1 1', 'camera2 0', 'camera2 1']
.sort(function (camera1, camera2) {
return camera1.label.localeCompare(camera2.label);
})[0];
}
}
return mainCameraForType;
}
CameraAccess.getMainCameraForType = getMainCameraForType;
/**
* @hidden
*
* Sort the given cameras in order of priority of access based on the given camera type.
*
* @param cameras The array of available [[Camera]] objects.
* @param cameraType The preferred camera type.
* @returns The sorted cameras.
*/
function sortCamerasForCameraType(cameras, cameraType) {
function prioritizeMainCameraOverride(prioritizedCameras, currentCameraType) {
var mainCameraOverride = CameraAccess.mainCameraForTypeOverridesOnDesktop.get(currentCameraType);
if (mainCameraOverride != null && prioritizedCameras.includes(mainCameraOverride)) {
prioritizedCameras = prioritizedCameras.filter(function (camera) {
return camera !== mainCameraOverride;
});
prioritizedCameras.unshift(mainCameraOverride);
}
return prioritizedCameras;
}
var frontCameras = cameras.filter(function (camera) {
return camera.cameraType === camera_1.Camera.Type.FRONT;
});
var backCameras = cameras.filter(function (camera) {
return camera.cameraType === camera_1.Camera.Type.BACK;
});
if (browserHelper_1.BrowserHelper.isDesktopDevice()) {
// When the device is a desktop/laptop, the cameras for each type are already ordered, we move the overrides
// first if present and change front / back group order if needed.
frontCameras = prioritizeMainCameraOverride(frontCameras, camera_1.Camera.Type.FRONT);
backCameras = prioritizeMainCameraOverride(backCameras, camera_1.Camera.Type.BACK);
}
else if (cameras.every(function (camera) {
return camera.label === "";
})) {
// When no camera label is available cameras are already in front to back order, we assume front cameras are
// ordered and back cameras are in reversed order (try to access last first), and we change front / back group
// order if needed.
backCameras.reverse();
}
else {
frontCameras.sort(function (camera1, camera2) {
return camera1.label.localeCompare(camera2.label);
});
backCameras.sort(function (camera1, camera2) {
return camera1.label.localeCompare(camera2.label);
});
}
return cameraType === camera_1.Camera.Type.FRONT ? tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(frontCameras), false), tslib_1.__read(backCameras), false) : tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(backCameras), false), tslib_1.__read(frontCameras), false);
}
CameraAccess.sortCamerasForCameraType = sortCamerasForCameraType;
/**
* @hidden
*
* Adjusts the camera's information based on the given currently active video stream.
*
* @param mediaStream The currently active `MediaStream` object.
* @param camera The currently active [[Camera]] object associated with the video stream.
*/
function adjustCameraFromMediaStream(mediaStream, camera) {
var videoTracks = mediaStream.getVideoTracks();
if (videoTracks.length !== 0) {
var mediaStreamTrack = videoTracks[0];
var mediaTrackSettings = void 0;
if (typeof mediaStreamTrack.getSettings === "function") {
mediaTrackSettings = mediaStreamTrack.getSettings();
if ((mediaTrackSettings === null || mediaTrackSettings === void 0 ? void 0 : mediaTrackSettings.facingMode) != null && mediaTrackSettings.facingMode.length > 0) {
camera.cameraType =
mediaTrackSettings.facingMode === "environment" ? camera_1.Camera.Type.BACK : camera_1.Camera.Type.FRONT;
}
}
if (mediaStreamTrack.label != null && mediaStreamTrack.label.length > 0) {
camera.label = mediaStreamTrack.label;
}
}
}
CameraAccess.adjustCameraFromMediaStream = adjustCameraFromMediaStream;
/**
* @hidden
*
* @param devices The list of available devices.
* @returns The extracted list of accessible camera objects initialized from the given devices.
*/
function extractAccessibleCamerasFromDevices(devices) {
function createCamera(videoDevice, index, videoDevices) {
var _a;
if (CameraAccess.deviceIdToCameraObjects.has(videoDevice.deviceId)) {
return CameraAccess.deviceIdToCameraObjects.get(videoDevice.deviceId);
}
var label = (_a = videoDevice.label) !== null && _a !== void 0 ? _a : "";
var cameraType;
if (!browserHelper_1.BrowserHelper.isDesktopDevice() &&
videoDevices.every(function (device) {
return device.label === "" && !CameraAccess.deviceIdToCameraObjects.has(device.deviceId);
})) {
// When the device is not a desktop/laptop and no camera label is available, assume the camera is a front one
// if it's the only one or comes in the first half of the list of cameras (if an odd number of cameras is
// available, it's more likely to have more back than front ones).
cameraType =
videoDevices.length === 1 || index + 1 <= Math.floor(videoDevices.length / 2)
? camera_1.Camera.Type.FRONT
: camera_1.Camera.Type.BACK;
}
else {
// Note that if the device is a desktop/laptop, unless the label specifies a back camera, a front one is assumed
cameraType = isBackCameraLabel(label) ? camera_1.Camera.Type.BACK : camera_1.Camera.Type.FRONT;
}
return {
deviceId: videoDevice.deviceId,
label: label,
cameraType: cameraType,
};
}
var cameras = devices
.map(createCamera)
.map(function (camera) {
// If it's the initial camera, do nothing
if (camera.deviceId !== "") {
CameraAccess.deviceIdToCameraObjects.set(camera.deviceId, camera);
}
return camera;
})
.filter(function (camera) {
// Ignore infrared cameras as they often fail to be accessed and are not useful in any case
return !/\b(?:ir|infrared)\b/i.test(camera.label);
})
.filter(function (camera) {
return !CameraAccess.inaccessibleDeviceIds.has(camera.deviceId);
});
if (!browserHelper_1.BrowserHelper.isDesktopDevice() &&
cameras.length > 1 &&
!cameras.some(function (camera) {
return camera.cameraType === camera_1.Camera.Type.BACK;
})) {
// When the device is not a desktop/laptop check if cameras are labeled with resolution information, if that's the
// case, take the higher - resolution one, otherwise pick the last camera (it's not true that the primary camera
// is first in most scenarios) and mark it as the back one.
var backCameraIndex = cameras.length - 1;
var cameraResolutions = cameras.map(function (camera) {
var match = camera.label.match(/\b([0-9]+)MP?\b/i);
if (match != null) {
return parseInt(match[1], 10);
}
return NaN;
});
if (!cameraResolutions.some(function (cameraResolution) {
return isNaN(cameraResolution);
})) {
backCameraIndex = cameraResolutions.lastIndexOf(Math.max.apply(Math, tslib_1.__spreadArray([], tslib_1.__read(cameraResolutions), false)));
}
cameras[backCameraIndex].cameraType = camera_1.Camera.Type.BACK;
}
return cameras;
}
/**
* @hidden
*
* @returns The stream, if necessary, accessed to provide access to complete device information
*/
function getStreamForDeviceAccessPermission() {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!(availableVideoDevices != null &&
availableVideoDevices.length > 0 &&
availableVideoDevices.every(function (device) {
return device.label === "" && !CameraAccess.deviceIdToCameraObjects.has(device.deviceId);
}))) return [3 /*break*/, 4];
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
video: true,
audio: false,
})];
case 2: return [2 /*return*/, _b.sent()];
case 3:
_a = _b.sent();
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
}
/**
* @hidden
*
* Checks and adjust cameras' deviceId information and related information if a change is detected. We can rely on the
* fact that devices are returned in the same order even when deviceId information changes.
*
* @param oldAvailableDevices The old list of available devices before deviceId information was refreshed.
* @param newAvailableDevices The new list of available devices after deviceId information was refreshed.
*/
function checkAndUpdateCameraDeviceIdInformation(oldAvailableDevices, newAvailableDevices) {
if (newAvailableDevices.length > 0 &&
oldAvailableDevices.length === newAvailableDevices.length &&
!newAvailableDevices.every(function (device, index) {
return oldAvailableDevices[index].deviceId === device.deviceId;
})) {
var deviceIdChanges_1 = {};
oldAvailableDevices.forEach(function (device, index) {
var _a;
var camera = CameraAccess.deviceIdToCameraObjects.get(device.deviceId);
if (camera == null || camera.label !== ((_a = newAvailableDevices[index].label) !== null && _a !== void 0 ? _a : "")) {
return;
}
var newDeviceId = newAvailableDevices[index].deviceId;
deviceIdChanges_1[camera.deviceId] = newDeviceId;
if (CameraAccess.inaccessibleDeviceIds.has(camera.deviceId)) {
CameraAccess.inaccessibleDeviceIds.add(newDeviceId);
}
camera.deviceId = newDeviceId;
CameraAccess.deviceIdToCameraObjects.set(newDeviceId, camera);
});
logger_1.Logger.log(logger_1.Logger.Level.DEBUG, "Detected updated camera deviceId information and updated it accordingly", deviceIdChanges_1);
}
}
/**
* Get a list of cameras (if any) available on the device, a camera access permission is requested to the user
* the first time this method is called if needed.
*
* If the browser is incompatible the returned promise is rejected with a `UnsupportedBrowserError` error.
*
* When refreshing available devices, if updated deviceId information is detected, cameras' deviceId are updated
* accordingly. This could happen after a camera access and stop in some situations.
*
* @param refreshDevices Force a call to refresh available video devices even when information is already available.
* @param cameraAlreadyAccessed Hint that a camera has already been accessed before, avoiding a possible initial
* camera access permission request on the first call, in cases this cannot be already reliably detected.
* @returns A promise resolving to the array of available [[Camera]] objects (could be empty).
*/
function getCameras(refreshDevices, cameraAlreadyAccessed) {
if (refreshDevices === void 0) { refreshDevices = false; }
if (cameraAlreadyAccessed === void 0) { cameraAlreadyAccessed = false; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var browserCompatibility, stream, oldAvailableDevices, error_1, cameras;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
browserCompatibility = browserHelper_1.BrowserHelper.checkBrowserCompatibility();
if (!browserCompatibility.fullSupport) {
throw new unsupportedBrowserError_1.UnsupportedBrowserError(browserCompatibility);
}
// This will add the listeners only once in case of multiple calls: identical listeners are ignored
navigator.mediaDevices.addEventListener("devicechange", deviceChangeListener);
if (!(availableVideoDevices == null || refreshDevices || outdatedDevices)) return [3 /*break*/, 8];
outdatedDevices = false;
stream = void 0;
oldAvailableDevices = availableVideoDevices !== null && availableVideoDevices !== void 0 ? availableVideoDevices : [];
availableVideoDevices = [];
_a.label = 1;
case 1:
_a.trys.push([1, 6, 7, 8]);
return [4 /*yield*/, enumerateVideoDevices()];
case 2:
availableVideoDevices = _a.sent();
if (!!cameraAlreadyAccessed) return [3 /*break*/, 5];
return [4 /*yield*/, getStreamForDeviceAccessPermission()];
case 3:
stream = _a.sent();
if (!(stream != null)) return [3 /*break*/, 5];
return [4 /*yield*/, enumerateVideoDevices()];
case 4:
availableVideoDevices = _a.sent();
_a.label = 5;
case 5:
logger_1.Logger.log.apply(logger_1.Logger, tslib_1.__spreadArray([logger_1.Logger.Level.DEBUG, "Camera list (devices):"], tslib_1.__read(availableVideoDevices), false));
checkAndUpdateCameraDeviceIdInformation(oldAvailableDevices, availableVideoDevices);
return [3 /*break*/, 8];
case 6:
error_1 = _a.sent();
mapNonStandardErrorName(error_1);
throw error_1;
case 7:
if (stream != null) {
stream.getVideoTracks().forEach(function (track) {
track.stop();
});
}
return [7 /*endfinally*/];
case 8:
cameras = extractAccessibleCamerasFromDevices(availableVideoDevices);
logger_1.Logger.log.apply(logger_1.Logger, tslib_1.__spreadArray([logger_1.Logger.Level.DEBUG, "Camera list (cameras): "], tslib_1.__read(cameras), false));
// Return a copy of the array to allow for array mutations in other functions
return [2 /*return*/, tslib_1.__spreadArray([], tslib_1.__read(cameras), false)];
}
});
});
}
CameraAccess.getCameras = getCameras;
/**
* @hidden
*
* Call `navigator.mediaDevices.getUserMedia` asynchronously in a `setTimeout` call.
*
* @param getUserMediaParams The parameters for the `navigator.mediaDevices.getUserMedia` call.
* @returns A promise resolving when the camera is accessed.
*/
function getUserMediaDelayed(getUserMediaParams) {
logger_1.Logger.log(logger_1.Logger.Level.DEBUG, "Attempt to access camera (parameters):", getUserMediaParams.video);
return new Promise(function (resolve, reject) {
window.setTimeout(function () {
var _a;
((_a = navigator.mediaDevices.getUserMedia(getUserMediaParams)) !== null && _a !== void 0 ? _a : Promise.reject(new customError_1.CustomError({ name: "AbortError" })))
.then(resolve)
.catch(reject);
}, 0);
});
}
/**
* @hidden
*
* Get the *getUserMedia* *video* parameters to be used given a resolution fallback level and the browser used.
*
* @param cameraResolutionConstraint The resolution constraint.
* @returns The resulting *getUserMedia* *video* parameters.
*/
function getUserMediaVideoParams(cameraResolutionConstraint) {
var userMediaVideoParams = {
// @ts-ignore
resizeMode: "none",
};
switch (cameraResolutionConstraint) {
case cameraManager_1.CameraResolutionConstraint.ULTRA_HD:
return tslib_1.__assign(tslib_1.__assign({}, userMediaVideoParams), { width: { min: 3200, ideal: 3840, max: 4096 }, height: { min: 1800, ideal: 2160, max: 2400 } });
case cameraManager_1.CameraResolutionConstraint.FULL_HD:
return tslib_1.__assign(tslib_1.__assign({}, userMediaVideoParams), { width: { min: 1400, ideal: 1920, max: 2160 }, height: { min: 900, ideal: 1080, max: 1440 } });
case cameraManager_1.CameraResolutionConstraint.HD:
return tslib_1.__assign(tslib_1.__assign({}, userMediaVideoParams), { width: { min: 960, ideal: 1280, max: 1440 }, height: { min: 480, ideal: 720, max: 960 } });
case cameraManager_1.CameraResolutionConstraint.SD:
return tslib_1.__assign(tslib_1.__assign({}, userMediaVideoParams), { width: { min: 640, ideal: 640, max: 800 }, height: { min: 480, ideal: 480, max: 600 } });
case cameraManager_1.CameraResolutionConstraint.NONE:
default:
return {};
}
}
/**
* @hidden
*
* Try to access a given camera for video input at the given resolution level.
*
* If a camera is inaccessible because of errors, then it's added to the inaccessible device list. If the specific
* error is of type `OverconstrainedError` or `NotReadableError` however, this procedure is done later on via a
* separate external logic; also, in case of an error of type `NotAllowedError` (permission denied) this procedure is
* not executed, in order to possibly recover if and when the user allows the camera to be accessed again.
* This is done to allow checking if the camera can still be accessed via an updated deviceId when deviceId
* information changes, or if it should then be confirmed to be considered inaccessible.
*
* Depending on parameters, device features and user permissions for camera access, any of the following errors
* could be the rejected result of the returned promise:
* - `AbortError`
* - `NotAllowedError`
* - `NotFoundError`
* - `NotReadableError`
* - `SecurityError`
* - `OverconstrainedError`
*
* @param cameraResolutionConstraint The resolution constraint.
* @param camera The camera to try to access for video input.
* @returns A promise resolving to the `MediaStream` object coming from the accessed camera.
*/
function accessCameraStream(cameraResolutionConstraint, camera) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var getUserMediaParams, mediaStream, error_2;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
logger_1.Logger.log(logger_1.Logger.Level.DEBUG, "Attempt to access camera (camera):", camera);
getUserMediaParams = {
audio: false,
video: getUserMediaVideoParams(cameraResolutionConstraint),
};
// If it's the initial camera, use the given cameraType, otherwise use the given deviceId
if (camera.deviceId === "") {
getUserMediaParams.video.facingMode = {
ideal: camera.cameraType === camera_1.Camera.Type.BACK ? "environment" : "user",
};
}
else {
getUserMediaParams.video.deviceId = {
exact: camera.deviceId,
};
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, getUserMediaDelayed(getUserMediaParams)];
case 2:
mediaStream = _a.sent();
adjustCameraFromMediaStream(mediaStream, camera);
return [2 /*return*/, mediaStream];
case 3:
error_2 = _a.sent();
mapNonStandardErrorName(error_2);
if (!["OverconstrainedError", "NotReadableError", "NotAllowedError"].includes(error_2.name)) {
markCameraAsInaccessible(camera);
}
throw error_2;
case 4: return [2 /*return*/];
}
});
});
}
CameraAccess.accessCameraStream = accessCameraStream;
/**
* @hidden
*
* Mark a camera to be inaccessible and thus excluded from the camera list returned by [[getCameras]].
*
* @param camera The camera to mark to be inaccessible.
*/
function markCameraAsInaccessible(camera) {
// If it's the initial camera, do nothing
if (camera.deviceId !== "") {
logger_1.Logger.log(logger_1.Logger.Level.DEBUG, "Camera marked to be inaccessible:", camera);
CameraAccess.inaccessibleDeviceIds.add(camera.deviceId);
}
}
CameraAccess.markCameraAsInaccessible = markCameraAsInaccessible;
/**
* @hidden
*
* Get a list of available video devices in a cross-browser compatible way.
*
* @returns A promise resolving to the `MediaDeviceInfo` array of all available video devices.
*/
function enumerateVideoDevices() {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var devices, _b;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(typeof navigator.enumerateDevices === "function")) return [3 /*break*/, 2];
return [4 /*yield*/, navigator.enumerateDevices()];
case 1:
devices = _c.sent();
return [3 /*break*/, 7];
case 2:
if (!(typeof navigator.mediaDevices === "object" &&
typeof navigator.mediaDevices.enumerateDevices === "function")) return [3 /*break*/, 4];
return [4 /*yield*/, navigator.mediaDevices.enumerateDevices()];
case 3:
devices = _c.sent();
return [3 /*break*/, 7];
case 4:
_c.trys.push([4, 6, , 7]);
if (((_a = window.MediaStreamTrack) === null || _a === void 0 ? void 0 : _a.getSources) == null) {
throw new Error();
}
return [4 /*yield*/, new Promise(function (resolve) {
var _a, _b;
(_b = (_a = window.MediaStreamTrack) === null || _a === void 0 ? void 0 : _a.getSources) === null || _b === void 0 ? void 0 : _b.call(_a, resolve);
})];
case 5:
devices = _c.sent();
devices = devices
.filter(function (device) {
return device.kind.toLowerCase() === "video" || device.kind.toLowerCase() === "videoinput";
})
.map(function (device) {
var _a;
return {
deviceId: (_a = device.deviceId) !== null && _a !== void 0 ? _a : "",
groupId: device.groupId,
kind: "videoinput",
label: device.label,
toJSON: /* istanbul ignore next */ function () {
return this;
},
};
});
return [3 /*break*/, 7];
case 6:
_b = _c.sent();
throw new unsupportedBrowserError_1.UnsupportedBrowserError({
fullSupport: false,
scannerSupport: true,
missingFeatures: [browserCompatibility_1.BrowserCompatibility.Feature.MEDIA_DEVICES],
});
case 7: return [2 /*return*/, devices.filter(function (device) {
return device.kind === "videoinput";
})];
}
});
});
}
})(CameraAccess = exports.CameraAccess || (exports.CameraAccess = {}));
//# sourceMappingURL=cameraAccess.js.map

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,36 @@
/**
* A configuration object to request custom capabilities when accessing a camera.
*/
export interface CameraSettings {
/**
* The preferred video frame resolution.
*
* Not guaranteed to be precise: depending on device, browser and camera it could be different/lower than requested.
*
* Note that higher resolutions lead to slower processing times and higher memory requirements.
*/
readonly resolutionPreference: CameraSettings.ResolutionPreference;
}
export declare namespace CameraSettings {
/**
* Video frame resolution request.
*
* Not guaranteed to be precise: depending on device, browser and camera it could be different/lower than requested.
*
* Note that higher resolutions lead to slower processing times and higher memory requirements.
*/
enum ResolutionPreference {
/**
* Resolution of around 3840 x 2160.
*/
ULTRA_HD = "ultra-hd",
/**
* Resolution of around 1920 x 1080.
*/
FULL_HD = "full-hd",
/**
* Resolution of around 1280 x 720.
*/
HD = "hd"
}
}

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CameraSettings = void 0;
var CameraSettings;
(function (CameraSettings) {
/**
* Video frame resolution request.
*
* Not guaranteed to be precise: depending on device, browser and camera it could be different/lower than requested.
*
* Note that higher resolutions lead to slower processing times and higher memory requirements.
*/
var ResolutionPreference;
(function (ResolutionPreference) {
/**
* Resolution of around 3840 x 2160.
*/
ResolutionPreference["ULTRA_HD"] = "ultra-hd";
/**
* Resolution of around 1920 x 1080.
*/
ResolutionPreference["FULL_HD"] = "full-hd";
/**
* Resolution of around 1280 x 720.
*/
ResolutionPreference["HD"] = "hd";
})(ResolutionPreference = CameraSettings.ResolutionPreference || (CameraSettings.ResolutionPreference = {}));
})(CameraSettings = exports.CameraSettings || (exports.CameraSettings = {}));
//# sourceMappingURL=cameraSettings.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"cameraSettings.js","sourceRoot":"","sources":["../../../src/lib/cameraSettings.ts"],"names":[],"mappings":";;;AAcA,IAAiB,cAAc,CAsB9B;AAtBD,WAAiB,cAAc;IAC7B;;;;;;OAMG;IACH,IAAY,oBAaX;IAbD,WAAY,oBAAoB;QAC9B;;WAEG;QACH,6CAAqB,CAAA;QACrB;;WAEG;QACH,2CAAmB,CAAA;QACnB;;WAEG;QACH,iCAAS,CAAA;IACX,CAAC,EAbW,oBAAoB,GAApB,mCAAoB,KAApB,mCAAoB,QAa/B;AACH,CAAC,EAtBgB,cAAc,GAAd,sBAAc,KAAd,sBAAc,QAsB9B"}

View File

@@ -0,0 +1,9 @@
/**
* @hidden
*/
export declare class CustomError extends Error {
constructor({ name, message, }?: {
name?: string;
message?: string;
});
}

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomError = void 0;
var tslib_1 = require("tslib");
/**
* @hidden
*/
var CustomError = /** @class */ (function (_super) {
tslib_1.__extends(CustomError, _super);
// istanbul ignore next
function CustomError(_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.name, name = _c === void 0 ? "" : _c, _d = _b.message, message = _d === void 0 ? "" : _d;
var _this = _super.call(this, message) || this;
Object.setPrototypeOf(_this, CustomError.prototype);
_this.name = name;
return _this;
}
return CustomError;
}(Error));
exports.CustomError = CustomError;
//# sourceMappingURL=customError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"customError.js","sourceRoot":"","sources":["../../../src/lib/customError.ts"],"names":[],"mappings":";;;;AAAA;;GAEG;AACH;IAAiC,uCAAK;IACpC,uBAAuB;IACvB,qBAAY,EAMN;YANM,qBAMR,EAAE,KAAA,EALJ,YAAS,EAAT,IAAI,mBAAG,EAAE,KAAA,EACT,eAAY,EAAZ,OAAO,mBAAG,EAAE,KAAA;QAFd,YAOE,kBAAM,OAAO,CAAC,SAGf;QAFC,MAAM,CAAC,cAAc,CAAC,KAAI,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;QACnD,KAAI,CAAC,IAAI,GAAG,IAAI,CAAC;;IACnB,CAAC;IACH,kBAAC;AAAD,CAAC,AAbD,CAAiC,KAAK,GAarC;AAbY,kCAAW"}

View File

@@ -0,0 +1,9 @@
import { DataCaptureWorker } from "./workers/dataCaptureWorker";
export declare class DataCaptureLoader {
private preloadedDataCaptureWorker?;
private preloadedDataCaptureWorkerAvailable;
constructor(preload: boolean);
static load(dataCaptureWorker: DataCaptureWorker, preload?: boolean, delayedRegistration?: boolean): void;
getDataCaptureWorker(): DataCaptureWorker;
returnDataCaptureWorker(dataCaptureWorker: DataCaptureWorker): void;
}

View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataCaptureLoader = void 0;
var index_1 = require("../index");
var browserHelper_1 = require("./browserHelper");
var dataCaptureWorker_1 = require("./workers/dataCaptureWorker");
var DataCaptureLoader = /** @class */ (function () {
function DataCaptureLoader(preload) {
if (preload) {
this.preloadedDataCaptureWorker = new Worker(URL.createObjectURL(dataCaptureWorker_1.dataCaptureWorkerBlob));
DataCaptureLoader.load(this.preloadedDataCaptureWorker);
}
this.preloadedDataCaptureWorkerAvailable = preload;
}
DataCaptureLoader.load = function (dataCaptureWorker, preload, delayedRegistration) {
if (preload === void 0) { preload = false; }
if (delayedRegistration === void 0) { delayedRegistration = false; }
dataCaptureWorker.postMessage({
type: "load-library",
deviceId: index_1.deviceId,
libraryLocation: index_1.scanditDataCaptureLocation,
path: window.location.pathname,
preload: preload,
delayedRegistration: delayedRegistration,
highEndBlurryRecognition: index_1.highEndBlurryRecognition,
textRecognition: index_1.textRecognition,
licenseKey: index_1.userLicenseKey,
deviceModelName: browserHelper_1.BrowserHelper.userAgentInfo.getDevice().model,
});
};
DataCaptureLoader.prototype.getDataCaptureWorker = function () {
if (this.preloadedDataCaptureWorkerAvailable && this.preloadedDataCaptureWorker != null) {
this.preloadedDataCaptureWorkerAvailable = false;
return this.preloadedDataCaptureWorker;
}
else {
return new Worker(URL.createObjectURL(dataCaptureWorker_1.dataCaptureWorkerBlob));
}
};
DataCaptureLoader.prototype.returnDataCaptureWorker = function (dataCaptureWorker) {
if (this.preloadedDataCaptureWorker == null) {
this.preloadedDataCaptureWorker = dataCaptureWorker;
}
if (this.preloadedDataCaptureWorker === dataCaptureWorker) {
this.preloadedDataCaptureWorker.onmessage = null;
this.preloadedDataCaptureWorker.postMessage({
type: "reset",
});
this.preloadedDataCaptureWorkerAvailable = true;
}
else {
dataCaptureWorker.terminate();
}
};
return DataCaptureLoader;
}());
exports.DataCaptureLoader = DataCaptureLoader;
//# sourceMappingURL=dataCaptureLoader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"dataCaptureLoader.js","sourceRoot":"","sources":["../../../src/lib/dataCaptureLoader.ts"],"names":[],"mappings":";;;AAAA,kCAMkB;AAClB,iDAAgD;AAChD,iEAAuF;AAEvF;IAIE,2BAAY,OAAgB;QAC1B,IAAI,OAAO,EAAE;YACX,IAAI,CAAC,0BAA0B,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,yCAAqB,CAAC,CAAC,CAAC;YACzF,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;SACzD;QACD,IAAI,CAAC,mCAAmC,GAAG,OAAO,CAAC;IACrD,CAAC;IAEa,sBAAI,GAAlB,UACE,iBAAoC,EACpC,OAAwB,EACxB,mBAAoC;QADpC,wBAAA,EAAA,eAAwB;QACxB,oCAAA,EAAA,2BAAoC;QAEpC,iBAAiB,CAAC,WAAW,CAAC;YAC5B,IAAI,EAAE,cAAc;YACpB,QAAQ,kBAAA;YACR,eAAe,EAAE,kCAA0B;YAC3C,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;YAC9B,OAAO,SAAA;YACP,mBAAmB,qBAAA;YACnB,wBAAwB,kCAAA;YACxB,eAAe,yBAAA;YACf,UAAU,EAAE,sBAAc;YAC1B,eAAe,EAAE,6BAAa,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,KAAK;SAC/D,CAAC,CAAC;IACL,CAAC;IAEM,gDAAoB,GAA3B;QACE,IAAI,IAAI,CAAC,mCAAmC,IAAI,IAAI,CAAC,0BAA0B,IAAI,IAAI,EAAE;YACvF,IAAI,CAAC,mCAAmC,GAAG,KAAK,CAAC;YAEjD,OAAO,IAAI,CAAC,0BAA0B,CAAC;SACxC;aAAM;YACL,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,yCAAqB,CAAC,CAAC,CAAC;SAC/D;IACH,CAAC;IAEM,mDAAuB,GAA9B,UAA+B,iBAAoC;QACjE,IAAI,IAAI,CAAC,0BAA0B,IAAI,IAAI,EAAE;YAC3C,IAAI,CAAC,0BAA0B,GAAG,iBAAiB,CAAC;SACrD;QACD,IAAI,IAAI,CAAC,0BAA0B,KAAK,iBAAiB,EAAE;YACzD,IAAI,CAAC,0BAA0B,CAAC,SAAS,GAAG,IAAI,CAAC;YACjD,IAAI,CAAC,0BAA0B,CAAC,WAAW,CAAC;gBAC1C,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;YACH,IAAI,CAAC,mCAAmC,GAAG,IAAI,CAAC;SACjD;aAAM;YACL,iBAAiB,CAAC,SAAS,EAAE,CAAC;SAC/B;IACH,CAAC;IACH,wBAAC;AAAD,CAAC,AAvDD,IAuDC;AAvDY,8CAAiB"}

View File

@@ -0,0 +1,36 @@
/**
* A configuration object to define the properties of an image to be scanned.
*/
export interface ImageSettings {
/**
* The width of the image (columns of pixels).
*/
readonly width: number;
/**
* The height of the image (rows of pixels).
*/
readonly height: number;
/**
* The format of the pixel data, meaning the mapping of array bytes to image pixels.
*/
readonly format: ImageSettings.Format;
}
export declare namespace ImageSettings {
/**
* Image bytes format/layout.
*/
enum Format {
/**
* Single-channel 8-bit gray scale image.
*/
GRAY_8U = 0,
/**
* RGB image with 8 bits per color channel.
*/
RGB_8U = 1,
/**
* RGBA image with 8 bits per color channel.
*/
RGBA_8U = 2
}
}

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageSettings = void 0;
var ImageSettings;
(function (ImageSettings) {
// Warning: the values of Format are important as the data capture web worker relies on them without type checking.
/**
* Image bytes format/layout.
*/
var Format;
(function (Format) {
/**
* Single-channel 8-bit gray scale image.
*/
Format[Format["GRAY_8U"] = 0] = "GRAY_8U";
/**
* RGB image with 8 bits per color channel.
*/
Format[Format["RGB_8U"] = 1] = "RGB_8U";
/**
* RGBA image with 8 bits per color channel.
*/
Format[Format["RGBA_8U"] = 2] = "RGBA_8U";
})(Format = ImageSettings.Format || (ImageSettings.Format = {}));
})(ImageSettings = exports.ImageSettings || (exports.ImageSettings = {}));
//# sourceMappingURL=imageSettings.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"imageSettings.js","sourceRoot":"","sources":["../../../src/lib/imageSettings.ts"],"names":[],"mappings":";;;AAkBA,IAAiB,aAAa,CAmB7B;AAnBD,WAAiB,aAAa;IAC5B,mHAAmH;IACnH;;OAEG;IACH,IAAY,MAaX;IAbD,WAAY,MAAM;QAChB;;WAEG;QACH,yCAAW,CAAA;QACX;;WAEG;QACH,uCAAU,CAAA;QACV;;WAEG;QACH,yCAAW,CAAA;IACb,CAAC,EAbW,MAAM,GAAN,oBAAM,KAAN,oBAAM,QAajB;AACH,CAAC,EAnBgB,aAAa,GAAb,qBAAa,KAAb,qBAAa,QAmB7B"}

View File

@@ -0,0 +1,25 @@
export declare namespace Logger {
/**
* Log level.
*/
enum Level {
DEBUG = "debug",
INFO = "info",
WARN = "warn",
ERROR = "error",
QUIET = "quiet"
}
/**
* @hidden
*
* @param level The log level.
*/
function setLevel(level: Level): void;
/**
* @hidden
*
* @param level The log level.
* @param data The log contents.
*/
function log(level: Exclude<Level, Level.QUIET>, ...data: any[]): void;
}

View File

@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
var tslib_1 = require("tslib");
/* tslint:disable:no-console */
var Logger;
(function (Logger) {
/**
* Log level.
*/
var Level;
(function (Level) {
Level["DEBUG"] = "debug";
Level["INFO"] = "info";
Level["WARN"] = "warn";
Level["ERROR"] = "error";
Level["QUIET"] = "quiet";
})(Level = Logger.Level || (Logger.Level = {}));
var levelToNumber = new Map([
[Level.DEBUG, 1],
[Level.INFO, 2],
[Level.WARN, 3],
[Level.ERROR, 4],
[Level.QUIET, 5],
]);
var currentLevel = Level.DEBUG;
/**
* @hidden
*
* @param level The log level.
*/
function setLevel(level) {
currentLevel = level;
}
Logger.setLevel = setLevel;
/**
* @hidden
*
* @param level The log level.
* @param data The log contents.
*/
// tslint:disable-next-line: no-any
function log(level) {
var data = [];
for (var _i = 1; _i < arguments.length; _i++) {
data[_i - 1] = arguments[_i];
}
// tslint:disable-next-line: no-non-null-assertion
if (levelToNumber.get(currentLevel) > levelToNumber.get(level)) {
return;
}
switch (level) {
case Level.DEBUG:
console.debug.apply(console, tslib_1.__spreadArray([], tslib_1.__read(data), false));
break;
case Level.INFO:
console.log.apply(console, tslib_1.__spreadArray([], tslib_1.__read(data), false));
break;
case Level.WARN:
console.warn.apply(console, tslib_1.__spreadArray([], tslib_1.__read(data), false));
break;
case Level.ERROR:
console.error.apply(console, tslib_1.__spreadArray([], tslib_1.__read(data), false));
break;
default:
break;
}
}
Logger.log = log;
})(Logger = exports.Logger || (exports.Logger = {}));
//# sourceMappingURL=logger.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/lib/logger.ts"],"names":[],"mappings":";;;;AAAA,+BAA+B;AAC/B,IAAiB,MAAM,CA4DtB;AA5DD,WAAiB,MAAM;IACrB;;OAEG;IACH,IAAY,KAMX;IAND,WAAY,KAAK;QACf,wBAAe,CAAA;QACf,sBAAa,CAAA;QACb,sBAAa,CAAA;QACb,wBAAe,CAAA;QACf,wBAAe,CAAA;IACjB,CAAC,EANW,KAAK,GAAL,YAAK,KAAL,YAAK,QAMhB;IAED,IAAM,aAAa,GAAuB,IAAI,GAAG,CAAC;QAChD,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACf,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACf,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAChB,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;KACjB,CAAC,CAAC;IAEH,IAAI,YAAY,GAAU,KAAK,CAAC,KAAK,CAAC;IAEtC;;;;OAIG;IACH,SAAgB,QAAQ,CAAC,KAAY;QACnC,YAAY,GAAG,KAAK,CAAC;IACvB,CAAC;IAFe,eAAQ,WAEvB,CAAA;IAED;;;;;OAKG;IACH,mCAAmC;IACnC,SAAgB,GAAG,CAAC,KAAkC;QAAE,cAAc;aAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;YAAd,6BAAc;;QACpE,kDAAkD;QAClD,IAAI,aAAa,CAAC,GAAG,CAAC,YAAY,CAAE,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAE,EAAE;YAChE,OAAO;SACR;QACD,QAAQ,KAAK,EAAE;YACb,KAAK,KAAK,CAAC,KAAK;gBACd,OAAO,CAAC,KAAK,OAAb,OAAO,2CAAU,IAAI,WAAE;gBACvB,MAAM;YACR,KAAK,KAAK,CAAC,IAAI;gBACb,OAAO,CAAC,GAAG,OAAX,OAAO,2CAAQ,IAAI,WAAE;gBACrB,MAAM;YACR,KAAK,KAAK,CAAC,IAAI;gBACb,OAAO,CAAC,IAAI,OAAZ,OAAO,2CAAS,IAAI,WAAE;gBACtB,MAAM;YACR,KAAK,KAAK,CAAC,KAAK;gBACd,OAAO,CAAC,KAAK,OAAb,OAAO,2CAAU,IAAI,WAAE;gBACvB,MAAM;YACR;gBACE,MAAM;SACT;IACH,CAAC;IArBe,UAAG,MAqBlB,CAAA;AACH,CAAC,EA5DgB,MAAM,GAAN,cAAM,KAAN,cAAM,QA4DtB"}

View File

@@ -0,0 +1,109 @@
import { ParserResult } from "./parserResult";
import { Scanner } from "./scanner";
/**
* A data string parser.
*
* Parsers are capable of parsing one particular data format, which is passed to them during construction.
*
* The parser is created through [[BarcodePicker.createParserForFormat]] or [[Scanner.createParserForFormat]].
*
* Note that you need to have a valid license key with the parsing feature enabled to use the parser functionalities.
*
* For documentation on the available formats, check the official parser library documentation here:
* https://docs.scandit.com/parser/formats.html.
*/
export declare class Parser {
private readonly scanner;
private readonly dataFormat;
private options?;
/**
* @hidden
*
* @param scanner The [[Scanner]] object used to interact with the external Scandit library.
* @param dataFormat The data format for this parser.
*/
constructor(scanner: Scanner, dataFormat: Parser.DataFormat);
/**
* Apply the option map to the parser, allowing the user to fine-tune the behaviour of the parser.
* Available options depend on the data format and are specified in the respective documentation.
*
* @param options The new options to be applied (replacing previous ones, if any).
*/
setOptions(options?: object): void;
/**
* Process the given raw (byte array) data with the parser, retrieving the result as a [[ParserResult]] object.
*
* Multiple requests done without waiting for previous results will be queued and handled in order.
*
* If parsing of the data fails the returned promise is rejected with a `ScanditEngineError` error.
*
* @param rawData The raw (byte array) data to be parsed.
* @returns A promise resolving to the [[ParserResult]] object.
*/
parseRawData(rawData: Uint8Array): Promise<ParserResult>;
/**
* Process the given string data with the parser, retrieving the result as a [[ParserResult]] object.
*
* Multiple requests done without waiting for previous results will be queued and handled in order.
*
* If parsing of the data fails the returned promise is rejected with a `ScanditEngineError` error.
*
* Note that you should use [[parseRawData]] whenever possible: some codes, such as those found on driving licenses,
* might have non-printable characters and will need to use [[Barcode.rawData]] information to be parsed correctly.
*
* @param data The string data to be parsed.
* @returns A promise resolving to the [[ParserResult]] object.
*/
parseString(data: string): Promise<ParserResult>;
}
export declare namespace Parser {
/**
* Data format of a string to be parsed into a set of key-value mappings by the Scandit Parser Library.
*
* See https://docs.scandit.com/parser/formats.html for more details.
*/
enum DataFormat {
/**
* GS1 Application Identifier (AI).
*
* See: http://www.gs1.org/docs/barcodes/GS1_General_Specifications.pdf.
*/
GS1_AI = 1,
/**
* Health Industry Bar Code (HIBC).
*
* See: http://www.hibcc.org.
*/
HIBC = 2,
/**
* AAMVA Driver License/Identification (DL/ID).
*
* See: http://www.aamva.org.
*/
DLID = 3,
/**
* ICAO Machine Readable Travel Document (MRTD).
*
* See: https://www.icao.int.
*/
MRTD = 4,
/**
* Swiss QR ISO 20022.
*
* See: https://www.paymentstandards.ch.
*/
SWISSQR = 5,
/**
* Vehicle Identification Number (VIN).
*
* See: https://www.iso.org/standard/52200.html.
*/
VIN = 6,
/**
* US Uniformed Services ID.
*
* See: https://www.cac.mil.
*/
US_USID = 7
}
}

View File

@@ -0,0 +1,122 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
/**
* A data string parser.
*
* Parsers are capable of parsing one particular data format, which is passed to them during construction.
*
* The parser is created through [[BarcodePicker.createParserForFormat]] or [[Scanner.createParserForFormat]].
*
* Note that you need to have a valid license key with the parsing feature enabled to use the parser functionalities.
*
* For documentation on the available formats, check the official parser library documentation here:
* https://docs.scandit.com/parser/formats.html.
*/
var Parser = /** @class */ (function () {
/**
* @hidden
*
* @param scanner The [[Scanner]] object used to interact with the external Scandit library.
* @param dataFormat The data format for this parser.
*/
function Parser(scanner, dataFormat) {
this.scanner = scanner;
this.dataFormat = dataFormat;
}
/**
* Apply the option map to the parser, allowing the user to fine-tune the behaviour of the parser.
* Available options depend on the data format and are specified in the respective documentation.
*
* @param options The new options to be applied (replacing previous ones, if any).
*/
Parser.prototype.setOptions = function (options) {
this.options = options;
};
/**
* Process the given raw (byte array) data with the parser, retrieving the result as a [[ParserResult]] object.
*
* Multiple requests done without waiting for previous results will be queued and handled in order.
*
* If parsing of the data fails the returned promise is rejected with a `ScanditEngineError` error.
*
* @param rawData The raw (byte array) data to be parsed.
* @returns A promise resolving to the [[ParserResult]] object.
*/
Parser.prototype.parseRawData = function (rawData) {
return this.scanner.parse(this.dataFormat, rawData, this.options);
};
/**
* Process the given string data with the parser, retrieving the result as a [[ParserResult]] object.
*
* Multiple requests done without waiting for previous results will be queued and handled in order.
*
* If parsing of the data fails the returned promise is rejected with a `ScanditEngineError` error.
*
* Note that you should use [[parseRawData]] whenever possible: some codes, such as those found on driving licenses,
* might have non-printable characters and will need to use [[Barcode.rawData]] information to be parsed correctly.
*
* @param data The string data to be parsed.
* @returns A promise resolving to the [[ParserResult]] object.
*/
Parser.prototype.parseString = function (data) {
return this.scanner.parse(this.dataFormat, data, this.options);
};
return Parser;
}());
exports.Parser = Parser;
// istanbul ignore next
(function (Parser) {
/**
* Data format of a string to be parsed into a set of key-value mappings by the Scandit Parser Library.
*
* See https://docs.scandit.com/parser/formats.html for more details.
*/
var DataFormat;
(function (DataFormat) {
/**
* GS1 Application Identifier (AI).
*
* See: http://www.gs1.org/docs/barcodes/GS1_General_Specifications.pdf.
*/
DataFormat[DataFormat["GS1_AI"] = 1] = "GS1_AI";
/**
* Health Industry Bar Code (HIBC).
*
* See: http://www.hibcc.org.
*/
DataFormat[DataFormat["HIBC"] = 2] = "HIBC";
/**
* AAMVA Driver License/Identification (DL/ID).
*
* See: http://www.aamva.org.
*/
DataFormat[DataFormat["DLID"] = 3] = "DLID";
/**
* ICAO Machine Readable Travel Document (MRTD).
*
* See: https://www.icao.int.
*/
DataFormat[DataFormat["MRTD"] = 4] = "MRTD";
/**
* Swiss QR ISO 20022.
*
* See: https://www.paymentstandards.ch.
*/
DataFormat[DataFormat["SWISSQR"] = 5] = "SWISSQR";
/**
* Vehicle Identification Number (VIN).
*
* See: https://www.iso.org/standard/52200.html.
*/
DataFormat[DataFormat["VIN"] = 6] = "VIN";
/**
* US Uniformed Services ID.
*
* See: https://www.cac.mil.
*/
DataFormat[DataFormat["US_USID"] = 7] = "US_USID";
})(DataFormat = Parser.DataFormat || (Parser.DataFormat = {}));
})(Parser = exports.Parser || (exports.Parser = {}));
exports.Parser = Parser;
//# sourceMappingURL=parser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/lib/parser.ts"],"names":[],"mappings":";;;AASA;;;;;;;;;;;GAWG;AACH;IAGE;;;;;OAKG;IACH,gBAA6B,OAAgB,EAAmB,UAA6B;QAAhE,YAAO,GAAP,OAAO,CAAS;QAAmB,eAAU,GAAV,UAAU,CAAmB;IAAG,CAAC;IAEjG;;;;;OAKG;IACI,2BAAU,GAAjB,UAAkB,OAAgB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;;;;;;;OASG;IACI,6BAAY,GAAnB,UAAoB,OAAmB;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,4BAAW,GAAlB,UAAmB,IAAY;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IACH,aAAC;AAAD,CAAC,AAnDD,IAmDC;AAnDY,wBAAM;AAqDnB,uBAAuB;AACvB,WAAiB,MAAM;IACrB;;;;OAIG;IACH,IAAY,UA2CX;IA3CD,WAAY,UAAU;QACpB;;;;WAIG;QACH,+CAAU,CAAA;QACV;;;;WAIG;QACH,2CAAQ,CAAA;QACR;;;;WAIG;QACH,2CAAQ,CAAA;QACR;;;;WAIG;QACH,2CAAQ,CAAA;QACR;;;;WAIG;QACH,iDAAW,CAAA;QACX;;;;WAIG;QACH,yCAAO,CAAA;QACP;;;;WAIG;QACH,iDAAW,CAAA;IACb,CAAC,EA3CW,UAAU,GAAV,iBAAU,KAAV,iBAAU,QA2CrB;AACH,CAAC,EAlDgB,MAAM,GAAN,cAAM,KAAN,cAAM,QAkDtB;AAxGY,wBAAM"}

View File

@@ -0,0 +1,21 @@
/**
* A particular field of a parsed result of a data string.
*/
export interface ParserField {
/**
* The name of the field.
*/
readonly name: string;
/**
* The parsed representation of the data contained in the field.
* If no parsed representation is available for the field, this property is undefined.
* Use [[ParserField.rawString]] to retrieve the data for these fields.
*/
readonly parsed?: any;
/**
* The raw substring of the original code containing the field data.
* For fields that are inferred and do not have a direct correspondence to a particular part of the string,
* the string is set to an empty string.
*/
readonly rawString: string;
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=parserField.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parserField.js","sourceRoot":"","sources":["../../../src/lib/parserField.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,22 @@
import { ParserField } from "./parserField";
/**
* A result of a successfully parsed data string.
*/
export interface ParserResult {
/**
* The result object as a serialized JSON string.
*/
readonly jsonString: string;
/**
* The fields contained in the result as an array of [[ParserField]] objects.
* The order of the fields in array depends on the order of the fields in the input data.
*/
readonly fields: ParserField[];
/**
* The fields contained in the result as a map of [[ParserField]] objects.
* The entries in the map are field names pointing to the parser field.
*/
readonly fieldsByName: {
[fieldName: string]: ParserField;
};
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=parserResult.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parserResult.js","sourceRoot":"","sources":["../../../src/lib/parserResult.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,13 @@
/**
* A 2-dimensional point representing integer pixel coordinates from a top-left origin.
*/
export interface Point {
/**
* The x-coordinate.
*/
readonly x: number;
/**
* The y-coordinate.
*/
readonly y: number;
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=point.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"point.js","sourceRoot":"","sources":["../../../src/lib/point.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,23 @@
import { Point } from "./point";
/**
* A 2-dimensional quadrilateral shape given by its 4 corners, representing a barcode location.
* The polygon has an orientation given by the specific corner types.
*/
export interface Quadrilateral {
/**
* The top-left corner.
*/
readonly topLeft: Point;
/**
* The top-right corner.
*/
readonly topRight: Point;
/**
* The bottom-right corner.
*/
readonly bottomRight: Point;
/**
* The bottom-left corner.
*/
readonly bottomLeft: Point;
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=quadrilateral.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"quadrilateral.js","sourceRoot":"","sources":["../../../src/lib/quadrilateral.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,32 @@
import { Quadrilateral } from "./quadrilateral";
/**
* A text result.
*/
export interface RecognizedText {
/**
* The location of the text.
*/
readonly location: Quadrilateral;
/**
* The value of the text.
*/
readonly value: string;
}
/**
* @hidden
*/
export declare type RecognizedTextWASMResult = {
readonly location: number[][];
readonly value: string;
};
export declare namespace RecognizedText {
/**
* @hidden
*
* Create a [[RecognizedText]] object from a partial object returned by the external Scandit Data Capture library.
*
* @param result The text result coming from the external Scandit Data Capture library.
* @returns The generated [[RecognizedText]] object.
*/
function createFromWASMResult(result: RecognizedTextWASMResult): RecognizedText;
}

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RecognizedText = void 0;
var RecognizedText;
(function (RecognizedText) {
/**
* @hidden
*
* Create a [[RecognizedText]] object from a partial object returned by the external Scandit Data Capture library.
*
* @param result The text result coming from the external Scandit Data Capture library.
* @returns The generated [[RecognizedText]] object.
*/
function createFromWASMResult(result) {
return {
location: {
topLeft: { x: result.location[0][0], y: result.location[0][1] },
topRight: { x: result.location[1][0], y: result.location[1][1] },
bottomRight: { x: result.location[2][0], y: result.location[2][1] },
bottomLeft: { x: result.location[3][0], y: result.location[3][1] },
},
value: result.value,
};
}
RecognizedText.createFromWASMResult = createFromWASMResult;
})(RecognizedText = exports.RecognizedText || (exports.RecognizedText = {}));
//# sourceMappingURL=recognizedText.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"recognizedText.js","sourceRoot":"","sources":["../../../src/lib/recognizedText.ts"],"names":[],"mappings":";;;AAwBA,IAAiB,cAAc,CAoB9B;AApBD,WAAiB,cAAc;IAC7B;;;;;;;OAOG;IACH,SAAgB,oBAAoB,CAAC,MAAgC;QACnE,OAAO;YACL,QAAQ,EAAE;gBACR,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC/D,QAAQ,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;gBAChE,WAAW,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;gBACnE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;aACnE;YACD,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC;IACJ,CAAC;IAVe,mCAAoB,uBAUnC,CAAA;AACH,CAAC,EApBgB,cAAc,GAAd,sBAAc,KAAd,sBAAc,QAoB9B"}

View File

@@ -0,0 +1,67 @@
import { Barcode, BarcodeWASMResult } from "./barcode";
import { ImageSettings } from "./imageSettings";
import { RecognizedText, RecognizedTextWASMResult } from "./recognizedText";
/**
* A result of a scanning operation on an image.
*/
export declare class ScanResult {
/**
* The list of barcodes found in the image (can be empty).
*/
readonly barcodes: Barcode[];
/**
* The list of texts found in the image (can be empty).
*/
readonly texts: RecognizedText[];
/**
* The image data given as a byte array, formatted accordingly to the set settings ([[imageSettings]]).
*/
readonly imageData: Uint8Array;
/**
* The configuration object defining the properties of the processed image ([[imageData]]).
*/
readonly imageSettings: ImageSettings;
/**
* @hidden
*
* The list of manually rejected barcodes.
*/
readonly rejectedCodes: Set<Barcode>;
/**
* @hidden
*
* The list of manually rejected texts.
*/
readonly rejectedTexts: Set<RecognizedText>;
/**
* @hidden
*
* Create a ScanResult instance.
*
* @param barcodes The list of barcodes found in the image.
* @param texts The list of texts found in the image.
* @param imageData The image data given as a byte array, formatted accordingly to the set settings.
* @param imageSettings The configuration object defining the properties of the processed image.
*/
constructor(barcodes: BarcodeWASMResult[], texts: RecognizedTextWASMResult[], imageData: Uint8Array, imageSettings: ImageSettings);
/**
* Prevent playing a sound, vibrating or flashing the GUI for a particular code.
* If all codes and texts in the result are rejected (or no barcode/text is present), sound, vibration and GUI
* flashing will be suppressed.
*
* Rejected codes will still be part of the [[ScanResult.barcodes]] property like all other codes.
*
* @param barcode The barcode to be rejected.
*/
rejectCode(barcode: Barcode): void;
/**
* Prevent playing a sound, vibrating or flashing the GUI for a particular text.
* If all codes and texts in the result are rejected (or no barcode/text is present), sound, vibration and GUI
* flashing will be suppressed.
*
* Rejected texts will still be part of the [[ScanResult.texts]] property like all other texts.
*
* @param text The text to be rejected.
*/
rejectText(text: RecognizedText): void;
}

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScanResult = void 0;
var barcode_1 = require("./barcode");
var recognizedText_1 = require("./recognizedText");
/**
* A result of a scanning operation on an image.
*/
var ScanResult = /** @class */ (function () {
/**
* @hidden
*
* Create a ScanResult instance.
*
* @param barcodes The list of barcodes found in the image.
* @param texts The list of texts found in the image.
* @param imageData The image data given as a byte array, formatted accordingly to the set settings.
* @param imageSettings The configuration object defining the properties of the processed image.
*/
function ScanResult(barcodes, texts, imageData, imageSettings) {
var _this = this;
this.barcodes = [];
barcodes.forEach(function (barcode) {
_this.barcodes.push(barcode_1.Barcode.createFromWASMResult(barcode));
});
this.texts = [];
texts.forEach(function (text) {
_this.texts.push(recognizedText_1.RecognizedText.createFromWASMResult(text));
});
this.imageData = imageData;
this.imageSettings = imageSettings;
this.rejectedCodes = new Set();
this.rejectedTexts = new Set();
}
/**
* Prevent playing a sound, vibrating or flashing the GUI for a particular code.
* If all codes and texts in the result are rejected (or no barcode/text is present), sound, vibration and GUI
* flashing will be suppressed.
*
* Rejected codes will still be part of the [[ScanResult.barcodes]] property like all other codes.
*
* @param barcode The barcode to be rejected.
*/
ScanResult.prototype.rejectCode = function (barcode) {
this.rejectedCodes.add(barcode);
};
/**
* Prevent playing a sound, vibrating or flashing the GUI for a particular text.
* If all codes and texts in the result are rejected (or no barcode/text is present), sound, vibration and GUI
* flashing will be suppressed.
*
* Rejected texts will still be part of the [[ScanResult.texts]] property like all other texts.
*
* @param text The text to be rejected.
*/
ScanResult.prototype.rejectText = function (text) {
this.rejectedTexts.add(text);
};
return ScanResult;
}());
exports.ScanResult = ScanResult;
//# sourceMappingURL=scanResult.js.map

Some files were not shown because too many files have changed in this diff Show More