box-content-preview 3.91.0 → 3.93.0
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 +7 -7
- package/dist/lib/index.css +6 -4
- package/dist/lib/index.js +2044 -438
- package/package.json +5 -5
package/dist/lib/index.js
CHANGED
|
@@ -620,8 +620,8 @@ const VIEWER_EVENT = {
|
|
|
620
620
|
// When gallery view opens
|
|
621
621
|
load: 'load',
|
|
622
622
|
// Preview is finished loading.
|
|
623
|
-
|
|
624
|
-
// Media playback has completed, with
|
|
623
|
+
mediaEndPlayNext: 'mediaEndPlayNext',
|
|
624
|
+
// Media playback has completed, with play-next enabled.
|
|
625
625
|
metric: 'viewermetric',
|
|
626
626
|
// A viewer metric.
|
|
627
627
|
notificationHide: 'notificationhide',
|
|
@@ -1018,7 +1018,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
|
|
|
1018
1018
|
const CLIENT_NAME = "box-content-preview"; // eslint-disable-line no-undef
|
|
1019
1019
|
const CLIENT_NAME_KEY = 'box_client_name';
|
|
1020
1020
|
const CLIENT_VERSION_KEY = 'box_client_version';
|
|
1021
|
-
const CLIENT_VERSION = "3.
|
|
1021
|
+
const CLIENT_VERSION = "3.93.0"; // eslint-disable-line no-undef
|
|
1022
1022
|
const HEADER_CLIENT_NAME = 'X-Box-Client-Name';
|
|
1023
1023
|
const HEADER_CLIENT_VERSION = 'X-Box-Client-Version';
|
|
1024
1024
|
const PROMISE_MAP = {};
|
|
@@ -2143,7 +2143,7 @@ function DurationLabels({
|
|
|
2143
2143
|
|
|
2144
2144
|
/***/ },
|
|
2145
2145
|
|
|
2146
|
-
/***/
|
|
2146
|
+
/***/ 9229
|
|
2147
2147
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
2148
2148
|
|
|
2149
2149
|
|
|
@@ -2250,6 +2250,36 @@ function MediaSettingsMenuAutoplay({
|
|
|
2250
2250
|
}
|
|
2251
2251
|
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MediaSettingsMenuGuides.tsx
|
|
2252
2252
|
var MediaSettingsMenuGuides = __webpack_require__(4692);
|
|
2253
|
+
;// ./src/lib/viewers/controls/media/MediaSettingsMenuPlayNext.tsx
|
|
2254
|
+
|
|
2255
|
+
|
|
2256
|
+
function MediaSettingsMenuPlayNext({
|
|
2257
|
+
playNext,
|
|
2258
|
+
onPlayNextChange
|
|
2259
|
+
}) {
|
|
2260
|
+
const {
|
|
2261
|
+
setActiveMenu
|
|
2262
|
+
} = external_react_["default"].useContext(Settings/* default */.A.Context);
|
|
2263
|
+
const handleChange = value => {
|
|
2264
|
+
setActiveMenu(SettingsContext/* Menu */.W.MAIN);
|
|
2265
|
+
onPlayNextChange(value);
|
|
2266
|
+
};
|
|
2267
|
+
return /*#__PURE__*/external_react_["default"].createElement(Settings/* default */.A.Menu, {
|
|
2268
|
+
name: SettingsContext/* Menu */.W.PLAY_NEXT
|
|
2269
|
+
}, /*#__PURE__*/external_react_["default"].createElement(Settings/* default */.A.MenuBack, {
|
|
2270
|
+
label: "Play next file"
|
|
2271
|
+
}), /*#__PURE__*/external_react_["default"].createElement(Settings/* default */.A.RadioItem, {
|
|
2272
|
+
isSelected: !playNext,
|
|
2273
|
+
label: "Disabled",
|
|
2274
|
+
onChange: handleChange,
|
|
2275
|
+
value: false
|
|
2276
|
+
}), /*#__PURE__*/external_react_["default"].createElement(Settings/* default */.A.RadioItem, {
|
|
2277
|
+
isSelected: playNext,
|
|
2278
|
+
label: "Enabled",
|
|
2279
|
+
onChange: handleChange,
|
|
2280
|
+
value: true
|
|
2281
|
+
}));
|
|
2282
|
+
}
|
|
2253
2283
|
;// ./src/lib/viewers/controls/media/MediaSettingsMenuQuality.tsx
|
|
2254
2284
|
|
|
2255
2285
|
|
|
@@ -2402,6 +2432,7 @@ function MediaSettingsMenuSubtitles({
|
|
|
2402
2432
|
|
|
2403
2433
|
|
|
2404
2434
|
|
|
2435
|
+
|
|
2405
2436
|
function MediaSettings({
|
|
2406
2437
|
audioTrack,
|
|
2407
2438
|
audioTracks = [],
|
|
@@ -2416,7 +2447,9 @@ function MediaSettings({
|
|
|
2416
2447
|
onGuideChange = (noop_default()),
|
|
2417
2448
|
onQualityChange,
|
|
2418
2449
|
onRateChange,
|
|
2450
|
+
onPlayNextChange,
|
|
2419
2451
|
onSubtitleChange,
|
|
2452
|
+
playNext = false,
|
|
2420
2453
|
quality,
|
|
2421
2454
|
rate,
|
|
2422
2455
|
subtitle,
|
|
@@ -2425,7 +2458,9 @@ function MediaSettings({
|
|
|
2425
2458
|
}) {
|
|
2426
2459
|
const subtitleDisplayLanguage = getDisplayLanguage(subtitle, subtitles);
|
|
2427
2460
|
const autoValue = autoplay ? "Enabled" : "Disabled";
|
|
2461
|
+
const playNextValue = playNext ? "Enabled" : "Disabled";
|
|
2428
2462
|
const rateValue = rate === '1.0' || !rate ? "Normal" : rate;
|
|
2463
|
+
const showPlayNext = typeof onPlayNextChange === 'function';
|
|
2429
2464
|
const labelledAudioTracks = external_react_["default"].useMemo(() => addLabels(audioTracks), [audioTracks]);
|
|
2430
2465
|
const hydratedSelectedAudioTrack = labelledAudioTracks.find(({
|
|
2431
2466
|
id
|
|
@@ -2444,6 +2479,11 @@ function MediaSettings({
|
|
|
2444
2479
|
label: "Autoplay",
|
|
2445
2480
|
target: SettingsContext/* Menu */.W.AUTOPLAY,
|
|
2446
2481
|
value: autoValue
|
|
2482
|
+
}), showPlayNext && /*#__PURE__*/external_react_["default"].createElement(Settings/* default */.A.MenuItem, {
|
|
2483
|
+
"data-testid": "bp-media-settings-play-next",
|
|
2484
|
+
label: "Play next file",
|
|
2485
|
+
target: SettingsContext/* Menu */.W.PLAY_NEXT,
|
|
2486
|
+
value: playNextValue
|
|
2447
2487
|
}), /*#__PURE__*/external_react_["default"].createElement(Settings/* default */.A.MenuItem, {
|
|
2448
2488
|
"data-testid": "bp-media-settings-speed",
|
|
2449
2489
|
label: "Speed",
|
|
@@ -2473,6 +2513,9 @@ function MediaSettings({
|
|
|
2473
2513
|
})), /*#__PURE__*/external_react_["default"].createElement(MediaSettingsMenuAutoplay, {
|
|
2474
2514
|
autoplay: autoplay,
|
|
2475
2515
|
onAutoplayChange: onAutoplayChange
|
|
2516
|
+
}), showPlayNext && onPlayNextChange && /*#__PURE__*/external_react_["default"].createElement(MediaSettingsMenuPlayNext, {
|
|
2517
|
+
onPlayNextChange: onPlayNextChange,
|
|
2518
|
+
playNext: playNext
|
|
2476
2519
|
}), /*#__PURE__*/external_react_["default"].createElement(MediaSettingsMenuRate, {
|
|
2477
2520
|
onRateChange: onRateChange,
|
|
2478
2521
|
rate: rate
|
|
@@ -2916,10 +2959,10 @@ function TimestampControl({
|
|
|
2916
2959
|
|
|
2917
2960
|
// EXPORTS
|
|
2918
2961
|
__webpack_require__.d(__webpack_exports__, {
|
|
2919
|
-
|
|
2962
|
+
Ay: () => (/* binding */ VolumeControls)
|
|
2920
2963
|
});
|
|
2921
2964
|
|
|
2922
|
-
// UNUSED EXPORTS: getIcon
|
|
2965
|
+
// UNUSED EXPORTS: VOLUME_FLYOUT_DISMISS_MS, getIcon
|
|
2923
2966
|
|
|
2924
2967
|
// EXTERNAL MODULE: external "react"
|
|
2925
2968
|
var external_react_ = __webpack_require__(1649);
|
|
@@ -2981,12 +3024,26 @@ function IconVolumeMuted24(props) {
|
|
|
2981
3024
|
var MediaToggle = __webpack_require__(8997);
|
|
2982
3025
|
;// ./src/lib/viewers/controls/hooks/useAttention.ts
|
|
2983
3026
|
|
|
3027
|
+
/** True when focus/hover is moving to a descendant, not leaving the host. */
|
|
3028
|
+
function isRelatedTargetInside(event) {
|
|
3029
|
+
return event.currentTarget.contains(event.relatedTarget);
|
|
3030
|
+
}
|
|
2984
3031
|
function useAttention() {
|
|
2985
3032
|
const [isFocused, setFocused] = external_react_.useState(false);
|
|
2986
3033
|
const [isHovered, setHovered] = external_react_.useState(false);
|
|
2987
|
-
const handleBlur =
|
|
3034
|
+
const handleBlur = event => {
|
|
3035
|
+
if (isRelatedTargetInside(event)) {
|
|
3036
|
+
return;
|
|
3037
|
+
}
|
|
3038
|
+
setFocused(false);
|
|
3039
|
+
};
|
|
2988
3040
|
const handleFocus = () => setFocused(true);
|
|
2989
|
-
const handleMouseOut =
|
|
3041
|
+
const handleMouseOut = event => {
|
|
3042
|
+
if (isRelatedTargetInside(event)) {
|
|
3043
|
+
return;
|
|
3044
|
+
}
|
|
3045
|
+
setHovered(false);
|
|
3046
|
+
};
|
|
2990
3047
|
const handleMouseOver = () => setHovered(true);
|
|
2991
3048
|
return [isFocused || isHovered, {
|
|
2992
3049
|
onBlur: handleBlur,
|
|
@@ -3023,7 +3080,7 @@ var util = __webpack_require__(4410);
|
|
|
3023
3080
|
// extracted by mini-css-extract-plugin
|
|
3024
3081
|
|
|
3025
3082
|
;// ./src/lib/viewers/controls/slider/VolumeSliderControl.tsx
|
|
3026
|
-
const _excluded = ["className", "max", "min", "onMove", "onUpdate", "step", "title", "value", "onMouseOver"];
|
|
3083
|
+
const _excluded = ["className", "max", "min", "onMove", "onUpdate", "step", "title", "value", "onMouseOver", "tabIndex"];
|
|
3027
3084
|
function VolumeSliderControl_extends() { return VolumeSliderControl_extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, VolumeSliderControl_extends.apply(null, arguments); }
|
|
3028
3085
|
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
3029
3086
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
@@ -3049,11 +3106,19 @@ function VolumeSliderControl(_ref) {
|
|
|
3049
3106
|
step = 1,
|
|
3050
3107
|
title,
|
|
3051
3108
|
value,
|
|
3052
|
-
onMouseOver
|
|
3109
|
+
onMouseOver,
|
|
3110
|
+
tabIndex = 0
|
|
3053
3111
|
} = _ref,
|
|
3054
3112
|
rest = _objectWithoutProperties(_ref, _excluded);
|
|
3055
3113
|
const [isScrubbing, setIsScrubbing] = external_react_["default"].useState(false);
|
|
3056
3114
|
const sliderElRef = external_react_["default"].useRef(null);
|
|
3115
|
+
const recordScrub = () => {
|
|
3116
|
+
window.Box?.Preview?.resin?.recordAction({
|
|
3117
|
+
action: 'programmatic',
|
|
3118
|
+
component: 'toolbar',
|
|
3119
|
+
target: 'volumeSlider'
|
|
3120
|
+
});
|
|
3121
|
+
};
|
|
3057
3122
|
const getPositionRelativeToSlider = external_react_["default"].useCallback(clientY => {
|
|
3058
3123
|
const {
|
|
3059
3124
|
current: sliderEl
|
|
@@ -3085,10 +3150,12 @@ function VolumeSliderControl(_ref) {
|
|
|
3085
3150
|
const key = (0,util/* decodeKeydown */.wU)(event);
|
|
3086
3151
|
if (key === 'ArrowDown') {
|
|
3087
3152
|
event.stopPropagation(); // Prevents global key handling
|
|
3153
|
+
recordScrub();
|
|
3088
3154
|
onUpdate(Math.max(min, Math.min(value - step, max)));
|
|
3089
3155
|
}
|
|
3090
3156
|
if (key === 'ArrowUp') {
|
|
3091
3157
|
event.stopPropagation(); // Prevents global key handling
|
|
3158
|
+
recordScrub();
|
|
3092
3159
|
onUpdate(Math.max(min, Math.min(value + step, max)));
|
|
3093
3160
|
}
|
|
3094
3161
|
};
|
|
@@ -3101,6 +3168,7 @@ function VolumeSliderControl(_ref) {
|
|
|
3101
3168
|
clientY
|
|
3102
3169
|
} = event;
|
|
3103
3170
|
if (button > 1 || ctrlKey || metaKey) return;
|
|
3171
|
+
recordScrub();
|
|
3104
3172
|
onUpdate(getPositionValue(pageY, clientY));
|
|
3105
3173
|
setIsScrubbing(true);
|
|
3106
3174
|
// Prevent clicking on the slider from triggering the mouse down event on the parent slider track
|
|
@@ -3123,6 +3191,7 @@ function VolumeSliderControl(_ref) {
|
|
|
3123
3191
|
const handleTouchStart = ({
|
|
3124
3192
|
touches
|
|
3125
3193
|
}) => {
|
|
3194
|
+
recordScrub();
|
|
3126
3195
|
onUpdate(getPositionValue(touches[0].pageY, touches[0].clientY));
|
|
3127
3196
|
setIsScrubbing(true);
|
|
3128
3197
|
};
|
|
@@ -3160,33 +3229,29 @@ function VolumeSliderControl(_ref) {
|
|
|
3160
3229
|
className: "bp-VolumeVerticalSliderControl-track-container"
|
|
3161
3230
|
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3162
3231
|
ref: sliderElRef,
|
|
3163
|
-
className: "bp-VolumeVerticalSliderControl-track-background",
|
|
3164
|
-
onMouseDown: handleMouseDown,
|
|
3165
|
-
role: "button",
|
|
3166
|
-
tabIndex: 0
|
|
3167
|
-
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3168
3232
|
"aria-label": title,
|
|
3169
3233
|
"aria-valuemax": max,
|
|
3170
3234
|
"aria-valuemin": min,
|
|
3171
3235
|
"aria-valuenow": value,
|
|
3172
|
-
className: "bp-VolumeVerticalSliderControl-track",
|
|
3236
|
+
className: "bp-VolumeVerticalSliderControl-track-background",
|
|
3173
3237
|
"data-resin-target": "volumeSlider",
|
|
3174
3238
|
"data-testid": "bp-volume-slider-control-track",
|
|
3175
|
-
onFocus:
|
|
3239
|
+
onFocus: (noop_default()),
|
|
3176
3240
|
onKeyDown: handleKeydown,
|
|
3177
3241
|
onMouseDown: handleMouseDown,
|
|
3178
3242
|
onMouseMove: handleMouseMove,
|
|
3179
3243
|
onMouseOver: onMouseOver,
|
|
3180
3244
|
onTouchStart: handleTouchStart,
|
|
3181
3245
|
role: "slider",
|
|
3246
|
+
tabIndex: tabIndex
|
|
3247
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3248
|
+
className: "bp-VolumeVerticalSliderControl-track",
|
|
3182
3249
|
style: {
|
|
3183
3250
|
height: `${heightValueBasedOnVolume / max * 100}%`
|
|
3184
|
-
}
|
|
3185
|
-
tabIndex: 0
|
|
3251
|
+
}
|
|
3186
3252
|
}))));
|
|
3187
3253
|
}
|
|
3188
3254
|
;// ./src/lib/viewers/controls/media/VolumeControls.tsx
|
|
3189
|
-
function VolumeControls_extends() { return VolumeControls_extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, VolumeControls_extends.apply(null, arguments); }
|
|
3190
3255
|
|
|
3191
3256
|
|
|
3192
3257
|
|
|
@@ -3197,6 +3262,9 @@ function VolumeControls_extends() { return VolumeControls_extends = Object.assig
|
|
|
3197
3262
|
|
|
3198
3263
|
|
|
3199
3264
|
|
|
3265
|
+
|
|
3266
|
+
/** Keyboard volume keeps the flyout open longer than the 200ms max-width transition. */
|
|
3267
|
+
const VOLUME_FLYOUT_DISMISS_MS = 1000;
|
|
3200
3268
|
function getIcon(volume) {
|
|
3201
3269
|
let Icon = icons_IconVolumeMuted24;
|
|
3202
3270
|
if (volume >= 0.66) {
|
|
@@ -3209,16 +3277,32 @@ function getIcon(volume) {
|
|
|
3209
3277
|
return Icon;
|
|
3210
3278
|
}
|
|
3211
3279
|
function VolumeControls({
|
|
3280
|
+
keyboardVolumeStep = 0,
|
|
3212
3281
|
onMuteChange,
|
|
3213
3282
|
onVolumeChange,
|
|
3214
3283
|
volume = 1
|
|
3215
3284
|
}) {
|
|
3216
3285
|
const [isActive, handlers] = useAttention();
|
|
3286
|
+
const [isRevealed, setIsRevealed] = (0,external_react_.useState)(false);
|
|
3287
|
+
const revealTimerRef = (0,external_react_.useRef)(0);
|
|
3217
3288
|
const isMuted = !volume;
|
|
3218
3289
|
const Icon = isMuted ? icons_IconVolumeMuted24 : getIcon(volume);
|
|
3219
3290
|
const title = isMuted ? "Unmute" : "Mute";
|
|
3220
3291
|
const value = Math.round(volume * 100);
|
|
3221
|
-
const
|
|
3292
|
+
const isOpen = isActive || isRevealed;
|
|
3293
|
+
(0,external_react_.useEffect)(() => {
|
|
3294
|
+
if (!keyboardVolumeStep) {
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
setIsRevealed(true);
|
|
3298
|
+
window.clearTimeout(revealTimerRef.current);
|
|
3299
|
+
revealTimerRef.current = window.setTimeout(() => {
|
|
3300
|
+
setIsRevealed(false);
|
|
3301
|
+
revealTimerRef.current = 0;
|
|
3302
|
+
}, VOLUME_FLYOUT_DISMISS_MS);
|
|
3303
|
+
}, [keyboardVolumeStep]);
|
|
3304
|
+
(0,external_react_.useEffect)(() => () => window.clearTimeout(revealTimerRef.current), []);
|
|
3305
|
+
const handleVolume = (0,external_react_.useCallback)(newValue => {
|
|
3222
3306
|
const newValueToUse = newValue <= 5 ? 0 : newValue;
|
|
3223
3307
|
// make sure the value is always between 0 and 1 since the value passed in could be
|
|
3224
3308
|
// greater than 100 if the user drags the mouse above the top of the sider when adjusting the volume
|
|
@@ -3228,27 +3312,39 @@ function VolumeControls({
|
|
|
3228
3312
|
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3229
3313
|
className: "bp-VolumeControls",
|
|
3230
3314
|
"data-testid": "bp-volume-controls",
|
|
3231
|
-
onBlur:
|
|
3315
|
+
onBlur: event => {
|
|
3316
|
+
handlers.onBlur(event);
|
|
3317
|
+
if (event.currentTarget.contains(event.relatedTarget)) {
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3320
|
+
window.clearTimeout(revealTimerRef.current);
|
|
3321
|
+
revealTimerRef.current = 0;
|
|
3322
|
+
setIsRevealed(false);
|
|
3323
|
+
},
|
|
3232
3324
|
onFocus: handlers.onFocus,
|
|
3233
3325
|
onMouseOut: handlers.onMouseOut,
|
|
3234
3326
|
onMouseOver: handlers.onMouseOver
|
|
3235
|
-
}, /*#__PURE__*/external_react_["default"].createElement(MediaToggle/* default */.A,
|
|
3327
|
+
}, /*#__PURE__*/external_react_["default"].createElement(MediaToggle/* default */.A, {
|
|
3236
3328
|
className: "bp-VolumeControls-toggle",
|
|
3237
3329
|
"data-resin-target": "volumeToggle",
|
|
3238
3330
|
onClick: () => onMuteChange(!isMuted),
|
|
3239
3331
|
title: title
|
|
3240
|
-
},
|
|
3332
|
+
}, /*#__PURE__*/external_react_["default"].createElement(Icon, null)), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3333
|
+
"aria-hidden": !isOpen,
|
|
3241
3334
|
className: classnames_default()('bp-VolumeControls-flyout', {
|
|
3242
|
-
'bp-is-open':
|
|
3335
|
+
'bp-is-open': isOpen
|
|
3243
3336
|
})
|
|
3244
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeSliderControl,
|
|
3337
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeSliderControl, {
|
|
3338
|
+
"aria-hidden": !isOpen,
|
|
3245
3339
|
className: "bp-VolumeControls-slider",
|
|
3246
3340
|
max: 100,
|
|
3341
|
+
onMouseOver: handlers.onMouseOver,
|
|
3247
3342
|
onUpdate: handleVolume,
|
|
3248
3343
|
step: 1,
|
|
3344
|
+
tabIndex: isOpen ? 0 : -1,
|
|
3249
3345
|
title: "Volume Slider",
|
|
3250
3346
|
value: value
|
|
3251
|
-
}
|
|
3347
|
+
})));
|
|
3252
3348
|
}
|
|
3253
3349
|
|
|
3254
3350
|
/***/ },
|
|
@@ -4137,7 +4233,14 @@ function SettingsRadioItem(props, ref) {
|
|
|
4137
4233
|
value
|
|
4138
4234
|
} = props;
|
|
4139
4235
|
const displayedValue = label || value.toString();
|
|
4236
|
+
const recordAction = window.Box?.Preview?.resin?.recordAction;
|
|
4237
|
+
const settingsRadioItemAction = {
|
|
4238
|
+
action: 'programmatic',
|
|
4239
|
+
component: 'toolbar',
|
|
4240
|
+
target: 'settingsRadioItem'
|
|
4241
|
+
};
|
|
4140
4242
|
const handleClick = () => {
|
|
4243
|
+
recordAction?.(settingsRadioItemAction);
|
|
4141
4244
|
onChange(value);
|
|
4142
4245
|
};
|
|
4143
4246
|
const handleKeydown = event => {
|
|
@@ -4145,6 +4248,7 @@ function SettingsRadioItem(props, ref) {
|
|
|
4145
4248
|
if (key !== 'ArrowLeft' && key !== 'Enter' && key !== 'Space') {
|
|
4146
4249
|
return;
|
|
4147
4250
|
}
|
|
4251
|
+
recordAction?.(settingsRadioItemAction);
|
|
4148
4252
|
onChange(value);
|
|
4149
4253
|
};
|
|
4150
4254
|
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
@@ -4297,6 +4401,7 @@ let Menu = /*#__PURE__*/function (Menu) {
|
|
|
4297
4401
|
Menu["AUDIO"] = "audio";
|
|
4298
4402
|
Menu["AUTOPLAY"] = "autoplay";
|
|
4299
4403
|
Menu["GUIDES"] = "guides";
|
|
4404
|
+
Menu["PLAY_NEXT"] = "playnext";
|
|
4300
4405
|
Menu["QUALITY"] = "quality";
|
|
4301
4406
|
Menu["RATE"] = "rate";
|
|
4302
4407
|
Menu["SUBTITLES"] = "subtitles";
|
|
@@ -4333,7 +4438,7 @@ var util = __webpack_require__(4410);
|
|
|
4333
4438
|
// extracted by mini-css-extract-plugin
|
|
4334
4439
|
|
|
4335
4440
|
;// ./src/lib/viewers/controls/slider/SliderControl.tsx
|
|
4336
|
-
const _excluded = ["className", "max", "min", "onMove", "onUpdate", "step", "title", "track", "value"];
|
|
4441
|
+
const _excluded = ["className", "data-resin-target", "max", "min", "onMove", "onUpdate", "step", "title", "track", "value"];
|
|
4337
4442
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
4338
4443
|
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
4339
4444
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
@@ -4345,6 +4450,7 @@ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t =
|
|
|
4345
4450
|
function SliderControl(_ref) {
|
|
4346
4451
|
let {
|
|
4347
4452
|
className,
|
|
4453
|
+
'data-resin-target': resinTarget,
|
|
4348
4454
|
max = 100,
|
|
4349
4455
|
min = 0,
|
|
4350
4456
|
onMove = (noop_default()),
|
|
@@ -4357,6 +4463,16 @@ function SliderControl(_ref) {
|
|
|
4357
4463
|
rest = _objectWithoutProperties(_ref, _excluded);
|
|
4358
4464
|
const [isScrubbing, setIsScrubbing] = external_react_["default"].useState(false);
|
|
4359
4465
|
const sliderElRef = external_react_["default"].useRef(null);
|
|
4466
|
+
const recordScrub = () => {
|
|
4467
|
+
if (!resinTarget) {
|
|
4468
|
+
return;
|
|
4469
|
+
}
|
|
4470
|
+
window.Box?.Preview?.resin?.recordAction({
|
|
4471
|
+
action: 'programmatic',
|
|
4472
|
+
component: 'toolbar',
|
|
4473
|
+
target: resinTarget
|
|
4474
|
+
});
|
|
4475
|
+
};
|
|
4360
4476
|
const getPosition = external_react_["default"].useCallback(pageX => {
|
|
4361
4477
|
const {
|
|
4362
4478
|
current: sliderEl
|
|
@@ -4383,10 +4499,12 @@ function SliderControl(_ref) {
|
|
|
4383
4499
|
const key = (0,util/* decodeKeydown */.wU)(event);
|
|
4384
4500
|
if (key === 'ArrowLeft') {
|
|
4385
4501
|
event.stopPropagation(); // Prevents global key handling
|
|
4502
|
+
recordScrub();
|
|
4386
4503
|
onUpdate(Math.max(min, Math.min(value - step, max)));
|
|
4387
4504
|
}
|
|
4388
4505
|
if (key === 'ArrowRight') {
|
|
4389
4506
|
event.stopPropagation(); // Prevents global key handling
|
|
4507
|
+
recordScrub();
|
|
4390
4508
|
onUpdate(Math.max(min, Math.min(value + step, max)));
|
|
4391
4509
|
}
|
|
4392
4510
|
};
|
|
@@ -4397,6 +4515,7 @@ function SliderControl(_ref) {
|
|
|
4397
4515
|
pageX
|
|
4398
4516
|
}) => {
|
|
4399
4517
|
if (button > 1 || ctrlKey || metaKey) return;
|
|
4518
|
+
recordScrub();
|
|
4400
4519
|
onUpdate(getPositionValue(pageX));
|
|
4401
4520
|
setIsScrubbing(true);
|
|
4402
4521
|
};
|
|
@@ -4416,6 +4535,7 @@ function SliderControl(_ref) {
|
|
|
4416
4535
|
const handleTouchStart = ({
|
|
4417
4536
|
touches
|
|
4418
4537
|
}) => {
|
|
4538
|
+
recordScrub();
|
|
4419
4539
|
onUpdate(getPositionValue(touches[0].pageX));
|
|
4420
4540
|
setIsScrubbing(true);
|
|
4421
4541
|
};
|
|
@@ -4453,6 +4573,7 @@ function SliderControl(_ref) {
|
|
|
4453
4573
|
className: classnames_default()('bp-SliderControl', className, {
|
|
4454
4574
|
'bp-is-scrubbing': isScrubbing
|
|
4455
4575
|
}),
|
|
4576
|
+
"data-resin-target": resinTarget,
|
|
4456
4577
|
onKeyDown: handleKeydown,
|
|
4457
4578
|
onMouseDown: handleMouseDown,
|
|
4458
4579
|
onMouseMove: handleMouseMove,
|
|
@@ -4488,7 +4609,7 @@ function getPdfjsWorkerSrc() {
|
|
|
4488
4609
|
|
|
4489
4610
|
/***/ },
|
|
4490
4611
|
|
|
4491
|
-
/***/
|
|
4612
|
+
/***/ 673
|
|
4492
4613
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
4493
4614
|
|
|
4494
4615
|
|
|
@@ -4504,8 +4625,8 @@ var external_react_ = __webpack_require__(1649);
|
|
|
4504
4625
|
// EXTERNAL MODULE: ./node_modules/lodash/isFinite.js
|
|
4505
4626
|
var lodash_isFinite = __webpack_require__(2297);
|
|
4506
4627
|
var isFinite_default = /*#__PURE__*/__webpack_require__.n(lodash_isFinite);
|
|
4507
|
-
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MediaSettings.tsx +
|
|
4508
|
-
var MediaSettings = __webpack_require__(
|
|
4628
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MediaSettings.tsx + 6 modules
|
|
4629
|
+
var MediaSettings = __webpack_require__(9229);
|
|
4509
4630
|
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/PlayPauseToggle.tsx + 1 modules
|
|
4510
4631
|
var PlayPauseToggle = __webpack_require__(6321);
|
|
4511
4632
|
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/TimestampControl.tsx + 1 modules
|
|
@@ -4612,316 +4733,8 @@ function morphPeaks(from, to, elapsedMs) {
|
|
|
4612
4733
|
}
|
|
4613
4734
|
return out;
|
|
4614
4735
|
}
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4618
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4619
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
4620
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4621
|
-
|
|
4622
|
-
/** Visible window: start/end times, pixels-per-second, and the current zoom. */
|
|
4623
|
-
function createWaveformViewport({
|
|
4624
|
-
durationSec,
|
|
4625
|
-
gutterPx = 0,
|
|
4626
|
-
heightPx,
|
|
4627
|
-
maxZoom,
|
|
4628
|
-
scrollLeftPx,
|
|
4629
|
-
widthPx,
|
|
4630
|
-
zoomLevel
|
|
4631
|
-
}) {
|
|
4632
|
-
const zoom = Number.isFinite(zoomLevel) && zoomLevel > 0 ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4633
|
-
const viewDurationSec = durationSec > 0 ? durationSec / zoom : 0; // seconds visible at this zoom
|
|
4634
|
-
const pixelsPerSecond = viewDurationSec > 0 && widthPx > 0 ? widthPx / viewDurationSec : 0;
|
|
4635
|
-
const leadingGutterPx = Number.isFinite(gutterPx) && gutterPx > 0 ? gutterPx : 0;
|
|
4636
|
-
const unclampedStartSec = pixelsPerSecond > 0 ? (scrollLeftPx - leadingGutterPx) / pixelsPerSecond : 0;
|
|
4637
|
-
const gutterDurationSec = pixelsPerSecond > 0 ? leadingGutterPx / pixelsPerSecond : 0;
|
|
4638
|
-
const latestWindowStartSec = leadingGutterPx > 0 ? durationSec + gutterDurationSec - viewDurationSec : Math.max(0, durationSec - viewDurationSec);
|
|
4639
|
-
const earliestWindowStartSec = leadingGutterPx > 0 ? -gutterDurationSec : 0;
|
|
4640
|
-
const startSec = pixelsPerSecond > 0 ? Math.min(latestWindowStartSec, Math.max(earliestWindowStartSec, unclampedStartSec)) : 0;
|
|
4641
|
-
return {
|
|
4642
|
-
durationSec,
|
|
4643
|
-
endSec: startSec + viewDurationSec,
|
|
4644
|
-
gutterPx: leadingGutterPx,
|
|
4645
|
-
heightPx,
|
|
4646
|
-
maxZoom,
|
|
4647
|
-
pixelsPerSecond,
|
|
4648
|
-
scrollLeftPx,
|
|
4649
|
-
startSec,
|
|
4650
|
-
widthPx,
|
|
4651
|
-
zoomLevel: zoom
|
|
4652
|
-
};
|
|
4653
|
-
}
|
|
4654
|
-
|
|
4655
|
-
/** Same viewport with a different scroll, so start/end times update. */
|
|
4656
|
-
function getViewportAtScroll(viewport, scrollLeftPx) {
|
|
4657
|
-
return createWaveformViewport(_objectSpread(_objectSpread({}, viewport), {}, {
|
|
4658
|
-
scrollLeftPx
|
|
4659
|
-
}));
|
|
4660
|
-
}
|
|
4661
|
-
|
|
4662
|
-
/** True when the visible window has not moved — skip a React state update. */
|
|
4663
|
-
function viewportEquals(prev, next) {
|
|
4664
|
-
return !!prev && prev.durationSec === next.durationSec && prev.endSec === next.endSec && prev.gutterPx === next.gutterPx && prev.maxZoom === next.maxZoom && prev.scrollLeftPx === next.scrollLeftPx && prev.startSec === next.startSec && prev.widthPx === next.widthPx && prev.zoomLevel === next.zoomLevel;
|
|
4665
|
-
}
|
|
4666
|
-
|
|
4667
|
-
/** How many CSS pixels from the left of the visible window this time sits. */
|
|
4668
|
-
function positionPxFromTime(timeSec, viewport) {
|
|
4669
|
-
return (timeSec - viewport.startSec) * viewport.pixelsPerSecond;
|
|
4670
|
-
}
|
|
4671
|
-
|
|
4672
|
-
/** Media time under a point this many CSS pixels from the left of the visible window. */
|
|
4673
|
-
function timeFromPositionPx(positionPx, viewport) {
|
|
4674
|
-
if (!(viewport.pixelsPerSecond > 0)) {
|
|
4675
|
-
return viewport.startSec;
|
|
4676
|
-
}
|
|
4677
|
-
return viewport.startSec + positionPx / viewport.pixelsPerSecond;
|
|
4678
|
-
}
|
|
4679
|
-
|
|
4680
|
-
/** True when this time sits inside the visible window. */
|
|
4681
|
-
function isTimeInView(timeSec, viewport) {
|
|
4682
|
-
return timeSec >= viewport.startSec && timeSec <= viewport.endSec;
|
|
4683
|
-
}
|
|
4684
|
-
|
|
4685
|
-
/** UI max zoom: 24×, ~1 peak per CSS pixel, and a minimum visible window. */
|
|
4686
|
-
function getWaveformZoomMax({
|
|
4687
|
-
durationSec,
|
|
4688
|
-
peakCount,
|
|
4689
|
-
viewWidthPx
|
|
4690
|
-
}) {
|
|
4691
|
-
if (!(peakCount > 0) || !(viewWidthPx > 0)) {
|
|
4692
|
-
return constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4693
|
-
}
|
|
4694
|
-
const peakLimitedMax = Math.floor(peakCount / viewWidthPx);
|
|
4695
|
-
const durationLimitedMax = durationSec > 0 ? durationSec / constants/* WAVEFORM_MIN_VIEW_WINDOW_SEC */.Kl : constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4696
|
-
return Math.max(constants/* WAVEFORM_ZOOM_MIN */.LW, Math.min(constants/* WAVEFORM_ZOOM_MAX */.tK, peakLimitedMax, durationLimitedMax));
|
|
4697
|
-
}
|
|
4698
|
-
|
|
4699
|
-
/** Keep zoom between 1× and this file's max. */
|
|
4700
|
-
function clampWaveformZoom(zoomLevel, maxZoom = constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4701
|
-
const max = Math.max(constants/* WAVEFORM_ZOOM_MIN */.LW, maxZoom);
|
|
4702
|
-
if (!Number.isFinite(zoomLevel)) {
|
|
4703
|
-
return constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4704
|
-
}
|
|
4705
|
-
return Math.min(max, Math.max(constants/* WAVEFORM_ZOOM_MIN */.LW, zoomLevel));
|
|
4706
|
-
}
|
|
4707
|
-
|
|
4708
|
-
/** WaveSurfer zoom density. 0 = fit the whole file in the view. */
|
|
4709
|
-
function getZoomedPixelsPerSecond({
|
|
4710
|
-
durationSec,
|
|
4711
|
-
isTape = false,
|
|
4712
|
-
maxZoom = constants/* WAVEFORM_ZOOM_MIN */.LW,
|
|
4713
|
-
viewWidthPx,
|
|
4714
|
-
zoomLevel
|
|
4715
|
-
}) {
|
|
4716
|
-
const zoom = clampWaveformZoom(zoomLevel, maxZoom);
|
|
4717
|
-
if (!(durationSec > 0) || !(viewWidthPx > 0)) {
|
|
4718
|
-
return 0;
|
|
4719
|
-
}
|
|
4720
|
-
if (!isTape && zoom <= constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4721
|
-
return 0;
|
|
4722
|
-
}
|
|
4723
|
-
return viewWidthPx / durationSec * zoom;
|
|
4724
|
-
}
|
|
4725
|
-
|
|
4726
|
-
/** Half-view empty space so t=0 and duration can sit under the center pin. */
|
|
4727
|
-
function getTapeGutterPx(widthPx) {
|
|
4728
|
-
return widthPx > 0 ? widthPx / 2 : 0;
|
|
4729
|
-
}
|
|
4730
|
-
|
|
4731
|
-
/** Tape first paint: 10s on screen, or 1× when the file is shorter than that. */
|
|
4732
|
-
function getTapeDefaultZoom(durationSec, maxZoom = constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4733
|
-
if (!(durationSec > 0)) {
|
|
4734
|
-
return constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4735
|
-
}
|
|
4736
|
-
return clampWaveformZoom(durationSec / constants/* WAVEFORM_TAPE_DEFAULT_WINDOW_SEC */.Av, maxZoom);
|
|
4737
|
-
}
|
|
4738
|
-
|
|
4739
|
-
/** Map zoom (1…max) onto the 0–100 slider. */
|
|
4740
|
-
function sliderValueFromZoom(zoomLevel, maxZoom = constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4741
|
-
const max = Math.max(constants/* WAVEFORM_ZOOM_MIN */.LW, maxZoom);
|
|
4742
|
-
const zoom = clampWaveformZoom(zoomLevel, max);
|
|
4743
|
-
if (max <= constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4744
|
-
return 0;
|
|
4745
|
-
}
|
|
4746
|
-
return (zoom - constants/* WAVEFORM_ZOOM_MIN */.LW) / (max - constants/* WAVEFORM_ZOOM_MIN */.LW) * constants/* WAVEFORM_ZOOM_SLIDER_MAX */.nh;
|
|
4747
|
-
}
|
|
4748
|
-
|
|
4749
|
-
/** Inverse of sliderValueFromZoom. */
|
|
4750
|
-
function zoomFromSliderValue(value, maxZoom = constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4751
|
-
const max = Math.max(constants/* WAVEFORM_ZOOM_MIN */.LW, maxZoom);
|
|
4752
|
-
if (max <= constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4753
|
-
return constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4754
|
-
}
|
|
4755
|
-
const t = Math.min(constants/* WAVEFORM_ZOOM_SLIDER_MAX */.nh, Math.max(0, value)) / constants/* WAVEFORM_ZOOM_SLIDER_MAX */.nh;
|
|
4756
|
-
return clampWaveformZoom(constants/* WAVEFORM_ZOOM_MIN */.LW + t * (max - constants/* WAVEFORM_ZOOM_MIN */.LW), max);
|
|
4757
|
-
}
|
|
4758
|
-
|
|
4759
|
-
/** Max scroll that still shows a full window (no overscroll). Gutters add empty lead/trail. */
|
|
4760
|
-
function maxScrollLeft(viewport) {
|
|
4761
|
-
const gutterPx = viewport.gutterPx || 0;
|
|
4762
|
-
return Math.max(0, viewport.durationSec * viewport.pixelsPerSecond + 2 * gutterPx - viewport.widthPx);
|
|
4763
|
-
}
|
|
4764
|
-
|
|
4765
|
-
/** Scroll offset that still shows a full window (no overscroll). */
|
|
4766
|
-
function clampScrollLeft(scrollLeftPx, viewport) {
|
|
4767
|
-
if (!Number.isFinite(scrollLeftPx)) {
|
|
4768
|
-
return 0;
|
|
4769
|
-
}
|
|
4770
|
-
return Math.min(maxScrollLeft(viewport), Math.max(0, scrollLeftPx));
|
|
4771
|
-
}
|
|
4772
|
-
|
|
4773
|
-
/** Center this time in the view, clamped so the window still fills the canvas. */
|
|
4774
|
-
function getCenteredScrollLeft(timeSec, viewport) {
|
|
4775
|
-
return clampScrollLeft(timeSec * viewport.pixelsPerSecond + (viewport.gutterPx || 0) - viewport.widthPx / 2, viewport);
|
|
4776
|
-
}
|
|
4777
|
-
|
|
4778
|
-
/**
|
|
4779
|
-
* Host/media seek while zoomed: jump so the time (and its comment avatar) is on screen.
|
|
4780
|
-
* No-op at fit-to-width or when that time is already visible.
|
|
4781
|
-
*/
|
|
4782
|
-
function getSeekCameraAction({
|
|
4783
|
-
cameraMode = 'desktop',
|
|
4784
|
-
timeSec,
|
|
4785
|
-
viewport
|
|
4786
|
-
}) {
|
|
4787
|
-
if (!(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
4788
|
-
return {
|
|
4789
|
-
type: 'none'
|
|
4790
|
-
};
|
|
4791
|
-
}
|
|
4792
|
-
if (cameraMode === 'tape') {
|
|
4793
|
-
const scrollLeftPx = getCenteredScrollLeft(timeSec, viewport);
|
|
4794
|
-
if (Math.abs(scrollLeftPx - viewport.scrollLeftPx) < 1) {
|
|
4795
|
-
return {
|
|
4796
|
-
type: 'none'
|
|
4797
|
-
};
|
|
4798
|
-
}
|
|
4799
|
-
return {
|
|
4800
|
-
type: 'jump',
|
|
4801
|
-
scrollLeftPx
|
|
4802
|
-
};
|
|
4803
|
-
}
|
|
4804
|
-
if (viewport.zoomLevel <= constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4805
|
-
return {
|
|
4806
|
-
type: 'none'
|
|
4807
|
-
};
|
|
4808
|
-
}
|
|
4809
|
-
if (isTimeInView(timeSec, viewport)) {
|
|
4810
|
-
return {
|
|
4811
|
-
type: 'none'
|
|
4812
|
-
};
|
|
4813
|
-
}
|
|
4814
|
-
return {
|
|
4815
|
-
type: 'jump',
|
|
4816
|
-
scrollLeftPx: getCenteredScrollLeft(timeSec, viewport)
|
|
4817
|
-
};
|
|
4818
|
-
}
|
|
4819
|
-
|
|
4820
|
-
/** Always keep this time under the center pin. Reuses followRight so the camera hook can pin. */
|
|
4821
|
-
function getTapeCameraAction({
|
|
4822
|
-
timeSec,
|
|
4823
|
-
viewport
|
|
4824
|
-
}) {
|
|
4825
|
-
if (!(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
4826
|
-
return {
|
|
4827
|
-
type: 'none'
|
|
4828
|
-
};
|
|
4829
|
-
}
|
|
4830
|
-
return {
|
|
4831
|
-
isPlayheadPinned: true,
|
|
4832
|
-
scrollLeftPx: getCenteredScrollLeft(timeSec, viewport),
|
|
4833
|
-
type: 'followRight'
|
|
4834
|
-
};
|
|
4835
|
-
}
|
|
4836
|
-
|
|
4837
|
-
/** Follow inset in CSS px, capped at one third of the view so a narrow player still has room. */
|
|
4838
|
-
function getFollowInsetPx(widthPx, insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM) {
|
|
4839
|
-
if (!(widthPx > 0)) {
|
|
4840
|
-
return 0;
|
|
4841
|
-
}
|
|
4842
|
-
return Math.min(Math.max(0, insetPx), widthPx / 3);
|
|
4843
|
-
}
|
|
4844
|
-
|
|
4845
|
-
/** CSS left for a playhead pinned to the follow inset. */
|
|
4846
|
-
function getPinnedPlayheadLeft(widthPx, insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM) {
|
|
4847
|
-
const inset = getFollowInsetPx(widthPx, insetPx);
|
|
4848
|
-
if (!(widthPx > 0)) {
|
|
4849
|
-
return '0%';
|
|
4850
|
-
}
|
|
4851
|
-
return `${(widthPx - inset) / widthPx * 100}%`;
|
|
4852
|
-
}
|
|
4853
|
-
|
|
4854
|
-
/** CSS left for a playhead locked to the center of the view. */
|
|
4855
|
-
function getTapePinnedPlayheadLeft() {
|
|
4856
|
-
return '50%';
|
|
4857
|
-
}
|
|
4858
|
-
|
|
4859
|
-
/** CSS left % of the playhead from the left of the visible window. */
|
|
4860
|
-
function timeLeftPercent(timeSec, durationSec, viewport) {
|
|
4861
|
-
if (viewport.widthPx > 0 && viewport.pixelsPerSecond > 0) {
|
|
4862
|
-
return `${positionPxFromTime(timeSec, viewport) / viewport.widthPx * 100}%`;
|
|
4863
|
-
}
|
|
4864
|
-
const progress = durationSec > 0 ? Math.min(1, Math.max(0, timeSec / durationSec)) : 0;
|
|
4865
|
-
return `${progress * 100}%`;
|
|
4866
|
-
}
|
|
4867
|
-
|
|
4868
|
-
/**
|
|
4869
|
-
* Walk across the view until the playhead nears the right edge, then follow.
|
|
4870
|
-
* Off-screen at play start jumps in; off-screen right while playing keeps following.
|
|
4871
|
-
*/
|
|
4872
|
-
function getPlayheadCameraAction({
|
|
4873
|
-
cameraMode = 'desktop',
|
|
4874
|
-
insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM,
|
|
4875
|
-
isPlaying,
|
|
4876
|
-
playJustStarted,
|
|
4877
|
-
timeSec,
|
|
4878
|
-
viewport
|
|
4879
|
-
}) {
|
|
4880
|
-
if (cameraMode === 'tape') {
|
|
4881
|
-
return getTapeCameraAction({
|
|
4882
|
-
timeSec,
|
|
4883
|
-
viewport
|
|
4884
|
-
});
|
|
4885
|
-
}
|
|
4886
|
-
if (!isPlaying || viewport.zoomLevel <= constants/* WAVEFORM_ZOOM_MIN */.LW || !(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
4887
|
-
return {
|
|
4888
|
-
type: 'none'
|
|
4889
|
-
};
|
|
4890
|
-
}
|
|
4891
|
-
const inset = getFollowInsetPx(viewport.widthPx, insetPx);
|
|
4892
|
-
const viewX = positionPxFromTime(timeSec, viewport);
|
|
4893
|
-
const playheadCanvasX = timeSec * viewport.pixelsPerSecond;
|
|
4894
|
-
const followX = viewport.widthPx - inset;
|
|
4895
|
-
if (viewX < 0) {
|
|
4896
|
-
if (!playJustStarted) {
|
|
4897
|
-
return {
|
|
4898
|
-
type: 'none'
|
|
4899
|
-
};
|
|
4900
|
-
}
|
|
4901
|
-
return {
|
|
4902
|
-
type: 'jump',
|
|
4903
|
-
scrollLeftPx: clampScrollLeft(playheadCanvasX - inset, viewport)
|
|
4904
|
-
};
|
|
4905
|
-
}
|
|
4906
|
-
if (viewX >= followX) {
|
|
4907
|
-
const unclampedScroll = playheadCanvasX - followX;
|
|
4908
|
-
const scrollLeftPx = clampScrollLeft(unclampedScroll, viewport);
|
|
4909
|
-
if (playJustStarted && viewX > viewport.widthPx) {
|
|
4910
|
-
return {
|
|
4911
|
-
type: 'jump',
|
|
4912
|
-
scrollLeftPx
|
|
4913
|
-
};
|
|
4914
|
-
}
|
|
4915
|
-
return {
|
|
4916
|
-
type: 'followRight',
|
|
4917
|
-
isPlayheadPinned: unclampedScroll <= maxScrollLeft(viewport),
|
|
4918
|
-
scrollLeftPx
|
|
4919
|
-
};
|
|
4920
|
-
}
|
|
4921
|
-
return {
|
|
4922
|
-
type: 'none'
|
|
4923
|
-
};
|
|
4924
|
-
}
|
|
4736
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/viewport.ts
|
|
4737
|
+
var waveform_viewport = __webpack_require__(772);
|
|
4925
4738
|
;// ./src/lib/viewers/media/waveform/useTapeWaveform.ts
|
|
4926
4739
|
|
|
4927
4740
|
|
|
@@ -5123,6 +4936,32 @@ function WaveformCommentMarkers({
|
|
|
5123
4936
|
}));
|
|
5124
4937
|
})));
|
|
5125
4938
|
}
|
|
4939
|
+
;// ./src/lib/viewers/media/waveform/WaveformGeneratingIndicator.scss
|
|
4940
|
+
// extracted by mini-css-extract-plugin
|
|
4941
|
+
|
|
4942
|
+
;// ./src/lib/viewers/media/waveform/WaveformGeneratingIndicator.tsx
|
|
4943
|
+
|
|
4944
|
+
|
|
4945
|
+
function WaveformGeneratingIndicator() {
|
|
4946
|
+
const label = "Generating waveform";
|
|
4947
|
+
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
4948
|
+
"aria-live": "polite",
|
|
4949
|
+
className: "bp-WaveformGeneratingIndicator",
|
|
4950
|
+
"data-testid": "bp-waveform-generating",
|
|
4951
|
+
role: "status"
|
|
4952
|
+
}, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
4953
|
+
"aria-hidden": "true",
|
|
4954
|
+
className: "bp-WaveformGeneratingIndicator-bars"
|
|
4955
|
+
}, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
4956
|
+
className: "bp-WaveformGeneratingIndicator-bar"
|
|
4957
|
+
}), /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
4958
|
+
className: "bp-WaveformGeneratingIndicator-bar"
|
|
4959
|
+
}), /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
4960
|
+
className: "bp-WaveformGeneratingIndicator-bar"
|
|
4961
|
+
})), /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
4962
|
+
className: "bp-WaveformGeneratingIndicator-label"
|
|
4963
|
+
}, label));
|
|
4964
|
+
}
|
|
5126
4965
|
;// external "react-dom"
|
|
5127
4966
|
|
|
5128
4967
|
;// ./node_modules/wavesurfer.js/dist/wavesurfer.esm.js
|
|
@@ -5213,15 +5052,62 @@ function getBufferedProgress(bufferedRange, durationSec) {
|
|
|
5213
5052
|
function getPlayedWaveformColor(isTape = false) {
|
|
5214
5053
|
return isTape ? WAVEFORM_COLOR_HOVER_PLAYED : WAVEFORM_COLOR_PLAYED;
|
|
5215
5054
|
}
|
|
5055
|
+
function rangeFills({
|
|
5056
|
+
buffer,
|
|
5057
|
+
hover,
|
|
5058
|
+
rangeEnd,
|
|
5059
|
+
rangeStart
|
|
5060
|
+
}) {
|
|
5061
|
+
const start = clampTo0And1(rangeStart);
|
|
5062
|
+
const end = clampTo0And1(rangeEnd);
|
|
5063
|
+
const hoverInside = hover != null && hover > start && hover < end;
|
|
5064
|
+
const outsideAfter = [{
|
|
5065
|
+
color: WAVEFORM_COLOR_UNPLAYED,
|
|
5066
|
+
end: Math.max(end, buffer),
|
|
5067
|
+
start: end
|
|
5068
|
+
}, {
|
|
5069
|
+
color: WAVEFORM_COLOR_BUFFER,
|
|
5070
|
+
end: 1,
|
|
5071
|
+
start: Math.max(end, buffer)
|
|
5072
|
+
}];
|
|
5073
|
+
const ranges = hoverInside ? [{
|
|
5074
|
+
color: WAVEFORM_COLOR_UNPLAYED,
|
|
5075
|
+
end: start,
|
|
5076
|
+
start: 0
|
|
5077
|
+
}, {
|
|
5078
|
+
color: WAVEFORM_COLOR_HOVER_PLAYED,
|
|
5079
|
+
end: hover,
|
|
5080
|
+
start
|
|
5081
|
+
}, {
|
|
5082
|
+
color: WAVEFORM_COLOR_HOVER_AREA,
|
|
5083
|
+
end,
|
|
5084
|
+
start: hover
|
|
5085
|
+
}, ...outsideAfter] : [{
|
|
5086
|
+
color: WAVEFORM_COLOR_UNPLAYED,
|
|
5087
|
+
end: start,
|
|
5088
|
+
start: 0
|
|
5089
|
+
}, {
|
|
5090
|
+
color: WAVEFORM_COLOR_PLAYED,
|
|
5091
|
+
end,
|
|
5092
|
+
start
|
|
5093
|
+
}, ...outsideAfter];
|
|
5094
|
+
const fill = gradientStopsFromColorRanges(ranges);
|
|
5095
|
+
return {
|
|
5096
|
+
progressColor: fill,
|
|
5097
|
+
waveColor: fill
|
|
5098
|
+
};
|
|
5099
|
+
}
|
|
5216
5100
|
|
|
5217
5101
|
/**
|
|
5218
5102
|
* progressColor paints left of the playhead (clipped by wavesurfer).
|
|
5219
5103
|
* waveColor paints right of the playhead, including buffered vs not-yet-buffered.
|
|
5104
|
+
* An open comment range replaces the played/unplayed split with in-range / out-of-range.
|
|
5220
5105
|
*/
|
|
5221
5106
|
function getWaveformFills({
|
|
5222
5107
|
bufferProgress,
|
|
5223
5108
|
hoverProgress,
|
|
5224
|
-
isTape = false
|
|
5109
|
+
isTape = false,
|
|
5110
|
+
rangeProgress
|
|
5225
5111
|
}) {
|
|
5226
5112
|
const buffer = clampTo0And1(bufferProgress);
|
|
5227
5113
|
const playedColor = getPlayedWaveformColor(isTape);
|
|
@@ -5231,6 +5117,14 @@ function getWaveformFills({
|
|
|
5231
5117
|
waveColor: WAVEFORM_COLOR_UNPLAYED
|
|
5232
5118
|
};
|
|
5233
5119
|
}
|
|
5120
|
+
if (rangeProgress && rangeProgress.end > rangeProgress.start) {
|
|
5121
|
+
return rangeFills({
|
|
5122
|
+
buffer,
|
|
5123
|
+
hover: hoverProgress == null ? null : clampTo0And1(hoverProgress),
|
|
5124
|
+
rangeEnd: rangeProgress.end,
|
|
5125
|
+
rangeStart: rangeProgress.start
|
|
5126
|
+
});
|
|
5127
|
+
}
|
|
5234
5128
|
if (hoverProgress == null) {
|
|
5235
5129
|
return {
|
|
5236
5130
|
progressColor: playedColor,
|
|
@@ -5394,6 +5288,8 @@ function tintWaveformTiles({
|
|
|
5394
5288
|
});
|
|
5395
5289
|
});
|
|
5396
5290
|
}
|
|
5291
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/range.ts
|
|
5292
|
+
var waveform_range = __webpack_require__(4253);
|
|
5397
5293
|
;// ./src/lib/viewers/media/waveform/usePlayheadCamera.ts
|
|
5398
5294
|
|
|
5399
5295
|
|
|
@@ -5487,7 +5383,7 @@ function usePlayheadCamera({
|
|
|
5487
5383
|
wavesurfer.setScroll(scrollLeftPx);
|
|
5488
5384
|
const appliedScrollLeft = getScrollLeft(wavesurfer, scrollLeftPx);
|
|
5489
5385
|
lastCameraScrollRef.current = appliedScrollLeft;
|
|
5490
|
-
viewportRef.current = getViewportAtScroll(viewportRef.current, appliedScrollLeft);
|
|
5386
|
+
viewportRef.current = (0,waveform_viewport/* getViewportAtScroll */.NI)(viewportRef.current, appliedScrollLeft);
|
|
5491
5387
|
window.requestAnimationFrame(() => {
|
|
5492
5388
|
// Keep the flag through delayed `scroll` while the camera is driving.
|
|
5493
5389
|
if (jumpAnimationRef.current || isFollowPinnedRef.current) {
|
|
@@ -5504,7 +5400,7 @@ function usePlayheadCamera({
|
|
|
5504
5400
|
if (!playhead || !isPinned || !(viewport.widthPx > 0)) {
|
|
5505
5401
|
return;
|
|
5506
5402
|
}
|
|
5507
|
-
playhead.style.left = isTape() ? getTapePinnedPlayheadLeft() : getPinnedPlayheadLeft(viewport.widthPx);
|
|
5403
|
+
playhead.style.left = isTape() ? (0,waveform_viewport/* getTapePinnedPlayheadLeft */.yW)() : (0,waveform_viewport/* getPinnedPlayheadLeft */.gl)(viewport.widthPx);
|
|
5508
5404
|
}, [isTape]);
|
|
5509
5405
|
const apply = (0,external_react_.useCallback)((timeSec, playJustStarted = false) => {
|
|
5510
5406
|
mediaTimeRef.current = timeSec;
|
|
@@ -5523,8 +5419,8 @@ function usePlayheadCamera({
|
|
|
5523
5419
|
if (jumpAnimationRef.current && !playJustStarted) {
|
|
5524
5420
|
return;
|
|
5525
5421
|
}
|
|
5526
|
-
const liveViewport = getViewportAtScroll(viewport, getScrollLeft(wavesurfer, viewport.scrollLeftPx));
|
|
5527
|
-
const action = getPlayheadCameraAction({
|
|
5422
|
+
const liveViewport = (0,waveform_viewport/* getViewportAtScroll */.NI)(viewport, getScrollLeft(wavesurfer, viewport.scrollLeftPx));
|
|
5423
|
+
const action = (0,waveform_viewport/* getPlayheadCameraAction */.aJ)({
|
|
5528
5424
|
cameraMode: cameraModeRef.current,
|
|
5529
5425
|
isPlaying: true,
|
|
5530
5426
|
playJustStarted,
|
|
@@ -5562,12 +5458,12 @@ function usePlayheadCamera({
|
|
|
5562
5458
|
const start = (0,util/* getCurrentTimeMs */.RU)();
|
|
5563
5459
|
const tick = now => {
|
|
5564
5460
|
const t = Math.min(1, (now - start) / constants/* WAVEFORM_PLAYHEAD_JUMP_MS */.Bq);
|
|
5565
|
-
const liveAction = getPlayheadCameraAction({
|
|
5461
|
+
const liveAction = (0,waveform_viewport/* getPlayheadCameraAction */.aJ)({
|
|
5566
5462
|
cameraMode: cameraModeRef.current,
|
|
5567
5463
|
isPlaying: true,
|
|
5568
5464
|
playJustStarted: true,
|
|
5569
5465
|
timeSec: mediaTimeRef.current,
|
|
5570
|
-
viewport: getViewportAtScroll(viewportRef.current, getScrollLeft(wavesurfer, from))
|
|
5466
|
+
viewport: (0,waveform_viewport/* getViewportAtScroll */.NI)(viewportRef.current, getScrollLeft(wavesurfer, from))
|
|
5571
5467
|
});
|
|
5572
5468
|
const to = liveAction.type === 'none' ? action.scrollLeftPx : liveAction.scrollLeftPx;
|
|
5573
5469
|
applyScrollLeft(from + (to - from) * (1 - (1 - t) * (1 - t)), false);
|
|
@@ -5590,7 +5486,7 @@ function usePlayheadCamera({
|
|
|
5590
5486
|
const isUserPan = (0,external_react_.useCallback)(scrollLeftPx => {
|
|
5591
5487
|
const isCameraOwnedScroll = programmaticScrollRef.current || jumpAnimationRef.current !== 0;
|
|
5592
5488
|
const lastCameraScroll = lastCameraScrollRef.current;
|
|
5593
|
-
const maxScroll = maxScrollLeft(viewportRef.current);
|
|
5489
|
+
const maxScroll = (0,waveform_viewport/* maxScrollLeft */.d0)(viewportRef.current);
|
|
5594
5490
|
const isClampedToMax = lastCameraScroll != null && scrollLeftPx >= maxScroll - 1 && lastCameraScroll >= maxScroll - 1;
|
|
5595
5491
|
const isFollowCameraScroll = isFollowPinnedRef.current && lastCameraScroll != null && Math.abs(scrollLeftPx - lastCameraScroll) <= 1;
|
|
5596
5492
|
return !(isCameraOwnedScroll && (jumpAnimationRef.current !== 0 || isFollowCameraScroll || isClampedToMax || !isFollowPinnedRef.current));
|
|
@@ -5606,8 +5502,8 @@ function usePlayheadCamera({
|
|
|
5606
5502
|
if (!isTape()) {
|
|
5607
5503
|
isFollowPinnedRef.current = false;
|
|
5608
5504
|
}
|
|
5609
|
-
const liveViewport = getViewportAtScroll(viewportRef.current, getScrollLeft(wavesurfer, viewportRef.current.scrollLeftPx));
|
|
5610
|
-
const action = getSeekCameraAction({
|
|
5505
|
+
const liveViewport = (0,waveform_viewport/* getViewportAtScroll */.NI)(viewportRef.current, getScrollLeft(wavesurfer, viewportRef.current.scrollLeftPx));
|
|
5506
|
+
const action = (0,waveform_viewport/* getSeekCameraAction */.wA)({
|
|
5611
5507
|
cameraMode: cameraModeRef.current,
|
|
5612
5508
|
timeSec,
|
|
5613
5509
|
viewport: liveViewport
|
|
@@ -5628,7 +5524,7 @@ function usePlayheadCamera({
|
|
|
5628
5524
|
applyScrollLeft(from + (to - from) * (1 - (1 - t) * (1 - t)), false);
|
|
5629
5525
|
const playhead = playheadRef.current;
|
|
5630
5526
|
if (playhead) {
|
|
5631
|
-
playhead.style.left = isTape() ? getTapePinnedPlayheadLeft() : timeLeftPercent(mediaTimeRef.current, viewportRef.current.durationSec, viewportRef.current);
|
|
5527
|
+
playhead.style.left = isTape() ? (0,waveform_viewport/* getTapePinnedPlayheadLeft */.yW)() : (0,waveform_viewport/* timeLeftPercent */.Mu)(mediaTimeRef.current, viewportRef.current.durationSec, viewportRef.current);
|
|
5632
5528
|
}
|
|
5633
5529
|
if (t < 1) {
|
|
5634
5530
|
jumpAnimationRef.current = window.requestAnimationFrame(tick);
|
|
@@ -5646,16 +5542,16 @@ function usePlayheadCamera({
|
|
|
5646
5542
|
}
|
|
5647
5543
|
const scrollLeftPx = getScrollLeft(wavesurfer);
|
|
5648
5544
|
if (!isUserPan(scrollLeftPx)) {
|
|
5649
|
-
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
5545
|
+
viewportRef.current = (0,waveform_viewport/* getViewportAtScroll */.NI)(viewportRef.current, scrollLeftPx);
|
|
5650
5546
|
return;
|
|
5651
5547
|
}
|
|
5652
|
-
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
5548
|
+
viewportRef.current = (0,waveform_viewport/* getViewportAtScroll */.NI)(viewportRef.current, scrollLeftPx);
|
|
5653
5549
|
const playhead = playheadRef.current;
|
|
5654
5550
|
if (isTape()) {
|
|
5655
5551
|
if (playhead) {
|
|
5656
|
-
playhead.style.left = getTapePinnedPlayheadLeft();
|
|
5552
|
+
playhead.style.left = (0,waveform_viewport/* getTapePinnedPlayheadLeft */.yW)();
|
|
5657
5553
|
}
|
|
5658
|
-
const pinTimeSec = Math.min(viewportRef.current.durationSec, Math.max(0, timeFromPositionPx(viewportRef.current.widthPx / 2, viewportRef.current)));
|
|
5554
|
+
const pinTimeSec = Math.min(viewportRef.current.durationSec, Math.max(0, (0,waveform_viewport/* timeFromPositionPx */.lZ)(viewportRef.current.widthPx / 2, viewportRef.current)));
|
|
5659
5555
|
userIsScrollingRef.current = true;
|
|
5660
5556
|
window.clearTimeout(scrollSettleTimerRef.current);
|
|
5661
5557
|
scrollSettleTimerRef.current = window.setTimeout(() => {
|
|
@@ -5673,7 +5569,7 @@ function usePlayheadCamera({
|
|
|
5673
5569
|
}
|
|
5674
5570
|
const timeSec = readMediaTime();
|
|
5675
5571
|
if (playhead) {
|
|
5676
|
-
playhead.style.left = timeLeftPercent(timeSec, viewportRef.current.durationSec, viewportRef.current);
|
|
5572
|
+
playhead.style.left = (0,waveform_viewport/* timeLeftPercent */.Mu)(timeSec, viewportRef.current.durationSec, viewportRef.current);
|
|
5677
5573
|
}
|
|
5678
5574
|
userIsScrollingRef.current = true;
|
|
5679
5575
|
holdFollowUntilInsetRef.current = true;
|
|
@@ -5709,15 +5605,318 @@ function usePlayheadCamera({
|
|
|
5709
5605
|
seekTo
|
|
5710
5606
|
};
|
|
5711
5607
|
}
|
|
5608
|
+
;// ./src/lib/viewers/media/waveform/WaveformRangeSelection.scss
|
|
5609
|
+
// extracted by mini-css-extract-plugin
|
|
5610
|
+
|
|
5611
|
+
;// ./src/lib/viewers/media/waveform/WaveformRangeSelection.tsx
|
|
5612
|
+
|
|
5613
|
+
|
|
5614
|
+
|
|
5615
|
+
|
|
5616
|
+
|
|
5617
|
+
|
|
5618
|
+
function offsetLeftCss(base, offsetPx) {
|
|
5619
|
+
if (!offsetPx) {
|
|
5620
|
+
return base;
|
|
5621
|
+
}
|
|
5622
|
+
const op = offsetPx < 0 ? '-' : '+';
|
|
5623
|
+
return `calc(${base} ${op} ${Math.abs(offsetPx)}px)`;
|
|
5624
|
+
}
|
|
5625
|
+
function applyHandleLeft(el, timeSec, durationSec, viewport, collapsedOffsetPx = 0) {
|
|
5626
|
+
if (!el) {
|
|
5627
|
+
return;
|
|
5628
|
+
}
|
|
5629
|
+
el.style.left = offsetLeftCss((0,waveform_viewport/* timeLeftPercent */.Mu)(timeSec, durationSec, viewport), collapsedOffsetPx);
|
|
5630
|
+
}
|
|
5631
|
+
function applyRegion(el, startSec, endSec, durationSec, viewport, collapsed) {
|
|
5632
|
+
if (!el) {
|
|
5633
|
+
return;
|
|
5634
|
+
}
|
|
5635
|
+
const start = (0,waveform_viewport/* timeLeftPercent */.Mu)(startSec, durationSec, viewport);
|
|
5636
|
+
const halfLine = constants/* WAVEFORM_RANGE_HANDLE_LINE_PX */.h1 / 2;
|
|
5637
|
+
if (collapsed) {
|
|
5638
|
+
const extentPx = constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG + halfLine;
|
|
5639
|
+
el.style.left = offsetLeftCss(start, -extentPx);
|
|
5640
|
+
el.style.width = `${extentPx * 2}px`;
|
|
5641
|
+
return;
|
|
5642
|
+
}
|
|
5643
|
+
const end = (0,waveform_viewport/* timeLeftPercent */.Mu)(endSec, durationSec, viewport);
|
|
5644
|
+
el.style.left = offsetLeftCss(start, -halfLine);
|
|
5645
|
+
el.style.width = `calc(${end} - ${start} + ${constants/* WAVEFORM_RANGE_HANDLE_LINE_PX */.h1}px)`;
|
|
5646
|
+
}
|
|
5647
|
+
const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(function WaveformRangeSelection({
|
|
5648
|
+
currentTimeSec = 0,
|
|
5649
|
+
durationSec,
|
|
5650
|
+
getPlayheadSec,
|
|
5651
|
+
interactive = true,
|
|
5652
|
+
isHighlighted = false,
|
|
5653
|
+
keepHighlight = true,
|
|
5654
|
+
onDragChange,
|
|
5655
|
+
onPreviewChange,
|
|
5656
|
+
onRangeChange,
|
|
5657
|
+
range,
|
|
5658
|
+
viewport
|
|
5659
|
+
}, ref) {
|
|
5660
|
+
const rootRef = (0,external_react_.useRef)(null);
|
|
5661
|
+
const regionRef = (0,external_react_.useRef)(null);
|
|
5662
|
+
const startHandleRef = (0,external_react_.useRef)(null);
|
|
5663
|
+
const endHandleRef = (0,external_react_.useRef)(null);
|
|
5664
|
+
const tooltipRef = (0,external_react_.useRef)(null);
|
|
5665
|
+
const dragRef = (0,external_react_.useRef)(null);
|
|
5666
|
+
const rangeRef = (0,external_react_.useRef)(range);
|
|
5667
|
+
const displayedRef = (0,external_react_.useRef)((0,waveform_range/* resolveRange */.Ss)(range, (0,waveform_range/* durationMsFromSec */.uH)(durationSec)));
|
|
5668
|
+
const viewportRef = (0,external_react_.useRef)(viewport);
|
|
5669
|
+
const durationSecRef = (0,external_react_.useRef)(durationSec);
|
|
5670
|
+
const onDragChangeRef = (0,external_react_.useRef)(onDragChange);
|
|
5671
|
+
const onPreviewChangeRef = (0,external_react_.useRef)(onPreviewChange);
|
|
5672
|
+
const onRangeChangeRef = (0,external_react_.useRef)(onRangeChange);
|
|
5673
|
+
const getPlayheadSecRef = (0,external_react_.useRef)(getPlayheadSec);
|
|
5674
|
+
const [dragRange, setDragRange] = (0,external_react_.useState)(null);
|
|
5675
|
+
const [activeHandle, setActiveHandle] = (0,external_react_.useState)(null);
|
|
5676
|
+
const activeHandleRef = (0,external_react_.useRef)(null);
|
|
5677
|
+
rangeRef.current = range;
|
|
5678
|
+
durationSecRef.current = durationSec;
|
|
5679
|
+
onDragChangeRef.current = onDragChange;
|
|
5680
|
+
onPreviewChangeRef.current = onPreviewChange;
|
|
5681
|
+
onRangeChangeRef.current = onRangeChange;
|
|
5682
|
+
getPlayheadSecRef.current = getPlayheadSec;
|
|
5683
|
+
activeHandleRef.current = activeHandle;
|
|
5684
|
+
const durationMs = (0,waveform_range/* durationMsFromSec */.uH)(durationSec);
|
|
5685
|
+
const displayed = dragRange ?? (0,waveform_range/* resolveRange */.Ss)(range, durationMs);
|
|
5686
|
+
displayedRef.current = displayed;
|
|
5687
|
+
const syncPositions = (0,external_react_.useCallback)((next, nextViewport, nextDurationSec) => {
|
|
5688
|
+
displayedRef.current = next;
|
|
5689
|
+
const collapsed = next.startMs === next.endMs;
|
|
5690
|
+
applyRegion(regionRef.current, next.startMs / 1000, next.endMs / 1000, nextDurationSec, nextViewport, collapsed);
|
|
5691
|
+
applyHandleLeft(startHandleRef.current, next.startMs / 1000, nextDurationSec, nextViewport, collapsed ? -constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG : 0);
|
|
5692
|
+
applyHandleLeft(endHandleRef.current, next.endMs / 1000, nextDurationSec, nextViewport, collapsed ? constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG : 0);
|
|
5693
|
+
const tooltip = tooltipRef.current;
|
|
5694
|
+
if (tooltip) {
|
|
5695
|
+
const tooltipHandle = activeHandleRef.current ?? 'end';
|
|
5696
|
+
const tooltipMs = tooltipHandle === 'start' ? next.startMs : next.endMs;
|
|
5697
|
+
tooltip.style.left = (0,waveform_viewport/* timeLeftPercent */.Mu)(tooltipMs / 1000, nextDurationSec, nextViewport);
|
|
5698
|
+
}
|
|
5699
|
+
}, []);
|
|
5700
|
+
(0,external_react_.useImperativeHandle)(ref, () => ({
|
|
5701
|
+
applyViewport: nextViewport => {
|
|
5702
|
+
viewportRef.current = nextViewport;
|
|
5703
|
+
syncPositions(displayedRef.current, nextViewport, durationSecRef.current);
|
|
5704
|
+
}
|
|
5705
|
+
}), [syncPositions]);
|
|
5706
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
5707
|
+
syncPositions(displayedRef.current, viewportRef.current, durationSec);
|
|
5708
|
+
}, [activeHandle, displayed.endMs, displayed.startMs, durationSec, syncPositions]);
|
|
5709
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
5710
|
+
const next = (0,waveform_viewport/* createWaveformViewport */.eq)({
|
|
5711
|
+
durationSec: viewport.durationSec,
|
|
5712
|
+
heightPx: viewport.heightPx,
|
|
5713
|
+
maxZoom: viewport.maxZoom,
|
|
5714
|
+
scrollLeftPx: viewportRef.current.scrollLeftPx,
|
|
5715
|
+
widthPx: viewport.widthPx,
|
|
5716
|
+
zoomLevel: viewport.zoomLevel
|
|
5717
|
+
});
|
|
5718
|
+
viewportRef.current = next;
|
|
5719
|
+
syncPositions(displayedRef.current, next, durationSecRef.current);
|
|
5720
|
+
}, [syncPositions, viewport.durationSec, viewport.heightPx, viewport.maxZoom, viewport.widthPx, viewport.zoomLevel]);
|
|
5721
|
+
const endDrag = (0,external_react_.useCallback)(event => {
|
|
5722
|
+
const drag = dragRef.current;
|
|
5723
|
+
if (!drag || event.pointerId && drag.pointerId !== event.pointerId) {
|
|
5724
|
+
return;
|
|
5725
|
+
}
|
|
5726
|
+
[startHandleRef.current, endHandleRef.current].forEach(handleEl => {
|
|
5727
|
+
if (handleEl && handleEl.hasPointerCapture(event.pointerId)) {
|
|
5728
|
+
handleEl.releasePointerCapture(event.pointerId);
|
|
5729
|
+
}
|
|
5730
|
+
});
|
|
5731
|
+
dragRef.current = null;
|
|
5732
|
+
setActiveHandle(null);
|
|
5733
|
+
setDragRange(null);
|
|
5734
|
+
onDragChangeRef.current?.(false);
|
|
5735
|
+
const didChange = drag.range.startMs !== drag.originRange.startMs || drag.range.endMs !== drag.originRange.endMs;
|
|
5736
|
+
if (!didChange) {
|
|
5737
|
+
return;
|
|
5738
|
+
}
|
|
5739
|
+
const committed = (0,waveform_range/* commitRangeChange */.dG)(drag.range);
|
|
5740
|
+
if (committed) {
|
|
5741
|
+
onRangeChangeRef.current?.(committed);
|
|
5742
|
+
}
|
|
5743
|
+
}, []);
|
|
5744
|
+
const moveDrag = (0,external_react_.useCallback)(event => {
|
|
5745
|
+
const drag = dragRef.current;
|
|
5746
|
+
if (!drag || event.pointerId && drag.pointerId !== event.pointerId) {
|
|
5747
|
+
return;
|
|
5748
|
+
}
|
|
5749
|
+
const root = rootRef.current;
|
|
5750
|
+
if (!root) {
|
|
5751
|
+
return;
|
|
5752
|
+
}
|
|
5753
|
+
const rect = root.getBoundingClientRect();
|
|
5754
|
+
const pointerX = event.clientX - rect.left;
|
|
5755
|
+
const vp = viewportRef.current;
|
|
5756
|
+
const duration = (0,waveform_range/* durationMsFromSec */.uH)(durationSecRef.current);
|
|
5757
|
+
const playheadSec = getPlayheadSecRef.current?.() ?? currentTimeSec;
|
|
5758
|
+
const pointerMs = (0,waveform_range/* snapTimeMs */.Mh)({
|
|
5759
|
+
pixelsPerSecond: vp.pixelsPerSecond,
|
|
5760
|
+
playheadMs: playheadSec * 1000,
|
|
5761
|
+
timeMs: (0,waveform_range/* pointerTimeMs */.v2)(pointerX, vp)
|
|
5762
|
+
});
|
|
5763
|
+
if (drag.originMs === drag.range.startMs && drag.originMs === drag.range.endMs && pointerMs === drag.originMs) {
|
|
5764
|
+
return;
|
|
5765
|
+
}
|
|
5766
|
+
const next = (0,waveform_range/* dragRangeHandle */.Mo)({
|
|
5767
|
+
durationMs: duration,
|
|
5768
|
+
handle: drag.handle,
|
|
5769
|
+
pointerMs,
|
|
5770
|
+
range: {
|
|
5771
|
+
endMs: drag.range.endMs,
|
|
5772
|
+
startMs: drag.range.startMs
|
|
5773
|
+
}
|
|
5774
|
+
});
|
|
5775
|
+
drag.handle = next.handle;
|
|
5776
|
+
drag.range = next.range;
|
|
5777
|
+
setActiveHandle(next.handle);
|
|
5778
|
+
setDragRange(next.range);
|
|
5779
|
+
syncPositions(next.range, vp, durationSecRef.current);
|
|
5780
|
+
onPreviewChangeRef.current?.({
|
|
5781
|
+
endMs: next.range.endMs,
|
|
5782
|
+
startMs: next.range.startMs
|
|
5783
|
+
});
|
|
5784
|
+
}, [currentTimeSec, syncPositions]);
|
|
5785
|
+
const startDrag = (0,external_react_.useCallback)((handle, event) => {
|
|
5786
|
+
if (!interactive || event.button > 1 || event.ctrlKey || event.metaKey) {
|
|
5787
|
+
return;
|
|
5788
|
+
}
|
|
5789
|
+
event.preventDefault();
|
|
5790
|
+
event.stopPropagation();
|
|
5791
|
+
const resolved = (0,waveform_range/* resolveRange */.Ss)(rangeRef.current, (0,waveform_range/* durationMsFromSec */.uH)(durationSecRef.current));
|
|
5792
|
+
dragRef.current = {
|
|
5793
|
+
handle,
|
|
5794
|
+
originMs: handle === 'start' ? resolved.startMs : resolved.endMs,
|
|
5795
|
+
originRange: {
|
|
5796
|
+
endMs: resolved.endMs,
|
|
5797
|
+
startMs: resolved.startMs
|
|
5798
|
+
},
|
|
5799
|
+
pointerId: event.pointerId,
|
|
5800
|
+
range: resolved
|
|
5801
|
+
};
|
|
5802
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
5803
|
+
setActiveHandle(handle);
|
|
5804
|
+
setDragRange(resolved);
|
|
5805
|
+
onDragChangeRef.current?.(true);
|
|
5806
|
+
onPreviewChangeRef.current?.({
|
|
5807
|
+
endMs: (0,waveform_range/* isRangeCollapsed */.BT)(rangeRef.current) ? null : resolved.endMs,
|
|
5808
|
+
startMs: resolved.startMs
|
|
5809
|
+
});
|
|
5810
|
+
}, [interactive]);
|
|
5811
|
+
const onHandlePointerDown = (0,external_react_.useCallback)(event => {
|
|
5812
|
+
const root = rootRef.current;
|
|
5813
|
+
if (!root) {
|
|
5814
|
+
return;
|
|
5815
|
+
}
|
|
5816
|
+
const rect = root.getBoundingClientRect();
|
|
5817
|
+
const pointerX = event.clientX - rect.left;
|
|
5818
|
+
const vp = viewportRef.current;
|
|
5819
|
+
const resolved = (0,waveform_range/* resolveRange */.Ss)(rangeRef.current, (0,waveform_range/* durationMsFromSec */.uH)(durationSecRef.current));
|
|
5820
|
+
const handle = (0,waveform_range/* pickRangeHandle */.HG)({
|
|
5821
|
+
endX: (0,waveform_range/* visualRangeHandlePx */.Eh)({
|
|
5822
|
+
handle: 'end',
|
|
5823
|
+
range: resolved,
|
|
5824
|
+
viewport: vp
|
|
5825
|
+
}),
|
|
5826
|
+
pointerX,
|
|
5827
|
+
startX: (0,waveform_range/* visualRangeHandlePx */.Eh)({
|
|
5828
|
+
handle: 'start',
|
|
5829
|
+
range: resolved,
|
|
5830
|
+
viewport: vp
|
|
5831
|
+
})
|
|
5832
|
+
});
|
|
5833
|
+
startDrag(handle, event);
|
|
5834
|
+
}, [startDrag]);
|
|
5835
|
+
(0,external_react_.useEffect)(() => {
|
|
5836
|
+
const onMove = event => {
|
|
5837
|
+
if (!dragRef.current) {
|
|
5838
|
+
return;
|
|
5839
|
+
}
|
|
5840
|
+
event.preventDefault();
|
|
5841
|
+
moveDrag(event);
|
|
5842
|
+
};
|
|
5843
|
+
const onUp = event => {
|
|
5844
|
+
if (!dragRef.current) {
|
|
5845
|
+
return;
|
|
5846
|
+
}
|
|
5847
|
+
endDrag(event);
|
|
5848
|
+
};
|
|
5849
|
+
window.addEventListener('pointermove', onMove);
|
|
5850
|
+
window.addEventListener('pointerup', onUp);
|
|
5851
|
+
window.addEventListener('pointercancel', onUp);
|
|
5852
|
+
return () => {
|
|
5853
|
+
window.removeEventListener('pointermove', onMove);
|
|
5854
|
+
window.removeEventListener('pointerup', onUp);
|
|
5855
|
+
window.removeEventListener('pointercancel', onUp);
|
|
5856
|
+
};
|
|
5857
|
+
}, [endDrag, moveDrag]);
|
|
5858
|
+
(0,external_react_.useEffect)(() => {
|
|
5859
|
+
return () => {
|
|
5860
|
+
if (!dragRef.current) {
|
|
5861
|
+
return;
|
|
5862
|
+
}
|
|
5863
|
+
dragRef.current = null;
|
|
5864
|
+
onDragChangeRef.current?.(false);
|
|
5865
|
+
};
|
|
5866
|
+
}, []);
|
|
5867
|
+
if (!(durationSec > 0) || !(durationMs >= 0)) {
|
|
5868
|
+
return null;
|
|
5869
|
+
}
|
|
5870
|
+
const tooltipHandle = activeHandle ?? 'end';
|
|
5871
|
+
const tooltipMs = tooltipHandle === 'start' ? displayed.startMs : displayed.endMs;
|
|
5872
|
+
const collapsed = displayed.startMs === displayed.endMs;
|
|
5873
|
+
const highlight = isHighlighted || collapsed;
|
|
5874
|
+
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5875
|
+
ref: rootRef,
|
|
5876
|
+
className: `bp-WaveformRange${keepHighlight ? ' bp-WaveformRange--persist' : ''}${highlight ? ' bp-WaveformRange--highlight' : ''}`,
|
|
5877
|
+
"data-collapsed": collapsed ? 'true' : 'false',
|
|
5878
|
+
"data-highlighted": highlight ? 'true' : 'false',
|
|
5879
|
+
"data-testid": "bp-waveform-range"
|
|
5880
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5881
|
+
ref: regionRef,
|
|
5882
|
+
className: "bp-WaveformRange-region",
|
|
5883
|
+
"data-testid": "bp-waveform-range-region"
|
|
5884
|
+
}), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5885
|
+
ref: startHandleRef,
|
|
5886
|
+
className: `bp-WaveformRange-handle bp-WaveformRange-handle--start${activeHandle === 'start' ? ' bp-WaveformRange-handle--dragging' : ''}`,
|
|
5887
|
+
"data-testid": "bp-waveform-range-handle-start",
|
|
5888
|
+
onMouseMove: event => event.stopPropagation(),
|
|
5889
|
+
onPointerDown: onHandlePointerDown
|
|
5890
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5891
|
+
className: "bp-WaveformRange-handleGrip"
|
|
5892
|
+
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5893
|
+
ref: endHandleRef,
|
|
5894
|
+
className: `bp-WaveformRange-handle bp-WaveformRange-handle--end${activeHandle === 'end' ? ' bp-WaveformRange-handle--dragging' : ''}`,
|
|
5895
|
+
"data-testid": "bp-waveform-range-handle-end",
|
|
5896
|
+
onMouseMove: event => event.stopPropagation(),
|
|
5897
|
+
onPointerDown: onHandlePointerDown
|
|
5898
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5899
|
+
className: "bp-WaveformRange-handleGrip"
|
|
5900
|
+
})), activeHandle && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5901
|
+
ref: tooltipRef,
|
|
5902
|
+
className: "bp-WaveformRange-tooltip",
|
|
5903
|
+
"data-testid": "bp-waveform-range-tooltip"
|
|
5904
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5905
|
+
className: "bp-WaveformRange-tooltipTime"
|
|
5906
|
+
}, formatTime(tooltipMs / 1000))));
|
|
5907
|
+
});
|
|
5908
|
+
/* harmony default export */ const waveform_WaveformRangeSelection = (/*#__PURE__*/external_react_["default"].memo(WaveformRangeSelection));
|
|
5712
5909
|
;// ./src/lib/viewers/media/waveform/WaveformView.scss
|
|
5713
5910
|
// extracted by mini-css-extract-plugin
|
|
5714
5911
|
|
|
5715
5912
|
;// ./src/lib/viewers/media/waveform/WaveformView.tsx
|
|
5716
|
-
function
|
|
5717
|
-
function
|
|
5718
|
-
function
|
|
5719
|
-
function
|
|
5720
|
-
function
|
|
5913
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
5914
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5915
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5916
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5917
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
5918
|
+
|
|
5919
|
+
|
|
5721
5920
|
|
|
5722
5921
|
|
|
5723
5922
|
|
|
@@ -5838,10 +6037,14 @@ function WaveformView({
|
|
|
5838
6037
|
isPlaying = false,
|
|
5839
6038
|
mediaEl,
|
|
5840
6039
|
onPlayPause,
|
|
6040
|
+
onRangeChange,
|
|
6041
|
+
onRangeClear,
|
|
6042
|
+
onRangeDragChange,
|
|
5841
6043
|
onSeek,
|
|
5842
6044
|
onViewportChange,
|
|
5843
6045
|
onZoomChange,
|
|
5844
6046
|
peaks,
|
|
6047
|
+
range = null,
|
|
5845
6048
|
zoomLevel: zoomLevelProp
|
|
5846
6049
|
}) {
|
|
5847
6050
|
// DOM / WaveSurfer
|
|
@@ -5850,6 +6053,7 @@ function WaveformView({
|
|
|
5850
6053
|
const playheadRef = (0,external_react_.useRef)(null); // playhead element the camera positions
|
|
5851
6054
|
const trackRef = (0,external_react_.useRef)(null); // hover / tap target around the canvas
|
|
5852
6055
|
const wavesurferRef = (0,external_react_.useRef)(null); // WaveSurfer instance
|
|
6056
|
+
const rangeLayerRef = (0,external_react_.useRef)(null);
|
|
5853
6057
|
|
|
5854
6058
|
// Latest props for WaveSurfer + media listeners that must not re-subscribe each render.
|
|
5855
6059
|
const cameraModeRef = (0,external_react_.useRef)(cameraMode); // latest tape/desktop; WaveSurfer create() deps stay empty
|
|
@@ -5861,6 +6065,7 @@ function WaveformView({
|
|
|
5861
6065
|
const mediaElRef = (0,external_react_.useRef)(mediaEl); // latest <audio>/<video>; camera + playhead tick read this
|
|
5862
6066
|
const onPlayPauseRef = (0,external_react_.useRef)(onPlayPause); // latest play/pause; tape tap must not re-bind
|
|
5863
6067
|
const onSeekRef = (0,external_react_.useRef)(onSeek); // latest onSeek; click/scroll handlers must not re-bind
|
|
6068
|
+
const onRangeClearRef = (0,external_react_.useRef)(onRangeClear); // latest click-outside clear; WaveSurfer click must not re-bind
|
|
5864
6069
|
const onViewportChangeRef = (0,external_react_.useRef)(onViewportChange); // latest viewport callback; camera commits here
|
|
5865
6070
|
const peaksRef = (0,external_react_.useRef)(peaks); // latest peaks; WaveSurfer create() + morph read this
|
|
5866
6071
|
|
|
@@ -5877,6 +6082,7 @@ function WaveformView({
|
|
|
5877
6082
|
const pointerZoomClearTimerRef = (0,external_react_.useRef)(0); // clears pointerZoomRef after WAVEFORM_ZOOM_DISMISS_MS
|
|
5878
6083
|
const pointerZoomRef = (0,external_react_.useRef)(false); // pinch/wheel in progress; skip play/pause and tape recenter
|
|
5879
6084
|
const queuedTapeSeekTimeSecRef = (0,external_react_.useRef)(null); // seek time waiting for the next animation frame
|
|
6085
|
+
const rangeProgressRef = (0,external_react_.useRef)(null); // latest range progress; zoomed tile tint reads this
|
|
5880
6086
|
const suppressNextTapPlayPauseRef = (0,external_react_.useRef)(false); // swallow play/pause after a swipe or pinch
|
|
5881
6087
|
const suppressNextTapPlayPauseTimerRef = (0,external_react_.useRef)(0); // clears suppressNextTapPlayPauseRef
|
|
5882
6088
|
const suppressViewportSyncRef = (0,external_react_.useRef)(false); // ignore WaveSurfer zoom/scroll while we setOptions
|
|
@@ -5892,6 +6098,7 @@ function WaveformView({
|
|
|
5892
6098
|
mediaElRef.current = mediaEl;
|
|
5893
6099
|
onPlayPauseRef.current = onPlayPause;
|
|
5894
6100
|
onSeekRef.current = onSeek;
|
|
6101
|
+
onRangeClearRef.current = onRangeClear;
|
|
5895
6102
|
onViewportChangeRef.current = onViewportChange;
|
|
5896
6103
|
peaksRef.current = peaks;
|
|
5897
6104
|
const [internalZoom, setInternalZoom] = (0,external_react_.useState)(constants/* WAVEFORM_ZOOM_MIN */.LW);
|
|
@@ -5900,14 +6107,20 @@ function WaveformView({
|
|
|
5900
6107
|
const [overlayPortalHost, setOverlayPortalHost] = (0,external_react_.useState)(null);
|
|
5901
6108
|
const [canvasWidthPx, setCanvasWidthPx] = (0,external_react_.useState)(0);
|
|
5902
6109
|
const [scrollLeft, setScrollLeft] = (0,external_react_.useState)(0);
|
|
6110
|
+
const [previewRange, setPreviewRange] = (0,external_react_.useState)(null);
|
|
6111
|
+
const [isRangeDragging, setIsRangeDragging] = (0,external_react_.useState)(false);
|
|
6112
|
+
const isRangeDraggingRef = (0,external_react_.useRef)(false);
|
|
6113
|
+
const skipNextSeekRef = (0,external_react_.useRef)(false);
|
|
6114
|
+
const lastSetTimeSecRef = (0,external_react_.useRef)(null);
|
|
6115
|
+
const [isRangeHovered, setIsRangeHovered] = (0,external_react_.useState)(false);
|
|
5903
6116
|
const isControlled = typeof zoomLevelProp === 'number';
|
|
5904
|
-
const maxZoom = getWaveformZoomMax({
|
|
6117
|
+
const maxZoom = (0,waveform_viewport/* getWaveformZoomMax */.by)({
|
|
5905
6118
|
durationSec,
|
|
5906
6119
|
peakCount: peaks.length,
|
|
5907
6120
|
viewWidthPx: canvasWidthPx
|
|
5908
6121
|
});
|
|
5909
6122
|
hasZoomHandlersRef.current = maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW && (typeof onZoomChange === 'function' || typeof zoomLevelProp !== 'number');
|
|
5910
|
-
const zoomLevel = clampWaveformZoom(isControlled ? zoomLevelProp : internalZoom, maxZoom);
|
|
6123
|
+
const zoomLevel = (0,waveform_viewport/* clampWaveformZoom */.ii)(isControlled ? zoomLevelProp : internalZoom, maxZoom);
|
|
5911
6124
|
const zoomRef = (0,external_react_.useRef)(zoomLevel); // latest zoom for WaveSurfer redraw/zoom handlers
|
|
5912
6125
|
zoomRef.current = zoomLevel;
|
|
5913
6126
|
const prevZoomRef = (0,external_react_.useRef)(null); // last applied zoom; tape recenters only when this changes
|
|
@@ -5916,10 +6129,26 @@ function WaveformView({
|
|
|
5916
6129
|
const isScrollableWindow = isZoomed || isTape;
|
|
5917
6130
|
const bufferProgress = getBufferedProgress(bufferedRange, durationSec);
|
|
5918
6131
|
bufferProgressRef.current = bufferProgress;
|
|
5919
|
-
hoverProgressRef.current = hoverProgress;
|
|
5920
|
-
const
|
|
6132
|
+
hoverProgressRef.current = isRangeDragging ? null : hoverProgress;
|
|
6133
|
+
const activeRange = isRangeDragging ? previewRange ?? range : range;
|
|
6134
|
+
const activeRangeRef = (0,external_react_.useRef)(activeRange);
|
|
6135
|
+
activeRangeRef.current = activeRange;
|
|
6136
|
+
const durationMs = (0,waveform_range/* durationMsFromSec */.uH)(durationSec);
|
|
6137
|
+
const rangeStartMs = activeRange?.startMs;
|
|
6138
|
+
const rangeEndMs = activeRange?.endMs;
|
|
6139
|
+
const activeRangeProgress = (0,external_react_.useMemo)(() => {
|
|
6140
|
+
if (rangeStartMs == null || !Number.isFinite(rangeStartMs)) {
|
|
6141
|
+
return null;
|
|
6142
|
+
}
|
|
6143
|
+
return (0,waveform_range/* rangeProgress */.D$)((0,waveform_range/* resolveRange */.Ss)({
|
|
6144
|
+
endMs: rangeEndMs ?? null,
|
|
6145
|
+
startMs: rangeStartMs
|
|
6146
|
+
}, durationMs), durationMs);
|
|
6147
|
+
}, [durationMs, rangeEndMs, rangeStartMs]);
|
|
6148
|
+
rangeProgressRef.current = activeRangeProgress;
|
|
6149
|
+
const viewport = (0,external_react_.useMemo)(() => (0,waveform_viewport/* createWaveformViewport */.eq)({
|
|
5921
6150
|
durationSec,
|
|
5922
|
-
gutterPx: isTape ? getTapeGutterPx(canvasWidthPx) : 0,
|
|
6151
|
+
gutterPx: isTape ? (0,waveform_viewport/* getTapeGutterPx */.iA)(canvasWidthPx) : 0,
|
|
5923
6152
|
heightPx: height,
|
|
5924
6153
|
maxZoom,
|
|
5925
6154
|
scrollLeftPx: scrollLeft,
|
|
@@ -5928,6 +6157,7 @@ function WaveformView({
|
|
|
5928
6157
|
}), [canvasWidthPx, durationSec, height, isTape, maxZoom, scrollLeft, zoomLevel]);
|
|
5929
6158
|
const viewportRef = (0,external_react_.useRef)(viewport); // live scroll window; prefer this over render-state while the camera is moving
|
|
5930
6159
|
const onViewportCommit = (0,external_react_.useCallback)((scrollLeftPx, nextViewport, commitReactState = true) => {
|
|
6160
|
+
rangeLayerRef.current?.applyViewport(nextViewport);
|
|
5931
6161
|
onViewportChangeRef.current?.(nextViewport);
|
|
5932
6162
|
if (commitReactState) {
|
|
5933
6163
|
setScrollLeft(scrollLeftPx);
|
|
@@ -5976,7 +6206,7 @@ function WaveformView({
|
|
|
5976
6206
|
}, [isUserPanning]);
|
|
5977
6207
|
toggleTapePlaybackRef.current = toggleTapePlayback;
|
|
5978
6208
|
(0,external_react_.useLayoutEffect)(() => {
|
|
5979
|
-
viewportRef.current = createWaveformViewport({
|
|
6209
|
+
viewportRef.current = (0,waveform_viewport/* createWaveformViewport */.eq)({
|
|
5980
6210
|
durationSec: viewport.durationSec,
|
|
5981
6211
|
gutterPx: viewport.gutterPx,
|
|
5982
6212
|
heightPx: viewport.heightPx,
|
|
@@ -5987,7 +6217,7 @@ function WaveformView({
|
|
|
5987
6217
|
});
|
|
5988
6218
|
}, [viewport]);
|
|
5989
6219
|
const setZoomLevel = (0,external_react_.useCallback)(nextZoom => {
|
|
5990
|
-
const zoom = clampWaveformZoom(nextZoom, maxZoom);
|
|
6220
|
+
const zoom = (0,waveform_viewport/* clampWaveformZoom */.ii)(nextZoom, maxZoom);
|
|
5991
6221
|
if (!isControlled) {
|
|
5992
6222
|
setInternalZoom(zoom);
|
|
5993
6223
|
}
|
|
@@ -6042,7 +6272,8 @@ function WaveformView({
|
|
|
6042
6272
|
return;
|
|
6043
6273
|
}
|
|
6044
6274
|
const scrollLeftPx = WaveformView_getScrollLeft(wavesurfer);
|
|
6045
|
-
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
6275
|
+
viewportRef.current = (0,waveform_viewport/* getViewportAtScroll */.NI)(viewportRef.current, scrollLeftPx);
|
|
6276
|
+
rangeLayerRef.current?.applyViewport(viewportRef.current);
|
|
6046
6277
|
onViewportChangeRef.current?.(viewportRef.current);
|
|
6047
6278
|
setScrollLeft(scrollLeftPx);
|
|
6048
6279
|
}, []);
|
|
@@ -6052,12 +6283,14 @@ function WaveformView({
|
|
|
6052
6283
|
return;
|
|
6053
6284
|
}
|
|
6054
6285
|
if (isTape) {
|
|
6055
|
-
playhead.style.left = getTapePinnedPlayheadLeft();
|
|
6286
|
+
playhead.style.left = (0,waveform_viewport/* getTapePinnedPlayheadLeft */.yW)();
|
|
6056
6287
|
} else if (!isFollowPinned()) {
|
|
6057
|
-
playhead.style.left = timeLeftPercent(timeSec, durationSecRef.current, viewportRef.current);
|
|
6288
|
+
playhead.style.left = (0,waveform_viewport/* timeLeftPercent */.Mu)(timeSec, durationSecRef.current, viewportRef.current);
|
|
6058
6289
|
}
|
|
6290
|
+
rangeLayerRef.current?.applyViewport(viewportRef.current);
|
|
6059
6291
|
const wavesurfer = wavesurferRef.current;
|
|
6060
|
-
if (wavesurfer && wavesurfer.setTime) {
|
|
6292
|
+
if (wavesurfer && wavesurfer.setTime && lastSetTimeSecRef.current !== timeSec) {
|
|
6293
|
+
lastSetTimeSecRef.current = timeSec;
|
|
6061
6294
|
wavesurfer.setTime(timeSec);
|
|
6062
6295
|
}
|
|
6063
6296
|
}, [isFollowPinned, isTape]);
|
|
@@ -6070,14 +6303,14 @@ function WaveformView({
|
|
|
6070
6303
|
return;
|
|
6071
6304
|
}
|
|
6072
6305
|
const viewWidthPx = wavesurfer.getWidth ? wavesurfer.getWidth() : container.clientWidth;
|
|
6073
|
-
const minPxPerSec = getZoomedPixelsPerSecond({
|
|
6306
|
+
const minPxPerSec = (0,waveform_viewport/* getZoomedPixelsPerSecond */.J$)({
|
|
6074
6307
|
durationSec,
|
|
6075
6308
|
isTape,
|
|
6076
6309
|
maxZoom,
|
|
6077
6310
|
viewWidthPx,
|
|
6078
6311
|
zoomLevel
|
|
6079
6312
|
});
|
|
6080
|
-
const gutterPx = isTape ? getTapeGutterPx(viewWidthPx) : 0;
|
|
6313
|
+
const gutterPx = isTape ? (0,waveform_viewport/* getTapeGutterPx */.iA)(viewWidthPx) : 0;
|
|
6081
6314
|
const origin = isTape ? null : zoomOriginRef.current;
|
|
6082
6315
|
zoomOriginRef.current = null;
|
|
6083
6316
|
const didZoomChange = prevZoomRef.current !== zoomLevel;
|
|
@@ -6086,7 +6319,7 @@ function WaveformView({
|
|
|
6086
6319
|
}
|
|
6087
6320
|
suppressViewportSyncRef.current = true;
|
|
6088
6321
|
try {
|
|
6089
|
-
wavesurfer.setOptions(
|
|
6322
|
+
wavesurfer.setOptions(_objectSpread({
|
|
6090
6323
|
autoScroll: false,
|
|
6091
6324
|
fillParent: !isTape,
|
|
6092
6325
|
minPxPerSec
|
|
@@ -6096,7 +6329,7 @@ function WaveformView({
|
|
|
6096
6329
|
} : {}));
|
|
6097
6330
|
applyWaveformGutters(wavesurfer, gutterPx);
|
|
6098
6331
|
if (minPxPerSec > 0) {
|
|
6099
|
-
const windowViewport = createWaveformViewport({
|
|
6332
|
+
const windowViewport = (0,waveform_viewport/* createWaveformViewport */.eq)({
|
|
6100
6333
|
durationSec,
|
|
6101
6334
|
gutterPx,
|
|
6102
6335
|
heightPx: liveHeightRef.current || height,
|
|
@@ -6108,9 +6341,10 @@ function WaveformView({
|
|
|
6108
6341
|
if (origin) {
|
|
6109
6342
|
applyScrollLeft(origin.timeSec * minPxPerSec + gutterPx - origin.pointerX, true);
|
|
6110
6343
|
} else if (didZoomChange && (isTape || !pointerZoomRef.current)) {
|
|
6111
|
-
applyScrollLeft(getCenteredScrollLeft(currentTimeRef.current, windowViewport), true);
|
|
6344
|
+
applyScrollLeft((0,waveform_viewport/* getCenteredScrollLeft */.b6)(currentTimeRef.current, windowViewport), true);
|
|
6112
6345
|
}
|
|
6113
6346
|
}
|
|
6347
|
+
lastSetTimeSecRef.current = currentTimeRef.current;
|
|
6114
6348
|
wavesurfer.setTime(currentTimeRef.current);
|
|
6115
6349
|
} finally {
|
|
6116
6350
|
suppressViewportSyncRef.current = false;
|
|
@@ -6149,14 +6383,30 @@ function WaveformView({
|
|
|
6149
6383
|
waveColor: WAVEFORM_COLOR_UNPLAYED
|
|
6150
6384
|
});
|
|
6151
6385
|
const unsubscribeClick = wavesurfer.on('click', relativeX => {
|
|
6152
|
-
if (
|
|
6386
|
+
if (skipNextSeekRef.current) {
|
|
6387
|
+
skipNextSeekRef.current = false;
|
|
6153
6388
|
return;
|
|
6154
6389
|
}
|
|
6390
|
+
if (!interactiveRef.current || isRangeDraggingRef.current) {
|
|
6391
|
+
return;
|
|
6392
|
+
}
|
|
6393
|
+
const rangeDraft = activeRangeRef.current;
|
|
6394
|
+
const timeSec = relativeX * durationSecRef.current;
|
|
6395
|
+
if (rangeDraft && !(0,waveform_range/* isRangeCollapsed */.BT)(rangeDraft)) {
|
|
6396
|
+
const pointerX = (0,waveform_viewport/* positionPxFromTime */.TO)(timeSec, viewportRef.current);
|
|
6397
|
+
if (!(0,waveform_range/* isPointerOverRange */.H5)({
|
|
6398
|
+
pointerX,
|
|
6399
|
+
range: rangeDraft,
|
|
6400
|
+
viewport: viewportRef.current
|
|
6401
|
+
})) {
|
|
6402
|
+
onRangeClearRef.current?.();
|
|
6403
|
+
}
|
|
6404
|
+
}
|
|
6155
6405
|
if (cameraModeRef.current === 'tape') {
|
|
6156
6406
|
toggleTapePlaybackRef.current?.();
|
|
6157
6407
|
return;
|
|
6158
6408
|
}
|
|
6159
|
-
onSeekRef.current?.(
|
|
6409
|
+
onSeekRef.current?.(timeSec);
|
|
6160
6410
|
});
|
|
6161
6411
|
const unsubscribeScroll = wavesurfer.on('scroll', () => {
|
|
6162
6412
|
if (suppressViewportSyncRef.current) {
|
|
@@ -6169,6 +6419,7 @@ function WaveformView({
|
|
|
6169
6419
|
}
|
|
6170
6420
|
syncViewport();
|
|
6171
6421
|
});
|
|
6422
|
+
rangeLayerRef.current?.applyViewport(viewportRef.current);
|
|
6172
6423
|
});
|
|
6173
6424
|
const unsubscribeZoom = wavesurfer.on('zoom', () => {
|
|
6174
6425
|
if (suppressViewportSyncRef.current) {
|
|
@@ -6183,11 +6434,13 @@ function WaveformView({
|
|
|
6183
6434
|
tintZoomedWaveform(wavesurfer, getWaveformFills({
|
|
6184
6435
|
bufferProgress: bufferProgressRef.current,
|
|
6185
6436
|
hoverProgress: cameraModeRef.current === 'tape' ? null : hoverProgressRef.current,
|
|
6186
|
-
isTape: cameraModeRef.current === 'tape'
|
|
6437
|
+
isTape: cameraModeRef.current === 'tape',
|
|
6438
|
+
rangeProgress: rangeProgressRef.current
|
|
6187
6439
|
}), true);
|
|
6188
6440
|
});
|
|
6189
6441
|
wavesurferRef.current = wavesurfer;
|
|
6190
6442
|
displayedPeaksRef.current = peaksRef.current;
|
|
6443
|
+
lastSetTimeSecRef.current = null;
|
|
6191
6444
|
disableScrollOverscroll(container);
|
|
6192
6445
|
syncViewport();
|
|
6193
6446
|
applyZoomWindowRef.current?.();
|
|
@@ -6205,6 +6458,7 @@ function WaveformView({
|
|
|
6205
6458
|
wavesurfer.destroy();
|
|
6206
6459
|
wavesurferRef.current = null;
|
|
6207
6460
|
displayedPeaksRef.current = null;
|
|
6461
|
+
lastSetTimeSecRef.current = null;
|
|
6208
6462
|
};
|
|
6209
6463
|
}, [cancelJump, handleCameraScroll, handleTapeSwipe, height, isUserPanning, releaseUserPanHold, syncViewport]);
|
|
6210
6464
|
(0,external_react_.useLayoutEffect)(() => {
|
|
@@ -6245,7 +6499,7 @@ function WaveformView({
|
|
|
6245
6499
|
}, [syncViewport]);
|
|
6246
6500
|
(0,external_react_.useEffect)(() => {
|
|
6247
6501
|
const rawZoom = isControlled ? zoomLevelProp : internalZoom;
|
|
6248
|
-
const clamped = clampWaveformZoom(typeof rawZoom === 'number' ? rawZoom : constants/* WAVEFORM_ZOOM_MIN */.LW, maxZoom);
|
|
6502
|
+
const clamped = (0,waveform_viewport/* clampWaveformZoom */.ii)(typeof rawZoom === 'number' ? rawZoom : constants/* WAVEFORM_ZOOM_MIN */.LW, maxZoom);
|
|
6249
6503
|
if (clamped === rawZoom) {
|
|
6250
6504
|
return;
|
|
6251
6505
|
}
|
|
@@ -6359,7 +6613,8 @@ function WaveformView({
|
|
|
6359
6613
|
const fills = getWaveformFills({
|
|
6360
6614
|
bufferProgress,
|
|
6361
6615
|
hoverProgress: isTape ? null : hoverProgress,
|
|
6362
|
-
isTape
|
|
6616
|
+
isTape,
|
|
6617
|
+
rangeProgress: activeRangeProgress
|
|
6363
6618
|
});
|
|
6364
6619
|
if (isScrollableWindow) {
|
|
6365
6620
|
tintZoomedWaveform(wavesurfer, fills);
|
|
@@ -6369,8 +6624,9 @@ function WaveformView({
|
|
|
6369
6624
|
progressColor: toCanvasFill(fills.progressColor, devicePixelWidth(canvasWidthPx)),
|
|
6370
6625
|
waveColor: toCanvasFill(fills.waveColor, devicePixelWidth(canvasWidthPx))
|
|
6371
6626
|
});
|
|
6627
|
+
lastSetTimeSecRef.current = currentTimeRef.current;
|
|
6372
6628
|
wavesurfer.setTime(currentTimeRef.current);
|
|
6373
|
-
}, [bufferProgress, canvasWidthPx, hoverProgress, isScrollableWindow, isTape]);
|
|
6629
|
+
}, [activeRangeProgress, bufferProgress, canvasWidthPx, hoverProgress, isRangeDragging, isScrollableWindow, isTape, isZoomed]);
|
|
6374
6630
|
(0,external_react_.useEffect)(() => {
|
|
6375
6631
|
const track = trackRef.current;
|
|
6376
6632
|
if (!track) {
|
|
@@ -6451,11 +6707,11 @@ function WaveformView({
|
|
|
6451
6707
|
};
|
|
6452
6708
|
}, [durationSec, markPointerZoom, setZoomLevel]);
|
|
6453
6709
|
const onHoverMove = (0,external_react_.useCallback)(event => {
|
|
6454
|
-
if (
|
|
6710
|
+
if (isTape || isTouchHoverInput(event)) {
|
|
6455
6711
|
return;
|
|
6456
6712
|
}
|
|
6457
6713
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
6458
|
-
if (!(rect.width > 0)
|
|
6714
|
+
if (!(rect.width > 0)) {
|
|
6459
6715
|
return;
|
|
6460
6716
|
}
|
|
6461
6717
|
const pointerX = event.clientX - rect.left;
|
|
@@ -6463,20 +6719,48 @@ function WaveformView({
|
|
|
6463
6719
|
return;
|
|
6464
6720
|
}
|
|
6465
6721
|
const vp = viewportRef.current;
|
|
6722
|
+
const rangeDraft = activeRangeRef.current;
|
|
6723
|
+
setIsRangeHovered(!!rangeDraft && (0,waveform_range/* isPointerOverRange */.H5)({
|
|
6724
|
+
pointerX,
|
|
6725
|
+
range: rangeDraft,
|
|
6726
|
+
viewport: vp
|
|
6727
|
+
}));
|
|
6728
|
+
if (!interactive || isRangeDraggingRef.current || !(durationSec > 0)) {
|
|
6729
|
+
return;
|
|
6730
|
+
}
|
|
6466
6731
|
if (vp.pixelsPerSecond > 0) {
|
|
6467
|
-
setHoverProgress(Math.min(1, Math.max(0, timeFromPositionPx(pointerX, vp) / durationSec)));
|
|
6732
|
+
setHoverProgress(Math.min(1, Math.max(0, (0,waveform_viewport/* timeFromPositionPx */.lZ)(pointerX, vp) / durationSec)));
|
|
6468
6733
|
return;
|
|
6469
6734
|
}
|
|
6470
6735
|
setHoverProgress(Math.min(1, Math.max(0, pointerX / rect.width)));
|
|
6471
6736
|
}, [durationSec, interactive, isTape]);
|
|
6472
6737
|
const onHoverLeave = (0,external_react_.useCallback)(() => {
|
|
6473
6738
|
setHoverProgress(null);
|
|
6739
|
+
setIsRangeHovered(false);
|
|
6740
|
+
}, []);
|
|
6741
|
+
const handleRangeDragChange = (0,external_react_.useCallback)(isDragging => {
|
|
6742
|
+
isRangeDraggingRef.current = isDragging;
|
|
6743
|
+
setIsRangeDragging(isDragging);
|
|
6744
|
+
if (isDragging) {
|
|
6745
|
+
setHoverProgress(null);
|
|
6746
|
+
} else {
|
|
6747
|
+
skipNextSeekRef.current = true;
|
|
6748
|
+
window.setTimeout(() => {
|
|
6749
|
+
skipNextSeekRef.current = false;
|
|
6750
|
+
}, 0);
|
|
6751
|
+
setPreviewRange(null);
|
|
6752
|
+
}
|
|
6753
|
+
onRangeDragChange?.(isDragging);
|
|
6754
|
+
}, [onRangeDragChange]);
|
|
6755
|
+
const getPlayheadSec = (0,external_react_.useCallback)(() => {
|
|
6756
|
+
return mediaElRef.current ? mediaElRef.current.currentTime : currentTimeRef.current;
|
|
6474
6757
|
}, []);
|
|
6475
6758
|
const bindOverlayPortalHost = (0,external_react_.useCallback)(node => {
|
|
6476
6759
|
const host = node?.parentElement ?? null;
|
|
6477
6760
|
setOverlayPortalHost(prev => prev === host ? prev : host);
|
|
6478
6761
|
}, []);
|
|
6479
|
-
const hoverLeft = hoverProgress == null ? null : timeLeftPercent(hoverProgress * durationSec, durationSec, viewportRef.current);
|
|
6762
|
+
const hoverLeft = isRangeDragging || hoverProgress == null ? null : (0,waveform_viewport/* timeLeftPercent */.Mu)(hoverProgress * durationSec, durationSec, viewportRef.current);
|
|
6763
|
+
const showRangeOverlay = Boolean(range) && (isRangeDragging || !isPlaying || !(0,waveform_range/* isRangeCollapsed */.BT)(range));
|
|
6480
6764
|
const scrubTimeChip = isTape && scrubPreviewTimeSec != null ? /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6481
6765
|
className: "bp-WaveformView-hover bp-WaveformView-hover--tape",
|
|
6482
6766
|
"data-testid": "bp-waveform-hover"
|
|
@@ -6518,7 +6802,20 @@ function WaveformView({
|
|
|
6518
6802
|
"aria-hidden": "true",
|
|
6519
6803
|
className: "bp-WaveformView-playhead",
|
|
6520
6804
|
"data-testid": "bp-waveform-playhead"
|
|
6521
|
-
}),
|
|
6805
|
+
}), showRangeOverlay && range && /*#__PURE__*/external_react_["default"].createElement(waveform_WaveformRangeSelection, {
|
|
6806
|
+
ref: rangeLayerRef,
|
|
6807
|
+
currentTimeSec: currentTime,
|
|
6808
|
+
durationSec: durationSec,
|
|
6809
|
+
getPlayheadSec: getPlayheadSec,
|
|
6810
|
+
interactive: interactive,
|
|
6811
|
+
isHighlighted: isRangeDragging || isRangeHovered,
|
|
6812
|
+
keepHighlight: true,
|
|
6813
|
+
onDragChange: handleRangeDragChange,
|
|
6814
|
+
onPreviewChange: setPreviewRange,
|
|
6815
|
+
onRangeChange: interactive ? onRangeChange : undefined,
|
|
6816
|
+
range: range,
|
|
6817
|
+
viewport: viewport
|
|
6818
|
+
}), hoverLeft != null && hoverProgress != null && !isRangeDragging && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6522
6819
|
className: "bp-WaveformView-hover",
|
|
6523
6820
|
"data-testid": "bp-waveform-hover",
|
|
6524
6821
|
style: {
|
|
@@ -6620,8 +6917,9 @@ function WaveformZoomControl({
|
|
|
6620
6917
|
const zoomControlElRef = (0,external_react_.useRef)(null); // root; outside pointerdown unpins the flyout
|
|
6621
6918
|
const dismissTimerRef = (0,external_react_.useRef)(0); // delay before hover-close of the flyout
|
|
6622
6919
|
const sliderId = `bp-waveform-zoom-slider${(0,external_react_.useId)()}`;
|
|
6623
|
-
const zoom = clampWaveformZoom(zoomLevel, maxZoom);
|
|
6624
|
-
const zoomValue = Math.round(sliderValueFromZoom(zoom, maxZoom));
|
|
6920
|
+
const zoom = (0,waveform_viewport/* clampWaveformZoom */.ii)(zoomLevel, maxZoom);
|
|
6921
|
+
const zoomValue = Math.round((0,waveform_viewport/* sliderValueFromZoom */.Iw)(zoom, maxZoom));
|
|
6922
|
+
const zoomMultiplier = (0,waveform_viewport/* getWaveformZoomMultiplier */.gd)(zoom);
|
|
6625
6923
|
const isOpen = isHovered || isFocused || isRevealed || isPinned;
|
|
6626
6924
|
const isAtMinZoom = zoomValue <= 0;
|
|
6627
6925
|
const isAtMaxZoom = zoomValue >= constants/* WAVEFORM_ZOOM_SLIDER_MAX */.nh;
|
|
@@ -6647,11 +6945,11 @@ function WaveformZoomControl({
|
|
|
6647
6945
|
return () => document.removeEventListener('pointerdown', closeIfOutside);
|
|
6648
6946
|
}, [isPinned]);
|
|
6649
6947
|
const handleSlider = (0,external_react_.useCallback)(newValue => {
|
|
6650
|
-
onZoomChange(zoomFromSliderValue(newValue, maxZoom));
|
|
6948
|
+
onZoomChange((0,waveform_viewport/* zoomFromSliderValue */.eU)(newValue, maxZoom));
|
|
6651
6949
|
}, [maxZoom, onZoomChange]);
|
|
6652
6950
|
const handleStep = (0,external_react_.useCallback)(delta => {
|
|
6653
|
-
onZoomChange(
|
|
6654
|
-
}, [maxZoom, onZoomChange,
|
|
6951
|
+
onZoomChange((0,waveform_viewport/* stepWaveformZoom */.xV)(zoom, maxZoom, delta));
|
|
6952
|
+
}, [maxZoom, onZoomChange, zoom]);
|
|
6655
6953
|
const handleZoomInPointerDown = (0,external_react_.useCallback)(() => {
|
|
6656
6954
|
wasFlyoutOpenOnPointerDownRef.current = isHovered || isFocused || isRevealed || isPinned;
|
|
6657
6955
|
}, [isFocused, isHovered, isPinned, isRevealed]);
|
|
@@ -6668,6 +6966,7 @@ function WaveformZoomControl({
|
|
|
6668
6966
|
ref: zoomControlElRef,
|
|
6669
6967
|
"aria-label": "Zoom",
|
|
6670
6968
|
className: classnames_default()('bp-WaveformZoomControl', {
|
|
6969
|
+
'bp-has-multiplier': zoomMultiplier,
|
|
6671
6970
|
'bp-is-open': isOpen
|
|
6672
6971
|
}),
|
|
6673
6972
|
"data-testid": "bp-waveform-zoom",
|
|
@@ -6693,7 +6992,15 @@ function WaveformZoomControl({
|
|
|
6693
6992
|
}, constants/* WAVEFORM_ZOOM_DISMISS_MS */.m6);
|
|
6694
6993
|
},
|
|
6695
6994
|
role: "group"
|
|
6696
|
-
}, /*#__PURE__*/external_react_["default"].createElement(
|
|
6995
|
+
}, zoomMultiplier && /*#__PURE__*/external_react_["default"].createElement(external_react_["default"].Fragment, null, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
6996
|
+
className: "bp-WaveformZoomControl-multiplier",
|
|
6997
|
+
"data-testid": "bp-waveform-zoom-multiplier",
|
|
6998
|
+
title: "Current zoom level"
|
|
6999
|
+
}, zoomMultiplier), /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
7000
|
+
"aria-hidden": "true",
|
|
7001
|
+
className: "bp-WaveformZoomControl-divider",
|
|
7002
|
+
"data-testid": "bp-waveform-zoom-divider"
|
|
7003
|
+
})), /*#__PURE__*/external_react_["default"].createElement(MediaToggle/* default */.A, {
|
|
6697
7004
|
"aria-disabled": isOpen && isAtMaxZoom,
|
|
6698
7005
|
className: "bp-WaveformZoomControl-button",
|
|
6699
7006
|
"data-resin-target": "waveformZoomIn",
|
|
@@ -6754,23 +7061,34 @@ function WaveformZoomControl({
|
|
|
6754
7061
|
|
|
6755
7062
|
|
|
6756
7063
|
|
|
7064
|
+
|
|
6757
7065
|
const PLACEHOLDER_PEAKS = placeholderPeaks();
|
|
6758
7066
|
function MP3ControlsV2({
|
|
6759
7067
|
autoplay,
|
|
6760
7068
|
bufferedRange,
|
|
6761
7069
|
commentMarkers,
|
|
7070
|
+
commentRangeDraft = null,
|
|
6762
7071
|
currentTime,
|
|
6763
7072
|
durationTime,
|
|
7073
|
+
hasStartedPlayback = false,
|
|
7074
|
+
isGeneratingWaveform = false,
|
|
6764
7075
|
isPlaying,
|
|
7076
|
+
keyboardVolumeStep = 0,
|
|
7077
|
+
keyboardZoomStep = 0,
|
|
6765
7078
|
mediaEl,
|
|
6766
7079
|
onAutoplayChange,
|
|
6767
7080
|
onCommentMarkerClick,
|
|
7081
|
+
onCommentRangeChange,
|
|
7082
|
+
onCommentRangeClear,
|
|
7083
|
+
onCommentRangeDragChange,
|
|
6768
7084
|
onMuteChange,
|
|
6769
7085
|
onPlayPause,
|
|
7086
|
+
onPlayNextChange,
|
|
6770
7087
|
onRateChange,
|
|
6771
7088
|
onTimeChange,
|
|
6772
7089
|
onVolumeChange,
|
|
6773
7090
|
peaks,
|
|
7091
|
+
playNext,
|
|
6774
7092
|
rate,
|
|
6775
7093
|
volume
|
|
6776
7094
|
}) {
|
|
@@ -6785,14 +7103,15 @@ function MP3ControlsV2({
|
|
|
6785
7103
|
const hasRealPeaks = !!(peaks && peaks.length);
|
|
6786
7104
|
const waveformPeaks = hasRealPeaks ? peaks : PLACEHOLDER_PEAKS;
|
|
6787
7105
|
const waveformDurationSec = hasWaveformDuration ? durationValue : PLACEHOLDER_DURATION_SEC;
|
|
6788
|
-
const [playRequested, setPlayRequested] = (0,external_react_.useState)(
|
|
7106
|
+
const [playRequested, setPlayRequested] = (0,external_react_.useState)(hasStartedPlayback);
|
|
6789
7107
|
const [viewport, setViewport] = (0,external_react_.useState)(null);
|
|
6790
7108
|
const isTape = useTapeWaveform();
|
|
6791
7109
|
const hasAppliedTapeDefaultZoomRef = (0,external_react_.useRef)(false); // ~10s window applied; reset to 1× when leaving tape
|
|
7110
|
+
const lastKeyboardZoomStepRef = (0,external_react_.useRef)(0); // last +/− step applied; skip re-step when maxZoom retriggers the effect
|
|
6792
7111
|
const userChangedTapeZoomRef = (0,external_react_.useRef)(false); // pinch/wheel zoom; skip re-applying the 10s default
|
|
6793
7112
|
const handleViewportChange = (0,external_react_.useCallback)(next => {
|
|
6794
7113
|
setMaxZoom(prev => prev === next.maxZoom ? prev : next.maxZoom);
|
|
6795
|
-
setViewport(prev => viewportEquals(prev, next) ? prev : next);
|
|
7114
|
+
setViewport(prev => (0,waveform_viewport/* viewportEquals */.KH)(prev, next) ? prev : next);
|
|
6796
7115
|
}, []);
|
|
6797
7116
|
const revealZoomControl = (0,external_react_.useCallback)(() => {
|
|
6798
7117
|
setIsZoomRevealed(true);
|
|
@@ -6808,7 +7127,20 @@ function MP3ControlsV2({
|
|
|
6808
7127
|
revealZoomControl();
|
|
6809
7128
|
}, [revealZoomControl]);
|
|
6810
7129
|
(0,external_react_.useEffect)(() => {
|
|
6811
|
-
|
|
7130
|
+
const steps = keyboardZoomStep - lastKeyboardZoomStepRef.current;
|
|
7131
|
+
if (!steps) {
|
|
7132
|
+
return;
|
|
7133
|
+
}
|
|
7134
|
+
lastKeyboardZoomStepRef.current = keyboardZoomStep;
|
|
7135
|
+
if (!(maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW)) {
|
|
7136
|
+
return;
|
|
7137
|
+
}
|
|
7138
|
+
userChangedTapeZoomRef.current = true;
|
|
7139
|
+
setZoomLevel(prev => (0,waveform_viewport/* stepWaveformZoom */.xV)(prev, maxZoom, steps * constants/* WAVEFORM_ZOOM_BUTTON_STEP */.QD));
|
|
7140
|
+
revealZoomControl();
|
|
7141
|
+
}, [keyboardZoomStep, maxZoom, revealZoomControl]);
|
|
7142
|
+
(0,external_react_.useEffect)(() => {
|
|
7143
|
+
setZoomLevel(prev => (0,waveform_viewport/* clampWaveformZoom */.ii)(prev, maxZoom));
|
|
6812
7144
|
}, [maxZoom]);
|
|
6813
7145
|
(0,external_react_.useEffect)(() => {
|
|
6814
7146
|
if (!isTape) {
|
|
@@ -6826,16 +7158,16 @@ function MP3ControlsV2({
|
|
|
6826
7158
|
hasAppliedTapeDefaultZoomRef.current = true;
|
|
6827
7159
|
return;
|
|
6828
7160
|
}
|
|
6829
|
-
const nextZoom = getTapeDefaultZoom(durationValue, Math.max(maxZoom, viewport.maxZoom));
|
|
7161
|
+
const nextZoom = (0,waveform_viewport/* getTapeDefaultZoom */.lz)(durationValue, Math.max(maxZoom, viewport.maxZoom));
|
|
6830
7162
|
hasAppliedTapeDefaultZoomRef.current = true;
|
|
6831
7163
|
setZoomLevel(prev => prev === nextZoom ? prev : nextZoom);
|
|
6832
7164
|
}, [durationValue, hasRealPeaks, hasWaveformDuration, isTape, maxZoom, viewport]);
|
|
6833
7165
|
(0,external_react_.useEffect)(() => () => window.clearTimeout(zoomRevealTimerRef.current), []);
|
|
6834
7166
|
(0,external_react_.useEffect)(() => {
|
|
6835
|
-
if (isPlaying) {
|
|
7167
|
+
if (isPlaying || hasStartedPlayback) {
|
|
6836
7168
|
setPlayRequested(true);
|
|
6837
7169
|
}
|
|
6838
|
-
}, [isPlaying]);
|
|
7170
|
+
}, [hasStartedPlayback, isPlaying]);
|
|
6839
7171
|
const handlePlayOverlayClick = (0,external_react_.useCallback)(() => {
|
|
6840
7172
|
setPlayRequested(true);
|
|
6841
7173
|
onPlayPause(true);
|
|
@@ -6853,11 +7185,13 @@ function MP3ControlsV2({
|
|
|
6853
7185
|
}
|
|
6854
7186
|
onTimeChange(marker.time);
|
|
6855
7187
|
}, [onCommentMarkerClick, onPlayPause, onTimeChange]);
|
|
6856
|
-
const
|
|
6857
|
-
const
|
|
6858
|
-
const
|
|
7188
|
+
const hasStarted = playRequested || hasStartedPlayback;
|
|
7189
|
+
const isWaveformInteractive = hasStarted && hasMediaMetadata;
|
|
7190
|
+
const isWaitingToPlay = hasStarted && !hasMediaMetadata;
|
|
7191
|
+
const showPlayOverlay = !hasStarted && !isPlaying;
|
|
6859
7192
|
const hasZoomHandlers = hasRealPeaks && !showPlayOverlay;
|
|
6860
7193
|
const hasZoomControl = hasZoomHandlers && hasMediaMetadata && maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
7194
|
+
const showGeneratingWaveformIndicator = isGeneratingWaveform && !hasRealPeaks;
|
|
6861
7195
|
const waveformZoomLevel = isTape || hasZoomHandlers ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
6862
7196
|
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6863
7197
|
className: "bp-MP3ControlsV2",
|
|
@@ -6875,10 +7209,14 @@ function MP3ControlsV2({
|
|
|
6875
7209
|
isPlaying: isPlaying,
|
|
6876
7210
|
mediaEl: mediaEl,
|
|
6877
7211
|
onPlayPause: isWaveformInteractive ? onPlayPause : undefined,
|
|
7212
|
+
onRangeChange: isWaveformInteractive ? onCommentRangeChange : undefined,
|
|
7213
|
+
onRangeClear: isWaveformInteractive ? onCommentRangeClear : undefined,
|
|
7214
|
+
onRangeDragChange: onCommentRangeDragChange,
|
|
6878
7215
|
onSeek: isWaveformInteractive ? onTimeChange : undefined,
|
|
6879
7216
|
onViewportChange: hasRealPeaks ? handleViewportChange : undefined,
|
|
6880
7217
|
onZoomChange: hasZoomHandlers ? handleWaveformZoom : undefined,
|
|
6881
7218
|
peaks: waveformPeaks,
|
|
7219
|
+
range: commentRangeDraft,
|
|
6882
7220
|
zoomLevel: waveformZoomLevel
|
|
6883
7221
|
}), /*#__PURE__*/external_react_["default"].createElement(WaveformCommentMarkers, {
|
|
6884
7222
|
commentMarkers: waveformMarkers,
|
|
@@ -6887,9 +7225,9 @@ function MP3ControlsV2({
|
|
|
6887
7225
|
onCommentMarkerClick: handleCommentMarkerClick,
|
|
6888
7226
|
selectedId: selectedMarkerId,
|
|
6889
7227
|
viewport: viewport
|
|
6890
|
-
})), hasZoomControl && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
7228
|
+
})), (showGeneratingWaveformIndicator || hasZoomControl) && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6891
7229
|
className: "bp-MP3ControlsV2-waveformZoom"
|
|
6892
|
-
}, /*#__PURE__*/external_react_["default"].createElement(WaveformZoomControl, {
|
|
7230
|
+
}, showGeneratingWaveformIndicator ? /*#__PURE__*/external_react_["default"].createElement(WaveformGeneratingIndicator, null) : /*#__PURE__*/external_react_["default"].createElement(WaveformZoomControl, {
|
|
6893
7231
|
isRevealed: isZoomRevealed,
|
|
6894
7232
|
maxZoom: maxZoom,
|
|
6895
7233
|
onZoomChange: handleWaveformZoom,
|
|
@@ -6926,7 +7264,8 @@ function MP3ControlsV2({
|
|
|
6926
7264
|
durationTime: durationValue
|
|
6927
7265
|
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6928
7266
|
className: "bp-MP3ControlsV2-group"
|
|
6929
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
7267
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
7268
|
+
keyboardVolumeStep: keyboardVolumeStep,
|
|
6930
7269
|
onMuteChange: onMuteChange,
|
|
6931
7270
|
onVolumeChange: onVolumeChange,
|
|
6932
7271
|
volume: volume
|
|
@@ -6934,7 +7273,9 @@ function MP3ControlsV2({
|
|
|
6934
7273
|
autoplay: autoplay,
|
|
6935
7274
|
className: "bp-MP3Controls-settings",
|
|
6936
7275
|
onAutoplayChange: onAutoplayChange,
|
|
7276
|
+
onPlayNextChange: onPlayNextChange,
|
|
6937
7277
|
onRateChange: onRateChange,
|
|
7278
|
+
playNext: playNext,
|
|
6938
7279
|
rate: rate
|
|
6939
7280
|
}))));
|
|
6940
7281
|
}
|
|
@@ -7013,11 +7354,13 @@ function isFpsAvailable(player) {
|
|
|
7013
7354
|
|
|
7014
7355
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
7015
7356
|
/* harmony export */ Av: () => (/* binding */ WAVEFORM_TAPE_DEFAULT_WINDOW_SEC),
|
|
7357
|
+
/* harmony export */ BG: () => (/* binding */ WAVEFORM_RANGE_COLLAPSED_OFFSET_PX),
|
|
7016
7358
|
/* harmony export */ Bq: () => (/* binding */ WAVEFORM_PLAYHEAD_JUMP_MS),
|
|
7017
7359
|
/* harmony export */ DY: () => (/* binding */ WAVEFORM_BAR_RADIUS),
|
|
7018
7360
|
/* harmony export */ EB: () => (/* binding */ CLIENT_DECODE_MAX_COMPRESSED_BYTES),
|
|
7019
7361
|
/* harmony export */ FY: () => (/* binding */ MAX_PEAK_COUNT),
|
|
7020
7362
|
/* harmony export */ GQ: () => (/* binding */ DURATION_MISMATCH_TOLERANCE_SEC),
|
|
7363
|
+
/* harmony export */ IQ: () => (/* binding */ WAVEFORM_RANGE_SNAP_PX),
|
|
7021
7364
|
/* harmony export */ Kl: () => (/* binding */ WAVEFORM_MIN_VIEW_WINDOW_SEC),
|
|
7022
7365
|
/* harmony export */ LW: () => (/* binding */ WAVEFORM_ZOOM_MIN),
|
|
7023
7366
|
/* harmony export */ Le: () => (/* binding */ TAPE_POINTER_MEDIA_QUERY),
|
|
@@ -7026,8 +7369,10 @@ function isFpsAvailable(player) {
|
|
|
7026
7369
|
/* harmony export */ QD: () => (/* binding */ WAVEFORM_ZOOM_BUTTON_STEP),
|
|
7027
7370
|
/* harmony export */ XS: () => (/* binding */ WAVEFORM_BAR_MIN_HEIGHT),
|
|
7028
7371
|
/* harmony export */ Zs: () => (/* binding */ WAVEFORM_FOLLOW_SCROLL_SETTLE_MS),
|
|
7372
|
+
/* harmony export */ bX: () => (/* binding */ WAVEFORM_RANGE_MIN_DURATION_MS),
|
|
7029
7373
|
/* harmony export */ f3: () => (/* binding */ CLIENT_DECODE_PEAK_COUNT),
|
|
7030
7374
|
/* harmony export */ fI: () => (/* binding */ WAVEFORM_TAPE_CLICK_SUPPRESS_MS),
|
|
7375
|
+
/* harmony export */ h1: () => (/* binding */ WAVEFORM_RANGE_HANDLE_LINE_PX),
|
|
7031
7376
|
/* harmony export */ i8: () => (/* binding */ PEAK_UNIT_MAX),
|
|
7032
7377
|
/* harmony export */ m6: () => (/* binding */ WAVEFORM_ZOOM_DISMISS_MS),
|
|
7033
7378
|
/* harmony export */ mJ: () => (/* binding */ PEAK_UNIT_MIN),
|
|
@@ -7035,10 +7380,12 @@ function isFpsAvailable(player) {
|
|
|
7035
7380
|
/* harmony export */ nh: () => (/* binding */ WAVEFORM_ZOOM_SLIDER_MAX),
|
|
7036
7381
|
/* harmony export */ oN: () => (/* binding */ WAVEFORM_HEIGHT),
|
|
7037
7382
|
/* harmony export */ qY: () => (/* binding */ MAX_PAYLOAD_BYTES),
|
|
7383
|
+
/* harmony export */ r0: () => (/* binding */ WAVEFORM_RANGE_HIT_AREA_PX),
|
|
7038
7384
|
/* harmony export */ sh: () => (/* binding */ WAVEFORM_PAYLOAD_VERSION),
|
|
7039
7385
|
/* harmony export */ tK: () => (/* binding */ WAVEFORM_ZOOM_MAX),
|
|
7040
7386
|
/* harmony export */ zo: () => (/* binding */ WAVEFORM_BAR_WIDTH)
|
|
7041
7387
|
/* harmony export */ });
|
|
7388
|
+
/* unused harmony exports WAVEFORM_RANGE_PLAYHEAD_GAP_PX, WAVEFORM_RANGE_GRIP_IN_MS, WAVEFORM_RANGE_GRIP_OUT_MS */
|
|
7042
7389
|
/** Current waveform payload schema version. Bump only with a migration path. */
|
|
7043
7390
|
const WAVEFORM_PAYLOAD_VERSION = 1;
|
|
7044
7391
|
|
|
@@ -7088,6 +7435,24 @@ const WAVEFORM_BAR_RADIUS = WAVEFORM_BAR_WIDTH / 2;
|
|
|
7088
7435
|
const WAVEFORM_BAR_MIN_HEIGHT = WAVEFORM_BAR_WIDTH;
|
|
7089
7436
|
const WAVEFORM_HEIGHT = 140;
|
|
7090
7437
|
|
|
7438
|
+
/** Hit target centered on each range handle line. */
|
|
7439
|
+
const WAVEFORM_RANGE_HIT_AREA_PX = 24;
|
|
7440
|
+
/** Visible handle line and playhead width. */
|
|
7441
|
+
const WAVEFORM_RANGE_HANDLE_LINE_PX = 2;
|
|
7442
|
+
/** Screen gap between the playhead and each collapsed handle line. */
|
|
7443
|
+
const WAVEFORM_RANGE_PLAYHEAD_GAP_PX = 1;
|
|
7444
|
+
/**
|
|
7445
|
+
* Offset of each collapsed handle from the timestamp/playhead center so the
|
|
7446
|
+
* 2px lines sit 1px left and right of the 2px playhead.
|
|
7447
|
+
*/
|
|
7448
|
+
const WAVEFORM_RANGE_COLLAPSED_OFFSET_PX = WAVEFORM_RANGE_HANDLE_LINE_PX / 2 + WAVEFORM_RANGE_PLAYHEAD_GAP_PX + WAVEFORM_RANGE_HANDLE_LINE_PX / 2;
|
|
7449
|
+
/** Snap a dragging handle to the playhead when this close. */
|
|
7450
|
+
const WAVEFORM_RANGE_SNAP_PX = 8;
|
|
7451
|
+
/** Shortest committed range. Collapsed drafts (`endMs: null`) are exempt. */
|
|
7452
|
+
const WAVEFORM_RANGE_MIN_DURATION_MS = 250;
|
|
7453
|
+
const WAVEFORM_RANGE_GRIP_IN_MS = 150;
|
|
7454
|
+
const WAVEFORM_RANGE_GRIP_OUT_MS = 100;
|
|
7455
|
+
|
|
7091
7456
|
/***/ },
|
|
7092
7457
|
|
|
7093
7458
|
/***/ 4971
|
|
@@ -7642,6 +8007,221 @@ function loadPeaks(request) {
|
|
|
7642
8007
|
|
|
7643
8008
|
/***/ },
|
|
7644
8009
|
|
|
8010
|
+
/***/ 4253
|
|
8011
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
8012
|
+
|
|
8013
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8014
|
+
/* harmony export */ BT: () => (/* binding */ isRangeCollapsed),
|
|
8015
|
+
/* harmony export */ D$: () => (/* binding */ rangeProgress),
|
|
8016
|
+
/* harmony export */ Eh: () => (/* binding */ visualRangeHandlePx),
|
|
8017
|
+
/* harmony export */ H5: () => (/* binding */ isPointerOverRange),
|
|
8018
|
+
/* harmony export */ HG: () => (/* binding */ pickRangeHandle),
|
|
8019
|
+
/* harmony export */ Mh: () => (/* binding */ snapTimeMs),
|
|
8020
|
+
/* harmony export */ Mo: () => (/* binding */ dragRangeHandle),
|
|
8021
|
+
/* harmony export */ Ss: () => (/* binding */ resolveRange),
|
|
8022
|
+
/* harmony export */ dG: () => (/* binding */ commitRangeChange),
|
|
8023
|
+
/* harmony export */ uH: () => (/* binding */ durationMsFromSec),
|
|
8024
|
+
/* harmony export */ v2: () => (/* binding */ pointerTimeMs)
|
|
8025
|
+
/* harmony export */ });
|
|
8026
|
+
/* unused harmony export clampTimeMs */
|
|
8027
|
+
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4929);
|
|
8028
|
+
/* harmony import */ var _viewport__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(772);
|
|
8029
|
+
|
|
8030
|
+
|
|
8031
|
+
function clampToRange(value, min, max) {
|
|
8032
|
+
if (!Number.isFinite(value)) {
|
|
8033
|
+
return min;
|
|
8034
|
+
}
|
|
8035
|
+
return Math.min(max, Math.max(min, value));
|
|
8036
|
+
}
|
|
8037
|
+
|
|
8038
|
+
/** Integer ms in `[0, durationMs]`. */
|
|
8039
|
+
function clampTimeMs(timeMs, durationMs) {
|
|
8040
|
+
const duration = Math.max(0, durationMs);
|
|
8041
|
+
return Math.round(clampToRange(timeMs, 0, duration));
|
|
8042
|
+
}
|
|
8043
|
+
function durationMsFromSec(durationSec) {
|
|
8044
|
+
if (!Number.isFinite(durationSec) || durationSec <= 0) {
|
|
8045
|
+
return 0;
|
|
8046
|
+
}
|
|
8047
|
+
return Math.round(durationSec * 1000);
|
|
8048
|
+
}
|
|
8049
|
+
function isRangeCollapsed(range) {
|
|
8050
|
+
return !range || range.endMs == null || range.endMs <= range.startMs;
|
|
8051
|
+
}
|
|
8052
|
+
|
|
8053
|
+
/** Clamp both edges onto the file. Collapsed drafts stay a point. */
|
|
8054
|
+
function resolveRange(range, durationMs) {
|
|
8055
|
+
const startMs = clampTimeMs(range.startMs, durationMs);
|
|
8056
|
+
if (range.endMs == null) {
|
|
8057
|
+
return {
|
|
8058
|
+
endMs: startMs,
|
|
8059
|
+
startMs
|
|
8060
|
+
};
|
|
8061
|
+
}
|
|
8062
|
+
const endMs = clampTimeMs(range.endMs, durationMs);
|
|
8063
|
+
if (endMs <= startMs) {
|
|
8064
|
+
return {
|
|
8065
|
+
endMs: startMs,
|
|
8066
|
+
startMs
|
|
8067
|
+
};
|
|
8068
|
+
}
|
|
8069
|
+
return {
|
|
8070
|
+
endMs,
|
|
8071
|
+
startMs
|
|
8072
|
+
};
|
|
8073
|
+
}
|
|
8074
|
+
|
|
8075
|
+
/**
|
|
8076
|
+
* Which handle should receive this pointer. Overlapping hit areas (collapsed or
|
|
8077
|
+
* a span narrower than the 24px target) split at the midpoint so each edge stays reachable.
|
|
8078
|
+
*/
|
|
8079
|
+
function pickRangeHandle({
|
|
8080
|
+
endX,
|
|
8081
|
+
pointerX,
|
|
8082
|
+
startX
|
|
8083
|
+
}) {
|
|
8084
|
+
const mid = (startX + endX) / 2;
|
|
8085
|
+
if (!Number.isFinite(mid)) {
|
|
8086
|
+
return 'end';
|
|
8087
|
+
}
|
|
8088
|
+
return pointerX < mid ? 'start' : 'end';
|
|
8089
|
+
}
|
|
8090
|
+
|
|
8091
|
+
/** Screen x of a handle. Collapsed drafts sit 1px left/right of the playhead, not on it. */
|
|
8092
|
+
function visualRangeHandlePx({
|
|
8093
|
+
handle,
|
|
8094
|
+
range,
|
|
8095
|
+
viewport
|
|
8096
|
+
}) {
|
|
8097
|
+
const timeSec = (handle === 'start' ? range.startMs : range.endMs) / 1000;
|
|
8098
|
+
const x = (0,_viewport__WEBPACK_IMPORTED_MODULE_1__/* .positionPxFromTime */ .TO)(timeSec, viewport);
|
|
8099
|
+
if (range.startMs !== range.endMs) {
|
|
8100
|
+
return x;
|
|
8101
|
+
}
|
|
8102
|
+
return handle === 'start' ? x - _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */ .BG : x + _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */ .BG;
|
|
8103
|
+
}
|
|
8104
|
+
|
|
8105
|
+
/** True when the pointer is over the range rectangle or its handle hit targets. */
|
|
8106
|
+
function isPointerOverRange({
|
|
8107
|
+
pointerX,
|
|
8108
|
+
range,
|
|
8109
|
+
viewport
|
|
8110
|
+
}) {
|
|
8111
|
+
const resolved = resolveRange(range, durationMsFromSec(viewport.durationSec));
|
|
8112
|
+
const startX = visualRangeHandlePx({
|
|
8113
|
+
handle: 'start',
|
|
8114
|
+
range: resolved,
|
|
8115
|
+
viewport
|
|
8116
|
+
});
|
|
8117
|
+
const endX = visualRangeHandlePx({
|
|
8118
|
+
handle: 'end',
|
|
8119
|
+
range: resolved,
|
|
8120
|
+
viewport
|
|
8121
|
+
});
|
|
8122
|
+
const pad = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_HIT_AREA_PX */ .r0 / 2;
|
|
8123
|
+
return pointerX >= Math.min(startX, endX) - pad && pointerX <= Math.max(startX, endX) + pad;
|
|
8124
|
+
}
|
|
8125
|
+
|
|
8126
|
+
/** Snap to the playhead when the pointer is within `WAVEFORM_RANGE_SNAP_PX`. */
|
|
8127
|
+
function snapTimeMs({
|
|
8128
|
+
pixelsPerSecond,
|
|
8129
|
+
playheadMs,
|
|
8130
|
+
timeMs
|
|
8131
|
+
}) {
|
|
8132
|
+
if (!(pixelsPerSecond > 0) || !Number.isFinite(playheadMs)) {
|
|
8133
|
+
return timeMs;
|
|
8134
|
+
}
|
|
8135
|
+
const deltaPx = Math.abs(timeMs - playheadMs) / 1000 * pixelsPerSecond;
|
|
8136
|
+
if (deltaPx <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_SNAP_PX */ .IQ) {
|
|
8137
|
+
return Math.round(playheadMs);
|
|
8138
|
+
}
|
|
8139
|
+
return timeMs;
|
|
8140
|
+
}
|
|
8141
|
+
|
|
8142
|
+
/**
|
|
8143
|
+
* Move one edge. Crossing the other edge swaps roles so a collapsed pair can
|
|
8144
|
+
* expand in either direction. Enforces `[0, duration]` and the minimum span
|
|
8145
|
+
* once the drag has actually opened a range. An already-open range stays a
|
|
8146
|
+
* span — snapping one edge onto the other clamps to the minimum duration.
|
|
8147
|
+
*/
|
|
8148
|
+
function dragRangeHandle({
|
|
8149
|
+
durationMs,
|
|
8150
|
+
handle,
|
|
8151
|
+
pointerMs,
|
|
8152
|
+
range
|
|
8153
|
+
}) {
|
|
8154
|
+
const duration = Math.max(0, durationMs);
|
|
8155
|
+
const pointer = clampTimeMs(pointerMs, duration);
|
|
8156
|
+
let {
|
|
8157
|
+
startMs,
|
|
8158
|
+
endMs
|
|
8159
|
+
} = range;
|
|
8160
|
+
let nextHandle = handle;
|
|
8161
|
+
if (handle === 'start') {
|
|
8162
|
+
if (pointer > endMs) {
|
|
8163
|
+
startMs = endMs;
|
|
8164
|
+
endMs = pointer;
|
|
8165
|
+
nextHandle = 'end';
|
|
8166
|
+
} else {
|
|
8167
|
+
startMs = pointer;
|
|
8168
|
+
}
|
|
8169
|
+
} else if (pointer < startMs) {
|
|
8170
|
+
endMs = startMs;
|
|
8171
|
+
startMs = pointer;
|
|
8172
|
+
nextHandle = 'start';
|
|
8173
|
+
} else {
|
|
8174
|
+
endMs = pointer;
|
|
8175
|
+
}
|
|
8176
|
+
const wasOpen = range.startMs !== range.endMs;
|
|
8177
|
+
const opened = wasOpen || startMs !== endMs;
|
|
8178
|
+
if (opened && endMs - startMs < _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX) {
|
|
8179
|
+
if (nextHandle === 'end') {
|
|
8180
|
+
endMs = clampTimeMs(startMs + _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX, duration);
|
|
8181
|
+
if (endMs - startMs < _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX) {
|
|
8182
|
+
startMs = clampTimeMs(endMs - _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX, duration);
|
|
8183
|
+
}
|
|
8184
|
+
} else {
|
|
8185
|
+
startMs = clampTimeMs(endMs - _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX, duration);
|
|
8186
|
+
if (endMs - startMs < _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX) {
|
|
8187
|
+
endMs = clampTimeMs(startMs + _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_MIN_DURATION_MS */ .bX, duration);
|
|
8188
|
+
}
|
|
8189
|
+
}
|
|
8190
|
+
}
|
|
8191
|
+
return {
|
|
8192
|
+
handle: nextHandle,
|
|
8193
|
+
range: {
|
|
8194
|
+
endMs,
|
|
8195
|
+
startMs
|
|
8196
|
+
}
|
|
8197
|
+
};
|
|
8198
|
+
}
|
|
8199
|
+
function pointerTimeMs(pointerX, viewport) {
|
|
8200
|
+
return Math.round((0,_viewport__WEBPACK_IMPORTED_MODULE_1__/* .timeFromPositionPx */ .lZ)(pointerX, viewport) * 1000);
|
|
8201
|
+
}
|
|
8202
|
+
|
|
8203
|
+
/** Sidebar payload after mouseup. Null when the draft is still a single timestamp. */
|
|
8204
|
+
function commitRangeChange(range) {
|
|
8205
|
+
if (range.endMs <= range.startMs) {
|
|
8206
|
+
return null;
|
|
8207
|
+
}
|
|
8208
|
+
return {
|
|
8209
|
+
endMs: range.endMs,
|
|
8210
|
+
startMs: range.startMs
|
|
8211
|
+
};
|
|
8212
|
+
}
|
|
8213
|
+
function rangeProgress(range, durationMs) {
|
|
8214
|
+
if (!(durationMs > 0) || range.endMs <= range.startMs) {
|
|
8215
|
+
return null;
|
|
8216
|
+
}
|
|
8217
|
+
return {
|
|
8218
|
+
end: range.endMs / durationMs,
|
|
8219
|
+
start: range.startMs / durationMs
|
|
8220
|
+
};
|
|
8221
|
+
}
|
|
8222
|
+
|
|
8223
|
+
/***/ },
|
|
8224
|
+
|
|
7645
8225
|
/***/ 1053
|
|
7646
8226
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
7647
8227
|
|
|
@@ -7829,6 +8409,369 @@ function isRetryableWaveformError(code) {
|
|
|
7829
8409
|
|
|
7830
8410
|
/***/ },
|
|
7831
8411
|
|
|
8412
|
+
/***/ 772
|
|
8413
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
8414
|
+
|
|
8415
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8416
|
+
/* harmony export */ Iw: () => (/* binding */ sliderValueFromZoom),
|
|
8417
|
+
/* harmony export */ J$: () => (/* binding */ getZoomedPixelsPerSecond),
|
|
8418
|
+
/* harmony export */ KH: () => (/* binding */ viewportEquals),
|
|
8419
|
+
/* harmony export */ Mu: () => (/* binding */ timeLeftPercent),
|
|
8420
|
+
/* harmony export */ NI: () => (/* binding */ getViewportAtScroll),
|
|
8421
|
+
/* harmony export */ TO: () => (/* binding */ positionPxFromTime),
|
|
8422
|
+
/* harmony export */ aJ: () => (/* binding */ getPlayheadCameraAction),
|
|
8423
|
+
/* harmony export */ b6: () => (/* binding */ getCenteredScrollLeft),
|
|
8424
|
+
/* harmony export */ by: () => (/* binding */ getWaveformZoomMax),
|
|
8425
|
+
/* harmony export */ d0: () => (/* binding */ maxScrollLeft),
|
|
8426
|
+
/* harmony export */ eU: () => (/* binding */ zoomFromSliderValue),
|
|
8427
|
+
/* harmony export */ eq: () => (/* binding */ createWaveformViewport),
|
|
8428
|
+
/* harmony export */ gd: () => (/* binding */ getWaveformZoomMultiplier),
|
|
8429
|
+
/* harmony export */ gl: () => (/* binding */ getPinnedPlayheadLeft),
|
|
8430
|
+
/* harmony export */ iA: () => (/* binding */ getTapeGutterPx),
|
|
8431
|
+
/* harmony export */ ii: () => (/* binding */ clampWaveformZoom),
|
|
8432
|
+
/* harmony export */ lZ: () => (/* binding */ timeFromPositionPx),
|
|
8433
|
+
/* harmony export */ lz: () => (/* binding */ getTapeDefaultZoom),
|
|
8434
|
+
/* harmony export */ wA: () => (/* binding */ getSeekCameraAction),
|
|
8435
|
+
/* harmony export */ xV: () => (/* binding */ stepWaveformZoom),
|
|
8436
|
+
/* harmony export */ yW: () => (/* binding */ getTapePinnedPlayheadLeft)
|
|
8437
|
+
/* harmony export */ });
|
|
8438
|
+
/* unused harmony exports isTimeInView, getTapeCameraAction, getFollowInsetPx */
|
|
8439
|
+
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4929);
|
|
8440
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
8441
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
8442
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
8443
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
8444
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
8445
|
+
|
|
8446
|
+
/** Visible window: start/end times, pixels-per-second, and the current zoom. */
|
|
8447
|
+
function createWaveformViewport({
|
|
8448
|
+
durationSec,
|
|
8449
|
+
gutterPx = 0,
|
|
8450
|
+
heightPx,
|
|
8451
|
+
maxZoom,
|
|
8452
|
+
scrollLeftPx,
|
|
8453
|
+
widthPx,
|
|
8454
|
+
zoomLevel
|
|
8455
|
+
}) {
|
|
8456
|
+
const zoom = Number.isFinite(zoomLevel) && zoomLevel > 0 ? zoomLevel : _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW;
|
|
8457
|
+
const viewDurationSec = durationSec > 0 ? durationSec / zoom : 0; // seconds visible at this zoom
|
|
8458
|
+
const pixelsPerSecond = viewDurationSec > 0 && widthPx > 0 ? widthPx / viewDurationSec : 0;
|
|
8459
|
+
const leadingGutterPx = Number.isFinite(gutterPx) && gutterPx > 0 ? gutterPx : 0;
|
|
8460
|
+
const unclampedStartSec = pixelsPerSecond > 0 ? (scrollLeftPx - leadingGutterPx) / pixelsPerSecond : 0;
|
|
8461
|
+
const gutterDurationSec = pixelsPerSecond > 0 ? leadingGutterPx / pixelsPerSecond : 0;
|
|
8462
|
+
const latestWindowStartSec = leadingGutterPx > 0 ? durationSec + gutterDurationSec - viewDurationSec : Math.max(0, durationSec - viewDurationSec);
|
|
8463
|
+
const earliestWindowStartSec = leadingGutterPx > 0 ? -gutterDurationSec : 0;
|
|
8464
|
+
const startSec = pixelsPerSecond > 0 ? Math.min(latestWindowStartSec, Math.max(earliestWindowStartSec, unclampedStartSec)) : 0;
|
|
8465
|
+
return {
|
|
8466
|
+
durationSec,
|
|
8467
|
+
endSec: startSec + viewDurationSec,
|
|
8468
|
+
gutterPx: leadingGutterPx,
|
|
8469
|
+
heightPx,
|
|
8470
|
+
maxZoom,
|
|
8471
|
+
pixelsPerSecond,
|
|
8472
|
+
scrollLeftPx,
|
|
8473
|
+
startSec,
|
|
8474
|
+
widthPx,
|
|
8475
|
+
zoomLevel: zoom
|
|
8476
|
+
};
|
|
8477
|
+
}
|
|
8478
|
+
|
|
8479
|
+
/** Same viewport with a different scroll, so start/end times update. */
|
|
8480
|
+
function getViewportAtScroll(viewport, scrollLeftPx) {
|
|
8481
|
+
return createWaveformViewport(_objectSpread(_objectSpread({}, viewport), {}, {
|
|
8482
|
+
scrollLeftPx
|
|
8483
|
+
}));
|
|
8484
|
+
}
|
|
8485
|
+
|
|
8486
|
+
/** True when the visible window has not moved — skip a React state update. */
|
|
8487
|
+
function viewportEquals(prev, next) {
|
|
8488
|
+
return !!prev && prev.durationSec === next.durationSec && prev.endSec === next.endSec && prev.gutterPx === next.gutterPx && prev.maxZoom === next.maxZoom && prev.scrollLeftPx === next.scrollLeftPx && prev.startSec === next.startSec && prev.widthPx === next.widthPx && prev.zoomLevel === next.zoomLevel;
|
|
8489
|
+
}
|
|
8490
|
+
|
|
8491
|
+
/** How many CSS pixels from the left of the visible window this time sits. */
|
|
8492
|
+
function positionPxFromTime(timeSec, viewport) {
|
|
8493
|
+
return (timeSec - viewport.startSec) * viewport.pixelsPerSecond;
|
|
8494
|
+
}
|
|
8495
|
+
|
|
8496
|
+
/** Media time under a point this many CSS pixels from the left of the visible window. */
|
|
8497
|
+
function timeFromPositionPx(positionPx, viewport) {
|
|
8498
|
+
if (!(viewport.pixelsPerSecond > 0)) {
|
|
8499
|
+
return viewport.startSec;
|
|
8500
|
+
}
|
|
8501
|
+
return viewport.startSec + positionPx / viewport.pixelsPerSecond;
|
|
8502
|
+
}
|
|
8503
|
+
|
|
8504
|
+
/** True when this time sits inside the visible window. */
|
|
8505
|
+
function isTimeInView(timeSec, viewport) {
|
|
8506
|
+
return timeSec >= viewport.startSec && timeSec <= viewport.endSec;
|
|
8507
|
+
}
|
|
8508
|
+
|
|
8509
|
+
/** UI max zoom: 24×, ~1 peak per CSS pixel, and a minimum visible window. */
|
|
8510
|
+
function getWaveformZoomMax({
|
|
8511
|
+
durationSec,
|
|
8512
|
+
peakCount,
|
|
8513
|
+
viewWidthPx
|
|
8514
|
+
}) {
|
|
8515
|
+
if (!(peakCount > 0) || !(viewWidthPx > 0)) {
|
|
8516
|
+
return _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW;
|
|
8517
|
+
}
|
|
8518
|
+
const peakLimitedMax = Math.floor(peakCount / viewWidthPx);
|
|
8519
|
+
const durationLimitedMax = durationSec > 0 ? durationSec / _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_MIN_VIEW_WINDOW_SEC */ .Kl : _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW;
|
|
8520
|
+
return Math.max(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW, Math.min(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MAX */ .tK, peakLimitedMax, durationLimitedMax));
|
|
8521
|
+
}
|
|
8522
|
+
|
|
8523
|
+
/** Keep zoom between 1× and this file's max. */
|
|
8524
|
+
function clampWaveformZoom(zoomLevel, maxZoom = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8525
|
+
const max = Math.max(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW, maxZoom);
|
|
8526
|
+
if (!Number.isFinite(zoomLevel)) {
|
|
8527
|
+
return _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW;
|
|
8528
|
+
}
|
|
8529
|
+
return Math.min(max, Math.max(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW, zoomLevel));
|
|
8530
|
+
}
|
|
8531
|
+
|
|
8532
|
+
/** Zoom badge: 1.1×–1.9× below 2×, then whole numbers. Omit at 1×. */
|
|
8533
|
+
function getWaveformZoomMultiplier(zoomLevel) {
|
|
8534
|
+
if (!Number.isFinite(zoomLevel) || zoomLevel <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8535
|
+
return null;
|
|
8536
|
+
}
|
|
8537
|
+
if (zoomLevel < 2) {
|
|
8538
|
+
const tenths = Math.round(zoomLevel * 10) / 10;
|
|
8539
|
+
if (tenths <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8540
|
+
return null;
|
|
8541
|
+
}
|
|
8542
|
+
if (tenths >= 2) {
|
|
8543
|
+
return '2x';
|
|
8544
|
+
}
|
|
8545
|
+
return `${tenths.toFixed(1)}x`;
|
|
8546
|
+
}
|
|
8547
|
+
return `${Math.floor(zoomLevel)}x`;
|
|
8548
|
+
}
|
|
8549
|
+
|
|
8550
|
+
/** WaveSurfer zoom density. 0 = fit the whole file in the view. */
|
|
8551
|
+
function getZoomedPixelsPerSecond({
|
|
8552
|
+
durationSec,
|
|
8553
|
+
isTape = false,
|
|
8554
|
+
maxZoom = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW,
|
|
8555
|
+
viewWidthPx,
|
|
8556
|
+
zoomLevel
|
|
8557
|
+
}) {
|
|
8558
|
+
const zoom = clampWaveformZoom(zoomLevel, maxZoom);
|
|
8559
|
+
if (!(durationSec > 0) || !(viewWidthPx > 0)) {
|
|
8560
|
+
return 0;
|
|
8561
|
+
}
|
|
8562
|
+
if (!isTape && zoom <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8563
|
+
return 0;
|
|
8564
|
+
}
|
|
8565
|
+
return viewWidthPx / durationSec * zoom;
|
|
8566
|
+
}
|
|
8567
|
+
|
|
8568
|
+
/** Half-view empty space so t=0 and duration can sit under the center pin. */
|
|
8569
|
+
function getTapeGutterPx(widthPx) {
|
|
8570
|
+
return widthPx > 0 ? widthPx / 2 : 0;
|
|
8571
|
+
}
|
|
8572
|
+
|
|
8573
|
+
/** Tape first paint: 10s on screen, or 1× when the file is shorter than that. */
|
|
8574
|
+
function getTapeDefaultZoom(durationSec, maxZoom = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8575
|
+
if (!(durationSec > 0)) {
|
|
8576
|
+
return _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW;
|
|
8577
|
+
}
|
|
8578
|
+
return clampWaveformZoom(durationSec / _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_TAPE_DEFAULT_WINDOW_SEC */ .Av, maxZoom);
|
|
8579
|
+
}
|
|
8580
|
+
|
|
8581
|
+
/** Map zoom (1…max) onto the 0–100 slider. */
|
|
8582
|
+
function sliderValueFromZoom(zoomLevel, maxZoom = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8583
|
+
const max = Math.max(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW, maxZoom);
|
|
8584
|
+
const zoom = clampWaveformZoom(zoomLevel, max);
|
|
8585
|
+
if (max <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8586
|
+
return 0;
|
|
8587
|
+
}
|
|
8588
|
+
return (zoom - _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) / (max - _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) * _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_SLIDER_MAX */ .nh;
|
|
8589
|
+
}
|
|
8590
|
+
|
|
8591
|
+
/** Inverse of sliderValueFromZoom. */
|
|
8592
|
+
function zoomFromSliderValue(value, maxZoom = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8593
|
+
const max = Math.max(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW, maxZoom);
|
|
8594
|
+
if (max <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8595
|
+
return _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW;
|
|
8596
|
+
}
|
|
8597
|
+
const t = Math.min(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_SLIDER_MAX */ .nh, Math.max(0, value)) / _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_SLIDER_MAX */ .nh;
|
|
8598
|
+
return clampWaveformZoom(_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW + t * (max - _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW), max);
|
|
8599
|
+
}
|
|
8600
|
+
|
|
8601
|
+
/** One zoom-in/out button step on the 0–100 slider, mapped back to zoom. */
|
|
8602
|
+
function stepWaveformZoom(zoomLevel, maxZoom, sliderDelta) {
|
|
8603
|
+
return zoomFromSliderValue(Math.round(sliderValueFromZoom(zoomLevel, maxZoom)) + sliderDelta, maxZoom);
|
|
8604
|
+
}
|
|
8605
|
+
|
|
8606
|
+
/** Max scroll that still shows a full window (no overscroll). Gutters add empty lead/trail. */
|
|
8607
|
+
function maxScrollLeft(viewport) {
|
|
8608
|
+
const gutterPx = viewport.gutterPx || 0;
|
|
8609
|
+
return Math.max(0, viewport.durationSec * viewport.pixelsPerSecond + 2 * gutterPx - viewport.widthPx);
|
|
8610
|
+
}
|
|
8611
|
+
|
|
8612
|
+
/** Scroll offset that still shows a full window (no overscroll). */
|
|
8613
|
+
function clampScrollLeft(scrollLeftPx, viewport) {
|
|
8614
|
+
if (!Number.isFinite(scrollLeftPx)) {
|
|
8615
|
+
return 0;
|
|
8616
|
+
}
|
|
8617
|
+
return Math.min(maxScrollLeft(viewport), Math.max(0, scrollLeftPx));
|
|
8618
|
+
}
|
|
8619
|
+
|
|
8620
|
+
/** Center this time in the view, clamped so the window still fills the canvas. */
|
|
8621
|
+
function getCenteredScrollLeft(timeSec, viewport) {
|
|
8622
|
+
return clampScrollLeft(timeSec * viewport.pixelsPerSecond + (viewport.gutterPx || 0) - viewport.widthPx / 2, viewport);
|
|
8623
|
+
}
|
|
8624
|
+
|
|
8625
|
+
/**
|
|
8626
|
+
* Host/media seek while zoomed: jump so the time (and its comment avatar) is on screen.
|
|
8627
|
+
* No-op at fit-to-width or when that time is already visible.
|
|
8628
|
+
*/
|
|
8629
|
+
function getSeekCameraAction({
|
|
8630
|
+
cameraMode = 'desktop',
|
|
8631
|
+
timeSec,
|
|
8632
|
+
viewport
|
|
8633
|
+
}) {
|
|
8634
|
+
if (!(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
8635
|
+
return {
|
|
8636
|
+
type: 'none'
|
|
8637
|
+
};
|
|
8638
|
+
}
|
|
8639
|
+
if (cameraMode === 'tape') {
|
|
8640
|
+
const scrollLeftPx = getCenteredScrollLeft(timeSec, viewport);
|
|
8641
|
+
if (Math.abs(scrollLeftPx - viewport.scrollLeftPx) < 1) {
|
|
8642
|
+
return {
|
|
8643
|
+
type: 'none'
|
|
8644
|
+
};
|
|
8645
|
+
}
|
|
8646
|
+
return {
|
|
8647
|
+
type: 'jump',
|
|
8648
|
+
scrollLeftPx
|
|
8649
|
+
};
|
|
8650
|
+
}
|
|
8651
|
+
if (viewport.zoomLevel <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW) {
|
|
8652
|
+
return {
|
|
8653
|
+
type: 'none'
|
|
8654
|
+
};
|
|
8655
|
+
}
|
|
8656
|
+
if (isTimeInView(timeSec, viewport)) {
|
|
8657
|
+
return {
|
|
8658
|
+
type: 'none'
|
|
8659
|
+
};
|
|
8660
|
+
}
|
|
8661
|
+
return {
|
|
8662
|
+
type: 'jump',
|
|
8663
|
+
scrollLeftPx: getCenteredScrollLeft(timeSec, viewport)
|
|
8664
|
+
};
|
|
8665
|
+
}
|
|
8666
|
+
|
|
8667
|
+
/** Always keep this time under the center pin. Reuses followRight so the camera hook can pin. */
|
|
8668
|
+
function getTapeCameraAction({
|
|
8669
|
+
timeSec,
|
|
8670
|
+
viewport
|
|
8671
|
+
}) {
|
|
8672
|
+
if (!(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
8673
|
+
return {
|
|
8674
|
+
type: 'none'
|
|
8675
|
+
};
|
|
8676
|
+
}
|
|
8677
|
+
return {
|
|
8678
|
+
isPlayheadPinned: true,
|
|
8679
|
+
scrollLeftPx: getCenteredScrollLeft(timeSec, viewport),
|
|
8680
|
+
type: 'followRight'
|
|
8681
|
+
};
|
|
8682
|
+
}
|
|
8683
|
+
|
|
8684
|
+
/** Follow inset in CSS px, capped at one third of the view so a narrow player still has room. */
|
|
8685
|
+
function getFollowInsetPx(widthPx, insetPx = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_FOLLOW_INSET_PX */ .NM) {
|
|
8686
|
+
if (!(widthPx > 0)) {
|
|
8687
|
+
return 0;
|
|
8688
|
+
}
|
|
8689
|
+
return Math.min(Math.max(0, insetPx), widthPx / 3);
|
|
8690
|
+
}
|
|
8691
|
+
|
|
8692
|
+
/** CSS left for a playhead pinned to the follow inset. */
|
|
8693
|
+
function getPinnedPlayheadLeft(widthPx, insetPx = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_FOLLOW_INSET_PX */ .NM) {
|
|
8694
|
+
const inset = getFollowInsetPx(widthPx, insetPx);
|
|
8695
|
+
if (!(widthPx > 0)) {
|
|
8696
|
+
return '0%';
|
|
8697
|
+
}
|
|
8698
|
+
return `${(widthPx - inset) / widthPx * 100}%`;
|
|
8699
|
+
}
|
|
8700
|
+
|
|
8701
|
+
/** CSS left for a playhead locked to the center of the view. */
|
|
8702
|
+
function getTapePinnedPlayheadLeft() {
|
|
8703
|
+
return '50%';
|
|
8704
|
+
}
|
|
8705
|
+
|
|
8706
|
+
/** CSS left % of the playhead from the left of the visible window. */
|
|
8707
|
+
function timeLeftPercent(timeSec, durationSec, viewport) {
|
|
8708
|
+
if (viewport.widthPx > 0 && viewport.pixelsPerSecond > 0) {
|
|
8709
|
+
return `${positionPxFromTime(timeSec, viewport) / viewport.widthPx * 100}%`;
|
|
8710
|
+
}
|
|
8711
|
+
const progress = durationSec > 0 ? Math.min(1, Math.max(0, timeSec / durationSec)) : 0;
|
|
8712
|
+
return `${progress * 100}%`;
|
|
8713
|
+
}
|
|
8714
|
+
|
|
8715
|
+
/**
|
|
8716
|
+
* Walk across the view until the playhead nears the right edge, then follow.
|
|
8717
|
+
* Off-screen at play start jumps in; off-screen right while playing keeps following.
|
|
8718
|
+
*/
|
|
8719
|
+
function getPlayheadCameraAction({
|
|
8720
|
+
cameraMode = 'desktop',
|
|
8721
|
+
insetPx = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_FOLLOW_INSET_PX */ .NM,
|
|
8722
|
+
isPlaying,
|
|
8723
|
+
playJustStarted,
|
|
8724
|
+
timeSec,
|
|
8725
|
+
viewport
|
|
8726
|
+
}) {
|
|
8727
|
+
if (cameraMode === 'tape') {
|
|
8728
|
+
return getTapeCameraAction({
|
|
8729
|
+
timeSec,
|
|
8730
|
+
viewport
|
|
8731
|
+
});
|
|
8732
|
+
}
|
|
8733
|
+
if (!isPlaying || viewport.zoomLevel <= _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_ZOOM_MIN */ .LW || !(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
8734
|
+
return {
|
|
8735
|
+
type: 'none'
|
|
8736
|
+
};
|
|
8737
|
+
}
|
|
8738
|
+
const inset = getFollowInsetPx(viewport.widthPx, insetPx);
|
|
8739
|
+
const viewX = positionPxFromTime(timeSec, viewport);
|
|
8740
|
+
const playheadCanvasX = timeSec * viewport.pixelsPerSecond;
|
|
8741
|
+
const followX = viewport.widthPx - inset;
|
|
8742
|
+
if (viewX < 0) {
|
|
8743
|
+
if (!playJustStarted) {
|
|
8744
|
+
return {
|
|
8745
|
+
type: 'none'
|
|
8746
|
+
};
|
|
8747
|
+
}
|
|
8748
|
+
return {
|
|
8749
|
+
type: 'jump',
|
|
8750
|
+
scrollLeftPx: clampScrollLeft(playheadCanvasX - inset, viewport)
|
|
8751
|
+
};
|
|
8752
|
+
}
|
|
8753
|
+
if (viewX >= followX) {
|
|
8754
|
+
const unclampedScroll = playheadCanvasX - followX;
|
|
8755
|
+
const scrollLeftPx = clampScrollLeft(unclampedScroll, viewport);
|
|
8756
|
+
if (playJustStarted && viewX > viewport.widthPx) {
|
|
8757
|
+
return {
|
|
8758
|
+
type: 'jump',
|
|
8759
|
+
scrollLeftPx
|
|
8760
|
+
};
|
|
8761
|
+
}
|
|
8762
|
+
return {
|
|
8763
|
+
type: 'followRight',
|
|
8764
|
+
isPlayheadPinned: unclampedScroll <= maxScrollLeft(viewport),
|
|
8765
|
+
scrollLeftPx
|
|
8766
|
+
};
|
|
8767
|
+
}
|
|
8768
|
+
return {
|
|
8769
|
+
type: 'none'
|
|
8770
|
+
};
|
|
8771
|
+
}
|
|
8772
|
+
|
|
8773
|
+
/***/ },
|
|
8774
|
+
|
|
7832
8775
|
/***/ 2485
|
|
7833
8776
|
(module, exports) {
|
|
7834
8777
|
|
|
@@ -14598,7 +15541,7 @@ var x = (y) => {
|
|
|
14598
15541
|
var x = {}; __webpack_require__.d(x, y); return x
|
|
14599
15542
|
}
|
|
14600
15543
|
var y = (x) => (() => (x))
|
|
14601
|
-
module.exports = x({ ["createElement"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.createElement), ["default"]: () => (__WEBPACK_EXTERNAL_MODULE_react__["default"]), ["useCallback"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useCallback), ["useEffect"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useEffect), ["useId"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useId), ["useLayoutEffect"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useLayoutEffect), ["useMemo"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useMemo), ["useRef"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useRef), ["useState"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useState) });
|
|
15544
|
+
module.exports = x({ ["createElement"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.createElement), ["default"]: () => (__WEBPACK_EXTERNAL_MODULE_react__["default"]), ["forwardRef"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.forwardRef), ["useCallback"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useCallback), ["useEffect"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useEffect), ["useId"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useId), ["useImperativeHandle"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useImperativeHandle), ["useLayoutEffect"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useLayoutEffect), ["useMemo"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useMemo), ["useRef"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useRef), ["useState"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useState) });
|
|
14602
15545
|
|
|
14603
15546
|
/***/ },
|
|
14604
15547
|
|
|
@@ -23492,7 +24435,7 @@ class Browser {
|
|
|
23492
24435
|
;// ./src/lib/Logger.js
|
|
23493
24436
|
/* eslint-disable no-undef */
|
|
23494
24437
|
const CLIENT_NAME = "box-content-preview";
|
|
23495
|
-
const CLIENT_VERSION = "3.
|
|
24438
|
+
const CLIENT_VERSION = "3.93.0";
|
|
23496
24439
|
/* eslint-enable no-undef */
|
|
23497
24440
|
|
|
23498
24441
|
class Logger {
|
|
@@ -32718,6 +33661,44 @@ class TextLoader extends viewers_AssetLoader {
|
|
|
32718
33661
|
}
|
|
32719
33662
|
}
|
|
32720
33663
|
/* harmony default export */ const text_TextLoader = (new TextLoader());
|
|
33664
|
+
;// ./src/lib/viewers/controls/media/types.ts
|
|
33665
|
+
/**
|
|
33666
|
+
* Draft range the activity sidebar is holding. Preview draws start/end handles
|
|
33667
|
+
* on the waveform until the sidebar sends `comment_range_draft_clear`.
|
|
33668
|
+
* The viewer emits `comment_range_draft_change` on pointer-up so the host
|
|
33669
|
+
* can persist the new timestamps, and `comment_range_draft_dismiss` when
|
|
33670
|
+
* the user clicks the waveform outside an open range. See media/README.md.
|
|
33671
|
+
* `endMs: null` means a single timestamp — both handles sit on `startMs`.
|
|
33672
|
+
*/
|
|
33673
|
+
|
|
33674
|
+
/** Committed range after a handle drag. Always a real span (`endMs > startMs`). */
|
|
33675
|
+
|
|
33676
|
+
/** Sidebar → viewer: show or update the draft handles. */
|
|
33677
|
+
const EVENT_COMMENT_RANGE_DRAFT = 'comment_range_draft';
|
|
33678
|
+
|
|
33679
|
+
/** Sidebar → viewer: hide the handles (toggle-off, post, version switch, unmount). */
|
|
33680
|
+
const EVENT_COMMENT_RANGE_DRAFT_CLEAR = 'comment_range_draft_clear';
|
|
33681
|
+
|
|
33682
|
+
/** Viewer → sidebar: the user clicked the waveform outside an open draft range. */
|
|
33683
|
+
const EVENT_COMMENT_RANGE_DRAFT_DISMISS = 'comment_range_draft_dismiss';
|
|
33684
|
+
|
|
33685
|
+
/** Viewer → sidebar: a handle drag finished. Emitted on pointer-up only. */
|
|
33686
|
+
const EVENT_COMMENT_RANGE_DRAFT_CHANGE = 'comment_range_draft_change';
|
|
33687
|
+
|
|
33688
|
+
/** True when a host draft can be shown. Collapsed drafts use `endMs: null`. */
|
|
33689
|
+
function isValidCommentRangeDraft(value) {
|
|
33690
|
+
if (!value || typeof value !== 'object') {
|
|
33691
|
+
return false;
|
|
33692
|
+
}
|
|
33693
|
+
const draft = value;
|
|
33694
|
+
if (!Number.isFinite(draft.startMs)) {
|
|
33695
|
+
return false;
|
|
33696
|
+
}
|
|
33697
|
+
if (draft.endMs != null && (!Number.isFinite(draft.endMs) || Number(draft.endMs) <= Number(draft.startMs))) {
|
|
33698
|
+
return false;
|
|
33699
|
+
}
|
|
33700
|
+
return true;
|
|
33701
|
+
}
|
|
32721
33702
|
// EXTERNAL MODULE: ./node_modules/lodash/isEmpty.js
|
|
32722
33703
|
var isEmpty = __webpack_require__(2193);
|
|
32723
33704
|
var isEmpty_default = /*#__PURE__*/__webpack_require__.n(isEmpty);
|
|
@@ -34687,6 +35668,7 @@ const CSS_CLASS_MEDIA_CONTAINER = 'bp-media-container';
|
|
|
34687
35668
|
const DEFAULT_VOLUME = 1;
|
|
34688
35669
|
const MEDIA_VOLUME_CACHE_KEY = 'media-volume';
|
|
34689
35670
|
const MEDIA_AUTOPLAY_CACHE_KEY = 'media-autoplay';
|
|
35671
|
+
const MEDIA_PLAY_NEXT_CACHE_KEY = 'media-play-next';
|
|
34690
35672
|
const MEDIA_SPEED_CACHE_KEY = 'media-speed';
|
|
34691
35673
|
const MEDIA_VOLUME_INCREMENT = 0.05;
|
|
34692
35674
|
const EMIT_WAIT_TIME_IN_MILLIS = 100;
|
|
@@ -34737,6 +35719,7 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
34737
35719
|
this.containerClickHandler = this.containerClickHandler.bind(this);
|
|
34738
35720
|
this.errorHandler = this.errorHandler.bind(this);
|
|
34739
35721
|
this.handleAutoplay = this.handleAutoplay.bind(this);
|
|
35722
|
+
this.handlePlayNext = this.handlePlayNext.bind(this);
|
|
34740
35723
|
this.handleRate = this.handleRate.bind(this);
|
|
34741
35724
|
this.handleTimeupdateFromMediaControls = this.handleTimeupdateFromMediaControls.bind(this);
|
|
34742
35725
|
this.loadeddataHandler = this.loadeddataHandler.bind(this);
|
|
@@ -34749,6 +35732,7 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
34749
35732
|
this.resetPlayIcon = this.resetPlayIcon.bind(this);
|
|
34750
35733
|
this.seekHandler = this.seekHandler.bind(this);
|
|
34751
35734
|
this.setAutoplay = this.setAutoplay.bind(this);
|
|
35735
|
+
this.setPlayNext = this.setPlayNext.bind(this);
|
|
34752
35736
|
this.setRate = this.setRate.bind(this);
|
|
34753
35737
|
this.setTimeCode = this.setTimeCode.bind(this);
|
|
34754
35738
|
this.setVolume = this.setVolume.bind(this);
|
|
@@ -35058,7 +36042,9 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35058
36042
|
* @return {void}
|
|
35059
36043
|
*/
|
|
35060
36044
|
handleRate() {
|
|
35061
|
-
const
|
|
36045
|
+
const cachedSpeed = this.cache.get(MEDIA_SPEED_CACHE_KEY) - 0;
|
|
36046
|
+
// Default to 1x when cache is empty (v2 overlay play can run before loadUIReact).
|
|
36047
|
+
const speed = Number.isFinite(cachedSpeed) ? cachedSpeed : 1;
|
|
35062
36048
|
if (speed && this.mediaEl.playbackRate !== speed && this.mediaEl.playbackRate > 0) {
|
|
35063
36049
|
this.emit('ratechange', speed);
|
|
35064
36050
|
}
|
|
@@ -35106,6 +36092,20 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35106
36092
|
this.renderUI();
|
|
35107
36093
|
}
|
|
35108
36094
|
}
|
|
36095
|
+
|
|
36096
|
+
/**
|
|
36097
|
+
* Handler for play next
|
|
36098
|
+
*
|
|
36099
|
+
* @private
|
|
36100
|
+
* @emits playnext
|
|
36101
|
+
* @return {void}
|
|
36102
|
+
*/
|
|
36103
|
+
handlePlayNext() {
|
|
36104
|
+
this.emit('playnext', this.isPlayNextEnabled());
|
|
36105
|
+
if (this.controls) {
|
|
36106
|
+
this.renderUI();
|
|
36107
|
+
}
|
|
36108
|
+
}
|
|
35109
36109
|
/**
|
|
35110
36110
|
* Autoplay the media
|
|
35111
36111
|
*
|
|
@@ -35132,6 +36132,16 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35132
36132
|
isAutoplayEnabled() {
|
|
35133
36133
|
return this.cache.get(MEDIA_AUTOPLAY_CACHE_KEY) === 'Enabled';
|
|
35134
36134
|
}
|
|
36135
|
+
|
|
36136
|
+
/**
|
|
36137
|
+
* Determines if play next is enabled
|
|
36138
|
+
*
|
|
36139
|
+
* @protected
|
|
36140
|
+
* @return {boolean} Indicates if play next is enabled
|
|
36141
|
+
*/
|
|
36142
|
+
isPlayNextEnabled() {
|
|
36143
|
+
return this.cache.get(MEDIA_PLAY_NEXT_CACHE_KEY) === 'Enabled';
|
|
36144
|
+
}
|
|
35135
36145
|
/**
|
|
35136
36146
|
* Loads the controls
|
|
35137
36147
|
*
|
|
@@ -35154,6 +36164,9 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35154
36164
|
if (!this.cache.has(MEDIA_AUTOPLAY_CACHE_KEY)) {
|
|
35155
36165
|
this.cache.set(MEDIA_AUTOPLAY_CACHE_KEY, 'Disabled');
|
|
35156
36166
|
}
|
|
36167
|
+
if (!this.cache.has(MEDIA_PLAY_NEXT_CACHE_KEY)) {
|
|
36168
|
+
this.cache.set(MEDIA_PLAY_NEXT_CACHE_KEY, 'Disabled');
|
|
36169
|
+
}
|
|
35157
36170
|
if (!this.cache.has(MEDIA_SPEED_CACHE_KEY)) {
|
|
35158
36171
|
this.cache.set(MEDIA_SPEED_CACHE_KEY, '1.0');
|
|
35159
36172
|
}
|
|
@@ -35248,6 +36261,18 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35248
36261
|
this.handleAutoplay();
|
|
35249
36262
|
}
|
|
35250
36263
|
|
|
36264
|
+
/**
|
|
36265
|
+
* Updates play next
|
|
36266
|
+
*
|
|
36267
|
+
* @protected
|
|
36268
|
+
* @param {boolean} playNext - True if enabled
|
|
36269
|
+
* @return {void}
|
|
36270
|
+
*/
|
|
36271
|
+
setPlayNext(playNext) {
|
|
36272
|
+
this.cache.set(MEDIA_PLAY_NEXT_CACHE_KEY, playNext ? 'Enabled' : 'Disabled', true);
|
|
36273
|
+
this.handlePlayNext();
|
|
36274
|
+
}
|
|
36275
|
+
|
|
35251
36276
|
/**
|
|
35252
36277
|
* Updates play rate
|
|
35253
36278
|
*
|
|
@@ -35349,17 +36374,17 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35349
36374
|
}
|
|
35350
36375
|
|
|
35351
36376
|
/**
|
|
35352
|
-
* Emits
|
|
36377
|
+
* Emits mediaEndPlayNext when play next is enabled.
|
|
35353
36378
|
*
|
|
35354
36379
|
* @private
|
|
35355
|
-
* @emits
|
|
36380
|
+
* @emits mediaEndPlayNext
|
|
35356
36381
|
* @return {void}
|
|
35357
36382
|
*/
|
|
35358
36383
|
mediaendHandler() {
|
|
35359
36384
|
this.resetPlayIcon();
|
|
35360
36385
|
this.processMetrics();
|
|
35361
|
-
if (this.
|
|
35362
|
-
this.emit(lib_events/* VIEWER_EVENT */.Oi.
|
|
36386
|
+
if (this.isPlayNextEnabled()) {
|
|
36387
|
+
this.emit(lib_events/* VIEWER_EVENT */.Oi.mediaEndPlayNext);
|
|
35363
36388
|
}
|
|
35364
36389
|
}
|
|
35365
36390
|
|
|
@@ -35935,8 +36960,8 @@ class MediaBaseViewer extends viewers_BaseViewer {
|
|
|
35935
36960
|
}
|
|
35936
36961
|
}
|
|
35937
36962
|
/* harmony default export */ const media_MediaBaseViewer = (MediaBaseViewer);
|
|
35938
|
-
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MediaSettings.tsx +
|
|
35939
|
-
var MediaSettings = __webpack_require__(
|
|
36963
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MediaSettings.tsx + 6 modules
|
|
36964
|
+
var MediaSettings = __webpack_require__(9229);
|
|
35940
36965
|
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/PlayPauseToggle.tsx + 1 modules
|
|
35941
36966
|
var PlayPauseToggle = __webpack_require__(6321);
|
|
35942
36967
|
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/DurationLabels.tsx + 1 modules
|
|
@@ -36129,7 +37154,7 @@ function MP3Controls({
|
|
|
36129
37154
|
isPlaying: isPlaying,
|
|
36130
37155
|
movePlayback: movePlayback,
|
|
36131
37156
|
onPlayPause: onPlayPause
|
|
36132
|
-
}), /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
37157
|
+
}), /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
36133
37158
|
onMuteChange: onMuteChange,
|
|
36134
37159
|
onVolumeChange: onVolumeChange,
|
|
36135
37160
|
volume: volume
|
|
@@ -36180,6 +37205,8 @@ class MP3ControlsRoot {
|
|
|
36180
37205
|
var waveform_constants = __webpack_require__(4929);
|
|
36181
37206
|
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/createWaveformLoader.ts + 1 modules
|
|
36182
37207
|
var createWaveformLoader = __webpack_require__(4971);
|
|
37208
|
+
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/range.ts
|
|
37209
|
+
var range = __webpack_require__(4253);
|
|
36183
37210
|
// EXTERNAL MODULE: ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
|
|
36184
37211
|
var validateWaveformPayload = __webpack_require__(1053);
|
|
36185
37212
|
;// ./src/lib/viewers/media/MP3.scss
|
|
@@ -36201,7 +37228,60 @@ function MP3Viewer_toPrimitive(t, r) { if ("object" != typeof t || !t) return t;
|
|
|
36201
37228
|
|
|
36202
37229
|
|
|
36203
37230
|
|
|
37231
|
+
|
|
37232
|
+
|
|
36204
37233
|
const CSS_CLASS_MP3 = 'bp-media-mp3';
|
|
37234
|
+
const AUDIO_V2_SHUTTLE_RATES = [2, 4, 8, 16];
|
|
37235
|
+
const AUDIO_V2_SHUTTLE_TICK_MS = 50;
|
|
37236
|
+
const AUDIO_V2_SKIP_SEC = 1;
|
|
37237
|
+
const AUDIO_V2_SHIFT_SKIP_SEC = 5;
|
|
37238
|
+
|
|
37239
|
+
/**
|
|
37240
|
+
* Next J/L shuttle rate. Opposite direction starts at 2×.
|
|
37241
|
+
*
|
|
37242
|
+
* @param {number} currentRate
|
|
37243
|
+
* @param {boolean} sameDirection
|
|
37244
|
+
* @return {number} 2, 4, 8, or 16
|
|
37245
|
+
*/
|
|
37246
|
+
function nextShuttleRate(currentRate, sameDirection) {
|
|
37247
|
+
if (!sameDirection) {
|
|
37248
|
+
return AUDIO_V2_SHUTTLE_RATES[0];
|
|
37249
|
+
}
|
|
37250
|
+
const index = AUDIO_V2_SHUTTLE_RATES.indexOf(currentRate);
|
|
37251
|
+
if (index < 0) {
|
|
37252
|
+
return AUDIO_V2_SHUTTLE_RATES[0];
|
|
37253
|
+
}
|
|
37254
|
+
return AUDIO_V2_SHUTTLE_RATES[Math.min(index + 1, AUDIO_V2_SHUTTLE_RATES.length - 1)];
|
|
37255
|
+
}
|
|
37256
|
+
|
|
37257
|
+
/**
|
|
37258
|
+
* Next/previous comment marker for ↑/↓. Walks by id so same-time stacks each get a stop.
|
|
37259
|
+
*
|
|
37260
|
+
* @param {Array<Object>} markers
|
|
37261
|
+
* @param {Object} options
|
|
37262
|
+
* @param {number} options.direction -1 previous, 1 next
|
|
37263
|
+
* @param {string|null} options.selectedId
|
|
37264
|
+
* @param {number} options.time current playhead
|
|
37265
|
+
* @return {Object|null} marker to select
|
|
37266
|
+
*/
|
|
37267
|
+
function nextCommentMarker(markers, {
|
|
37268
|
+
direction,
|
|
37269
|
+
selectedId,
|
|
37270
|
+
time
|
|
37271
|
+
}) {
|
|
37272
|
+
const sorted = (markers || []).filter(marker => Number.isFinite(marker.time)).sort((left, right) => left.time - right.time || String(left.id).localeCompare(String(right.id)));
|
|
37273
|
+
if (!sorted.length) {
|
|
37274
|
+
return null;
|
|
37275
|
+
}
|
|
37276
|
+
const selectedIndex = sorted.findIndex(marker => marker.id === selectedId);
|
|
37277
|
+
if (selectedIndex >= 0) {
|
|
37278
|
+
return sorted[Math.max(0, Math.min(sorted.length - 1, selectedIndex + direction))];
|
|
37279
|
+
}
|
|
37280
|
+
if (direction > 0) {
|
|
37281
|
+
return sorted.find(marker => marker.time >= time) || sorted[sorted.length - 1];
|
|
37282
|
+
}
|
|
37283
|
+
return [...sorted].reverse().find(marker => marker.time <= time) || sorted[0];
|
|
37284
|
+
}
|
|
36205
37285
|
function createLoadFailedError(message) {
|
|
36206
37286
|
const error = new Error(message);
|
|
36207
37287
|
error.name = 'LOAD_FAILED';
|
|
@@ -36214,6 +37294,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36214
37294
|
* @inheritdoc
|
|
36215
37295
|
*/
|
|
36216
37296
|
MP3Viewer_defineProperty(this, "handlePlayRequest", () => {
|
|
37297
|
+
this.exitShuttle();
|
|
36217
37298
|
this.userRequestedPlay = true;
|
|
36218
37299
|
this.togglePlay();
|
|
36219
37300
|
if (this.shouldRaceClientWaveformDecode() && this.isWaveformDecodeRetryPending && !this.hasUsedWaveformDecodePlayRetry) {
|
|
@@ -36230,6 +37311,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36230
37311
|
* @return {void}
|
|
36231
37312
|
*/
|
|
36232
37313
|
MP3Viewer_defineProperty(this, "handlePlayPause", shouldPlay => {
|
|
37314
|
+
this.exitShuttle();
|
|
36233
37315
|
if (shouldPlay) {
|
|
36234
37316
|
this.handlePlayRequest();
|
|
36235
37317
|
return;
|
|
@@ -36239,19 +37321,69 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36239
37321
|
MP3Viewer_defineProperty(this, "handleCommentMarkersUpdated", (markers = []) => {
|
|
36240
37322
|
this.commentMarkers = markers;
|
|
36241
37323
|
const selected = markers.find(marker => marker.isSelected);
|
|
36242
|
-
|
|
36243
|
-
|
|
36244
|
-
|
|
36245
|
-
|
|
36246
|
-
|
|
36247
|
-
this.
|
|
36248
|
-
|
|
36249
|
-
|
|
37324
|
+
|
|
37325
|
+
// Host echoes often omit isSelected. Keep hostSelectedMarkerId so ↑/↓ can
|
|
37326
|
+
// still walk other comments at the same time. Clear only when that id is gone.
|
|
37327
|
+
if (selected) {
|
|
37328
|
+
if (selected.id !== this.hostSelectedMarkerId) {
|
|
37329
|
+
this.hostSelectedMarkerId = selected.id;
|
|
37330
|
+
if (Number.isFinite(selected.time)) {
|
|
37331
|
+
this.pendingHostSelectedSeek = selected;
|
|
37332
|
+
this.applyPendingHostSelectedSeek();
|
|
37333
|
+
}
|
|
36250
37334
|
}
|
|
37335
|
+
} else if (this.hostSelectedMarkerId && !markers.some(marker => marker.id === this.hostSelectedMarkerId)) {
|
|
37336
|
+
this.hostSelectedMarkerId = null;
|
|
37337
|
+
this.pendingHostSelectedSeek = null;
|
|
37338
|
+
}
|
|
37339
|
+
this.renderUI();
|
|
37340
|
+
});
|
|
37341
|
+
MP3Viewer_defineProperty(this, "handleCommentRangeDraft", draft => {
|
|
37342
|
+
if (this.isCommentRangeDragging || !isValidCommentRangeDraft(draft)) {
|
|
37343
|
+
return;
|
|
37344
|
+
}
|
|
37345
|
+
this.commentRangeDraft = {
|
|
37346
|
+
endMs: draft.endMs == null ? null : draft.endMs,
|
|
37347
|
+
startMs: draft.startMs
|
|
37348
|
+
};
|
|
37349
|
+
this.syncCommentRangeLoop();
|
|
37350
|
+
this.renderUI();
|
|
37351
|
+
});
|
|
37352
|
+
MP3Viewer_defineProperty(this, "handleCommentRangeDraftClear", () => {
|
|
37353
|
+
this.commentRangeDraft = null;
|
|
37354
|
+
this.isCommentRangeDragging = false;
|
|
37355
|
+
this.syncCommentRangeLoop();
|
|
37356
|
+
this.renderUI();
|
|
37357
|
+
});
|
|
37358
|
+
MP3Viewer_defineProperty(this, "handleCommentRangeChange", range => {
|
|
37359
|
+
if (!range || !Number.isFinite(range.startMs) || !Number.isFinite(range.endMs) || range.endMs <= range.startMs) {
|
|
37360
|
+
return;
|
|
37361
|
+
}
|
|
37362
|
+
this.commentRangeDraft = {
|
|
37363
|
+
endMs: range.endMs,
|
|
37364
|
+
startMs: range.startMs
|
|
37365
|
+
};
|
|
37366
|
+
this.emit(EVENT_COMMENT_RANGE_DRAFT_CHANGE, {
|
|
37367
|
+
endMs: range.endMs,
|
|
37368
|
+
startMs: range.startMs
|
|
37369
|
+
});
|
|
37370
|
+
this.syncCommentRangeLoop();
|
|
37371
|
+
this.renderUI();
|
|
37372
|
+
});
|
|
37373
|
+
MP3Viewer_defineProperty(this, "handleCommentRangeDragChange", isDragging => {
|
|
37374
|
+
this.isCommentRangeDragging = !!isDragging;
|
|
37375
|
+
});
|
|
37376
|
+
MP3Viewer_defineProperty(this, "handleCommentRangeClear", () => {
|
|
37377
|
+
if (!this.commentRangeDraft || this.commentRangeDraft.endMs == null) {
|
|
37378
|
+
return;
|
|
36251
37379
|
}
|
|
37380
|
+
this.commentRangeDraft = null;
|
|
37381
|
+
this.emit(EVENT_COMMENT_RANGE_DRAFT_DISMISS);
|
|
37382
|
+
this.syncCommentRangeLoop();
|
|
36252
37383
|
this.renderUI();
|
|
36253
37384
|
});
|
|
36254
37385
|
MP3Viewer_defineProperty(this, "handleCommentMarkerClick", marker => {
|
|
37386
|
+
this.exitShuttle();
|
|
36255
37387
|
this.hostSelectedMarkerId = marker.id;
|
|
36256
37388
|
this.pendingHostSelectedSeek = marker;
|
|
36257
37389
|
if (this.mediaEl) {
|
|
@@ -36290,6 +37422,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36290
37422
|
this.isAudioPlayerV2 = this.getIsAudioPlayerV2();
|
|
36291
37423
|
this.waveformPeaks = [];
|
|
36292
37424
|
this.waveformPeaksSource = null;
|
|
37425
|
+
this.isWaveformConversionPolling = false;
|
|
36293
37426
|
this.waveformDurationSec = 0;
|
|
36294
37427
|
if (this.isAudioPlayerV2) {
|
|
36295
37428
|
this.wrapperEl.classList.add('bp-media--v2');
|
|
@@ -36299,12 +37432,22 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36299
37432
|
// Listen on the loading shell. The waveform is on
|
|
36300
37433
|
// screen before the audio blob is playable; getViewer() is still null.
|
|
36301
37434
|
this.bindCommentMarkersListener();
|
|
37435
|
+
this.bindCommentRangeDraftListeners();
|
|
36302
37436
|
}
|
|
36303
37437
|
|
|
36304
37438
|
// Audio element
|
|
36305
37439
|
this.mediaEl = this.mediaContainerEl.appendChild(document.createElement('audio'));
|
|
36306
37440
|
this.mediaEl.setAttribute('preload', 'auto');
|
|
36307
37441
|
this.commentMarkers = [];
|
|
37442
|
+
this.commentRangeDraft = null;
|
|
37443
|
+
this.hostSelectedMarkerId = null;
|
|
37444
|
+
this.isCommentRangeDragging = false;
|
|
37445
|
+
this.shuttleDirection = null;
|
|
37446
|
+
this.shuttleRate = 0;
|
|
37447
|
+
this.reverseShuttleTimer = 0;
|
|
37448
|
+
this.commentRangeLoopTimer = 0;
|
|
37449
|
+
this.keyboardVolumeStep = 0;
|
|
37450
|
+
this.keyboardZoomStep = 0;
|
|
36308
37451
|
}
|
|
36309
37452
|
bindCommentMarkersListener() {
|
|
36310
37453
|
if (!this.isAudioPlayerV2) {
|
|
@@ -36313,6 +37456,15 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36313
37456
|
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
36314
37457
|
this.addListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
36315
37458
|
}
|
|
37459
|
+
bindCommentRangeDraftListeners() {
|
|
37460
|
+
if (!this.isAudioPlayerV2) {
|
|
37461
|
+
return;
|
|
37462
|
+
}
|
|
37463
|
+
this.removeListener(EVENT_COMMENT_RANGE_DRAFT, this.handleCommentRangeDraft);
|
|
37464
|
+
this.removeListener(EVENT_COMMENT_RANGE_DRAFT_CLEAR, this.handleCommentRangeDraftClear);
|
|
37465
|
+
this.addListener(EVENT_COMMENT_RANGE_DRAFT, this.handleCommentRangeDraft);
|
|
37466
|
+
this.addListener(EVENT_COMMENT_RANGE_DRAFT_CLEAR, this.handleCommentRangeDraftClear);
|
|
37467
|
+
}
|
|
36316
37468
|
|
|
36317
37469
|
/**
|
|
36318
37470
|
* Audio player v2 (waveform). Off unless the host enables `audioPlayerV2`
|
|
@@ -36324,6 +37476,217 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36324
37476
|
return this.featureEnabled(constants/* AUDIO_PLAYER_V2 */.Ku) && this.useReactControls();
|
|
36325
37477
|
}
|
|
36326
37478
|
|
|
37479
|
+
/**
|
|
37480
|
+
* V2 audio keymap. Flag off and video keep MediaBaseViewer.handleKeydownReact.
|
|
37481
|
+
* Alt is not in Preview's key decoder — read it from the native event.
|
|
37482
|
+
*
|
|
37483
|
+
* @param {string} key
|
|
37484
|
+
* @param {KeyboardEvent} [event]
|
|
37485
|
+
* @return {boolean} consumed
|
|
37486
|
+
*/
|
|
37487
|
+
onKeydown(key, event) {
|
|
37488
|
+
if (this.isAudioPlayerV2 && this.handleKeydownAudioV2(key, event)) {
|
|
37489
|
+
return true;
|
|
37490
|
+
}
|
|
37491
|
+
return super.onKeydown(key, event);
|
|
37492
|
+
}
|
|
37493
|
+
handleKeydownAudioV2(key, event) {
|
|
37494
|
+
const decoded = (key || '').toLowerCase();
|
|
37495
|
+
const altKey = !!(event && event.altKey);
|
|
37496
|
+
switch (decoded) {
|
|
37497
|
+
case 'space':
|
|
37498
|
+
this.toggleV2Play();
|
|
37499
|
+
return true;
|
|
37500
|
+
case 'k':
|
|
37501
|
+
this.exitShuttle();
|
|
37502
|
+
this.pause(undefined, true);
|
|
37503
|
+
return true;
|
|
37504
|
+
case 'j':
|
|
37505
|
+
this.shuttle('reverse');
|
|
37506
|
+
return true;
|
|
37507
|
+
case 'l':
|
|
37508
|
+
this.shuttle('forward');
|
|
37509
|
+
return true;
|
|
37510
|
+
case 'arrowleft':
|
|
37511
|
+
this.quickSeek(-AUDIO_V2_SKIP_SEC);
|
|
37512
|
+
return true;
|
|
37513
|
+
case 'arrowright':
|
|
37514
|
+
this.quickSeek(AUDIO_V2_SKIP_SEC);
|
|
37515
|
+
return true;
|
|
37516
|
+
case ',':
|
|
37517
|
+
this.frameStep('back');
|
|
37518
|
+
return true;
|
|
37519
|
+
case '.':
|
|
37520
|
+
this.frameStep('forward');
|
|
37521
|
+
return true;
|
|
37522
|
+
case 'arrowup':
|
|
37523
|
+
if (altKey || !(this.commentMarkers || []).some(marker => Number.isFinite(marker.time))) {
|
|
37524
|
+
this.stepKeyboardVolume(1);
|
|
37525
|
+
return true;
|
|
37526
|
+
}
|
|
37527
|
+
this.jumpToCommentMarker(-1);
|
|
37528
|
+
return true;
|
|
37529
|
+
case 'arrowdown':
|
|
37530
|
+
if (altKey || !(this.commentMarkers || []).some(marker => Number.isFinite(marker.time))) {
|
|
37531
|
+
this.stepKeyboardVolume(-1);
|
|
37532
|
+
return true;
|
|
37533
|
+
}
|
|
37534
|
+
this.jumpToCommentMarker(1);
|
|
37535
|
+
return true;
|
|
37536
|
+
case 'end':
|
|
37537
|
+
if (!this.mediaEl || !Number.isFinite(this.mediaEl.duration)) {
|
|
37538
|
+
return false;
|
|
37539
|
+
}
|
|
37540
|
+
this.exitShuttle();
|
|
37541
|
+
this.setMediaTime(this.mediaEl.duration);
|
|
37542
|
+
return true;
|
|
37543
|
+
case '0':
|
|
37544
|
+
case 'home':
|
|
37545
|
+
this.exitShuttle();
|
|
37546
|
+
return false;
|
|
37547
|
+
case 'shift+arrowleft':
|
|
37548
|
+
this.quickSeek(-AUDIO_V2_SHIFT_SKIP_SEC);
|
|
37549
|
+
return true;
|
|
37550
|
+
case 'shift+arrowright':
|
|
37551
|
+
this.quickSeek(AUDIO_V2_SHIFT_SKIP_SEC);
|
|
37552
|
+
return true;
|
|
37553
|
+
case 'i':
|
|
37554
|
+
case 'o':
|
|
37555
|
+
case '/':
|
|
37556
|
+
case 'shift+l':
|
|
37557
|
+
// Range UI is not on this branch yet. Consume so I/O/loop cannot
|
|
37558
|
+
// fall through to shuttle or Preview navigation.
|
|
37559
|
+
return true;
|
|
37560
|
+
case 'shift++':
|
|
37561
|
+
case '+':
|
|
37562
|
+
case '=':
|
|
37563
|
+
this.stepKeyboardZoom(1);
|
|
37564
|
+
return true;
|
|
37565
|
+
case '-':
|
|
37566
|
+
case 'shift+_':
|
|
37567
|
+
this.stepKeyboardZoom(-1);
|
|
37568
|
+
return true;
|
|
37569
|
+
default:
|
|
37570
|
+
return false;
|
|
37571
|
+
}
|
|
37572
|
+
}
|
|
37573
|
+
toggleV2Play() {
|
|
37574
|
+
const reverseShuttle = this.shuttleDirection === 'reverse';
|
|
37575
|
+
const wasPlaying = !!(this.mediaEl && !this.mediaEl.paused);
|
|
37576
|
+
this.exitShuttle();
|
|
37577
|
+
if (reverseShuttle || wasPlaying) {
|
|
37578
|
+
this.pause(undefined, true);
|
|
37579
|
+
return;
|
|
37580
|
+
}
|
|
37581
|
+
this.handlePlayRequest();
|
|
37582
|
+
}
|
|
37583
|
+
shuttle(direction) {
|
|
37584
|
+
const sameDirection = this.shuttleDirection === direction;
|
|
37585
|
+
const rate = nextShuttleRate(this.shuttleRate, sameDirection);
|
|
37586
|
+
if (direction === 'forward') {
|
|
37587
|
+
this.startForwardShuttle(rate);
|
|
37588
|
+
return;
|
|
37589
|
+
}
|
|
37590
|
+
this.startReverseShuttle(rate);
|
|
37591
|
+
}
|
|
37592
|
+
startForwardShuttle(rate) {
|
|
37593
|
+
this.stopReverseShuttle();
|
|
37594
|
+
this.shuttleDirection = 'forward';
|
|
37595
|
+
this.shuttleRate = rate;
|
|
37596
|
+
this.userRequestedPlay = true;
|
|
37597
|
+
const playPromise = this.play();
|
|
37598
|
+
if (this.mediaEl) {
|
|
37599
|
+
this.mediaEl.playbackRate = this.shuttleRate;
|
|
37600
|
+
}
|
|
37601
|
+
if (playPromise && typeof playPromise.then === 'function') {
|
|
37602
|
+
playPromise.then(() => {
|
|
37603
|
+
if (this.mediaEl && this.shuttleDirection === 'forward') {
|
|
37604
|
+
this.mediaEl.playbackRate = this.shuttleRate;
|
|
37605
|
+
}
|
|
37606
|
+
this.scheduleCommentRangeLoopWrap();
|
|
37607
|
+
}).catch(() => {});
|
|
37608
|
+
}
|
|
37609
|
+
this.scheduleCommentRangeLoopWrap(true);
|
|
37610
|
+
}
|
|
37611
|
+
startReverseShuttle(rate) {
|
|
37612
|
+
this.stopReverseShuttle();
|
|
37613
|
+
this.shuttleDirection = 'reverse';
|
|
37614
|
+
this.shuttleRate = rate;
|
|
37615
|
+
this.userRequestedPlay = true;
|
|
37616
|
+
this.pause(undefined, true);
|
|
37617
|
+
this.handleRate();
|
|
37618
|
+
this.reverseShuttleTimer = window.setInterval(() => {
|
|
37619
|
+
const floor = this.clampTimeToOpenCommentRange(0);
|
|
37620
|
+
if (!this.mediaEl || this.mediaEl.currentTime <= floor) {
|
|
37621
|
+
this.exitShuttle();
|
|
37622
|
+
return;
|
|
37623
|
+
}
|
|
37624
|
+
this.quickSeek(-(this.shuttleRate * AUDIO_V2_SHUTTLE_TICK_MS / 1000));
|
|
37625
|
+
if (this.mediaEl.currentTime <= floor) {
|
|
37626
|
+
this.exitShuttle();
|
|
37627
|
+
}
|
|
37628
|
+
}, AUDIO_V2_SHUTTLE_TICK_MS);
|
|
37629
|
+
}
|
|
37630
|
+
stopReverseShuttle() {
|
|
37631
|
+
if (this.reverseShuttleTimer) {
|
|
37632
|
+
window.clearInterval(this.reverseShuttleTimer);
|
|
37633
|
+
this.reverseShuttleTimer = 0;
|
|
37634
|
+
}
|
|
37635
|
+
}
|
|
37636
|
+
exitShuttle() {
|
|
37637
|
+
const wasShuttling = !!this.shuttleDirection;
|
|
37638
|
+
this.stopReverseShuttle();
|
|
37639
|
+
this.shuttleDirection = null;
|
|
37640
|
+
this.shuttleRate = 0;
|
|
37641
|
+
if (wasShuttling) {
|
|
37642
|
+
this.handleRate();
|
|
37643
|
+
}
|
|
37644
|
+
}
|
|
37645
|
+
|
|
37646
|
+
/**
|
|
37647
|
+
* Keep the settings rate unless forward shuttle owns playbackRate.
|
|
37648
|
+
*
|
|
37649
|
+
* @inheritdoc
|
|
37650
|
+
*/
|
|
37651
|
+
handleRate() {
|
|
37652
|
+
if (this.shuttleDirection === 'forward' && this.shuttleRate > 0 && this.mediaEl) {
|
|
37653
|
+
this.mediaEl.playbackRate = this.shuttleRate;
|
|
37654
|
+
if (this.controls) {
|
|
37655
|
+
this.renderUI();
|
|
37656
|
+
}
|
|
37657
|
+
this.scheduleCommentRangeLoopWrap();
|
|
37658
|
+
return;
|
|
37659
|
+
}
|
|
37660
|
+
super.handleRate();
|
|
37661
|
+
this.scheduleCommentRangeLoopWrap();
|
|
37662
|
+
}
|
|
37663
|
+
jumpToCommentMarker(direction) {
|
|
37664
|
+
if (!this.mediaEl) {
|
|
37665
|
+
return;
|
|
37666
|
+
}
|
|
37667
|
+
const target = nextCommentMarker(this.commentMarkers, {
|
|
37668
|
+
direction,
|
|
37669
|
+
selectedId: this.hostSelectedMarkerId,
|
|
37670
|
+
time: this.mediaEl.currentTime
|
|
37671
|
+
});
|
|
37672
|
+
if (!target || target.id === this.hostSelectedMarkerId) {
|
|
37673
|
+
return;
|
|
37674
|
+
}
|
|
37675
|
+
this.handleCommentMarkerClick(target);
|
|
37676
|
+
}
|
|
37677
|
+
stepKeyboardVolume(direction) {
|
|
37678
|
+
this.keyboardVolumeStep += 1;
|
|
37679
|
+
if (direction > 0) {
|
|
37680
|
+
this.increaseVolume();
|
|
37681
|
+
return;
|
|
37682
|
+
}
|
|
37683
|
+
this.decreaseVolume();
|
|
37684
|
+
}
|
|
37685
|
+
stepKeyboardZoom(direction) {
|
|
37686
|
+
this.keyboardZoomStep += direction;
|
|
37687
|
+
this.renderUI();
|
|
37688
|
+
}
|
|
37689
|
+
|
|
36327
37690
|
/**
|
|
36328
37691
|
* Load v2 controls (and wavesurfer) only when the audio player v2 gate is on.
|
|
36329
37692
|
*
|
|
@@ -36366,7 +37729,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36366
37729
|
* @return {Promise<{ default: Function }>} MP3ControlsV2 module
|
|
36367
37730
|
*/
|
|
36368
37731
|
importV2Controls() {
|
|
36369
|
-
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
37732
|
+
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 673));
|
|
36370
37733
|
}
|
|
36371
37734
|
|
|
36372
37735
|
/**
|
|
@@ -36388,7 +37751,15 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36388
37751
|
* @inheritdoc
|
|
36389
37752
|
*/
|
|
36390
37753
|
destroy() {
|
|
37754
|
+
this.clearCommentRangeLoopTimer();
|
|
36391
37755
|
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
37756
|
+
this.removeListener(EVENT_COMMENT_RANGE_DRAFT, this.handleCommentRangeDraft);
|
|
37757
|
+
this.removeListener(EVENT_COMMENT_RANGE_DRAFT_CLEAR, this.handleCommentRangeDraftClear);
|
|
37758
|
+
this.commentRangeDraft = null;
|
|
37759
|
+
this.isCommentRangeDragging = false;
|
|
37760
|
+
this.stopReverseShuttle();
|
|
37761
|
+
this.shuttleDirection = null;
|
|
37762
|
+
this.shuttleRate = 0;
|
|
36392
37763
|
this.abortWaveformLoads();
|
|
36393
37764
|
super.destroy();
|
|
36394
37765
|
}
|
|
@@ -36398,6 +37769,10 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36398
37769
|
*/
|
|
36399
37770
|
load() {
|
|
36400
37771
|
if (this.isAudioPlayerV2) {
|
|
37772
|
+
// A file-version switch is a clear, not a resync of the previous draft.
|
|
37773
|
+
this.commentRangeDraft = null;
|
|
37774
|
+
this.isCommentRangeDragging = false;
|
|
37775
|
+
this.syncCommentRangeLoop();
|
|
36401
37776
|
this.showAudioLoadingShell();
|
|
36402
37777
|
this.startConversionWaveformLoad();
|
|
36403
37778
|
}
|
|
@@ -36471,6 +37846,48 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36471
37846
|
return (0,validateWaveformPayload/* isPositiveFinite */.Ze)(compressedBytes) && compressedBytes <= waveform_constants/* CLIENT_DECODE_MAX_COMPRESSED_BYTES */.EB && (0,validateWaveformPayload/* isPositiveFinite */.Ze)(durationSec) && durationSec <= waveform_constants/* CLIENT_DECODE_MAX_DURATION_SEC */.nG;
|
|
36472
37847
|
}
|
|
36473
37848
|
|
|
37849
|
+
/**
|
|
37850
|
+
* @return {Object|null} waveform conversion representation
|
|
37851
|
+
*/
|
|
37852
|
+
getWaveformRepresentation() {
|
|
37853
|
+
const {
|
|
37854
|
+
file
|
|
37855
|
+
} = this.options;
|
|
37856
|
+
return file?.representations?.entries ? getRepresentation(file, constants/* WAVEFORM_REP_NAME */.u4) : null;
|
|
37857
|
+
}
|
|
37858
|
+
|
|
37859
|
+
/**
|
|
37860
|
+
* @return {string|null} conversion representation state
|
|
37861
|
+
*/
|
|
37862
|
+
getWaveformConversionState() {
|
|
37863
|
+
const conversionStatus = this.getWaveformRepresentation()?.status;
|
|
37864
|
+
return conversionStatus && typeof conversionStatus === 'object' ? conversionStatus.state : null;
|
|
37865
|
+
}
|
|
37866
|
+
|
|
37867
|
+
/**
|
|
37868
|
+
* Conversion JSON is already (or about to be) fetchable.
|
|
37869
|
+
*
|
|
37870
|
+
* @return {boolean}
|
|
37871
|
+
*/
|
|
37872
|
+
isConversionWaveformAvailable() {
|
|
37873
|
+
const conversionState = this.getWaveformConversionState();
|
|
37874
|
+
return conversionState === constants/* STATUS_SUCCESS */.$g || conversionState === constants/* STATUS_VIEWABLE */.Re;
|
|
37875
|
+
}
|
|
37876
|
+
|
|
37877
|
+
/**
|
|
37878
|
+
* Generating chip while conversion RepStatus is polling. Hidden when the
|
|
37879
|
+
* rep is already success/viewable, when polling finishes, when conversion
|
|
37880
|
+
* errors, and once any source applies peaks.
|
|
37881
|
+
*
|
|
37882
|
+
* @return {boolean}
|
|
37883
|
+
*/
|
|
37884
|
+
isGeneratingWaveform() {
|
|
37885
|
+
if (!this.isAudioPlayerV2 || this.destroyed || this.waveformPeaksSource) {
|
|
37886
|
+
return false;
|
|
37887
|
+
}
|
|
37888
|
+
return !!this.isWaveformConversionPolling;
|
|
37889
|
+
}
|
|
37890
|
+
|
|
36474
37891
|
/**
|
|
36475
37892
|
* @param {number} durationSec
|
|
36476
37893
|
* @return {boolean}
|
|
@@ -36507,30 +37924,40 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36507
37924
|
if (!this.isAudioPlayerV2 || this.destroyed) {
|
|
36508
37925
|
return;
|
|
36509
37926
|
}
|
|
36510
|
-
const
|
|
36511
|
-
file
|
|
36512
|
-
} = this.options;
|
|
36513
|
-
const waveform = file?.representations?.entries ? getRepresentation(file, constants/* WAVEFORM_REP_NAME */.u4) : null;
|
|
37927
|
+
const waveform = this.getWaveformRepresentation();
|
|
36514
37928
|
const template = waveform?.content?.url_template;
|
|
36515
|
-
const
|
|
36516
|
-
|
|
36517
|
-
if (!waveform || !template || !statusState || statusState === constants/* STATUS_ERROR */.uD) {
|
|
37929
|
+
const conversionState = this.getWaveformConversionState();
|
|
37930
|
+
if (!waveform || !template || !conversionState || conversionState === constants/* STATUS_ERROR */.uD) {
|
|
36518
37931
|
this.startClientWaveformDecode();
|
|
37932
|
+
this.renderUI();
|
|
36519
37933
|
return;
|
|
36520
37934
|
}
|
|
36521
37935
|
this.abortConversionWaveformLoad();
|
|
36522
37936
|
this.waveformStatus = this.getRepStatus(waveform);
|
|
36523
37937
|
this.waveformStatus.removeListener('conversionpending', this.resetLoadTimeout);
|
|
36524
37938
|
const status = this.waveformStatus;
|
|
37939
|
+
const shouldPollConversion = !this.isConversionWaveformAvailable();
|
|
36525
37940
|
try {
|
|
37941
|
+
if (shouldPollConversion) {
|
|
37942
|
+
this.isWaveformConversionPolling = true;
|
|
37943
|
+
this.renderUI();
|
|
37944
|
+
}
|
|
36526
37945
|
await status.getPromise();
|
|
37946
|
+
this.isWaveformConversionPolling = false;
|
|
36527
37947
|
if (this.destroyed || this.waveformStatus !== status || this.waveformPeaksSource) {
|
|
36528
37948
|
return;
|
|
36529
37949
|
}
|
|
37950
|
+
if (shouldPollConversion) {
|
|
37951
|
+
this.renderUI();
|
|
37952
|
+
}
|
|
36530
37953
|
const result = await this.loadConversionWaveformPayload(template);
|
|
36531
37954
|
this.handleConversionWaveformResult(result, status);
|
|
36532
37955
|
} catch {
|
|
37956
|
+
this.isWaveformConversionPolling = false;
|
|
36533
37957
|
this.startClientWaveformDecode();
|
|
37958
|
+
if (shouldPollConversion) {
|
|
37959
|
+
this.renderUI();
|
|
37960
|
+
}
|
|
36534
37961
|
}
|
|
36535
37962
|
}
|
|
36536
37963
|
|
|
@@ -36581,6 +38008,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36581
38008
|
}
|
|
36582
38009
|
this.waveformPeaks = payload.peaks;
|
|
36583
38010
|
this.waveformPeaksSource = source;
|
|
38011
|
+
this.isWaveformConversionPolling = false;
|
|
36584
38012
|
this.isWaveformDecodeRetryPending = false;
|
|
36585
38013
|
if (source === 'conversion') {
|
|
36586
38014
|
this.waveformDurationSec = payload.durationSec;
|
|
@@ -36749,6 +38177,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36749
38177
|
});
|
|
36750
38178
|
}
|
|
36751
38179
|
this.bindCommentMarkersListener();
|
|
38180
|
+
this.bindCommentRangeDraftListeners();
|
|
36752
38181
|
this.renderUI();
|
|
36753
38182
|
}
|
|
36754
38183
|
/**
|
|
@@ -36764,11 +38193,162 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36764
38193
|
return;
|
|
36765
38194
|
}
|
|
36766
38195
|
this.pendingHostSelectedSeek = null;
|
|
38196
|
+
this.exitShuttle();
|
|
38197
|
+
this.handleCommentRangeClear();
|
|
36767
38198
|
this.mediaEl.pause();
|
|
36768
38199
|
if (this.mediaEl.currentTime !== marker.time) {
|
|
36769
38200
|
this.mediaEl.currentTime = marker.time;
|
|
36770
38201
|
}
|
|
36771
38202
|
}
|
|
38203
|
+
|
|
38204
|
+
/**
|
|
38205
|
+
* Seconds of the open draft span, or null when collapsed / absent.
|
|
38206
|
+
* Collapsed drafts (`endMs: null`) do not confine playback.
|
|
38207
|
+
*
|
|
38208
|
+
* @return {{endSec: number, startSec: number}|null}
|
|
38209
|
+
*/
|
|
38210
|
+
getOpenCommentRangeSeconds() {
|
|
38211
|
+
const draft = this.commentRangeDraft;
|
|
38212
|
+
if ((0,range/* isRangeCollapsed */.BT)(draft) || !Number.isFinite(draft.startMs) || !Number.isFinite(draft.endMs)) {
|
|
38213
|
+
return null;
|
|
38214
|
+
}
|
|
38215
|
+
return {
|
|
38216
|
+
endSec: draft.endMs / 1000,
|
|
38217
|
+
startSec: draft.startMs / 1000
|
|
38218
|
+
};
|
|
38219
|
+
}
|
|
38220
|
+
|
|
38221
|
+
/**
|
|
38222
|
+
* Keep a seek inside the open draft. Waveform click-outside and host
|
|
38223
|
+
* comment seeks dismiss first, then seek; clamp does not apply then.
|
|
38224
|
+
*
|
|
38225
|
+
* @param {number} time
|
|
38226
|
+
* @return {number}
|
|
38227
|
+
*/
|
|
38228
|
+
clampTimeToOpenCommentRange(time) {
|
|
38229
|
+
const range = this.getOpenCommentRangeSeconds();
|
|
38230
|
+
if (!range || !Number.isFinite(time)) {
|
|
38231
|
+
return time;
|
|
38232
|
+
}
|
|
38233
|
+
return Math.min(Math.max(time, range.startSec), range.endSec);
|
|
38234
|
+
}
|
|
38235
|
+
clearCommentRangeLoopTimer() {
|
|
38236
|
+
if (this.commentRangeLoopTimer) {
|
|
38237
|
+
window.clearTimeout(this.commentRangeLoopTimer);
|
|
38238
|
+
this.commentRangeLoopTimer = 0;
|
|
38239
|
+
}
|
|
38240
|
+
}
|
|
38241
|
+
|
|
38242
|
+
/**
|
|
38243
|
+
* Wrap when the remaining time to end elapses. Recalculate after play, seek,
|
|
38244
|
+
* rate change, or a draft resize.
|
|
38245
|
+
*
|
|
38246
|
+
* @param {boolean} [force] schedule even if the element still reports paused
|
|
38247
|
+
* @return {void}
|
|
38248
|
+
*/
|
|
38249
|
+
scheduleCommentRangeLoopWrap(force = false) {
|
|
38250
|
+
this.clearCommentRangeLoopTimer();
|
|
38251
|
+
const range = this.getOpenCommentRangeSeconds();
|
|
38252
|
+
if (!range || !this.mediaEl || !force && this.mediaEl.paused) {
|
|
38253
|
+
return;
|
|
38254
|
+
}
|
|
38255
|
+
const rate = this.mediaEl.playbackRate > 0 ? this.mediaEl.playbackRate : 1;
|
|
38256
|
+
const remainingSec = range.endSec - this.mediaEl.currentTime;
|
|
38257
|
+
this.commentRangeLoopTimer = window.setTimeout(() => {
|
|
38258
|
+
this.commentRangeLoopTimer = 0;
|
|
38259
|
+
const openRange = this.getOpenCommentRangeSeconds();
|
|
38260
|
+
if (!openRange || !this.mediaEl || this.mediaEl.paused) {
|
|
38261
|
+
return;
|
|
38262
|
+
}
|
|
38263
|
+
if (this.mediaEl.currentTime !== openRange.startSec) {
|
|
38264
|
+
this.mediaEl.currentTime = openRange.startSec;
|
|
38265
|
+
}
|
|
38266
|
+
this.scheduleCommentRangeLoopWrap();
|
|
38267
|
+
}, Math.max(0, remainingSec / rate * 1000));
|
|
38268
|
+
}
|
|
38269
|
+
|
|
38270
|
+
/**
|
|
38271
|
+
* Update the playback loop to match the current range after it arrives, resizes,
|
|
38272
|
+
* or clears.
|
|
38273
|
+
*
|
|
38274
|
+
* @return {void}
|
|
38275
|
+
*/
|
|
38276
|
+
syncCommentRangeLoop() {
|
|
38277
|
+
this.clearCommentRangeLoopTimer();
|
|
38278
|
+
const range = this.getOpenCommentRangeSeconds();
|
|
38279
|
+
if (!range || !this.mediaEl || this.mediaEl.paused) {
|
|
38280
|
+
return;
|
|
38281
|
+
}
|
|
38282
|
+
this.enforceCommentRangePlayback(range);
|
|
38283
|
+
}
|
|
38284
|
+
|
|
38285
|
+
/**
|
|
38286
|
+
* Keep playback inside the open span. A playhead outside [start, end) jumps
|
|
38287
|
+
* to start, then the wrap timer is armed.
|
|
38288
|
+
*
|
|
38289
|
+
* @param {{endSec: number, startSec: number}} range Open draft in seconds
|
|
38290
|
+
* @return {void}
|
|
38291
|
+
*/
|
|
38292
|
+
enforceCommentRangePlayback(range) {
|
|
38293
|
+
const {
|
|
38294
|
+
endSec,
|
|
38295
|
+
startSec
|
|
38296
|
+
} = range;
|
|
38297
|
+
const currPlayhead = this.mediaEl.currentTime;
|
|
38298
|
+
const nextPlayhead = currPlayhead >= startSec && currPlayhead < endSec ? currPlayhead : startSec;
|
|
38299
|
+
if (nextPlayhead !== currPlayhead) {
|
|
38300
|
+
this.mediaEl.currentTime = nextPlayhead;
|
|
38301
|
+
}
|
|
38302
|
+
this.scheduleCommentRangeLoopWrap();
|
|
38303
|
+
}
|
|
38304
|
+
|
|
38305
|
+
/**
|
|
38306
|
+
* Play. An open draft loops that span: keep the playhead when it is already
|
|
38307
|
+
* inside, otherwise jump to start. Does not use play(start, end) because
|
|
38308
|
+
* that pauses at end.
|
|
38309
|
+
*
|
|
38310
|
+
* @inheritdoc
|
|
38311
|
+
*/
|
|
38312
|
+
play(...args) {
|
|
38313
|
+
const range = this.getOpenCommentRangeSeconds();
|
|
38314
|
+
if (!range || !this.mediaEl) {
|
|
38315
|
+
// Spread so an argument-less call stays argument-less; super.play() skips
|
|
38316
|
+
// playback when it is handed an explicit undefined start.
|
|
38317
|
+
return super.play(...args);
|
|
38318
|
+
}
|
|
38319
|
+
const requested = Number.isFinite(args[0]) ? args[0] : this.mediaEl.currentTime;
|
|
38320
|
+
const next = requested >= range.startSec && requested < range.endSec ? requested : range.startSec;
|
|
38321
|
+
if (this.mediaEl.currentTime !== next) {
|
|
38322
|
+
this.mediaEl.currentTime = next;
|
|
38323
|
+
}
|
|
38324
|
+
const playPromise = super.play();
|
|
38325
|
+
this.scheduleCommentRangeLoopWrap(true);
|
|
38326
|
+
return playPromise;
|
|
38327
|
+
}
|
|
38328
|
+
|
|
38329
|
+
/**
|
|
38330
|
+
* Seek. Keyboard and in-range waveform seeks stay inside an open draft.
|
|
38331
|
+
*
|
|
38332
|
+
* @inheritdoc
|
|
38333
|
+
*/
|
|
38334
|
+
setMediaTime(time) {
|
|
38335
|
+
super.setMediaTime(this.clampTimeToOpenCommentRange(time));
|
|
38336
|
+
this.scheduleCommentRangeLoopWrap();
|
|
38337
|
+
}
|
|
38338
|
+
|
|
38339
|
+
/**
|
|
38340
|
+
* If the range ends at file end, wrap instead of resetting the play icon.
|
|
38341
|
+
*
|
|
38342
|
+
* @inheritdoc
|
|
38343
|
+
*/
|
|
38344
|
+
mediaendHandler() {
|
|
38345
|
+
if (this.getOpenCommentRangeSeconds()) {
|
|
38346
|
+
// `ended` fires after the element is paused; play() wraps and restarts.
|
|
38347
|
+
this.play();
|
|
38348
|
+
return;
|
|
38349
|
+
}
|
|
38350
|
+
super.mediaendHandler();
|
|
38351
|
+
}
|
|
36772
38352
|
/**
|
|
36773
38353
|
* @inheritdoc
|
|
36774
38354
|
*/
|
|
@@ -36806,9 +38386,19 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36806
38386
|
const Mp3ControlsV2 = this.MP3ControlsV2;
|
|
36807
38387
|
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(Mp3ControlsV2, MP3Viewer_extends({}, sharedProps, {
|
|
36808
38388
|
commentMarkers: this.commentMarkers || [],
|
|
38389
|
+
commentRangeDraft: this.commentRangeDraft || null,
|
|
38390
|
+
hasStartedPlayback: !!this.userRequestedPlay,
|
|
38391
|
+
isGeneratingWaveform: this.isGeneratingWaveform(),
|
|
38392
|
+
keyboardVolumeStep: this.keyboardVolumeStep,
|
|
38393
|
+
keyboardZoomStep: this.keyboardZoomStep,
|
|
36809
38394
|
mediaEl: this.mediaEl,
|
|
36810
38395
|
onCommentMarkerClick: this.handleCommentMarkerClick,
|
|
36811
|
-
|
|
38396
|
+
onCommentRangeChange: this.handleCommentRangeChange,
|
|
38397
|
+
onCommentRangeClear: this.handleCommentRangeClear,
|
|
38398
|
+
onCommentRangeDragChange: this.handleCommentRangeDragChange,
|
|
38399
|
+
onPlayNextChange: this.setPlayNext,
|
|
38400
|
+
peaks: this.waveformPeaks,
|
|
38401
|
+
playNext: this.isPlayNextEnabled()
|
|
36812
38402
|
})));
|
|
36813
38403
|
return;
|
|
36814
38404
|
}
|
|
@@ -38404,7 +39994,7 @@ function VideoControls({
|
|
|
38404
39994
|
onPlayPause: onPlayPause
|
|
38405
39995
|
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
38406
39996
|
className: "bp-VideoControls-group bp-VideoControls-group--media-controls"
|
|
38407
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
39997
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
38408
39998
|
onMuteChange: onMuteChange,
|
|
38409
39999
|
onVolumeChange: onVolumeChange,
|
|
38410
40000
|
volume: volume
|
|
@@ -38889,12 +40479,14 @@ function VideoControlsV2({
|
|
|
38889
40479
|
onGuideChange,
|
|
38890
40480
|
onMuteChange,
|
|
38891
40481
|
onPlayPause,
|
|
40482
|
+
onPlayNextChange,
|
|
38892
40483
|
onQualityChange,
|
|
38893
40484
|
onRateChange,
|
|
38894
40485
|
onSubtitleChange,
|
|
38895
40486
|
onSubtitlesToggle,
|
|
38896
40487
|
onTimeChange,
|
|
38897
40488
|
onVolumeChange,
|
|
40489
|
+
playNext,
|
|
38898
40490
|
quality,
|
|
38899
40491
|
rate,
|
|
38900
40492
|
subtitle,
|
|
@@ -38963,7 +40555,7 @@ function VideoControlsV2({
|
|
|
38963
40555
|
mediaEl: mediaEl
|
|
38964
40556
|
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
38965
40557
|
className: "bp-VideoControlsV2-group bp-VideoControlsV2-group--right"
|
|
38966
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
40558
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
38967
40559
|
onMuteChange: onMuteChange,
|
|
38968
40560
|
onVolumeChange: onVolumeChange,
|
|
38969
40561
|
volume: volume
|
|
@@ -38983,9 +40575,11 @@ function VideoControlsV2({
|
|
|
38983
40575
|
onAudioTrackChange: onAudioTrackChange,
|
|
38984
40576
|
onAutoplayChange: onAutoplayChange,
|
|
38985
40577
|
onGuideChange: onGuideChange,
|
|
40578
|
+
onPlayNextChange: onPlayNextChange,
|
|
38986
40579
|
onQualityChange: onQualityChange,
|
|
38987
40580
|
onRateChange: onRateChange,
|
|
38988
40581
|
onSubtitleChange: onSubtitleChange,
|
|
40582
|
+
playNext: playNext,
|
|
38989
40583
|
quality: quality,
|
|
38990
40584
|
rate: rate,
|
|
38991
40585
|
subtitle: subtitle,
|
|
@@ -39143,7 +40737,10 @@ class MP4Viewer extends media_VideoBaseViewer {
|
|
|
39143
40737
|
volume: this.mediaEl.volume
|
|
39144
40738
|
};
|
|
39145
40739
|
if (this.isVideoPlayerV2) {
|
|
39146
|
-
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(VideoControlsV2, sharedProps
|
|
40740
|
+
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(VideoControlsV2, MP4Viewer_extends({}, sharedProps, {
|
|
40741
|
+
onPlayNextChange: this.setPlayNext,
|
|
40742
|
+
playNext: this.isPlayNextEnabled()
|
|
40743
|
+
})));
|
|
39147
40744
|
return;
|
|
39148
40745
|
}
|
|
39149
40746
|
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(VideoControls, MP4Viewer_extends({}, sharedProps, {
|
|
@@ -40639,7 +42236,10 @@ class DashViewer extends media_VideoBaseViewer {
|
|
|
40639
42236
|
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(VideoControlsV2, DashViewer_extends({
|
|
40640
42237
|
commentMarkers: this.commentMarkers,
|
|
40641
42238
|
onCommentMarkerClick: this.handleCommentMarkerClick
|
|
40642
|
-
}, sharedProps
|
|
42239
|
+
}, sharedProps, {
|
|
42240
|
+
onPlayNextChange: this.setPlayNext,
|
|
42241
|
+
playNext: this.isPlayNextEnabled()
|
|
42242
|
+
})));
|
|
40643
42243
|
return;
|
|
40644
42244
|
}
|
|
40645
42245
|
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(VideoControls, DashViewer_extends({}, sharedProps, {
|
|
@@ -53307,6 +54907,7 @@ class Preview extends (events_default()) {
|
|
|
53307
54907
|
this.viewer.destroy();
|
|
53308
54908
|
}
|
|
53309
54909
|
this.viewer = undefined;
|
|
54910
|
+
Preview.resin = null;
|
|
53310
54911
|
}
|
|
53311
54912
|
|
|
53312
54913
|
/**
|
|
@@ -54192,6 +55793,7 @@ class Preview extends (events_default()) {
|
|
|
54192
55793
|
|
|
54193
55794
|
// Optional resin analytics instance for tracking user interactions
|
|
54194
55795
|
this.options.resin = options.resin;
|
|
55796
|
+
Preview.resin = options.resin;
|
|
54195
55797
|
|
|
54196
55798
|
// Options that are applicable to certain file ids
|
|
54197
55799
|
this.options.fileOptions = options.fileOptions || {};
|
|
@@ -54567,6 +56169,10 @@ class Preview extends (events_default()) {
|
|
|
54567
56169
|
this.emit(data.event, data.data);
|
|
54568
56170
|
this.emit(lib_events/* VIEWER_EVENT */.Oi.default, data);
|
|
54569
56171
|
break;
|
|
56172
|
+
case lib_events/* VIEWER_EVENT */.Oi.mediaEndPlayNext:
|
|
56173
|
+
this.emit(data.event, data.data);
|
|
56174
|
+
this.emit(lib_events/* VIEWER_EVENT */.Oi.default, data);
|
|
56175
|
+
break;
|
|
54570
56176
|
case lib_events/* VIEWER_EVENT */.Oi.error:
|
|
54571
56177
|
// Do nothing since 'error' event was already caught, and will be emitted
|
|
54572
56178
|
// as a 'preview_error' event
|