@exode-team/react-recorder 1.1.7 → 1.1.9
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/dist/components/AudioRecorder.d.ts +1 -1
- package/dist/components/AudioRecorder.d.ts.map +1 -1
- package/dist/components/RecordingShell/RecordingShell.d.ts +1 -0
- package/dist/components/RecordingShell/RecordingShell.d.ts.map +1 -1
- package/dist/components/RecordingShell/RecordingShell.styled.d.ts +0 -2
- package/dist/components/RecordingShell/RecordingShell.styled.d.ts.map +1 -1
- package/dist/components/VoiceMessagePlayer/VoiceMessagePlayer.d.ts +1 -0
- package/dist/components/VoiceMessagePlayer/VoiceMessagePlayer.d.ts.map +1 -1
- package/dist/components/WaveformBars/WaveformBars.d.ts +4 -0
- package/dist/components/WaveformBars/WaveformBars.d.ts.map +1 -1
- package/dist/components/WaveformBars/WaveformBars.styled.d.ts +3 -0
- package/dist/components/WaveformBars/WaveformBars.styled.d.ts.map +1 -0
- package/dist/hooks/useAudioRecorderHandlers.d.ts.map +1 -1
- package/dist/hooks/useMediaRecorder.d.ts.map +1 -1
- package/dist/hooks/useRecordingSender.d.ts +2 -1
- package/dist/hooks/useRecordingSender.d.ts.map +1 -1
- package/dist/hooks/useRecordingTiming.d.ts +2 -0
- package/dist/hooks/useRecordingTiming.d.ts.map +1 -1
- package/dist/hooks/useVoiceMessagePlayer.d.ts.map +1 -1
- package/dist/hooks/useVoiceRecorder.d.ts.map +1 -1
- package/dist/hooks/useVoiceRecorderInput.d.ts +1 -1
- package/dist/hooks/useVoiceRecorderInput.d.ts.map +1 -1
- package/dist/index.cjs +149 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +149 -54
- package/dist/index.js.map +1 -1
- package/dist/types/recorder.d.ts +10 -2
- package/dist/types/recorder.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -12,7 +12,7 @@ interface Props extends Partial<RecorderOptionOverrides> {
|
|
|
12
12
|
uploadId?: string;
|
|
13
13
|
className?: string;
|
|
14
14
|
onUploadError?: (error: unknown) => void;
|
|
15
|
-
onUploaded?: (file: Partial<StorageFileEntity
|
|
15
|
+
onUploaded?: (file: Partial<StorageFileEntity>, duration: number) => void | Promise<void>;
|
|
16
16
|
}
|
|
17
17
|
declare const AudioRecorder: (props: Props) => any;
|
|
18
18
|
export { AudioRecorder };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioRecorder.d.ts","sourceRoot":"","sources":["../../src/components/AudioRecorder.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAErF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC/B,MAAM,UAAU,CAAC;AAGlB,KAAK,uBAAuB,GAAG,IAAI,CAC/B,uBAAuB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EACnD,UAAU,GAAG,YAAY,GAAG,UAAU,CACzC,CAAC;AAEF,UAAU,KAAM,SAAQ,OAAO,CAAC,uBAAuB,CAAC;IACpD,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"AudioRecorder.d.ts","sourceRoot":"","sources":["../../src/components/AudioRecorder.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAErF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC/B,MAAM,UAAU,CAAC;AAGlB,KAAK,uBAAuB,GAAG,IAAI,CAC/B,uBAAuB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EACnD,UAAU,GAAG,YAAY,GAAG,UAAU,CACzC,CAAC;AAEF,UAAU,KAAM,SAAQ,OAAO,CAAC,uBAAuB,CAAC;IACpD,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7F;AAGD,QAAA,MAAM,aAAa,GAAI,OAAO,KAAK,QAwHlC,CAAC;AAGF,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordingShell.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA2BH,UAAU,KAAK;IACX,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3C;AAGD,QAAA,MAAM,cAAc,GAAI,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"RecordingShell.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA2BH,UAAU,KAAK;IACX,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3C;AAGD,QAAA,MAAM,cAAc,GAAI,OAAO,KAAK,QA+JnC,CAAC;AAGF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -8,8 +8,6 @@ export declare const CancelButton: any;
|
|
|
8
8
|
export declare const Track: any;
|
|
9
9
|
export declare const CircleButton: any;
|
|
10
10
|
export declare const Waveform: any;
|
|
11
|
-
export declare const Bars: any;
|
|
12
|
-
export declare const Bar: any;
|
|
13
11
|
export declare const Timer: any;
|
|
14
12
|
export declare const SendButton: any;
|
|
15
13
|
export declare const SpinnerSlot: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordingShell.styled.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,OAAO,KAOnB,CAAC;AAEF,eAAO,MAAM,YAAY,KAqBxB,CAAC;AAEF,eAAO,MAAM,KAAK,KAQjB,CAAC;AAEF,eAAO,MAAM,YAAY,KA2CxB,CAAC;AAEF,eAAO,MAAM,QAAQ,KAOpB,CAAC;AAEF,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"RecordingShell.styled.d.ts","sourceRoot":"","sources":["../../../src/components/RecordingShell/RecordingShell.styled.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,OAAO,KAOnB,CAAC;AAEF,eAAO,MAAM,YAAY,KAqBxB,CAAC;AAEF,eAAO,MAAM,KAAK,KAQjB,CAAC;AAEF,eAAO,MAAM,YAAY,KA2CxB,CAAC;AAEF,eAAO,MAAM,QAAQ,KAOpB,CAAC;AAEF,eAAO,MAAM,KAAK,KAKjB,CAAC;AAEF,eAAO,MAAM,UAAU,KAyBtB,CAAC;AAEF,eAAO,MAAM,WAAW,KAMvB,CAAC;AAEF,eAAO,MAAM,OAAO,KAoBnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoiceMessagePlayer.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceMessagePlayer/VoiceMessagePlayer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"VoiceMessagePlayer.d.ts","sourceRoot":"","sources":["../../../src/components/VoiceMessagePlayer/VoiceMessagePlayer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAeD,QAAA,MAAM,kBAAkB,KAuNtB,CAAC;AAGH,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -8,11 +8,15 @@ interface Props {
|
|
|
8
8
|
scale?: number;
|
|
9
9
|
divider?: number;
|
|
10
10
|
values: number[];
|
|
11
|
+
progress?: number;
|
|
11
12
|
minHeight?: number;
|
|
12
13
|
styleInterpolator?: (context: {
|
|
13
14
|
normalized: number;
|
|
14
15
|
height: number;
|
|
15
16
|
index: number;
|
|
17
|
+
progress: number;
|
|
18
|
+
barProgress: number;
|
|
19
|
+
isPlayed: boolean;
|
|
16
20
|
}) => React.CSSProperties;
|
|
17
21
|
}
|
|
18
22
|
declare const WaveformBars: (props: Props) => any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WaveformBars.d.ts","sourceRoot":"","sources":["../../../src/components/WaveformBars/WaveformBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,UAAU,KAAK;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"WaveformBars.d.ts","sourceRoot":"","sources":["../../../src/components/WaveformBars/WaveformBars.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,UAAU,KAAK;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC;KACrB,KAAK,KAAK,CAAC,aAAa,CAAC;CAC7B;AAGD,QAAA,MAAM,YAAY,GAAI,OAAO,KAAK,QAoCjC,CAAC;AAGF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WaveformBars.styled.d.ts","sourceRoot":"","sources":["../../../src/components/WaveformBars/WaveformBars.styled.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,IAAI,KAMhB,CAAC;AAEF,eAAO,MAAM,GAAG,KAOf,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioRecorderHandlers.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioRecorderHandlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAG7E,UAAU,+BAA+B;IACrC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAGD,QAAA,MAAM,wBAAwB,GAAI,SAAS,+BAA+B;;;;;;
|
|
1
|
+
{"version":3,"file":"useAudioRecorderHandlers.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioRecorderHandlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAG7E,UAAU,+BAA+B;IACrC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAGD,QAAA,MAAM,wBAAwB,GAAI,SAAS,+BAA+B;;;;;;CAuKzE,CAAC;AAGF,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMediaRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useMediaRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGvD,UAAU,sBAAsB;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,QAAA,MAAM,gBAAgB,GAAI,WAAW,sBAAsB,KAAG,
|
|
1
|
+
{"version":3,"file":"useMediaRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useMediaRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGvD,UAAU,sBAAsB;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,QAAA,MAAM,gBAAgB,GAAI,WAAW,sBAAsB,KAAG,sBAsI7D,CAAC;AAGF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -9,8 +9,9 @@ interface UseRecordingSenderOptions<TFile> {
|
|
|
9
9
|
mimeType: string;
|
|
10
10
|
audioBlob: Blob | null;
|
|
11
11
|
uploadId: string;
|
|
12
|
+
getDurationMs: () => number;
|
|
12
13
|
uploader?: UploadStrategy<TFile>;
|
|
13
|
-
onUploaded: (file: TFile) => void | Promise<void>;
|
|
14
|
+
onUploaded: (file: TFile, duration: number) => void | Promise<void>;
|
|
14
15
|
deleteRecording: () => void;
|
|
15
16
|
autoResetAfterUpload: boolean;
|
|
16
17
|
onRecordingError?: (error: unknown) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRecordingSender.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingSender.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,yBAAyB,CAAC,KAAK;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IACjC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"useRecordingSender.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingSender.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,yBAAyB,CAAC,KAAK;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IACjC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAGD,QAAA,MAAM,kBAAkB,GAAI,KAAK,GAAG,OAAO,EAAE,SAAS,yBAAyB,CAAC,KAAK,CAAC;;CA+DrF,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRecordingTiming.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingTiming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,wBAAwB;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,kBAAkB,QAAO,
|
|
1
|
+
{"version":3,"file":"useRecordingTiming.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecordingTiming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,wBAAwB;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,kBAAkB,QAAO,wBAwG9B,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVoiceMessagePlayer.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceMessagePlayer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAG1F,QAAA,MAAM,qBAAqB,GAAI,SAAS,4BAA4B,KAAG,
|
|
1
|
+
{"version":3,"file":"useVoiceMessagePlayer.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceMessagePlayer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAG1F,QAAA,MAAM,qBAAqB,GAAI,SAAS,4BAA4B,KAAG,2BAqMtE,CAAC;AAGF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVoiceRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGhF,iBAAS,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,uBAAuB,CAAC,KAAK,CAAC,GAAG,sBAAsB,
|
|
1
|
+
{"version":3,"file":"useVoiceRecorder.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGhF,iBAAS,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,uBAAuB,CAAC,KAAK,CAAC,GAAG,sBAAsB,CA2MxG;AAGD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { UploadStrategy } from '../types';
|
|
7
7
|
interface UseVoiceRecorderInputOptions {
|
|
8
8
|
uploader?: UploadStrategy<unknown>;
|
|
9
|
-
onUploaded?: (file: unknown) => void | Promise<void>;
|
|
9
|
+
onUploaded?: (file: unknown, duration: number) => void | Promise<void>;
|
|
10
10
|
onSend?: (file: File, duration: number) => void | Promise<void>;
|
|
11
11
|
onError?: (error: unknown) => void;
|
|
12
12
|
onCancel?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVoiceRecorderInput.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorderInput.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,4BAA4B;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"useVoiceRecorderInput.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceRecorderInput.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,4BAA4B;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAGD,QAAA,MAAM,qBAAqB,GAAI,SAAS,4BAA4B;;;;;;;;;;CA6MnE,CAAC;AAGF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -276,6 +276,9 @@ const useMediaRecorder = (callbacks) => {
|
|
|
276
276
|
if (!mediaRecorderRef.current || !isRecording) {
|
|
277
277
|
return;
|
|
278
278
|
}
|
|
279
|
+
if (mediaRecorderRef.current.state === 'paused') {
|
|
280
|
+
mediaRecorderRef.current.resume();
|
|
281
|
+
}
|
|
279
282
|
mediaRecorderRef.current.stop();
|
|
280
283
|
}, [isRecording]);
|
|
281
284
|
const cancelRecording = React.useCallback(() => {
|
|
@@ -434,6 +437,7 @@ const useAudioPlayback = () => {
|
|
|
434
437
|
* @author: exode <hello@exode.ru>
|
|
435
438
|
*/
|
|
436
439
|
const useRecordingTiming = () => {
|
|
440
|
+
const [lastDuration, setLastDuration] = React.useState(0);
|
|
437
441
|
const [recordingTime, setRecordingTime] = React.useState(0);
|
|
438
442
|
const timerRef = React.useRef(null);
|
|
439
443
|
const recordingStartRef = React.useRef(null);
|
|
@@ -461,6 +465,7 @@ const useRecordingTiming = () => {
|
|
|
461
465
|
const startNewSession = React.useCallback(() => {
|
|
462
466
|
recordingAccumulatedRef.current = 0;
|
|
463
467
|
setRecordingTime(0);
|
|
468
|
+
setLastDuration(0);
|
|
464
469
|
recordingStartRef.current = performance.now();
|
|
465
470
|
startTicker();
|
|
466
471
|
}, [startTicker]);
|
|
@@ -478,7 +483,21 @@ const useRecordingTiming = () => {
|
|
|
478
483
|
setRecordingTime(roundTo(recordingAccumulatedRef.current));
|
|
479
484
|
stopTicker();
|
|
480
485
|
}, [stopTicker]);
|
|
486
|
+
const getElapsedMs = React.useCallback(() => {
|
|
487
|
+
const accumulated = recordingAccumulatedRef.current;
|
|
488
|
+
const elapsed = recordingStartRef.current !== null
|
|
489
|
+
? (performance.now() - recordingStartRef.current) / 1000 + accumulated
|
|
490
|
+
: accumulated;
|
|
491
|
+
return Math.round(elapsed * 1000);
|
|
492
|
+
}, []);
|
|
481
493
|
const resetSession = React.useCallback(() => {
|
|
494
|
+
const accumulated = recordingAccumulatedRef.current;
|
|
495
|
+
const elapsed = recordingStartRef.current !== null
|
|
496
|
+
? (performance.now() - recordingStartRef.current) / 1000 + accumulated
|
|
497
|
+
: accumulated;
|
|
498
|
+
if (elapsed > 0) {
|
|
499
|
+
setLastDuration(roundTo(elapsed));
|
|
500
|
+
}
|
|
482
501
|
stopTicker();
|
|
483
502
|
recordingStartRef.current = null;
|
|
484
503
|
recordingAccumulatedRef.current = 0;
|
|
@@ -490,6 +509,8 @@ const useRecordingTiming = () => {
|
|
|
490
509
|
};
|
|
491
510
|
}, [stopTicker]);
|
|
492
511
|
return {
|
|
512
|
+
lastDuration,
|
|
513
|
+
getElapsedMs,
|
|
493
514
|
pauseSession,
|
|
494
515
|
resetSession,
|
|
495
516
|
recordingTime,
|
|
@@ -591,7 +612,7 @@ const useRecorderVisualization = () => {
|
|
|
591
612
|
* @author: exode <hello@exode.ru>
|
|
592
613
|
*/
|
|
593
614
|
const useRecordingSender = (options) => {
|
|
594
|
-
const { uploader, fileName, mimeType, uploadId, audioBlob, onUploaded, onRecordingError, deleteRecording, autoResetAfterUpload, } = options;
|
|
615
|
+
const { uploader, fileName, mimeType, uploadId, audioBlob, onUploaded, getDurationMs, onRecordingError, deleteRecording, autoResetAfterUpload, } = options;
|
|
595
616
|
const sendRecording = React.useCallback(async () => {
|
|
596
617
|
if (!audioBlob) {
|
|
597
618
|
const error = new Error('Voice recording is not available');
|
|
@@ -604,11 +625,13 @@ const useRecordingSender = (options) => {
|
|
|
604
625
|
throw error;
|
|
605
626
|
}
|
|
606
627
|
try {
|
|
628
|
+
const durationMs = getDurationMs();
|
|
629
|
+
const durationSec = durationMs / 1000;
|
|
607
630
|
const file = new File([audioBlob], fileName, {
|
|
608
631
|
type: audioBlob.type || mimeType,
|
|
609
632
|
});
|
|
610
633
|
const uploaded = await uploader(file, { uploadId });
|
|
611
|
-
await onUploaded(uploaded);
|
|
634
|
+
await onUploaded(uploaded, durationSec);
|
|
612
635
|
if (autoResetAfterUpload) {
|
|
613
636
|
deleteRecording();
|
|
614
637
|
}
|
|
@@ -624,8 +647,9 @@ const useRecordingSender = (options) => {
|
|
|
624
647
|
audioBlob,
|
|
625
648
|
mimeType,
|
|
626
649
|
onUploaded,
|
|
627
|
-
|
|
650
|
+
getDurationMs,
|
|
628
651
|
deleteRecording,
|
|
652
|
+
onRecordingError,
|
|
629
653
|
autoResetAfterUpload,
|
|
630
654
|
]);
|
|
631
655
|
return { sendRecording };
|
|
@@ -641,7 +665,7 @@ function useVoiceRecorder(props) {
|
|
|
641
665
|
const [audioBlob, setAudioBlob] = React.useState(null);
|
|
642
666
|
const { audioURL, isPlaying, mountBlob, playbackTime, stopPlayback, resetPlayback, togglePlayback: _togglePlayback, playbackDuration, } = useAudioPlayback();
|
|
643
667
|
const { audioLevels, previewLevels, resetAudioLevels, stopVisualization, resetPreviewLevels, resumeVisualization, cleanupVisualization, generatePreviewLevels, initializeVisualization, } = useRecorderVisualization();
|
|
644
|
-
const { recordingTime, pauseSession, resetSession, resumeSession, startNewSession, } = useRecordingTiming();
|
|
668
|
+
const { lastDuration, getElapsedMs, recordingTime, pauseSession, resetSession, resumeSession, startNewSession, } = useRecordingTiming();
|
|
645
669
|
const resetCurrentRecording = React.useCallback((opts) => {
|
|
646
670
|
var _a;
|
|
647
671
|
setAudioBlob(null);
|
|
@@ -669,10 +693,11 @@ function useVoiceRecorder(props) {
|
|
|
669
693
|
mimeType,
|
|
670
694
|
uploadId,
|
|
671
695
|
uploader,
|
|
672
|
-
autoResetAfterUpload,
|
|
673
696
|
onUploaded,
|
|
674
|
-
onRecordingError,
|
|
675
697
|
deleteRecording,
|
|
698
|
+
onRecordingError,
|
|
699
|
+
autoResetAfterUpload,
|
|
700
|
+
getDurationMs: getElapsedMs,
|
|
676
701
|
});
|
|
677
702
|
const mountRecordingBlob = React.useCallback((blob) => {
|
|
678
703
|
setAudioBlob(blob);
|
|
@@ -755,6 +780,7 @@ function useVoiceRecorder(props) {
|
|
|
755
780
|
isPlaying,
|
|
756
781
|
isRecording,
|
|
757
782
|
audioLevels,
|
|
783
|
+
lastDuration,
|
|
758
784
|
playbackTime,
|
|
759
785
|
recordingTime,
|
|
760
786
|
previewLevels,
|
|
@@ -1019,15 +1045,44 @@ const useVoiceMessagePlayer = (options) => {
|
|
|
1019
1045
|
setIsPlaying(false);
|
|
1020
1046
|
}
|
|
1021
1047
|
}, [isLoading, stopThis, audioRef]);
|
|
1022
|
-
const seekTo = React.useCallback((
|
|
1048
|
+
const seekTo = React.useCallback((seekPercent) => {
|
|
1023
1049
|
const audio = audioRef.current;
|
|
1024
1050
|
if (!audio || !isFinite(audio.duration)) {
|
|
1025
1051
|
return;
|
|
1026
1052
|
}
|
|
1027
|
-
const time =
|
|
1053
|
+
const time = seekPercent * audio.duration;
|
|
1028
1054
|
audio.currentTime = time;
|
|
1029
1055
|
setCurrentTime(time);
|
|
1030
1056
|
}, [audioRef]);
|
|
1057
|
+
/** Seek to a specific time in seconds and start playback */
|
|
1058
|
+
const seekToTime = React.useCallback((seconds) => {
|
|
1059
|
+
const audio = audioRef.current;
|
|
1060
|
+
if (audio && isFinite(audio.duration)) {
|
|
1061
|
+
audioPlaybackManager.stopOthers(stopThis);
|
|
1062
|
+
audio.currentTime = Math.max(0, Math.min(seconds, audio.duration));
|
|
1063
|
+
setCurrentTime(audio.currentTime);
|
|
1064
|
+
audio.play()
|
|
1065
|
+
.then(() => setIsPlaying(true))
|
|
1066
|
+
.catch(() => setIsPlaying(false));
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
1069
|
+
void ensureAudioLoaded().then(() => {
|
|
1070
|
+
const loadedAudio = audioRef.current;
|
|
1071
|
+
if (loadedAudio) {
|
|
1072
|
+
audioPlaybackManager.stopOthers(stopThis);
|
|
1073
|
+
loadedAudio.currentTime = Math.max(0, Math.min(seconds, loadedAudio.duration || seconds));
|
|
1074
|
+
setCurrentTime(loadedAudio.currentTime);
|
|
1075
|
+
loadedAudio.play()
|
|
1076
|
+
.then(() => setIsPlaying(true))
|
|
1077
|
+
.catch(() => setIsPlaying(false));
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
}, [
|
|
1082
|
+
audioRef,
|
|
1083
|
+
stopThis,
|
|
1084
|
+
ensureAudioLoaded,
|
|
1085
|
+
]);
|
|
1031
1086
|
/** Sync external duration */
|
|
1032
1087
|
React.useEffect(() => {
|
|
1033
1088
|
if (externalDuration) {
|
|
@@ -1044,6 +1099,7 @@ const useVoiceMessagePlayer = (options) => {
|
|
|
1044
1099
|
currentTime,
|
|
1045
1100
|
waveformLevels,
|
|
1046
1101
|
seekTo,
|
|
1102
|
+
seekToTime,
|
|
1047
1103
|
prefetch,
|
|
1048
1104
|
preload,
|
|
1049
1105
|
formatTime,
|
|
@@ -1101,9 +1157,6 @@ const useAudioRecorderHandlers = (options) => {
|
|
|
1101
1157
|
toggleRecordingPause,
|
|
1102
1158
|
]);
|
|
1103
1159
|
const handleSend = React.useCallback(async () => {
|
|
1104
|
-
if (isSending) {
|
|
1105
|
-
return;
|
|
1106
|
-
}
|
|
1107
1160
|
shouldSendAfterStopRef.current = false;
|
|
1108
1161
|
setIsSending(true);
|
|
1109
1162
|
try {
|
|
@@ -1120,7 +1173,6 @@ const useAudioRecorderHandlers = (options) => {
|
|
|
1120
1173
|
setIsSending(false);
|
|
1121
1174
|
}
|
|
1122
1175
|
}, [
|
|
1123
|
-
isSending,
|
|
1124
1176
|
stopPlayback,
|
|
1125
1177
|
onUploadError,
|
|
1126
1178
|
sendRecording,
|
|
@@ -1131,6 +1183,7 @@ const useAudioRecorderHandlers = (options) => {
|
|
|
1131
1183
|
return;
|
|
1132
1184
|
}
|
|
1133
1185
|
if (isRecording) {
|
|
1186
|
+
setIsSending(true);
|
|
1134
1187
|
shouldSendAfterStopRef.current = true;
|
|
1135
1188
|
stopRecording();
|
|
1136
1189
|
return;
|
|
@@ -1268,6 +1321,44 @@ const IdleControl = (props) => {
|
|
|
1268
1321
|
return (jsxRuntime.jsxs(IdleWrapper, { children: [jsxRuntime.jsxs(IdleButton, { type: "button", onClick: onClick, "aria-label": startAriaLabel, children: [jsxRuntime.jsx(IdleButtonOutline, { "aria-hidden": true }), jsxRuntime.jsx(IdleButtonGlow, { "aria-hidden": true }), jsxRuntime.jsx(icons.Icon32Microphone, { height: 48, width: 48 })] }), jsxRuntime.jsx(IdleInstruction, { children: instruction })] }));
|
|
1269
1322
|
};
|
|
1270
1323
|
|
|
1324
|
+
const Bars = styled.div `
|
|
1325
|
+
position: absolute;
|
|
1326
|
+
inset: 0;
|
|
1327
|
+
display: flex;
|
|
1328
|
+
align-items: flex-end;
|
|
1329
|
+
gap: 3px;
|
|
1330
|
+
`;
|
|
1331
|
+
const Bar = styled.div `
|
|
1332
|
+
flex: 1;
|
|
1333
|
+
min-width: 2px;
|
|
1334
|
+
border-radius: 9999px;
|
|
1335
|
+
background: var(--white, #ffffff);
|
|
1336
|
+
opacity: 0.6;
|
|
1337
|
+
transition: height 120ms ease, opacity 120ms ease;
|
|
1338
|
+
`;
|
|
1339
|
+
|
|
1340
|
+
const WaveformBars = (props) => {
|
|
1341
|
+
const { values, progress, styleInterpolator, scale = 40, minHeight = 6, divider = 100, } = props;
|
|
1342
|
+
return (jsxRuntime.jsx(Bars, { children: values.map((value, index) => {
|
|
1343
|
+
const normalized = clampValue(value);
|
|
1344
|
+
const height = Math.max(minHeight, (normalized / divider) * scale);
|
|
1345
|
+
const barProgress = values.length > 1 ? index / (values.length - 1) : 0;
|
|
1346
|
+
const isPlayed = (progress !== null && progress !== void 0 ? progress : 0) > 0 && barProgress <= (progress !== null && progress !== void 0 ? progress : 0);
|
|
1347
|
+
const interpolated = styleInterpolator === null || styleInterpolator === void 0 ? void 0 : styleInterpolator({
|
|
1348
|
+
normalized,
|
|
1349
|
+
height,
|
|
1350
|
+
index,
|
|
1351
|
+
progress: progress !== null && progress !== void 0 ? progress : 0,
|
|
1352
|
+
barProgress,
|
|
1353
|
+
isPlayed,
|
|
1354
|
+
});
|
|
1355
|
+
return (jsxRuntime.jsx(Bar, { style: {
|
|
1356
|
+
height: `${height}px`,
|
|
1357
|
+
...interpolated,
|
|
1358
|
+
} }, index));
|
|
1359
|
+
}) }));
|
|
1360
|
+
};
|
|
1361
|
+
|
|
1271
1362
|
/**
|
|
1272
1363
|
* RecordingShell styles
|
|
1273
1364
|
*
|
|
@@ -1362,21 +1453,6 @@ const Waveform = styled.div `
|
|
|
1362
1453
|
align-items: center;
|
|
1363
1454
|
overflow: hidden;
|
|
1364
1455
|
`;
|
|
1365
|
-
const Bars = styled.div `
|
|
1366
|
-
position: absolute;
|
|
1367
|
-
inset: 0;
|
|
1368
|
-
display: flex;
|
|
1369
|
-
align-items: flex-end;
|
|
1370
|
-
gap: 3px;
|
|
1371
|
-
`;
|
|
1372
|
-
const Bar = styled.div `
|
|
1373
|
-
flex: 1;
|
|
1374
|
-
min-width: 2px;
|
|
1375
|
-
border-radius: 9999px;
|
|
1376
|
-
background: var(--white, #ffffff);
|
|
1377
|
-
opacity: 0.6;
|
|
1378
|
-
transition: height 120ms ease, opacity 120ms ease;
|
|
1379
|
-
`;
|
|
1380
1456
|
const Timer$1 = styled.span `
|
|
1381
1457
|
text-align: right;
|
|
1382
1458
|
font-size: 13px;
|
|
@@ -1438,31 +1514,33 @@ const Spinner = styled.span `
|
|
|
1438
1514
|
}
|
|
1439
1515
|
`;
|
|
1440
1516
|
|
|
1441
|
-
const WaveformBars = (props) => {
|
|
1442
|
-
const { values, styleInterpolator, scale = 40, minHeight = 6, divider = 100, } = props;
|
|
1443
|
-
return (jsxRuntime.jsx(Bars, { children: values.map((value, index) => {
|
|
1444
|
-
const normalized = clampValue(value);
|
|
1445
|
-
const height = Math.max(minHeight, (normalized / divider) * scale);
|
|
1446
|
-
const interpolated = styleInterpolator === null || styleInterpolator === void 0 ? void 0 : styleInterpolator({ normalized, height, index });
|
|
1447
|
-
return (jsxRuntime.jsx(Bar, { style: {
|
|
1448
|
-
height: `${height}px`,
|
|
1449
|
-
...interpolated,
|
|
1450
|
-
} }, index));
|
|
1451
|
-
}) }));
|
|
1452
|
-
};
|
|
1453
|
-
|
|
1454
1517
|
const RecordingShell = (props) => {
|
|
1455
1518
|
const { isPaused, isPlaying, isSending, isRecording, audioLevels, hasRecording, playbackTime, previewLevels, recordingTime, stopAriaLabel, playAriaLabel, sendAriaLabel, startAriaLabel, cancelAriaLabel, playbackDuration, pausePlaybackAriaLabel, pauseRecordingAriaLabel, resumeRecordingAriaLabel, onSend, onCancel, formatTime, onRecordToggle, onTogglePlayback, } = props;
|
|
1519
|
+
const { lastDuration } = props;
|
|
1520
|
+
const isPreview = !isRecording || isPaused;
|
|
1456
1521
|
const waveformValues = isRecording ? audioLevels : (hasRecording ? previewLevels : audioLevels);
|
|
1522
|
+
const effectiveDuration = recordingTime
|
|
1523
|
+
|| playbackDuration
|
|
1524
|
+
|| lastDuration
|
|
1525
|
+
|| 1;
|
|
1526
|
+
const progress = (isPreview && isPlaying)
|
|
1527
|
+
? Math.min(1, playbackTime / effectiveDuration)
|
|
1528
|
+
: 0;
|
|
1457
1529
|
const displayTime = React.useMemo(() => {
|
|
1458
|
-
if (
|
|
1530
|
+
if (isPlaying) {
|
|
1531
|
+
return formatTime(playbackTime);
|
|
1532
|
+
}
|
|
1533
|
+
if (isRecording && !isPaused) {
|
|
1534
|
+
return formatTime(recordingTime);
|
|
1535
|
+
}
|
|
1536
|
+
if (isRecording && isPaused) {
|
|
1459
1537
|
return formatTime(recordingTime);
|
|
1460
1538
|
}
|
|
1539
|
+
if (lastDuration > 0) {
|
|
1540
|
+
return formatTime(lastDuration);
|
|
1541
|
+
}
|
|
1461
1542
|
if (hasRecording) {
|
|
1462
|
-
if (
|
|
1463
|
-
return formatTime(playbackTime);
|
|
1464
|
-
}
|
|
1465
|
-
if (playbackDuration > 0) {
|
|
1543
|
+
if (playbackDuration > 0.5) {
|
|
1466
1544
|
return formatTime(playbackDuration);
|
|
1467
1545
|
}
|
|
1468
1546
|
if (recordingTime > 0) {
|
|
@@ -1470,7 +1548,17 @@ const RecordingShell = (props) => {
|
|
|
1470
1548
|
}
|
|
1471
1549
|
}
|
|
1472
1550
|
return formatTime(0);
|
|
1473
|
-
}, [
|
|
1551
|
+
}, [
|
|
1552
|
+
isPaused,
|
|
1553
|
+
isPlaying,
|
|
1554
|
+
formatTime,
|
|
1555
|
+
isRecording,
|
|
1556
|
+
lastDuration,
|
|
1557
|
+
hasRecording,
|
|
1558
|
+
playbackTime,
|
|
1559
|
+
recordingTime,
|
|
1560
|
+
playbackDuration,
|
|
1561
|
+
]);
|
|
1474
1562
|
const recordButtonDisabled = isSending;
|
|
1475
1563
|
const recordButtonIcon = !isRecording || isPaused
|
|
1476
1564
|
? jsxRuntime.jsx(icons.Icon16Microphone, { width: 24, height: 24 })
|
|
@@ -1488,10 +1576,13 @@ const RecordingShell = (props) => {
|
|
|
1488
1576
|
: jsxRuntime.jsx(icons.Icon16Play, { width: 24, height: 24 });
|
|
1489
1577
|
const playbackAria = isPlaying ? pausePlaybackAriaLabel : playAriaLabel;
|
|
1490
1578
|
const sendDisabled = isSending || (!hasRecording && !isRecording);
|
|
1491
|
-
return (jsxRuntime.jsxs(Wrapper$1, { children: [jsxRuntime.jsx(CancelButton$1, { type: "button", onClick: onCancel, "aria-label": cancelAriaLabel, children: jsxRuntime.jsx(icons.Icon28DeleteOutlineAndroid, { fill: "var(--exode_red)", width: 24, height: 24, style: { minWidth: 24 } }) }), jsxRuntime.jsxs(Track, { children: [jsxRuntime.jsx(CircleButton, { type: "button", "$variant": recordButtonVariant, onClick: onRecordToggle, "aria-label": recordButtonAria, disabled: recordButtonDisabled, children: recordButtonIcon }), !canShowPlayback ? null : (jsxRuntime.jsx(CircleButton, { type: "button", "$variant": "play", onClick: onTogglePlayback, "aria-label": playbackAria, disabled: playbackDisabled, children: playbackIcon })), jsxRuntime.jsx(Waveform, { "$expanded": canShowPlayback, children: jsxRuntime.jsx(WaveformBars, {
|
|
1579
|
+
return (jsxRuntime.jsxs(Wrapper$1, { children: [jsxRuntime.jsx(CancelButton$1, { type: "button", onClick: onCancel, "aria-label": cancelAriaLabel, children: jsxRuntime.jsx(icons.Icon28DeleteOutlineAndroid, { fill: "var(--exode_red)", width: 24, height: 24, style: { minWidth: 24 } }) }), jsxRuntime.jsxs(Track, { children: [jsxRuntime.jsx(CircleButton, { type: "button", "$variant": recordButtonVariant, onClick: onRecordToggle, "aria-label": recordButtonAria, disabled: recordButtonDisabled, children: recordButtonIcon }), !canShowPlayback ? null : (jsxRuntime.jsx(CircleButton, { type: "button", "$variant": "play", onClick: onTogglePlayback, "aria-label": playbackAria, disabled: playbackDisabled, children: playbackIcon })), jsxRuntime.jsx(Waveform, { "$expanded": canShowPlayback, children: jsxRuntime.jsx(WaveformBars, { scale: 42, minHeight: 6, divider: 100, progress: progress, values: waveformValues, styleInterpolator: ({ normalized, isPlayed, progress: p }) => ({
|
|
1492
1580
|
height: `${12 + normalized / 2}px`,
|
|
1493
1581
|
maxHeight: '34px',
|
|
1494
|
-
opacity:
|
|
1582
|
+
opacity: p > 0
|
|
1583
|
+
? (isPlayed ? 0.80 : 0.22)
|
|
1584
|
+
: 0.38 + Math.min(0.5, normalized / 120),
|
|
1585
|
+
transition: 'opacity 80ms ease',
|
|
1495
1586
|
}) }) }), jsxRuntime.jsx(Timer$1, { children: displayTime })] }), jsxRuntime.jsx(SendButton$1, { type: "button", onClick: onSend, disabled: sendDisabled, "aria-label": sendAriaLabel, children: isSending ? (jsxRuntime.jsx(SpinnerSlot, { children: jsxRuntime.jsx(Spinner, {}) })) : (jsxRuntime.jsx(icons.Icon28SendOutline, { width: 24, height: 24 })) })] }));
|
|
1496
1587
|
};
|
|
1497
1588
|
|
|
@@ -1574,9 +1665,9 @@ const AudioRecorder = (props) => {
|
|
|
1574
1665
|
messages,
|
|
1575
1666
|
onUploadError,
|
|
1576
1667
|
});
|
|
1577
|
-
const { isPaused, isPlaying, formatTime, audioLevels, isRecording, playbackTime, hasRecording, previewLevels, recordingTime, playbackDuration, } = recorder;
|
|
1578
|
-
const showRecorderBar = isRecording || hasRecording;
|
|
1579
|
-
return (jsxRuntime.jsx(Container, { className: className, children: showRecorderBar ? (jsxRuntime.jsx(RecordingShell, { isPaused: isPaused, isSending: isSending, isPlaying: isPlaying, formatTime: formatTime, onCancel: handleCancel, isRecording: isRecording, audioLevels: audioLevels, onSend: handleSendRequest, playbackTime: playbackTime, hasRecording: hasRecording, previewLevels: previewLevels, recordingTime: recordingTime, playbackDuration: playbackDuration, onRecordToggle: handleRecordToggle, sendAriaLabel: messages.buttons.send, onTogglePlayback: handlePlaybackToggle, cancelAriaLabel: messages.buttons.cancel, playAriaLabel: messages.aria.playRecording, stopAriaLabel: messages.aria.stopRecording, startAriaLabel: messages.aria.startRecording, pauseRecordingAriaLabel: messages.aria.pauseRecording, resumeRecordingAriaLabel: messages.aria.resumeRecording, pausePlaybackAriaLabel: messages.aria.pausePlayback })) : (jsxRuntime.jsx(IdleControl, { onClick: handleRecordToggle, startAriaLabel: messages.aria.startRecording, instruction: messages.instruction })) }));
|
|
1668
|
+
const { isPaused, isPlaying, formatTime, audioLevels, isRecording, lastDuration, playbackTime, hasRecording, previewLevels, recordingTime, playbackDuration, } = recorder;
|
|
1669
|
+
const showRecorderBar = isRecording || hasRecording || isSending;
|
|
1670
|
+
return (jsxRuntime.jsx(Container, { className: className, children: showRecorderBar ? (jsxRuntime.jsx(RecordingShell, { isPaused: isPaused, isSending: isSending, isPlaying: isPlaying, formatTime: formatTime, onCancel: handleCancel, isRecording: isRecording, audioLevels: audioLevels, onSend: handleSendRequest, playbackTime: playbackTime, lastDuration: lastDuration, hasRecording: hasRecording, previewLevels: previewLevels, recordingTime: recordingTime, playbackDuration: playbackDuration, onRecordToggle: handleRecordToggle, sendAriaLabel: messages.buttons.send, onTogglePlayback: handlePlaybackToggle, cancelAriaLabel: messages.buttons.cancel, playAriaLabel: messages.aria.playRecording, stopAriaLabel: messages.aria.stopRecording, startAriaLabel: messages.aria.startRecording, pauseRecordingAriaLabel: messages.aria.pauseRecording, resumeRecordingAriaLabel: messages.aria.resumeRecording, pausePlaybackAriaLabel: messages.aria.pausePlayback })) : (jsxRuntime.jsx(IdleControl, { onClick: handleRecordToggle, startAriaLabel: messages.aria.startRecording, instruction: messages.instruction })) }));
|
|
1580
1671
|
};
|
|
1581
1672
|
|
|
1582
1673
|
/**
|
|
@@ -2154,14 +2245,18 @@ const VoiceMessagePlayer = React.forwardRef((props, ref) => {
|
|
|
2154
2245
|
VoicePlaybackChain.playNext(chainId);
|
|
2155
2246
|
}
|
|
2156
2247
|
}, [onEnded, chainId]);
|
|
2157
|
-
const { play, progress, isLoaded, isPlaying, isLoading, currentTime, waveformLevels, seekTo, prefetch, preload, formatTime, togglePlayback, duration: resolvedDuration, } = useVoiceMessagePlayer({
|
|
2248
|
+
const { play, progress, isLoaded, isPlaying, isLoading, currentTime, waveformLevels, seekTo, seekToTime, prefetch, preload, formatTime, togglePlayback, duration: resolvedDuration, } = useVoiceMessagePlayer({
|
|
2158
2249
|
src,
|
|
2159
2250
|
duration,
|
|
2160
2251
|
waveformData,
|
|
2161
2252
|
preloadedBlob: props.preloadedBlob,
|
|
2162
2253
|
onEnded: handleEnded,
|
|
2163
2254
|
});
|
|
2164
|
-
React.useImperativeHandle(ref, () => ({ play, prefetch }), [
|
|
2255
|
+
React.useImperativeHandle(ref, () => ({ play, prefetch, seekToTime }), [
|
|
2256
|
+
play,
|
|
2257
|
+
prefetch,
|
|
2258
|
+
seekToTime,
|
|
2259
|
+
]);
|
|
2165
2260
|
/** Auto-preload audio when player enters viewport */
|
|
2166
2261
|
React.useEffect(() => {
|
|
2167
2262
|
if (!autoPreload || isLoaded || isLoading) {
|
|
@@ -2215,7 +2310,7 @@ const VoiceMessagePlayer = React.forwardRef((props, ref) => {
|
|
|
2215
2310
|
observer.disconnect();
|
|
2216
2311
|
};
|
|
2217
2312
|
}, []);
|
|
2218
|
-
const displayTime = isPlaying
|
|
2313
|
+
const displayTime = (isPlaying || currentTime > 0)
|
|
2219
2314
|
? formatTime(currentTime)
|
|
2220
2315
|
: formatTime(resolvedDuration);
|
|
2221
2316
|
const handleTrackClick = React.useCallback((e) => {
|