@privateid/ultrapass-web-sdk 1.3.1 → 1.3.2-1300478
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -75
- package/dist/apiUtils.d.ts +46 -46
- package/dist/apiUtils.js +922 -922
- package/dist/application/index.d.ts +7 -7
- package/dist/application/index.js +27 -27
- package/dist/application/modules/core/document/DocumentService.d.ts +22 -22
- package/dist/application/modules/core/document/DocumentService.js +254 -254
- package/dist/application/modules/core/document/document.constants.d.ts +15 -15
- package/dist/application/modules/core/document/document.constants.js +21 -21
- package/dist/application/modules/core/document/document.domain.d.ts +7 -7
- package/dist/application/modules/core/document/document.domain.js +1 -1
- package/dist/application/modules/core/document/document.types.d.ts +17 -17
- package/dist/application/modules/core/document/document.types.js +1 -1
- package/dist/application/modules/core/document/document.utils.d.ts +3 -3
- package/dist/application/modules/core/document/document.utils.js +58 -58
- package/dist/application/modules/core/document/index.d.ts +3 -3
- package/dist/application/modules/core/document/index.js +1 -1
- package/dist/application/modules/core/face/FaceService.d.ts +33 -33
- package/dist/application/modules/core/face/FaceService.js +228 -221
- package/dist/application/modules/core/face/FaceService.js.map +1 -1
- package/dist/application/modules/core/face/face.constants.d.ts +53 -53
- package/dist/application/modules/core/face/face.constants.js +53 -53
- package/dist/application/modules/core/face/face.domain.d.ts +10 -10
- package/dist/application/modules/core/face/face.domain.js +1 -1
- package/dist/application/modules/core/face/face.types.d.ts +41 -38
- package/dist/application/modules/core/face/face.types.js +1 -1
- package/dist/application/modules/core/face/face.utils.d.ts +15 -15
- package/dist/application/modules/core/face/face.utils.js +101 -101
- package/dist/application/modules/core/face/index.d.ts +3 -3
- package/dist/application/modules/core/face/index.js +1 -1
- package/dist/application/modules/global/shared.constants.d.ts +2 -2
- package/dist/application/modules/global/shared.constants.js +2 -2
- package/dist/application/modules/global/shared.utils.d.ts +25 -25
- package/dist/application/modules/global/shared.utils.js +100 -100
- package/dist/application/modules/global/shared.utils.js.map +1 -1
- package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.d.ts +9 -0
- package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js +32 -0
- package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js.map +1 -0
- package/dist/application/modules/internal/feature-flag/feature-flag-init.d.ts +11 -0
- package/dist/application/modules/internal/feature-flag/feature-flag-init.js +24 -0
- package/dist/application/modules/internal/feature-flag/feature-flag-init.js.map +1 -0
- package/dist/application/modules/internal/feature-flag/feature-flag.domain.d.ts +10 -0
- package/dist/application/modules/internal/feature-flag/feature-flag.domain.js +7 -0
- package/dist/application/modules/internal/feature-flag/feature-flag.domain.js.map +1 -0
- package/dist/application/modules/internal/feature-flag/featureFlagInit.d.ts +11 -0
- package/dist/application/modules/internal/feature-flag/featureFlagInit.js +44 -0
- package/dist/application/modules/internal/feature-flag/featureFlagInit.js.map +1 -0
- package/dist/application/modules/internal/feature-flag/index.d.ts +2 -0
- package/dist/application/modules/internal/feature-flag/index.js +3 -0
- package/dist/application/modules/internal/feature-flag/index.js.map +1 -0
- package/dist/application/modules/internal/shared/index.d.ts +2 -0
- package/dist/application/modules/internal/shared/index.js +3 -0
- package/dist/application/modules/internal/shared/index.js.map +1 -0
- package/dist/application/modules/internal/shared/shared.constants.d.ts +2 -0
- package/dist/application/modules/internal/shared/shared.constants.js +3 -0
- package/dist/application/modules/internal/shared/shared.constants.js.map +1 -0
- package/dist/application/modules/internal/shared/shared.utils.d.ts +44 -0
- package/dist/application/modules/internal/shared/shared.utils.js +204 -0
- package/dist/application/modules/internal/shared/shared.utils.js.map +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.d.ts +28 -0
- package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js +380 -0
- package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js.map +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/index.d.ts +6 -0
- package/dist/application/modules/internal/wasm-orchestrator/index.js +9 -0
- package/dist/application/modules/internal/wasm-orchestrator/index.js.map +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.constants.d.ts +28 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.constants.js +35 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.constants.js.map +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.domain.d.ts +51 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.domain.js +2 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.domain.js.map +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.d.ts +142 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.js +2 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.js.map +1 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.d.ts +86 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js +201 -0
- package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js.map +1 -0
- package/dist/application/modules/support/camera/CameraServiceFactory.d.ts +10 -10
- package/dist/application/modules/support/camera/CameraServiceFactory.js +33 -33
- package/dist/application/modules/support/camera/CameraServiceFactory.js.map +1 -1
- package/dist/application/modules/support/camera/camera.constants.d.ts +9 -9
- package/dist/application/modules/support/camera/camera.constants.js +48 -48
- package/dist/application/modules/support/camera/camera.domain.d.ts +15 -15
- package/dist/application/modules/support/camera/camera.domain.js +1 -1
- package/dist/application/modules/support/camera/camera.types.d.ts +42 -42
- package/dist/application/modules/support/camera/camera.types.js +10 -10
- package/dist/application/modules/support/camera/camera.utils.d.ts +157 -157
- package/dist/application/modules/support/camera/camera.utils.js +623 -623
- package/dist/application/modules/support/camera/index.d.ts +24 -24
- package/dist/application/modules/support/camera/index.js +27 -27
- package/dist/application/modules/support/camera/services/BaseCameraService.d.ts +41 -41
- package/dist/application/modules/support/camera/services/BaseCameraService.js +278 -278
- package/dist/application/modules/support/camera/services/DesktopCameraService.d.ts +5 -5
- package/dist/application/modules/support/camera/services/DesktopCameraService.js +46 -46
- package/dist/application/modules/support/camera/services/FirefoxCameraService.d.ts +5 -5
- package/dist/application/modules/support/camera/services/FirefoxCameraService.js +46 -46
- package/dist/application/modules/support/camera/services/MacSafariCameraService.d.ts +5 -5
- package/dist/application/modules/support/camera/services/MacSafariCameraService.js +47 -47
- package/dist/application/modules/support/camera/services/MobileCameraService.d.ts +5 -5
- package/dist/application/modules/support/camera/services/MobileCameraService.js +133 -133
- package/dist/application/modules/support/engine/EngineService.d.ts +15 -0
- package/dist/application/modules/support/engine/EngineService.js +106 -0
- package/dist/application/modules/support/engine/EngineService.js.map +1 -0
- package/dist/application/modules/support/engine/engine.constants.d.ts +33 -0
- package/dist/application/modules/support/engine/engine.constants.js +35 -0
- package/dist/application/modules/support/engine/engine.constants.js.map +1 -0
- package/dist/application/modules/support/engine/engine.domain.d.ts +23 -0
- package/dist/application/modules/support/engine/engine.domain.js +2 -0
- package/dist/application/modules/support/engine/engine.domain.js.map +1 -0
- package/dist/application/modules/support/engine/engine.types.d.ts +32 -0
- package/dist/application/modules/support/engine/engine.types.js +2 -0
- package/dist/application/modules/support/engine/engine.types.js.map +1 -0
- package/dist/application/modules/support/engine/engine.utils.d.ts +65 -0
- package/dist/application/modules/support/engine/engine.utils.js +135 -0
- package/dist/application/modules/support/engine/engine.utils.js.map +1 -0
- package/dist/application/modules/support/engine/index.d.ts +3 -0
- package/dist/application/modules/support/engine/index.js +2 -0
- package/dist/application/modules/support/engine/index.js.map +1 -0
- package/dist/application/modules/support/permissions/PermissionsService.d.ts +55 -55
- package/dist/application/modules/support/permissions/PermissionsService.js +183 -183
- package/dist/application/modules/support/permissions/index.d.ts +4 -4
- package/dist/application/modules/support/permissions/index.js +2 -2
- package/dist/application/modules/support/permissions/permission.utils.d.ts +6 -6
- package/dist/application/modules/support/permissions/permission.utils.js +33 -33
- package/dist/application/modules/support/permissions/permissions.domain.d.ts +6 -6
- package/dist/application/modules/support/permissions/permissions.domain.js +1 -1
- package/dist/application/modules/support/permissions/permissions.types.d.ts +9 -9
- package/dist/application/modules/support/permissions/permissions.types.js +1 -1
- package/dist/application/modules/support/wasm/WasmService.d.ts +25 -25
- package/dist/application/modules/support/wasm/WasmService.js +156 -155
- package/dist/application/modules/support/wasm/WasmService.js.map +1 -1
- package/dist/application/modules/support/wasm/index.d.ts +6 -6
- package/dist/application/modules/support/wasm/index.js +8 -8
- package/dist/application/modules/support/wasm/wasm.constants.d.ts +78 -78
- package/dist/application/modules/support/wasm/wasm.constants.js +86 -86
- package/dist/application/modules/support/wasm/wasm.domain.d.ts +52 -52
- package/dist/application/modules/support/wasm/wasm.domain.js +1 -1
- package/dist/application/modules/support/wasm/wasm.types.d.ts +119 -118
- package/dist/application/modules/support/wasm/wasm.types.js +1 -1
- package/dist/application/modules/support/wasm/wasm.utils.d.ts +88 -88
- package/dist/application/modules/support/wasm/wasm.utils.js +243 -243
- package/dist/application/modules/support/wasm-orchestrator/WasmOrchestratorService.d.ts +28 -0
- package/dist/application/modules/support/wasm-orchestrator/WasmOrchestratorService.js +324 -0
- package/dist/application/modules/support/wasm-orchestrator/WasmOrchestratorService.js.map +1 -0
- package/dist/application/modules/support/wasm-orchestrator/index.d.ts +6 -0
- package/dist/application/modules/support/wasm-orchestrator/index.js +9 -0
- package/dist/application/modules/support/wasm-orchestrator/index.js.map +1 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.constants.d.ts +36 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.constants.js +44 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.constants.js.map +1 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.domain.d.ts +47 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.domain.js +2 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.domain.js.map +1 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.types.d.ts +136 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.types.js +2 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.types.js.map +1 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.utils.d.ts +91 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.utils.js +250 -0
- package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.utils.js.map +1 -0
- package/dist/application/workers/index.d.ts +42 -42
- package/dist/application/workers/index.js +8 -8
- package/dist/application/workers/wasm/WasmWorkerService.d.ts +66 -0
- package/dist/application/workers/wasm/WasmWorkerService.js +801 -0
- package/dist/application/workers/wasm/WasmWorkerService.js.map +1 -0
- package/dist/application/workers/wasm/index.d.ts +4 -0
- package/dist/application/workers/wasm/index.js +9 -0
- package/dist/application/workers/wasm/index.js.map +1 -0
- package/dist/application/workers/wasm/wasm-worker.constants.d.ts +5 -0
- package/dist/application/workers/wasm/wasm-worker.constants.js +6 -0
- package/dist/application/workers/wasm/wasm-worker.constants.js.map +1 -0
- package/dist/application/workers/wasm/wasm-worker.domain.d.ts +99 -0
- package/dist/application/workers/wasm/wasm-worker.domain.js +2 -0
- package/dist/application/workers/wasm/wasm-worker.domain.js.map +1 -0
- package/dist/application/workers/wasm/wasm-worker.types.d.ts +88 -0
- package/dist/application/workers/wasm/wasm-worker.types.js +2 -0
- package/dist/application/workers/wasm/wasm-worker.types.js.map +1 -0
- package/dist/application/workers/wasm/wasm-worker.utils.d.ts +10 -0
- package/dist/application/workers/wasm/wasm-worker.utils.js +130 -0
- package/dist/application/workers/wasm/wasm-worker.utils.js.map +1 -0
- package/dist/buildConfig.d.ts +3 -0
- package/dist/buildConfig.js +7 -0
- package/dist/buildConfig.js.map +1 -0
- package/dist/cameraUtils.d.ts +77 -77
- package/dist/cameraUtils.js +361 -361
- package/dist/constants.d.ts +9 -9
- package/dist/constants.js +13 -13
- package/dist/createCallback.d.ts +56 -56
- package/dist/createCallback.js +332 -331
- package/dist/createCallback.js.map +1 -1
- package/dist/dbUtils.d.ts +14 -14
- package/dist/dbUtils.js +148 -148
- package/dist/envUtils.d.ts +4 -4
- package/dist/envUtils.js +16 -16
- package/dist/faceModule.d.ts +196 -196
- package/dist/faceModule.js +978 -978
- package/dist/featureFlagInit.d.ts +11 -0
- package/dist/featureFlagInit.js +44 -0
- package/dist/featureFlagInit.js.map +1 -0
- package/dist/index.d.ts +38 -38
- package/dist/index.js +82 -82
- package/dist/main.d.ts +30 -30
- package/dist/main.js +84 -84
- package/dist/types.d.ts +139 -139
- package/dist/types.js +77 -77
- package/dist/utils.d.ts +84 -84
- package/dist/utils.js +580 -580
- package/package.json +102 -102
- package/wasm/ultra/nosimd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.js +18 -18
- package/wasm/ultra/nosimd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.wasm +0 -0
- package/wasm/ultra/nosimd/version.json +2 -2
- package/wasm/ultra/simd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.js +18 -18
- package/wasm/ultra/simd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.wasm +0 -0
- package/wasm/ultra/simd/version.json +2 -2
- package/workers/comlink.min.js +7 -7
- package/workers/comlink.min.js.map +1 -1
- package/workers/wasm.worker.js +936 -924
|
@@ -1,624 +1,624 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { UAParser } from 'ua-parser-js';
|
|
11
|
-
import { CameraFaceMode, FacingMode, } from './camera.types';
|
|
12
|
-
import { PORTRAIT, LANDSCAPE, BACK_CAMERA_WORDS, CAMERA_HEIGHT, CAMERA_WIDTH, CAMERA_LOW_RES_WIDTH, MOBILE_CAMERA_RES_HEIGHT, MOBILE_CAMERA_LOW_RES_HEIGHT, } from './camera.constants';
|
|
13
|
-
import { getDefaultCameraDeviceId, printLogs } from '../../global/shared.utils';
|
|
14
|
-
export function getScreenOrientation() {
|
|
15
|
-
if (window.innerHeight > window.innerWidth) {
|
|
16
|
-
return PORTRAIT;
|
|
17
|
-
}
|
|
18
|
-
return LANDSCAPE;
|
|
19
|
-
}
|
|
20
|
-
export function getUserAgent() {
|
|
21
|
-
const userAgent = typeof window !== 'undefined' && navigator && window.navigator.userAgent;
|
|
22
|
-
return userAgent || undefined;
|
|
23
|
-
}
|
|
24
|
-
export function parseUserAgent() {
|
|
25
|
-
// This maybe evaluated in next.js Node rather than in Browser
|
|
26
|
-
if (!getUserAgent()) {
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
const parser = new UAParser();
|
|
30
|
-
return parser.getResult();
|
|
31
|
-
}
|
|
32
|
-
export function isPortrait() {
|
|
33
|
-
return getScreenOrientation() === PORTRAIT;
|
|
34
|
-
}
|
|
35
|
-
export function isBackCameraAndPortrait(faceMode) {
|
|
36
|
-
const isBack = faceMode === FacingMode.environment;
|
|
37
|
-
return isBack && isPortrait();
|
|
38
|
-
}
|
|
39
|
-
// TODO: Refactor these `isSomethingUA` functions to be one.
|
|
40
|
-
export function isMobileUA() {
|
|
41
|
-
const result = parseUserAgent();
|
|
42
|
-
if (!result || !result.device || !result.device.type) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
return ['mobile', 'tablet'].includes(result.device.type);
|
|
46
|
-
}
|
|
47
|
-
export function isFirefoxUA() {
|
|
48
|
-
var _a;
|
|
49
|
-
const result = parseUserAgent();
|
|
50
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === 'Firefox';
|
|
51
|
-
}
|
|
52
|
-
export function isSafariUA() {
|
|
53
|
-
var _a;
|
|
54
|
-
const result = parseUserAgent();
|
|
55
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === 'Safari';
|
|
56
|
-
}
|
|
57
|
-
export function isChromeUA() {
|
|
58
|
-
var _a;
|
|
59
|
-
const result = parseUserAgent();
|
|
60
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === 'Chrome';
|
|
61
|
-
}
|
|
62
|
-
export function isSamsungUA() {
|
|
63
|
-
var _a;
|
|
64
|
-
const result = parseUserAgent();
|
|
65
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.device) === null || _a === void 0 ? void 0 : _a.vendor) === 'Samsung';
|
|
66
|
-
}
|
|
67
|
-
export function isAndroid() {
|
|
68
|
-
var _a;
|
|
69
|
-
const result = parseUserAgent();
|
|
70
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'Android';
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* See https://developer.chrome.com/docs/multidevice/user-agent/#webview_user_agent
|
|
74
|
-
* This onloy detects the WebView after Android 4.4. It'd return false for older
|
|
75
|
-
* Android version.
|
|
76
|
-
*/
|
|
77
|
-
export function isAndroidWebView() {
|
|
78
|
-
var _a, _b;
|
|
79
|
-
const result = parseUserAgent();
|
|
80
|
-
// If the user-agent string contains "wv", 'ua-parser-js' will return the
|
|
81
|
-
// string "WebView" as part of its browser name.
|
|
82
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'Android' && /WebView/.test(String((_b = result === null || result === void 0 ? void 0 : result.browser) === null || _b === void 0 ? void 0 : _b.name));
|
|
83
|
-
}
|
|
84
|
-
export function isAndroid12OrAbove() {
|
|
85
|
-
return getMajorAndroidVersion() >= 12;
|
|
86
|
-
}
|
|
87
|
-
export function isIOSUA() {
|
|
88
|
-
var _a;
|
|
89
|
-
const result = parseUserAgent();
|
|
90
|
-
return ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'iOS';
|
|
91
|
-
}
|
|
92
|
-
export function getMajorAndroidVersion() {
|
|
93
|
-
var _a, _b;
|
|
94
|
-
const result = parseUserAgent();
|
|
95
|
-
const matched = ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'Android' ? String(((_b = result === null || result === void 0 ? void 0 : result.os) === null || _b === void 0 ? void 0 : _b.version) || '').match(/^\d+/) : null;
|
|
96
|
-
return matched ? parseInt(matched[0], 10) : NaN;
|
|
97
|
-
}
|
|
98
|
-
export function getMajorSafariVersion() {
|
|
99
|
-
var _a, _b;
|
|
100
|
-
const result = parseUserAgent();
|
|
101
|
-
const name = (_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name;
|
|
102
|
-
if (name === 'Safari' || name === 'Mobile Safari') {
|
|
103
|
-
return parseInt(((_b = result === null || result === void 0 ? void 0 : result.browser) === null || _b === void 0 ? void 0 : _b.version) || '', 10);
|
|
104
|
-
}
|
|
105
|
-
return NaN;
|
|
106
|
-
}
|
|
107
|
-
export function getMajorChromeVersion() {
|
|
108
|
-
var _a, _b, _c;
|
|
109
|
-
const result = parseUserAgent();
|
|
110
|
-
return ((_b = (_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.includes('Chrome')) ? parseInt(((_c = result === null || result === void 0 ? void 0 : result.browser) === null || _c === void 0 ? void 0 : _c.version) || '', 10) : NaN;
|
|
111
|
-
}
|
|
112
|
-
export function getMajorIOSVersion() {
|
|
113
|
-
var _a, _b;
|
|
114
|
-
const result = parseUserAgent();
|
|
115
|
-
const matched = ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'iOS' ? String(((_b = result === null || result === void 0 ? void 0 : result.os) === null || _b === void 0 ? void 0 : _b.version) || '').match(/^\d+/) : null;
|
|
116
|
-
return matched ? parseInt(matched[0], 10) : NaN;
|
|
117
|
-
}
|
|
118
|
-
export function getMajorMinorOsVersion() {
|
|
119
|
-
var _a;
|
|
120
|
-
const result = parseUserAgent();
|
|
121
|
-
const version = String(((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.version) || '');
|
|
122
|
-
const matched = version.match(/(^\d+)(\.\d+)?/);
|
|
123
|
-
return (matched && matched[0]) || 'unknown';
|
|
124
|
-
}
|
|
125
|
-
export function isWindows() {
|
|
126
|
-
var _a, _b;
|
|
127
|
-
return getPlatform() === 'desktop' && ((_b = (_a = parseUserAgent()) === null || _a === void 0 ? void 0 : _a.os) === null || _b === void 0 ? void 0 : _b.name) === 'Windows';
|
|
128
|
-
}
|
|
129
|
-
export function isMac() {
|
|
130
|
-
var _a, _b;
|
|
131
|
-
return getPlatform() === 'desktop' && ((_b = (_a = parseUserAgent()) === null || _a === void 0 ? void 0 : _a.os) === null || _b === void 0 ? void 0 : _b.name) === 'Mac OS';
|
|
132
|
-
}
|
|
133
|
-
export function isLinux() {
|
|
134
|
-
var _a;
|
|
135
|
-
const ua = parseUserAgent();
|
|
136
|
-
return ((_a = ua === null || ua === void 0 ? void 0 : ua.os) === null || _a === void 0 ? void 0 : _a.name) === 'Linux';
|
|
137
|
-
}
|
|
138
|
-
// This returns the "platform"- iphone vs android vs desktop used for reporting metrics.
|
|
139
|
-
// Do not make this into something with high cardinality- that will impact SignalFX.
|
|
140
|
-
// If you need to alter/add to these values, please make sure to update the relevant
|
|
141
|
-
// SignalFX metrics as well.
|
|
142
|
-
export function getPlatform() {
|
|
143
|
-
if (isAndroid()) {
|
|
144
|
-
return 'android';
|
|
145
|
-
}
|
|
146
|
-
if (isIOSUA()) {
|
|
147
|
-
return 'iphone';
|
|
148
|
-
}
|
|
149
|
-
return 'desktop';
|
|
150
|
-
}
|
|
151
|
-
export function isMobileDevice() {
|
|
152
|
-
return isMobileUA() || isAndroidDesktop() || isIOSDesktop();
|
|
153
|
-
}
|
|
154
|
-
// Whether it's an IOS browser requesting desktop site.
|
|
155
|
-
export function isIOSDesktop() {
|
|
156
|
-
// IOS browser => Request Desktop Site.
|
|
157
|
-
return isMac() && window.navigator.maxTouchPoints > 1;
|
|
158
|
-
}
|
|
159
|
-
export function isIOS() {
|
|
160
|
-
return isIOSUA() || isIOSDesktop();
|
|
161
|
-
}
|
|
162
|
-
export function isIOS15OrGreater() {
|
|
163
|
-
if (isIOSDesktop()) {
|
|
164
|
-
// In the past, the version of Safari has been in sync with the version of
|
|
165
|
-
// iOS. Therefore, we could use Safari's version as a proxy to determine
|
|
166
|
-
// the version of iOS. However, it's not possible to determine the iOS
|
|
167
|
-
// version using other types of browsers.
|
|
168
|
-
return getMajorSafariVersion() >= 15;
|
|
169
|
-
}
|
|
170
|
-
// iOS Mobile.
|
|
171
|
-
return getMajorIOSVersion() >= 15;
|
|
172
|
-
}
|
|
173
|
-
// Whether it's an Android browser requesting desktop site.
|
|
174
|
-
export function isAndroidDesktop() {
|
|
175
|
-
// Android browser => Request Desktop Site.
|
|
176
|
-
return isLinux() && window.navigator.maxTouchPoints > 1;
|
|
177
|
-
}
|
|
178
|
-
export const isBackCameraLabel = (label) => {
|
|
179
|
-
const lowerCase = (label === null || label === void 0 ? void 0 : label.toLowerCase()) || '';
|
|
180
|
-
return BACK_CAMERA_WORDS.some((keyword) => lowerCase === null || lowerCase === void 0 ? void 0 : lowerCase.includes(keyword));
|
|
181
|
-
};
|
|
182
|
-
export const isMobileBackCameraPortrait = ({ label, facingMode }) => {
|
|
183
|
-
const isBackCamera = isBackCameraLabel(label) || (facingMode === null || facingMode === void 0 ? void 0 : facingMode.includes(FacingMode.environment));
|
|
184
|
-
return isMobileDevice() && isBackCamera && isPortrait();
|
|
185
|
-
};
|
|
186
|
-
export function isFaceTimeCamera(label, isDocumentScan) {
|
|
187
|
-
return isMac() && label.includes('FaceTime') && isDocumentScan;
|
|
188
|
-
}
|
|
189
|
-
export const getCameraList = (backOnly) => __awaiter(void 0, void 0, void 0, function* () {
|
|
190
|
-
try {
|
|
191
|
-
if (!navigator.mediaDevices) {
|
|
192
|
-
return [];
|
|
193
|
-
}
|
|
194
|
-
let cameraList = yield navigator.mediaDevices.enumerateDevices().then((devices) => {
|
|
195
|
-
const filteredDevices = devices.filter((device) => {
|
|
196
|
-
let filteredLabels = true;
|
|
197
|
-
if (!backOnly) {
|
|
198
|
-
filteredLabels = !isBackCameraLabel(device.label);
|
|
199
|
-
}
|
|
200
|
-
return device.kind === 'videoinput' && filteredLabels;
|
|
201
|
-
});
|
|
202
|
-
return filteredDevices.map((device) => {
|
|
203
|
-
// @ts-ignore
|
|
204
|
-
if (device === null || device === void 0 ? void 0 : device.getCapabilities) {
|
|
205
|
-
// @ts-ignore
|
|
206
|
-
return Object.assign(Object.assign({}, device === null || device === void 0 ? void 0 : device.getCapabilities()), { deviceId: device.deviceId, label: device.label });
|
|
207
|
-
}
|
|
208
|
-
return { deviceId: device.deviceId, label: device.label };
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
if (isAndroid()) {
|
|
212
|
-
cameraList = cameraList.sort((a, b) => (a.label < b.label ? -1 : 1));
|
|
213
|
-
}
|
|
214
|
-
return cameraList;
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
// handleException(error, 'error listing cameras');
|
|
218
|
-
return [];
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
export const getMobileVideoConstraints = (availableDevices, faceMode, isDocumentScan, canvasResolution, selectedDeviceId, isFirstPermissionRequest) => {
|
|
222
|
-
// Use 1.5 ratio. US DL are 1.58, passport are 1.42, so take something in the middle
|
|
223
|
-
let device = availableDevices === null || availableDevices === void 0 ? void 0 : availableDevices[0]; // get the first device by default
|
|
224
|
-
let useDirectDeviceId = false;
|
|
225
|
-
if (selectedDeviceId && availableDevices) {
|
|
226
|
-
const selectedDevice = availableDevices.find((d) => d.deviceId === selectedDeviceId);
|
|
227
|
-
if (selectedDevice) {
|
|
228
|
-
device = selectedDevice;
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
useDirectDeviceId = true;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
else if (isIOS() && isDocumentScan && availableDevices && (availableDevices === null || availableDevices === void 0 ? void 0 : availableDevices.length) > 2) {
|
|
235
|
-
const ultraWideDevice = availableDevices.find(({ label }) => label.includes('Dual Wide') || label.includes('Back Triple'));
|
|
236
|
-
device = ultraWideDevice || availableDevices[0];
|
|
237
|
-
}
|
|
238
|
-
let resizeMode = 'crop-and-scale';
|
|
239
|
-
if (isMobileDevice()) {
|
|
240
|
-
// Known cases that 'crop-and-scale' does not work.
|
|
241
|
-
if (
|
|
242
|
-
// Chrome 107+ on Android shows broken video in 'crop-and-scale'.
|
|
243
|
-
(isAndroid() && getMajorChromeVersion() >= 107) ||
|
|
244
|
-
// Samsung video driver has a bug when using resizeMode
|
|
245
|
-
(isSamsungUA() && !isAndroid12OrAbove())) {
|
|
246
|
-
resizeMode = 'none';
|
|
247
|
-
}
|
|
248
|
-
// If it's the first permission request, use simpler constraints for better compatibility
|
|
249
|
-
if (isFirstPermissionRequest) {
|
|
250
|
-
printLogs('[getMobileVideoConstraints] Using simplified constraints for first permission request', {});
|
|
251
|
-
return {
|
|
252
|
-
audio: false,
|
|
253
|
-
video: {
|
|
254
|
-
facingMode: faceMode,
|
|
255
|
-
},
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
let videoWidth;
|
|
259
|
-
let videoHeight;
|
|
260
|
-
let aspectRatio;
|
|
261
|
-
if ((canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) && (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height)) {
|
|
262
|
-
// Front cameras typically don't support high resolutions, limit them to 1920x1080
|
|
263
|
-
// Back cameras can use higher resolution for document scanning quality
|
|
264
|
-
const isFrontCamera = faceMode === FacingMode.face;
|
|
265
|
-
const maxWidth = isFrontCamera ? Math.min(canvasResolution.width, 1920) : canvasResolution.width;
|
|
266
|
-
const maxHeight = isFrontCamera ? Math.min(canvasResolution.height, 1080) : canvasResolution.height;
|
|
267
|
-
// Use 'ideal' instead of exact values to allow camera to fall back to supported resolutions
|
|
268
|
-
videoWidth = { ideal: maxWidth };
|
|
269
|
-
videoHeight = { ideal: maxHeight };
|
|
270
|
-
aspectRatio = 1.7777777778;
|
|
271
|
-
}
|
|
272
|
-
else if (faceMode) {
|
|
273
|
-
videoWidth = isBackCameraAndPortrait(faceMode)
|
|
274
|
-
? // ? { min: cameraLowResHeight, max: mobileCameraResHeight }
|
|
275
|
-
{ ideal: MOBILE_CAMERA_RES_HEIGHT }
|
|
276
|
-
: { ideal: CAMERA_LOW_RES_WIDTH };
|
|
277
|
-
videoHeight = isBackCameraAndPortrait(faceMode)
|
|
278
|
-
? // ? { min: cameraLowResHeight, max: mobileCameraResHeight }
|
|
279
|
-
{ ideal: MOBILE_CAMERA_RES_HEIGHT }
|
|
280
|
-
: undefined;
|
|
281
|
-
aspectRatio = isBackCameraAndPortrait(faceMode) ? 1 : 1.7777777778;
|
|
282
|
-
}
|
|
283
|
-
const finalConstraints = {
|
|
284
|
-
audio: false,
|
|
285
|
-
video: Object.assign(Object.assign({
|
|
286
|
-
// Use facingMode environment for back camera, user for front camera also provides better compatibility
|
|
287
|
-
facingMode: faceMode, resizeMode, width: videoWidth, height: videoHeight }, ((selectedDeviceId || useDirectDeviceId) && { deviceId: selectedDeviceId })), { aspectRatio }),
|
|
288
|
-
};
|
|
289
|
-
printLogs('[getMobileVideoConstraints] finalConstraits:', finalConstraints);
|
|
290
|
-
return finalConstraints;
|
|
291
|
-
}
|
|
292
|
-
return {
|
|
293
|
-
audio: false,
|
|
294
|
-
video: {
|
|
295
|
-
aspectRatio: 1.5,
|
|
296
|
-
// deviceId: deviceId ? deviceId.deviceId : undefined,
|
|
297
|
-
height: { min: MOBILE_CAMERA_LOW_RES_HEIGHT },
|
|
298
|
-
resizeMode,
|
|
299
|
-
},
|
|
300
|
-
};
|
|
301
|
-
};
|
|
302
|
-
export function scaleImageData(imageData, scaleFactor) {
|
|
303
|
-
const { width, height, data } = imageData;
|
|
304
|
-
// Create a new canvas and context for temporary scaling
|
|
305
|
-
const tempCanvas = document.createElement('canvas');
|
|
306
|
-
const tempCtx = tempCanvas.getContext('2d');
|
|
307
|
-
// Set the dimensions of the temporary canvas
|
|
308
|
-
tempCanvas.width = width * scaleFactor;
|
|
309
|
-
tempCanvas.height = height * scaleFactor;
|
|
310
|
-
// Draw the original image data onto the temporary canvas
|
|
311
|
-
tempCtx === null || tempCtx === void 0 ? void 0 : tempCtx.putImageData(imageData, 0, 0);
|
|
312
|
-
// Get the scaled image data from the temporary canvas
|
|
313
|
-
const scaledImageData = tempCtx === null || tempCtx === void 0 ? void 0 : tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
|
314
|
-
return scaledImageData;
|
|
315
|
-
}
|
|
316
|
-
export function zoomInCanvasImage(canvas, scaleFactor) {
|
|
317
|
-
// Get the current width and height of the canvas
|
|
318
|
-
const originalWidth = canvas.width;
|
|
319
|
-
const originalHeight = canvas.height;
|
|
320
|
-
// Calculate the new dimensions after applying the scale factor
|
|
321
|
-
const newWidth = Math.round(originalWidth / scaleFactor);
|
|
322
|
-
const newHeight = Math.round(originalHeight / scaleFactor);
|
|
323
|
-
// Calculate the amount of width and height to be cropped
|
|
324
|
-
const cropWidth = originalWidth - newWidth;
|
|
325
|
-
const cropHeight = originalHeight - newHeight;
|
|
326
|
-
// Create an offscreen canvas to hold the cropped image
|
|
327
|
-
const offscreenCanvas = document.createElement('canvas');
|
|
328
|
-
const offscreenCtx = offscreenCanvas.getContext('2d');
|
|
329
|
-
// Set the dimensions for the offscreen canvas
|
|
330
|
-
offscreenCanvas.width = originalWidth;
|
|
331
|
-
offscreenCanvas.height = originalHeight;
|
|
332
|
-
const centerX = originalWidth / 2;
|
|
333
|
-
const centerY = originalHeight / 2;
|
|
334
|
-
const sx = centerX - newWidth / (2 * scaleFactor);
|
|
335
|
-
const sy = centerY - newHeight / (2 * scaleFactor);
|
|
336
|
-
offscreenCtx === null || offscreenCtx === void 0 ? void 0 : offscreenCtx.drawImage(canvas, sx, sy, newWidth / scaleFactor, newHeight / scaleFactor,
|
|
337
|
-
// cropWidth / 2,
|
|
338
|
-
// cropHeight / 2, // sourceX, sourceY
|
|
339
|
-
// originalWidth - cropWidth,
|
|
340
|
-
// originalHeight - cropHeight, // sourceWidth, sourceHeight
|
|
341
|
-
0, 0, // destinationX, destinationY
|
|
342
|
-
// changing this for testing
|
|
343
|
-
newWidth, newHeight);
|
|
344
|
-
// Get the image data from the offscreen canvas
|
|
345
|
-
const imageData = offscreenCtx === null || offscreenCtx === void 0 ? void 0 : offscreenCtx.getImageData(0, 0, newWidth, newHeight);
|
|
346
|
-
// Return the image data
|
|
347
|
-
return imageData;
|
|
348
|
-
}
|
|
349
|
-
export const checkDeviceIsVirtualCamera = (deviceLabel) => {
|
|
350
|
-
const virtualCameraKeywords = ['virtual', 'obs', 'software', 'manycam'];
|
|
351
|
-
return virtualCameraKeywords.some((keyword) => deviceLabel.toLowerCase().includes(keyword));
|
|
352
|
-
};
|
|
353
|
-
export function getFilteredVideoDevices() {
|
|
354
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
355
|
-
// Retry logic for enumerateDevices to handle race conditions
|
|
356
|
-
let devices = [];
|
|
357
|
-
let attempts = 0;
|
|
358
|
-
const maxAttempts = 3;
|
|
359
|
-
while (attempts < maxAttempts) {
|
|
360
|
-
devices = yield navigator.mediaDevices.enumerateDevices();
|
|
361
|
-
const videoDevices = devices.filter((d) => d.kind === 'videoinput');
|
|
362
|
-
// Check if we have devices with labels (indicating permission was granted)
|
|
363
|
-
const hasValidDevices = videoDevices.some((d) => d.label && d.label.trim() !== '');
|
|
364
|
-
if (hasValidDevices || attempts === maxAttempts - 1) {
|
|
365
|
-
break;
|
|
366
|
-
}
|
|
367
|
-
printLogs(`[getFilteredVideoDevices] Attempt ${attempts + 1}: No valid devices found, retrying...`, '');
|
|
368
|
-
yield new Promise((resolve) => setTimeout(resolve, 200));
|
|
369
|
-
attempts++;
|
|
370
|
-
}
|
|
371
|
-
// Filter devices: only videoinput with valid label and not virtual
|
|
372
|
-
const filtered = devices.filter((d) => {
|
|
373
|
-
const isVideoInput = d.kind === 'videoinput';
|
|
374
|
-
const hasLabel = d.label && d.label.trim() !== '';
|
|
375
|
-
const notVirtual = !checkDeviceIsVirtualCamera(d.label);
|
|
376
|
-
return isVideoInput && hasLabel && notVirtual;
|
|
377
|
-
});
|
|
378
|
-
printLogs(`[getFilteredVideoDevices] Found ${filtered.length} valid video devices`, '');
|
|
379
|
-
return filtered;
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
export function filterDevicesByPattern(devices, pattern) {
|
|
383
|
-
return devices.filter((d) => pattern.test(d.label));
|
|
384
|
-
}
|
|
385
|
-
export function getExternalDevice(devices) {
|
|
386
|
-
return devices.length > 1 ? devices.find((device) => !device.label.includes('FaceTime')) : devices[0];
|
|
387
|
-
}
|
|
388
|
-
export function isWindowsDevice() {
|
|
389
|
-
return ['windows', 'win16', 'win32', 'wince'].includes(navigator.platform.toUpperCase());
|
|
390
|
-
}
|
|
391
|
-
export function getMediaDeviceInfo(devices, deviceId) {
|
|
392
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
393
|
-
const mediaDevinceInfo = devices.find((device) => device.deviceId === deviceId);
|
|
394
|
-
return mediaDevinceInfo;
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* This function open camera, and returns the stream, current faceMode and the list of available media devices
|
|
399
|
-
* @category Face
|
|
400
|
-
* @param domElement id of the video tag
|
|
401
|
-
*/
|
|
402
|
-
export function getTheNextResolutionAvailable(currentResolution) {
|
|
403
|
-
printLogs(`getTheNextResolutionAvailable `, currentResolution);
|
|
404
|
-
const resolutions = [2560, 1920, 1600, 1552, 1440, 1280, 1024, 960, 800, 720, 704, 640].sort((a, b) => b - a);
|
|
405
|
-
return resolutions.find((e) => e < currentResolution) || 640;
|
|
406
|
-
}
|
|
407
|
-
export function startVideo(videoElement, stream) {
|
|
408
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
-
// Wait for the video element to exist in DOM (up to 5 seconds)
|
|
410
|
-
let element = null;
|
|
411
|
-
const maxAttempts = 50; // 50 attempts * 100ms = 5 seconds max
|
|
412
|
-
const delayMs = 100;
|
|
413
|
-
printLogs(`[startVideo] Waiting for video element "${videoElement}" to be available in DOM...`, '');
|
|
414
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
415
|
-
element = document.getElementById(videoElement);
|
|
416
|
-
if (element) {
|
|
417
|
-
printLogs(`[startVideo] Element found after ${attempt} attempts (${attempt * delayMs}ms)`, '');
|
|
418
|
-
break;
|
|
419
|
-
}
|
|
420
|
-
printLogs(`[startVideo] Attempt ${attempt + 1}/${maxAttempts} - Element not found yet, waiting ${delayMs}ms...`, '');
|
|
421
|
-
yield new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
422
|
-
}
|
|
423
|
-
if (!element) {
|
|
424
|
-
const error = `[startVideo] Video element "${videoElement}" not found in DOM after ${maxAttempts * delayMs}ms`;
|
|
425
|
-
printLogs(error, '', 'ERROR');
|
|
426
|
-
throw new Error(error);
|
|
427
|
-
}
|
|
428
|
-
printLogs('[startVideo] Element found:', !!element);
|
|
429
|
-
printLogs('[startVideo] Stream tracks:', stream.getTracks().length);
|
|
430
|
-
element.srcObject = stream;
|
|
431
|
-
// Create a listener for the 'onplaying' event before calling play()
|
|
432
|
-
const playingPromise = new Promise((resolve) => {
|
|
433
|
-
element.onplaying = () => {
|
|
434
|
-
printLogs('[startVideo] Video onplaying fired', '');
|
|
435
|
-
resolve(undefined);
|
|
436
|
-
};
|
|
437
|
-
});
|
|
438
|
-
yield element.play();
|
|
439
|
-
printLogs('[startVideo] Video playing:', !element.paused);
|
|
440
|
-
// wait for the 'onplaying' event to ensure video is actually playing
|
|
441
|
-
yield playingPromise;
|
|
442
|
-
enableMutationObserver(element, stream);
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
export function enableMutationObserver(videoElement, stream) {
|
|
446
|
-
const videoMutationObserver = new MutationObserver(() => {
|
|
447
|
-
if (videoElement.srcObject !== stream) {
|
|
448
|
-
printLogs('Unauthorized video source change detected! Resetting to correct camera.', '', 'WARN');
|
|
449
|
-
// eslint-disable-next-line no-param-reassign
|
|
450
|
-
videoElement.srcObject = stream;
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
videoMutationObserver.observe(videoElement, { attributes: true, attributeFilter: ['srcObject'] });
|
|
454
|
-
}
|
|
455
|
-
export function calculateWidth(canvasResolution, isPortraitMobileCamera, resolution) {
|
|
456
|
-
if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) {
|
|
457
|
-
return resolution;
|
|
458
|
-
}
|
|
459
|
-
if (isPortraitMobileCamera) {
|
|
460
|
-
return CAMERA_HEIGHT;
|
|
461
|
-
}
|
|
462
|
-
return resolution;
|
|
463
|
-
}
|
|
464
|
-
export function calculateHeight(canvasResolution) {
|
|
465
|
-
if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) {
|
|
466
|
-
return canvasResolution.height;
|
|
467
|
-
}
|
|
468
|
-
return CAMERA_HEIGHT;
|
|
469
|
-
}
|
|
470
|
-
export function calculateAspectRatio(canvasResolution, isPortraitMobileCamera) {
|
|
471
|
-
if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) {
|
|
472
|
-
return 1.7777777778;
|
|
473
|
-
}
|
|
474
|
-
if (isPortraitMobileCamera) {
|
|
475
|
-
return 1;
|
|
476
|
-
}
|
|
477
|
-
return 1.7777777778;
|
|
478
|
-
}
|
|
479
|
-
export function prepareCameraResult(stream, devices, faceMode, videoElement) {
|
|
480
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
481
|
-
const track = stream.getVideoTracks()[0];
|
|
482
|
-
const capabilities = track.getCapabilities ? track.getCapabilities() : null;
|
|
483
|
-
const settings = track.getSettings();
|
|
484
|
-
printLogs('settings: ', settings);
|
|
485
|
-
if (capabilities) {
|
|
486
|
-
printLogs('capabilities: ', capabilities);
|
|
487
|
-
}
|
|
488
|
-
yield startVideo(videoElement, stream);
|
|
489
|
-
return {
|
|
490
|
-
status: true,
|
|
491
|
-
stream,
|
|
492
|
-
devices,
|
|
493
|
-
faceMode,
|
|
494
|
-
settings,
|
|
495
|
-
capabilities,
|
|
496
|
-
errorMessage: null,
|
|
497
|
-
};
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Handles device ID selection for camera devices based on platform and availability.
|
|
502
|
-
*
|
|
503
|
-
* @returns The most probable device ID string
|
|
504
|
-
*/
|
|
505
|
-
export function handleDeviceId(devices, id, isMacSafari) {
|
|
506
|
-
if (id) {
|
|
507
|
-
return id;
|
|
508
|
-
}
|
|
509
|
-
const defaultDeviceId = getDefaultCameraDeviceId();
|
|
510
|
-
const isDefaultDeviceAvailable = devices.find((device) => device.deviceId === defaultDeviceId);
|
|
511
|
-
if (isMacSafari) {
|
|
512
|
-
const externalDeviceId = getExternalDevice(devices);
|
|
513
|
-
return isDefaultDeviceAvailable ? defaultDeviceId : externalDeviceId.deviceId;
|
|
514
|
-
}
|
|
515
|
-
return isDefaultDeviceAvailable ? defaultDeviceId : devices[0].deviceId;
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Creates a MediaStream from the specified camera device for a specific camera service with optimized constraints.
|
|
519
|
-
*
|
|
520
|
-
* @returns A promise that resolves to a MediaStream from the specified camera device
|
|
521
|
-
* @throws {Error} When camera access is denied or device is not available
|
|
522
|
-
*
|
|
523
|
-
* @example
|
|
524
|
-
* ```typescript
|
|
525
|
-
* const devices = await navigator.mediaDevices.enumerateDevices();
|
|
526
|
-
* const camera = devices.find(d => d.kind === 'videoinput');
|
|
527
|
-
* const stream = await getDeviceMediaStream(camera.deviceId, 'desktop', {
|
|
528
|
-
* canvasResolution: { width: 1280, height: 720 }
|
|
529
|
-
* });
|
|
530
|
-
* ```
|
|
531
|
-
*/
|
|
532
|
-
export function getDeviceMediaStream(deviceId, type, options) {
|
|
533
|
-
var _a, _b, _c, _d;
|
|
534
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
535
|
-
const idealWidth = ((_a = options === null || options === void 0 ? void 0 : options.canvasResolution) === null || _a === void 0 ? void 0 : _a.width) || CAMERA_WIDTH;
|
|
536
|
-
const idealHeight = ((_b = options === null || options === void 0 ? void 0 : options.canvasResolution) === null || _b === void 0 ? void 0 : _b.height) || CAMERA_HEIGHT;
|
|
537
|
-
const constraints = yield generateUserMediaConstraints(type, {
|
|
538
|
-
deviceId,
|
|
539
|
-
isMacFaceTimeCamera: options === null || options === void 0 ? void 0 : options.isMacFaceTimeCamera,
|
|
540
|
-
faceMode: options === null || options === void 0 ? void 0 : options.faceMode,
|
|
541
|
-
enabledDevices: options === null || options === void 0 ? void 0 : options.enabledDevices,
|
|
542
|
-
isDocumentScan: options === null || options === void 0 ? void 0 : options.isDocumentScan,
|
|
543
|
-
isFirstPermissionRequest: options === null || options === void 0 ? void 0 : options.isFirstPermissionRequest,
|
|
544
|
-
idealResolution: {
|
|
545
|
-
width: idealWidth,
|
|
546
|
-
height: idealHeight,
|
|
547
|
-
},
|
|
548
|
-
});
|
|
549
|
-
try {
|
|
550
|
-
const stream = yield navigator.mediaDevices.getUserMedia(constraints);
|
|
551
|
-
printLogs('[getDeviceMediaStream] getUserMedia successful with constraints:', stream);
|
|
552
|
-
const streamSettings = (_d = (_c = stream.getVideoTracks()[0]) === null || _c === void 0 ? void 0 : _c.getSettings) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
553
|
-
printLogs('[getDeviceMediaStream] opened stream settings:', {
|
|
554
|
-
deviceId: streamSettings === null || streamSettings === void 0 ? void 0 : streamSettings.deviceId,
|
|
555
|
-
facingMode: streamSettings === null || streamSettings === void 0 ? void 0 : streamSettings.facingMode,
|
|
556
|
-
});
|
|
557
|
-
return stream;
|
|
558
|
-
}
|
|
559
|
-
catch (error) {
|
|
560
|
-
printLogs('[getDeviceMediaStream] getUserMedia error:', {
|
|
561
|
-
name: error === null || error === void 0 ? void 0 : error.name,
|
|
562
|
-
message: error === null || error === void 0 ? void 0 : error.message,
|
|
563
|
-
stack: error === null || error === void 0 ? void 0 : error.stack,
|
|
564
|
-
}, 'ERROR');
|
|
565
|
-
printLogs('[getDeviceMediaStream] Failed constraints:', constraints);
|
|
566
|
-
throw error;
|
|
567
|
-
}
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
* Creates platform-specific video constraints for different camera service types including
|
|
572
|
-
* desktop, Firefox, Mac Safari, and mobile devices with appropriate resolutions and settings.
|
|
573
|
-
*
|
|
574
|
-
* @returns A promise that resolves to GeneratedUserMediaConstraints object
|
|
575
|
-
*/
|
|
576
|
-
export function generateUserMediaConstraints(type, params) {
|
|
577
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
578
|
-
switch (type) {
|
|
579
|
-
case 'desktop':
|
|
580
|
-
return {
|
|
581
|
-
audio: false,
|
|
582
|
-
video: {
|
|
583
|
-
deviceId: { exact: params.deviceId },
|
|
584
|
-
width: { ideal: params.idealResolution.width },
|
|
585
|
-
height: { ideal: params.idealResolution.height },
|
|
586
|
-
aspectRatio: params.isMacFaceTimeCamera ? 1 : 1.777777778,
|
|
587
|
-
resizeMode: 'none',
|
|
588
|
-
focusMode: 'continuous',
|
|
589
|
-
facingMode: isWindowsDevice() ? 'user' : undefined,
|
|
590
|
-
},
|
|
591
|
-
};
|
|
592
|
-
case 'firefox':
|
|
593
|
-
return {
|
|
594
|
-
audio: false,
|
|
595
|
-
video: {
|
|
596
|
-
deviceId: { exact: params.deviceId },
|
|
597
|
-
width: params.idealResolution.width || CAMERA_LOW_RES_WIDTH,
|
|
598
|
-
height: params.idealResolution.height || 1080,
|
|
599
|
-
aspectRatio: 1.7777777778,
|
|
600
|
-
facingMode: params.faceMode === CameraFaceMode.back ? 'environment' : 'user',
|
|
601
|
-
focusMode: 'continuous',
|
|
602
|
-
},
|
|
603
|
-
};
|
|
604
|
-
case 'mac-safari':
|
|
605
|
-
return {
|
|
606
|
-
audio: false,
|
|
607
|
-
video: {
|
|
608
|
-
deviceId: { exact: params.deviceId },
|
|
609
|
-
width: params.idealResolution.width || CAMERA_LOW_RES_WIDTH,
|
|
610
|
-
height: params.idealResolution.height || 1080,
|
|
611
|
-
},
|
|
612
|
-
};
|
|
613
|
-
case 'mobile':
|
|
614
|
-
// update, instead of get a list of cameras again i'm using the same list already fetched on open camera function to avoid inconsistencies
|
|
615
|
-
return getMobileVideoConstraints(params.enabledDevices, params.faceMode === CameraFaceMode.back ? FacingMode.environment : FacingMode.face, params.isDocumentScan, params.idealResolution, params.deviceId, params.isFirstPermissionRequest);
|
|
616
|
-
default:
|
|
617
|
-
return {
|
|
618
|
-
audio: false,
|
|
619
|
-
video: true,
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
}
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { UAParser } from 'ua-parser-js';
|
|
11
|
+
import { CameraFaceMode, FacingMode, } from './camera.types';
|
|
12
|
+
import { PORTRAIT, LANDSCAPE, BACK_CAMERA_WORDS, CAMERA_HEIGHT, CAMERA_WIDTH, CAMERA_LOW_RES_WIDTH, MOBILE_CAMERA_RES_HEIGHT, MOBILE_CAMERA_LOW_RES_HEIGHT, } from './camera.constants';
|
|
13
|
+
import { getDefaultCameraDeviceId, printLogs } from '../../global/shared.utils';
|
|
14
|
+
export function getScreenOrientation() {
|
|
15
|
+
if (window.innerHeight > window.innerWidth) {
|
|
16
|
+
return PORTRAIT;
|
|
17
|
+
}
|
|
18
|
+
return LANDSCAPE;
|
|
19
|
+
}
|
|
20
|
+
export function getUserAgent() {
|
|
21
|
+
const userAgent = typeof window !== 'undefined' && navigator && window.navigator.userAgent;
|
|
22
|
+
return userAgent || undefined;
|
|
23
|
+
}
|
|
24
|
+
export function parseUserAgent() {
|
|
25
|
+
// This maybe evaluated in next.js Node rather than in Browser
|
|
26
|
+
if (!getUserAgent()) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const parser = new UAParser();
|
|
30
|
+
return parser.getResult();
|
|
31
|
+
}
|
|
32
|
+
export function isPortrait() {
|
|
33
|
+
return getScreenOrientation() === PORTRAIT;
|
|
34
|
+
}
|
|
35
|
+
export function isBackCameraAndPortrait(faceMode) {
|
|
36
|
+
const isBack = faceMode === FacingMode.environment;
|
|
37
|
+
return isBack && isPortrait();
|
|
38
|
+
}
|
|
39
|
+
// TODO: Refactor these `isSomethingUA` functions to be one.
|
|
40
|
+
export function isMobileUA() {
|
|
41
|
+
const result = parseUserAgent();
|
|
42
|
+
if (!result || !result.device || !result.device.type) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return ['mobile', 'tablet'].includes(result.device.type);
|
|
46
|
+
}
|
|
47
|
+
export function isFirefoxUA() {
|
|
48
|
+
var _a;
|
|
49
|
+
const result = parseUserAgent();
|
|
50
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === 'Firefox';
|
|
51
|
+
}
|
|
52
|
+
export function isSafariUA() {
|
|
53
|
+
var _a;
|
|
54
|
+
const result = parseUserAgent();
|
|
55
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === 'Safari';
|
|
56
|
+
}
|
|
57
|
+
export function isChromeUA() {
|
|
58
|
+
var _a;
|
|
59
|
+
const result = parseUserAgent();
|
|
60
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === 'Chrome';
|
|
61
|
+
}
|
|
62
|
+
export function isSamsungUA() {
|
|
63
|
+
var _a;
|
|
64
|
+
const result = parseUserAgent();
|
|
65
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.device) === null || _a === void 0 ? void 0 : _a.vendor) === 'Samsung';
|
|
66
|
+
}
|
|
67
|
+
export function isAndroid() {
|
|
68
|
+
var _a;
|
|
69
|
+
const result = parseUserAgent();
|
|
70
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'Android';
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* See https://developer.chrome.com/docs/multidevice/user-agent/#webview_user_agent
|
|
74
|
+
* This onloy detects the WebView after Android 4.4. It'd return false for older
|
|
75
|
+
* Android version.
|
|
76
|
+
*/
|
|
77
|
+
export function isAndroidWebView() {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const result = parseUserAgent();
|
|
80
|
+
// If the user-agent string contains "wv", 'ua-parser-js' will return the
|
|
81
|
+
// string "WebView" as part of its browser name.
|
|
82
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'Android' && /WebView/.test(String((_b = result === null || result === void 0 ? void 0 : result.browser) === null || _b === void 0 ? void 0 : _b.name));
|
|
83
|
+
}
|
|
84
|
+
export function isAndroid12OrAbove() {
|
|
85
|
+
return getMajorAndroidVersion() >= 12;
|
|
86
|
+
}
|
|
87
|
+
export function isIOSUA() {
|
|
88
|
+
var _a;
|
|
89
|
+
const result = parseUserAgent();
|
|
90
|
+
return ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'iOS';
|
|
91
|
+
}
|
|
92
|
+
export function getMajorAndroidVersion() {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
const result = parseUserAgent();
|
|
95
|
+
const matched = ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'Android' ? String(((_b = result === null || result === void 0 ? void 0 : result.os) === null || _b === void 0 ? void 0 : _b.version) || '').match(/^\d+/) : null;
|
|
96
|
+
return matched ? parseInt(matched[0], 10) : NaN;
|
|
97
|
+
}
|
|
98
|
+
export function getMajorSafariVersion() {
|
|
99
|
+
var _a, _b;
|
|
100
|
+
const result = parseUserAgent();
|
|
101
|
+
const name = (_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name;
|
|
102
|
+
if (name === 'Safari' || name === 'Mobile Safari') {
|
|
103
|
+
return parseInt(((_b = result === null || result === void 0 ? void 0 : result.browser) === null || _b === void 0 ? void 0 : _b.version) || '', 10);
|
|
104
|
+
}
|
|
105
|
+
return NaN;
|
|
106
|
+
}
|
|
107
|
+
export function getMajorChromeVersion() {
|
|
108
|
+
var _a, _b, _c;
|
|
109
|
+
const result = parseUserAgent();
|
|
110
|
+
return ((_b = (_a = result === null || result === void 0 ? void 0 : result.browser) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.includes('Chrome')) ? parseInt(((_c = result === null || result === void 0 ? void 0 : result.browser) === null || _c === void 0 ? void 0 : _c.version) || '', 10) : NaN;
|
|
111
|
+
}
|
|
112
|
+
export function getMajorIOSVersion() {
|
|
113
|
+
var _a, _b;
|
|
114
|
+
const result = parseUserAgent();
|
|
115
|
+
const matched = ((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.name) === 'iOS' ? String(((_b = result === null || result === void 0 ? void 0 : result.os) === null || _b === void 0 ? void 0 : _b.version) || '').match(/^\d+/) : null;
|
|
116
|
+
return matched ? parseInt(matched[0], 10) : NaN;
|
|
117
|
+
}
|
|
118
|
+
export function getMajorMinorOsVersion() {
|
|
119
|
+
var _a;
|
|
120
|
+
const result = parseUserAgent();
|
|
121
|
+
const version = String(((_a = result === null || result === void 0 ? void 0 : result.os) === null || _a === void 0 ? void 0 : _a.version) || '');
|
|
122
|
+
const matched = version.match(/(^\d+)(\.\d+)?/);
|
|
123
|
+
return (matched && matched[0]) || 'unknown';
|
|
124
|
+
}
|
|
125
|
+
export function isWindows() {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
return getPlatform() === 'desktop' && ((_b = (_a = parseUserAgent()) === null || _a === void 0 ? void 0 : _a.os) === null || _b === void 0 ? void 0 : _b.name) === 'Windows';
|
|
128
|
+
}
|
|
129
|
+
export function isMac() {
|
|
130
|
+
var _a, _b;
|
|
131
|
+
return getPlatform() === 'desktop' && ((_b = (_a = parseUserAgent()) === null || _a === void 0 ? void 0 : _a.os) === null || _b === void 0 ? void 0 : _b.name) === 'Mac OS';
|
|
132
|
+
}
|
|
133
|
+
export function isLinux() {
|
|
134
|
+
var _a;
|
|
135
|
+
const ua = parseUserAgent();
|
|
136
|
+
return ((_a = ua === null || ua === void 0 ? void 0 : ua.os) === null || _a === void 0 ? void 0 : _a.name) === 'Linux';
|
|
137
|
+
}
|
|
138
|
+
// This returns the "platform"- iphone vs android vs desktop used for reporting metrics.
|
|
139
|
+
// Do not make this into something with high cardinality- that will impact SignalFX.
|
|
140
|
+
// If you need to alter/add to these values, please make sure to update the relevant
|
|
141
|
+
// SignalFX metrics as well.
|
|
142
|
+
export function getPlatform() {
|
|
143
|
+
if (isAndroid()) {
|
|
144
|
+
return 'android';
|
|
145
|
+
}
|
|
146
|
+
if (isIOSUA()) {
|
|
147
|
+
return 'iphone';
|
|
148
|
+
}
|
|
149
|
+
return 'desktop';
|
|
150
|
+
}
|
|
151
|
+
export function isMobileDevice() {
|
|
152
|
+
return isMobileUA() || isAndroidDesktop() || isIOSDesktop();
|
|
153
|
+
}
|
|
154
|
+
// Whether it's an IOS browser requesting desktop site.
|
|
155
|
+
export function isIOSDesktop() {
|
|
156
|
+
// IOS browser => Request Desktop Site.
|
|
157
|
+
return isMac() && window.navigator.maxTouchPoints > 1;
|
|
158
|
+
}
|
|
159
|
+
export function isIOS() {
|
|
160
|
+
return isIOSUA() || isIOSDesktop();
|
|
161
|
+
}
|
|
162
|
+
export function isIOS15OrGreater() {
|
|
163
|
+
if (isIOSDesktop()) {
|
|
164
|
+
// In the past, the version of Safari has been in sync with the version of
|
|
165
|
+
// iOS. Therefore, we could use Safari's version as a proxy to determine
|
|
166
|
+
// the version of iOS. However, it's not possible to determine the iOS
|
|
167
|
+
// version using other types of browsers.
|
|
168
|
+
return getMajorSafariVersion() >= 15;
|
|
169
|
+
}
|
|
170
|
+
// iOS Mobile.
|
|
171
|
+
return getMajorIOSVersion() >= 15;
|
|
172
|
+
}
|
|
173
|
+
// Whether it's an Android browser requesting desktop site.
|
|
174
|
+
export function isAndroidDesktop() {
|
|
175
|
+
// Android browser => Request Desktop Site.
|
|
176
|
+
return isLinux() && window.navigator.maxTouchPoints > 1;
|
|
177
|
+
}
|
|
178
|
+
export const isBackCameraLabel = (label) => {
|
|
179
|
+
const lowerCase = (label === null || label === void 0 ? void 0 : label.toLowerCase()) || '';
|
|
180
|
+
return BACK_CAMERA_WORDS.some((keyword) => lowerCase === null || lowerCase === void 0 ? void 0 : lowerCase.includes(keyword));
|
|
181
|
+
};
|
|
182
|
+
export const isMobileBackCameraPortrait = ({ label, facingMode }) => {
|
|
183
|
+
const isBackCamera = isBackCameraLabel(label) || (facingMode === null || facingMode === void 0 ? void 0 : facingMode.includes(FacingMode.environment));
|
|
184
|
+
return isMobileDevice() && isBackCamera && isPortrait();
|
|
185
|
+
};
|
|
186
|
+
export function isFaceTimeCamera(label, isDocumentScan) {
|
|
187
|
+
return isMac() && label.includes('FaceTime') && isDocumentScan;
|
|
188
|
+
}
|
|
189
|
+
export const getCameraList = (backOnly) => __awaiter(void 0, void 0, void 0, function* () {
|
|
190
|
+
try {
|
|
191
|
+
if (!navigator.mediaDevices) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
let cameraList = yield navigator.mediaDevices.enumerateDevices().then((devices) => {
|
|
195
|
+
const filteredDevices = devices.filter((device) => {
|
|
196
|
+
let filteredLabels = true;
|
|
197
|
+
if (!backOnly) {
|
|
198
|
+
filteredLabels = !isBackCameraLabel(device.label);
|
|
199
|
+
}
|
|
200
|
+
return device.kind === 'videoinput' && filteredLabels;
|
|
201
|
+
});
|
|
202
|
+
return filteredDevices.map((device) => {
|
|
203
|
+
// @ts-ignore
|
|
204
|
+
if (device === null || device === void 0 ? void 0 : device.getCapabilities) {
|
|
205
|
+
// @ts-ignore
|
|
206
|
+
return Object.assign(Object.assign({}, device === null || device === void 0 ? void 0 : device.getCapabilities()), { deviceId: device.deviceId, label: device.label });
|
|
207
|
+
}
|
|
208
|
+
return { deviceId: device.deviceId, label: device.label };
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
if (isAndroid()) {
|
|
212
|
+
cameraList = cameraList.sort((a, b) => (a.label < b.label ? -1 : 1));
|
|
213
|
+
}
|
|
214
|
+
return cameraList;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
// handleException(error, 'error listing cameras');
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
export const getMobileVideoConstraints = (availableDevices, faceMode, isDocumentScan, canvasResolution, selectedDeviceId, isFirstPermissionRequest) => {
|
|
222
|
+
// Use 1.5 ratio. US DL are 1.58, passport are 1.42, so take something in the middle
|
|
223
|
+
let device = availableDevices === null || availableDevices === void 0 ? void 0 : availableDevices[0]; // get the first device by default
|
|
224
|
+
let useDirectDeviceId = false;
|
|
225
|
+
if (selectedDeviceId && availableDevices) {
|
|
226
|
+
const selectedDevice = availableDevices.find((d) => d.deviceId === selectedDeviceId);
|
|
227
|
+
if (selectedDevice) {
|
|
228
|
+
device = selectedDevice;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
useDirectDeviceId = true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (isIOS() && isDocumentScan && availableDevices && (availableDevices === null || availableDevices === void 0 ? void 0 : availableDevices.length) > 2) {
|
|
235
|
+
const ultraWideDevice = availableDevices.find(({ label }) => label.includes('Dual Wide') || label.includes('Back Triple'));
|
|
236
|
+
device = ultraWideDevice || availableDevices[0];
|
|
237
|
+
}
|
|
238
|
+
let resizeMode = 'crop-and-scale';
|
|
239
|
+
if (isMobileDevice()) {
|
|
240
|
+
// Known cases that 'crop-and-scale' does not work.
|
|
241
|
+
if (
|
|
242
|
+
// Chrome 107+ on Android shows broken video in 'crop-and-scale'.
|
|
243
|
+
(isAndroid() && getMajorChromeVersion() >= 107) ||
|
|
244
|
+
// Samsung video driver has a bug when using resizeMode
|
|
245
|
+
(isSamsungUA() && !isAndroid12OrAbove())) {
|
|
246
|
+
resizeMode = 'none';
|
|
247
|
+
}
|
|
248
|
+
// If it's the first permission request, use simpler constraints for better compatibility
|
|
249
|
+
if (isFirstPermissionRequest) {
|
|
250
|
+
printLogs('[getMobileVideoConstraints] Using simplified constraints for first permission request', {});
|
|
251
|
+
return {
|
|
252
|
+
audio: false,
|
|
253
|
+
video: {
|
|
254
|
+
facingMode: faceMode,
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
let videoWidth;
|
|
259
|
+
let videoHeight;
|
|
260
|
+
let aspectRatio;
|
|
261
|
+
if ((canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) && (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height)) {
|
|
262
|
+
// Front cameras typically don't support high resolutions, limit them to 1920x1080
|
|
263
|
+
// Back cameras can use higher resolution for document scanning quality
|
|
264
|
+
const isFrontCamera = faceMode === FacingMode.face;
|
|
265
|
+
const maxWidth = isFrontCamera ? Math.min(canvasResolution.width, 1920) : canvasResolution.width;
|
|
266
|
+
const maxHeight = isFrontCamera ? Math.min(canvasResolution.height, 1080) : canvasResolution.height;
|
|
267
|
+
// Use 'ideal' instead of exact values to allow camera to fall back to supported resolutions
|
|
268
|
+
videoWidth = { ideal: maxWidth };
|
|
269
|
+
videoHeight = { ideal: maxHeight };
|
|
270
|
+
aspectRatio = 1.7777777778;
|
|
271
|
+
}
|
|
272
|
+
else if (faceMode) {
|
|
273
|
+
videoWidth = isBackCameraAndPortrait(faceMode)
|
|
274
|
+
? // ? { min: cameraLowResHeight, max: mobileCameraResHeight }
|
|
275
|
+
{ ideal: MOBILE_CAMERA_RES_HEIGHT }
|
|
276
|
+
: { ideal: CAMERA_LOW_RES_WIDTH };
|
|
277
|
+
videoHeight = isBackCameraAndPortrait(faceMode)
|
|
278
|
+
? // ? { min: cameraLowResHeight, max: mobileCameraResHeight }
|
|
279
|
+
{ ideal: MOBILE_CAMERA_RES_HEIGHT }
|
|
280
|
+
: undefined;
|
|
281
|
+
aspectRatio = isBackCameraAndPortrait(faceMode) ? 1 : 1.7777777778;
|
|
282
|
+
}
|
|
283
|
+
const finalConstraints = {
|
|
284
|
+
audio: false,
|
|
285
|
+
video: Object.assign(Object.assign({
|
|
286
|
+
// Use facingMode environment for back camera, user for front camera also provides better compatibility
|
|
287
|
+
facingMode: faceMode, resizeMode, width: videoWidth, height: videoHeight }, ((selectedDeviceId || useDirectDeviceId) && { deviceId: selectedDeviceId })), { aspectRatio }),
|
|
288
|
+
};
|
|
289
|
+
printLogs('[getMobileVideoConstraints] finalConstraits:', finalConstraints);
|
|
290
|
+
return finalConstraints;
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
audio: false,
|
|
294
|
+
video: {
|
|
295
|
+
aspectRatio: 1.5,
|
|
296
|
+
// deviceId: deviceId ? deviceId.deviceId : undefined,
|
|
297
|
+
height: { min: MOBILE_CAMERA_LOW_RES_HEIGHT },
|
|
298
|
+
resizeMode,
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
export function scaleImageData(imageData, scaleFactor) {
|
|
303
|
+
const { width, height, data } = imageData;
|
|
304
|
+
// Create a new canvas and context for temporary scaling
|
|
305
|
+
const tempCanvas = document.createElement('canvas');
|
|
306
|
+
const tempCtx = tempCanvas.getContext('2d');
|
|
307
|
+
// Set the dimensions of the temporary canvas
|
|
308
|
+
tempCanvas.width = width * scaleFactor;
|
|
309
|
+
tempCanvas.height = height * scaleFactor;
|
|
310
|
+
// Draw the original image data onto the temporary canvas
|
|
311
|
+
tempCtx === null || tempCtx === void 0 ? void 0 : tempCtx.putImageData(imageData, 0, 0);
|
|
312
|
+
// Get the scaled image data from the temporary canvas
|
|
313
|
+
const scaledImageData = tempCtx === null || tempCtx === void 0 ? void 0 : tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
|
314
|
+
return scaledImageData;
|
|
315
|
+
}
|
|
316
|
+
export function zoomInCanvasImage(canvas, scaleFactor) {
|
|
317
|
+
// Get the current width and height of the canvas
|
|
318
|
+
const originalWidth = canvas.width;
|
|
319
|
+
const originalHeight = canvas.height;
|
|
320
|
+
// Calculate the new dimensions after applying the scale factor
|
|
321
|
+
const newWidth = Math.round(originalWidth / scaleFactor);
|
|
322
|
+
const newHeight = Math.round(originalHeight / scaleFactor);
|
|
323
|
+
// Calculate the amount of width and height to be cropped
|
|
324
|
+
const cropWidth = originalWidth - newWidth;
|
|
325
|
+
const cropHeight = originalHeight - newHeight;
|
|
326
|
+
// Create an offscreen canvas to hold the cropped image
|
|
327
|
+
const offscreenCanvas = document.createElement('canvas');
|
|
328
|
+
const offscreenCtx = offscreenCanvas.getContext('2d');
|
|
329
|
+
// Set the dimensions for the offscreen canvas
|
|
330
|
+
offscreenCanvas.width = originalWidth;
|
|
331
|
+
offscreenCanvas.height = originalHeight;
|
|
332
|
+
const centerX = originalWidth / 2;
|
|
333
|
+
const centerY = originalHeight / 2;
|
|
334
|
+
const sx = centerX - newWidth / (2 * scaleFactor);
|
|
335
|
+
const sy = centerY - newHeight / (2 * scaleFactor);
|
|
336
|
+
offscreenCtx === null || offscreenCtx === void 0 ? void 0 : offscreenCtx.drawImage(canvas, sx, sy, newWidth / scaleFactor, newHeight / scaleFactor,
|
|
337
|
+
// cropWidth / 2,
|
|
338
|
+
// cropHeight / 2, // sourceX, sourceY
|
|
339
|
+
// originalWidth - cropWidth,
|
|
340
|
+
// originalHeight - cropHeight, // sourceWidth, sourceHeight
|
|
341
|
+
0, 0, // destinationX, destinationY
|
|
342
|
+
// changing this for testing
|
|
343
|
+
newWidth, newHeight);
|
|
344
|
+
// Get the image data from the offscreen canvas
|
|
345
|
+
const imageData = offscreenCtx === null || offscreenCtx === void 0 ? void 0 : offscreenCtx.getImageData(0, 0, newWidth, newHeight);
|
|
346
|
+
// Return the image data
|
|
347
|
+
return imageData;
|
|
348
|
+
}
|
|
349
|
+
export const checkDeviceIsVirtualCamera = (deviceLabel) => {
|
|
350
|
+
const virtualCameraKeywords = ['virtual', 'obs', 'software', 'manycam'];
|
|
351
|
+
return virtualCameraKeywords.some((keyword) => deviceLabel.toLowerCase().includes(keyword));
|
|
352
|
+
};
|
|
353
|
+
export function getFilteredVideoDevices() {
|
|
354
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
355
|
+
// Retry logic for enumerateDevices to handle race conditions
|
|
356
|
+
let devices = [];
|
|
357
|
+
let attempts = 0;
|
|
358
|
+
const maxAttempts = 3;
|
|
359
|
+
while (attempts < maxAttempts) {
|
|
360
|
+
devices = yield navigator.mediaDevices.enumerateDevices();
|
|
361
|
+
const videoDevices = devices.filter((d) => d.kind === 'videoinput');
|
|
362
|
+
// Check if we have devices with labels (indicating permission was granted)
|
|
363
|
+
const hasValidDevices = videoDevices.some((d) => d.label && d.label.trim() !== '');
|
|
364
|
+
if (hasValidDevices || attempts === maxAttempts - 1) {
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
printLogs(`[getFilteredVideoDevices] Attempt ${attempts + 1}: No valid devices found, retrying...`, '');
|
|
368
|
+
yield new Promise((resolve) => setTimeout(resolve, 200));
|
|
369
|
+
attempts++;
|
|
370
|
+
}
|
|
371
|
+
// Filter devices: only videoinput with valid label and not virtual
|
|
372
|
+
const filtered = devices.filter((d) => {
|
|
373
|
+
const isVideoInput = d.kind === 'videoinput';
|
|
374
|
+
const hasLabel = d.label && d.label.trim() !== '';
|
|
375
|
+
const notVirtual = !checkDeviceIsVirtualCamera(d.label);
|
|
376
|
+
return isVideoInput && hasLabel && notVirtual;
|
|
377
|
+
});
|
|
378
|
+
printLogs(`[getFilteredVideoDevices] Found ${filtered.length} valid video devices`, '');
|
|
379
|
+
return filtered;
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
export function filterDevicesByPattern(devices, pattern) {
|
|
383
|
+
return devices.filter((d) => pattern.test(d.label));
|
|
384
|
+
}
|
|
385
|
+
export function getExternalDevice(devices) {
|
|
386
|
+
return devices.length > 1 ? devices.find((device) => !device.label.includes('FaceTime')) : devices[0];
|
|
387
|
+
}
|
|
388
|
+
export function isWindowsDevice() {
|
|
389
|
+
return ['windows', 'win16', 'win32', 'wince'].includes(navigator.platform.toUpperCase());
|
|
390
|
+
}
|
|
391
|
+
export function getMediaDeviceInfo(devices, deviceId) {
|
|
392
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
393
|
+
const mediaDevinceInfo = devices.find((device) => device.deviceId === deviceId);
|
|
394
|
+
return mediaDevinceInfo;
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* This function open camera, and returns the stream, current faceMode and the list of available media devices
|
|
399
|
+
* @category Face
|
|
400
|
+
* @param domElement id of the video tag
|
|
401
|
+
*/
|
|
402
|
+
export function getTheNextResolutionAvailable(currentResolution) {
|
|
403
|
+
printLogs(`getTheNextResolutionAvailable `, currentResolution);
|
|
404
|
+
const resolutions = [2560, 1920, 1600, 1552, 1440, 1280, 1024, 960, 800, 720, 704, 640].sort((a, b) => b - a);
|
|
405
|
+
return resolutions.find((e) => e < currentResolution) || 640;
|
|
406
|
+
}
|
|
407
|
+
export function startVideo(videoElement, stream) {
|
|
408
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
+
// Wait for the video element to exist in DOM (up to 5 seconds)
|
|
410
|
+
let element = null;
|
|
411
|
+
const maxAttempts = 50; // 50 attempts * 100ms = 5 seconds max
|
|
412
|
+
const delayMs = 100;
|
|
413
|
+
printLogs(`[startVideo] Waiting for video element "${videoElement}" to be available in DOM...`, '');
|
|
414
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
415
|
+
element = document.getElementById(videoElement);
|
|
416
|
+
if (element) {
|
|
417
|
+
printLogs(`[startVideo] Element found after ${attempt} attempts (${attempt * delayMs}ms)`, '');
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
printLogs(`[startVideo] Attempt ${attempt + 1}/${maxAttempts} - Element not found yet, waiting ${delayMs}ms...`, '');
|
|
421
|
+
yield new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
422
|
+
}
|
|
423
|
+
if (!element) {
|
|
424
|
+
const error = `[startVideo] Video element "${videoElement}" not found in DOM after ${maxAttempts * delayMs}ms`;
|
|
425
|
+
printLogs(error, '', 'ERROR');
|
|
426
|
+
throw new Error(error);
|
|
427
|
+
}
|
|
428
|
+
printLogs('[startVideo] Element found:', !!element);
|
|
429
|
+
printLogs('[startVideo] Stream tracks:', stream.getTracks().length);
|
|
430
|
+
element.srcObject = stream;
|
|
431
|
+
// Create a listener for the 'onplaying' event before calling play()
|
|
432
|
+
const playingPromise = new Promise((resolve) => {
|
|
433
|
+
element.onplaying = () => {
|
|
434
|
+
printLogs('[startVideo] Video onplaying fired', '');
|
|
435
|
+
resolve(undefined);
|
|
436
|
+
};
|
|
437
|
+
});
|
|
438
|
+
yield element.play();
|
|
439
|
+
printLogs('[startVideo] Video playing:', !element.paused);
|
|
440
|
+
// wait for the 'onplaying' event to ensure video is actually playing
|
|
441
|
+
yield playingPromise;
|
|
442
|
+
enableMutationObserver(element, stream);
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
export function enableMutationObserver(videoElement, stream) {
|
|
446
|
+
const videoMutationObserver = new MutationObserver(() => {
|
|
447
|
+
if (videoElement.srcObject !== stream) {
|
|
448
|
+
printLogs('Unauthorized video source change detected! Resetting to correct camera.', '', 'WARN');
|
|
449
|
+
// eslint-disable-next-line no-param-reassign
|
|
450
|
+
videoElement.srcObject = stream;
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
videoMutationObserver.observe(videoElement, { attributes: true, attributeFilter: ['srcObject'] });
|
|
454
|
+
}
|
|
455
|
+
export function calculateWidth(canvasResolution, isPortraitMobileCamera, resolution) {
|
|
456
|
+
if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) {
|
|
457
|
+
return resolution;
|
|
458
|
+
}
|
|
459
|
+
if (isPortraitMobileCamera) {
|
|
460
|
+
return CAMERA_HEIGHT;
|
|
461
|
+
}
|
|
462
|
+
return resolution;
|
|
463
|
+
}
|
|
464
|
+
export function calculateHeight(canvasResolution) {
|
|
465
|
+
if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) {
|
|
466
|
+
return canvasResolution.height;
|
|
467
|
+
}
|
|
468
|
+
return CAMERA_HEIGHT;
|
|
469
|
+
}
|
|
470
|
+
export function calculateAspectRatio(canvasResolution, isPortraitMobileCamera) {
|
|
471
|
+
if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) {
|
|
472
|
+
return 1.7777777778;
|
|
473
|
+
}
|
|
474
|
+
if (isPortraitMobileCamera) {
|
|
475
|
+
return 1;
|
|
476
|
+
}
|
|
477
|
+
return 1.7777777778;
|
|
478
|
+
}
|
|
479
|
+
export function prepareCameraResult(stream, devices, faceMode, videoElement) {
|
|
480
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
481
|
+
const track = stream.getVideoTracks()[0];
|
|
482
|
+
const capabilities = track.getCapabilities ? track.getCapabilities() : null;
|
|
483
|
+
const settings = track.getSettings();
|
|
484
|
+
printLogs('settings: ', settings);
|
|
485
|
+
if (capabilities) {
|
|
486
|
+
printLogs('capabilities: ', capabilities);
|
|
487
|
+
}
|
|
488
|
+
yield startVideo(videoElement, stream);
|
|
489
|
+
return {
|
|
490
|
+
status: true,
|
|
491
|
+
stream,
|
|
492
|
+
devices,
|
|
493
|
+
faceMode,
|
|
494
|
+
settings,
|
|
495
|
+
capabilities,
|
|
496
|
+
errorMessage: null,
|
|
497
|
+
};
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Handles device ID selection for camera devices based on platform and availability.
|
|
502
|
+
*
|
|
503
|
+
* @returns The most probable device ID string
|
|
504
|
+
*/
|
|
505
|
+
export function handleDeviceId(devices, id, isMacSafari) {
|
|
506
|
+
if (id) {
|
|
507
|
+
return id;
|
|
508
|
+
}
|
|
509
|
+
const defaultDeviceId = getDefaultCameraDeviceId();
|
|
510
|
+
const isDefaultDeviceAvailable = devices.find((device) => device.deviceId === defaultDeviceId);
|
|
511
|
+
if (isMacSafari) {
|
|
512
|
+
const externalDeviceId = getExternalDevice(devices);
|
|
513
|
+
return isDefaultDeviceAvailable ? defaultDeviceId : externalDeviceId.deviceId;
|
|
514
|
+
}
|
|
515
|
+
return isDefaultDeviceAvailable ? defaultDeviceId : devices[0].deviceId;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Creates a MediaStream from the specified camera device for a specific camera service with optimized constraints.
|
|
519
|
+
*
|
|
520
|
+
* @returns A promise that resolves to a MediaStream from the specified camera device
|
|
521
|
+
* @throws {Error} When camera access is denied or device is not available
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```typescript
|
|
525
|
+
* const devices = await navigator.mediaDevices.enumerateDevices();
|
|
526
|
+
* const camera = devices.find(d => d.kind === 'videoinput');
|
|
527
|
+
* const stream = await getDeviceMediaStream(camera.deviceId, 'desktop', {
|
|
528
|
+
* canvasResolution: { width: 1280, height: 720 }
|
|
529
|
+
* });
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
export function getDeviceMediaStream(deviceId, type, options) {
|
|
533
|
+
var _a, _b, _c, _d;
|
|
534
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
535
|
+
const idealWidth = ((_a = options === null || options === void 0 ? void 0 : options.canvasResolution) === null || _a === void 0 ? void 0 : _a.width) || CAMERA_WIDTH;
|
|
536
|
+
const idealHeight = ((_b = options === null || options === void 0 ? void 0 : options.canvasResolution) === null || _b === void 0 ? void 0 : _b.height) || CAMERA_HEIGHT;
|
|
537
|
+
const constraints = yield generateUserMediaConstraints(type, {
|
|
538
|
+
deviceId,
|
|
539
|
+
isMacFaceTimeCamera: options === null || options === void 0 ? void 0 : options.isMacFaceTimeCamera,
|
|
540
|
+
faceMode: options === null || options === void 0 ? void 0 : options.faceMode,
|
|
541
|
+
enabledDevices: options === null || options === void 0 ? void 0 : options.enabledDevices,
|
|
542
|
+
isDocumentScan: options === null || options === void 0 ? void 0 : options.isDocumentScan,
|
|
543
|
+
isFirstPermissionRequest: options === null || options === void 0 ? void 0 : options.isFirstPermissionRequest,
|
|
544
|
+
idealResolution: {
|
|
545
|
+
width: idealWidth,
|
|
546
|
+
height: idealHeight,
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
try {
|
|
550
|
+
const stream = yield navigator.mediaDevices.getUserMedia(constraints);
|
|
551
|
+
printLogs('[getDeviceMediaStream] getUserMedia successful with constraints:', stream);
|
|
552
|
+
const streamSettings = (_d = (_c = stream.getVideoTracks()[0]) === null || _c === void 0 ? void 0 : _c.getSettings) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
553
|
+
printLogs('[getDeviceMediaStream] opened stream settings:', {
|
|
554
|
+
deviceId: streamSettings === null || streamSettings === void 0 ? void 0 : streamSettings.deviceId,
|
|
555
|
+
facingMode: streamSettings === null || streamSettings === void 0 ? void 0 : streamSettings.facingMode,
|
|
556
|
+
});
|
|
557
|
+
return stream;
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
printLogs('[getDeviceMediaStream] getUserMedia error:', {
|
|
561
|
+
name: error === null || error === void 0 ? void 0 : error.name,
|
|
562
|
+
message: error === null || error === void 0 ? void 0 : error.message,
|
|
563
|
+
stack: error === null || error === void 0 ? void 0 : error.stack,
|
|
564
|
+
}, 'ERROR');
|
|
565
|
+
printLogs('[getDeviceMediaStream] Failed constraints:', constraints);
|
|
566
|
+
throw error;
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Creates platform-specific video constraints for different camera service types including
|
|
572
|
+
* desktop, Firefox, Mac Safari, and mobile devices with appropriate resolutions and settings.
|
|
573
|
+
*
|
|
574
|
+
* @returns A promise that resolves to GeneratedUserMediaConstraints object
|
|
575
|
+
*/
|
|
576
|
+
export function generateUserMediaConstraints(type, params) {
|
|
577
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
578
|
+
switch (type) {
|
|
579
|
+
case 'desktop':
|
|
580
|
+
return {
|
|
581
|
+
audio: false,
|
|
582
|
+
video: {
|
|
583
|
+
deviceId: { exact: params.deviceId },
|
|
584
|
+
width: { ideal: params.idealResolution.width },
|
|
585
|
+
height: { ideal: params.idealResolution.height },
|
|
586
|
+
aspectRatio: params.isMacFaceTimeCamera ? 1 : 1.777777778,
|
|
587
|
+
resizeMode: 'none',
|
|
588
|
+
focusMode: 'continuous',
|
|
589
|
+
facingMode: isWindowsDevice() ? 'user' : undefined,
|
|
590
|
+
},
|
|
591
|
+
};
|
|
592
|
+
case 'firefox':
|
|
593
|
+
return {
|
|
594
|
+
audio: false,
|
|
595
|
+
video: {
|
|
596
|
+
deviceId: { exact: params.deviceId },
|
|
597
|
+
width: params.idealResolution.width || CAMERA_LOW_RES_WIDTH,
|
|
598
|
+
height: params.idealResolution.height || 1080,
|
|
599
|
+
aspectRatio: 1.7777777778,
|
|
600
|
+
facingMode: params.faceMode === CameraFaceMode.back ? 'environment' : 'user',
|
|
601
|
+
focusMode: 'continuous',
|
|
602
|
+
},
|
|
603
|
+
};
|
|
604
|
+
case 'mac-safari':
|
|
605
|
+
return {
|
|
606
|
+
audio: false,
|
|
607
|
+
video: {
|
|
608
|
+
deviceId: { exact: params.deviceId },
|
|
609
|
+
width: params.idealResolution.width || CAMERA_LOW_RES_WIDTH,
|
|
610
|
+
height: params.idealResolution.height || 1080,
|
|
611
|
+
},
|
|
612
|
+
};
|
|
613
|
+
case 'mobile':
|
|
614
|
+
// update, instead of get a list of cameras again i'm using the same list already fetched on open camera function to avoid inconsistencies
|
|
615
|
+
return getMobileVideoConstraints(params.enabledDevices, params.faceMode === CameraFaceMode.back ? FacingMode.environment : FacingMode.face, params.isDocumentScan, params.idealResolution, params.deviceId, params.isFirstPermissionRequest);
|
|
616
|
+
default:
|
|
617
|
+
return {
|
|
618
|
+
audio: false,
|
|
619
|
+
video: true,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
624
|
//# sourceMappingURL=camera.utils.js.map
|