Skip to content

Commit

Permalink
Refactor account modal component to better handle camera status
Browse files Browse the repository at this point in the history
  • Loading branch information
jlcvp committed Oct 24, 2024
1 parent a2a097b commit fbfc4c2
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<ion-toolbar>
<ion-title>{{ "ADD_ACCOUNT_MODAL.TITLE" | translate }}</ion-title>
<ion-buttons slot="end">
<ion-button (click)="dismiss()"><ion-icon slot="icon-only" name="close-outline"></ion-icon></ion-button>
<ion-button (click)="dismiss()" [disabled]="!isCameraSettled"><ion-icon slot="icon-only" name="close-outline"></ion-icon></ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
Expand All @@ -16,7 +16,7 @@
</ion-col>
<ion-col></ion-col>
<ion-col size="auto">
<ion-button size="large" (click)="cycleCamera()">
<ion-button size="large" [disabled]="!isCameraSettled" (click)="cycleCamera()">
<ion-icon slot="icon-only" name="sync-outline"></ion-icon>
</ion-button>
</ion-col>
Expand Down
57 changes: 51 additions & 6 deletions src/app/home/components/account-modal/account-modal.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class AccountModalComponent implements OnInit {
@ViewChild('qrscanner') qrscanner!: NgxScannerQrcodeComponent;

isScanActive = false;
isCameraSettled = false;
draftLogoURL = '';
draftLogoSearchTxt = '';
searchLogoResults: string[] = [];
Expand Down Expand Up @@ -69,7 +70,7 @@ export class AccountModalComponent implements OnInit {
async onWillDismiss() {
if (this.qrscanner) {
console.log("STOP QR")
await this.qrscanner.stop()
await this.stopScanner()
}
}

Expand All @@ -83,7 +84,7 @@ export class AccountModalComponent implements OnInit {
async onQRCodeScanned(evt: ScannerQRCodeResult[], qrscanner: NgxScannerQrcodeComponent) {
try {
await qrscanner.stop()
await this.qrscanner.stop()
await this.stopScanner()
} catch (error) {
console.error("Error stopping scanner", error)
}
Expand All @@ -95,19 +96,22 @@ export class AccountModalComponent implements OnInit {
}

async cycleCamera() {
this.isCameraSettled = false
const current = this.qrscanner.deviceIndexActive
const devices = await firstValueFrom(this.qrscanner.devices)
console.log({ })
const next = (current + 1) % devices.length
const nextDevice = devices[next]
console.log(`cycle device [${current}] -> [${next}]`, { playDevice: nextDevice, devices })
await this.qrscanner.playDevice(nextDevice.deviceId)
await this.showInfoToast(`${nextDevice.label}`, 'top')
await this.awaitCameraSettle()
this.isCameraSettled = true
}

manualInputAction() {
async manualInputAction() {
if (this.qrscanner) {
console.log("STOP QR Reading")
this.qrscanner.stop()
await this.stopScanner()
}
this.isScanActive = false;
}
Expand All @@ -119,6 +123,8 @@ export class AccountModalComponent implements OnInit {
await this.presentLoading(message)
try {
await firstValueFrom(this.qrscanner.start())
console.log('QR scanner started')
await this.awaitCameraSettle()
} catch (error) {
// camera permission denial
const header = await firstValueFrom(this.translateService.get('ADD_ACCOUNT_MODAL.ERROR_MSGS.ERROR_CAMERA_HEADER'))
Expand All @@ -140,7 +146,9 @@ export class AccountModalComponent implements OnInit {
if (backCamera && backCamera.deviceId) {
console.log("using device", { backCamera })
await this.qrscanner.playDevice(backCamera.deviceId)
await this.awaitCameraSettle()
}
this.isCameraSettled = true
await this.dismissLoading()
}

Expand Down Expand Up @@ -201,10 +209,11 @@ export class AccountModalComponent implements OnInit {
}
}

private async showInfoToast(message: string) {
private async showInfoToast(message: string, position: "top" | "bottom" | "middle" | undefined = undefined) {
const toast = await this.toastController.create({
message,
duration: 2000,
position: position
})
await toast.present()
}
Expand Down Expand Up @@ -247,4 +256,40 @@ export class AccountModalComponent implements OnInit {
})
await alert.present()
}

private async stopScanner() {
if(this.qrscanner) {
await this.awaitCameraSettle()
await firstValueFrom(this.qrscanner.stop())
}
}

private async awaitCameraSettle(timeoutMillis: number = 10000) {
return new Promise<void>((resolve, reject) => {
console.log("Waiting for camera to settle")
if(!this.qrscanner) {
reject("No scanner")
return
}
let timeout: any = undefined // eslint-disable-line @typescript-eslint/no-explicit-any
// while not settled, keep checking every 100ms
const interval = setInterval(() => {
if(this.qrscanner.isStart) {
clearInterval(interval)
if(timeout) {
clearTimeout(timeout)
}
console.log("Camera settled")
resolve()
}
}, 100)

// if timeout, reject
timeout = setTimeout(() => {
clearInterval(interval)
reject("Timeout")
}, timeoutMillis)

})
}
}
1 change: 1 addition & 0 deletions src/app/home/home.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export class HomePage implements OnInit {
// show modal
const modal = await this.modalController.create({
component: AccountModalComponent,
backdropDismiss: false
})

await modal.present()
Expand Down
2 changes: 1 addition & 1 deletion src/app/login/login.page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
width: 30%;
}

.login-bg, #background-content {
.login-bg{
height: 100%;
background: linear-gradient(to right, var(--ion-color-light) 0%, var(--ion-color-light) 50%, var(--ion-color-dark) 50%, var(--ion-color-dark) 100%) !important;
}
Expand Down

0 comments on commit fbfc4c2

Please sign in to comment.