@opengeni/react 1.4.0 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/accounts.js +2 -0
- package/dist/accounts.js.map +1 -1
- package/dist/artifacts-document.js +5 -4
- package/dist/artifacts-presentation.js +5 -4
- package/dist/artifacts-spreadsheet.js +4 -3
- package/dist/artifacts.js +14 -13
- package/dist/artifacts.js.map +1 -1
- package/dist/browser-viewer-5EEAS3IU.js +17 -0
- package/dist/chat-interactive-block-ZFHOKTMS.js +12 -0
- package/dist/{chunk-WEHMPOXK.js → chunk-2DDJ6YH6.js} +3 -1
- package/dist/{chunk-WEHMPOXK.js.map → chunk-2DDJ6YH6.js.map} +1 -1
- package/dist/{chunk-C5X5AJXK.js → chunk-2HVLQ26H.js} +5 -4
- package/dist/{chunk-C5X5AJXK.js.map → chunk-2HVLQ26H.js.map} +1 -1
- package/dist/{chunk-HDJWDK7W.js → chunk-2OQA3CPB.js} +300 -166
- package/dist/{chunk-HDJWDK7W.js.map → chunk-2OQA3CPB.js.map} +1 -1
- package/dist/{chunk-A4UJB2MM.js → chunk-32CGLXW2.js} +4 -3
- package/dist/{chunk-A4UJB2MM.js.map → chunk-32CGLXW2.js.map} +1 -1
- package/dist/{chunk-5CVXZA3Y.js → chunk-45NUOSXQ.js} +3 -2
- package/dist/{chunk-5CVXZA3Y.js.map → chunk-45NUOSXQ.js.map} +1 -1
- package/dist/{chunk-WUISZ3WU.js → chunk-53KJBGPZ.js} +5 -4
- package/dist/{chunk-WUISZ3WU.js.map → chunk-53KJBGPZ.js.map} +1 -1
- package/dist/{chunk-MBMPHOMA.js → chunk-55DXD22O.js} +3 -2
- package/dist/{chunk-MBMPHOMA.js.map → chunk-55DXD22O.js.map} +1 -1
- package/dist/{chunk-JT4JW7BC.js → chunk-5I4VRWBB.js} +3 -1
- package/dist/{chunk-JT4JW7BC.js.map → chunk-5I4VRWBB.js.map} +1 -1
- package/dist/{chunk-UK4TINKT.js → chunk-B27E3V37.js} +3 -1
- package/dist/{chunk-UK4TINKT.js.map → chunk-B27E3V37.js.map} +1 -1
- package/dist/{chunk-J6DBS4T3.js → chunk-BNKV5ZLF.js} +5 -4
- package/dist/{chunk-J6DBS4T3.js.map → chunk-BNKV5ZLF.js.map} +1 -1
- package/dist/{chunk-YM2DE7BQ.js → chunk-C5BF4L26.js} +13 -12
- package/dist/{chunk-YM2DE7BQ.js.map → chunk-C5BF4L26.js.map} +1 -1
- package/dist/{chunk-YBXQDQFX.js → chunk-C7CMD56T.js} +6 -5
- package/dist/{chunk-YBXQDQFX.js.map → chunk-C7CMD56T.js.map} +1 -1
- package/dist/{chunk-UGLEYEMP.js → chunk-CM7LVUKC.js} +3 -1
- package/dist/{chunk-UGLEYEMP.js.map → chunk-CM7LVUKC.js.map} +1 -1
- package/dist/{chunk-JVYQRRC4.js → chunk-CVYCLFMH.js} +3 -1
- package/dist/{chunk-JVYQRRC4.js.map → chunk-CVYCLFMH.js.map} +1 -1
- package/dist/{chunk-LJ2UTJJE.js → chunk-EAOSEIXB.js} +182 -97
- package/dist/chunk-EAOSEIXB.js.map +1 -0
- package/dist/{chunk-Y2PRMYLC.js → chunk-G3U2A6GS.js} +3 -2
- package/dist/{chunk-Y2PRMYLC.js.map → chunk-G3U2A6GS.js.map} +1 -1
- package/dist/{chunk-WZMYFJD3.js → chunk-G6YRCIYJ.js} +16 -7
- package/dist/{chunk-WZMYFJD3.js.map → chunk-G6YRCIYJ.js.map} +1 -1
- package/dist/{chunk-B3V6TG77.js → chunk-GC3PH6N7.js} +3 -1
- package/dist/{chunk-B3V6TG77.js.map → chunk-GC3PH6N7.js.map} +1 -1
- package/dist/{chunk-CJUO7J5Z.js → chunk-HXYOSSQO.js} +3 -2
- package/dist/{chunk-CJUO7J5Z.js.map → chunk-HXYOSSQO.js.map} +1 -1
- package/dist/{chunk-GYVRFZDY.js → chunk-I6OY3MWC.js} +310 -115
- package/dist/chunk-I6OY3MWC.js.map +1 -0
- package/dist/{chunk-BRM6FVZA.js → chunk-IEE7WCLN.js} +4 -3
- package/dist/{chunk-BRM6FVZA.js.map → chunk-IEE7WCLN.js.map} +1 -1
- package/dist/{chunk-DYWBUX5Q.js → chunk-IMSUVYQB.js} +6 -5
- package/dist/{chunk-DYWBUX5Q.js.map → chunk-IMSUVYQB.js.map} +1 -1
- package/dist/{chunk-LN6TCXD3.js → chunk-IUHHPMAX.js} +184 -48
- package/dist/chunk-IUHHPMAX.js.map +1 -0
- package/dist/{chunk-SGKD2OCN.js → chunk-IYQCWGU5.js} +6 -5
- package/dist/{chunk-SGKD2OCN.js.map → chunk-IYQCWGU5.js.map} +1 -1
- package/dist/{chunk-J2QWVSQY.js → chunk-JH7V627O.js} +8 -7
- package/dist/{chunk-J2QWVSQY.js.map → chunk-JH7V627O.js.map} +1 -1
- package/dist/{chunk-EESD3PY3.js → chunk-JHTIMBOL.js} +6 -5
- package/dist/{chunk-EESD3PY3.js.map → chunk-JHTIMBOL.js.map} +1 -1
- package/dist/{chunk-LNIRAOA3.js → chunk-L2J3PU7A.js} +7 -6
- package/dist/{chunk-LNIRAOA3.js.map → chunk-L2J3PU7A.js.map} +1 -1
- package/dist/{chunk-ZYRGEKWS.js → chunk-LJUMYUBO.js} +3 -1
- package/dist/{chunk-ZYRGEKWS.js.map → chunk-LJUMYUBO.js.map} +1 -1
- package/dist/{chunk-4RVYOY4O.js → chunk-LSW2OJVV.js} +4 -3
- package/dist/{chunk-4RVYOY4O.js.map → chunk-LSW2OJVV.js.map} +1 -1
- package/dist/{chunk-UTRTG6LH.js → chunk-LVS3MH5T.js} +3 -1
- package/dist/{chunk-UTRTG6LH.js.map → chunk-LVS3MH5T.js.map} +1 -1
- package/dist/chunk-M357MHH3.js +2 -0
- package/dist/{chunk-WRHIZYZF.js → chunk-MEQM4LI3.js} +6 -5
- package/dist/{chunk-WRHIZYZF.js.map → chunk-MEQM4LI3.js.map} +1 -1
- package/dist/chunk-NX4ADH73.js +14 -0
- package/dist/chunk-NX4ADH73.js.map +1 -0
- package/dist/{chunk-XCHWDJ22.js → chunk-OGTTUYNT.js} +3 -1
- package/dist/{chunk-XCHWDJ22.js.map → chunk-OGTTUYNT.js.map} +1 -1
- package/dist/{chunk-GIMRELBW.js → chunk-OYQQJL3J.js} +3 -1
- package/dist/{chunk-GIMRELBW.js.map → chunk-OYQQJL3J.js.map} +1 -1
- package/dist/{chunk-RSI7XYXL.js → chunk-PBCZL4JP.js} +6 -5
- package/dist/{chunk-RSI7XYXL.js.map → chunk-PBCZL4JP.js.map} +1 -1
- package/dist/{chunk-I7IWRQLN.js → chunk-PHBFJCEU.js} +17 -11
- package/dist/chunk-PHBFJCEU.js.map +1 -0
- package/dist/{chunk-3CTRFMAK.js → chunk-PKCAYHDC.js} +5 -4
- package/dist/{chunk-3CTRFMAK.js.map → chunk-PKCAYHDC.js.map} +1 -1
- package/dist/{chunk-K3HQAKQX.js → chunk-PMV53IMM.js} +3 -1
- package/dist/{chunk-K3HQAKQX.js.map → chunk-PMV53IMM.js.map} +1 -1
- package/dist/{chunk-YQEAA6LT.js → chunk-QHUE7E4N.js} +3 -2
- package/dist/{chunk-YQEAA6LT.js.map → chunk-QHUE7E4N.js.map} +1 -1
- package/dist/{chunk-OA6HFRQP.js → chunk-QMMCJGFI.js} +4 -3
- package/dist/{chunk-OA6HFRQP.js.map → chunk-QMMCJGFI.js.map} +1 -1
- package/dist/{chunk-YV4L3ILF.js → chunk-QV3DJVRZ.js} +3 -1
- package/dist/{chunk-YV4L3ILF.js.map → chunk-QV3DJVRZ.js.map} +1 -1
- package/dist/{chunk-447JLCBU.js → chunk-S2QH6EZ5.js} +3 -1
- package/dist/{chunk-447JLCBU.js.map → chunk-S2QH6EZ5.js.map} +1 -1
- package/dist/{chunk-PNY3JKBJ.js → chunk-SFH43JT2.js} +5 -4
- package/dist/{chunk-PNY3JKBJ.js.map → chunk-SFH43JT2.js.map} +1 -1
- package/dist/{chunk-AWZLIMKX.js → chunk-T46QZH3E.js} +3 -1
- package/dist/{chunk-AWZLIMKX.js.map → chunk-T46QZH3E.js.map} +1 -1
- package/dist/{chunk-5J4FOW6Q.js → chunk-TNEZNMSN.js} +3 -1
- package/dist/{chunk-5J4FOW6Q.js.map → chunk-TNEZNMSN.js.map} +1 -1
- package/dist/{chunk-22KP6LR5.js → chunk-TXS65BB2.js} +3 -1
- package/dist/{chunk-22KP6LR5.js.map → chunk-TXS65BB2.js.map} +1 -1
- package/dist/{chunk-H5X55XH7.js → chunk-UDPH5SLV.js} +4 -3
- package/dist/{chunk-H5X55XH7.js.map → chunk-UDPH5SLV.js.map} +1 -1
- package/dist/{chunk-VZTQ73XT.js → chunk-XEA5BCMA.js} +3 -1
- package/dist/{chunk-VZTQ73XT.js.map → chunk-XEA5BCMA.js.map} +1 -1
- package/dist/{chunk-5F4WR7X7.js → chunk-XS67YG5R.js} +3 -1
- package/dist/{chunk-5F4WR7X7.js.map → chunk-XS67YG5R.js.map} +1 -1
- package/dist/{chunk-TKOTKRWY.js → chunk-XTD7TZHW.js} +3 -1
- package/dist/{chunk-TKOTKRWY.js.map → chunk-XTD7TZHW.js.map} +1 -1
- package/dist/{chunk-A2PI6UMY.js → chunk-YSRBFJMQ.js} +3 -1
- package/dist/{chunk-A2PI6UMY.js.map → chunk-YSRBFJMQ.js.map} +1 -1
- package/dist/chunk-YVFRBXST.js +1420 -0
- package/dist/chunk-YVFRBXST.js.map +1 -0
- package/dist/{chunk-SCOTPE2I.js → chunk-YYLBXXTE.js} +3 -1
- package/dist/{chunk-SCOTPE2I.js.map → chunk-YYLBXXTE.js.map} +1 -1
- package/dist/{chunk-RHREZ7BO.js → chunk-ZUWF4NF7.js} +3 -1
- package/dist/{chunk-RHREZ7BO.js.map → chunk-ZUWF4NF7.js.map} +1 -1
- package/dist/clipboard.js +3 -2
- package/dist/components/composer-transcription-control.d.ts +4 -0
- package/dist/components/session-conversation.d.ts +6 -0
- package/dist/composer-voice-events.d.ts +8 -0
- package/dist/composer.js +15 -13
- package/dist/computer-viewer-ELNLZGHI.js +20 -0
- package/dist/connect.js +15 -12
- package/dist/connect.js.map +1 -1
- package/dist/desktop.js +6 -5
- package/dist/desktop.js.map +1 -1
- package/dist/diffs.js +2 -1
- package/dist/diffs.js.map +1 -1
- package/dist/editor.js +4 -3
- package/dist/editor.js.map +1 -1
- package/dist/embedded-voice-NIL4RDX3.js +69 -0
- package/dist/embedded-voice-NIL4RDX3.js.map +1 -0
- package/dist/{fleet-decision-row-YZ3ZKWMM.js → fleet-decision-row-SI63O5V4.js} +3 -1
- package/dist/{fleet-decision-row-YZ3ZKWMM.js.map → fleet-decision-row-SI63O5V4.js.map} +1 -1
- package/dist/hooks/use-client-config-flags.d.ts +6 -0
- package/dist/hooks/use-computer-session.d.ts +2 -0
- package/dist/hooks/use-realtime-voice-models.d.ts +9 -0
- package/dist/hooks/use-voice-input.d.ts +8 -1
- package/dist/index.js +47 -45
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +14 -13
- package/dist/interaction.js.map +1 -1
- package/dist/{latest-question-GPYM2JNU.js → latest-question-2POFPYNB.js} +5 -4
- package/dist/{latest-question-GPYM2JNU.js.map → latest-question-2POFPYNB.js.map} +1 -1
- package/dist/machines.js +8 -7
- package/dist/{markdown-table-layout-QXSLK4BY.js → markdown-table-layout-DQ4DRNVT.js} +3 -1
- package/dist/{markdown-table-layout-QXSLK4BY.js.map → markdown-table-layout-DQ4DRNVT.js.map} +1 -1
- package/dist/model-policy-picker-menu-WRNSRFQC.js +15 -0
- package/dist/model-policy.js +2 -1
- package/dist/{noto-sans-arabic-loader-IA2T4X2A.js → noto-sans-arabic-loader-XSH2KYWJ.js} +3 -1
- package/dist/{noto-sans-arabic-loader-IA2T4X2A.js.map → noto-sans-arabic-loader-XSH2KYWJ.js.map} +1 -1
- package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js → noto-sans-jp-loader.generated-MR5L6V7K.js} +3 -1
- package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js.map → noto-sans-jp-loader.generated-MR5L6V7K.js.map} +1 -1
- package/dist/{platform-activity-row-627BFZ46.js → platform-activity-row-PJJVATTZ.js} +3 -1
- package/dist/{platform-activity-row-627BFZ46.js.map → platform-activity-row-PJJVATTZ.js.map} +1 -1
- package/dist/{queue-surface-implementation-ZHFI5JBP.js → queue-surface-implementation-67FS7FUI.js} +10 -9
- package/dist/{queue-surface-implementation-ZHFI5JBP.js.map → queue-surface-implementation-67FS7FUI.js.map} +1 -1
- package/dist/realtime/embedded-voice.d.ts +20 -0
- package/dist/realtime.js +22 -1353
- package/dist/realtime.js.map +1 -1
- package/dist/sandbox-files-34CJJNOY.js +21 -0
- package/dist/session-ui.js +32 -30
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +10 -9
- package/dist/sites.js +2 -1
- package/dist/terminal.js +6 -5
- package/dist/terminal.js.map +1 -1
- package/dist/{timeline-annotation-markers-GNDHTGBD.js → timeline-annotation-markers-U3G66KUD.js} +5 -4
- package/dist/{timeline-annotation-markers-GNDHTGBD.js.map → timeline-annotation-markers-U3G66KUD.js.map} +1 -1
- package/dist/{timeline-annotation-selection-DMLMM2TX.js → timeline-annotation-selection-BI7QTPTZ.js} +4 -3
- package/dist/{timeline-annotation-selection-DMLMM2TX.js.map → timeline-annotation-selection-BI7QTPTZ.js.map} +1 -1
- package/dist/{timeline-annotations-dialog-ELRDBHTS.js → timeline-annotations-dialog-FOMHSDTE.js} +7 -6
- package/dist/{timeline-annotations-dialog-ELRDBHTS.js.map → timeline-annotations-dialog-FOMHSDTE.js.map} +1 -1
- package/dist/usage.js +6 -5
- package/dist/usage.js.map +1 -1
- package/dist/voice-recording-owner.d.ts +7 -0
- package/package.json +3 -3
- package/src/components/composer-transcription-control.tsx +109 -27
- package/src/components/computer-viewer.tsx +139 -30
- package/src/components/markdown.tsx +7 -2
- package/src/components/message-timeline.tsx +10 -1
- package/src/components/session-conversation.tsx +44 -0
- package/src/components/session-list.tsx +1 -1
- package/src/components/session-proxy-scope.tsx +26 -5
- package/src/composer-voice-events.ts +12 -0
- package/src/connection-discovery.tsx +4 -1
- package/src/hooks/use-browser-session.ts +445 -168
- package/src/hooks/use-client-config-flags.ts +8 -0
- package/src/hooks/use-computer-session.ts +334 -98
- package/src/hooks/use-goal.ts +12 -1
- package/src/hooks/use-realtime-voice-models.ts +67 -0
- package/src/hooks/use-voice-input.ts +109 -18
- package/src/realtime/embedded-voice.tsx +81 -0
- package/src/realtime/realtime-control.tsx +82 -17
- package/src/voice-recording-owner.ts +22 -0
- package/styles/compiled.css +77 -18
- package/styles/index.css +49 -0
- package/styles/responsive.css +61 -4
- package/styles/session-capability.css +1 -1
- package/dist/browser-viewer-SHYKQRNX.js +0 -16
- package/dist/chat-interactive-block-UGBTNB3L.js +0 -11
- package/dist/chunk-GYVRFZDY.js.map +0 -1
- package/dist/chunk-I7IWRQLN.js.map +0 -1
- package/dist/chunk-IWIDV7SB.js +0 -1
- package/dist/chunk-LJ2UTJJE.js.map +0 -1
- package/dist/chunk-LN6TCXD3.js.map +0 -1
- package/dist/computer-viewer-6SRGWRUX.js +0 -19
- package/dist/model-policy-picker-menu-DXHUL73H.js +0 -14
- package/dist/sandbox-files-GORZOUUJ.js +0 -20
- /package/dist/{browser-viewer-SHYKQRNX.js.map → browser-viewer-5EEAS3IU.js.map} +0 -0
- /package/dist/{chat-interactive-block-UGBTNB3L.js.map → chat-interactive-block-ZFHOKTMS.js.map} +0 -0
- /package/dist/{chunk-IWIDV7SB.js.map → chunk-M357MHH3.js.map} +0 -0
- /package/dist/{computer-viewer-6SRGWRUX.js.map → computer-viewer-ELNLZGHI.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-DXHUL73H.js.map → model-policy-picker-menu-WRNSRFQC.js.map} +0 -0
- /package/dist/{sandbox-files-GORZOUUJ.js.map → sandbox-files-34CJJNOY.js.map} +0 -0
|
@@ -1,31 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import {
|
|
2
3
|
shouldSteerOnKey,
|
|
3
4
|
shouldSubmitOnKey
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PBCZL4JP.js";
|
|
5
6
|
import {
|
|
6
7
|
Tooltip,
|
|
7
8
|
TooltipContent,
|
|
8
9
|
TooltipProvider,
|
|
9
10
|
TooltipTrigger,
|
|
10
11
|
useLightboxOptional
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IEE7WCLN.js";
|
|
13
|
+
import {
|
|
14
|
+
COMPOSER_VOICE_INPUT_START_EVENT,
|
|
15
|
+
composerVoiceEventScope
|
|
16
|
+
} from "./chunk-NX4ADH73.js";
|
|
12
17
|
import {
|
|
13
18
|
groupPickerRowsByBillingClass
|
|
14
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-XS67YG5R.js";
|
|
15
20
|
import {
|
|
16
21
|
ComposerResponsiveContext
|
|
17
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-XEA5BCMA.js";
|
|
18
23
|
import {
|
|
19
24
|
composerSubmissionErrorMessage,
|
|
20
25
|
formatBytes,
|
|
21
26
|
formatRelativeTime
|
|
22
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-LVS3MH5T.js";
|
|
23
28
|
import {
|
|
24
29
|
useErrorMessage
|
|
25
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-CM7LVUKC.js";
|
|
26
31
|
import {
|
|
27
32
|
cn
|
|
28
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-TXS65BB2.js";
|
|
29
34
|
|
|
30
35
|
// src/workstream-control-event.ts
|
|
31
36
|
var OPEN_WORKSTREAM_CONTROL_EVENT = "opengeni:open-workstream-control";
|
|
@@ -3019,6 +3024,21 @@ async function createUnderlyingOwnerLease() {
|
|
|
3019
3024
|
writeSessionOwnerId(ownerId);
|
|
3020
3025
|
return { ownerId, release: () => void 0 };
|
|
3021
3026
|
}
|
|
3027
|
+
async function liveVoiceRecordingOwnerIds() {
|
|
3028
|
+
if (!hasWebLocks() || typeof navigator.locks.query !== "function") return null;
|
|
3029
|
+
try {
|
|
3030
|
+
const snapshot = await navigator.locks.query();
|
|
3031
|
+
const live = /* @__PURE__ */ new Set();
|
|
3032
|
+
for (const lock of [...snapshot.held ?? [], ...snapshot.pending ?? []]) {
|
|
3033
|
+
if (lock.name?.startsWith(VOICE_RECORDING_OWNER_LOCK_PREFIX)) {
|
|
3034
|
+
live.add(lock.name.slice(VOICE_RECORDING_OWNER_LOCK_PREFIX.length));
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
return live;
|
|
3038
|
+
} catch {
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3022
3042
|
function hasWebLocks() {
|
|
3023
3043
|
return typeof navigator !== "undefined" && navigator.locks !== null && navigator.locks !== void 0 && typeof navigator.locks.request === "function";
|
|
3024
3044
|
}
|
|
@@ -3140,6 +3160,7 @@ var VOICE_RECORDING_TIMESLICE_MILLISECONDS = 5e3;
|
|
|
3140
3160
|
var VOICE_RECORDING_OWNER_HEARTBEAT_MILLISECONDS = 5e3;
|
|
3141
3161
|
var VOICE_RECORDING_OWNER_STALE_MILLISECONDS = 3e4;
|
|
3142
3162
|
var VOICE_RECORDING_CLIENT_MAX_DURATION_SECONDS = 600;
|
|
3163
|
+
var VOICE_RECORDING_DISCARD_ON_CANCEL_MAX_MILLISECONDS = 3e3;
|
|
3143
3164
|
var VOICE_RECORDING_RESUMABLE_CLIENT_MAX_DURATION_SECONDS = 8 * 60 * 60;
|
|
3144
3165
|
var VOICE_RECORDING_RECOVERY_STATUS_POLL_MILLISECONDS = 2e3;
|
|
3145
3166
|
var VOICE_RECORDING_RECOVERY_MAX_MUTATION_DELAY_MILLISECONDS = 3e4;
|
|
@@ -3203,6 +3224,8 @@ function useVoiceInput({
|
|
|
3203
3224
|
const recorderRef = useRef4(null);
|
|
3204
3225
|
const streamRef = useRef4(null);
|
|
3205
3226
|
const timerRef = useRef4(null);
|
|
3227
|
+
const holdOnStopRef = useRef4(false);
|
|
3228
|
+
const recordingStartedAtRef = useRef4(0);
|
|
3206
3229
|
const automaticRetryTimerRef = useRef4(null);
|
|
3207
3230
|
const automaticRetryAttemptRef = useRef4(0);
|
|
3208
3231
|
const ownerHeartbeatTimerRef = useRef4(null);
|
|
@@ -3342,15 +3365,17 @@ function useVoiceInput({
|
|
|
3342
3365
|
const active = () => generation === generationRef.current && workspaceIdRef.current === workspaceId;
|
|
3343
3366
|
const [store, ownerId] = await Promise.all([ensureStore(), ensureOwnerId()]);
|
|
3344
3367
|
if (!active()) return;
|
|
3345
|
-
const
|
|
3368
|
+
const heartbeatStaleBefore = new Date(
|
|
3346
3369
|
readNow().getTime() - VOICE_RECORDING_OWNER_STALE_MILLISECONDS
|
|
3347
3370
|
).toISOString();
|
|
3348
|
-
await store.cleanupHandedOffManifests({ ownerId, staleBefore }).catch(() => void 0);
|
|
3371
|
+
await store.cleanupHandedOffManifests({ ownerId, staleBefore: heartbeatStaleBefore }).catch(() => void 0);
|
|
3349
3372
|
if (!active()) return;
|
|
3350
|
-
const
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
})
|
|
3373
|
+
const liveOwners = createOwnerIdRef.current === void 0 ? await liveVoiceRecordingOwnerIds() : null;
|
|
3374
|
+
if (!active()) return;
|
|
3375
|
+
const staleBefore = liveOwners ? readNow().toISOString() : heartbeatStaleBefore;
|
|
3376
|
+
const manifests = (await store.listRecoverableManifests(workspaceId, { ownerId, staleBefore })).filter(
|
|
3377
|
+
(manifest) => !liveOwners || !manifest.ownerId || manifest.ownerId === ownerId || !liveOwners.has(manifest.ownerId) || !manifest.ownerHeartbeatAt || manifest.ownerHeartbeatAt <= heartbeatStaleBefore
|
|
3378
|
+
);
|
|
3354
3379
|
if (!active()) return;
|
|
3355
3380
|
for (const candidate of manifests) {
|
|
3356
3381
|
try {
|
|
@@ -3372,10 +3397,13 @@ function useVoiceInput({
|
|
|
3372
3397
|
}
|
|
3373
3398
|
rememberManifest(claimed);
|
|
3374
3399
|
beginOwnerHeartbeat(claimed);
|
|
3400
|
+
const transcriptReady = claimed.finalizationState === "transcript-ready" && claimed.transcriptText !== null;
|
|
3375
3401
|
setStatus(
|
|
3376
|
-
|
|
3402
|
+
transcriptReady ? "transcript-ready" : claimed.recoveryMode === "automatic" ? "retrying" : "recovered"
|
|
3403
|
+
);
|
|
3404
|
+
setError(
|
|
3405
|
+
transcriptReady && candidate.handoffMode === "append" ? "handoff_uncertain" : null
|
|
3377
3406
|
);
|
|
3378
|
-
setError(null);
|
|
3379
3407
|
return;
|
|
3380
3408
|
} catch (reason) {
|
|
3381
3409
|
if (reason instanceof VoiceRecordingOwnedError) continue;
|
|
@@ -3466,7 +3494,7 @@ function useVoiceInput({
|
|
|
3466
3494
|
automaticRetryAttemptRef.current = 0;
|
|
3467
3495
|
if (ready.handoffMode === "explicit") {
|
|
3468
3496
|
setStatus("transcript-ready");
|
|
3469
|
-
setError(
|
|
3497
|
+
setError(null);
|
|
3470
3498
|
focusInput();
|
|
3471
3499
|
return;
|
|
3472
3500
|
}
|
|
@@ -3742,6 +3770,15 @@ function useVoiceInput({
|
|
|
3742
3770
|
await preserveForRetry(retained, attemptCaptureLimitError, generation);
|
|
3743
3771
|
return;
|
|
3744
3772
|
}
|
|
3773
|
+
if (holdOnStopRef.current) {
|
|
3774
|
+
holdOnStopRef.current = false;
|
|
3775
|
+
const retained = await updateManifestBestEffort(stopped, {
|
|
3776
|
+
recoveryMode: "manual",
|
|
3777
|
+
handoffMode: "explicit"
|
|
3778
|
+
});
|
|
3779
|
+
await preserveForRetry(retained, null, generation);
|
|
3780
|
+
return;
|
|
3781
|
+
}
|
|
3745
3782
|
await finalizePersistedRecording(generation);
|
|
3746
3783
|
});
|
|
3747
3784
|
};
|
|
@@ -3750,6 +3787,8 @@ function useVoiceInput({
|
|
|
3750
3787
|
resolveCaptureSettledRef.current = resolve;
|
|
3751
3788
|
});
|
|
3752
3789
|
attemptRecordingStartedAt = readNow().getTime();
|
|
3790
|
+
recordingStartedAtRef.current = attemptRecordingStartedAt;
|
|
3791
|
+
holdOnStopRef.current = false;
|
|
3753
3792
|
recorder.start(VOICE_RECORDING_TIMESLICE_MILLISECONDS);
|
|
3754
3793
|
recorderStarted = true;
|
|
3755
3794
|
setStatus("recording");
|
|
@@ -3951,7 +3990,21 @@ function useVoiceInput({
|
|
|
3951
3990
|
workspaceId
|
|
3952
3991
|
]);
|
|
3953
3992
|
const cancel = useCallback4(() => {
|
|
3954
|
-
if (status === "recording"
|
|
3993
|
+
if (status === "recording") {
|
|
3994
|
+
const recorder = recorderRef.current;
|
|
3995
|
+
const elapsed = readNow().getTime() - recordingStartedAtRef.current;
|
|
3996
|
+
if (recorder && recorder.state !== "inactive" && elapsed >= VOICE_RECORDING_DISCARD_ON_CANCEL_MAX_MILLISECONDS) {
|
|
3997
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
3998
|
+
timerRef.current = null;
|
|
3999
|
+
holdOnStopRef.current = true;
|
|
4000
|
+
setStatus("saving");
|
|
4001
|
+
recorder.stop();
|
|
4002
|
+
return;
|
|
4003
|
+
}
|
|
4004
|
+
void discard();
|
|
4005
|
+
return;
|
|
4006
|
+
}
|
|
4007
|
+
if (status === "requesting-permission") {
|
|
3955
4008
|
void discard();
|
|
3956
4009
|
return;
|
|
3957
4010
|
}
|
|
@@ -3975,7 +4028,7 @@ function useVoiceInput({
|
|
|
3975
4028
|
await preserveForRetry(retained, null, generation);
|
|
3976
4029
|
});
|
|
3977
4030
|
}
|
|
3978
|
-
}, [discard, preserveForRetry, status, updateManifestBestEffort]);
|
|
4031
|
+
}, [discard, preserveForRetry, readNow, status, updateManifestBestEffort]);
|
|
3979
4032
|
useEffect3(() => {
|
|
3980
4033
|
const current = manifestRef.current;
|
|
3981
4034
|
const generation = ++generationRef.current;
|
|
@@ -4028,7 +4081,8 @@ function useVoiceInput({
|
|
|
4028
4081
|
]);
|
|
4029
4082
|
useEffect3(() => {
|
|
4030
4083
|
const onKeyDown = (event) => {
|
|
4031
|
-
if (event.key === "Escape" &&
|
|
4084
|
+
if (event.key === "Escape" && // A dialog, menu, or popover that handled Escape owns it.
|
|
4085
|
+
!event.defaultPrevented && (status === "requesting-permission" || status === "recording" || status === "saving" || status === "transcribing" || status === "retrying")) {
|
|
4032
4086
|
event.preventDefault();
|
|
4033
4087
|
cancel();
|
|
4034
4088
|
}
|
|
@@ -4045,6 +4099,16 @@ function useVoiceInput({
|
|
|
4045
4099
|
automaticRetryTimerRef.current = null;
|
|
4046
4100
|
const manifest = manifestRef.current;
|
|
4047
4101
|
const ownerReady = ownerIdPromiseRef.current;
|
|
4102
|
+
const knownOwnerId = ownerIdRef.current;
|
|
4103
|
+
const ownerLease = ownerLeaseRef.current;
|
|
4104
|
+
const closingStore = storeRef.current;
|
|
4105
|
+
const ownsClosingStore = ownsStoreRef.current;
|
|
4106
|
+
storeRef.current = null;
|
|
4107
|
+
storePromiseRef.current = null;
|
|
4108
|
+
ownerIdRef.current = null;
|
|
4109
|
+
ownerIdPromiseRef.current = null;
|
|
4110
|
+
ownerLeaseRef.current = null;
|
|
4111
|
+
manifestRef.current = null;
|
|
4048
4112
|
stopOwnerHeartbeat();
|
|
4049
4113
|
const recorder = recorderRef.current;
|
|
4050
4114
|
let captureSettled = persistenceQueueRef.current;
|
|
@@ -4054,8 +4118,8 @@ function useVoiceInput({
|
|
|
4054
4118
|
}
|
|
4055
4119
|
clearCaptureRuntime();
|
|
4056
4120
|
void captureSettled.catch(() => void 0).then(async () => {
|
|
4057
|
-
const ownerId =
|
|
4058
|
-
const store =
|
|
4121
|
+
const ownerId = knownOwnerId ?? (ownerReady ? await ownerReady.catch(() => null) : null);
|
|
4122
|
+
const store = closingStore;
|
|
4059
4123
|
if (store && manifest && ownerId) {
|
|
4060
4124
|
const wasProcessing = statusRef.current === "saving" || statusRef.current === "transcribing" || statusRef.current === "retrying";
|
|
4061
4125
|
await store.updateManifest(
|
|
@@ -4075,10 +4139,9 @@ function useVoiceInput({
|
|
|
4075
4139
|
ownerId
|
|
4076
4140
|
).catch(() => void 0);
|
|
4077
4141
|
}
|
|
4078
|
-
if (
|
|
4142
|
+
if (ownsClosingStore) await store?.close();
|
|
4079
4143
|
}).catch(() => void 0).finally(() => {
|
|
4080
|
-
|
|
4081
|
-
ownerLeaseRef.current = null;
|
|
4144
|
+
ownerLease?.release();
|
|
4082
4145
|
});
|
|
4083
4146
|
},
|
|
4084
4147
|
[clearCaptureRuntime, readNow, stopOwnerHeartbeat]
|
|
@@ -4090,6 +4153,11 @@ function useVoiceInput({
|
|
|
4090
4153
|
stream,
|
|
4091
4154
|
recordingId,
|
|
4092
4155
|
durationSeconds,
|
|
4156
|
+
recordingStartedAt: status === "recording" ? recordingStartedAtRef.current || null : null,
|
|
4157
|
+
maxRecordingSeconds: capability ? Math.min(
|
|
4158
|
+
capability.resumable && isResumableVoiceInputClient(client) ? capability.resumable.maxDurationSeconds : capability.maxDurationSeconds,
|
|
4159
|
+
capability.resumable && isResumableVoiceInputClient(client) ? VOICE_RECORDING_RESUMABLE_CLIENT_MAX_DURATION_SECONDS : VOICE_RECORDING_CLIENT_MAX_DURATION_SECONDS
|
|
4160
|
+
) : null,
|
|
4093
4161
|
locallySaved,
|
|
4094
4162
|
hasRecoverableRecording: manifestRef.current !== null && status !== "recording",
|
|
4095
4163
|
savedTranscript: manifestRef.current?.finalizationState === "transcript-ready" ? manifestRef.current.transcriptText : null,
|
|
@@ -4338,31 +4406,33 @@ function Tip({ tip, children }) {
|
|
|
4338
4406
|
var defaultMessages = {
|
|
4339
4407
|
start: "Start voice input",
|
|
4340
4408
|
stop: "Stop and transcribe",
|
|
4341
|
-
cancel: "
|
|
4409
|
+
cancel: "Stop without transcribing",
|
|
4342
4410
|
retry: "Retry voice input",
|
|
4411
|
+
transcribeSaved: "Transcribe saved recording",
|
|
4412
|
+
timeRemaining: "Stops and transcribes in {seconds}s",
|
|
4343
4413
|
pauseRetrying: "Pause automatic retry",
|
|
4344
4414
|
requestingPermission: "Requesting microphone\u2026",
|
|
4345
|
-
recording: "Recording. Press Escape to
|
|
4415
|
+
recording: "Recording. Press Escape to stop without transcribing.",
|
|
4346
4416
|
saving: "Saving audio locally\u2026",
|
|
4347
4417
|
transcribing: "Transcribing\u2026",
|
|
4348
|
-
retrying: "
|
|
4349
|
-
recovered: "Recording
|
|
4350
|
-
recoveredTranscript: "Transcript saved
|
|
4418
|
+
retrying: "Saved. Retrying transcription\u2026",
|
|
4419
|
+
recovered: "Recording saved on this device.",
|
|
4420
|
+
recoveredTranscript: "Transcript saved. Insert it into your draft?",
|
|
4351
4421
|
insertRecoveredTranscript: "Insert saved transcript",
|
|
4352
4422
|
discardRecovered: "Discard saved recording",
|
|
4353
4423
|
unavailableDisabled: "Voice input is unavailable while the composer is disabled.",
|
|
4354
4424
|
unavailable: "Voice input is unavailable for this workspace.",
|
|
4355
|
-
errorPermissionDenied: "Microphone
|
|
4425
|
+
errorPermissionDenied: "Microphone access is blocked. Allow it in site settings, then try again.",
|
|
4356
4426
|
errorNotSupported: "Voice input is not supported on this device.",
|
|
4357
4427
|
errorUnavailable: "Voice input is not configured.",
|
|
4358
|
-
errorInsufficientCredits: "Voice input needs
|
|
4359
|
-
errorAllowanceExhausted: "
|
|
4428
|
+
errorInsufficientCredits: "Voice input needs credits. Recording saved; retry after adding credits.",
|
|
4429
|
+
errorAllowanceExhausted: "Usage limit reached. Recording saved for later.",
|
|
4360
4430
|
errorPolicyBlocked: "Voice input isn't allowed for this account or workspace.",
|
|
4361
4431
|
errorTooLarge: "Recording is too large. Try a shorter message.",
|
|
4362
4432
|
errorInvalidAudio: "The recording could not be read. Try again.",
|
|
4363
4433
|
errorStorageUnavailable: "Voice input stopped because audio could not be saved safely.",
|
|
4364
|
-
errorRetryable: "
|
|
4365
|
-
errorHandoffUncertain: "Transcript
|
|
4434
|
+
errorRetryable: "Saved. Transcription failed, retry when ready.",
|
|
4435
|
+
errorHandoffUncertain: "Transcript saved. Check your draft before inserting again.",
|
|
4366
4436
|
errorUnknown: "Voice input could not start. Try again."
|
|
4367
4437
|
};
|
|
4368
4438
|
var WAVEFORM_BARS = 18;
|
|
@@ -4399,12 +4469,16 @@ function ComposerTranscriptionControl({
|
|
|
4399
4469
|
const retrying = status === "retrying";
|
|
4400
4470
|
const capturing = status === "requesting-permission" || status === "recording";
|
|
4401
4471
|
const cancelTranscription = transcription.cancel;
|
|
4472
|
+
const discardTranscription = transcription.discard;
|
|
4473
|
+
const hasRecoverableRecording = transcription.hasRecoverableRecording;
|
|
4402
4474
|
useEffect4(() => {
|
|
4403
4475
|
if (!suppressed) return;
|
|
4404
4476
|
if (status === "recording" || status === "requesting-permission") {
|
|
4405
4477
|
cancelTranscription();
|
|
4478
|
+
} else if (status === "error" && !hasRecoverableRecording) {
|
|
4479
|
+
void discardTranscription();
|
|
4406
4480
|
}
|
|
4407
|
-
}, [cancelTranscription, status, suppressed]);
|
|
4481
|
+
}, [cancelTranscription, discardTranscription, hasRecoverableRecording, status, suppressed]);
|
|
4408
4482
|
const active = capturing || status === "saving" || status === "transcribing";
|
|
4409
4483
|
const recoverable = transcription.hasRecoverableRecording && (retrying || status === "recovered" || status === "transcript-ready" || status === "error");
|
|
4410
4484
|
const savedTranscript = status === "transcript-ready" && transcription.savedTranscript !== null;
|
|
@@ -4412,11 +4486,15 @@ function ComposerTranscriptionControl({
|
|
|
4412
4486
|
const idleLabel = unavailableMessage ?? (status === "error" ? messages.retry : messages.start);
|
|
4413
4487
|
const errorMessage = transcription.error ? transcriptionErrorMessage(transcription.error, messages) : null;
|
|
4414
4488
|
const announcement = status === "requesting-permission" ? messages.requestingPermission : status === "recording" ? messages.recording : status === "saving" ? messages.saving : status === "transcribing" ? messages.transcribing : retrying ? messages.retrying : status === "recovered" ? messages.recovered : status === "transcript-ready" ? messages.recoveredTranscript : status === "error" ? errorMessage ?? messages.errorUnknown : unavailableMessage;
|
|
4489
|
+
const recoveredLabel = savedTranscript ? errorMessage ?? messages.recoveredTranscript : retrying ? messages.retrying : status === "error" ? errorMessage ?? messages.errorRetryable : messages.recovered;
|
|
4415
4490
|
function start(event) {
|
|
4416
4491
|
if (unavailableMessage) {
|
|
4417
4492
|
event.preventDefault();
|
|
4418
4493
|
return;
|
|
4419
4494
|
}
|
|
4495
|
+
composerVoiceEventScope(event.currentTarget)?.dispatchEvent(
|
|
4496
|
+
new Event(COMPOSER_VOICE_INPUT_START_EVENT)
|
|
4497
|
+
);
|
|
4420
4498
|
void transcription.start();
|
|
4421
4499
|
}
|
|
4422
4500
|
return /* @__PURE__ */ jsx4(AnimatePresence3, { initial: false, children: suppressed ? null : /* @__PURE__ */ jsx4(
|
|
@@ -4435,6 +4513,7 @@ function ComposerTranscriptionControl({
|
|
|
4435
4513
|
),
|
|
4436
4514
|
"data-transcription-status": status,
|
|
4437
4515
|
"data-transcription-capturing": capturing ? "" : void 0,
|
|
4516
|
+
"data-transcription-attention": !capturing && (recoverable || status === "error" && errorMessage) ? "" : void 0,
|
|
4438
4517
|
children: /* @__PURE__ */ jsxs4("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
|
|
4439
4518
|
/* @__PURE__ */ jsx4(AnimatePresence3, { mode: "popLayout", initial: false, children: recoverable ? /* @__PURE__ */ jsxs4(
|
|
4440
4519
|
motion3.span,
|
|
@@ -4448,18 +4527,25 @@ function ComposerTranscriptionControl({
|
|
|
4448
4527
|
"bg-og-surface-2/70 pl-2 pr-1 pointer-coarse:h-11"
|
|
4449
4528
|
),
|
|
4450
4529
|
children: [
|
|
4451
|
-
/* @__PURE__ */ jsx4(
|
|
4530
|
+
/* @__PURE__ */ jsx4(
|
|
4531
|
+
"span",
|
|
4532
|
+
{
|
|
4533
|
+
title: recoveredLabel,
|
|
4534
|
+
className: "og-transcription-recovered-label max-w-56 line-clamp-2 text-og-xs leading-tight text-og-fg-muted max-sm:max-w-32",
|
|
4535
|
+
children: recoveredLabel
|
|
4536
|
+
}
|
|
4537
|
+
),
|
|
4452
4538
|
/* @__PURE__ */ jsx4(
|
|
4453
4539
|
Tip,
|
|
4454
4540
|
{
|
|
4455
|
-
tip: savedTranscript ? messages.insertRecoveredTranscript : retrying ? messages.pauseRetrying : messages.retry,
|
|
4541
|
+
tip: savedTranscript ? messages.insertRecoveredTranscript : retrying ? messages.pauseRetrying : status === "recovered" ? messages.transcribeSaved : messages.retry,
|
|
4456
4542
|
children: /* @__PURE__ */ jsx4(
|
|
4457
4543
|
"button",
|
|
4458
4544
|
{
|
|
4459
4545
|
type: "button",
|
|
4460
4546
|
disabled: composer.disabled && !retrying,
|
|
4461
4547
|
onClick: () => savedTranscript ? void transcription.insertSavedTranscript() : retrying ? transcription.cancel() : transcription.retry(),
|
|
4462
|
-
"aria-label": savedTranscript ? messages.insertRecoveredTranscript : retrying ? messages.pauseRetrying : messages.retry,
|
|
4548
|
+
"aria-label": savedTranscript ? messages.insertRecoveredTranscript : retrying ? messages.pauseRetrying : status === "recovered" ? messages.transcribeSaved : messages.retry,
|
|
4463
4549
|
className: cn(
|
|
4464
4550
|
"inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm",
|
|
4465
4551
|
"border border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover transition-colors duration-150 motion-reduce:transition-none",
|
|
@@ -4520,7 +4606,15 @@ function ComposerTranscriptionControl({
|
|
|
4520
4606
|
stream: status === "recording" ? transcription.stream : null,
|
|
4521
4607
|
mode: status === "recording" ? "recording" : "transcribing"
|
|
4522
4608
|
}
|
|
4523
|
-
)
|
|
4609
|
+
),
|
|
4610
|
+
status === "recording" && transcription.recordingStartedAt !== null ? /* @__PURE__ */ jsx4(
|
|
4611
|
+
RecordingClock,
|
|
4612
|
+
{
|
|
4613
|
+
startedAt: transcription.recordingStartedAt,
|
|
4614
|
+
maxSeconds: transcription.maxRecordingSeconds,
|
|
4615
|
+
remainingLabel: messages.timeRemaining
|
|
4616
|
+
}
|
|
4617
|
+
) : null
|
|
4524
4618
|
] }),
|
|
4525
4619
|
status === "recording" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
4526
4620
|
/* @__PURE__ */ jsx4(Tip, { tip: messages.cancel, children: /* @__PURE__ */ jsx4(
|
|
@@ -4577,14 +4671,26 @@ function ComposerTranscriptionControl({
|
|
|
4577
4671
|
children: /* @__PURE__ */ jsx4(MicIcon, { className: "size-4" })
|
|
4578
4672
|
}
|
|
4579
4673
|
) }, "idle") }),
|
|
4580
|
-
status === "error" && errorMessage && !recoverable ?
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
"
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4674
|
+
status === "error" && errorMessage && !recoverable ? (
|
|
4675
|
+
// Nothing is saved in this state, so dismissing loses no speech.
|
|
4676
|
+
/* @__PURE__ */ jsxs4(
|
|
4677
|
+
"button",
|
|
4678
|
+
{
|
|
4679
|
+
type: "button",
|
|
4680
|
+
title: errorMessage,
|
|
4681
|
+
"aria-label": `Dismiss: ${errorMessage}`,
|
|
4682
|
+
onClick: () => void transcription.discard(),
|
|
4683
|
+
className: cn(
|
|
4684
|
+
"inline-flex min-w-0 items-center gap-1 rounded-og-sm text-left outline-hidden",
|
|
4685
|
+
"text-og-status-failed focus-visible:ring-2 focus-visible:ring-og-accent/45"
|
|
4686
|
+
),
|
|
4687
|
+
children: [
|
|
4688
|
+
/* @__PURE__ */ jsx4("span", { className: "og-transcription-error-label max-w-56 line-clamp-2 text-og-xs leading-tight max-sm:max-w-32", children: errorMessage }),
|
|
4689
|
+
/* @__PURE__ */ jsx4(XIcon2, { className: "size-3 shrink-0 opacity-70", "aria-hidden": true })
|
|
4690
|
+
]
|
|
4691
|
+
}
|
|
4692
|
+
)
|
|
4693
|
+
) : null,
|
|
4588
4694
|
/* @__PURE__ */ jsx4(
|
|
4589
4695
|
"span",
|
|
4590
4696
|
{
|
|
@@ -4599,6 +4705,36 @@ function ComposerTranscriptionControl({
|
|
|
4599
4705
|
"composer-dictate"
|
|
4600
4706
|
) });
|
|
4601
4707
|
}
|
|
4708
|
+
function RecordingClock({
|
|
4709
|
+
startedAt,
|
|
4710
|
+
maxSeconds,
|
|
4711
|
+
remainingLabel
|
|
4712
|
+
}) {
|
|
4713
|
+
const [now, setNow] = useState5(() => Date.now());
|
|
4714
|
+
useEffect4(() => {
|
|
4715
|
+
const timer = setInterval(() => setNow(Date.now()), 500);
|
|
4716
|
+
return () => clearInterval(timer);
|
|
4717
|
+
}, []);
|
|
4718
|
+
const elapsed = Math.max(0, Math.floor((now - startedAt) / 1e3));
|
|
4719
|
+
const remaining = maxSeconds === null ? null : Math.max(0, maxSeconds - elapsed);
|
|
4720
|
+
const warn = remaining !== null && remaining <= 15;
|
|
4721
|
+
const label = `${Math.floor(elapsed / 60)}:${String(elapsed % 60).padStart(2, "0")}`;
|
|
4722
|
+
return /* @__PURE__ */ jsxs4(
|
|
4723
|
+
"span",
|
|
4724
|
+
{
|
|
4725
|
+
"data-recording-clock": true,
|
|
4726
|
+
title: warn ? remainingLabel.replace("{seconds}", String(remaining)) : void 0,
|
|
4727
|
+
className: cn(
|
|
4728
|
+
"min-w-[2.25rem] text-right text-og-xs tabular-nums",
|
|
4729
|
+
warn ? "font-medium text-og-status-failed" : "text-og-fg-muted"
|
|
4730
|
+
),
|
|
4731
|
+
children: [
|
|
4732
|
+
label,
|
|
4733
|
+
warn ? /* @__PURE__ */ jsx4("span", { className: "sr-only", children: remainingLabel.replace("{seconds}", String(remaining)) }) : null
|
|
4734
|
+
]
|
|
4735
|
+
}
|
|
4736
|
+
);
|
|
4737
|
+
}
|
|
4602
4738
|
function VoiceWaveform({
|
|
4603
4739
|
stream,
|
|
4604
4740
|
mode
|
|
@@ -4773,4 +4909,4 @@ export {
|
|
|
4773
4909
|
useVoiceInput,
|
|
4774
4910
|
ComposerTranscriptionControl
|
|
4775
4911
|
};
|
|
4776
|
-
//# sourceMappingURL=chunk-
|
|
4912
|
+
//# sourceMappingURL=chunk-IUHHPMAX.js.map
|