@exode-team/react-recorder 1.1.9 → 1.1.10
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/VoiceMessagePlayer/VoiceMessagePlayer.d.ts.map +1 -1
- package/dist/hooks/useAudioBlobLoader.d.ts.map +1 -1
- package/dist/hooks/useAudioPlayback.d.ts.map +1 -1
- package/dist/hooks/useVoiceMessagePlayer.d.ts.map +1 -1
- package/dist/index.cjs +116 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +116 -1
- package/dist/index.js.map +1 -1
- package/dist/platform/audio-playback-adapter.d.ts +7 -0
- package/dist/platform/audio-playback-adapter.d.ts.map +1 -1
- package/dist/types/recorder.d.ts +2 -0
- package/dist/types/recorder.d.ts.map +1 -1
- package/dist/utils/voice-playback-chain.d.ts +2 -0
- package/dist/utils/voice-playback-chain.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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;IACrB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAeD,QAAA,MAAM,kBAAkB,
|
|
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,KAqOtB,CAAC;AAGH,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioBlobLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioBlobLoader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,UAAU,yBAAyB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,iBAAiB,CAAC;CACxC;AAED,UAAU,wBAAwB;IAC9B,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,QAAA,MAAM,kBAAkB,GAAI,SAAS,yBAAyB,KAAG,
|
|
1
|
+
{"version":3,"file":"useAudioBlobLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioBlobLoader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,UAAU,yBAAyB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,iBAAiB,CAAC;CACxC;AAED,UAAU,wBAAwB;IAC9B,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,QAAA,MAAM,kBAAkB,GAAI,SAAS,yBAAyB,KAAG,wBA2IhE,CAAC;AAGF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioPlayback.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioPlayback.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,sBAAsB;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IAClC,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IAC7D,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACnC;AAED,QAAA,MAAM,gBAAgB,QAAO,
|
|
1
|
+
{"version":3,"file":"useAudioPlayback.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudioPlayback.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,UAAU,sBAAsB;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IAClC,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IAC7D,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACnC;AAED,QAAA,MAAM,gBAAgB,QAAO,sBA+H5B,CAAC;AAGF,OAAO,EAAE,gBAAgB,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,2BAmNtE,CAAC;AAGF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -78,6 +78,61 @@ const stopStream = (stream) => {
|
|
|
78
78
|
*
|
|
79
79
|
* @author: exode <hello@exode.ru>
|
|
80
80
|
*/
|
|
81
|
+
const SEEK_OFFSET = 5;
|
|
82
|
+
const setupMediaSession = (audio, callbacks) => {
|
|
83
|
+
if (!('mediaSession' in navigator)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
navigator.mediaSession.setActionHandler('play', () => {
|
|
87
|
+
audio.play().catch(() => { });
|
|
88
|
+
});
|
|
89
|
+
navigator.mediaSession.setActionHandler('pause', () => {
|
|
90
|
+
audio.pause();
|
|
91
|
+
});
|
|
92
|
+
navigator.mediaSession.setActionHandler('stop', () => {
|
|
93
|
+
var _a;
|
|
94
|
+
audio.pause();
|
|
95
|
+
audio.currentTime = 0;
|
|
96
|
+
(_a = callbacks.onStop) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
97
|
+
});
|
|
98
|
+
navigator.mediaSession.setActionHandler('seekbackward', () => {
|
|
99
|
+
var _a;
|
|
100
|
+
audio.currentTime = Math.max(0, audio.currentTime - SEEK_OFFSET);
|
|
101
|
+
(_a = callbacks.onSeekBackward) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
102
|
+
});
|
|
103
|
+
navigator.mediaSession.setActionHandler('seekforward', () => {
|
|
104
|
+
var _a;
|
|
105
|
+
audio.currentTime = Math.min(audio.duration, audio.currentTime + SEEK_OFFSET);
|
|
106
|
+
(_a = callbacks.onSeekForward) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
107
|
+
});
|
|
108
|
+
navigator.mediaSession.setActionHandler('seekto', (details) => {
|
|
109
|
+
if (details.seekTime != null && isFinite(audio.duration)) {
|
|
110
|
+
audio.currentTime = details.seekTime;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
|
114
|
+
var _a;
|
|
115
|
+
(_a = callbacks.onPreviousTrack) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
116
|
+
});
|
|
117
|
+
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
|
118
|
+
var _a;
|
|
119
|
+
(_a = callbacks.onNextTrack) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const clearMediaSession = () => {
|
|
123
|
+
if (!('mediaSession' in navigator)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const actions = [
|
|
127
|
+
'play', 'pause', 'stop',
|
|
128
|
+
'seekbackward', 'seekforward', 'seekto',
|
|
129
|
+
'previoustrack', 'nexttrack',
|
|
130
|
+
];
|
|
131
|
+
actions.forEach((action) => {
|
|
132
|
+
navigator.mediaSession.setActionHandler(action, null);
|
|
133
|
+
});
|
|
134
|
+
navigator.mediaSession.playbackState = 'none';
|
|
135
|
+
};
|
|
81
136
|
const createAudioPlayback = (url, callbacks) => {
|
|
82
137
|
const audio = new Audio(url);
|
|
83
138
|
audio.onloadedmetadata = () => {
|
|
@@ -89,6 +144,21 @@ const createAudioPlayback = (url, callbacks) => {
|
|
|
89
144
|
audio.onended = () => {
|
|
90
145
|
callbacks.onEnded();
|
|
91
146
|
};
|
|
147
|
+
audio.onplay = () => {
|
|
148
|
+
var _a;
|
|
149
|
+
setupMediaSession(audio, callbacks);
|
|
150
|
+
if ('mediaSession' in navigator) {
|
|
151
|
+
navigator.mediaSession.playbackState = 'playing';
|
|
152
|
+
}
|
|
153
|
+
(_a = callbacks.onPlay) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
154
|
+
};
|
|
155
|
+
audio.onpause = () => {
|
|
156
|
+
var _a;
|
|
157
|
+
if ('mediaSession' in navigator) {
|
|
158
|
+
navigator.mediaSession.playbackState = 'paused';
|
|
159
|
+
}
|
|
160
|
+
(_a = callbacks.onPause) === null || _a === void 0 ? void 0 : _a.call(callbacks);
|
|
161
|
+
};
|
|
92
162
|
return { audio, url };
|
|
93
163
|
};
|
|
94
164
|
const cleanupAudio = (audio) => {
|
|
@@ -97,6 +167,9 @@ const cleanupAudio = (audio) => {
|
|
|
97
167
|
audio.onended = null;
|
|
98
168
|
audio.ontimeupdate = null;
|
|
99
169
|
audio.onloadedmetadata = null;
|
|
170
|
+
audio.onplay = null;
|
|
171
|
+
audio.onpause = null;
|
|
172
|
+
clearMediaSession();
|
|
100
173
|
};
|
|
101
174
|
const createObjectURL = (blob) => {
|
|
102
175
|
return URL.createObjectURL(blob);
|
|
@@ -366,6 +439,8 @@ const useAudioPlayback = () => {
|
|
|
366
439
|
setIsPlaying(false);
|
|
367
440
|
setPlaybackTime(0);
|
|
368
441
|
},
|
|
442
|
+
onPlay: () => setIsPlaying(true),
|
|
443
|
+
onPause: () => setIsPlaying(false),
|
|
369
444
|
});
|
|
370
445
|
audioRef.current = audio;
|
|
371
446
|
setPlaybackTime(0);
|
|
@@ -385,6 +460,8 @@ const useAudioPlayback = () => {
|
|
|
385
460
|
setIsPlaying(false);
|
|
386
461
|
setPlaybackTime(0);
|
|
387
462
|
},
|
|
463
|
+
onPlay: () => setIsPlaying(true),
|
|
464
|
+
onPause: () => setIsPlaying(false),
|
|
388
465
|
});
|
|
389
466
|
audioRef.current = audio;
|
|
390
467
|
}
|
|
@@ -825,6 +902,13 @@ const useAudioBlobLoader = (options) => {
|
|
|
825
902
|
onLoadedMetadata: (dur) => callbacksRef.current.onLoadedMetadata(dur),
|
|
826
903
|
onTimeUpdate: (time) => callbacksRef.current.onTimeUpdate(time),
|
|
827
904
|
onEnded: () => callbacksRef.current.onEnded(),
|
|
905
|
+
onPlay: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onPlay) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
906
|
+
onPause: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onPause) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
907
|
+
onStop: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onStop) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
908
|
+
onSeekBackward: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onSeekBackward) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
909
|
+
onSeekForward: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onSeekForward) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
910
|
+
onPreviousTrack: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onPreviousTrack) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
911
|
+
onNextTrack: () => { var _a, _b; return (_b = (_a = callbacksRef.current).onNextTrack) === null || _b === void 0 ? void 0 : _b.call(_a); },
|
|
828
912
|
});
|
|
829
913
|
audioRef.current = audio;
|
|
830
914
|
setIsLoaded(true);
|
|
@@ -955,9 +1039,13 @@ const audioPlaybackManager = {
|
|
|
955
1039
|
* @author: exode <hello@exode.ru>
|
|
956
1040
|
*/
|
|
957
1041
|
const useVoiceMessagePlayer = (options) => {
|
|
958
|
-
const { src, onEnded, waveformData, preloadedBlob, duration: externalDuration, } = options;
|
|
1042
|
+
const { src, onEnded, onPreviousTrack, onNextTrack, waveformData, preloadedBlob, duration: externalDuration, } = options;
|
|
959
1043
|
const onEndedRef = React.useRef(onEnded);
|
|
1044
|
+
const onPreviousTrackRef = React.useRef(onPreviousTrack);
|
|
1045
|
+
const onNextTrackRef = React.useRef(onNextTrack);
|
|
960
1046
|
onEndedRef.current = onEnded;
|
|
1047
|
+
onPreviousTrackRef.current = onPreviousTrack;
|
|
1048
|
+
onNextTrackRef.current = onNextTrack;
|
|
961
1049
|
const [isPlaying, setIsPlaying] = React.useState(false);
|
|
962
1050
|
const [currentTime, setCurrentTime] = React.useState(0);
|
|
963
1051
|
const [duration, setDuration] = React.useState(externalDuration || 0);
|
|
@@ -991,6 +1079,14 @@ const useVoiceMessagePlayer = (options) => {
|
|
|
991
1079
|
setCurrentTime(0);
|
|
992
1080
|
(_a = onEndedRef.current) === null || _a === void 0 ? void 0 : _a.call(onEndedRef);
|
|
993
1081
|
},
|
|
1082
|
+
onPlay: () => setIsPlaying(true),
|
|
1083
|
+
onPause: () => setIsPlaying(false),
|
|
1084
|
+
onStop: () => {
|
|
1085
|
+
setIsPlaying(false);
|
|
1086
|
+
setCurrentTime(0);
|
|
1087
|
+
},
|
|
1088
|
+
onPreviousTrack: () => { var _a; return (_a = onPreviousTrackRef.current) === null || _a === void 0 ? void 0 : _a.call(onPreviousTrackRef); },
|
|
1089
|
+
onNextTrack: () => { var _a; return (_a = onNextTrackRef.current) === null || _a === void 0 ? void 0 : _a.call(onNextTrackRef); },
|
|
994
1090
|
},
|
|
995
1091
|
});
|
|
996
1092
|
/** Pre-fetch audio without playing (for viewport preloading) */
|
|
@@ -2138,6 +2234,13 @@ class VoicePlaybackChainClass {
|
|
|
2138
2234
|
this.entries[idx + 1].play();
|
|
2139
2235
|
}
|
|
2140
2236
|
};
|
|
2237
|
+
/** Play the previous voice message before the given media ID */
|
|
2238
|
+
this.playPrevious = (currentId) => {
|
|
2239
|
+
const idx = this.entries.findIndex((e) => e.id === currentId);
|
|
2240
|
+
if (idx > 0) {
|
|
2241
|
+
this.entries[idx - 1].play();
|
|
2242
|
+
}
|
|
2243
|
+
};
|
|
2141
2244
|
}
|
|
2142
2245
|
}
|
|
2143
2246
|
const VoicePlaybackChain = new VoicePlaybackChainClass();
|
|
@@ -2245,12 +2348,24 @@ const VoiceMessagePlayer = React.forwardRef((props, ref) => {
|
|
|
2245
2348
|
VoicePlaybackChain.playNext(chainId);
|
|
2246
2349
|
}
|
|
2247
2350
|
}, [onEnded, chainId]);
|
|
2351
|
+
const handleNextTrack = React.useCallback(() => {
|
|
2352
|
+
if (chainId != null) {
|
|
2353
|
+
VoicePlaybackChain.playNext(chainId);
|
|
2354
|
+
}
|
|
2355
|
+
}, [chainId]);
|
|
2356
|
+
const handlePreviousTrack = React.useCallback(() => {
|
|
2357
|
+
if (chainId != null) {
|
|
2358
|
+
VoicePlaybackChain.playPrevious(chainId);
|
|
2359
|
+
}
|
|
2360
|
+
}, [chainId]);
|
|
2248
2361
|
const { play, progress, isLoaded, isPlaying, isLoading, currentTime, waveformLevels, seekTo, seekToTime, prefetch, preload, formatTime, togglePlayback, duration: resolvedDuration, } = useVoiceMessagePlayer({
|
|
2249
2362
|
src,
|
|
2250
2363
|
duration,
|
|
2251
2364
|
waveformData,
|
|
2252
2365
|
preloadedBlob: props.preloadedBlob,
|
|
2253
2366
|
onEnded: handleEnded,
|
|
2367
|
+
onNextTrack: handleNextTrack,
|
|
2368
|
+
onPreviousTrack: handlePreviousTrack,
|
|
2254
2369
|
});
|
|
2255
2370
|
React.useImperativeHandle(ref, () => ({ play, prefetch, seekToTime }), [
|
|
2256
2371
|
play,
|