Merge pull request #3860 from alfonso-salces/MOBILE-3947

MOBILE-3947 qr-scanner: Create qr sscanner service
main
Noel De Martin 2023-12-04 10:31:25 +01:00 committed by GitHub
commit ef26d6db39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 260 additions and 6 deletions

View File

@ -31,7 +31,7 @@ import { Keyboard } from '@awesome-cordova-plugins/keyboard/ngx';
import { LocalNotifications } from '@awesome-cordova-plugins/local-notifications/ngx'; import { LocalNotifications } from '@awesome-cordova-plugins/local-notifications/ngx';
import { MediaCapture } from '@awesome-cordova-plugins/media-capture/ngx'; import { MediaCapture } from '@awesome-cordova-plugins/media-capture/ngx';
import { Push } from '@features/native/plugins/push'; import { Push } from '@features/native/plugins/push';
import { QRScanner } from '@ionic-native/qr-scanner/ngx'; import { QRScanner } from './plugins/qrscanner';
import { SplashScreen } from '@awesome-cordova-plugins/splash-screen/ngx'; import { SplashScreen } from '@awesome-cordova-plugins/splash-screen/ngx';
import { SQLite } from '@awesome-cordova-plugins/sqlite/ngx'; import { SQLite } from '@awesome-cordova-plugins/sqlite/ngx';
import { StatusBar } from '@awesome-cordova-plugins/status-bar/ngx'; import { StatusBar } from '@awesome-cordova-plugins/status-bar/ngx';
@ -80,7 +80,6 @@ export const CORE_NATIVE_SERVICES = [
Keyboard, Keyboard,
LocalNotifications, LocalNotifications,
MediaCapture, MediaCapture,
QRScanner,
SplashScreen, SplashScreen,
SQLite, SQLite,
StatusBar, StatusBar,

View File

@ -16,7 +16,9 @@ import { makeSingleton } from '@singletons';
import { Chooser as ChooserService } from './chooser'; import { Chooser as ChooserService } from './chooser';
import { Push as PushService } from './push'; import { Push as PushService } from './push';
import { Zip as ZipService } from './zip'; import { Zip as ZipService } from './zip';
import { QRScanner as QRScannerService } from './qrscanner';
export const Chooser = makeSingleton(ChooserService); export const Chooser = makeSingleton(ChooserService);
export const Push = makeSingleton(PushService); export const Push = makeSingleton(PushService);
export const Zip = makeSingleton(ZipService); export const Zip = makeSingleton(ZipService);
export const QRScanner = makeSingleton(QRScannerService);

View File

@ -0,0 +1,187 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { QRScannerError, QRScannerStatus } from '@moodlehq/cordova-plugin-qrscanner';
/**
* QR Scanner plugin wrapper
*/
@Injectable({ providedIn: 'root' })
export class QRScanner {
/**
* Destroy the scanner instance.
*
* @returns QR scanner status.
*/
destroy(): Promise<QRScannerStatus> {
return new Promise((resolve) => window.QRScanner.destroy(resolve));
}
/**
* Request permission to use QR scanner.
*
* @returns QR scanner status.
*/
prepare(): Promise<QRScannerStatus> {
return new Promise((resolve, reject) => {
window.QRScanner.prepare((error: QRScannerError, status: QRScannerStatus) => {
error ? reject(error) : resolve(status);
});
});
}
/**
* Configures the native webview to have a transparent background, then sets the background of the <body> and <html> DOM
* elements to transparent, allowing the webview to re-render with the transparent background.
*
* @returns QR scanner status.
*/
show(): Promise<QRScannerStatus> {
return new Promise(resolve => window.QRScanner.show((status) => resolve(status)));
}
/**
* Call this method to enable scanning. You must then call the `show` method to make the camera preview visible.
*
* @returns Observable that emits the scanned text. Unsubscribe from the observable to stop scanning.
*/
scan(): Observable<string> {
return new Observable(observer => {
window.QRScanner.scan((error: QRScannerError, text: string) => {
error ? observer.error(error) : observer.next(text);
});
return () => {
window.QRScanner.cancelScan();
};
});
}
/**
* Configures the native webview to be opaque with a white background, covering the video preview.
*
* @returns QR scanner status.
*/
hide(): Promise<QRScannerStatus> {
return new Promise((resolve) => window.QRScanner.hide(resolve));
}
/**
* Enable the device's light (for scanning in low-light environments).
*
* @returns QR scanner status.
*/
enableLight(): Promise<QRScannerStatus> {
return new Promise((resolve, reject) => {
window.QRScanner.enableLight((error: QRScannerError, status: QRScannerStatus) => {
error ? reject(error) : resolve(status);
});
});
}
/**
* Disable the device's light.
*
* @returns QR scanner status.
*/
disableLight(): Promise<QRScannerStatus> {
return new Promise((resolve, reject) => {
window.QRScanner.disableLight((error: QRScannerError, status: QRScannerStatus) => {
error ? reject(error) : resolve(status);
});
});
}
/**
* Use front camera.
*
* @returns QR scanner status.
*/
useFrontCamera(): Promise<QRScannerStatus> {
return new Promise((resolve, reject) => {
window.QRScanner.useFrontCamera((error: QRScannerError, status: QRScannerStatus) => {
error ? reject(error) : resolve(status);
});
});
}
/**
* Use back camera.
*
* @returns QR scanner status.
*/
useBackCamera(): Promise<QRScannerStatus> {
return new Promise((resolve, reject) => {
window.QRScanner.useBackCamera((error: QRScannerError, status: QRScannerStatus) => {
error ? reject(error) : resolve(status);
});
});
}
/**
* Disable the device's light.
*
* @param camera Provide `0` for back camera, and `1` for front camera.
* @returns QR scanner status.
*/
useCamera(camera: QRScannerCamera): Promise<QRScannerStatus> {
return new Promise((resolve, reject) => {
window.QRScanner.useCamera(camera, (error: QRScannerError, status: QRScannerStatus) => {
error ? reject(error) : resolve(status);
});
});
}
/**
* Pauses the video preview on the current frame and pauses scanning.
*
* @returns QR scanner status.
*/
pausePreview(): Promise<QRScannerStatus> {
return new Promise((resolve) => window.QRScanner.pausePreview(resolve));
}
/**
* Resume the video preview and resumes scanning.
*
* @returns QR scanner status.
*/
resumePreview(): Promise<QRScannerStatus> {
return new Promise((resolve) => window.QRScanner.resumePreview(resolve));
}
/**
* Returns permission status.
*
* @returns QR scanner status.
*/
getStatus(): Promise<QRScannerStatus> {
return new Promise((resolve) => window.QRScanner.getStatus(resolve));
}
/**
* Opens settings to edit app permissions.
*/
openSettings(): void {
window.QRScanner.openSettings();
}
}
export enum QRScannerCamera {
FRONT_CAMERA = 0,
BACK_CAMERA = 1,
}

View File

@ -16,7 +16,6 @@ import { Injectable } from '@angular/core';
import { InAppBrowserObject, InAppBrowserOptions } from '@awesome-cordova-plugins/in-app-browser'; import { InAppBrowserObject, InAppBrowserOptions } from '@awesome-cordova-plugins/in-app-browser';
import { FileEntry } from '@awesome-cordova-plugins/file/ngx'; import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { CoreFile } from '@services/file'; import { CoreFile } from '@services/file';
import { CoreLang } from '@services/lang'; import { CoreLang } from '@services/lang';
@ -24,7 +23,7 @@ import { CoreWS } from '@services/ws';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, QRScanner, Translate, NgZone } from '@singletons'; import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, Translate, NgZone } from '@singletons';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
import { CoreViewerQRScannerComponent } from '@features/viewer/components/qr-scanner/qr-scanner'; import { CoreViewerQRScannerComponent } from '@features/viewer/components/qr-scanner/qr-scanner';
import { CoreCanceledError } from '@classes/errors/cancelederror'; import { CoreCanceledError } from '@classes/errors/cancelederror';
@ -40,6 +39,7 @@ import { CoreSites } from '@services/sites';
import { CoreCancellablePromise } from '@classes/cancellable-promise'; import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { CoreUrlUtils } from './url'; import { CoreUrlUtils } from './url';
import { QRScanner } from '@features/native/plugins';
export type TreeNode<T> = T & { children: TreeNode<T>[] }; export type TreeNode<T> = T & { children: TreeNode<T>[] };

