Files
securebit-chat/node_modules/html5-qrcode/src/state-manager.ts
lockbitchat 34094956b7 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
2025-09-23 20:01:02 -04:00

194 lines
5.6 KiB
TypeScript

/**
* @fileoverview
* State handler.
*
* @author mebjas <minhazav@gmail.com>
*/
/** Different states of scanner */
export enum Html5QrcodeScannerState {
// Invalid internal state, do not set to this state.
UNKNOWN = 0,
// Indicates the scanning is not running or user is using file based
// scanning.
NOT_STARTED = 1,
// Camera scan is running.
SCANNING,
// Camera scan is paused but camera is running.
PAUSED,
}
/** Transaction for state transition. */
export interface StateManagerTransaction {
/**
* Executes the current transaction.
*/
execute(): void;
/**
* Cancels the current transaction.
*/
cancel(): void;
}
/** Manager class for states. */
export interface StateManager {
/**
* Start a transition to a new state. No other transitions will be allowed
* till this one is executed.
*
* @param newState new state to transition to.
*
* @returns transaction of type {@interface StateManagerTransaction}.
*
* @throws error if the new state is not a valid transition from current
* state.
*/
startTransition(newState: Html5QrcodeScannerState): StateManagerTransaction;
/**
* Directly execute a transition.
*
* @param newState new state to transition to.
*
* @throws error if the new state is not a valid transition from current
* state.
*/
directTransition(newState: Html5QrcodeScannerState): void;
/**
* Get current state.
*/
getState(): Html5QrcodeScannerState;
}
/**
* Implementation of {@interface StateManager} and
* {@interface StateManagerTransaction}.
*/
class StateManagerImpl implements StateManager, StateManagerTransaction {
private state: Html5QrcodeScannerState = Html5QrcodeScannerState.NOT_STARTED;
private onGoingTransactionNewState: Html5QrcodeScannerState
= Html5QrcodeScannerState.UNKNOWN;
public directTransition(newState: Html5QrcodeScannerState) {
this.failIfTransitionOngoing();
this.validateTransition(newState);
this.state = newState;
}
public startTransition(newState: Html5QrcodeScannerState): StateManagerTransaction {
this.failIfTransitionOngoing();
this.validateTransition(newState);
this.onGoingTransactionNewState = newState;
return this;
}
public execute() {
if (this.onGoingTransactionNewState
=== Html5QrcodeScannerState.UNKNOWN) {
throw "Transaction is already cancelled, cannot execute().";
}
const tempNewState = this.onGoingTransactionNewState;
this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;
this.directTransition(tempNewState);
}
public cancel() {
if (this.onGoingTransactionNewState
=== Html5QrcodeScannerState.UNKNOWN) {
throw "Transaction is already cancelled, cannot cancel().";
}
this.onGoingTransactionNewState = Html5QrcodeScannerState.UNKNOWN;
}
public getState(): Html5QrcodeScannerState {
return this.state;
}
//#region private methods
private failIfTransitionOngoing() {
if (this.onGoingTransactionNewState
!== Html5QrcodeScannerState.UNKNOWN) {
throw "Cannot transition to a new state, already under transition";
}
}
private validateTransition(newState: Html5QrcodeScannerState) {
switch(this.state) {
case Html5QrcodeScannerState.UNKNOWN:
throw "Transition from unknown is not allowed";
case Html5QrcodeScannerState.NOT_STARTED:
this.failIfNewStateIs(newState, [Html5QrcodeScannerState.PAUSED]);
break;
case Html5QrcodeScannerState.SCANNING:
// Both state transitions legal from here.
break;
case Html5QrcodeScannerState.PAUSED:
// Both state transitions legal from here.
break;
}
}
private failIfNewStateIs(
newState: Html5QrcodeScannerState,
disallowedStatesToTransition: Array<Html5QrcodeScannerState>) {
for (const disallowedState of disallowedStatesToTransition) {
if (newState === disallowedState) {
throw `Cannot transition from ${this.state} to ${newState}`;
}
}
}
//#endregion
}
export class StateManagerProxy {
private stateManager: StateManager;
constructor(stateManager: StateManager) {
this.stateManager = stateManager;
}
startTransition(newState: Html5QrcodeScannerState): StateManagerTransaction {
return this.stateManager.startTransition(newState);
}
directTransition(newState: Html5QrcodeScannerState) {
this.stateManager.directTransition(newState);
}
getState(): Html5QrcodeScannerState {
return this.stateManager.getState();
}
canScanFile(): boolean {
return this.stateManager.getState() === Html5QrcodeScannerState.NOT_STARTED;
}
isScanning(): boolean {
return this.stateManager.getState() !== Html5QrcodeScannerState.NOT_STARTED;
}
isStrictlyScanning(): boolean {
return this.stateManager.getState() === Html5QrcodeScannerState.SCANNING;
}
isPaused(): boolean {
return this.stateManager.getState() === Html5QrcodeScannerState.PAUSED;
}
}
/**
* Factory for creating instance of {@class StateManagerProxy}.
*/
export class StateManagerFactory {
public static create(): StateManagerProxy {
return new StateManagerProxy(new StateManagerImpl());
}
}