mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
zxing scanner poc
This commit is contained in:
@@ -4,9 +4,11 @@ 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({
|
||||
imports: [ScanditModalModule],
|
||||
imports: [ScanditModalModule, ZxingModalModule],
|
||||
})
|
||||
export class ScanAdapterModule {
|
||||
static forRoot(dev?: boolean) {
|
||||
@@ -14,7 +16,8 @@ export class ScanAdapterModule {
|
||||
ngModule: ScanAdapterModule,
|
||||
providers: [
|
||||
{ provide: SCAN_ADAPTER, useClass: NativeScanAdapter, multi: true },
|
||||
{ provide: SCAN_ADAPTER, useClass: ScanditScanAdapter, 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 }],
|
||||
|
||||
2
apps/adapter/scan/src/lib/zxing-modal/index.ts
Normal file
2
apps/adapter/scan/src/lib/zxing-modal/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './zxing-modal.component';
|
||||
export * from './zxing-modal.module';
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Component, ChangeDetectionStrategy, ViewChild, ElementRef, AfterViewInit, NgZone, Inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { 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) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
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());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._modalRef.close();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this._onDestroy$.next();
|
||||
|
||||
this._reader?.reset();
|
||||
}
|
||||
|
||||
setSelectedDevice(id: string) {
|
||||
this.selectedDevice$.next(id);
|
||||
}
|
||||
}
|
||||
11
apps/adapter/scan/src/lib/zxing-modal/zxing-modal.module.ts
Normal file
11
apps/adapter/scan/src/lib/zxing-modal/zxing-modal.module.ts
Normal 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 {}
|
||||
38
apps/adapter/scan/src/lib/zxing.scan-adapter.ts
Normal file
38
apps/adapter/scan/src/lib/zxing.scan-adapter.ts
Normal 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
20
package-lock.json
generated
20
package-lock.json
generated
@@ -4969,6 +4969,21 @@
|
||||
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@zxing/library": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.19.1.tgz",
|
||||
"integrity": "sha512-rKwvl3Uuqs8yf364iU9l3HDDaIx8yPv+CH6DbtQaQr67VdKLG22G1ukEp9fOdDefE6tpLtRAdMnTrgtpiaKAZw==",
|
||||
"requires": {
|
||||
"@zxing/text-encoding": "~0.9.0",
|
||||
"ts-custom-error": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"@zxing/text-encoding": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
|
||||
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
|
||||
"optional": true
|
||||
},
|
||||
"abab": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
||||
@@ -18887,6 +18902,11 @@
|
||||
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-custom-error": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.2.0.tgz",
|
||||
"integrity": "sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A=="
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz",
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
"@ngrx/store": "~12.5.1",
|
||||
"@ngrx/store-devtools": "~12.5.1",
|
||||
"@ngxs/store": "^3.6.2",
|
||||
"@zxing/library": "^0.19.1",
|
||||
"angular-oauth2-oidc": "^13.0.1",
|
||||
"angular-oauth2-oidc-jwks": "^13.0.1",
|
||||
"core-js": "^2.6.5",
|
||||
|
||||
Reference in New Issue
Block a user