View File

@ -52,7 +52,6 @@ import { WebView as WebViewService } from '@awesome-cordova-plugins/ionic-webvie
import { Keyboard as KeyboardService } from '@awesome-cordova-plugins/keyboard/ngx'; import { Keyboard as KeyboardService } from '@awesome-cordova-plugins/keyboard/ngx';
import { LocalNotifications as LocalNotificationsService } from '@awesome-cordova-plugins/local-notifications/ngx'; import { LocalNotifications as LocalNotificationsService } from '@awesome-cordova-plugins/local-notifications/ngx';
import { MediaCapture as MediaCaptureService } from '@awesome-cordova-plugins/media-capture/ngx'; import { MediaCapture as MediaCaptureService } from '@awesome-cordova-plugins/media-capture/ngx';
import { QRScanner as QRScannerService } from '@ionic-native/qr-scanner/ngx';
import { StatusBar as StatusBarService } from '@awesome-cordova-plugins/status-bar/ngx'; import { StatusBar as StatusBarService } from '@awesome-cordova-plugins/status-bar/ngx';
import { SplashScreen as SplashScreenService } from '@awesome-cordova-plugins/splash-screen/ngx'; import { SplashScreen as SplashScreenService } from '@awesome-cordova-plugins/splash-screen/ngx';
import { SQLite as SQLiteService } from '@awesome-cordova-plugins/sqlite/ngx'; import { SQLite as SQLiteService } from '@awesome-cordova-plugins/sqlite/ngx';
@ -183,7 +182,6 @@ export const Keyboard = makeSingleton(KeyboardService);
export const LocalNotifications = makeSingleton(LocalNotificationsService); export const LocalNotifications = makeSingleton(LocalNotificationsService);
export const MediaCapture = makeSingleton(MediaCaptureService); export const MediaCapture = makeSingleton(MediaCaptureService);
export const NativeHttp = makeSingleton(HTTP); export const NativeHttp = makeSingleton(HTTP);
export const QRScanner = makeSingleton(QRScannerService);
export const StatusBar = makeSingleton(StatusBarService); export const StatusBar = makeSingleton(StatusBarService);
export const SplashScreen = makeSingleton(SplashScreenService); export const SplashScreen = makeSingleton(SplashScreenService);
export const SQLite = makeSingleton(SQLiteService); export const SQLite = makeSingleton(SQLiteService);

