feat(core): update session, security system and QR exchange
- Removed session creation and Lightning payment logic - Refactored security system: * no more restrictions * all systems enabled on session creation - Improved QR code exchange for mobile devices
This commit is contained in:
340
node_modules/html5-qrcode/src/camera/core-impl.ts
generated
vendored
Normal file
340
node_modules/html5-qrcode/src/camera/core-impl.ts
generated
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
* @fileoverview
|
||||
* Core camera library implementations.
|
||||
*
|
||||
* @author mebjas <minhazav@gmail.com>
|
||||
*/
|
||||
|
||||
import {
|
||||
Camera,
|
||||
CameraCapabilities,
|
||||
CameraCapability,
|
||||
RangeCameraCapability,
|
||||
CameraRenderingOptions,
|
||||
RenderedCamera,
|
||||
RenderingCallbacks,
|
||||
BooleanCameraCapability
|
||||
} from "./core";
|
||||
|
||||
/** Interface for a range value. */
|
||||
interface RangeValue {
|
||||
min: number;
|
||||
max: number;
|
||||
step: number;
|
||||
}
|
||||
|
||||
/** Abstract camera capability class. */
|
||||
abstract class AbstractCameraCapability<T> implements CameraCapability<T> {
|
||||
protected readonly name: string;
|
||||
protected readonly track: MediaStreamTrack;
|
||||
|
||||
constructor(name: string, track: MediaStreamTrack) {
|
||||
this.name = name;
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
public isSupported(): boolean {
|
||||
// TODO(minhazav): Figure out fallback for getCapabilities()
|
||||
// in firefox.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API/Constraints
|
||||
if (!this.track.getCapabilities) {
|
||||
return false;
|
||||
}
|
||||
return this.name in this.track.getCapabilities();
|
||||
}
|
||||
|
||||
public apply(value: T): Promise<void> {
|
||||
let constraint: any = {};
|
||||
constraint[this.name] = value;
|
||||
let constraints = { advanced: [ constraint ] };
|
||||
return this.track.applyConstraints(constraints);
|
||||
}
|
||||
|
||||
public value(): T | null {
|
||||
let settings: any = this.track.getSettings();
|
||||
if (this.name in settings) {
|
||||
let settingValue = settings[this.name];
|
||||
return settingValue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractRangeCameraCapability extends AbstractCameraCapability<number> {
|
||||
constructor(name: string, track: MediaStreamTrack) {
|
||||
super(name, track);
|
||||
}
|
||||
|
||||
public min(): number {
|
||||
return this.getCapabilities().min;
|
||||
}
|
||||
|
||||
public max(): number {
|
||||
return this.getCapabilities().max;
|
||||
}
|
||||
|
||||
public step(): number {
|
||||
return this.getCapabilities().step;
|
||||
}
|
||||
|
||||
public apply(value: number): Promise<void> {
|
||||
let constraint: any = {};
|
||||
constraint[this.name] = value;
|
||||
let constraints = {advanced: [ constraint ]};
|
||||
return this.track.applyConstraints(constraints);
|
||||
}
|
||||
|
||||
private getCapabilities(): RangeValue {
|
||||
this.failIfNotSupported();
|
||||
let capabilities: any = this.track.getCapabilities();
|
||||
let capability: any = capabilities[this.name];
|
||||
return {
|
||||
min: capability.min,
|
||||
max: capability.max,
|
||||
step: capability.step,
|
||||
};
|
||||
}
|
||||
|
||||
private failIfNotSupported() {
|
||||
if (!this.isSupported()) {
|
||||
throw new Error(`${this.name} capability not supported`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Zoom feature. */
|
||||
class ZoomFeatureImpl extends AbstractRangeCameraCapability {
|
||||
constructor(track: MediaStreamTrack) {
|
||||
super("zoom", track);
|
||||
}
|
||||
}
|
||||
|
||||
/** Torch feature. */
|
||||
class TorchFeatureImpl extends AbstractCameraCapability<boolean> {
|
||||
constructor(track: MediaStreamTrack) {
|
||||
super("torch", track);
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of {@link CameraCapabilities}. */
|
||||
class CameraCapabilitiesImpl implements CameraCapabilities {
|
||||
private readonly track: MediaStreamTrack;
|
||||
|
||||
constructor(track: MediaStreamTrack) {
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
zoomFeature(): RangeCameraCapability {
|
||||
return new ZoomFeatureImpl(this.track);
|
||||
}
|
||||
|
||||
torchFeature(): BooleanCameraCapability {
|
||||
return new TorchFeatureImpl(this.track);
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of {@link RenderedCamera}. */
|
||||
class RenderedCameraImpl implements RenderedCamera {
|
||||
|
||||
private readonly parentElement: HTMLElement;
|
||||
private readonly mediaStream: MediaStream;
|
||||
private readonly surface: HTMLVideoElement;
|
||||
private readonly callbacks: RenderingCallbacks;
|
||||
|
||||
private isClosed: boolean = false;
|
||||
|
||||
private constructor(
|
||||
parentElement: HTMLElement,
|
||||
mediaStream: MediaStream,
|
||||
callbacks: RenderingCallbacks) {
|
||||
this.parentElement = parentElement;
|
||||
this.mediaStream = mediaStream;
|
||||
this.callbacks = callbacks;
|
||||
|
||||
this.surface = this.createVideoElement(this.parentElement.clientWidth);
|
||||
|
||||
// Setup
|
||||
parentElement.append(this.surface);
|
||||
}
|
||||
|
||||
private createVideoElement(width: number): HTMLVideoElement {
|
||||
const videoElement = document.createElement("video");
|
||||
videoElement.style.width = `${width}px`;
|
||||
videoElement.style.display = "block";
|
||||
videoElement.muted = true;
|
||||
videoElement.setAttribute("muted", "true");
|
||||
(<any>videoElement).playsInline = true;
|
||||
return videoElement;
|
||||
}
|
||||
|
||||
private setupSurface() {
|
||||
this.surface.onabort = () => {
|
||||
throw "RenderedCameraImpl video surface onabort() called";
|
||||
};
|
||||
|
||||
this.surface.onerror = () => {
|
||||
throw "RenderedCameraImpl video surface onerror() called";
|
||||
};
|
||||
|
||||
let onVideoStart = () => {
|
||||
const videoWidth = this.surface.clientWidth;
|
||||
const videoHeight = this.surface.clientHeight;
|
||||
this.callbacks.onRenderSurfaceReady(videoWidth, videoHeight);
|
||||
this.surface.removeEventListener("playing", onVideoStart);
|
||||
};
|
||||
|
||||
this.surface.addEventListener("playing", onVideoStart);
|
||||
this.surface.srcObject = this.mediaStream;
|
||||
this.surface.play();
|
||||
}
|
||||
|
||||
static async create(
|
||||
parentElement: HTMLElement,
|
||||
mediaStream: MediaStream,
|
||||
options: CameraRenderingOptions,
|
||||
callbacks: RenderingCallbacks)
|
||||
: Promise<RenderedCamera> {
|
||||
let renderedCamera = new RenderedCameraImpl(
|
||||
parentElement, mediaStream, callbacks);
|
||||
if (options.aspectRatio) {
|
||||
let aspectRatioConstraint = {
|
||||
aspectRatio: options.aspectRatio!
|
||||
};
|
||||
await renderedCamera.getFirstTrackOrFail().applyConstraints(
|
||||
aspectRatioConstraint);
|
||||
}
|
||||
|
||||
renderedCamera.setupSurface();
|
||||
return renderedCamera;
|
||||
}
|
||||
|
||||
private failIfClosed() {
|
||||
if (this.isClosed) {
|
||||
throw "The RenderedCamera has already been closed.";
|
||||
}
|
||||
}
|
||||
|
||||
private getFirstTrackOrFail(): MediaStreamTrack {
|
||||
this.failIfClosed();
|
||||
|
||||
if (this.mediaStream.getVideoTracks().length === 0) {
|
||||
throw "No video tracks found";
|
||||
}
|
||||
|
||||
return this.mediaStream.getVideoTracks()[0];
|
||||
}
|
||||
|
||||
//#region Public APIs.
|
||||
public pause(): void {
|
||||
this.failIfClosed();
|
||||
this.surface.pause();
|
||||
}
|
||||
|
||||
public resume(onResumeCallback: () => void): void {
|
||||
this.failIfClosed();
|
||||
let $this = this;
|
||||
|
||||
const onVideoResume = () => {
|
||||
// Transition after 200ms to avoid the previous canvas frame being
|
||||
// re-scanned.
|
||||
setTimeout(onResumeCallback, 200);
|
||||
$this.surface.removeEventListener("playing", onVideoResume);
|
||||
};
|
||||
|
||||
this.surface.addEventListener("playing", onVideoResume);
|
||||
this.surface.play();
|
||||
}
|
||||
|
||||
public isPaused(): boolean {
|
||||
this.failIfClosed();
|
||||
return this.surface.paused;
|
||||
}
|
||||
|
||||
public getSurface(): HTMLVideoElement {
|
||||
this.failIfClosed();
|
||||
return this.surface;
|
||||
}
|
||||
|
||||
public getRunningTrackCapabilities(): MediaTrackCapabilities {
|
||||
return this.getFirstTrackOrFail().getCapabilities();
|
||||
}
|
||||
|
||||
public getRunningTrackSettings(): MediaTrackSettings {
|
||||
return this.getFirstTrackOrFail().getSettings();
|
||||
}
|
||||
|
||||
public async applyVideoConstraints(constraints: MediaTrackConstraints)
|
||||
: Promise<void> {
|
||||
if ("aspectRatio" in constraints) {
|
||||
throw "Changing 'aspectRatio' in run-time is not yet supported.";
|
||||
}
|
||||
|
||||
return this.getFirstTrackOrFail().applyConstraints(constraints);
|
||||
}
|
||||
|
||||
public close(): Promise<void> {
|
||||
if (this.isClosed) {
|
||||
// Already closed.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let $this = this;
|
||||
return new Promise((resolve, _) => {
|
||||
let tracks = $this.mediaStream.getVideoTracks();
|
||||
const tracksToClose = tracks.length;
|
||||
var tracksClosed = 0;
|
||||
$this.mediaStream.getVideoTracks().forEach((videoTrack) => {
|
||||
$this.mediaStream.removeTrack(videoTrack);
|
||||
videoTrack.stop();
|
||||
++tracksClosed;
|
||||
|
||||
if (tracksClosed >= tracksToClose) {
|
||||
$this.isClosed = true;
|
||||
$this.parentElement.removeChild($this.surface);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
getCapabilities(): CameraCapabilities {
|
||||
return new CameraCapabilitiesImpl(this.getFirstTrackOrFail());
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
/** Default implementation of {@link Camera} interface. */
|
||||
export class CameraImpl implements Camera {
|
||||
private readonly mediaStream: MediaStream;
|
||||
|
||||
private constructor(mediaStream: MediaStream) {
|
||||
this.mediaStream = mediaStream;
|
||||
}
|
||||
|
||||
async render(
|
||||
parentElement: HTMLElement,
|
||||
options: CameraRenderingOptions,
|
||||
callbacks: RenderingCallbacks)
|
||||
: Promise<RenderedCamera> {
|
||||
return RenderedCameraImpl.create(
|
||||
parentElement, this.mediaStream, options, callbacks);
|
||||
}
|
||||
|
||||
static async create(videoConstraints: MediaTrackConstraints)
|
||||
: Promise<Camera> {
|
||||
if (!navigator.mediaDevices) {
|
||||
throw "navigator.mediaDevices not supported";
|
||||
}
|
||||
let constraints: MediaStreamConstraints = {
|
||||
audio: false,
|
||||
video: videoConstraints
|
||||
};
|
||||
|
||||
let mediaStream = await navigator.mediaDevices.getUserMedia(
|
||||
constraints);
|
||||
return new CameraImpl(mediaStream);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user