box-content-preview 3.91.0 → 3.92.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 +2 -1
- package/dist/lib/index.js +1062 -59
- package/package.json +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -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.92.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 = {};
|
|
@@ -2916,10 +2916,10 @@ function TimestampControl({
|
|
|
2916
2916
|
|
|
2917
2917
|
// EXPORTS
|
|
2918
2918
|
__webpack_require__.d(__webpack_exports__, {
|
|
2919
|
-
|
|
2919
|
+
Ay: () => (/* binding */ VolumeControls)
|
|
2920
2920
|
});
|
|
2921
2921
|
|
|
2922
|
-
// UNUSED EXPORTS: getIcon
|
|
2922
|
+
// UNUSED EXPORTS: VOLUME_FLYOUT_DISMISS_MS, getIcon
|
|
2923
2923
|
|
|
2924
2924
|
// EXTERNAL MODULE: external "react"
|
|
2925
2925
|
var external_react_ = __webpack_require__(1649);
|
|
@@ -2981,12 +2981,26 @@ function IconVolumeMuted24(props) {
|
|
|
2981
2981
|
var MediaToggle = __webpack_require__(8997);
|
|
2982
2982
|
;// ./src/lib/viewers/controls/hooks/useAttention.ts
|
|
2983
2983
|
|
|
2984
|
+
/** True when focus/hover is moving to a descendant, not leaving the host. */
|
|
2985
|
+
function isRelatedTargetInside(event) {
|
|
2986
|
+
return event.currentTarget.contains(event.relatedTarget);
|
|
2987
|
+
}
|
|
2984
2988
|
function useAttention() {
|
|
2985
2989
|
const [isFocused, setFocused] = external_react_.useState(false);
|
|
2986
2990
|
const [isHovered, setHovered] = external_react_.useState(false);
|
|
2987
|
-
const handleBlur =
|
|
2991
|
+
const handleBlur = event => {
|
|
2992
|
+
if (isRelatedTargetInside(event)) {
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
setFocused(false);
|
|
2996
|
+
};
|
|
2988
2997
|
const handleFocus = () => setFocused(true);
|
|
2989
|
-
const handleMouseOut =
|
|
2998
|
+
const handleMouseOut = event => {
|
|
2999
|
+
if (isRelatedTargetInside(event)) {
|
|
3000
|
+
return;
|
|
3001
|
+
}
|
|
3002
|
+
setHovered(false);
|
|
3003
|
+
};
|
|
2990
3004
|
const handleMouseOver = () => setHovered(true);
|
|
2991
3005
|
return [isFocused || isHovered, {
|
|
2992
3006
|
onBlur: handleBlur,
|
|
@@ -3023,7 +3037,7 @@ var util = __webpack_require__(4410);
|
|
|
3023
3037
|
// extracted by mini-css-extract-plugin
|
|
3024
3038
|
|
|
3025
3039
|
;// ./src/lib/viewers/controls/slider/VolumeSliderControl.tsx
|
|
3026
|
-
const _excluded = ["className", "max", "min", "onMove", "onUpdate", "step", "title", "value", "onMouseOver"];
|
|
3040
|
+
const _excluded = ["className", "max", "min", "onMove", "onUpdate", "step", "title", "value", "onMouseOver", "tabIndex"];
|
|
3027
3041
|
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
3042
|
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
3043
|
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,7 +3063,8 @@ function VolumeSliderControl(_ref) {
|
|
|
3049
3063
|
step = 1,
|
|
3050
3064
|
title,
|
|
3051
3065
|
value,
|
|
3052
|
-
onMouseOver
|
|
3066
|
+
onMouseOver,
|
|
3067
|
+
tabIndex = 0
|
|
3053
3068
|
} = _ref,
|
|
3054
3069
|
rest = _objectWithoutProperties(_ref, _excluded);
|
|
3055
3070
|
const [isScrubbing, setIsScrubbing] = external_react_["default"].useState(false);
|
|
@@ -3160,33 +3175,29 @@ function VolumeSliderControl(_ref) {
|
|
|
3160
3175
|
className: "bp-VolumeVerticalSliderControl-track-container"
|
|
3161
3176
|
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3162
3177
|
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
3178
|
"aria-label": title,
|
|
3169
3179
|
"aria-valuemax": max,
|
|
3170
3180
|
"aria-valuemin": min,
|
|
3171
3181
|
"aria-valuenow": value,
|
|
3172
|
-
className: "bp-VolumeVerticalSliderControl-track",
|
|
3182
|
+
className: "bp-VolumeVerticalSliderControl-track-background",
|
|
3173
3183
|
"data-resin-target": "volumeSlider",
|
|
3174
3184
|
"data-testid": "bp-volume-slider-control-track",
|
|
3175
|
-
onFocus:
|
|
3185
|
+
onFocus: (noop_default()),
|
|
3176
3186
|
onKeyDown: handleKeydown,
|
|
3177
3187
|
onMouseDown: handleMouseDown,
|
|
3178
3188
|
onMouseMove: handleMouseMove,
|
|
3179
3189
|
onMouseOver: onMouseOver,
|
|
3180
3190
|
onTouchStart: handleTouchStart,
|
|
3181
3191
|
role: "slider",
|
|
3192
|
+
tabIndex: tabIndex
|
|
3193
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3194
|
+
className: "bp-VolumeVerticalSliderControl-track",
|
|
3182
3195
|
style: {
|
|
3183
3196
|
height: `${heightValueBasedOnVolume / max * 100}%`
|
|
3184
|
-
}
|
|
3185
|
-
tabIndex: 0
|
|
3197
|
+
}
|
|
3186
3198
|
}))));
|
|
3187
3199
|
}
|
|
3188
3200
|
;// ./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
3201
|
|
|
3191
3202
|
|
|
3192
3203
|
|
|
@@ -3197,6 +3208,9 @@ function VolumeControls_extends() { return VolumeControls_extends = Object.assig
|
|
|
3197
3208
|
|
|
3198
3209
|
|
|
3199
3210
|
|
|
3211
|
+
|
|
3212
|
+
/** Keyboard volume keeps the flyout open longer than the 200ms max-width transition. */
|
|
3213
|
+
const VOLUME_FLYOUT_DISMISS_MS = 1000;
|
|
3200
3214
|
function getIcon(volume) {
|
|
3201
3215
|
let Icon = icons_IconVolumeMuted24;
|
|
3202
3216
|
if (volume >= 0.66) {
|
|
@@ -3209,16 +3223,32 @@ function getIcon(volume) {
|
|
|
3209
3223
|
return Icon;
|
|
3210
3224
|
}
|
|
3211
3225
|
function VolumeControls({
|
|
3226
|
+
keyboardVolumeStep = 0,
|
|
3212
3227
|
onMuteChange,
|
|
3213
3228
|
onVolumeChange,
|
|
3214
3229
|
volume = 1
|
|
3215
3230
|
}) {
|
|
3216
3231
|
const [isActive, handlers] = useAttention();
|
|
3232
|
+
const [isRevealed, setIsRevealed] = (0,external_react_.useState)(false);
|
|
3233
|
+
const revealTimerRef = (0,external_react_.useRef)(0);
|
|
3217
3234
|
const isMuted = !volume;
|
|
3218
3235
|
const Icon = isMuted ? icons_IconVolumeMuted24 : getIcon(volume);
|
|
3219
3236
|
const title = isMuted ? "Unmute" : "Mute";
|
|
3220
3237
|
const value = Math.round(volume * 100);
|
|
3221
|
-
const
|
|
3238
|
+
const isOpen = isActive || isRevealed;
|
|
3239
|
+
(0,external_react_.useEffect)(() => {
|
|
3240
|
+
if (!keyboardVolumeStep) {
|
|
3241
|
+
return;
|
|
3242
|
+
}
|
|
3243
|
+
setIsRevealed(true);
|
|
3244
|
+
window.clearTimeout(revealTimerRef.current);
|
|
3245
|
+
revealTimerRef.current = window.setTimeout(() => {
|
|
3246
|
+
setIsRevealed(false);
|
|
3247
|
+
revealTimerRef.current = 0;
|
|
3248
|
+
}, VOLUME_FLYOUT_DISMISS_MS);
|
|
3249
|
+
}, [keyboardVolumeStep]);
|
|
3250
|
+
(0,external_react_.useEffect)(() => () => window.clearTimeout(revealTimerRef.current), []);
|
|
3251
|
+
const handleVolume = (0,external_react_.useCallback)(newValue => {
|
|
3222
3252
|
const newValueToUse = newValue <= 5 ? 0 : newValue;
|
|
3223
3253
|
// make sure the value is always between 0 and 1 since the value passed in could be
|
|
3224
3254
|
// greater than 100 if the user drags the mouse above the top of the sider when adjusting the volume
|
|
@@ -3228,27 +3258,39 @@ function VolumeControls({
|
|
|
3228
3258
|
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3229
3259
|
className: "bp-VolumeControls",
|
|
3230
3260
|
"data-testid": "bp-volume-controls",
|
|
3231
|
-
onBlur:
|
|
3261
|
+
onBlur: event => {
|
|
3262
|
+
handlers.onBlur(event);
|
|
3263
|
+
if (event.currentTarget.contains(event.relatedTarget)) {
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
window.clearTimeout(revealTimerRef.current);
|
|
3267
|
+
revealTimerRef.current = 0;
|
|
3268
|
+
setIsRevealed(false);
|
|
3269
|
+
},
|
|
3232
3270
|
onFocus: handlers.onFocus,
|
|
3233
3271
|
onMouseOut: handlers.onMouseOut,
|
|
3234
3272
|
onMouseOver: handlers.onMouseOver
|
|
3235
|
-
}, /*#__PURE__*/external_react_["default"].createElement(MediaToggle/* default */.A,
|
|
3273
|
+
}, /*#__PURE__*/external_react_["default"].createElement(MediaToggle/* default */.A, {
|
|
3236
3274
|
className: "bp-VolumeControls-toggle",
|
|
3237
3275
|
"data-resin-target": "volumeToggle",
|
|
3238
3276
|
onClick: () => onMuteChange(!isMuted),
|
|
3239
3277
|
title: title
|
|
3240
|
-
},
|
|
3278
|
+
}, /*#__PURE__*/external_react_["default"].createElement(Icon, null)), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
3279
|
+
"aria-hidden": !isOpen,
|
|
3241
3280
|
className: classnames_default()('bp-VolumeControls-flyout', {
|
|
3242
|
-
'bp-is-open':
|
|
3281
|
+
'bp-is-open': isOpen
|
|
3243
3282
|
})
|
|
3244
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeSliderControl,
|
|
3283
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeSliderControl, {
|
|
3284
|
+
"aria-hidden": !isOpen,
|
|
3245
3285
|
className: "bp-VolumeControls-slider",
|
|
3246
3286
|
max: 100,
|
|
3287
|
+
onMouseOver: handlers.onMouseOver,
|
|
3247
3288
|
onUpdate: handleVolume,
|
|
3248
3289
|
step: 1,
|
|
3290
|
+
tabIndex: isOpen ? 0 : -1,
|
|
3249
3291
|
title: "Volume Slider",
|
|
3250
3292
|
value: value
|
|
3251
|
-
}
|
|
3293
|
+
})));
|
|
3252
3294
|
}
|
|
3253
3295
|
|
|
3254
3296
|
/***/ },
|
|
@@ -4488,7 +4530,7 @@ function getPdfjsWorkerSrc() {
|
|
|
4488
4530
|
|
|
4489
4531
|
/***/ },
|
|
4490
4532
|
|
|
4491
|
-
/***/
|
|
4533
|
+
/***/ 7450
|
|
4492
4534
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
4493
4535
|
|
|
4494
4536
|
|
|
@@ -4756,6 +4798,11 @@ function zoomFromSliderValue(value, maxZoom = constants/* WAVEFORM_ZOOM_MIN */.L
|
|
|
4756
4798
|
return clampWaveformZoom(constants/* WAVEFORM_ZOOM_MIN */.LW + t * (max - constants/* WAVEFORM_ZOOM_MIN */.LW), max);
|
|
4757
4799
|
}
|
|
4758
4800
|
|
|
4801
|
+
/** One zoom-in/out button step on the 0–100 slider, mapped back to zoom. */
|
|
4802
|
+
function stepWaveformZoom(zoomLevel, maxZoom, sliderDelta) {
|
|
4803
|
+
return zoomFromSliderValue(Math.round(sliderValueFromZoom(zoomLevel, maxZoom)) + sliderDelta, maxZoom);
|
|
4804
|
+
}
|
|
4805
|
+
|
|
4759
4806
|
/** Max scroll that still shows a full window (no overscroll). Gutters add empty lead/trail. */
|
|
4760
4807
|
function maxScrollLeft(viewport) {
|
|
4761
4808
|
const gutterPx = viewport.gutterPx || 0;
|
|
@@ -5213,15 +5260,62 @@ function getBufferedProgress(bufferedRange, durationSec) {
|
|
|
5213
5260
|
function getPlayedWaveformColor(isTape = false) {
|
|
5214
5261
|
return isTape ? WAVEFORM_COLOR_HOVER_PLAYED : WAVEFORM_COLOR_PLAYED;
|
|
5215
5262
|
}
|
|
5263
|
+
function rangeFills({
|
|
5264
|
+
buffer,
|
|
5265
|
+
hover,
|
|
5266
|
+
rangeEnd,
|
|
5267
|
+
rangeStart
|
|
5268
|
+
}) {
|
|
5269
|
+
const start = clampTo0And1(rangeStart);
|
|
5270
|
+
const end = clampTo0And1(rangeEnd);
|
|
5271
|
+
const hoverInside = hover != null && hover > start && hover < end;
|
|
5272
|
+
const outsideAfter = [{
|
|
5273
|
+
color: WAVEFORM_COLOR_UNPLAYED,
|
|
5274
|
+
end: Math.max(end, buffer),
|
|
5275
|
+
start: end
|
|
5276
|
+
}, {
|
|
5277
|
+
color: WAVEFORM_COLOR_BUFFER,
|
|
5278
|
+
end: 1,
|
|
5279
|
+
start: Math.max(end, buffer)
|
|
5280
|
+
}];
|
|
5281
|
+
const ranges = hoverInside ? [{
|
|
5282
|
+
color: WAVEFORM_COLOR_UNPLAYED,
|
|
5283
|
+
end: start,
|
|
5284
|
+
start: 0
|
|
5285
|
+
}, {
|
|
5286
|
+
color: WAVEFORM_COLOR_HOVER_PLAYED,
|
|
5287
|
+
end: hover,
|
|
5288
|
+
start
|
|
5289
|
+
}, {
|
|
5290
|
+
color: WAVEFORM_COLOR_HOVER_AREA,
|
|
5291
|
+
end,
|
|
5292
|
+
start: hover
|
|
5293
|
+
}, ...outsideAfter] : [{
|
|
5294
|
+
color: WAVEFORM_COLOR_UNPLAYED,
|
|
5295
|
+
end: start,
|
|
5296
|
+
start: 0
|
|
5297
|
+
}, {
|
|
5298
|
+
color: WAVEFORM_COLOR_PLAYED,
|
|
5299
|
+
end,
|
|
5300
|
+
start
|
|
5301
|
+
}, ...outsideAfter];
|
|
5302
|
+
const fill = gradientStopsFromColorRanges(ranges);
|
|
5303
|
+
return {
|
|
5304
|
+
progressColor: fill,
|
|
5305
|
+
waveColor: fill
|
|
5306
|
+
};
|
|
5307
|
+
}
|
|
5216
5308
|
|
|
5217
5309
|
/**
|
|
5218
5310
|
* progressColor paints left of the playhead (clipped by wavesurfer).
|
|
5219
5311
|
* waveColor paints right of the playhead, including buffered vs not-yet-buffered.
|
|
5312
|
+
* An open comment range replaces the played/unplayed split with in-range / out-of-range.
|
|
5220
5313
|
*/
|
|
5221
5314
|
function getWaveformFills({
|
|
5222
5315
|
bufferProgress,
|
|
5223
5316
|
hoverProgress,
|
|
5224
|
-
isTape = false
|
|
5317
|
+
isTape = false,
|
|
5318
|
+
rangeProgress
|
|
5225
5319
|
}) {
|
|
5226
5320
|
const buffer = clampTo0And1(bufferProgress);
|
|
5227
5321
|
const playedColor = getPlayedWaveformColor(isTape);
|
|
@@ -5231,6 +5325,14 @@ function getWaveformFills({
|
|
|
5231
5325
|
waveColor: WAVEFORM_COLOR_UNPLAYED
|
|
5232
5326
|
};
|
|
5233
5327
|
}
|
|
5328
|
+
if (rangeProgress && rangeProgress.end > rangeProgress.start) {
|
|
5329
|
+
return rangeFills({
|
|
5330
|
+
buffer,
|
|
5331
|
+
hover: hoverProgress == null ? null : clampTo0And1(hoverProgress),
|
|
5332
|
+
rangeEnd: rangeProgress.end,
|
|
5333
|
+
rangeStart: rangeProgress.start
|
|
5334
|
+
});
|
|
5335
|
+
}
|
|
5234
5336
|
if (hoverProgress == null) {
|
|
5235
5337
|
return {
|
|
5236
5338
|
progressColor: playedColor,
|
|
@@ -5394,6 +5496,200 @@ function tintWaveformTiles({
|
|
|
5394
5496
|
});
|
|
5395
5497
|
});
|
|
5396
5498
|
}
|
|
5499
|
+
;// ./src/lib/viewers/media/waveform/range.ts
|
|
5500
|
+
|
|
5501
|
+
|
|
5502
|
+
function clampToRange(value, min, max) {
|
|
5503
|
+
if (!Number.isFinite(value)) {
|
|
5504
|
+
return min;
|
|
5505
|
+
}
|
|
5506
|
+
return Math.min(max, Math.max(min, value));
|
|
5507
|
+
}
|
|
5508
|
+
|
|
5509
|
+
/** Integer ms in `[0, durationMs]`. */
|
|
5510
|
+
function clampTimeMs(timeMs, durationMs) {
|
|
5511
|
+
const duration = Math.max(0, durationMs);
|
|
5512
|
+
return Math.round(clampToRange(timeMs, 0, duration));
|
|
5513
|
+
}
|
|
5514
|
+
function durationMsFromSec(durationSec) {
|
|
5515
|
+
if (!Number.isFinite(durationSec) || durationSec <= 0) {
|
|
5516
|
+
return 0;
|
|
5517
|
+
}
|
|
5518
|
+
return Math.round(durationSec * 1000);
|
|
5519
|
+
}
|
|
5520
|
+
function isRangeCollapsed(range) {
|
|
5521
|
+
return !range || range.endMs == null || range.endMs <= range.startMs;
|
|
5522
|
+
}
|
|
5523
|
+
|
|
5524
|
+
/** Clamp both edges onto the file. Collapsed drafts stay a point. */
|
|
5525
|
+
function resolveRange(range, durationMs) {
|
|
5526
|
+
const startMs = clampTimeMs(range.startMs, durationMs);
|
|
5527
|
+
if (range.endMs == null) {
|
|
5528
|
+
return {
|
|
5529
|
+
endMs: startMs,
|
|
5530
|
+
startMs
|
|
5531
|
+
};
|
|
5532
|
+
}
|
|
5533
|
+
const endMs = clampTimeMs(range.endMs, durationMs);
|
|
5534
|
+
if (endMs <= startMs) {
|
|
5535
|
+
return {
|
|
5536
|
+
endMs: startMs,
|
|
5537
|
+
startMs
|
|
5538
|
+
};
|
|
5539
|
+
}
|
|
5540
|
+
return {
|
|
5541
|
+
endMs,
|
|
5542
|
+
startMs
|
|
5543
|
+
};
|
|
5544
|
+
}
|
|
5545
|
+
|
|
5546
|
+
/**
|
|
5547
|
+
* Which handle should receive this pointer. Overlapping hit areas (collapsed or
|
|
5548
|
+
* a span narrower than the 24px target) split at the midpoint so each edge stays reachable.
|
|
5549
|
+
*/
|
|
5550
|
+
function pickRangeHandle({
|
|
5551
|
+
endX,
|
|
5552
|
+
pointerX,
|
|
5553
|
+
startX
|
|
5554
|
+
}) {
|
|
5555
|
+
const mid = (startX + endX) / 2;
|
|
5556
|
+
if (!Number.isFinite(mid)) {
|
|
5557
|
+
return 'end';
|
|
5558
|
+
}
|
|
5559
|
+
return pointerX < mid ? 'start' : 'end';
|
|
5560
|
+
}
|
|
5561
|
+
|
|
5562
|
+
/** Screen x of a handle. Collapsed drafts sit 1px left/right of the playhead, not on it. */
|
|
5563
|
+
function visualRangeHandlePx({
|
|
5564
|
+
handle,
|
|
5565
|
+
range,
|
|
5566
|
+
viewport
|
|
5567
|
+
}) {
|
|
5568
|
+
const timeSec = (handle === 'start' ? range.startMs : range.endMs) / 1000;
|
|
5569
|
+
const x = positionPxFromTime(timeSec, viewport);
|
|
5570
|
+
if (range.startMs !== range.endMs) {
|
|
5571
|
+
return x;
|
|
5572
|
+
}
|
|
5573
|
+
return handle === 'start' ? x - constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG : x + constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG;
|
|
5574
|
+
}
|
|
5575
|
+
|
|
5576
|
+
/** True when the pointer is over the range rectangle or its handle hit targets. */
|
|
5577
|
+
function isPointerOverRange({
|
|
5578
|
+
pointerX,
|
|
5579
|
+
range,
|
|
5580
|
+
viewport
|
|
5581
|
+
}) {
|
|
5582
|
+
const resolved = resolveRange(range, durationMsFromSec(viewport.durationSec));
|
|
5583
|
+
const startX = visualRangeHandlePx({
|
|
5584
|
+
handle: 'start',
|
|
5585
|
+
range: resolved,
|
|
5586
|
+
viewport
|
|
5587
|
+
});
|
|
5588
|
+
const endX = visualRangeHandlePx({
|
|
5589
|
+
handle: 'end',
|
|
5590
|
+
range: resolved,
|
|
5591
|
+
viewport
|
|
5592
|
+
});
|
|
5593
|
+
const pad = constants/* WAVEFORM_RANGE_HIT_AREA_PX */.r0 / 2;
|
|
5594
|
+
return pointerX >= Math.min(startX, endX) - pad && pointerX <= Math.max(startX, endX) + pad;
|
|
5595
|
+
}
|
|
5596
|
+
|
|
5597
|
+
/** Snap to the playhead when the pointer is within `WAVEFORM_RANGE_SNAP_PX`. */
|
|
5598
|
+
function snapTimeMs({
|
|
5599
|
+
pixelsPerSecond,
|
|
5600
|
+
playheadMs,
|
|
5601
|
+
timeMs
|
|
5602
|
+
}) {
|
|
5603
|
+
if (!(pixelsPerSecond > 0) || !Number.isFinite(playheadMs)) {
|
|
5604
|
+
return timeMs;
|
|
5605
|
+
}
|
|
5606
|
+
const deltaPx = Math.abs(timeMs - playheadMs) / 1000 * pixelsPerSecond;
|
|
5607
|
+
if (deltaPx <= constants/* WAVEFORM_RANGE_SNAP_PX */.IQ) {
|
|
5608
|
+
return Math.round(playheadMs);
|
|
5609
|
+
}
|
|
5610
|
+
return timeMs;
|
|
5611
|
+
}
|
|
5612
|
+
|
|
5613
|
+
/**
|
|
5614
|
+
* Move one edge. Crossing the other edge swaps roles so a collapsed pair can
|
|
5615
|
+
* expand in either direction. Enforces `[0, duration]` and the minimum span
|
|
5616
|
+
* once the drag has actually opened a range. An already-open range stays a
|
|
5617
|
+
* span — snapping one edge onto the other clamps to the minimum duration.
|
|
5618
|
+
*/
|
|
5619
|
+
function dragRangeHandle({
|
|
5620
|
+
durationMs,
|
|
5621
|
+
handle,
|
|
5622
|
+
pointerMs,
|
|
5623
|
+
range
|
|
5624
|
+
}) {
|
|
5625
|
+
const duration = Math.max(0, durationMs);
|
|
5626
|
+
const pointer = clampTimeMs(pointerMs, duration);
|
|
5627
|
+
let {
|
|
5628
|
+
startMs,
|
|
5629
|
+
endMs
|
|
5630
|
+
} = range;
|
|
5631
|
+
let nextHandle = handle;
|
|
5632
|
+
if (handle === 'start') {
|
|
5633
|
+
if (pointer > endMs) {
|
|
5634
|
+
startMs = endMs;
|
|
5635
|
+
endMs = pointer;
|
|
5636
|
+
nextHandle = 'end';
|
|
5637
|
+
} else {
|
|
5638
|
+
startMs = pointer;
|
|
5639
|
+
}
|
|
5640
|
+
} else if (pointer < startMs) {
|
|
5641
|
+
endMs = startMs;
|
|
5642
|
+
startMs = pointer;
|
|
5643
|
+
nextHandle = 'start';
|
|
5644
|
+
} else {
|
|
5645
|
+
endMs = pointer;
|
|
5646
|
+
}
|
|
5647
|
+
const wasOpen = range.startMs !== range.endMs;
|
|
5648
|
+
const opened = wasOpen || startMs !== endMs;
|
|
5649
|
+
if (opened && endMs - startMs < constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX) {
|
|
5650
|
+
if (nextHandle === 'end') {
|
|
5651
|
+
endMs = clampTimeMs(startMs + constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX, duration);
|
|
5652
|
+
if (endMs - startMs < constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX) {
|
|
5653
|
+
startMs = clampTimeMs(endMs - constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX, duration);
|
|
5654
|
+
}
|
|
5655
|
+
} else {
|
|
5656
|
+
startMs = clampTimeMs(endMs - constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX, duration);
|
|
5657
|
+
if (endMs - startMs < constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX) {
|
|
5658
|
+
endMs = clampTimeMs(startMs + constants/* WAVEFORM_RANGE_MIN_DURATION_MS */.bX, duration);
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
}
|
|
5662
|
+
return {
|
|
5663
|
+
handle: nextHandle,
|
|
5664
|
+
range: {
|
|
5665
|
+
endMs,
|
|
5666
|
+
startMs
|
|
5667
|
+
}
|
|
5668
|
+
};
|
|
5669
|
+
}
|
|
5670
|
+
function pointerTimeMs(pointerX, viewport) {
|
|
5671
|
+
return Math.round(timeFromPositionPx(pointerX, viewport) * 1000);
|
|
5672
|
+
}
|
|
5673
|
+
|
|
5674
|
+
/** Sidebar payload after mouseup. Null when the draft is still a single timestamp. */
|
|
5675
|
+
function commitRangeChange(range) {
|
|
5676
|
+
if (range.endMs <= range.startMs) {
|
|
5677
|
+
return null;
|
|
5678
|
+
}
|
|
5679
|
+
return {
|
|
5680
|
+
endMs: range.endMs,
|
|
5681
|
+
startMs: range.startMs
|
|
5682
|
+
};
|
|
5683
|
+
}
|
|
5684
|
+
function rangeProgress(range, durationMs) {
|
|
5685
|
+
if (!(durationMs > 0) || range.endMs <= range.startMs) {
|
|
5686
|
+
return null;
|
|
5687
|
+
}
|
|
5688
|
+
return {
|
|
5689
|
+
end: range.endMs / durationMs,
|
|
5690
|
+
start: range.startMs / durationMs
|
|
5691
|
+
};
|
|
5692
|
+
}
|
|
5397
5693
|
;// ./src/lib/viewers/media/waveform/usePlayheadCamera.ts
|
|
5398
5694
|
|
|
5399
5695
|
|
|
@@ -5709,6 +6005,307 @@ function usePlayheadCamera({
|
|
|
5709
6005
|
seekTo
|
|
5710
6006
|
};
|
|
5711
6007
|
}
|
|
6008
|
+
;// ./src/lib/viewers/media/waveform/WaveformRangeSelection.scss
|
|
6009
|
+
// extracted by mini-css-extract-plugin
|
|
6010
|
+
|
|
6011
|
+
;// ./src/lib/viewers/media/waveform/WaveformRangeSelection.tsx
|
|
6012
|
+
|
|
6013
|
+
|
|
6014
|
+
|
|
6015
|
+
|
|
6016
|
+
|
|
6017
|
+
|
|
6018
|
+
function offsetLeftCss(base, offsetPx) {
|
|
6019
|
+
if (!offsetPx) {
|
|
6020
|
+
return base;
|
|
6021
|
+
}
|
|
6022
|
+
const op = offsetPx < 0 ? '-' : '+';
|
|
6023
|
+
return `calc(${base} ${op} ${Math.abs(offsetPx)}px)`;
|
|
6024
|
+
}
|
|
6025
|
+
function applyHandleLeft(el, timeSec, durationSec, viewport, collapsedOffsetPx = 0) {
|
|
6026
|
+
if (!el) {
|
|
6027
|
+
return;
|
|
6028
|
+
}
|
|
6029
|
+
el.style.left = offsetLeftCss(timeLeftPercent(timeSec, durationSec, viewport), collapsedOffsetPx);
|
|
6030
|
+
}
|
|
6031
|
+
function applyRegion(el, startSec, endSec, durationSec, viewport, collapsed) {
|
|
6032
|
+
if (!el) {
|
|
6033
|
+
return;
|
|
6034
|
+
}
|
|
6035
|
+
const start = timeLeftPercent(startSec, durationSec, viewport);
|
|
6036
|
+
const halfLine = constants/* WAVEFORM_RANGE_HANDLE_LINE_PX */.h1 / 2;
|
|
6037
|
+
if (collapsed) {
|
|
6038
|
+
const extentPx = constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG + halfLine;
|
|
6039
|
+
el.style.left = offsetLeftCss(start, -extentPx);
|
|
6040
|
+
el.style.width = `${extentPx * 2}px`;
|
|
6041
|
+
return;
|
|
6042
|
+
}
|
|
6043
|
+
const end = timeLeftPercent(endSec, durationSec, viewport);
|
|
6044
|
+
el.style.left = offsetLeftCss(start, -halfLine);
|
|
6045
|
+
el.style.width = `calc(${end} - ${start} + ${constants/* WAVEFORM_RANGE_HANDLE_LINE_PX */.h1}px)`;
|
|
6046
|
+
}
|
|
6047
|
+
const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(function WaveformRangeSelection({
|
|
6048
|
+
currentTimeSec = 0,
|
|
6049
|
+
durationSec,
|
|
6050
|
+
getPlayheadSec,
|
|
6051
|
+
interactive = true,
|
|
6052
|
+
isHighlighted = false,
|
|
6053
|
+
keepHighlight = true,
|
|
6054
|
+
onDragChange,
|
|
6055
|
+
onPreviewChange,
|
|
6056
|
+
onRangeChange,
|
|
6057
|
+
range,
|
|
6058
|
+
viewport
|
|
6059
|
+
}, ref) {
|
|
6060
|
+
const rootRef = (0,external_react_.useRef)(null);
|
|
6061
|
+
const regionRef = (0,external_react_.useRef)(null);
|
|
6062
|
+
const startHandleRef = (0,external_react_.useRef)(null);
|
|
6063
|
+
const endHandleRef = (0,external_react_.useRef)(null);
|
|
6064
|
+
const tooltipRef = (0,external_react_.useRef)(null);
|
|
6065
|
+
const dragRef = (0,external_react_.useRef)(null);
|
|
6066
|
+
const rangeRef = (0,external_react_.useRef)(range);
|
|
6067
|
+
const displayedRef = (0,external_react_.useRef)(resolveRange(range, durationMsFromSec(durationSec)));
|
|
6068
|
+
const viewportRef = (0,external_react_.useRef)(viewport);
|
|
6069
|
+
const durationSecRef = (0,external_react_.useRef)(durationSec);
|
|
6070
|
+
const onDragChangeRef = (0,external_react_.useRef)(onDragChange);
|
|
6071
|
+
const onPreviewChangeRef = (0,external_react_.useRef)(onPreviewChange);
|
|
6072
|
+
const onRangeChangeRef = (0,external_react_.useRef)(onRangeChange);
|
|
6073
|
+
const getPlayheadSecRef = (0,external_react_.useRef)(getPlayheadSec);
|
|
6074
|
+
const [dragRange, setDragRange] = (0,external_react_.useState)(null);
|
|
6075
|
+
const [activeHandle, setActiveHandle] = (0,external_react_.useState)(null);
|
|
6076
|
+
const activeHandleRef = (0,external_react_.useRef)(null);
|
|
6077
|
+
rangeRef.current = range;
|
|
6078
|
+
durationSecRef.current = durationSec;
|
|
6079
|
+
onDragChangeRef.current = onDragChange;
|
|
6080
|
+
onPreviewChangeRef.current = onPreviewChange;
|
|
6081
|
+
onRangeChangeRef.current = onRangeChange;
|
|
6082
|
+
getPlayheadSecRef.current = getPlayheadSec;
|
|
6083
|
+
activeHandleRef.current = activeHandle;
|
|
6084
|
+
const durationMs = durationMsFromSec(durationSec);
|
|
6085
|
+
const displayed = dragRange ?? resolveRange(range, durationMs);
|
|
6086
|
+
displayedRef.current = displayed;
|
|
6087
|
+
const syncPositions = (0,external_react_.useCallback)((next, nextViewport, nextDurationSec) => {
|
|
6088
|
+
displayedRef.current = next;
|
|
6089
|
+
const collapsed = next.startMs === next.endMs;
|
|
6090
|
+
applyRegion(regionRef.current, next.startMs / 1000, next.endMs / 1000, nextDurationSec, nextViewport, collapsed);
|
|
6091
|
+
applyHandleLeft(startHandleRef.current, next.startMs / 1000, nextDurationSec, nextViewport, collapsed ? -constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG : 0);
|
|
6092
|
+
applyHandleLeft(endHandleRef.current, next.endMs / 1000, nextDurationSec, nextViewport, collapsed ? constants/* WAVEFORM_RANGE_COLLAPSED_OFFSET_PX */.BG : 0);
|
|
6093
|
+
const tooltip = tooltipRef.current;
|
|
6094
|
+
if (tooltip) {
|
|
6095
|
+
const tooltipHandle = activeHandleRef.current ?? 'end';
|
|
6096
|
+
const tooltipMs = tooltipHandle === 'start' ? next.startMs : next.endMs;
|
|
6097
|
+
tooltip.style.left = timeLeftPercent(tooltipMs / 1000, nextDurationSec, nextViewport);
|
|
6098
|
+
}
|
|
6099
|
+
}, []);
|
|
6100
|
+
(0,external_react_.useImperativeHandle)(ref, () => ({
|
|
6101
|
+
applyViewport: nextViewport => {
|
|
6102
|
+
viewportRef.current = nextViewport;
|
|
6103
|
+
syncPositions(displayedRef.current, nextViewport, durationSecRef.current);
|
|
6104
|
+
}
|
|
6105
|
+
}), [syncPositions]);
|
|
6106
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
6107
|
+
syncPositions(displayedRef.current, viewportRef.current, durationSec);
|
|
6108
|
+
}, [activeHandle, displayed.endMs, displayed.startMs, durationSec, syncPositions]);
|
|
6109
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
6110
|
+
const next = createWaveformViewport({
|
|
6111
|
+
durationSec: viewport.durationSec,
|
|
6112
|
+
heightPx: viewport.heightPx,
|
|
6113
|
+
maxZoom: viewport.maxZoom,
|
|
6114
|
+
scrollLeftPx: viewportRef.current.scrollLeftPx,
|
|
6115
|
+
widthPx: viewport.widthPx,
|
|
6116
|
+
zoomLevel: viewport.zoomLevel
|
|
6117
|
+
});
|
|
6118
|
+
viewportRef.current = next;
|
|
6119
|
+
syncPositions(displayedRef.current, next, durationSecRef.current);
|
|
6120
|
+
}, [syncPositions, viewport.durationSec, viewport.heightPx, viewport.maxZoom, viewport.widthPx, viewport.zoomLevel]);
|
|
6121
|
+
const endDrag = (0,external_react_.useCallback)(event => {
|
|
6122
|
+
const drag = dragRef.current;
|
|
6123
|
+
if (!drag || event.pointerId && drag.pointerId !== event.pointerId) {
|
|
6124
|
+
return;
|
|
6125
|
+
}
|
|
6126
|
+
[startHandleRef.current, endHandleRef.current].forEach(handleEl => {
|
|
6127
|
+
if (handleEl && handleEl.hasPointerCapture(event.pointerId)) {
|
|
6128
|
+
handleEl.releasePointerCapture(event.pointerId);
|
|
6129
|
+
}
|
|
6130
|
+
});
|
|
6131
|
+
dragRef.current = null;
|
|
6132
|
+
setActiveHandle(null);
|
|
6133
|
+
setDragRange(null);
|
|
6134
|
+
onDragChangeRef.current?.(false);
|
|
6135
|
+
const didChange = drag.range.startMs !== drag.originRange.startMs || drag.range.endMs !== drag.originRange.endMs;
|
|
6136
|
+
if (!didChange) {
|
|
6137
|
+
return;
|
|
6138
|
+
}
|
|
6139
|
+
const committed = commitRangeChange(drag.range);
|
|
6140
|
+
if (committed) {
|
|
6141
|
+
onRangeChangeRef.current?.(committed);
|
|
6142
|
+
}
|
|
6143
|
+
}, []);
|
|
6144
|
+
const moveDrag = (0,external_react_.useCallback)(event => {
|
|
6145
|
+
const drag = dragRef.current;
|
|
6146
|
+
if (!drag || event.pointerId && drag.pointerId !== event.pointerId) {
|
|
6147
|
+
return;
|
|
6148
|
+
}
|
|
6149
|
+
const root = rootRef.current;
|
|
6150
|
+
if (!root) {
|
|
6151
|
+
return;
|
|
6152
|
+
}
|
|
6153
|
+
const rect = root.getBoundingClientRect();
|
|
6154
|
+
const pointerX = event.clientX - rect.left;
|
|
6155
|
+
const vp = viewportRef.current;
|
|
6156
|
+
const duration = durationMsFromSec(durationSecRef.current);
|
|
6157
|
+
const playheadSec = getPlayheadSecRef.current?.() ?? currentTimeSec;
|
|
6158
|
+
const pointerMs = snapTimeMs({
|
|
6159
|
+
pixelsPerSecond: vp.pixelsPerSecond,
|
|
6160
|
+
playheadMs: playheadSec * 1000,
|
|
6161
|
+
timeMs: pointerTimeMs(pointerX, vp)
|
|
6162
|
+
});
|
|
6163
|
+
if (drag.originMs === drag.range.startMs && drag.originMs === drag.range.endMs && pointerMs === drag.originMs) {
|
|
6164
|
+
return;
|
|
6165
|
+
}
|
|
6166
|
+
const next = dragRangeHandle({
|
|
6167
|
+
durationMs: duration,
|
|
6168
|
+
handle: drag.handle,
|
|
6169
|
+
pointerMs,
|
|
6170
|
+
range: {
|
|
6171
|
+
endMs: drag.range.endMs,
|
|
6172
|
+
startMs: drag.range.startMs
|
|
6173
|
+
}
|
|
6174
|
+
});
|
|
6175
|
+
drag.handle = next.handle;
|
|
6176
|
+
drag.range = next.range;
|
|
6177
|
+
setActiveHandle(next.handle);
|
|
6178
|
+
setDragRange(next.range);
|
|
6179
|
+
syncPositions(next.range, vp, durationSecRef.current);
|
|
6180
|
+
onPreviewChangeRef.current?.({
|
|
6181
|
+
endMs: next.range.endMs,
|
|
6182
|
+
startMs: next.range.startMs
|
|
6183
|
+
});
|
|
6184
|
+
}, [currentTimeSec, syncPositions]);
|
|
6185
|
+
const startDrag = (0,external_react_.useCallback)((handle, event) => {
|
|
6186
|
+
if (!interactive || event.button > 1 || event.ctrlKey || event.metaKey) {
|
|
6187
|
+
return;
|
|
6188
|
+
}
|
|
6189
|
+
event.preventDefault();
|
|
6190
|
+
event.stopPropagation();
|
|
6191
|
+
const resolved = resolveRange(rangeRef.current, durationMsFromSec(durationSecRef.current));
|
|
6192
|
+
dragRef.current = {
|
|
6193
|
+
handle,
|
|
6194
|
+
originMs: handle === 'start' ? resolved.startMs : resolved.endMs,
|
|
6195
|
+
originRange: {
|
|
6196
|
+
endMs: resolved.endMs,
|
|
6197
|
+
startMs: resolved.startMs
|
|
6198
|
+
},
|
|
6199
|
+
pointerId: event.pointerId,
|
|
6200
|
+
range: resolved
|
|
6201
|
+
};
|
|
6202
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
6203
|
+
setActiveHandle(handle);
|
|
6204
|
+
setDragRange(resolved);
|
|
6205
|
+
onDragChangeRef.current?.(true);
|
|
6206
|
+
onPreviewChangeRef.current?.({
|
|
6207
|
+
endMs: isRangeCollapsed(rangeRef.current) ? null : resolved.endMs,
|
|
6208
|
+
startMs: resolved.startMs
|
|
6209
|
+
});
|
|
6210
|
+
}, [interactive]);
|
|
6211
|
+
const onHandlePointerDown = (0,external_react_.useCallback)(event => {
|
|
6212
|
+
const root = rootRef.current;
|
|
6213
|
+
if (!root) {
|
|
6214
|
+
return;
|
|
6215
|
+
}
|
|
6216
|
+
const rect = root.getBoundingClientRect();
|
|
6217
|
+
const pointerX = event.clientX - rect.left;
|
|
6218
|
+
const vp = viewportRef.current;
|
|
6219
|
+
const resolved = resolveRange(rangeRef.current, durationMsFromSec(durationSecRef.current));
|
|
6220
|
+
const handle = pickRangeHandle({
|
|
6221
|
+
endX: visualRangeHandlePx({
|
|
6222
|
+
handle: 'end',
|
|
6223
|
+
range: resolved,
|
|
6224
|
+
viewport: vp
|
|
6225
|
+
}),
|
|
6226
|
+
pointerX,
|
|
6227
|
+
startX: visualRangeHandlePx({
|
|
6228
|
+
handle: 'start',
|
|
6229
|
+
range: resolved,
|
|
6230
|
+
viewport: vp
|
|
6231
|
+
})
|
|
6232
|
+
});
|
|
6233
|
+
startDrag(handle, event);
|
|
6234
|
+
}, [startDrag]);
|
|
6235
|
+
(0,external_react_.useEffect)(() => {
|
|
6236
|
+
const onMove = event => {
|
|
6237
|
+
if (!dragRef.current) {
|
|
6238
|
+
return;
|
|
6239
|
+
}
|
|
6240
|
+
event.preventDefault();
|
|
6241
|
+
moveDrag(event);
|
|
6242
|
+
};
|
|
6243
|
+
const onUp = event => {
|
|
6244
|
+
if (!dragRef.current) {
|
|
6245
|
+
return;
|
|
6246
|
+
}
|
|
6247
|
+
endDrag(event);
|
|
6248
|
+
};
|
|
6249
|
+
window.addEventListener('pointermove', onMove);
|
|
6250
|
+
window.addEventListener('pointerup', onUp);
|
|
6251
|
+
window.addEventListener('pointercancel', onUp);
|
|
6252
|
+
return () => {
|
|
6253
|
+
window.removeEventListener('pointermove', onMove);
|
|
6254
|
+
window.removeEventListener('pointerup', onUp);
|
|
6255
|
+
window.removeEventListener('pointercancel', onUp);
|
|
6256
|
+
};
|
|
6257
|
+
}, [endDrag, moveDrag]);
|
|
6258
|
+
(0,external_react_.useEffect)(() => {
|
|
6259
|
+
return () => {
|
|
6260
|
+
if (!dragRef.current) {
|
|
6261
|
+
return;
|
|
6262
|
+
}
|
|
6263
|
+
dragRef.current = null;
|
|
6264
|
+
onDragChangeRef.current?.(false);
|
|
6265
|
+
};
|
|
6266
|
+
}, []);
|
|
6267
|
+
if (!(durationSec > 0) || !(durationMs >= 0)) {
|
|
6268
|
+
return null;
|
|
6269
|
+
}
|
|
6270
|
+
const tooltipHandle = activeHandle ?? 'end';
|
|
6271
|
+
const tooltipMs = tooltipHandle === 'start' ? displayed.startMs : displayed.endMs;
|
|
6272
|
+
const collapsed = displayed.startMs === displayed.endMs;
|
|
6273
|
+
const highlight = isHighlighted || collapsed;
|
|
6274
|
+
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6275
|
+
ref: rootRef,
|
|
6276
|
+
className: `bp-WaveformRange${keepHighlight ? ' bp-WaveformRange--persist' : ''}${highlight ? ' bp-WaveformRange--highlight' : ''}`,
|
|
6277
|
+
"data-collapsed": collapsed ? 'true' : 'false',
|
|
6278
|
+
"data-highlighted": highlight ? 'true' : 'false',
|
|
6279
|
+
"data-testid": "bp-waveform-range"
|
|
6280
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6281
|
+
ref: regionRef,
|
|
6282
|
+
className: "bp-WaveformRange-region",
|
|
6283
|
+
"data-testid": "bp-waveform-range-region"
|
|
6284
|
+
}), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6285
|
+
ref: startHandleRef,
|
|
6286
|
+
className: `bp-WaveformRange-handle bp-WaveformRange-handle--start${activeHandle === 'start' ? ' bp-WaveformRange-handle--dragging' : ''}`,
|
|
6287
|
+
"data-testid": "bp-waveform-range-handle-start",
|
|
6288
|
+
onMouseMove: event => event.stopPropagation(),
|
|
6289
|
+
onPointerDown: onHandlePointerDown
|
|
6290
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6291
|
+
className: "bp-WaveformRange-handleGrip"
|
|
6292
|
+
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6293
|
+
ref: endHandleRef,
|
|
6294
|
+
className: `bp-WaveformRange-handle bp-WaveformRange-handle--end${activeHandle === 'end' ? ' bp-WaveformRange-handle--dragging' : ''}`,
|
|
6295
|
+
"data-testid": "bp-waveform-range-handle-end",
|
|
6296
|
+
onMouseMove: event => event.stopPropagation(),
|
|
6297
|
+
onPointerDown: onHandlePointerDown
|
|
6298
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6299
|
+
className: "bp-WaveformRange-handleGrip"
|
|
6300
|
+
})), activeHandle && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6301
|
+
ref: tooltipRef,
|
|
6302
|
+
className: "bp-WaveformRange-tooltip",
|
|
6303
|
+
"data-testid": "bp-waveform-range-tooltip"
|
|
6304
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6305
|
+
className: "bp-WaveformRange-tooltipTime"
|
|
6306
|
+
}, formatTime(tooltipMs / 1000))));
|
|
6307
|
+
});
|
|
6308
|
+
/* harmony default export */ const waveform_WaveformRangeSelection = (/*#__PURE__*/external_react_["default"].memo(WaveformRangeSelection));
|
|
5712
6309
|
;// ./src/lib/viewers/media/waveform/WaveformView.scss
|
|
5713
6310
|
// extracted by mini-css-extract-plugin
|
|
5714
6311
|
|
|
@@ -5730,6 +6327,8 @@ function WaveformView_toPrimitive(t, r) { if ("object" != typeof t || !t) return
|
|
|
5730
6327
|
|
|
5731
6328
|
|
|
5732
6329
|
|
|
6330
|
+
|
|
6331
|
+
|
|
5733
6332
|
/** Pointer X in the view and the media time under it; zoom keeps this point fixed. */
|
|
5734
6333
|
|
|
5735
6334
|
/** CSS width × devicePixelRatio, for canvas gradient fills. */
|
|
@@ -5838,10 +6437,13 @@ function WaveformView({
|
|
|
5838
6437
|
isPlaying = false,
|
|
5839
6438
|
mediaEl,
|
|
5840
6439
|
onPlayPause,
|
|
6440
|
+
onRangeChange,
|
|
6441
|
+
onRangeDragChange,
|
|
5841
6442
|
onSeek,
|
|
5842
6443
|
onViewportChange,
|
|
5843
6444
|
onZoomChange,
|
|
5844
6445
|
peaks,
|
|
6446
|
+
range = null,
|
|
5845
6447
|
zoomLevel: zoomLevelProp
|
|
5846
6448
|
}) {
|
|
5847
6449
|
// DOM / WaveSurfer
|
|
@@ -5850,6 +6452,7 @@ function WaveformView({
|
|
|
5850
6452
|
const playheadRef = (0,external_react_.useRef)(null); // playhead element the camera positions
|
|
5851
6453
|
const trackRef = (0,external_react_.useRef)(null); // hover / tap target around the canvas
|
|
5852
6454
|
const wavesurferRef = (0,external_react_.useRef)(null); // WaveSurfer instance
|
|
6455
|
+
const rangeLayerRef = (0,external_react_.useRef)(null);
|
|
5853
6456
|
|
|
5854
6457
|
// Latest props for WaveSurfer + media listeners that must not re-subscribe each render.
|
|
5855
6458
|
const cameraModeRef = (0,external_react_.useRef)(cameraMode); // latest tape/desktop; WaveSurfer create() deps stay empty
|
|
@@ -5877,6 +6480,7 @@ function WaveformView({
|
|
|
5877
6480
|
const pointerZoomClearTimerRef = (0,external_react_.useRef)(0); // clears pointerZoomRef after WAVEFORM_ZOOM_DISMISS_MS
|
|
5878
6481
|
const pointerZoomRef = (0,external_react_.useRef)(false); // pinch/wheel in progress; skip play/pause and tape recenter
|
|
5879
6482
|
const queuedTapeSeekTimeSecRef = (0,external_react_.useRef)(null); // seek time waiting for the next animation frame
|
|
6483
|
+
const rangeProgressRef = (0,external_react_.useRef)(null); // latest range progress; zoomed tile tint reads this
|
|
5880
6484
|
const suppressNextTapPlayPauseRef = (0,external_react_.useRef)(false); // swallow play/pause after a swipe or pinch
|
|
5881
6485
|
const suppressNextTapPlayPauseTimerRef = (0,external_react_.useRef)(0); // clears suppressNextTapPlayPauseRef
|
|
5882
6486
|
const suppressViewportSyncRef = (0,external_react_.useRef)(false); // ignore WaveSurfer zoom/scroll while we setOptions
|
|
@@ -5900,6 +6504,12 @@ function WaveformView({
|
|
|
5900
6504
|
const [overlayPortalHost, setOverlayPortalHost] = (0,external_react_.useState)(null);
|
|
5901
6505
|
const [canvasWidthPx, setCanvasWidthPx] = (0,external_react_.useState)(0);
|
|
5902
6506
|
const [scrollLeft, setScrollLeft] = (0,external_react_.useState)(0);
|
|
6507
|
+
const [previewRange, setPreviewRange] = (0,external_react_.useState)(null);
|
|
6508
|
+
const [isRangeDragging, setIsRangeDragging] = (0,external_react_.useState)(false);
|
|
6509
|
+
const isRangeDraggingRef = (0,external_react_.useRef)(false);
|
|
6510
|
+
const skipNextSeekRef = (0,external_react_.useRef)(false);
|
|
6511
|
+
const lastSetTimeSecRef = (0,external_react_.useRef)(null);
|
|
6512
|
+
const [isRangeHovered, setIsRangeHovered] = (0,external_react_.useState)(false);
|
|
5903
6513
|
const isControlled = typeof zoomLevelProp === 'number';
|
|
5904
6514
|
const maxZoom = getWaveformZoomMax({
|
|
5905
6515
|
durationSec,
|
|
@@ -5916,7 +6526,23 @@ function WaveformView({
|
|
|
5916
6526
|
const isScrollableWindow = isZoomed || isTape;
|
|
5917
6527
|
const bufferProgress = getBufferedProgress(bufferedRange, durationSec);
|
|
5918
6528
|
bufferProgressRef.current = bufferProgress;
|
|
5919
|
-
hoverProgressRef.current = hoverProgress;
|
|
6529
|
+
hoverProgressRef.current = isRangeDragging ? null : hoverProgress;
|
|
6530
|
+
const activeRange = isRangeDragging ? previewRange ?? range : range;
|
|
6531
|
+
const activeRangeRef = (0,external_react_.useRef)(activeRange);
|
|
6532
|
+
activeRangeRef.current = activeRange;
|
|
6533
|
+
const durationMs = durationMsFromSec(durationSec);
|
|
6534
|
+
const rangeStartMs = activeRange?.startMs;
|
|
6535
|
+
const rangeEndMs = activeRange?.endMs;
|
|
6536
|
+
const activeRangeProgress = (0,external_react_.useMemo)(() => {
|
|
6537
|
+
if (rangeStartMs == null || !Number.isFinite(rangeStartMs)) {
|
|
6538
|
+
return null;
|
|
6539
|
+
}
|
|
6540
|
+
return rangeProgress(resolveRange({
|
|
6541
|
+
endMs: rangeEndMs ?? null,
|
|
6542
|
+
startMs: rangeStartMs
|
|
6543
|
+
}, durationMs), durationMs);
|
|
6544
|
+
}, [durationMs, rangeEndMs, rangeStartMs]);
|
|
6545
|
+
rangeProgressRef.current = activeRangeProgress;
|
|
5920
6546
|
const viewport = (0,external_react_.useMemo)(() => createWaveformViewport({
|
|
5921
6547
|
durationSec,
|
|
5922
6548
|
gutterPx: isTape ? getTapeGutterPx(canvasWidthPx) : 0,
|
|
@@ -5928,6 +6554,7 @@ function WaveformView({
|
|
|
5928
6554
|
}), [canvasWidthPx, durationSec, height, isTape, maxZoom, scrollLeft, zoomLevel]);
|
|
5929
6555
|
const viewportRef = (0,external_react_.useRef)(viewport); // live scroll window; prefer this over render-state while the camera is moving
|
|
5930
6556
|
const onViewportCommit = (0,external_react_.useCallback)((scrollLeftPx, nextViewport, commitReactState = true) => {
|
|
6557
|
+
rangeLayerRef.current?.applyViewport(nextViewport);
|
|
5931
6558
|
onViewportChangeRef.current?.(nextViewport);
|
|
5932
6559
|
if (commitReactState) {
|
|
5933
6560
|
setScrollLeft(scrollLeftPx);
|
|
@@ -6043,6 +6670,7 @@ function WaveformView({
|
|
|
6043
6670
|
}
|
|
6044
6671
|
const scrollLeftPx = WaveformView_getScrollLeft(wavesurfer);
|
|
6045
6672
|
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
6673
|
+
rangeLayerRef.current?.applyViewport(viewportRef.current);
|
|
6046
6674
|
onViewportChangeRef.current?.(viewportRef.current);
|
|
6047
6675
|
setScrollLeft(scrollLeftPx);
|
|
6048
6676
|
}, []);
|
|
@@ -6056,8 +6684,10 @@ function WaveformView({
|
|
|
6056
6684
|
} else if (!isFollowPinned()) {
|
|
6057
6685
|
playhead.style.left = timeLeftPercent(timeSec, durationSecRef.current, viewportRef.current);
|
|
6058
6686
|
}
|
|
6687
|
+
rangeLayerRef.current?.applyViewport(viewportRef.current);
|
|
6059
6688
|
const wavesurfer = wavesurferRef.current;
|
|
6060
|
-
if (wavesurfer && wavesurfer.setTime) {
|
|
6689
|
+
if (wavesurfer && wavesurfer.setTime && lastSetTimeSecRef.current !== timeSec) {
|
|
6690
|
+
lastSetTimeSecRef.current = timeSec;
|
|
6061
6691
|
wavesurfer.setTime(timeSec);
|
|
6062
6692
|
}
|
|
6063
6693
|
}, [isFollowPinned, isTape]);
|
|
@@ -6111,6 +6741,7 @@ function WaveformView({
|
|
|
6111
6741
|
applyScrollLeft(getCenteredScrollLeft(currentTimeRef.current, windowViewport), true);
|
|
6112
6742
|
}
|
|
6113
6743
|
}
|
|
6744
|
+
lastSetTimeSecRef.current = currentTimeRef.current;
|
|
6114
6745
|
wavesurfer.setTime(currentTimeRef.current);
|
|
6115
6746
|
} finally {
|
|
6116
6747
|
suppressViewportSyncRef.current = false;
|
|
@@ -6149,7 +6780,11 @@ function WaveformView({
|
|
|
6149
6780
|
waveColor: WAVEFORM_COLOR_UNPLAYED
|
|
6150
6781
|
});
|
|
6151
6782
|
const unsubscribeClick = wavesurfer.on('click', relativeX => {
|
|
6152
|
-
if (
|
|
6783
|
+
if (skipNextSeekRef.current) {
|
|
6784
|
+
skipNextSeekRef.current = false;
|
|
6785
|
+
return;
|
|
6786
|
+
}
|
|
6787
|
+
if (!interactiveRef.current || isRangeDraggingRef.current) {
|
|
6153
6788
|
return;
|
|
6154
6789
|
}
|
|
6155
6790
|
if (cameraModeRef.current === 'tape') {
|
|
@@ -6169,6 +6804,7 @@ function WaveformView({
|
|
|
6169
6804
|
}
|
|
6170
6805
|
syncViewport();
|
|
6171
6806
|
});
|
|
6807
|
+
rangeLayerRef.current?.applyViewport(viewportRef.current);
|
|
6172
6808
|
});
|
|
6173
6809
|
const unsubscribeZoom = wavesurfer.on('zoom', () => {
|
|
6174
6810
|
if (suppressViewportSyncRef.current) {
|
|
@@ -6183,11 +6819,13 @@ function WaveformView({
|
|
|
6183
6819
|
tintZoomedWaveform(wavesurfer, getWaveformFills({
|
|
6184
6820
|
bufferProgress: bufferProgressRef.current,
|
|
6185
6821
|
hoverProgress: cameraModeRef.current === 'tape' ? null : hoverProgressRef.current,
|
|
6186
|
-
isTape: cameraModeRef.current === 'tape'
|
|
6822
|
+
isTape: cameraModeRef.current === 'tape',
|
|
6823
|
+
rangeProgress: rangeProgressRef.current
|
|
6187
6824
|
}), true);
|
|
6188
6825
|
});
|
|
6189
6826
|
wavesurferRef.current = wavesurfer;
|
|
6190
6827
|
displayedPeaksRef.current = peaksRef.current;
|
|
6828
|
+
lastSetTimeSecRef.current = null;
|
|
6191
6829
|
disableScrollOverscroll(container);
|
|
6192
6830
|
syncViewport();
|
|
6193
6831
|
applyZoomWindowRef.current?.();
|
|
@@ -6205,6 +6843,7 @@ function WaveformView({
|
|
|
6205
6843
|
wavesurfer.destroy();
|
|
6206
6844
|
wavesurferRef.current = null;
|
|
6207
6845
|
displayedPeaksRef.current = null;
|
|
6846
|
+
lastSetTimeSecRef.current = null;
|
|
6208
6847
|
};
|
|
6209
6848
|
}, [cancelJump, handleCameraScroll, handleTapeSwipe, height, isUserPanning, releaseUserPanHold, syncViewport]);
|
|
6210
6849
|
(0,external_react_.useLayoutEffect)(() => {
|
|
@@ -6359,7 +6998,8 @@ function WaveformView({
|
|
|
6359
6998
|
const fills = getWaveformFills({
|
|
6360
6999
|
bufferProgress,
|
|
6361
7000
|
hoverProgress: isTape ? null : hoverProgress,
|
|
6362
|
-
isTape
|
|
7001
|
+
isTape,
|
|
7002
|
+
rangeProgress: activeRangeProgress
|
|
6363
7003
|
});
|
|
6364
7004
|
if (isScrollableWindow) {
|
|
6365
7005
|
tintZoomedWaveform(wavesurfer, fills);
|
|
@@ -6369,8 +7009,9 @@ function WaveformView({
|
|
|
6369
7009
|
progressColor: toCanvasFill(fills.progressColor, devicePixelWidth(canvasWidthPx)),
|
|
6370
7010
|
waveColor: toCanvasFill(fills.waveColor, devicePixelWidth(canvasWidthPx))
|
|
6371
7011
|
});
|
|
7012
|
+
lastSetTimeSecRef.current = currentTimeRef.current;
|
|
6372
7013
|
wavesurfer.setTime(currentTimeRef.current);
|
|
6373
|
-
}, [bufferProgress, canvasWidthPx, hoverProgress, isScrollableWindow, isTape]);
|
|
7014
|
+
}, [activeRangeProgress, bufferProgress, canvasWidthPx, hoverProgress, isRangeDragging, isScrollableWindow, isTape, isZoomed]);
|
|
6374
7015
|
(0,external_react_.useEffect)(() => {
|
|
6375
7016
|
const track = trackRef.current;
|
|
6376
7017
|
if (!track) {
|
|
@@ -6451,11 +7092,11 @@ function WaveformView({
|
|
|
6451
7092
|
};
|
|
6452
7093
|
}, [durationSec, markPointerZoom, setZoomLevel]);
|
|
6453
7094
|
const onHoverMove = (0,external_react_.useCallback)(event => {
|
|
6454
|
-
if (
|
|
7095
|
+
if (isTape || isTouchHoverInput(event)) {
|
|
6455
7096
|
return;
|
|
6456
7097
|
}
|
|
6457
7098
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
6458
|
-
if (!(rect.width > 0)
|
|
7099
|
+
if (!(rect.width > 0)) {
|
|
6459
7100
|
return;
|
|
6460
7101
|
}
|
|
6461
7102
|
const pointerX = event.clientX - rect.left;
|
|
@@ -6463,6 +7104,15 @@ function WaveformView({
|
|
|
6463
7104
|
return;
|
|
6464
7105
|
}
|
|
6465
7106
|
const vp = viewportRef.current;
|
|
7107
|
+
const draft = activeRangeRef.current;
|
|
7108
|
+
setIsRangeHovered(!!draft && isPointerOverRange({
|
|
7109
|
+
pointerX,
|
|
7110
|
+
range: draft,
|
|
7111
|
+
viewport: vp
|
|
7112
|
+
}));
|
|
7113
|
+
if (!interactive || isRangeDraggingRef.current || !(durationSec > 0)) {
|
|
7114
|
+
return;
|
|
7115
|
+
}
|
|
6466
7116
|
if (vp.pixelsPerSecond > 0) {
|
|
6467
7117
|
setHoverProgress(Math.min(1, Math.max(0, timeFromPositionPx(pointerX, vp) / durationSec)));
|
|
6468
7118
|
return;
|
|
@@ -6471,12 +7121,31 @@ function WaveformView({
|
|
|
6471
7121
|
}, [durationSec, interactive, isTape]);
|
|
6472
7122
|
const onHoverLeave = (0,external_react_.useCallback)(() => {
|
|
6473
7123
|
setHoverProgress(null);
|
|
7124
|
+
setIsRangeHovered(false);
|
|
7125
|
+
}, []);
|
|
7126
|
+
const handleRangeDragChange = (0,external_react_.useCallback)(isDragging => {
|
|
7127
|
+
isRangeDraggingRef.current = isDragging;
|
|
7128
|
+
setIsRangeDragging(isDragging);
|
|
7129
|
+
if (isDragging) {
|
|
7130
|
+
setHoverProgress(null);
|
|
7131
|
+
} else {
|
|
7132
|
+
skipNextSeekRef.current = true;
|
|
7133
|
+
window.setTimeout(() => {
|
|
7134
|
+
skipNextSeekRef.current = false;
|
|
7135
|
+
}, 0);
|
|
7136
|
+
setPreviewRange(null);
|
|
7137
|
+
}
|
|
7138
|
+
onRangeDragChange?.(isDragging);
|
|
7139
|
+
}, [onRangeDragChange]);
|
|
7140
|
+
const getPlayheadSec = (0,external_react_.useCallback)(() => {
|
|
7141
|
+
return mediaElRef.current ? mediaElRef.current.currentTime : currentTimeRef.current;
|
|
6474
7142
|
}, []);
|
|
6475
7143
|
const bindOverlayPortalHost = (0,external_react_.useCallback)(node => {
|
|
6476
7144
|
const host = node?.parentElement ?? null;
|
|
6477
7145
|
setOverlayPortalHost(prev => prev === host ? prev : host);
|
|
6478
7146
|
}, []);
|
|
6479
|
-
const hoverLeft = hoverProgress == null ? null : timeLeftPercent(hoverProgress * durationSec, durationSec, viewportRef.current);
|
|
7147
|
+
const hoverLeft = isRangeDragging || hoverProgress == null ? null : timeLeftPercent(hoverProgress * durationSec, durationSec, viewportRef.current);
|
|
7148
|
+
const showRangeOverlay = Boolean(range) && (isRangeDragging || !isPlaying || !isRangeCollapsed(range));
|
|
6480
7149
|
const scrubTimeChip = isTape && scrubPreviewTimeSec != null ? /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6481
7150
|
className: "bp-WaveformView-hover bp-WaveformView-hover--tape",
|
|
6482
7151
|
"data-testid": "bp-waveform-hover"
|
|
@@ -6518,7 +7187,20 @@ function WaveformView({
|
|
|
6518
7187
|
"aria-hidden": "true",
|
|
6519
7188
|
className: "bp-WaveformView-playhead",
|
|
6520
7189
|
"data-testid": "bp-waveform-playhead"
|
|
6521
|
-
}),
|
|
7190
|
+
}), showRangeOverlay && range && /*#__PURE__*/external_react_["default"].createElement(waveform_WaveformRangeSelection, {
|
|
7191
|
+
ref: rangeLayerRef,
|
|
7192
|
+
currentTimeSec: currentTime,
|
|
7193
|
+
durationSec: durationSec,
|
|
7194
|
+
getPlayheadSec: getPlayheadSec,
|
|
7195
|
+
interactive: interactive,
|
|
7196
|
+
isHighlighted: isRangeDragging || isRangeHovered,
|
|
7197
|
+
keepHighlight: true,
|
|
7198
|
+
onDragChange: handleRangeDragChange,
|
|
7199
|
+
onPreviewChange: setPreviewRange,
|
|
7200
|
+
onRangeChange: interactive ? onRangeChange : undefined,
|
|
7201
|
+
range: range,
|
|
7202
|
+
viewport: viewport
|
|
7203
|
+
}), hoverLeft != null && hoverProgress != null && !isRangeDragging && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6522
7204
|
className: "bp-WaveformView-hover",
|
|
6523
7205
|
"data-testid": "bp-waveform-hover",
|
|
6524
7206
|
style: {
|
|
@@ -6650,8 +7332,8 @@ function WaveformZoomControl({
|
|
|
6650
7332
|
onZoomChange(zoomFromSliderValue(newValue, maxZoom));
|
|
6651
7333
|
}, [maxZoom, onZoomChange]);
|
|
6652
7334
|
const handleStep = (0,external_react_.useCallback)(delta => {
|
|
6653
|
-
onZoomChange(
|
|
6654
|
-
}, [maxZoom, onZoomChange,
|
|
7335
|
+
onZoomChange(stepWaveformZoom(zoom, maxZoom, delta));
|
|
7336
|
+
}, [maxZoom, onZoomChange, zoom]);
|
|
6655
7337
|
const handleZoomInPointerDown = (0,external_react_.useCallback)(() => {
|
|
6656
7338
|
wasFlyoutOpenOnPointerDownRef.current = isHovered || isFocused || isRevealed || isPinned;
|
|
6657
7339
|
}, [isFocused, isHovered, isPinned, isRevealed]);
|
|
@@ -6761,7 +7443,10 @@ function MP3ControlsV2({
|
|
|
6761
7443
|
commentMarkers,
|
|
6762
7444
|
currentTime,
|
|
6763
7445
|
durationTime,
|
|
7446
|
+
hasStartedPlayback = false,
|
|
6764
7447
|
isPlaying,
|
|
7448
|
+
keyboardVolumeStep = 0,
|
|
7449
|
+
keyboardZoomStep = 0,
|
|
6765
7450
|
mediaEl,
|
|
6766
7451
|
onAutoplayChange,
|
|
6767
7452
|
onCommentMarkerClick,
|
|
@@ -6785,10 +7470,11 @@ function MP3ControlsV2({
|
|
|
6785
7470
|
const hasRealPeaks = !!(peaks && peaks.length);
|
|
6786
7471
|
const waveformPeaks = hasRealPeaks ? peaks : PLACEHOLDER_PEAKS;
|
|
6787
7472
|
const waveformDurationSec = hasWaveformDuration ? durationValue : PLACEHOLDER_DURATION_SEC;
|
|
6788
|
-
const [playRequested, setPlayRequested] = (0,external_react_.useState)(
|
|
7473
|
+
const [playRequested, setPlayRequested] = (0,external_react_.useState)(hasStartedPlayback);
|
|
6789
7474
|
const [viewport, setViewport] = (0,external_react_.useState)(null);
|
|
6790
7475
|
const isTape = useTapeWaveform();
|
|
6791
7476
|
const hasAppliedTapeDefaultZoomRef = (0,external_react_.useRef)(false); // ~10s window applied; reset to 1× when leaving tape
|
|
7477
|
+
const lastKeyboardZoomStepRef = (0,external_react_.useRef)(0); // last +/− step applied; skip re-step when maxZoom retriggers the effect
|
|
6792
7478
|
const userChangedTapeZoomRef = (0,external_react_.useRef)(false); // pinch/wheel zoom; skip re-applying the 10s default
|
|
6793
7479
|
const handleViewportChange = (0,external_react_.useCallback)(next => {
|
|
6794
7480
|
setMaxZoom(prev => prev === next.maxZoom ? prev : next.maxZoom);
|
|
@@ -6807,6 +7493,19 @@ function MP3ControlsV2({
|
|
|
6807
7493
|
setZoomLevel(nextZoom);
|
|
6808
7494
|
revealZoomControl();
|
|
6809
7495
|
}, [revealZoomControl]);
|
|
7496
|
+
(0,external_react_.useEffect)(() => {
|
|
7497
|
+
const steps = keyboardZoomStep - lastKeyboardZoomStepRef.current;
|
|
7498
|
+
if (!steps) {
|
|
7499
|
+
return;
|
|
7500
|
+
}
|
|
7501
|
+
lastKeyboardZoomStepRef.current = keyboardZoomStep;
|
|
7502
|
+
if (!(maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW)) {
|
|
7503
|
+
return;
|
|
7504
|
+
}
|
|
7505
|
+
userChangedTapeZoomRef.current = true;
|
|
7506
|
+
setZoomLevel(prev => stepWaveformZoom(prev, maxZoom, steps * constants/* WAVEFORM_ZOOM_BUTTON_STEP */.QD));
|
|
7507
|
+
revealZoomControl();
|
|
7508
|
+
}, [keyboardZoomStep, maxZoom, revealZoomControl]);
|
|
6810
7509
|
(0,external_react_.useEffect)(() => {
|
|
6811
7510
|
setZoomLevel(prev => clampWaveformZoom(prev, maxZoom));
|
|
6812
7511
|
}, [maxZoom]);
|
|
@@ -6832,10 +7531,10 @@ function MP3ControlsV2({
|
|
|
6832
7531
|
}, [durationValue, hasRealPeaks, hasWaveformDuration, isTape, maxZoom, viewport]);
|
|
6833
7532
|
(0,external_react_.useEffect)(() => () => window.clearTimeout(zoomRevealTimerRef.current), []);
|
|
6834
7533
|
(0,external_react_.useEffect)(() => {
|
|
6835
|
-
if (isPlaying) {
|
|
7534
|
+
if (isPlaying || hasStartedPlayback) {
|
|
6836
7535
|
setPlayRequested(true);
|
|
6837
7536
|
}
|
|
6838
|
-
}, [isPlaying]);
|
|
7537
|
+
}, [hasStartedPlayback, isPlaying]);
|
|
6839
7538
|
const handlePlayOverlayClick = (0,external_react_.useCallback)(() => {
|
|
6840
7539
|
setPlayRequested(true);
|
|
6841
7540
|
onPlayPause(true);
|
|
@@ -6853,9 +7552,10 @@ function MP3ControlsV2({
|
|
|
6853
7552
|
}
|
|
6854
7553
|
onTimeChange(marker.time);
|
|
6855
7554
|
}, [onCommentMarkerClick, onPlayPause, onTimeChange]);
|
|
6856
|
-
const
|
|
6857
|
-
const
|
|
6858
|
-
const
|
|
7555
|
+
const hasStarted = playRequested || hasStartedPlayback;
|
|
7556
|
+
const isWaveformInteractive = hasStarted && hasMediaMetadata;
|
|
7557
|
+
const isWaitingToPlay = hasStarted && !hasMediaMetadata;
|
|
7558
|
+
const showPlayOverlay = !hasStarted && !isPlaying;
|
|
6859
7559
|
const hasZoomHandlers = hasRealPeaks && !showPlayOverlay;
|
|
6860
7560
|
const hasZoomControl = hasZoomHandlers && hasMediaMetadata && maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
6861
7561
|
const waveformZoomLevel = isTape || hasZoomHandlers ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
@@ -6926,7 +7626,8 @@ function MP3ControlsV2({
|
|
|
6926
7626
|
durationTime: durationValue
|
|
6927
7627
|
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6928
7628
|
className: "bp-MP3ControlsV2-group"
|
|
6929
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
7629
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
7630
|
+
keyboardVolumeStep: keyboardVolumeStep,
|
|
6930
7631
|
onMuteChange: onMuteChange,
|
|
6931
7632
|
onVolumeChange: onVolumeChange,
|
|
6932
7633
|
volume: volume
|
|
@@ -7013,11 +7714,13 @@ function isFpsAvailable(player) {
|
|
|
7013
7714
|
|
|
7014
7715
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
7015
7716
|
/* harmony export */ Av: () => (/* binding */ WAVEFORM_TAPE_DEFAULT_WINDOW_SEC),
|
|
7717
|
+
/* harmony export */ BG: () => (/* binding */ WAVEFORM_RANGE_COLLAPSED_OFFSET_PX),
|
|
7016
7718
|
/* harmony export */ Bq: () => (/* binding */ WAVEFORM_PLAYHEAD_JUMP_MS),
|
|
7017
7719
|
/* harmony export */ DY: () => (/* binding */ WAVEFORM_BAR_RADIUS),
|
|
7018
7720
|
/* harmony export */ EB: () => (/* binding */ CLIENT_DECODE_MAX_COMPRESSED_BYTES),
|
|
7019
7721
|
/* harmony export */ FY: () => (/* binding */ MAX_PEAK_COUNT),
|
|
7020
7722
|
/* harmony export */ GQ: () => (/* binding */ DURATION_MISMATCH_TOLERANCE_SEC),
|
|
7723
|
+
/* harmony export */ IQ: () => (/* binding */ WAVEFORM_RANGE_SNAP_PX),
|
|
7021
7724
|
/* harmony export */ Kl: () => (/* binding */ WAVEFORM_MIN_VIEW_WINDOW_SEC),
|
|
7022
7725
|
/* harmony export */ LW: () => (/* binding */ WAVEFORM_ZOOM_MIN),
|
|
7023
7726
|
/* harmony export */ Le: () => (/* binding */ TAPE_POINTER_MEDIA_QUERY),
|
|
@@ -7026,8 +7729,10 @@ function isFpsAvailable(player) {
|
|
|
7026
7729
|
/* harmony export */ QD: () => (/* binding */ WAVEFORM_ZOOM_BUTTON_STEP),
|
|
7027
7730
|
/* harmony export */ XS: () => (/* binding */ WAVEFORM_BAR_MIN_HEIGHT),
|
|
7028
7731
|
/* harmony export */ Zs: () => (/* binding */ WAVEFORM_FOLLOW_SCROLL_SETTLE_MS),
|
|
7732
|
+
/* harmony export */ bX: () => (/* binding */ WAVEFORM_RANGE_MIN_DURATION_MS),
|
|
7029
7733
|
/* harmony export */ f3: () => (/* binding */ CLIENT_DECODE_PEAK_COUNT),
|
|
7030
7734
|
/* harmony export */ fI: () => (/* binding */ WAVEFORM_TAPE_CLICK_SUPPRESS_MS),
|
|
7735
|
+
/* harmony export */ h1: () => (/* binding */ WAVEFORM_RANGE_HANDLE_LINE_PX),
|
|
7031
7736
|
/* harmony export */ i8: () => (/* binding */ PEAK_UNIT_MAX),
|
|
7032
7737
|
/* harmony export */ m6: () => (/* binding */ WAVEFORM_ZOOM_DISMISS_MS),
|
|
7033
7738
|
/* harmony export */ mJ: () => (/* binding */ PEAK_UNIT_MIN),
|
|
@@ -7035,10 +7740,12 @@ function isFpsAvailable(player) {
|
|
|
7035
7740
|
/* harmony export */ nh: () => (/* binding */ WAVEFORM_ZOOM_SLIDER_MAX),
|
|
7036
7741
|
/* harmony export */ oN: () => (/* binding */ WAVEFORM_HEIGHT),
|
|
7037
7742
|
/* harmony export */ qY: () => (/* binding */ MAX_PAYLOAD_BYTES),
|
|
7743
|
+
/* harmony export */ r0: () => (/* binding */ WAVEFORM_RANGE_HIT_AREA_PX),
|
|
7038
7744
|
/* harmony export */ sh: () => (/* binding */ WAVEFORM_PAYLOAD_VERSION),
|
|
7039
7745
|
/* harmony export */ tK: () => (/* binding */ WAVEFORM_ZOOM_MAX),
|
|
7040
7746
|
/* harmony export */ zo: () => (/* binding */ WAVEFORM_BAR_WIDTH)
|
|
7041
7747
|
/* harmony export */ });
|
|
7748
|
+
/* unused harmony exports WAVEFORM_RANGE_PLAYHEAD_GAP_PX, WAVEFORM_RANGE_GRIP_IN_MS, WAVEFORM_RANGE_GRIP_OUT_MS */
|
|
7042
7749
|
/** Current waveform payload schema version. Bump only with a migration path. */
|
|
7043
7750
|
const WAVEFORM_PAYLOAD_VERSION = 1;
|
|
7044
7751
|
|
|
@@ -7088,6 +7795,24 @@ const WAVEFORM_BAR_RADIUS = WAVEFORM_BAR_WIDTH / 2;
|
|
|
7088
7795
|
const WAVEFORM_BAR_MIN_HEIGHT = WAVEFORM_BAR_WIDTH;
|
|
7089
7796
|
const WAVEFORM_HEIGHT = 140;
|
|
7090
7797
|
|
|
7798
|
+
/** Hit target centered on each range handle line. */
|
|
7799
|
+
const WAVEFORM_RANGE_HIT_AREA_PX = 24;
|
|
7800
|
+
/** Visible handle line and playhead width. */
|
|
7801
|
+
const WAVEFORM_RANGE_HANDLE_LINE_PX = 2;
|
|
7802
|
+
/** Screen gap between the playhead and each collapsed handle line. */
|
|
7803
|
+
const WAVEFORM_RANGE_PLAYHEAD_GAP_PX = 1;
|
|
7804
|
+
/**
|
|
7805
|
+
* Offset of each collapsed handle from the timestamp/playhead center so the
|
|
7806
|
+
* 2px lines sit 1px left and right of the 2px playhead.
|
|
7807
|
+
*/
|
|
7808
|
+
const WAVEFORM_RANGE_COLLAPSED_OFFSET_PX = WAVEFORM_RANGE_HANDLE_LINE_PX / 2 + WAVEFORM_RANGE_PLAYHEAD_GAP_PX + WAVEFORM_RANGE_HANDLE_LINE_PX / 2;
|
|
7809
|
+
/** Snap a dragging handle to the playhead when this close. */
|
|
7810
|
+
const WAVEFORM_RANGE_SNAP_PX = 8;
|
|
7811
|
+
/** Shortest committed range. Collapsed drafts (`endMs: null`) are exempt. */
|
|
7812
|
+
const WAVEFORM_RANGE_MIN_DURATION_MS = 250;
|
|
7813
|
+
const WAVEFORM_RANGE_GRIP_IN_MS = 150;
|
|
7814
|
+
const WAVEFORM_RANGE_GRIP_OUT_MS = 100;
|
|
7815
|
+
|
|
7091
7816
|
/***/ },
|
|
7092
7817
|
|
|
7093
7818
|
/***/ 4971
|
|
@@ -14598,7 +15323,7 @@ var x = (y) => {
|
|
|
14598
15323
|
var x = {}; __webpack_require__.d(x, y); return x
|
|
14599
15324
|
}
|
|
14600
15325
|
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) });
|
|
15326
|
+
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
15327
|
|
|
14603
15328
|
/***/ },
|
|
14604
15329
|
|
|
@@ -23492,7 +24217,7 @@ class Browser {
|
|
|
23492
24217
|
;// ./src/lib/Logger.js
|
|
23493
24218
|
/* eslint-disable no-undef */
|
|
23494
24219
|
const CLIENT_NAME = "box-content-preview";
|
|
23495
|
-
const CLIENT_VERSION = "3.
|
|
24220
|
+
const CLIENT_VERSION = "3.92.0";
|
|
23496
24221
|
/* eslint-enable no-undef */
|
|
23497
24222
|
|
|
23498
24223
|
class Logger {
|
|
@@ -36129,7 +36854,7 @@ function MP3Controls({
|
|
|
36129
36854
|
isPlaying: isPlaying,
|
|
36130
36855
|
movePlayback: movePlayback,
|
|
36131
36856
|
onPlayPause: onPlayPause
|
|
36132
|
-
}), /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
36857
|
+
}), /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
36133
36858
|
onMuteChange: onMuteChange,
|
|
36134
36859
|
onVolumeChange: onVolumeChange,
|
|
36135
36860
|
volume: volume
|
|
@@ -36202,6 +36927,57 @@ function MP3Viewer_toPrimitive(t, r) { if ("object" != typeof t || !t) return t;
|
|
|
36202
36927
|
|
|
36203
36928
|
|
|
36204
36929
|
const CSS_CLASS_MP3 = 'bp-media-mp3';
|
|
36930
|
+
const AUDIO_V2_SHUTTLE_RATES = [2, 4, 8, 16];
|
|
36931
|
+
const AUDIO_V2_SHUTTLE_TICK_MS = 50;
|
|
36932
|
+
const AUDIO_V2_SKIP_SEC = 1;
|
|
36933
|
+
const AUDIO_V2_SHIFT_SKIP_SEC = 5;
|
|
36934
|
+
|
|
36935
|
+
/**
|
|
36936
|
+
* Next J/L shuttle rate. Opposite direction starts at 2×.
|
|
36937
|
+
*
|
|
36938
|
+
* @param {number} currentRate
|
|
36939
|
+
* @param {boolean} sameDirection
|
|
36940
|
+
* @return {number} 2, 4, 8, or 16
|
|
36941
|
+
*/
|
|
36942
|
+
function nextShuttleRate(currentRate, sameDirection) {
|
|
36943
|
+
if (!sameDirection) {
|
|
36944
|
+
return AUDIO_V2_SHUTTLE_RATES[0];
|
|
36945
|
+
}
|
|
36946
|
+
const index = AUDIO_V2_SHUTTLE_RATES.indexOf(currentRate);
|
|
36947
|
+
if (index < 0) {
|
|
36948
|
+
return AUDIO_V2_SHUTTLE_RATES[0];
|
|
36949
|
+
}
|
|
36950
|
+
return AUDIO_V2_SHUTTLE_RATES[Math.min(index + 1, AUDIO_V2_SHUTTLE_RATES.length - 1)];
|
|
36951
|
+
}
|
|
36952
|
+
|
|
36953
|
+
/**
|
|
36954
|
+
* Next/previous comment marker for ↑/↓. Walks by id so same-time stacks each get a stop.
|
|
36955
|
+
*
|
|
36956
|
+
* @param {Array<Object>} markers
|
|
36957
|
+
* @param {Object} options
|
|
36958
|
+
* @param {number} options.direction -1 previous, 1 next
|
|
36959
|
+
* @param {string|null} options.selectedId
|
|
36960
|
+
* @param {number} options.time current playhead
|
|
36961
|
+
* @return {Object|null} marker to select
|
|
36962
|
+
*/
|
|
36963
|
+
function nextCommentMarker(markers, {
|
|
36964
|
+
direction,
|
|
36965
|
+
selectedId,
|
|
36966
|
+
time
|
|
36967
|
+
}) {
|
|
36968
|
+
const sorted = (markers || []).filter(marker => Number.isFinite(marker.time)).sort((left, right) => left.time - right.time || String(left.id).localeCompare(String(right.id)));
|
|
36969
|
+
if (!sorted.length) {
|
|
36970
|
+
return null;
|
|
36971
|
+
}
|
|
36972
|
+
const selectedIndex = sorted.findIndex(marker => marker.id === selectedId);
|
|
36973
|
+
if (selectedIndex >= 0) {
|
|
36974
|
+
return sorted[Math.max(0, Math.min(sorted.length - 1, selectedIndex + direction))];
|
|
36975
|
+
}
|
|
36976
|
+
if (direction > 0) {
|
|
36977
|
+
return sorted.find(marker => marker.time >= time) || sorted[sorted.length - 1];
|
|
36978
|
+
}
|
|
36979
|
+
return [...sorted].reverse().find(marker => marker.time <= time) || sorted[0];
|
|
36980
|
+
}
|
|
36205
36981
|
function createLoadFailedError(message) {
|
|
36206
36982
|
const error = new Error(message);
|
|
36207
36983
|
error.name = 'LOAD_FAILED';
|
|
@@ -36214,6 +36990,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36214
36990
|
* @inheritdoc
|
|
36215
36991
|
*/
|
|
36216
36992
|
MP3Viewer_defineProperty(this, "handlePlayRequest", () => {
|
|
36993
|
+
this.exitShuttle();
|
|
36217
36994
|
this.userRequestedPlay = true;
|
|
36218
36995
|
this.togglePlay();
|
|
36219
36996
|
if (this.shouldRaceClientWaveformDecode() && this.isWaveformDecodeRetryPending && !this.hasUsedWaveformDecodePlayRetry) {
|
|
@@ -36230,6 +37007,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36230
37007
|
* @return {void}
|
|
36231
37008
|
*/
|
|
36232
37009
|
MP3Viewer_defineProperty(this, "handlePlayPause", shouldPlay => {
|
|
37010
|
+
this.exitShuttle();
|
|
36233
37011
|
if (shouldPlay) {
|
|
36234
37012
|
this.handlePlayRequest();
|
|
36235
37013
|
return;
|
|
@@ -36239,19 +37017,25 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36239
37017
|
MP3Viewer_defineProperty(this, "handleCommentMarkersUpdated", (markers = []) => {
|
|
36240
37018
|
this.commentMarkers = markers;
|
|
36241
37019
|
const selected = markers.find(marker => marker.isSelected);
|
|
36242
|
-
|
|
36243
|
-
|
|
36244
|
-
|
|
36245
|
-
|
|
36246
|
-
|
|
36247
|
-
this.
|
|
36248
|
-
|
|
36249
|
-
|
|
37020
|
+
|
|
37021
|
+
// Host echoes often omit isSelected. Keep hostSelectedMarkerId so ↑/↓ can
|
|
37022
|
+
// still walk other comments at the same time. Clear only when that id is gone.
|
|
37023
|
+
if (selected) {
|
|
37024
|
+
if (selected.id !== this.hostSelectedMarkerId) {
|
|
37025
|
+
this.hostSelectedMarkerId = selected.id;
|
|
37026
|
+
if (Number.isFinite(selected.time)) {
|
|
37027
|
+
this.pendingHostSelectedSeek = selected;
|
|
37028
|
+
this.applyPendingHostSelectedSeek();
|
|
37029
|
+
}
|
|
36250
37030
|
}
|
|
37031
|
+
} else if (this.hostSelectedMarkerId && !markers.some(marker => marker.id === this.hostSelectedMarkerId)) {
|
|
37032
|
+
this.hostSelectedMarkerId = null;
|
|
37033
|
+
this.pendingHostSelectedSeek = null;
|
|
36251
37034
|
}
|
|
36252
37035
|
this.renderUI();
|
|
36253
37036
|
});
|
|
36254
37037
|
MP3Viewer_defineProperty(this, "handleCommentMarkerClick", marker => {
|
|
37038
|
+
this.exitShuttle();
|
|
36255
37039
|
this.hostSelectedMarkerId = marker.id;
|
|
36256
37040
|
this.pendingHostSelectedSeek = marker;
|
|
36257
37041
|
if (this.mediaEl) {
|
|
@@ -36305,6 +37089,12 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36305
37089
|
this.mediaEl = this.mediaContainerEl.appendChild(document.createElement('audio'));
|
|
36306
37090
|
this.mediaEl.setAttribute('preload', 'auto');
|
|
36307
37091
|
this.commentMarkers = [];
|
|
37092
|
+
this.hostSelectedMarkerId = null;
|
|
37093
|
+
this.shuttleDirection = null;
|
|
37094
|
+
this.shuttleRate = 0;
|
|
37095
|
+
this.reverseShuttleTimer = 0;
|
|
37096
|
+
this.keyboardVolumeStep = 0;
|
|
37097
|
+
this.keyboardZoomStep = 0;
|
|
36308
37098
|
}
|
|
36309
37099
|
bindCommentMarkersListener() {
|
|
36310
37100
|
if (!this.isAudioPlayerV2) {
|
|
@@ -36324,6 +37114,212 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36324
37114
|
return this.featureEnabled(constants/* AUDIO_PLAYER_V2 */.Ku) && this.useReactControls();
|
|
36325
37115
|
}
|
|
36326
37116
|
|
|
37117
|
+
/**
|
|
37118
|
+
* V2 audio keymap. Flag off and video keep MediaBaseViewer.handleKeydownReact.
|
|
37119
|
+
* Alt is not in Preview's key decoder — read it from the native event.
|
|
37120
|
+
*
|
|
37121
|
+
* @param {string} key
|
|
37122
|
+
* @param {KeyboardEvent} [event]
|
|
37123
|
+
* @return {boolean} consumed
|
|
37124
|
+
*/
|
|
37125
|
+
onKeydown(key, event) {
|
|
37126
|
+
if (this.isAudioPlayerV2 && this.handleKeydownAudioV2(key, event)) {
|
|
37127
|
+
return true;
|
|
37128
|
+
}
|
|
37129
|
+
return super.onKeydown(key, event);
|
|
37130
|
+
}
|
|
37131
|
+
handleKeydownAudioV2(key, event) {
|
|
37132
|
+
const decoded = (key || '').toLowerCase();
|
|
37133
|
+
const altKey = !!(event && event.altKey);
|
|
37134
|
+
switch (decoded) {
|
|
37135
|
+
case 'space':
|
|
37136
|
+
this.toggleV2Play();
|
|
37137
|
+
return true;
|
|
37138
|
+
case 'k':
|
|
37139
|
+
this.exitShuttle();
|
|
37140
|
+
this.pause(undefined, true);
|
|
37141
|
+
return true;
|
|
37142
|
+
case 'j':
|
|
37143
|
+
this.shuttle('reverse');
|
|
37144
|
+
return true;
|
|
37145
|
+
case 'l':
|
|
37146
|
+
this.shuttle('forward');
|
|
37147
|
+
return true;
|
|
37148
|
+
case 'arrowleft':
|
|
37149
|
+
this.quickSeek(-AUDIO_V2_SKIP_SEC);
|
|
37150
|
+
return true;
|
|
37151
|
+
case 'arrowright':
|
|
37152
|
+
this.quickSeek(AUDIO_V2_SKIP_SEC);
|
|
37153
|
+
return true;
|
|
37154
|
+
case ',':
|
|
37155
|
+
this.frameStep('back');
|
|
37156
|
+
return true;
|
|
37157
|
+
case '.':
|
|
37158
|
+
this.frameStep('forward');
|
|
37159
|
+
return true;
|
|
37160
|
+
case 'arrowup':
|
|
37161
|
+
if (altKey || !(this.commentMarkers || []).some(marker => Number.isFinite(marker.time))) {
|
|
37162
|
+
this.stepKeyboardVolume(1);
|
|
37163
|
+
return true;
|
|
37164
|
+
}
|
|
37165
|
+
this.jumpToCommentMarker(-1);
|
|
37166
|
+
return true;
|
|
37167
|
+
case 'arrowdown':
|
|
37168
|
+
if (altKey || !(this.commentMarkers || []).some(marker => Number.isFinite(marker.time))) {
|
|
37169
|
+
this.stepKeyboardVolume(-1);
|
|
37170
|
+
return true;
|
|
37171
|
+
}
|
|
37172
|
+
this.jumpToCommentMarker(1);
|
|
37173
|
+
return true;
|
|
37174
|
+
case 'end':
|
|
37175
|
+
if (!this.mediaEl || !Number.isFinite(this.mediaEl.duration)) {
|
|
37176
|
+
return false;
|
|
37177
|
+
}
|
|
37178
|
+
this.exitShuttle();
|
|
37179
|
+
this.setMediaTime(this.mediaEl.duration);
|
|
37180
|
+
return true;
|
|
37181
|
+
case '0':
|
|
37182
|
+
case 'home':
|
|
37183
|
+
this.exitShuttle();
|
|
37184
|
+
return false;
|
|
37185
|
+
case 'shift+arrowleft':
|
|
37186
|
+
this.quickSeek(-AUDIO_V2_SHIFT_SKIP_SEC);
|
|
37187
|
+
return true;
|
|
37188
|
+
case 'shift+arrowright':
|
|
37189
|
+
this.quickSeek(AUDIO_V2_SHIFT_SKIP_SEC);
|
|
37190
|
+
return true;
|
|
37191
|
+
case 'i':
|
|
37192
|
+
case 'o':
|
|
37193
|
+
case '/':
|
|
37194
|
+
case 'shift+l':
|
|
37195
|
+
// Range UI is not on this branch yet. Consume so I/O/loop cannot
|
|
37196
|
+
// fall through to shuttle or Preview navigation.
|
|
37197
|
+
return true;
|
|
37198
|
+
case 'shift++':
|
|
37199
|
+
case '+':
|
|
37200
|
+
case '=':
|
|
37201
|
+
this.stepKeyboardZoom(1);
|
|
37202
|
+
return true;
|
|
37203
|
+
case '-':
|
|
37204
|
+
case 'shift+_':
|
|
37205
|
+
this.stepKeyboardZoom(-1);
|
|
37206
|
+
return true;
|
|
37207
|
+
default:
|
|
37208
|
+
return false;
|
|
37209
|
+
}
|
|
37210
|
+
}
|
|
37211
|
+
toggleV2Play() {
|
|
37212
|
+
const reverseShuttle = this.shuttleDirection === 'reverse';
|
|
37213
|
+
const wasPlaying = !!(this.mediaEl && !this.mediaEl.paused);
|
|
37214
|
+
this.exitShuttle();
|
|
37215
|
+
if (reverseShuttle || wasPlaying) {
|
|
37216
|
+
this.pause(undefined, true);
|
|
37217
|
+
return;
|
|
37218
|
+
}
|
|
37219
|
+
this.handlePlayRequest();
|
|
37220
|
+
}
|
|
37221
|
+
shuttle(direction) {
|
|
37222
|
+
const sameDirection = this.shuttleDirection === direction;
|
|
37223
|
+
const rate = nextShuttleRate(this.shuttleRate, sameDirection);
|
|
37224
|
+
if (direction === 'forward') {
|
|
37225
|
+
this.startForwardShuttle(rate);
|
|
37226
|
+
return;
|
|
37227
|
+
}
|
|
37228
|
+
this.startReverseShuttle(rate);
|
|
37229
|
+
}
|
|
37230
|
+
startForwardShuttle(rate) {
|
|
37231
|
+
this.stopReverseShuttle();
|
|
37232
|
+
this.shuttleDirection = 'forward';
|
|
37233
|
+
this.shuttleRate = rate;
|
|
37234
|
+
this.userRequestedPlay = true;
|
|
37235
|
+
const playPromise = this.play();
|
|
37236
|
+
if (this.mediaEl) {
|
|
37237
|
+
this.mediaEl.playbackRate = this.shuttleRate;
|
|
37238
|
+
}
|
|
37239
|
+
if (playPromise && typeof playPromise.then === 'function') {
|
|
37240
|
+
playPromise.then(() => {
|
|
37241
|
+
if (this.mediaEl && this.shuttleDirection === 'forward') {
|
|
37242
|
+
this.mediaEl.playbackRate = this.shuttleRate;
|
|
37243
|
+
}
|
|
37244
|
+
}).catch(() => {});
|
|
37245
|
+
}
|
|
37246
|
+
}
|
|
37247
|
+
startReverseShuttle(rate) {
|
|
37248
|
+
this.stopReverseShuttle();
|
|
37249
|
+
this.shuttleDirection = 'reverse';
|
|
37250
|
+
this.shuttleRate = rate;
|
|
37251
|
+
this.userRequestedPlay = true;
|
|
37252
|
+
this.pause(undefined, true);
|
|
37253
|
+
this.handleRate();
|
|
37254
|
+
this.reverseShuttleTimer = window.setInterval(() => {
|
|
37255
|
+
if (!this.mediaEl || this.mediaEl.currentTime <= 0) {
|
|
37256
|
+
this.exitShuttle();
|
|
37257
|
+
return;
|
|
37258
|
+
}
|
|
37259
|
+
this.quickSeek(-(this.shuttleRate * AUDIO_V2_SHUTTLE_TICK_MS / 1000));
|
|
37260
|
+
if (this.mediaEl.currentTime <= 0) {
|
|
37261
|
+
this.exitShuttle();
|
|
37262
|
+
}
|
|
37263
|
+
}, AUDIO_V2_SHUTTLE_TICK_MS);
|
|
37264
|
+
}
|
|
37265
|
+
stopReverseShuttle() {
|
|
37266
|
+
if (this.reverseShuttleTimer) {
|
|
37267
|
+
window.clearInterval(this.reverseShuttleTimer);
|
|
37268
|
+
this.reverseShuttleTimer = 0;
|
|
37269
|
+
}
|
|
37270
|
+
}
|
|
37271
|
+
exitShuttle() {
|
|
37272
|
+
const wasShuttling = !!this.shuttleDirection;
|
|
37273
|
+
this.stopReverseShuttle();
|
|
37274
|
+
this.shuttleDirection = null;
|
|
37275
|
+
this.shuttleRate = 0;
|
|
37276
|
+
if (wasShuttling) {
|
|
37277
|
+
this.handleRate();
|
|
37278
|
+
}
|
|
37279
|
+
}
|
|
37280
|
+
|
|
37281
|
+
/**
|
|
37282
|
+
* Keep the settings rate unless forward shuttle owns playbackRate.
|
|
37283
|
+
*
|
|
37284
|
+
* @inheritdoc
|
|
37285
|
+
*/
|
|
37286
|
+
handleRate() {
|
|
37287
|
+
if (this.shuttleDirection === 'forward' && this.shuttleRate > 0 && this.mediaEl) {
|
|
37288
|
+
this.mediaEl.playbackRate = this.shuttleRate;
|
|
37289
|
+
if (this.controls) {
|
|
37290
|
+
this.renderUI();
|
|
37291
|
+
}
|
|
37292
|
+
return;
|
|
37293
|
+
}
|
|
37294
|
+
super.handleRate();
|
|
37295
|
+
}
|
|
37296
|
+
jumpToCommentMarker(direction) {
|
|
37297
|
+
if (!this.mediaEl) {
|
|
37298
|
+
return;
|
|
37299
|
+
}
|
|
37300
|
+
const target = nextCommentMarker(this.commentMarkers, {
|
|
37301
|
+
direction,
|
|
37302
|
+
selectedId: this.hostSelectedMarkerId,
|
|
37303
|
+
time: this.mediaEl.currentTime
|
|
37304
|
+
});
|
|
37305
|
+
if (!target || target.id === this.hostSelectedMarkerId) {
|
|
37306
|
+
return;
|
|
37307
|
+
}
|
|
37308
|
+
this.handleCommentMarkerClick(target);
|
|
37309
|
+
}
|
|
37310
|
+
stepKeyboardVolume(direction) {
|
|
37311
|
+
this.keyboardVolumeStep += 1;
|
|
37312
|
+
if (direction > 0) {
|
|
37313
|
+
this.increaseVolume();
|
|
37314
|
+
return;
|
|
37315
|
+
}
|
|
37316
|
+
this.decreaseVolume();
|
|
37317
|
+
}
|
|
37318
|
+
stepKeyboardZoom(direction) {
|
|
37319
|
+
this.keyboardZoomStep += direction;
|
|
37320
|
+
this.renderUI();
|
|
37321
|
+
}
|
|
37322
|
+
|
|
36327
37323
|
/**
|
|
36328
37324
|
* Load v2 controls (and wavesurfer) only when the audio player v2 gate is on.
|
|
36329
37325
|
*
|
|
@@ -36366,7 +37362,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36366
37362
|
* @return {Promise<{ default: Function }>} MP3ControlsV2 module
|
|
36367
37363
|
*/
|
|
36368
37364
|
importV2Controls() {
|
|
36369
|
-
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
37365
|
+
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 7450));
|
|
36370
37366
|
}
|
|
36371
37367
|
|
|
36372
37368
|
/**
|
|
@@ -36389,6 +37385,9 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36389
37385
|
*/
|
|
36390
37386
|
destroy() {
|
|
36391
37387
|
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
37388
|
+
this.stopReverseShuttle();
|
|
37389
|
+
this.shuttleDirection = null;
|
|
37390
|
+
this.shuttleRate = 0;
|
|
36392
37391
|
this.abortWaveformLoads();
|
|
36393
37392
|
super.destroy();
|
|
36394
37393
|
}
|
|
@@ -36764,6 +37763,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36764
37763
|
return;
|
|
36765
37764
|
}
|
|
36766
37765
|
this.pendingHostSelectedSeek = null;
|
|
37766
|
+
this.exitShuttle();
|
|
36767
37767
|
this.mediaEl.pause();
|
|
36768
37768
|
if (this.mediaEl.currentTime !== marker.time) {
|
|
36769
37769
|
this.mediaEl.currentTime = marker.time;
|
|
@@ -36806,6 +37806,9 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
36806
37806
|
const Mp3ControlsV2 = this.MP3ControlsV2;
|
|
36807
37807
|
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(Mp3ControlsV2, MP3Viewer_extends({}, sharedProps, {
|
|
36808
37808
|
commentMarkers: this.commentMarkers || [],
|
|
37809
|
+
hasStartedPlayback: !!this.userRequestedPlay,
|
|
37810
|
+
keyboardVolumeStep: this.keyboardVolumeStep,
|
|
37811
|
+
keyboardZoomStep: this.keyboardZoomStep,
|
|
36809
37812
|
mediaEl: this.mediaEl,
|
|
36810
37813
|
onCommentMarkerClick: this.handleCommentMarkerClick,
|
|
36811
37814
|
peaks: this.waveformPeaks
|
|
@@ -38404,7 +39407,7 @@ function VideoControls({
|
|
|
38404
39407
|
onPlayPause: onPlayPause
|
|
38405
39408
|
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
38406
39409
|
className: "bp-VideoControls-group bp-VideoControls-group--media-controls"
|
|
38407
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
39410
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
38408
39411
|
onMuteChange: onMuteChange,
|
|
38409
39412
|
onVolumeChange: onVolumeChange,
|
|
38410
39413
|
volume: volume
|
|
@@ -38963,7 +39966,7 @@ function VideoControlsV2({
|
|
|
38963
39966
|
mediaEl: mediaEl
|
|
38964
39967
|
})), /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
38965
39968
|
className: "bp-VideoControlsV2-group bp-VideoControlsV2-group--right"
|
|
38966
|
-
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.
|
|
39969
|
+
}, /*#__PURE__*/external_react_["default"].createElement(VolumeControls/* default */.Ay, {
|
|
38967
39970
|
onMuteChange: onMuteChange,
|
|
38968
39971
|
onVolumeChange: onVolumeChange,
|
|
38969
39972
|
volume: volume
|