@authme/util 2.8.29 → 2.8.30

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 (3) hide show
  1. package/index.cjs +134 -14
  2. package/index.js +134 -14
  3. package/package.json +1 -1
package/index.cjs CHANGED
@@ -27,6 +27,7 @@ var fileSaver = require('file-saver');
27
27
  var JSZip = require('jszip');
28
28
  require('core-js/modules/es.parse-int.js');
29
29
  var Lottie = require('lottie-web');
30
+ require('core-js/modules/es.number.to-fixed.js');
30
31
  require('core-js/modules/es.array.sort.js');
31
32
  require('core-js/modules/es.string.trim.js');
32
33
  require('core-js/modules/es.string.starts-with.js');
@@ -1447,6 +1448,42 @@ const videoConstraintsFactory = (isPC, facingMode) => {
1447
1448
  }
1448
1449
  };
1449
1450
  };
1451
+ /**
1452
+ * 等待camera完全就緒
1453
+ * 用於解決外接camera初始化延遲問題
1454
+ * @param videoTrack - MediaStreamTrack 實例
1455
+ * @param maxWaitMs - 最大等待時間(毫秒)
1456
+ * @returns Promise<boolean> - true表示camera已就緒,false表示超時
1457
+ */
1458
+ function waitForCameraReady(videoTrack, maxWaitMs = 100) {
1459
+ var _a, _b, _c, _d;
1460
+ return __awaiter(this, void 0, void 0, function* () {
1461
+ const startTime = Date.now();
1462
+ const checkInterval = 50; // 每50ms檢查一次
1463
+ while (Date.now() - startTime < maxWaitMs) {
1464
+ const _settings = videoTrack.getSettings();
1465
+ const capabilities = (_a = videoTrack.getCapabilities) === null || _a === void 0 ? void 0 : _a.call(videoTrack);
1466
+ // 檢查camera是否已提供完整資訊
1467
+ // 1. 必須有基本的寬高設定
1468
+ // 2. 如果支援 getCapabilities,確認有最大解析度資訊
1469
+ const hasBasicSettings = _settings.width && _settings.height;
1470
+ const hasCapabilities = !capabilities || ((_b = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _b === void 0 ? void 0 : _b.max) && ((_c = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _c === void 0 ? void 0 : _c.max);
1471
+ if (hasBasicSettings && hasCapabilities) {
1472
+ const elapsedTime = Date.now() - startTime;
1473
+ console.log(`✅ Camera就緒 (耗時: ${elapsedTime}ms, 解析度: ${_settings.width}x${_settings.height})`);
1474
+ return true;
1475
+ }
1476
+ yield new Promise(resolve => setTimeout(resolve, checkInterval));
1477
+ }
1478
+ const settings = videoTrack.getSettings();
1479
+ console.warn(`⚠️ Camera未在時限內完全就緒 (${maxWaitMs}ms), 當前狀態:`, {
1480
+ width: settings.width,
1481
+ height: settings.height,
1482
+ hasCapabilities: !!((_d = videoTrack.getCapabilities) === null || _d === void 0 ? void 0 : _d.call(videoTrack))
1483
+ });
1484
+ return false;
1485
+ });
1486
+ }
1450
1487
  function inferFacingModeFromLabel(label) {
1451
1488
  const pattern = /rear|back|rück|arrière|trasera|trás|traseira|posteriore|后|後|背|задней|الخلفية|후|arka|achterzijde|หลัง|baksidan|bagside|sau|bak|tylny|takakamera|belakang|אחורית|πίσω|spate|hátsó|zadní|darrere|zadná|задня|stražnja|belakang|बैक/i;
1452
1489
  if (pattern.test(label !== null && label !== void 0 ? label : '')) {
@@ -1501,7 +1538,9 @@ function arrayFromAsync(asyncIterable) {
1501
1538
  });
1502
1539
  }
1503
1540
  function switchCamera(deviceId, video) {
1541
+ var _a, _b;
1504
1542
  return __awaiter(this, void 0, void 0, function* () {
1543
+ const startTime = performance.now();
1505
1544
  try {
1506
1545
  if (stream) {
1507
1546
  stream.getTracks().forEach(track => track.stop());
@@ -1515,13 +1554,15 @@ function switchCamera(deviceId, video) {
1515
1554
  };
1516
1555
  const constraint = localStorage.getItem('camera_constraint');
1517
1556
  stream = yield navigator.mediaDevices.getUserMedia(basicConstraints);
1518
- // 第二階段:如果沒有設定跳過約束,嘗試使用 applyConstraints 提升解析度
1557
+ // 第二階段:等待就緒策略 + 漸進式重試提升解析度
1519
1558
  if (!constraint && stream) {
1520
1559
  const videoTrack = stream.getVideoTracks()[0];
1521
1560
  if (videoTrack && videoTrack.applyConstraints) {
1522
- try {
1523
- // 嘗試應用更高解析度(使用 ideal 而非 min/max)
1524
- yield videoTrack.applyConstraints({
1561
+ // 🆕 策略 1: 等待camera完全就緒(特別針對外接camera)
1562
+ const isReady = yield waitForCameraReady(videoTrack, 2000);
1563
+ if (isReady) {
1564
+ // 🆕 策略 2: 漸進式重試邏輯
1565
+ const targetConstraints = {
1525
1566
  width: {
1526
1567
  ideal: 1920,
1527
1568
  max: 3840
@@ -1530,10 +1571,60 @@ function switchCamera(deviceId, video) {
1530
1571
  ideal: 1080,
1531
1572
  max: 2160
1532
1573
  }
1533
- });
1534
- } catch (error) {
1535
- // 失敗時保持原有流,不會中斷相機
1574
+ };
1575
+ const maxRetries = 3;
1576
+ const delays = [0, 100, 300]; // 第一次立即嘗試,後續間隔遞增
1577
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
1578
+ try {
1579
+ if (delays[attempt] > 0) {
1580
+ yield new Promise(resolve => setTimeout(resolve, delays[attempt]));
1581
+ }
1582
+ yield videoTrack.applyConstraints(targetConstraints);
1583
+ const settings = videoTrack.getSettings();
1584
+ console.log(`✅ 解析度提升成功 (嘗試 ${attempt + 1}/${maxRetries})`, {
1585
+ resolution: `${settings.width}x${settings.height}`,
1586
+ deviceLabel: videoTrack.label
1587
+ });
1588
+ break; // 成功後跳出
1589
+ } catch (error) {
1590
+ if (attempt === maxRetries - 1) {
1591
+ // 最後一次嘗試失敗,記錄警告但不影響功能
1592
+ const settings = videoTrack.getSettings();
1593
+ console.warn(`⚠️ 無法提升解析度,使用基本設定 (${settings.width}x${settings.height})`, error);
1594
+ } else {
1595
+ console.log(`⏳ 解析度提升嘗試 ${attempt + 1} 失敗,準備重試...`);
1596
+ }
1597
+ }
1598
+ }
1599
+ } else {
1600
+ // Camera未完全就緒,但仍嘗試套用約束
1601
+ console.warn('⚠️ Camera未完全就緒,嘗試套用解析度約束...');
1602
+ try {
1603
+ yield videoTrack.applyConstraints({
1604
+ width: {
1605
+ ideal: 1920,
1606
+ max: 3840
1607
+ },
1608
+ height: {
1609
+ ideal: 1080,
1610
+ max: 2160
1611
+ }
1612
+ });
1613
+ } catch (error) {
1614
+ console.warn('⚠️ 解析度提升失敗,使用預設解析度', error);
1615
+ }
1536
1616
  }
1617
+ // 🆕 記錄最終解析度資訊
1618
+ const finalSettings = videoTrack.getSettings();
1619
+ const initTime = (performance.now() - startTime).toFixed(2);
1620
+ console.log('📹 Camera初始化完成', {
1621
+ deviceId,
1622
+ deviceLabel: videoTrack.label,
1623
+ resolution: `${finalSettings.width}x${finalSettings.height}`,
1624
+ frameRate: finalSettings.frameRate,
1625
+ facingMode: finalSettings.facingMode,
1626
+ initTime: `${initTime}ms`
1627
+ });
1537
1628
  }
1538
1629
  }
1539
1630
  // try {
@@ -1579,12 +1670,28 @@ function switchCamera(deviceId, video) {
1579
1670
  video.srcObject = stream;
1580
1671
  }, 10);
1581
1672
  } catch (e) {
1673
+ // 🆕 增強錯誤日誌
1674
+ const initTime = (performance.now() - startTime).toFixed(2);
1675
+ console.error('❌ Camera切換失敗', {
1676
+ deviceId,
1677
+ error: e,
1678
+ errorName: e === null || e === void 0 ? void 0 : e.name,
1679
+ errorMessage: e === null || e === void 0 ? void 0 : e.message,
1680
+ initTime: `${initTime}ms`,
1681
+ streamExists: !!stream,
1682
+ trackCount: (_b = (_a = stream === null || stream === void 0 ? void 0 : stream.getTracks()) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0
1683
+ });
1582
1684
  throw new AuthmeError(exports.ErrorCode.CAMERA_NOT_SUPPORT, e);
1583
1685
  }
1584
1686
  });
1585
1687
  }
1586
1688
  function _requestCamera(video, facingMode) {
1689
+ var _a, _b, _c, _d, _e, _f;
1587
1690
  return __awaiter(this, void 0, void 0, function* () {
1691
+ const requestStartTime = performance.now();
1692
+ console.log('🎬 開始camera請求流程', {
1693
+ facingMode
1694
+ });
1588
1695
  if (!('mediaDevices' in navigator)) {
1589
1696
  throw BROWSER_CAMERA_ERRORS.NOT_SUPPORT;
1590
1697
  }
@@ -1607,7 +1714,7 @@ function _requestCamera(video, facingMode) {
1607
1714
  // 輪詢取得攝影機 解析度等資訊
1608
1715
  const videoDevices = (yield navigator.mediaDevices.enumerateDevices()).filter(device => device.kind === 'videoinput');
1609
1716
  const deviceMetas = yield arrayFromAsync(asyncMap(device => __awaiter(this, void 0, void 0, function* () {
1610
- var _a, _b, _c, _d;
1717
+ var _g, _h, _j, _k;
1611
1718
  const stream = yield navigator.mediaDevices.getUserMedia({
1612
1719
  video: {
1613
1720
  deviceId: {
@@ -1615,10 +1722,10 @@ function _requestCamera(video, facingMode) {
1615
1722
  }
1616
1723
  }
1617
1724
  });
1618
- const track = (_a = stream.getVideoTracks()) === null || _a === void 0 ? void 0 : _a[0];
1619
- const capabilities = ((_b = track === null || track === void 0 ? void 0 : track.getCapabilities) !== null && _b !== void 0 ? _b : () => undefined).bind(track)(); // firefox 沒有 getCapabilities 可以用。
1620
- const widthMax = (_c = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _c === void 0 ? void 0 : _c.max;
1621
- const heightMax = (_d = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _d === void 0 ? void 0 : _d.max;
1725
+ const track = (_g = stream.getVideoTracks()) === null || _g === void 0 ? void 0 : _g[0];
1726
+ const capabilities = ((_h = track === null || track === void 0 ? void 0 : track.getCapabilities) !== null && _h !== void 0 ? _h : () => undefined).bind(track)(); // firefox 沒有 getCapabilities 可以用。
1727
+ const widthMax = (_j = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _j === void 0 ? void 0 : _j.max;
1728
+ const heightMax = (_k = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _k === void 0 ? void 0 : _k.max;
1622
1729
  const resolution = widthMax && heightMax ? widthMax * heightMax : 0;
1623
1730
  const facingModeFromLabel = inferFacingModeFromLabel(device === null || device === void 0 ? void 0 : device.label);
1624
1731
  const facingModeFromapabilities = inferFacingModeFromCapabilities(capabilities);
@@ -1678,6 +1785,19 @@ function _requestCamera(video, facingMode) {
1678
1785
  stream.getTracks().forEach(track => track.stop());
1679
1786
  }
1680
1787
  yield switchCamera(deviceId, video);
1788
+ // 🆕 記錄整個請求流程的總結資訊
1789
+ const totalTime = (performance.now() - requestStartTime).toFixed(2);
1790
+ console.log('🎉 Camera請求流程完成', {
1791
+ totalTime: `${totalTime}ms`,
1792
+ selectedDevice: {
1793
+ deviceId,
1794
+ label: firstDevice.device.label,
1795
+ facingMode: firstDevice.meta.facingMode,
1796
+ resolution: `${(_c = (_b = (_a = firstDevice.meta.capabilities) === null || _a === void 0 ? void 0 : _a.width) === null || _b === void 0 ? void 0 : _b.max) !== null && _c !== void 0 ? _c : 0}x${(_f = (_e = (_d = firstDevice.meta.capabilities) === null || _d === void 0 ? void 0 : _d.height) === null || _e === void 0 ? void 0 : _e.max) !== null && _f !== void 0 ? _f : 0}`
1797
+ },
1798
+ availableDevices: deviceMetas.length,
1799
+ isSamsung
1800
+ });
1681
1801
  return {
1682
1802
  facingMode: firstDevice.meta.facingMode,
1683
1803
  deviceMetas: deviceMetas
@@ -3243,8 +3363,8 @@ const themeConfigDefault = {
3243
3363
  };
3244
3364
 
3245
3365
  var name = "authme/sdk";
3246
- var version$1 = "2.8.29";
3247
- var date = "2025-10-30T04:42:12+0000";
3366
+ var version$1 = "2.8.30";
3367
+ var date = "2025-10-30T10:27:17+0000";
3248
3368
  var packageInfo = {
3249
3369
  name: name,
3250
3370
  version: version$1,
package/index.js CHANGED
@@ -23,6 +23,7 @@ import { saveAs } from 'file-saver';
23
23
  import JSZip from 'jszip';
24
24
  import 'core-js/modules/es.parse-int.js';
25
25
  import Lottie from 'lottie-web';
26
+ import 'core-js/modules/es.number.to-fixed.js';
26
27
  import 'core-js/modules/es.array.sort.js';
27
28
  import 'core-js/modules/es.string.trim.js';
28
29
  import 'core-js/modules/es.string.starts-with.js';
@@ -1437,6 +1438,42 @@ const videoConstraintsFactory = (isPC, facingMode) => {
1437
1438
  }
1438
1439
  };
1439
1440
  };
1441
+ /**
1442
+ * 等待camera完全就緒
1443
+ * 用於解決外接camera初始化延遲問題
1444
+ * @param videoTrack - MediaStreamTrack 實例
1445
+ * @param maxWaitMs - 最大等待時間(毫秒)
1446
+ * @returns Promise<boolean> - true表示camera已就緒,false表示超時
1447
+ */
1448
+ function waitForCameraReady(videoTrack, maxWaitMs = 100) {
1449
+ var _a, _b, _c, _d;
1450
+ return __awaiter(this, void 0, void 0, function* () {
1451
+ const startTime = Date.now();
1452
+ const checkInterval = 50; // 每50ms檢查一次
1453
+ while (Date.now() - startTime < maxWaitMs) {
1454
+ const _settings = videoTrack.getSettings();
1455
+ const capabilities = (_a = videoTrack.getCapabilities) === null || _a === void 0 ? void 0 : _a.call(videoTrack);
1456
+ // 檢查camera是否已提供完整資訊
1457
+ // 1. 必須有基本的寬高設定
1458
+ // 2. 如果支援 getCapabilities,確認有最大解析度資訊
1459
+ const hasBasicSettings = _settings.width && _settings.height;
1460
+ const hasCapabilities = !capabilities || ((_b = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _b === void 0 ? void 0 : _b.max) && ((_c = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _c === void 0 ? void 0 : _c.max);
1461
+ if (hasBasicSettings && hasCapabilities) {
1462
+ const elapsedTime = Date.now() - startTime;
1463
+ console.log(`✅ Camera就緒 (耗時: ${elapsedTime}ms, 解析度: ${_settings.width}x${_settings.height})`);
1464
+ return true;
1465
+ }
1466
+ yield new Promise(resolve => setTimeout(resolve, checkInterval));
1467
+ }
1468
+ const settings = videoTrack.getSettings();
1469
+ console.warn(`⚠️ Camera未在時限內完全就緒 (${maxWaitMs}ms), 當前狀態:`, {
1470
+ width: settings.width,
1471
+ height: settings.height,
1472
+ hasCapabilities: !!((_d = videoTrack.getCapabilities) === null || _d === void 0 ? void 0 : _d.call(videoTrack))
1473
+ });
1474
+ return false;
1475
+ });
1476
+ }
1440
1477
  function inferFacingModeFromLabel(label) {
1441
1478
  const pattern = /rear|back|rück|arrière|trasera|trás|traseira|posteriore|后|後|背|задней|الخلفية|후|arka|achterzijde|หลัง|baksidan|bagside|sau|bak|tylny|takakamera|belakang|אחורית|πίσω|spate|hátsó|zadní|darrere|zadná|задня|stražnja|belakang|बैक/i;
1442
1479
  if (pattern.test(label !== null && label !== void 0 ? label : '')) {
@@ -1491,7 +1528,9 @@ function arrayFromAsync(asyncIterable) {
1491
1528
  });
1492
1529
  }
1493
1530
  function switchCamera(deviceId, video) {
1531
+ var _a, _b;
1494
1532
  return __awaiter(this, void 0, void 0, function* () {
1533
+ const startTime = performance.now();
1495
1534
  try {
1496
1535
  if (stream) {
1497
1536
  stream.getTracks().forEach(track => track.stop());
@@ -1505,13 +1544,15 @@ function switchCamera(deviceId, video) {
1505
1544
  };
1506
1545
  const constraint = localStorage.getItem('camera_constraint');
1507
1546
  stream = yield navigator.mediaDevices.getUserMedia(basicConstraints);
1508
- // 第二階段:如果沒有設定跳過約束,嘗試使用 applyConstraints 提升解析度
1547
+ // 第二階段:等待就緒策略 + 漸進式重試提升解析度
1509
1548
  if (!constraint && stream) {
1510
1549
  const videoTrack = stream.getVideoTracks()[0];
1511
1550
  if (videoTrack && videoTrack.applyConstraints) {
1512
- try {
1513
- // 嘗試應用更高解析度(使用 ideal 而非 min/max)
1514
- yield videoTrack.applyConstraints({
1551
+ // 🆕 策略 1: 等待camera完全就緒(特別針對外接camera)
1552
+ const isReady = yield waitForCameraReady(videoTrack, 2000);
1553
+ if (isReady) {
1554
+ // 🆕 策略 2: 漸進式重試邏輯
1555
+ const targetConstraints = {
1515
1556
  width: {
1516
1557
  ideal: 1920,
1517
1558
  max: 3840
@@ -1520,10 +1561,60 @@ function switchCamera(deviceId, video) {
1520
1561
  ideal: 1080,
1521
1562
  max: 2160
1522
1563
  }
1523
- });
1524
- } catch (error) {
1525
- // 失敗時保持原有流,不會中斷相機
1564
+ };
1565
+ const maxRetries = 3;
1566
+ const delays = [0, 100, 300]; // 第一次立即嘗試,後續間隔遞增
1567
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
1568
+ try {
1569
+ if (delays[attempt] > 0) {
1570
+ yield new Promise(resolve => setTimeout(resolve, delays[attempt]));
1571
+ }
1572
+ yield videoTrack.applyConstraints(targetConstraints);
1573
+ const settings = videoTrack.getSettings();
1574
+ console.log(`✅ 解析度提升成功 (嘗試 ${attempt + 1}/${maxRetries})`, {
1575
+ resolution: `${settings.width}x${settings.height}`,
1576
+ deviceLabel: videoTrack.label
1577
+ });
1578
+ break; // 成功後跳出
1579
+ } catch (error) {
1580
+ if (attempt === maxRetries - 1) {
1581
+ // 最後一次嘗試失敗,記錄警告但不影響功能
1582
+ const settings = videoTrack.getSettings();
1583
+ console.warn(`⚠️ 無法提升解析度,使用基本設定 (${settings.width}x${settings.height})`, error);
1584
+ } else {
1585
+ console.log(`⏳ 解析度提升嘗試 ${attempt + 1} 失敗,準備重試...`);
1586
+ }
1587
+ }
1588
+ }
1589
+ } else {
1590
+ // Camera未完全就緒,但仍嘗試套用約束
1591
+ console.warn('⚠️ Camera未完全就緒,嘗試套用解析度約束...');
1592
+ try {
1593
+ yield videoTrack.applyConstraints({
1594
+ width: {
1595
+ ideal: 1920,
1596
+ max: 3840
1597
+ },
1598
+ height: {
1599
+ ideal: 1080,
1600
+ max: 2160
1601
+ }
1602
+ });
1603
+ } catch (error) {
1604
+ console.warn('⚠️ 解析度提升失敗,使用預設解析度', error);
1605
+ }
1526
1606
  }
1607
+ // 🆕 記錄最終解析度資訊
1608
+ const finalSettings = videoTrack.getSettings();
1609
+ const initTime = (performance.now() - startTime).toFixed(2);
1610
+ console.log('📹 Camera初始化完成', {
1611
+ deviceId,
1612
+ deviceLabel: videoTrack.label,
1613
+ resolution: `${finalSettings.width}x${finalSettings.height}`,
1614
+ frameRate: finalSettings.frameRate,
1615
+ facingMode: finalSettings.facingMode,
1616
+ initTime: `${initTime}ms`
1617
+ });
1527
1618
  }
1528
1619
  }
1529
1620
  // try {
@@ -1569,12 +1660,28 @@ function switchCamera(deviceId, video) {
1569
1660
  video.srcObject = stream;
1570
1661
  }, 10);
1571
1662
  } catch (e) {
1663
+ // 🆕 增強錯誤日誌
1664
+ const initTime = (performance.now() - startTime).toFixed(2);
1665
+ console.error('❌ Camera切換失敗', {
1666
+ deviceId,
1667
+ error: e,
1668
+ errorName: e === null || e === void 0 ? void 0 : e.name,
1669
+ errorMessage: e === null || e === void 0 ? void 0 : e.message,
1670
+ initTime: `${initTime}ms`,
1671
+ streamExists: !!stream,
1672
+ trackCount: (_b = (_a = stream === null || stream === void 0 ? void 0 : stream.getTracks()) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0
1673
+ });
1572
1674
  throw new AuthmeError(ErrorCode.CAMERA_NOT_SUPPORT, e);
1573
1675
  }
1574
1676
  });
1575
1677
  }
1576
1678
  function _requestCamera(video, facingMode) {
1679
+ var _a, _b, _c, _d, _e, _f;
1577
1680
  return __awaiter(this, void 0, void 0, function* () {
1681
+ const requestStartTime = performance.now();
1682
+ console.log('🎬 開始camera請求流程', {
1683
+ facingMode
1684
+ });
1578
1685
  if (!('mediaDevices' in navigator)) {
1579
1686
  throw BROWSER_CAMERA_ERRORS.NOT_SUPPORT;
1580
1687
  }
@@ -1597,7 +1704,7 @@ function _requestCamera(video, facingMode) {
1597
1704
  // 輪詢取得攝影機 解析度等資訊
1598
1705
  const videoDevices = (yield navigator.mediaDevices.enumerateDevices()).filter(device => device.kind === 'videoinput');
1599
1706
  const deviceMetas = yield arrayFromAsync(asyncMap(device => __awaiter(this, void 0, void 0, function* () {
1600
- var _a, _b, _c, _d;
1707
+ var _g, _h, _j, _k;
1601
1708
  const stream = yield navigator.mediaDevices.getUserMedia({
1602
1709
  video: {
1603
1710
  deviceId: {
@@ -1605,10 +1712,10 @@ function _requestCamera(video, facingMode) {
1605
1712
  }
1606
1713
  }
1607
1714
  });
1608
- const track = (_a = stream.getVideoTracks()) === null || _a === void 0 ? void 0 : _a[0];
1609
- const capabilities = ((_b = track === null || track === void 0 ? void 0 : track.getCapabilities) !== null && _b !== void 0 ? _b : () => undefined).bind(track)(); // firefox 沒有 getCapabilities 可以用。
1610
- const widthMax = (_c = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _c === void 0 ? void 0 : _c.max;
1611
- const heightMax = (_d = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _d === void 0 ? void 0 : _d.max;
1715
+ const track = (_g = stream.getVideoTracks()) === null || _g === void 0 ? void 0 : _g[0];
1716
+ const capabilities = ((_h = track === null || track === void 0 ? void 0 : track.getCapabilities) !== null && _h !== void 0 ? _h : () => undefined).bind(track)(); // firefox 沒有 getCapabilities 可以用。
1717
+ const widthMax = (_j = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _j === void 0 ? void 0 : _j.max;
1718
+ const heightMax = (_k = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _k === void 0 ? void 0 : _k.max;
1612
1719
  const resolution = widthMax && heightMax ? widthMax * heightMax : 0;
1613
1720
  const facingModeFromLabel = inferFacingModeFromLabel(device === null || device === void 0 ? void 0 : device.label);
1614
1721
  const facingModeFromapabilities = inferFacingModeFromCapabilities(capabilities);
@@ -1668,6 +1775,19 @@ function _requestCamera(video, facingMode) {
1668
1775
  stream.getTracks().forEach(track => track.stop());
1669
1776
  }
1670
1777
  yield switchCamera(deviceId, video);
1778
+ // 🆕 記錄整個請求流程的總結資訊
1779
+ const totalTime = (performance.now() - requestStartTime).toFixed(2);
1780
+ console.log('🎉 Camera請求流程完成', {
1781
+ totalTime: `${totalTime}ms`,
1782
+ selectedDevice: {
1783
+ deviceId,
1784
+ label: firstDevice.device.label,
1785
+ facingMode: firstDevice.meta.facingMode,
1786
+ resolution: `${(_c = (_b = (_a = firstDevice.meta.capabilities) === null || _a === void 0 ? void 0 : _a.width) === null || _b === void 0 ? void 0 : _b.max) !== null && _c !== void 0 ? _c : 0}x${(_f = (_e = (_d = firstDevice.meta.capabilities) === null || _d === void 0 ? void 0 : _d.height) === null || _e === void 0 ? void 0 : _e.max) !== null && _f !== void 0 ? _f : 0}`
1787
+ },
1788
+ availableDevices: deviceMetas.length,
1789
+ isSamsung
1790
+ });
1671
1791
  return {
1672
1792
  facingMode: firstDevice.meta.facingMode,
1673
1793
  deviceMetas: deviceMetas
@@ -3233,8 +3353,8 @@ const themeConfigDefault = {
3233
3353
  };
3234
3354
 
3235
3355
  var name = "authme/sdk";
3236
- var version$1 = "2.8.29";
3237
- var date = "2025-10-30T04:42:12+0000";
3356
+ var version$1 = "2.8.30";
3357
+ var date = "2025-10-30T10:27:17+0000";
3238
3358
  var packageInfo = {
3239
3359
  name: name,
3240
3360
  version: version$1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authme/util",
3
- "version": "2.8.29",
3
+ "version": "2.8.30",
4
4
  "peerDependencies": {
5
5
  "core-js": "^3.6.0",
6
6
  "file-saver": "2.0.5",