@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.
Files changed (216) hide show
  1. package/README.md +75 -75
  2. package/dist/apiUtils.d.ts +46 -46
  3. package/dist/apiUtils.js +922 -922
  4. package/dist/application/index.d.ts +7 -7
  5. package/dist/application/index.js +27 -27
  6. package/dist/application/modules/core/document/DocumentService.d.ts +22 -22
  7. package/dist/application/modules/core/document/DocumentService.js +254 -254
  8. package/dist/application/modules/core/document/document.constants.d.ts +15 -15
  9. package/dist/application/modules/core/document/document.constants.js +21 -21
  10. package/dist/application/modules/core/document/document.domain.d.ts +7 -7
  11. package/dist/application/modules/core/document/document.domain.js +1 -1
  12. package/dist/application/modules/core/document/document.types.d.ts +17 -17
  13. package/dist/application/modules/core/document/document.types.js +1 -1
  14. package/dist/application/modules/core/document/document.utils.d.ts +3 -3
  15. package/dist/application/modules/core/document/document.utils.js +58 -58
  16. package/dist/application/modules/core/document/index.d.ts +3 -3
  17. package/dist/application/modules/core/document/index.js +1 -1
  18. package/dist/application/modules/core/face/FaceService.d.ts +33 -33
  19. package/dist/application/modules/core/face/FaceService.js +228 -221
  20. package/dist/application/modules/core/face/FaceService.js.map +1 -1
  21. package/dist/application/modules/core/face/face.constants.d.ts +53 -53
  22. package/dist/application/modules/core/face/face.constants.js +53 -53
  23. package/dist/application/modules/core/face/face.domain.d.ts +10 -10
  24. package/dist/application/modules/core/face/face.domain.js +1 -1
  25. package/dist/application/modules/core/face/face.types.d.ts +41 -38
  26. package/dist/application/modules/core/face/face.types.js +1 -1
  27. package/dist/application/modules/core/face/face.utils.d.ts +15 -15
  28. package/dist/application/modules/core/face/face.utils.js +101 -101
  29. package/dist/application/modules/core/face/index.d.ts +3 -3
  30. package/dist/application/modules/core/face/index.js +1 -1
  31. package/dist/application/modules/global/shared.constants.d.ts +2 -2
  32. package/dist/application/modules/global/shared.constants.js +2 -2
  33. package/dist/application/modules/global/shared.utils.d.ts +25 -25
  34. package/dist/application/modules/global/shared.utils.js +100 -100
  35. package/dist/application/modules/global/shared.utils.js.map +1 -1
  36. package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.d.ts +9 -0
  37. package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js +32 -0
  38. package/dist/application/modules/internal/feature-flag/LDFeatureFlagService.js.map +1 -0
  39. package/dist/application/modules/internal/feature-flag/feature-flag-init.d.ts +11 -0
  40. package/dist/application/modules/internal/feature-flag/feature-flag-init.js +24 -0
  41. package/dist/application/modules/internal/feature-flag/feature-flag-init.js.map +1 -0
  42. package/dist/application/modules/internal/feature-flag/feature-flag.domain.d.ts +10 -0
  43. package/dist/application/modules/internal/feature-flag/feature-flag.domain.js +7 -0
  44. package/dist/application/modules/internal/feature-flag/feature-flag.domain.js.map +1 -0
  45. package/dist/application/modules/internal/feature-flag/featureFlagInit.d.ts +11 -0
  46. package/dist/application/modules/internal/feature-flag/featureFlagInit.js +44 -0
  47. package/dist/application/modules/internal/feature-flag/featureFlagInit.js.map +1 -0
  48. package/dist/application/modules/internal/feature-flag/index.d.ts +2 -0
  49. package/dist/application/modules/internal/feature-flag/index.js +3 -0
  50. package/dist/application/modules/internal/feature-flag/index.js.map +1 -0
  51. package/dist/application/modules/internal/shared/index.d.ts +2 -0
  52. package/dist/application/modules/internal/shared/index.js +3 -0
  53. package/dist/application/modules/internal/shared/index.js.map +1 -0
  54. package/dist/application/modules/internal/shared/shared.constants.d.ts +2 -0
  55. package/dist/application/modules/internal/shared/shared.constants.js +3 -0
  56. package/dist/application/modules/internal/shared/shared.constants.js.map +1 -0
  57. package/dist/application/modules/internal/shared/shared.utils.d.ts +44 -0
  58. package/dist/application/modules/internal/shared/shared.utils.js +204 -0
  59. package/dist/application/modules/internal/shared/shared.utils.js.map +1 -0
  60. package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.d.ts +28 -0
  61. package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js +380 -0
  62. package/dist/application/modules/internal/wasm-orchestrator/WasmOrchestratorService.js.map +1 -0
  63. package/dist/application/modules/internal/wasm-orchestrator/index.d.ts +6 -0
  64. package/dist/application/modules/internal/wasm-orchestrator/index.js +9 -0
  65. package/dist/application/modules/internal/wasm-orchestrator/index.js.map +1 -0
  66. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.constants.d.ts +28 -0
  67. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.constants.js +35 -0
  68. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.constants.js.map +1 -0
  69. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.domain.d.ts +51 -0
  70. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.domain.js +2 -0
  71. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.domain.js.map +1 -0
  72. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.d.ts +142 -0
  73. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.js +2 -0
  74. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.types.js.map +1 -0
  75. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.d.ts +86 -0
  76. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js +201 -0
  77. package/dist/application/modules/internal/wasm-orchestrator/wasm-orchestrator.utils.js.map +1 -0
  78. package/dist/application/modules/support/camera/CameraServiceFactory.d.ts +10 -10
  79. package/dist/application/modules/support/camera/CameraServiceFactory.js +33 -33
  80. package/dist/application/modules/support/camera/CameraServiceFactory.js.map +1 -1
  81. package/dist/application/modules/support/camera/camera.constants.d.ts +9 -9
  82. package/dist/application/modules/support/camera/camera.constants.js +48 -48
  83. package/dist/application/modules/support/camera/camera.domain.d.ts +15 -15
  84. package/dist/application/modules/support/camera/camera.domain.js +1 -1
  85. package/dist/application/modules/support/camera/camera.types.d.ts +42 -42
  86. package/dist/application/modules/support/camera/camera.types.js +10 -10
  87. package/dist/application/modules/support/camera/camera.utils.d.ts +157 -157
  88. package/dist/application/modules/support/camera/camera.utils.js +623 -623
  89. package/dist/application/modules/support/camera/index.d.ts +24 -24
  90. package/dist/application/modules/support/camera/index.js +27 -27
  91. package/dist/application/modules/support/camera/services/BaseCameraService.d.ts +41 -41
  92. package/dist/application/modules/support/camera/services/BaseCameraService.js +278 -278
  93. package/dist/application/modules/support/camera/services/DesktopCameraService.d.ts +5 -5
  94. package/dist/application/modules/support/camera/services/DesktopCameraService.js +46 -46
  95. package/dist/application/modules/support/camera/services/FirefoxCameraService.d.ts +5 -5
  96. package/dist/application/modules/support/camera/services/FirefoxCameraService.js +46 -46
  97. package/dist/application/modules/support/camera/services/MacSafariCameraService.d.ts +5 -5
  98. package/dist/application/modules/support/camera/services/MacSafariCameraService.js +47 -47
  99. package/dist/application/modules/support/camera/services/MobileCameraService.d.ts +5 -5
  100. package/dist/application/modules/support/camera/services/MobileCameraService.js +133 -133
  101. package/dist/application/modules/support/engine/EngineService.d.ts +15 -0
  102. package/dist/application/modules/support/engine/EngineService.js +106 -0
  103. package/dist/application/modules/support/engine/EngineService.js.map +1 -0
  104. package/dist/application/modules/support/engine/engine.constants.d.ts +33 -0
  105. package/dist/application/modules/support/engine/engine.constants.js +35 -0
  106. package/dist/application/modules/support/engine/engine.constants.js.map +1 -0
  107. package/dist/application/modules/support/engine/engine.domain.d.ts +23 -0
  108. package/dist/application/modules/support/engine/engine.domain.js +2 -0
  109. package/dist/application/modules/support/engine/engine.domain.js.map +1 -0
  110. package/dist/application/modules/support/engine/engine.types.d.ts +32 -0
  111. package/dist/application/modules/support/engine/engine.types.js +2 -0
  112. package/dist/application/modules/support/engine/engine.types.js.map +1 -0
  113. package/dist/application/modules/support/engine/engine.utils.d.ts +65 -0
  114. package/dist/application/modules/support/engine/engine.utils.js +135 -0
  115. package/dist/application/modules/support/engine/engine.utils.js.map +1 -0
  116. package/dist/application/modules/support/engine/index.d.ts +3 -0
  117. package/dist/application/modules/support/engine/index.js +2 -0
  118. package/dist/application/modules/support/engine/index.js.map +1 -0
  119. package/dist/application/modules/support/permissions/PermissionsService.d.ts +55 -55
  120. package/dist/application/modules/support/permissions/PermissionsService.js +183 -183
  121. package/dist/application/modules/support/permissions/index.d.ts +4 -4
  122. package/dist/application/modules/support/permissions/index.js +2 -2
  123. package/dist/application/modules/support/permissions/permission.utils.d.ts +6 -6
  124. package/dist/application/modules/support/permissions/permission.utils.js +33 -33
  125. package/dist/application/modules/support/permissions/permissions.domain.d.ts +6 -6
  126. package/dist/application/modules/support/permissions/permissions.domain.js +1 -1
  127. package/dist/application/modules/support/permissions/permissions.types.d.ts +9 -9
  128. package/dist/application/modules/support/permissions/permissions.types.js +1 -1
  129. package/dist/application/modules/support/wasm/WasmService.d.ts +25 -25
  130. package/dist/application/modules/support/wasm/WasmService.js +156 -155
  131. package/dist/application/modules/support/wasm/WasmService.js.map +1 -1
  132. package/dist/application/modules/support/wasm/index.d.ts +6 -6
  133. package/dist/application/modules/support/wasm/index.js +8 -8
  134. package/dist/application/modules/support/wasm/wasm.constants.d.ts +78 -78
  135. package/dist/application/modules/support/wasm/wasm.constants.js +86 -86
  136. package/dist/application/modules/support/wasm/wasm.domain.d.ts +52 -52
  137. package/dist/application/modules/support/wasm/wasm.domain.js +1 -1
  138. package/dist/application/modules/support/wasm/wasm.types.d.ts +119 -118
  139. package/dist/application/modules/support/wasm/wasm.types.js +1 -1
  140. package/dist/application/modules/support/wasm/wasm.utils.d.ts +88 -88
  141. package/dist/application/modules/support/wasm/wasm.utils.js +243 -243
  142. package/dist/application/modules/support/wasm-orchestrator/WasmOrchestratorService.d.ts +28 -0
  143. package/dist/application/modules/support/wasm-orchestrator/WasmOrchestratorService.js +324 -0
  144. package/dist/application/modules/support/wasm-orchestrator/WasmOrchestratorService.js.map +1 -0
  145. package/dist/application/modules/support/wasm-orchestrator/index.d.ts +6 -0
  146. package/dist/application/modules/support/wasm-orchestrator/index.js +9 -0
  147. package/dist/application/modules/support/wasm-orchestrator/index.js.map +1 -0
  148. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.constants.d.ts +36 -0
  149. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.constants.js +44 -0
  150. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.constants.js.map +1 -0
  151. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.domain.d.ts +47 -0
  152. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.domain.js +2 -0
  153. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.domain.js.map +1 -0
  154. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.types.d.ts +136 -0
  155. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.types.js +2 -0
  156. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.types.js.map +1 -0
  157. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.utils.d.ts +91 -0
  158. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.utils.js +250 -0
  159. package/dist/application/modules/support/wasm-orchestrator/wasm-orchestrator.utils.js.map +1 -0
  160. package/dist/application/workers/index.d.ts +42 -42
  161. package/dist/application/workers/index.js +8 -8
  162. package/dist/application/workers/wasm/WasmWorkerService.d.ts +66 -0
  163. package/dist/application/workers/wasm/WasmWorkerService.js +801 -0
  164. package/dist/application/workers/wasm/WasmWorkerService.js.map +1 -0
  165. package/dist/application/workers/wasm/index.d.ts +4 -0
  166. package/dist/application/workers/wasm/index.js +9 -0
  167. package/dist/application/workers/wasm/index.js.map +1 -0
  168. package/dist/application/workers/wasm/wasm-worker.constants.d.ts +5 -0
  169. package/dist/application/workers/wasm/wasm-worker.constants.js +6 -0
  170. package/dist/application/workers/wasm/wasm-worker.constants.js.map +1 -0
  171. package/dist/application/workers/wasm/wasm-worker.domain.d.ts +99 -0
  172. package/dist/application/workers/wasm/wasm-worker.domain.js +2 -0
  173. package/dist/application/workers/wasm/wasm-worker.domain.js.map +1 -0
  174. package/dist/application/workers/wasm/wasm-worker.types.d.ts +88 -0
  175. package/dist/application/workers/wasm/wasm-worker.types.js +2 -0
  176. package/dist/application/workers/wasm/wasm-worker.types.js.map +1 -0
  177. package/dist/application/workers/wasm/wasm-worker.utils.d.ts +10 -0
  178. package/dist/application/workers/wasm/wasm-worker.utils.js +130 -0
  179. package/dist/application/workers/wasm/wasm-worker.utils.js.map +1 -0
  180. package/dist/buildConfig.d.ts +3 -0
  181. package/dist/buildConfig.js +7 -0
  182. package/dist/buildConfig.js.map +1 -0
  183. package/dist/cameraUtils.d.ts +77 -77
  184. package/dist/cameraUtils.js +361 -361
  185. package/dist/constants.d.ts +9 -9
  186. package/dist/constants.js +13 -13
  187. package/dist/createCallback.d.ts +56 -56
  188. package/dist/createCallback.js +332 -331
  189. package/dist/createCallback.js.map +1 -1
  190. package/dist/dbUtils.d.ts +14 -14
  191. package/dist/dbUtils.js +148 -148
  192. package/dist/envUtils.d.ts +4 -4
  193. package/dist/envUtils.js +16 -16
  194. package/dist/faceModule.d.ts +196 -196
  195. package/dist/faceModule.js +978 -978
  196. package/dist/featureFlagInit.d.ts +11 -0
  197. package/dist/featureFlagInit.js +44 -0
  198. package/dist/featureFlagInit.js.map +1 -0
  199. package/dist/index.d.ts +38 -38
  200. package/dist/index.js +82 -82
  201. package/dist/main.d.ts +30 -30
  202. package/dist/main.js +84 -84
  203. package/dist/types.d.ts +139 -139
  204. package/dist/types.js +77 -77
  205. package/dist/utils.d.ts +84 -84
  206. package/dist/utils.js +580 -580
  207. package/package.json +102 -102
  208. package/wasm/ultra/nosimd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.js +18 -18
  209. package/wasm/ultra/nosimd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.wasm +0 -0
  210. package/wasm/ultra/nosimd/version.json +2 -2
  211. package/wasm/ultra/simd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.js +18 -18
  212. package/wasm/ultra/simd/{25.11.13-1357710 → 26.01.08-1300478}/privid_fhe_uber.wasm +0 -0
  213. package/wasm/ultra/simd/version.json +2 -2
  214. package/workers/comlink.min.js +7 -7
  215. package/workers/comlink.min.js.map +1 -1
  216. 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