View File

@ -0,0 +1,68 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* Types for qr scanner plugin.
*
* @see https://github.com/moodlemobile/cordova-plugin-qrscanner
*/
type IQRScannerStatus = {
authorized: boolean;
denied: boolean;
restricted: boolean;
prepared: boolean;
scanning: boolean;
previewing: boolean;
showing: boolean;
lightEnabled: boolean;
canOpenSettings: boolean;
canEnableLight: boolean;
canChangeCamera: boolean;
currentCamera: number;
};
type IQRScannerError = {
name: string;
code: number;
_message: string; // eslint-disable-line @typescript-eslint/naming-convention
};
interface Window {
// eslint-disable-next-line @typescript-eslint/naming-convention
QRScanner: {
prepare(onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
destroy(onDone?: (status: IQRScannerStatus) => void): void;
scan(onDone: (error: IQRScannerError, text: string) => void): void;
cancelScan(onDone?: (status: IQRScannerStatus) => void): void;
show(onDone?: (status: IQRScannerStatus) => void): void;
hide(onDone?: (status: IQRScannerStatus) => void): void;
pausePreview(onDone?: (status: IQRScannerStatus) => void): void;
resumePreview(onDone?: (status: IQRScannerStatus) => void): void;
enableLight(onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
disableLight(onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
useCamera(camera: number, onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
useFrontCamera(onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
useBackCamera(onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
openSettings(onDone?: (error: IQRScannerError, status: IQRScannerStatus) => void): void;
getStatus(onDone: (status: IQRScannerStatus) => void): void;
};
}
declare module '@moodlehq/cordova-plugin-qrscanner' {
export type QRScannerStatus = IQRScannerStatus;
export type QRScannerError = IQRScannerError;
}