box-content-preview 3.86.0 → 3.87.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 +5 -4
- package/dist/lib/index.js +748 -273
- package/package.json +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -1010,7 +1010,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
|
|
|
1010
1010
|
const CLIENT_NAME = "box-content-preview"; // eslint-disable-line no-undef
|
|
1011
1011
|
const CLIENT_NAME_KEY = 'box_client_name';
|
|
1012
1012
|
const CLIENT_VERSION_KEY = 'box_client_version';
|
|
1013
|
-
const CLIENT_VERSION = "3.
|
|
1013
|
+
const CLIENT_VERSION = "3.87.0"; // eslint-disable-line no-undef
|
|
1014
1014
|
const HEADER_CLIENT_NAME = 'X-Box-Client-Name';
|
|
1015
1015
|
const HEADER_CLIENT_VERSION = 'X-Box-Client-Version';
|
|
1016
1016
|
const PROMISE_MAP = {};
|
|
@@ -2135,6 +2135,204 @@ function DurationLabels({
|
|
|
2135
2135
|
|
|
2136
2136
|
/***/ },
|
|
2137
2137
|
|
|
2138
|
+
/***/ 3524
|
|
2139
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
2140
|
+
|
|
2141
|
+
|
|
2142
|
+
// EXPORTS
|
|
2143
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
2144
|
+
A: () => (/* binding */ MarkerAvatar)
|
|
2145
|
+
});
|
|
2146
|
+
|
|
2147
|
+
// EXTERNAL MODULE: external "react"
|
|
2148
|
+
var external_react_ = __webpack_require__(1649);
|
|
2149
|
+
;// ./src/lib/viewers/controls/media/MarkerAvatar.scss
|
|
2150
|
+
// extracted by mini-css-extract-plugin
|
|
2151
|
+
|
|
2152
|
+
;// ./src/lib/viewers/controls/media/MarkerAvatar.tsx
|
|
2153
|
+
|
|
2154
|
+
|
|
2155
|
+
const AVATAR_PALETTE = [{
|
|
2156
|
+
bg: '#7fb0ea',
|
|
2157
|
+
fg: '#222'
|
|
2158
|
+
}, {
|
|
2159
|
+
bg: '#003c84',
|
|
2160
|
+
fg: '#fff'
|
|
2161
|
+
}, {
|
|
2162
|
+
bg: '#ffeb7f',
|
|
2163
|
+
fg: '#222'
|
|
2164
|
+
}, {
|
|
2165
|
+
bg: '#92e0c0',
|
|
2166
|
+
fg: '#222'
|
|
2167
|
+
}, {
|
|
2168
|
+
bg: '#fad98d',
|
|
2169
|
+
fg: '#222'
|
|
2170
|
+
}, {
|
|
2171
|
+
bg: '#91c2fd',
|
|
2172
|
+
fg: '#222'
|
|
2173
|
+
}, {
|
|
2174
|
+
bg: '#f69bab',
|
|
2175
|
+
fg: '#222'
|
|
2176
|
+
}, {
|
|
2177
|
+
bg: '#cf9ff6',
|
|
2178
|
+
fg: '#222'
|
|
2179
|
+
}, {
|
|
2180
|
+
bg: '#f8c08c',
|
|
2181
|
+
fg: '#222'
|
|
2182
|
+
}, {
|
|
2183
|
+
bg: '#a392e0',
|
|
2184
|
+
fg: '#222'
|
|
2185
|
+
}];
|
|
2186
|
+
function AnonymousAvatarIcon() {
|
|
2187
|
+
return /*#__PURE__*/external_react_["default"].createElement("svg", {
|
|
2188
|
+
"aria-hidden": "true",
|
|
2189
|
+
className: "bp-MarkerAvatar-anonymousIcon",
|
|
2190
|
+
focusable: "false",
|
|
2191
|
+
viewBox: "0 0 16 16"
|
|
2192
|
+
}, /*#__PURE__*/external_react_["default"].createElement("path", {
|
|
2193
|
+
d: "M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm0 1.5c-2.5 0-5 1.25-5 3.75V14h10v-.75c0-2.5-2.5-3.75-5-3.75Z",
|
|
2194
|
+
fill: "currentColor"
|
|
2195
|
+
}));
|
|
2196
|
+
}
|
|
2197
|
+
function MarkerAvatar({
|
|
2198
|
+
avatarUrl,
|
|
2199
|
+
colorIndex = 0,
|
|
2200
|
+
initial,
|
|
2201
|
+
size
|
|
2202
|
+
}) {
|
|
2203
|
+
const safeIndex = Number.isFinite(colorIndex) ? Math.abs(colorIndex) % AVATAR_PALETTE.length : 0;
|
|
2204
|
+
const {
|
|
2205
|
+
bg: bgColor,
|
|
2206
|
+
fg: textColor
|
|
2207
|
+
} = AVATAR_PALETTE[safeIndex];
|
|
2208
|
+
const [imgFailed, setImgFailed] = external_react_["default"].useState(false);
|
|
2209
|
+
const [loadedUrl, setLoadedUrl] = external_react_["default"].useState(null);
|
|
2210
|
+
const imgRef = external_react_["default"].useRef(null);
|
|
2211
|
+
// Keep initial + palette until onLoad (and for cached complete). Shared with video ticks.
|
|
2212
|
+
const showImage = Boolean(avatarUrl) && !imgFailed && loadedUrl === avatarUrl;
|
|
2213
|
+
external_react_["default"].useEffect(() => {
|
|
2214
|
+
setImgFailed(false);
|
|
2215
|
+
}, [avatarUrl]);
|
|
2216
|
+
external_react_["default"].useLayoutEffect(() => {
|
|
2217
|
+
const img = imgRef.current;
|
|
2218
|
+
if (avatarUrl && img?.complete && img.naturalWidth > 0) {
|
|
2219
|
+
setLoadedUrl(avatarUrl);
|
|
2220
|
+
}
|
|
2221
|
+
}, [avatarUrl]);
|
|
2222
|
+
let fallback = /*#__PURE__*/external_react_["default"].createElement(AnonymousAvatarIcon, null);
|
|
2223
|
+
if (initial) {
|
|
2224
|
+
fallback = /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
2225
|
+
className: "bp-MarkerAvatar-initial",
|
|
2226
|
+
style: {
|
|
2227
|
+
color: textColor
|
|
2228
|
+
}
|
|
2229
|
+
}, initial);
|
|
2230
|
+
}
|
|
2231
|
+
const style = {};
|
|
2232
|
+
if (!showImage) {
|
|
2233
|
+
style.backgroundColor = bgColor;
|
|
2234
|
+
}
|
|
2235
|
+
if (size) {
|
|
2236
|
+
style.width = size;
|
|
2237
|
+
style.height = size;
|
|
2238
|
+
}
|
|
2239
|
+
return /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
2240
|
+
className: "bp-MarkerAvatar",
|
|
2241
|
+
style: Object.keys(style).length > 0 ? style : undefined
|
|
2242
|
+
}, avatarUrl && !imgFailed && /*#__PURE__*/external_react_["default"].createElement("img", {
|
|
2243
|
+
ref: imgRef,
|
|
2244
|
+
alt: "",
|
|
2245
|
+
onError: () => {
|
|
2246
|
+
setImgFailed(true);
|
|
2247
|
+
},
|
|
2248
|
+
onLoad: () => {
|
|
2249
|
+
if (avatarUrl) {
|
|
2250
|
+
setLoadedUrl(avatarUrl);
|
|
2251
|
+
}
|
|
2252
|
+
},
|
|
2253
|
+
src: avatarUrl
|
|
2254
|
+
}), !showImage && fallback);
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
/***/ },
|
|
2258
|
+
|
|
2259
|
+
/***/ 9232
|
|
2260
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
2261
|
+
|
|
2262
|
+
|
|
2263
|
+
// EXPORTS
|
|
2264
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
2265
|
+
A: () => (/* binding */ MarkerAvatarStack)
|
|
2266
|
+
});
|
|
2267
|
+
|
|
2268
|
+
// EXTERNAL MODULE: external "react"
|
|
2269
|
+
var external_react_ = __webpack_require__(1649);
|
|
2270
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MarkerAvatar.tsx + 1 modules
|
|
2271
|
+
var MarkerAvatar = __webpack_require__(3524);
|
|
2272
|
+
;// ./src/lib/viewers/controls/media/MarkerAvatarStack.scss
|
|
2273
|
+
// extracted by mini-css-extract-plugin
|
|
2274
|
+
|
|
2275
|
+
;// ./src/lib/viewers/controls/media/MarkerAvatarStack.tsx
|
|
2276
|
+
|
|
2277
|
+
|
|
2278
|
+
|
|
2279
|
+
const MAX_VISIBLE_AVATARS = 4;
|
|
2280
|
+
function MarkerAvatarStack({
|
|
2281
|
+
markers,
|
|
2282
|
+
onMarkerClick,
|
|
2283
|
+
overlapPx,
|
|
2284
|
+
selectedId,
|
|
2285
|
+
size
|
|
2286
|
+
}) {
|
|
2287
|
+
const hasOverflow = markers.length > MAX_VISIBLE_AVATARS;
|
|
2288
|
+
const visibleMarkers = hasOverflow ? markers.slice(0, MAX_VISIBLE_AVATARS - 1) : markers;
|
|
2289
|
+
const overflowMarkers = hasOverflow ? markers.slice(MAX_VISIBLE_AVATARS - 1) : [];
|
|
2290
|
+
const isOverflowSelected = overflowMarkers.some(marker => marker.id === selectedId);
|
|
2291
|
+
const style = overlapPx != null ? {
|
|
2292
|
+
'--bp-marker-stack-overlap': `-${overlapPx}px`
|
|
2293
|
+
} : undefined;
|
|
2294
|
+
return /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
2295
|
+
className: "bp-MarkerAvatarStack",
|
|
2296
|
+
style: style
|
|
2297
|
+
}, visibleMarkers.map(marker => /*#__PURE__*/external_react_["default"].createElement("button", {
|
|
2298
|
+
key: marker.id,
|
|
2299
|
+
"aria-label": "Comment marker",
|
|
2300
|
+
"aria-pressed": marker.id === selectedId,
|
|
2301
|
+
className: `bp-MarkerAvatarStack-item${marker.id === selectedId ? ' bp-MarkerAvatarStack-item--selected' : ''}`,
|
|
2302
|
+
"data-resin-target": "commentMarkerStackAvatar",
|
|
2303
|
+
onClick: e => {
|
|
2304
|
+
e.stopPropagation();
|
|
2305
|
+
onMarkerClick?.(marker);
|
|
2306
|
+
},
|
|
2307
|
+
type: "button"
|
|
2308
|
+
}, /*#__PURE__*/external_react_["default"].createElement(MarkerAvatar/* default */.A, {
|
|
2309
|
+
avatarUrl: marker.avatarUrl,
|
|
2310
|
+
colorIndex: marker.colorIndex,
|
|
2311
|
+
initial: marker.initial,
|
|
2312
|
+
size: size
|
|
2313
|
+
}))), hasOverflow && /*#__PURE__*/external_react_["default"].createElement("button", {
|
|
2314
|
+
"aria-label": "Comment marker",
|
|
2315
|
+
"aria-pressed": isOverflowSelected,
|
|
2316
|
+
className: `bp-MarkerAvatarStack-item bp-MarkerAvatarStack-overflow${isOverflowSelected ? ' bp-MarkerAvatarStack-item--selected' : ''}`,
|
|
2317
|
+
"data-resin-target": "commentMarkerStackAvatarOverflow",
|
|
2318
|
+
onClick: e => {
|
|
2319
|
+
e.stopPropagation();
|
|
2320
|
+
onMarkerClick?.(markers[MAX_VISIBLE_AVATARS - 1]);
|
|
2321
|
+
},
|
|
2322
|
+
type: "button"
|
|
2323
|
+
}, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
2324
|
+
className: "bp-MarkerAvatar bp-MarkerAvatarStack-overflowBadge",
|
|
2325
|
+
style: size ? {
|
|
2326
|
+
width: size,
|
|
2327
|
+
height: size
|
|
2328
|
+
} : undefined
|
|
2329
|
+
}, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
2330
|
+
className: "bp-MarkerAvatar-initial"
|
|
2331
|
+
}, "+", markers.length - (MAX_VISIBLE_AVATARS - 1)))));
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
/***/ },
|
|
2335
|
+
|
|
2138
2336
|
/***/ 6929
|
|
2139
2337
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
2140
2338
|
|
|
@@ -3245,6 +3443,75 @@ function VolumeControls({
|
|
|
3245
3443
|
|
|
3246
3444
|
/***/ },
|
|
3247
3445
|
|
|
3446
|
+
/***/ 2400
|
|
3447
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
3448
|
+
|
|
3449
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
3450
|
+
/* harmony export */ A: () => (/* binding */ buildClusters)
|
|
3451
|
+
/* harmony export */ });
|
|
3452
|
+
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5346);
|
|
3453
|
+
|
|
3454
|
+
|
|
3455
|
+
/** Max pixel distance between adjacent markers (sorted by time) for them to be grouped into a single cluster. */
|
|
3456
|
+
const CLUSTER_THRESHOLD_PX = 2;
|
|
3457
|
+
|
|
3458
|
+
/** Converts a group of markers into a ClusterData object with computed positions and metadata. */
|
|
3459
|
+
function finalizeCluster(group, durationValue) {
|
|
3460
|
+
const leftPercent = (0,_utils__WEBPACK_IMPORTED_MODULE_0__/* .percent */ .K)(group[0].time, durationValue);
|
|
3461
|
+
const rightPercent = (0,_utils__WEBPACK_IMPORTED_MODULE_0__/* .percent */ .K)(group[group.length - 1].time, durationValue);
|
|
3462
|
+
const isSinglePoint = leftPercent === rightPercent;
|
|
3463
|
+
return {
|
|
3464
|
+
id: group.map(m => m.id).join('|'),
|
|
3465
|
+
isSinglePoint,
|
|
3466
|
+
leftPercent,
|
|
3467
|
+
markers: group,
|
|
3468
|
+
rightPercent
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
/**
|
|
3473
|
+
* Groups comment markers into clusters based on their pixel proximity on the scrubber track.
|
|
3474
|
+
* Markers are sorted by time, then chained: each marker that is within CLUSTER_THRESHOLD_PX
|
|
3475
|
+
* of its neighbor joins the same cluster. This means distant markers can end up in one cluster
|
|
3476
|
+
* if intermediate markers bridge the gap.
|
|
3477
|
+
*/
|
|
3478
|
+
function buildClusters(markers, durationValue, trackWidth, thresholdPx = CLUSTER_THRESHOLD_PX) {
|
|
3479
|
+
if (durationValue <= 0 || markers.length === 0 || trackWidth <= 0) return [];
|
|
3480
|
+
const sorted = [...markers].sort((a, b) => a.time - b.time);
|
|
3481
|
+
const clusters = [];
|
|
3482
|
+
let currentGroup = [sorted[0]];
|
|
3483
|
+
for (let i = 1; i < sorted.length; i += 1) {
|
|
3484
|
+
const prevPx = sorted[i - 1].time / durationValue * trackWidth;
|
|
3485
|
+
const currPx = sorted[i].time / durationValue * trackWidth;
|
|
3486
|
+
if (currPx - prevPx <= thresholdPx) {
|
|
3487
|
+
currentGroup.push(sorted[i]);
|
|
3488
|
+
} else {
|
|
3489
|
+
clusters.push(finalizeCluster(currentGroup, durationValue));
|
|
3490
|
+
currentGroup = [sorted[i]];
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
clusters.push(finalizeCluster(currentGroup, durationValue));
|
|
3494
|
+
return clusters;
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
/***/ },
|
|
3498
|
+
|
|
3499
|
+
/***/ 5346
|
|
3500
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
3501
|
+
|
|
3502
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
3503
|
+
/* harmony export */ K: () => (/* binding */ percent)
|
|
3504
|
+
/* harmony export */ });
|
|
3505
|
+
/* unused harmony export round */
|
|
3506
|
+
const round = value => {
|
|
3507
|
+
return +value.toFixed(4);
|
|
3508
|
+
};
|
|
3509
|
+
const percent = (value1, value2) => {
|
|
3510
|
+
return round(value1 / value2 * 100);
|
|
3511
|
+
};
|
|
3512
|
+
|
|
3513
|
+
/***/ },
|
|
3514
|
+
|
|
3248
3515
|
/***/ 709
|
|
3249
3516
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
3250
3517
|
|
|
@@ -4118,7 +4385,7 @@ function getPdfjsWorkerSrc() {
|
|
|
4118
4385
|
|
|
4119
4386
|
/***/ },
|
|
4120
4387
|
|
|
4121
|
-
/***/
|
|
4388
|
+
/***/ 9286
|
|
4122
4389
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
4123
4390
|
|
|
4124
4391
|
|
|
@@ -4283,6 +4550,11 @@ function getViewportAtScroll(viewport, scrollLeftPx) {
|
|
|
4283
4550
|
}));
|
|
4284
4551
|
}
|
|
4285
4552
|
|
|
4553
|
+
/** True when the visible window has not moved — skip a React state update. */
|
|
4554
|
+
function viewportEquals(prev, next) {
|
|
4555
|
+
return !!prev && prev.durationSec === next.durationSec && prev.endSec === next.endSec && prev.maxZoom === next.maxZoom && prev.scrollLeftPx === next.scrollLeftPx && prev.startSec === next.startSec && prev.widthPx === next.widthPx && prev.zoomLevel === next.zoomLevel;
|
|
4556
|
+
}
|
|
4557
|
+
|
|
4286
4558
|
/** How many CSS pixels from the left of the visible window this time sits. */
|
|
4287
4559
|
function positionPxFromTime(timeSec, viewport) {
|
|
4288
4560
|
return (timeSec - viewport.startSec) * viewport.pixelsPerSecond;
|
|
@@ -4371,6 +4643,35 @@ function clampScrollLeft(scrollLeftPx, viewport) {
|
|
|
4371
4643
|
return Math.min(maxScrollLeft(viewport), Math.max(0, scrollLeftPx));
|
|
4372
4644
|
}
|
|
4373
4645
|
|
|
4646
|
+
/** Center this time in the view, clamped so the window still fills the canvas. */
|
|
4647
|
+
function getCenteredScrollLeft(timeSec, viewport) {
|
|
4648
|
+
return clampScrollLeft(timeSec * viewport.pixelsPerSecond - viewport.widthPx / 2, viewport);
|
|
4649
|
+
}
|
|
4650
|
+
|
|
4651
|
+
/**
|
|
4652
|
+
* Host/media seek while zoomed: jump so the time (and its comment avatar) is on screen.
|
|
4653
|
+
* No-op at fit-to-width or when that time is already visible.
|
|
4654
|
+
*/
|
|
4655
|
+
function getSeekCameraAction({
|
|
4656
|
+
timeSec,
|
|
4657
|
+
viewport
|
|
4658
|
+
}) {
|
|
4659
|
+
if (viewport.zoomLevel <= constants/* WAVEFORM_ZOOM_MIN */.LW || !(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
4660
|
+
return {
|
|
4661
|
+
type: 'none'
|
|
4662
|
+
};
|
|
4663
|
+
}
|
|
4664
|
+
if (isTimeInView(timeSec, viewport)) {
|
|
4665
|
+
return {
|
|
4666
|
+
type: 'none'
|
|
4667
|
+
};
|
|
4668
|
+
}
|
|
4669
|
+
return {
|
|
4670
|
+
type: 'jump',
|
|
4671
|
+
scrollLeftPx: getCenteredScrollLeft(timeSec, viewport)
|
|
4672
|
+
};
|
|
4673
|
+
}
|
|
4674
|
+
|
|
4374
4675
|
/** Follow inset in CSS px, capped at one third of the view so a narrow player still has room. */
|
|
4375
4676
|
function getFollowInsetPx(widthPx, insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM) {
|
|
4376
4677
|
if (!(widthPx > 0)) {
|
|
@@ -4447,6 +4748,198 @@ function getPlayheadCameraAction({
|
|
|
4447
4748
|
type: 'none'
|
|
4448
4749
|
};
|
|
4449
4750
|
}
|
|
4751
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/buildClusters.ts
|
|
4752
|
+
var buildClusters = __webpack_require__(2400);
|
|
4753
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MarkerAvatar.tsx + 1 modules
|
|
4754
|
+
var MarkerAvatar = __webpack_require__(3524);
|
|
4755
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MarkerAvatarStack.tsx + 1 modules
|
|
4756
|
+
var MarkerAvatarStack = __webpack_require__(9232);
|
|
4757
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/utils.ts
|
|
4758
|
+
var utils = __webpack_require__(5346);
|
|
4759
|
+
;// ./src/lib/viewers/media/waveform/WaveformCommentMarkers.scss
|
|
4760
|
+
// extracted by mini-css-extract-plugin
|
|
4761
|
+
|
|
4762
|
+
;// ./src/lib/viewers/media/waveform/WaveformCommentMarkers.tsx
|
|
4763
|
+
|
|
4764
|
+
|
|
4765
|
+
|
|
4766
|
+
|
|
4767
|
+
|
|
4768
|
+
|
|
4769
|
+
|
|
4770
|
+
const WAVEFORM_MARKER_SIZE_PX = 20;
|
|
4771
|
+
function hasMappedWindow(viewport) {
|
|
4772
|
+
return !!viewport && Number.isFinite(viewport.startSec) && viewport.endSec > viewport.startSec;
|
|
4773
|
+
}
|
|
4774
|
+
function markerLeftPercent(time, durationSec, viewport) {
|
|
4775
|
+
const mapped = hasMappedWindow(viewport);
|
|
4776
|
+
const origin = mapped ? viewport.startSec : 0;
|
|
4777
|
+
const span = mapped ? viewport.endSec - viewport.startSec : durationSec;
|
|
4778
|
+
return (0,utils/* percent */.K)(time - origin, span);
|
|
4779
|
+
}
|
|
4780
|
+
|
|
4781
|
+
/** Width is unknown until layout. Still place badges, and stack exact same timestamps. */
|
|
4782
|
+
function clustersByExactTime(markers, durationSec) {
|
|
4783
|
+
const sorted = [...markers].sort((a, b) => a.time - b.time);
|
|
4784
|
+
const groups = [];
|
|
4785
|
+
sorted.forEach(marker => {
|
|
4786
|
+
const last = groups[groups.length - 1];
|
|
4787
|
+
if (last && last[last.length - 1].time === marker.time) {
|
|
4788
|
+
last.push(marker);
|
|
4789
|
+
} else {
|
|
4790
|
+
groups.push([marker]);
|
|
4791
|
+
}
|
|
4792
|
+
});
|
|
4793
|
+
return groups.map(group => {
|
|
4794
|
+
const leftPercent = (0,utils/* percent */.K)(group[0].time, durationSec);
|
|
4795
|
+
const rightPercent = (0,utils/* percent */.K)(group[group.length - 1].time, durationSec);
|
|
4796
|
+
return {
|
|
4797
|
+
id: group.map(m => m.id).join('|'),
|
|
4798
|
+
isSinglePoint: leftPercent === rightPercent,
|
|
4799
|
+
leftPercent,
|
|
4800
|
+
markers: group,
|
|
4801
|
+
rightPercent
|
|
4802
|
+
};
|
|
4803
|
+
});
|
|
4804
|
+
}
|
|
4805
|
+
function WaveformCommentMarkers({
|
|
4806
|
+
commentMarkers,
|
|
4807
|
+
durationSec,
|
|
4808
|
+
onCommentMarkerClick,
|
|
4809
|
+
selectedId: hostSelectedId = null,
|
|
4810
|
+
viewport = null
|
|
4811
|
+
}) {
|
|
4812
|
+
const overlayRef = (0,external_react_.useRef)(null);
|
|
4813
|
+
const trackRef = (0,external_react_.useRef)(null);
|
|
4814
|
+
const dismissedIdRef = (0,external_react_.useRef)(null);
|
|
4815
|
+
const [trackWidth, setTrackWidth] = (0,external_react_.useState)(0);
|
|
4816
|
+
const [optimisticSelectedId, setOptimisticSelectedId] = (0,external_react_.useState)(null);
|
|
4817
|
+
const [isSelectionDismissed, setIsSelectionDismissed] = (0,external_react_.useState)(false);
|
|
4818
|
+
const selectedId = optimisticSelectedId ?? (isSelectionDismissed ? null : hostSelectedId);
|
|
4819
|
+
const canShowTrack = durationSec > 0 && commentMarkers.length > 0;
|
|
4820
|
+
const zoomLevel = viewport?.zoomLevel ?? constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4821
|
+
const isZoomed = hasMappedWindow(viewport) && viewport.zoomLevel > constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
4822
|
+
(0,external_react_.useEffect)(() => {
|
|
4823
|
+
setOptimisticSelectedId(null);
|
|
4824
|
+
// Host ack of the dismissed id must not bring the ring back.
|
|
4825
|
+
if (dismissedIdRef.current && hostSelectedId === dismissedIdRef.current) {
|
|
4826
|
+
return;
|
|
4827
|
+
}
|
|
4828
|
+
dismissedIdRef.current = null;
|
|
4829
|
+
setIsSelectionDismissed(false);
|
|
4830
|
+
}, [hostSelectedId]);
|
|
4831
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
4832
|
+
if (!canShowTrack) {
|
|
4833
|
+
setTrackWidth(0);
|
|
4834
|
+
return undefined;
|
|
4835
|
+
}
|
|
4836
|
+
const el = trackRef.current;
|
|
4837
|
+
if (!el) {
|
|
4838
|
+
return undefined;
|
|
4839
|
+
}
|
|
4840
|
+
setTrackWidth(el.clientWidth);
|
|
4841
|
+
const observer = new ResizeObserver(entries => {
|
|
4842
|
+
entries.forEach(entry => {
|
|
4843
|
+
setTrackWidth(entry.contentRect.width);
|
|
4844
|
+
});
|
|
4845
|
+
});
|
|
4846
|
+
observer.observe(el);
|
|
4847
|
+
return () => observer.disconnect();
|
|
4848
|
+
}, [canShowTrack]);
|
|
4849
|
+
const clusters = (0,external_react_.useMemo)(() => {
|
|
4850
|
+
const clusterWidth = trackWidth * Math.max(constants/* WAVEFORM_ZOOM_MIN */.LW, zoomLevel);
|
|
4851
|
+
if (clusterWidth <= 0) {
|
|
4852
|
+
return clustersByExactTime(commentMarkers, durationSec);
|
|
4853
|
+
}
|
|
4854
|
+
return (0,buildClusters/* default */.A)(commentMarkers, durationSec, clusterWidth, WAVEFORM_MARKER_SIZE_PX);
|
|
4855
|
+
}, [commentMarkers, durationSec, trackWidth, zoomLevel]);
|
|
4856
|
+
const handleMarkerClick = (0,external_react_.useCallback)((marker, event) => {
|
|
4857
|
+
event?.stopPropagation();
|
|
4858
|
+
dismissedIdRef.current = null;
|
|
4859
|
+
setIsSelectionDismissed(false);
|
|
4860
|
+
setOptimisticSelectedId(marker.id);
|
|
4861
|
+
onCommentMarkerClick?.(marker);
|
|
4862
|
+
}, [onCommentMarkerClick]);
|
|
4863
|
+
(0,external_react_.useEffect)(() => {
|
|
4864
|
+
if (!selectedId) {
|
|
4865
|
+
return undefined;
|
|
4866
|
+
}
|
|
4867
|
+
const isEventInsideSelectedBadge = target => {
|
|
4868
|
+
if (!(target instanceof Element) || !overlayRef.current) {
|
|
4869
|
+
return false;
|
|
4870
|
+
}
|
|
4871
|
+
const selected = overlayRef.current.querySelector('.bp-WaveformCommentMarkers-marker--selected, .bp-MarkerAvatarStack-item--selected');
|
|
4872
|
+
return Boolean(selected && selected.contains(target));
|
|
4873
|
+
};
|
|
4874
|
+
const onDocumentPointerDown = event => {
|
|
4875
|
+
if (isEventInsideSelectedBadge(event.target)) {
|
|
4876
|
+
return;
|
|
4877
|
+
}
|
|
4878
|
+
dismissedIdRef.current = selectedId;
|
|
4879
|
+
setOptimisticSelectedId(null);
|
|
4880
|
+
setIsSelectionDismissed(true);
|
|
4881
|
+
const active = document.activeElement;
|
|
4882
|
+
if (active instanceof HTMLElement && overlayRef.current?.contains(active)) {
|
|
4883
|
+
active.blur();
|
|
4884
|
+
}
|
|
4885
|
+
};
|
|
4886
|
+
document.addEventListener('pointerdown', onDocumentPointerDown, true);
|
|
4887
|
+
return () => {
|
|
4888
|
+
document.removeEventListener('pointerdown', onDocumentPointerDown, true);
|
|
4889
|
+
};
|
|
4890
|
+
}, [selectedId]);
|
|
4891
|
+
if (!(durationSec > 0) || commentMarkers.length === 0) {
|
|
4892
|
+
return null;
|
|
4893
|
+
}
|
|
4894
|
+
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
4895
|
+
ref: overlayRef,
|
|
4896
|
+
className: `bp-WaveformCommentMarkers${isZoomed ? ' bp-WaveformCommentMarkers--zoomed' : ''}`,
|
|
4897
|
+
"data-testid": "bp-waveform-comment-markers"
|
|
4898
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
4899
|
+
ref: trackRef,
|
|
4900
|
+
className: "bp-WaveformCommentMarkers-track"
|
|
4901
|
+
}, clusters.map(cluster => {
|
|
4902
|
+
const marker = cluster.markers[0];
|
|
4903
|
+
const isGroup = cluster.markers.length > 1;
|
|
4904
|
+
const isSelected = cluster.markers.some(entry => entry.id === selectedId);
|
|
4905
|
+
const className = `bp-WaveformCommentMarkers-marker${isSelected ? ' bp-WaveformCommentMarkers-marker--selected' : ''}${isGroup ? ' bp-WaveformCommentMarkers-marker--group' : ''}`;
|
|
4906
|
+
const left = `${markerLeftPercent(marker.time, durationSec, viewport)}%`;
|
|
4907
|
+
if (isGroup) {
|
|
4908
|
+
return /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
4909
|
+
key: cluster.id,
|
|
4910
|
+
className: className,
|
|
4911
|
+
"data-testid": "bp-waveform-comment-marker",
|
|
4912
|
+
style: {
|
|
4913
|
+
left
|
|
4914
|
+
}
|
|
4915
|
+
}, /*#__PURE__*/external_react_["default"].createElement(MarkerAvatarStack/* default */.A, {
|
|
4916
|
+
markers: cluster.markers,
|
|
4917
|
+
onMarkerClick: handleMarkerClick,
|
|
4918
|
+
overlapPx: WAVEFORM_MARKER_SIZE_PX / 2,
|
|
4919
|
+
selectedId: selectedId,
|
|
4920
|
+
size: WAVEFORM_MARKER_SIZE_PX
|
|
4921
|
+
}));
|
|
4922
|
+
}
|
|
4923
|
+
return /*#__PURE__*/external_react_["default"].createElement("button", {
|
|
4924
|
+
key: cluster.id,
|
|
4925
|
+
"aria-label": "Comment marker",
|
|
4926
|
+
"aria-pressed": isSelected,
|
|
4927
|
+
className: className,
|
|
4928
|
+
"data-resin-target": "commentMarker",
|
|
4929
|
+
"data-testid": "bp-waveform-comment-marker",
|
|
4930
|
+
onClick: event => handleMarkerClick(marker, event),
|
|
4931
|
+
style: {
|
|
4932
|
+
left
|
|
4933
|
+
},
|
|
4934
|
+
type: "button"
|
|
4935
|
+
}, /*#__PURE__*/external_react_["default"].createElement(MarkerAvatar/* default */.A, {
|
|
4936
|
+
avatarUrl: marker.avatarUrl,
|
|
4937
|
+
colorIndex: marker.colorIndex,
|
|
4938
|
+
initial: marker.initial,
|
|
4939
|
+
size: WAVEFORM_MARKER_SIZE_PX
|
|
4940
|
+
}));
|
|
4941
|
+
})));
|
|
4942
|
+
}
|
|
4450
4943
|
;// ./node_modules/wavesurfer.js/dist/wavesurfer.esm.js
|
|
4451
4944
|
function t(t,e,i,n){return new(i||(i=Promise))((function(s,r){function o(t){try{l(n.next(t))}catch(t){r(t)}}function a(t){try{l(n.throw(t))}catch(t){r(t)}}function l(t){var e;t.done?s(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(o,a)}l((n=n.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class e{constructor(){this.listeners={}}on(t,e,i){if(this.listeners[t]||(this.listeners[t]=new Set),null==i?void 0:i.once){const i=(...n)=>{this.un(t,i),e(...n)};return this.listeners[t].add(i),()=>this.un(t,i)}return this.listeners[t].add(e),()=>this.un(t,e)}un(t,e){var i;null===(i=this.listeners[t])||void 0===i||i.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}const i={decode:function(e,i){return t(this,void 0,void 0,(function*(){const t=new AudioContext({sampleRate:i});try{return yield t.decodeAudioData(e)}finally{"closed"!==t.state&&(yield t.close().catch((()=>{})))}}))},createBuffer:function(t,e){if(!t||0===t.length)throw new Error("channelData must be a non-empty array");if(e<=0)throw new Error("duration must be greater than 0");if("number"==typeof t[0]&&(t=[t]),!t[0]||0===t[0].length)throw new Error("channelData must contain non-empty channel arrays");!function(t){const e=t[0];if(e.some((t=>t>1||t<-1))){const i=e.length;let n=0;for(let t=0;t<i;t++){const i=Math.abs(e[t]);i>n&&(n=i)}for(const e of t)for(let t=0;t<i;t++)e[t]/=n}}(t);const i=t.map((t=>t instanceof Float32Array?t:Float32Array.from(t)));return{duration:e,length:i[0].length,sampleRate:i[0].length/e,numberOfChannels:i.length,getChannelData:t=>{const e=i[t];if(!e)throw new Error(`Channel ${t} not found`);return e},copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};function n(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,s]of Object.entries(e))if("children"===t&&s)for(const[t,e]of Object.entries(s))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(n(t,e));else"style"===t?Object.assign(i.style,s):"textContent"===t?i.textContent=s:i.setAttribute(t,s.toString());return i}function s(t,e,i){const s=n(t,e||{});return null==i||i.appendChild(s),s}function r(t){return t instanceof HTMLElement||"object"==typeof t&&null!==t&&t.nodeType===Node.ELEMENT_NODE&&"object"==typeof t.style}var o=Object.freeze({__proto__:null,createElement:s,default:s,isHTMLElement:r});const a={fetchBlob:function(e,i,n){return t(this,void 0,void 0,(function*(){var s;const r=yield fetch(e,n);if(r.status>=400)throw new Error(`Failed to fetch ${e}: ${r.status} (${r.statusText})`);return function(e,i,n){t(this,void 0,void 0,(function*(){var t;if(!e.body||!e.headers)return;const s=e.body.getReader(),r=Number(e.headers.get("Content-Length"))||0;let o=0;const a=()=>{s.cancel()};if(n){if(n.aborted)return void s.cancel();n.addEventListener("abort",a,{once:!0})}try{for(;;){const e=yield s.read();if(e.done)break;if(o+=(null===(t=e.value)||void 0===t?void 0:t.length)||0,r>0){const t=Math.round(o/r*100);i(t)}}}catch(t){if(t instanceof DOMException&&"AbortError"===t.name)return;console.warn("Progress tracking error:",t)}finally{n&&n.removeEventListener("abort",a)}}))}(r.clone(),i,null!==(s=null==n?void 0:n.signal)&&void 0!==s?s:void 0),r.blob()}))}};function l(t){let e=t;const i=new Set;return{get value(){return e},set(t){Object.is(e,t)||(e=t,i.forEach((t=>t(e))))},update(t){this.set(t(e))},subscribe:t=>(i.add(t),()=>i.delete(t))}}function h(t,e){const i=l(t());return e.forEach((e=>e.subscribe((()=>{const e=t();Object.is(i.value,e)||i.set(e)})))),{get value(){return i.value},subscribe:t=>i.subscribe(t)}}function c(t,e){let i;const n=()=>{i&&(i(),i=void 0),i=t()},s=e.map((t=>t.subscribe(n)));return n(),()=>{i&&(i(),i=void 0),s.forEach((t=>t()))}}class u extends e{get isPlayingSignal(){return this._isPlaying}get currentTimeSignal(){return this._currentTime}get durationSignal(){return this._duration}get volumeSignal(){return this._volume}get mutedSignal(){return this._muted}get playbackRateSignal(){return this._playbackRate}get seekingSignal(){return this._seeking}constructor(t){super(),this.isExternalMedia=!1,this._ownBlobUrl=null,this.reactiveMediaEventCleanups=[],t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),this._isPlaying=l(!1),this._currentTime=l(0),this._duration=l(0),this._volume=l(this.media.volume),this._muted=l(this.media.muted),this._playbackRate=l(this.media.playbackRate||1),this._seeking=l(!1),this.setupReactiveMediaEvents(),t.mediaControls&&(this.media.controls=!0),t.autoplay&&(this.media.autoplay=!0),null!=t.playbackRate&&this.onMediaEvent("canplay",(()=>{null!=t.playbackRate&&(this.media.playbackRate=t.playbackRate)}),{once:!0})}setupReactiveMediaEvents(){this.reactiveMediaEventCleanups.push(this.onMediaEvent("play",(()=>{this._isPlaying.set(!0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("pause",(()=>{this._isPlaying.set(!1)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("ended",(()=>{this._isPlaying.set(!1)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("timeupdate",(()=>{this._currentTime.set(this.media.currentTime)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("durationchange",(()=>{this._duration.set(this.media.duration||0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("loadedmetadata",(()=>{this._duration.set(this.media.duration||0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("seeking",(()=>{this._seeking.set(!0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("seeked",(()=>{this._seeking.set(!1)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("volumechange",(()=>{this._volume.set(this.media.volume),this._muted.set(this.media.muted)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("ratechange",(()=>{this._playbackRate.set(this.media.playbackRate)})))}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e,i)}getSrc(){return this.media.currentSrc||this.media.src||""}revokeSrc(){this._ownBlobUrl&&(URL.revokeObjectURL(this._ownBlobUrl),this._ownBlobUrl=null)}canPlayType(t){return""!==this.media.canPlayType(t)}setSrc(t,e){const i=this.getSrc();if(t&&i===t)return;this.revokeSrc();const n=e instanceof Blob&&(this.canPlayType(e.type)||!t)?URL.createObjectURL(e):t;if(n!==t&&(this._ownBlobUrl=n),i&&this.media.removeAttribute("src"),n||t)try{this.media.src=n}catch(e){this.media.src=t}}destroy(){this.reactiveMediaEventCleanups.forEach((t=>t())),this.reactiveMediaEventCleanups=[],this.revokeSrc(),this.unAll(),this.isExternalMedia||(this.media.pause(),this.media.removeAttribute("src"),this.media.load(),this.media.remove())}setMediaElement(t){this.reactiveMediaEventCleanups.forEach((t=>t())),this.reactiveMediaEventCleanups=[],this.media=t,this.setupReactiveMediaEvents()}play(){return t(this,void 0,void 0,(function*(){try{return yield this.media.play()}catch(t){if(t instanceof DOMException&&"AbortError"===t.name)return;throw t}}))}pause(){this.media.pause()}isPlaying(){return!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=Math.max(0,Math.min(t,this.getDuration()))}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}isSeeking(){return this.media.seeking}setPlaybackRate(t,e){null!=e&&(this.media.preservesPitch=e),this.media.playbackRate=t}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}}function d({maxTop:t,maxBottom:e,halfHeight:i,vScale:n,barMinHeight:s=0,barAlign:r}){let o=Math.round(t*i*n);let a=o+Math.round(e*i*n)||1;return a<s&&(a=s,r||(o=a/2)),{topHeight:o,totalHeight:a}}function p({barAlign:t,halfHeight:e,topHeight:i,totalHeight:n,canvasHeight:s}){return"top"===t?0:"bottom"===t?s-n:e-i}function m(t,e,i){const n=e-t.left,s=i-t.top;return[n/t.width,s/t.height]}function g(t){return Boolean(t.barWidth||t.barGap||t.barAlign)}function f(t,e){if(!g(e))return t;const i=e.barWidth||.5,n=i+(e.barGap||i/2);return 0===n?t:Math.floor(t/n)*n}function v({scrollLeft:t,totalWidth:e,numCanvases:i}){if(0===e)return[0];const n=t/e,s=Math.floor(n*i);return[s-1,s,s+1]}function b(t){const e=t._cleanup;"function"==typeof e&&e()}function y(t){const e=l({scrollLeft:t.scrollLeft,scrollWidth:t.scrollWidth,clientWidth:t.clientWidth}),i=h((()=>function(t){const{scrollLeft:e,scrollWidth:i,clientWidth:n}=t;if(0===i)return{startX:0,endX:1};const s=e/i,r=(e+n)/i;return{startX:Math.max(0,Math.min(1,s)),endX:Math.max(0,Math.min(1,r))}}(e.value)),[e]),n=h((()=>function(t){return{left:t.scrollLeft,right:t.scrollLeft+t.clientWidth}}(e.value)),[e]),s=()=>{e.set({scrollLeft:t.scrollLeft,scrollWidth:t.scrollWidth,clientWidth:t.clientWidth})};t.addEventListener("scroll",s,{passive:!0});return{scrollData:e,percentages:i,bounds:n,cleanup:()=>{t.removeEventListener("scroll",s),b(e)}}}class C extends e{constructor(t,e){super(),this.timeouts=[],this.isScrollable=!1,this.audioData=null,this.resizeObserver=null,this.lastContainerWidth=0,this.isDragging=!1,this.subscriptions=[],this.unsubscribeOnScroll=[],this.dragStream=null,this.scrollStream=null,this.containerInlinePadding=0,this.onClickWrapper=t=>{const e=this.wrapper.getBoundingClientRect(),[i,n]=m(e,t.clientX,t.clientY);this.emit("click",i,n)},this.onDblClickWrapper=t=>{const e=this.wrapper.getBoundingClientRect(),[i,n]=m(e,t.clientX,t.clientY);this.emit("dblclick",i,n)},this.subscriptions=[],this.options=t;const i=this.parentFromOptionsContainer(t.container);this.parent=i;const[n,s]=this.initHtml();i.appendChild(n),this.container=n,this.scrollContainer=s.querySelector(".scroll"),this.wrapper=s.querySelector(".wrapper"),this.canvasWrapper=s.querySelector(".canvases"),this.progressWrapper=s.querySelector(".progress"),this.cursor=s.querySelector(".cursor"),this.calculateInlinePadding(),e&&s.appendChild(e),this.initEvents()}parentFromOptionsContainer(t){let e;if("string"==typeof t?e=document.querySelector(t):r(t)&&(e=t),!e)throw new Error("Container not found");return e}initEvents(){this.wrapper.addEventListener("click",this.onClickWrapper),this.wrapper.addEventListener("dblclick",this.onDblClickWrapper),!0!==this.options.dragToSeek&&"object"!=typeof this.options.dragToSeek||this.initDrag(),this.scrollStream=y(this.scrollContainer);const t=c((()=>{const{startX:t,endX:e}=this.scrollStream.percentages.value,{left:i,right:n}=this.scrollStream.bounds.value;this.emit("scroll",t,e,i,n)}),[this.scrollStream.percentages,this.scrollStream.bounds]);if(this.subscriptions.push(t),"function"==typeof ResizeObserver){const t=this.createDelay(100);this.resizeObserver=new ResizeObserver((()=>{t().then((()=>this.onContainerResize())).catch((()=>{}))})),this.resizeObserver.observe(this.scrollContainer)}}onContainerResize(){const t=this.parent.clientWidth;this.calculateInlinePadding(),t===this.lastContainerWidth&&"auto"!==this.options.height||(this.lastContainerWidth=t,this.reRender(),this.emit("resize"))}initDrag(){if(this.dragStream)return;this.dragStream=function(t,e={}){const{threshold:i=3,mouseButton:n=0,touchDelay:s=100}=e,r=l(null),o=new Map,a=matchMedia("(pointer: coarse)").matches;let h=()=>{};const c=e=>{if(e.button!==n)return;if(o.has(e.pointerId))return;if(o.set(e.pointerId,e),o.size>1)return;const l=e.pointerId;let c=e.clientX,u=e.clientY,d=!1;const p=Date.now(),m=t.getBoundingClientRect(),{left:g,top:f}=m,v=t=>{if(t.pointerId!==l)return;if(t.defaultPrevented||o.size>1)return;if(a&&Date.now()-p<s)return;const e=t.clientX,n=t.clientY,h=e-c,m=n-u;(d||Math.abs(h)>i||Math.abs(m)>i)&&(t.preventDefault(),t.stopPropagation(),d||(r.set({type:"start",x:c-g,y:u-f}),d=!0),r.set({type:"move",x:e-g,y:n-f,deltaX:h,deltaY:m}),c=e,u=n)},b=t=>{if(o.delete(t.pointerId)){if(t.pointerId===l&&d){const e=t.clientX,i=t.clientY;r.set({type:"end",x:e-g,y:i-f})}0===o.size&&h()}},y=t=>{t.relatedTarget&&t.relatedTarget!==document.documentElement||b(t)},C=t=>{d&&(t.stopPropagation(),t.preventDefault())},S=t=>{t.defaultPrevented||o.size>1||d&&t.preventDefault()};document.addEventListener("pointermove",v),document.addEventListener("pointerup",b),document.addEventListener("pointerout",y),document.addEventListener("pointercancel",y),document.addEventListener("touchmove",S,{passive:!1}),document.addEventListener("click",C,{capture:!0}),h=()=>{document.removeEventListener("pointermove",v),document.removeEventListener("pointerup",b),document.removeEventListener("pointerout",y),document.removeEventListener("pointercancel",y),document.removeEventListener("touchmove",S),setTimeout((()=>{document.removeEventListener("click",C,{capture:!0})}),10)}};return t.addEventListener("pointerdown",c),{signal:r,cleanup:()=>{h(),t.removeEventListener("pointerdown",c),o.clear(),b(r)}}}(this.wrapper);const t=c((()=>{const t=this.dragStream.signal.value;if(!t)return;const e=this.wrapper.getBoundingClientRect().width,i=(n=t.x/e)<0?0:n>1?1:n;var n;"start"===t.type?(this.isDragging=!0,this.emit("dragstart",i)):"move"===t.type?this.emit("drag",i):"end"===t.type&&(this.isDragging=!1,this.emit("dragend",i))}),[this.dragStream.signal]);this.subscriptions.push(t)}calculateInlinePadding(){const{paddingLeft:t,paddingRight:e}=getComputedStyle(this.scrollContainer),i=parseFloat(t)+parseFloat(e);this.containerInlinePadding=Number.isNaN(i)?0:i}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"}),i=this.options.cspNonce&&"string"==typeof this.options.cspNonce?this.options.cspNonce.replace(/"/g,""):"";return e.innerHTML=`\n <style${i?` nonce="${i}"`:""}>\n :host {\n user-select: none;\n min-width: 1px;\n }\n :host audio {\n display: block;\n width: 100%;\n }\n :host .scroll {\n overflow-x: auto;\n overflow-y: hidden;\n width: 100%;\n position: relative;\n }\n :host .noScrollbar {\n scrollbar-color: transparent;\n scrollbar-width: none;\n }\n :host .noScrollbar::-webkit-scrollbar {\n display: none;\n -webkit-appearance: none;\n }\n :host .wrapper {\n position: relative;\n overflow: visible;\n z-index: 2;\n }\n :host .canvases {\n min-height: ${this.getHeight(this.options.height,this.options.splitChannels)}px;\n pointer-events: none;\n }\n :host .canvases > div {\n position: relative;\n }\n :host canvas {\n display: block;\n position: absolute;\n top: 0;\n image-rendering: pixelated;\n }\n :host .progress {\n pointer-events: none;\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n overflow: hidden;\n }\n :host .progress > div {\n position: relative;\n }\n :host .cursor {\n pointer-events: none;\n position: absolute;\n z-index: 5;\n top: 0;\n left: 0;\n height: 100%;\n border-radius: 2px;\n }\n </style>\n\n <div class="scroll" part="scroll">\n <div class="wrapper" part="wrapper">\n <div class="canvases" part="canvases"></div>\n <div class="progress" part="progress"></div>\n <div class="cursor" part="cursor"></div>\n </div>\n </div>\n `,[t,e]}setOptions(t){var e;if(this.options.container!==t.container){const e=this.parentFromOptionsContainer(t.container);e.appendChild(this.container),this.parent=e}!0===t.dragToSeek||"object"==typeof this.options.dragToSeek?this.initDrag():(null===(e=this.dragStream)||void 0===e||e.cleanup(),this.dragStream=null),this.options=t,this.reRender()}getWrapper(){return this.wrapper}getWidth(){return this.scrollContainer.clientWidth-this.containerInlinePadding}getScroll(){return this.scrollContainer.scrollLeft}setScroll(t){this.scrollContainer.scrollLeft=t}setScrollPercentage(t){const{scrollWidth:e}=this.scrollContainer,i=e*t;this.setScroll(i)}destroy(){var t;this.wrapper.removeEventListener("click",this.onClickWrapper),this.wrapper.removeEventListener("dblclick",this.onDblClickWrapper),this.timeouts.forEach((t=>t())),this.timeouts=[],this.subscriptions.forEach((t=>t())),this.container.remove(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),null===(t=this.unsubscribeOnScroll)||void 0===t||t.forEach((t=>t())),this.unsubscribeOnScroll=[],this.dragStream&&(this.dragStream.cleanup(),this.dragStream=null),this.scrollStream&&(this.scrollStream.cleanup(),this.scrollStream=null)}createDelay(t=10){let e,i;const n=()=>{e&&(clearTimeout(e),e=void 0),i&&(i(),i=void 0)};return this.timeouts.push(n),()=>new Promise(((s,r)=>{n(),i=r,e=setTimeout((()=>{e=void 0,i=void 0,s()}),t)}))}getHeight(t,e){var i;const n=(null===(i=this.audioData)||void 0===i?void 0:i.numberOfChannels)||1;return function({optionsHeight:t,optionsSplitChannels:e,parentHeight:i,numberOfChannels:n,defaultHeight:s=128}){if(null==t)return s;const r=Number(t);if(!isNaN(r))return r;if("auto"===t){const t=i||s;return(null==e?void 0:e.every((t=>!t.overlay)))?t/n:t}return s}({optionsHeight:t,optionsSplitChannels:e,parentHeight:this.parent.clientHeight,numberOfChannels:n,defaultHeight:128})}convertColorValues(t,e){return function(t,e,i){if(!Array.isArray(t))return t||"";if(0===t.length)return"#999";if(t.length<2)return t[0]||"";const n=document.createElement("canvas"),s=n.getContext("2d");if(!s)return t[0]||"";const r=i||n.height*e,o=s.createLinearGradient(0,0,0,r),a=1/(t.length-1);return t.forEach(((t,e)=>{o.addColorStop(e*a,t)})),o}(t,this.getPixelRatio(),null==e?void 0:e.canvas.height)}getPixelRatio(){return t=window.devicePixelRatio,Math.max(1,t||1);// removed by dead control flow
|
|
4452
4945
|
var t; }renderBarWaveform(t,e,i,n){const{width:s,height:r}=i.canvas,{halfHeight:o,barWidth:a,barRadius:l,barIndexScale:h,barSpacing:c,barMinHeight:u}=function({width:t,height:e,length:i,options:n,pixelRatio:s}){const r=e/2,o=n.barWidth?n.barWidth*s:1,a=n.barGap?n.barGap*s:n.barWidth?o/2:0,l=o+a||1;return{halfHeight:r,barWidth:o,barGap:a,barRadius:n.barRadius||0,barMinHeight:n.barMinHeight?n.barMinHeight*s:0,barIndexScale:i>0?t/l/i:0,barSpacing:l}}({width:s,height:r,length:(t[0]||[]).length,options:e,pixelRatio:this.getPixelRatio()}),m=function({channelData:t,barIndexScale:e,barSpacing:i,barWidth:n,halfHeight:s,vScale:r,canvasHeight:o,barAlign:a,barMinHeight:l}){const h=t[0]||[],c=t[1]||h,u=h.length,m=[];let g=0,f=0,v=0;for(let t=0;t<=u;t++){const u=Math.round(t*e);if(u>g){const{topHeight:t,totalHeight:e}=d({maxTop:f,maxBottom:v,halfHeight:s,vScale:r,barMinHeight:l,barAlign:a}),h=p({barAlign:a,halfHeight:s,topHeight:t,totalHeight:e,canvasHeight:o});m.push({x:g*i,y:h,width:n,height:e}),g=u,f=0,v=0}const b=Math.abs(h[t]||0),y=Math.abs(c[t]||0);b>f&&(f=b),y>v&&(v=y)}return m}({channelData:t,barIndexScale:h,barSpacing:c,barWidth:a,halfHeight:o,vScale:n,canvasHeight:r,barAlign:e.barAlign,barMinHeight:u});i.beginPath();for(const t of m)l&&"roundRect"in i?i.roundRect(t.x,t.y,t.width,t.height,l):i.rect(t.x,t.y,t.width,t.height);i.fill(),i.closePath()}renderLineWaveform(t,e,i,n){const{width:s,height:r}=i.canvas,o=function({channelData:t,width:e,height:i,vScale:n}){const s=i/2,r=t[0]||[];return[r,t[1]||r].map(((t,i)=>{const r=t.length,o=r?e/r:0,a=s,l=0===i?-1:1,h=[{x:0,y:a}];let c=0,u=0;for(let e=0;e<=r;e++){const i=Math.round(e*o);if(i>c){const t=a+(Math.round(u*s*n)||1)*l;h.push({x:c,y:t}),c=i,u=0}const r=Math.abs(t[e]||0);r>u&&(u=r)}return h.push({x:c,y:a}),h}))}({channelData:t,width:s,height:r,vScale:n});i.beginPath();for(const t of o)if(t.length){i.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e++){const n=t[e];i.lineTo(n.x,n.y)}}i.fill(),i.closePath()}renderWaveform(t,e,i){if(i.fillStyle=this.convertColorValues(e.waveColor,i),e.renderFunction)return void e.renderFunction(t,i);const n=function({channelData:t,barHeight:e,normalize:i,maxPeak:n}){var s;const r=e||1;if(!i)return r;const o=t[0];if(!o||0===o.length)return r;let a=null!=n?n:0;if(!n)for(let t=0;t<o.length;t++){const e=null!==(s=o[t])&&void 0!==s?s:0,i=Math.abs(e);i>a&&(a=i)}return a?r/a:r}({channelData:t,barHeight:e.barHeight,normalize:e.normalize,maxPeak:e.maxPeak});g(e)?this.renderBarWaveform(t,e,i,n):this.renderLineWaveform(t,e,i,n)}renderSingleCanvas(t,e,i,n,s,r,o){const a=this.getPixelRatio(),l=document.createElement("canvas");l.width=Math.round(i*a),l.height=Math.round(n*a),l.style.width=`${i}px`,l.style.height=`${n}px`,l.style.left=`${Math.round(s)}px`,r.appendChild(l);const h=l.getContext("2d");if(e.renderFunction?(h.fillStyle=this.convertColorValues(e.waveColor,h),e.renderFunction(t,h)):this.renderWaveform(t,e,h),l.width>0&&l.height>0){const t=l.cloneNode(),i=t.getContext("2d");i.drawImage(l,0,0),i.globalCompositeOperation="source-in",i.fillStyle=this.convertColorValues(e.progressColor,i),i.fillRect(0,0,l.width,l.height),o.appendChild(t)}}renderMultiCanvas(t,e,i,n,s,r){const o=this.getPixelRatio(),{clientWidth:a}=this.scrollContainer,l=i/o,h=function({clientWidth:t,totalWidth:e,options:i}){return f(Math.min(8e3,t,e),i)}({clientWidth:a,totalWidth:l,options:e});let c={};if(0===h)return;const u=i=>{if(i<0||i>=d)return;if(c[i])return;c[i]=!0;const o=i*h;let a=Math.min(l-o,h);if(a=f(a,e),a<=0)return;const u=function({channelData:t,offset:e,clampedWidth:i,totalWidth:n}){return t.map((t=>{const s=Math.floor(e/n*t.length),r=Math.floor((e+i)/n*t.length);return t.slice(s,r)}))}({channelData:t,offset:o,clampedWidth:a,totalWidth:l});this.renderSingleCanvas(u,e,a,n,o,s,r)},d=Math.ceil(l/h);if(!this.isScrollable){for(let t=0;t<d;t++)u(t);return}if(v({scrollLeft:this.scrollContainer.scrollLeft,totalWidth:l,numCanvases:d}).forEach((t=>u(t))),d>1){const t=this.on("scroll",(()=>{const{scrollLeft:t}=this.scrollContainer;Object.keys(c).length>10&&(s.innerHTML="",r.innerHTML="",c={}),v({scrollLeft:t,totalWidth:l,numCanvases:d}).forEach((t=>u(t)))}));this.unsubscribeOnScroll.push(t)}}renderChannel(t,e,i,n){var{overlay:s}=e,r=function(t,e){var i={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&e.indexOf(n)<0&&(i[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(n=Object.getOwnPropertySymbols(t);s<n.length;s++)e.indexOf(n[s])<0&&Object.prototype.propertyIsEnumerable.call(t,n[s])&&(i[n[s]]=t[n[s]])}return i}(e,["overlay"]);const o=document.createElement("div"),a=this.getHeight(r.height,r.splitChannels);o.style.height=`${a}px`,s&&n>0&&(o.style.marginTop=`-${a}px`),this.canvasWrapper.style.minHeight=`${a}px`,this.canvasWrapper.appendChild(o);const l=o.cloneNode();this.progressWrapper.appendChild(l),this.renderMultiCanvas(t,r,i,a,o,l)}render(e){return t(this,void 0,void 0,(function*(){var t;this.timeouts.forEach((t=>t())),this.timeouts=[],this.unsubscribeOnScroll.forEach((t=>t())),this.unsubscribeOnScroll=[],this.canvasWrapper.innerHTML="",this.progressWrapper.innerHTML="",null!=this.options.width&&(this.scrollContainer.style.width="number"==typeof this.options.width?`${this.options.width}px`:this.options.width);const i=this.getPixelRatio(),n=this.scrollContainer.clientWidth-this.containerInlinePadding,{scrollWidth:s,isScrollable:r,useParentWidth:o,width:a}=function({duration:t,minPxPerSec:e=0,parentWidth:i,fillParent:n,pixelRatio:s}){const r=Math.ceil(t*e),o=r>i,a=Boolean(n&&!o);return{scrollWidth:r,isScrollable:o,useParentWidth:a,width:(a?i:r)*s}}({duration:e.duration,minPxPerSec:this.options.minPxPerSec||0,parentWidth:n,fillParent:this.options.fillParent,pixelRatio:i});if(this.isScrollable=r,this.wrapper.style.width=o?"100%":`${s}px`,this.scrollContainer.style.overflowX=this.isScrollable?"auto":"hidden",this.scrollContainer.classList.toggle("noScrollbar",!!this.options.hideScrollbar),this.cursor.style.backgroundColor=`${this.options.cursorColor||this.options.progressColor}`,this.cursor.style.width=`${this.options.cursorWidth}px`,this.audioData=e,this.emit("render"),this.options.splitChannels)for(let i=0;i<e.numberOfChannels;i++){const n=Object.assign(Object.assign({},this.options),null===(t=this.options.splitChannels)||void 0===t?void 0:t[i]);this.renderChannel([e.getChannelData(i)],n,a,i)}else{const t=[e.getChannelData(0)];e.numberOfChannels>1&&t.push(e.getChannelData(1)),this.renderChannel(t,this.options,a,0)}Promise.resolve().then((()=>this.emit("rendered")))}))}reRender(){if(this.unsubscribeOnScroll.forEach((t=>t())),this.unsubscribeOnScroll=[],!this.audioData)return;const{scrollWidth:t}=this.scrollContainer,{right:e}=this.progressWrapper.getBoundingClientRect();if(this.render(this.audioData),!this.isScrollable&&this.scrollContainer.scrollLeft)this.scrollContainer.scrollLeft=0;else if(this.isScrollable&&t!==this.scrollContainer.scrollWidth){const{right:t}=this.progressWrapper.getBoundingClientRect(),i=function(t){const e=2*t;return(e<0?Math.floor(e):Math.ceil(e))/2}(t-e);this.scrollContainer.scrollLeft+=i}}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){var i;const{scrollLeft:n,scrollWidth:s,clientWidth:r}=this.scrollContainer,o=t*s,a=n,l=n+r,h=r/2;if(this.isDragging){const t=30;o+t>l?this.scrollContainer.scrollLeft+=t:o-t<a&&(this.scrollContainer.scrollLeft-=t)}else{(o<a||o>l)&&(this.scrollContainer.scrollLeft=o-(this.options.autoCenter?h:0));const t=o-n-h;if(e&&this.options.autoCenter&&t>0){const e=null===(i=this.audioData)||void 0===i?void 0:i.duration;if(void 0===e||e<=0)return void(this.scrollContainer.scrollLeft+=t);const n=s/e;this.scrollContainer.scrollLeft+=n<=600?Math.min(t,10):t}}}renderProgress(t,e){if(isNaN(t))return;const i=100*t;this.canvasWrapper.style.clipPath=`polygon(${i}% 0%, 100% 0%, 100% 100%, ${i}% 100%)`,this.progressWrapper.style.width=`${i}%`,this.cursor.style.left=`${i}%`,this.cursor.style.transform=this.options.cursorWidth?`translateX(-${t*this.options.cursorWidth}px)`:"",this.isScrollable&&this.options.autoScroll&&this.audioData&&this.audioData.duration>0&&this.scrollIntoView(t,e)}exportImage(e,i,n){return t(this,void 0,void 0,(function*(){const t=this.canvasWrapper.querySelectorAll("canvas");if(!t.length)throw new Error("No waveform data");if("dataURL"===n){const n=Array.from(t).map((t=>t.toDataURL(e,i)));return Promise.resolve(n)}return Promise.all(Array.from(t).map((t=>new Promise(((n,s)=>{t.toBlob((t=>{t?n(t):s(new Error("Could not export image"))}),e,i)})))))}))}}class S extends e{constructor(){super(...arguments),this.animationFrameId=null,this.isRunning=!1}start(){if(this.isRunning)return;this.isRunning=!0;const t=()=>{this.isRunning&&(this.emit("tick"),this.animationFrameId=requestAnimationFrame(t))};t()}stop(){this.isRunning=!1,null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}destroy(){this.stop(),this.unAll()}}class E extends e{constructor(t){super(),this.bufferNode=null,this.playStartTime=0,this.playbackPosition=0,this._muted=!1,this._playbackRate=1,this._duration=void 0,this.buffer=null,this.currentSrc="",this.paused=!0,this.crossOrigin=null,this.seeking=!1,this.autoplay=!1,this.addEventListener=this.on,this.removeEventListener=this.un,this._destroyed=!1,function(){const t=globalThis.navigator;if(null==t?void 0:t.audioSession)try{t.audioSession.type="playback"}catch(t){console.warn("Setting navigator.audioSession.type failed:",t)}}(),this.audioContext=t||new AudioContext,this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination)}load(){return t(this,void 0,void 0,(function*(){}))}remove(){this.destroy()}destroy(){if(!this._destroyed){if(this._destroyed=!0,this.currentSrc="",this.bufferNode){this.bufferNode.onended=null;try{this.bufferNode.stop()}catch(t){}this.bufferNode.disconnect(),this.bufferNode=null}this.gainNode.disconnect(),"function"==typeof this.audioContext.close&&Promise.resolve(this.audioContext.close.call(this.audioContext)).catch((()=>{})),this.buffer=null,this.unAll()}}get src(){return this.currentSrc}set src(t){if(this.currentSrc=t,this._duration=void 0,!t)return this.buffer=null,void this.emit("emptied");fetch(t).then((e=>{if(e.status>=400)throw new Error(`Failed to fetch ${t}: ${e.status} (${e.statusText})`);return e.arrayBuffer()})).then((e=>this.currentSrc!==t?null:this.audioContext.decodeAudioData(e))).then((e=>{this.currentSrc===t&&(this.buffer=e,this.emit("loadedmetadata"),this.emit("canplay"),this.autoplay&&this.play())})).catch((t=>{console.error("WebAudioPlayer load error:",t)}))}_play(){if(!this.paused)return;this.paused=!1,this.bufferNode&&(this.bufferNode.onended=null,this.bufferNode.disconnect()),this.bufferNode=this.audioContext.createBufferSource(),this.buffer&&(this.bufferNode.buffer=this.buffer),this.bufferNode.playbackRate.value=this._playbackRate,this.bufferNode.connect(this.gainNode);let t=this.playbackPosition;(t>=this.duration||t<0)&&(t=0,this.playbackPosition=0),this.bufferNode.start(this.audioContext.currentTime,t),this.playStartTime=this.audioContext.currentTime,this.bufferNode.onended=()=>{!this.paused&&this.duration-this.currentTime<.01&&(this.pause(),this.emit("ended"))}}_pause(){if(this.paused=!0,this.bufferNode){this.bufferNode.onended=null;try{this.bufferNode.stop()}catch(t){}}this.playbackPosition+=(this.audioContext.currentTime-this.playStartTime)*this._playbackRate}play(){return t(this,void 0,void 0,(function*(){this.paused&&(this._play(),this.emit("play"))}))}pause(){this.paused||(this._pause(),this.emit("pause"))}stopAt(t){const e=(t-this.currentTime)/this._playbackRate,i=this.bufferNode;null==i||i.stop(this.audioContext.currentTime+e),null==i||i.addEventListener("ended",(()=>{i===this.bufferNode&&(this.bufferNode=null,this.pause(),this.playbackPosition=Math.min(t,this.duration),this.emit("timeupdate"))}),{once:!0})}setSinkId(e){return t(this,void 0,void 0,(function*(){return this.audioContext.setSinkId(e)}))}get playbackRate(){return this._playbackRate}set playbackRate(t){const e=!this.paused;e&&this._pause(),this._playbackRate=t,e&&this._play(),this.bufferNode&&(this.bufferNode.playbackRate.value=t)}get currentTime(){return this.paused?this.playbackPosition:this.playbackPosition+(this.audioContext.currentTime-this.playStartTime)*this._playbackRate}set currentTime(t){const e=!this.paused;e&&this._pause(),this.playbackPosition=t,e&&this._play(),this.emit("seeking"),this.emit("timeupdate")}get duration(){var t,e;return null!==(t=this._duration)&&void 0!==t?t:(null===(e=this.buffer)||void 0===e?void 0:e.duration)||0}set duration(t){this._duration=t}get volume(){return this.gainNode.gain.value}set volume(t){this.gainNode.gain.value=t,this.emit("volumechange")}get muted(){return this._muted}set muted(t){this._muted!==t&&(this._muted=t,this._muted?this.gainNode.disconnect():this.gainNode.connect(this.audioContext.destination))}canPlayType(t){return/^(audio|video)\//.test(t)}getGainNode(){return this.gainNode}getChannelData(){const t=[];if(!this.buffer)return t;const e=this.buffer.numberOfChannels;for(let i=0;i<e;i++)t.push(this.buffer.getChannelData(i));return t}removeAttribute(t){switch(t){case"src":this.src="";break;case"playbackRate":this.playbackRate=0;break;case"currentTime":this.currentTime=0;break;case"duration":this.duration=0;break;case"volume":this.volume=0;break;case"muted":this.muted=!1}}}const P={waveColor:"#999",progressColor:"#555",cursorWidth:1,minPxPerSec:0,fillParent:!0,interact:!0,dragToSeek:!1,autoScroll:!0,autoCenter:!0,sampleRate:8e3};class w extends u{static create(t){return new w(t)}getState(){return this.wavesurferState}getRenderer(){return this.renderer}constructor(t){const e=t.media||("WebAudio"===t.backend?new E:void 0);super({media:e,mediaControls:t.mediaControls,autoplay:t.autoplay,playbackRate:t.audioRate}),this.plugins=[],this.decodedData=null,this.stopAtPosition=null,this.subscriptions=[],this.mediaSubscriptions=[],this.abortController=null,this._isDestroyed=!1,this._loadVersion=0,this.reactiveCleanups=[],this.options=Object.assign({},P,t);const{state:i,actions:n}=function(t){var e,i,n,s,r,o;const a=null!==(e=null==t?void 0:t.currentTime)&&void 0!==e?e:l(0),c=null!==(i=null==t?void 0:t.duration)&&void 0!==i?i:l(0),u=null!==(n=null==t?void 0:t.isPlaying)&&void 0!==n?n:l(!1),d=null!==(s=null==t?void 0:t.isSeeking)&&void 0!==s?s:l(!1),p=null!==(r=null==t?void 0:t.volume)&&void 0!==r?r:l(1),m=null!==(o=null==t?void 0:t.playbackRate)&&void 0!==o?o:l(1),g=l(null),f=l(null),v=l(""),b=l(0),y=l(0),C=h((()=>!u.value),[u]),S=h((()=>null!==g.value),[g]),E=h((()=>S.value&&c.value>0),[S,c]),P=h((()=>a.value),[a]),w=h((()=>c.value>0?a.value/c.value:0),[a,c]);return{state:{currentTime:a,duration:c,isPlaying:u,isPaused:C,isSeeking:d,volume:p,playbackRate:m,audioBuffer:g,peaks:f,url:v,zoom:b,scrollPosition:y,canPlay:S,isReady:E,progress:P,progressPercent:w},actions:{setCurrentTime:t=>{const e=Math.max(0,Math.min(c.value||1/0,t));a.set(e)},setDuration:t=>{c.set(Math.max(0,t))},setPlaying:t=>{u.set(t)},setSeeking:t=>{d.set(t)},setVolume:t=>{const e=Math.max(0,Math.min(1,t));p.set(e)},setPlaybackRate:t=>{const e=Math.max(.1,Math.min(16,t));m.set(e)},setAudioBuffer:t=>{g.set(t),t&&c.set(t.duration)},setPeaks:t=>{f.set(t)},setUrl:t=>{v.set(t)},setZoom:t=>{b.set(Math.max(0,t))},setScrollPosition:t=>{y.set(Math.max(0,t))}}}}({isPlaying:this.isPlayingSignal,currentTime:this.currentTimeSignal,duration:this.durationSignal,volume:this.volumeSignal,playbackRate:this.playbackRateSignal,isSeeking:this.seekingSignal});this.wavesurferState=i,this.wavesurferActions=n,this.timer=new S;const s=e?void 0:this.getMediaElement();this.renderer=new C(this.options,s),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initReactiveState(),this.initPlugins();const r=this.options.url||this.getSrc()||"";Promise.resolve().then((()=>{this.emit("init");const{peaks:t,duration:e}=this.options;(r||t&&e)&&this.load(r,t,e).catch((()=>{}))}))}updateProgress(t=this.getCurrentTime()){return this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),t}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{if(!this.isSeeking()){const t=this.updateProgress();if(this.emit("timeupdate",t),this.emit("audioprocess",t),null!=this.stopAtPosition&&this.isPlaying()&&t>=this.stopAtPosition){const t=this.stopAtPosition;this.pause(),this.setTime(t)}}})))}initReactiveState(){this.reactiveCleanups.push(function(t,e){const i=[];i.push(c((()=>{const i=t.isPlaying.value;e.emit(i?"play":"pause")}),[t.isPlaying])),i.push(c((()=>{const i=t.currentTime.value;e.emit("timeupdate",i),t.isPlaying.value&&e.emit("audioprocess",i)}),[t.currentTime,t.isPlaying])),i.push(c((()=>{t.isSeeking.value&&e.emit("seeking",t.currentTime.value)}),[t.isSeeking,t.currentTime]));let n=!1;i.push(c((()=>{t.isReady.value&&!n&&(n=!0,e.emit("ready",t.duration.value))}),[t.isReady,t.duration])),i.push(c((()=>{null===t.audioBuffer.value&&(n=!1)}),[t.audioBuffer]));let s=!1;return i.push(c((()=>{const i=t.isPlaying.value,n=t.currentTime.value,r=t.duration.value,o=r>0&&n>=r;s&&!i&&o&&e.emit("finish"),s=i&&o}),[t.isPlaying,t.currentTime,t.duration])),i.push(c((()=>{const i=t.zoom.value;i>0&&e.emit("zoom",i)}),[t.zoom])),()=>{i.forEach((t=>t()))}}(this.wavesurferState,{emit:this.emit.bind(this)}))}initPlayerEvents(){this.isPlaying()&&(this.emit("play"),this.timer.start()),this.mediaSubscriptions.push(this.onMediaEvent("timeupdate",(()=>{const t=this.updateProgress();this.emit("timeupdate",t)})),this.onMediaEvent("play",(()=>{this.emit("play"),this.timer.start()})),this.onMediaEvent("pause",(()=>{this.emit("pause"),this.timer.stop(),this.stopAtPosition=null})),this.onMediaEvent("emptied",(()=>{this.timer.stop(),this.stopAtPosition=null})),this.onMediaEvent("ended",(()=>{this.emit("timeupdate",this.getDuration()),this.emit("finish"),this.stopAtPosition=null})),this.onMediaEvent("seeking",(()=>{this.emit("seeking",this.getCurrentTime())})),this.onMediaEvent("error",(()=>{var t;this.emit("error",null!==(t=this.getMediaElement().error)&&void 0!==t?t:new Error("Media error")),this.stopAtPosition=null})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",((t,e)=>{this.options.interact&&(this.seekTo(t),this.emit("interaction",t*this.getDuration()),this.emit("click",t,e))})),this.renderer.on("dblclick",((t,e)=>{this.emit("dblclick",t,e)})),this.renderer.on("scroll",((t,e,i,n)=>{const s=this.getDuration();this.emit("scroll",t*s,e*s,i,n)})),this.renderer.on("render",(()=>{this.emit("redraw")})),this.renderer.on("rendered",(()=>{this.emit("redrawcomplete")})),this.renderer.on("dragstart",(t=>{this.emit("dragstart",t)})),this.renderer.on("dragend",(t=>{this.emit("dragend",t)})),this.renderer.on("resize",(()=>{this.emit("resize")})));{let t;const e=this.renderer.on("drag",(e=>{var i;if(!this.options.interact)return;this.renderer.renderProgress(e),clearTimeout(t);let n=0;const s=this.options.dragToSeek;this.isPlaying()?n=0:!0===s?n=200:s&&"object"==typeof s&&(n=null!==(i=s.debounceTime)&&void 0!==i?i:200),t=setTimeout((()=>{this.seekTo(e)}),n),this.emit("interaction",e*this.getDuration()),this.emit("drag",e)}));this.subscriptions.push((()=>{clearTimeout(t),e()}))}}initPlugins(){var t;(null===(t=this.options.plugins)||void 0===t?void 0:t.length)&&this.options.plugins.forEach((t=>{this.registerPlugin(t)}))}unsubscribePlayerEvents(){this.mediaSubscriptions.forEach((t=>t())),this.mediaSubscriptions=[]}setOptions(t){this.options=Object.assign({},this.options,t),t.duration&&!t.peaks&&(this.decodedData=i.createBuffer(this.exportPeaks(),t.duration)),t.peaks&&t.duration&&(this.decodedData=i.createBuffer(t.peaks,t.duration)),this.renderer.setOptions(this.options),t.audioRate&&this.setPlaybackRate(t.audioRate),null!=t.mediaControls&&(this.getMediaElement().controls=t.mediaControls)}registerPlugin(t){if(this.plugins.includes(t))return t;t._init(this),this.plugins.push(t);const e=t.once("destroy",(()=>{this.plugins=this.plugins.filter((e=>e!==t)),this.subscriptions=this.subscriptions.filter((t=>t!==e))}));return this.subscriptions.push(e),t}unregisterPlugin(t){this.plugins=this.plugins.filter((e=>e!==t)),t.destroy()}getWrapper(){return this.renderer.getWrapper()}getWidth(){return this.renderer.getWidth()}getScroll(){return this.renderer.getScroll()}setScroll(t){return this.renderer.setScroll(t)}setScrollTime(t){const e=t/this.getDuration();this.renderer.setScrollPercentage(e)}getActivePlugins(){return this.plugins}loadAudio(e,n,s,r){return t(this,void 0,void 0,(function*(){var t;const o=++this._loadVersion;if(this._isDestroyed=!1,this.emit("load",e),!this.options.media&&this.isPlaying()&&this.pause(),this.decodedData=null,this.stopAtPosition=null,null===(t=this.abortController)||void 0===t||t.abort(),this.abortController=null,!n&&!s){const t=this.options.fetchParams||{};window.AbortController&&!t.signal&&(this.abortController=new AbortController,t.signal=this.abortController.signal);const i=t=>this.emit("loading",t);if(n=yield a.fetchBlob(e,i,t),this._isDestroyed||o!==this._loadVersion)return;const s=this.options.blobMimeType;s&&(n=new Blob([n],{type:s}))}if(this._isDestroyed||o!==this._loadVersion)return;this.setSrc(e,n);const l=yield new Promise((t=>{const e=r||this.getDuration();e?t(e):this.mediaSubscriptions.push(this.onMediaEvent("loadedmetadata",(()=>t(this.getDuration())),{once:!0}))}));if(!this._isDestroyed&&o===this._loadVersion){if(!e&&!n){const t=this.getMediaElement();t instanceof E&&(t.duration=l)}if(s)this.decodedData=i.createBuffer(s,l||0);else if(n){const t=yield n.arrayBuffer();if(this._isDestroyed||o!==this._loadVersion)return;this.decodedData=yield i.decode(t,this.options.sampleRate)}this._isDestroyed||o!==this._loadVersion||(this.decodedData&&(this.emit("decode",this.getDuration()),this.renderer.render(this.decodedData)),this.emit("ready",this.getDuration()))}}))}load(e,i,n){return t(this,void 0,void 0,(function*(){try{return yield this.loadAudio(e,void 0,i,n)}catch(t){throw this.emit("error",t),t}}))}loadBlob(e,i,n){return t(this,void 0,void 0,(function*(){try{return yield this.loadAudio("",e,i,n)}catch(t){throw this.emit("error",t),t}}))}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(t),this.emit("zoom",t)}getDecodedData(){return this.decodedData}exportPeaks({channels:t=2,maxLength:e=8e3,precision:i=1e4}={}){if(!this.decodedData)throw new Error("The audio has not been decoded yet");const n=Math.min(t,this.decodedData.numberOfChannels),s=[];for(let t=0;t<n;t++){const n=this.decodedData.getChannelData(t),r=[],o=n.length/e;for(let t=0;t<e;t++){const e=n.slice(Math.floor(t*o),Math.ceil((t+1)*o));let s=0;for(let t=0;t<e.length;t++){const i=e[t];Math.abs(i)>Math.abs(s)&&(s=i)}r.push(Math.round(s*i)/i)}s.push(r)}return s}getDuration(){let t=super.getDuration()||0;return 0!==t&&t!==1/0||!this.decodedData||(t=this.decodedData.duration),t}toggleInteraction(t){this.options.interact=t}setTime(t){this.stopAtPosition=null,super.setTime(t),this.updateProgress(t),this.emit("timeupdate",t)}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}play(e,i){const n=Object.create(null,{play:{get:()=>super.play}});return t(this,void 0,void 0,(function*(){null!=e&&this.setTime(e);const t=yield n.play.call(this);return null!=i&&(this.media instanceof E?this.media.stopAt(i):this.stopAtPosition=i),t}))}playPause(){return t(this,void 0,void 0,(function*(){return this.isPlaying()?this.pause():this.play()}))}stop(){this.pause(),this.setTime(0)}skip(t){this.setTime(this.getCurrentTime()+t)}empty(){this.load("",[[0]],.001)}setMediaElement(t){this.unsubscribePlayerEvents(),super.setMediaElement(t),this.initPlayerEvents()}exportImage(){return t(this,arguments,void 0,(function*(t="image/png",e=1,i="dataURL"){return this.renderer.exportImage(t,e,i)}))}destroy(){var t;this._isDestroyed=!0,this.emit("destroy"),null===(t=this.abortController)||void 0===t||t.abort(),this.plugins.forEach((t=>t.destroy())),this.subscriptions.forEach((t=>t())),this.unsubscribePlayerEvents(),this.reactiveCleanups.forEach((t=>t())),this.reactiveCleanups=[],this.timer.destroy(),this.renderer.destroy(),super.destroy()}}w.BasePlugin=class extends e{constructor(t){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=t}onInit(){}_init(t){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}},w.dom=o;
|
|
@@ -4792,9 +5285,9 @@ function usePlayheadCamera({
|
|
|
4792
5285
|
}
|
|
4793
5286
|
programmaticScrollRef.current = false;
|
|
4794
5287
|
});
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
5288
|
+
// Overlay always gets the live window. React scroll state only when not pinned,
|
|
5289
|
+
// so WaveformView does not re-render every follow frame.
|
|
5290
|
+
onViewportCommitRef.current(appliedScrollLeft, viewportRef.current, shouldCommitState);
|
|
4798
5291
|
}, [viewportRef, wavesurferRef]);
|
|
4799
5292
|
const pinFollowPlayhead = (0,external_react_.useCallback)((playhead, viewport, isPinned) => {
|
|
4800
5293
|
isFollowPinnedRef.current = isPinned;
|
|
@@ -4890,6 +5383,47 @@ function usePlayheadCamera({
|
|
|
4890
5383
|
const isFollowCameraScroll = isFollowPinnedRef.current && lastCameraScroll != null && Math.abs(scrollLeftPx - lastCameraScroll) <= 1;
|
|
4891
5384
|
return !(isCameraOwnedScroll && (jumpAnimationRef.current !== 0 || isFollowCameraScroll || isClampedToMax || !isFollowPinnedRef.current));
|
|
4892
5385
|
}, [viewportRef]);
|
|
5386
|
+
const seekTo = (0,external_react_.useCallback)(timeSec => {
|
|
5387
|
+
mediaTimeRef.current = timeSec;
|
|
5388
|
+
const wavesurfer = wavesurferRef.current;
|
|
5389
|
+
if (!wavesurfer) {
|
|
5390
|
+
return;
|
|
5391
|
+
}
|
|
5392
|
+
releaseUserPanHold();
|
|
5393
|
+
cancelJump();
|
|
5394
|
+
isFollowPinnedRef.current = false;
|
|
5395
|
+
const liveViewport = getViewportAtScroll(viewportRef.current, getScrollLeft(wavesurfer, viewportRef.current.scrollLeftPx));
|
|
5396
|
+
const action = getSeekCameraAction({
|
|
5397
|
+
timeSec,
|
|
5398
|
+
viewport: liveViewport
|
|
5399
|
+
});
|
|
5400
|
+
if (action.type !== 'jump') {
|
|
5401
|
+
return;
|
|
5402
|
+
}
|
|
5403
|
+
const from = liveViewport.scrollLeftPx;
|
|
5404
|
+
const to = action.scrollLeftPx;
|
|
5405
|
+
if (prefersReducedMotion() || typeof window.requestAnimationFrame !== 'function' || from === to) {
|
|
5406
|
+
applyScrollLeft(to, true);
|
|
5407
|
+
return;
|
|
5408
|
+
}
|
|
5409
|
+
programmaticScrollRef.current = true;
|
|
5410
|
+
const start = (0,util/* getCurrentTimeMs */.RU)();
|
|
5411
|
+
const tick = now => {
|
|
5412
|
+
const t = Math.min(1, (now - start) / constants/* WAVEFORM_PLAYHEAD_JUMP_MS */.Bq);
|
|
5413
|
+
applyScrollLeft(from + (to - from) * (1 - (1 - t) * (1 - t)), false);
|
|
5414
|
+
const playhead = playheadRef.current;
|
|
5415
|
+
if (playhead) {
|
|
5416
|
+
playhead.style.left = timeLeftPercent(mediaTimeRef.current, viewportRef.current.durationSec, viewportRef.current);
|
|
5417
|
+
}
|
|
5418
|
+
if (t < 1) {
|
|
5419
|
+
jumpAnimationRef.current = window.requestAnimationFrame(tick);
|
|
5420
|
+
return;
|
|
5421
|
+
}
|
|
5422
|
+
jumpAnimationRef.current = 0;
|
|
5423
|
+
applyScrollLeft(to, true);
|
|
5424
|
+
};
|
|
5425
|
+
jumpAnimationRef.current = window.requestAnimationFrame(tick);
|
|
5426
|
+
}, [applyScrollLeft, cancelJump, playheadRef, releaseUserPanHold, viewportRef, wavesurferRef]);
|
|
4893
5427
|
const handleScroll = (0,external_react_.useCallback)(onUserPan => {
|
|
4894
5428
|
const wavesurfer = wavesurferRef.current;
|
|
4895
5429
|
if (!wavesurfer) {
|
|
@@ -4935,7 +5469,8 @@ function usePlayheadCamera({
|
|
|
4935
5469
|
isFollowPinned,
|
|
4936
5470
|
onSeek,
|
|
4937
5471
|
onZoom,
|
|
4938
|
-
releaseUserPanHold
|
|
5472
|
+
releaseUserPanHold,
|
|
5473
|
+
seekTo
|
|
4939
5474
|
};
|
|
4940
5475
|
}
|
|
4941
5476
|
;// ./src/lib/viewers/media/waveform/WaveformView.scss
|
|
@@ -4977,6 +5512,15 @@ function applyPeaks(wavesurfer, peaks, durationSec) {
|
|
|
4977
5512
|
wavesurfer.load('', toChannels(peaks), durationSec);
|
|
4978
5513
|
}
|
|
4979
5514
|
|
|
5515
|
+
/** Stop the zoomed waveform from bouncing on trackpad overscroll. WaveSurfer's scroller is inside a shadow root, so SCSS uses `::part(scroll)` while zoomed and this sets the same property as soon as WaveSurfer exists. */
|
|
5516
|
+
function disableScrollOverscroll(container) {
|
|
5517
|
+
const host = container.firstElementChild;
|
|
5518
|
+
const scroll = host instanceof HTMLElement ? host.shadowRoot?.querySelector('.scroll') : null;
|
|
5519
|
+
if (scroll instanceof HTMLElement) {
|
|
5520
|
+
scroll.style.overscrollBehaviorX = 'none';
|
|
5521
|
+
}
|
|
5522
|
+
}
|
|
5523
|
+
|
|
4980
5524
|
/** Tint WaveSurfer's zoomed tiles with played/unplayed/hover/buffer colors. */
|
|
4981
5525
|
function tintZoomedWaveform(wavesurfer, fills, replaceSnapshot = false) {
|
|
4982
5526
|
const wrapper = wavesurfer.getWrapper ? wavesurfer.getWrapper() : null;
|
|
@@ -5054,6 +5598,9 @@ function WaveformView({
|
|
|
5054
5598
|
const pinchStartRef = (0,external_react_.useRef)(null);
|
|
5055
5599
|
const pointerZoomRef = (0,external_react_.useRef)(false);
|
|
5056
5600
|
const pointerZoomClearTimerRef = (0,external_react_.useRef)(0);
|
|
5601
|
+
const applyZoomWindowRef = (0,external_react_.useRef)(null);
|
|
5602
|
+
// WaveSurfer `setOptions` fires zoom/scroll before we apply the intended scroll.
|
|
5603
|
+
const suppressViewportSyncRef = (0,external_react_.useRef)(false);
|
|
5057
5604
|
const bufferProgressRef = (0,external_react_.useRef)(0);
|
|
5058
5605
|
const hoverProgressRef = (0,external_react_.useRef)(null);
|
|
5059
5606
|
onSeekRef.current = onSeek;
|
|
@@ -5091,9 +5638,11 @@ function WaveformView({
|
|
|
5091
5638
|
zoomLevel
|
|
5092
5639
|
}), [canvasWidthPx, durationSec, height, maxZoom, scrollLeft, zoomLevel]);
|
|
5093
5640
|
const viewportRef = (0,external_react_.useRef)(viewport); // live scroll window; prefer this over render-state while the camera is moving
|
|
5094
|
-
const onViewportCommit = (0,external_react_.useCallback)((scrollLeftPx, nextViewport) => {
|
|
5641
|
+
const onViewportCommit = (0,external_react_.useCallback)((scrollLeftPx, nextViewport, commitReactState = true) => {
|
|
5095
5642
|
onViewportChangeRef.current?.(nextViewport);
|
|
5096
|
-
|
|
5643
|
+
if (commitReactState) {
|
|
5644
|
+
setScrollLeft(scrollLeftPx);
|
|
5645
|
+
}
|
|
5097
5646
|
}, []);
|
|
5098
5647
|
const {
|
|
5099
5648
|
apply: applyPlayheadCamera,
|
|
@@ -5104,7 +5653,8 @@ function WaveformView({
|
|
|
5104
5653
|
isFollowPinned,
|
|
5105
5654
|
onSeek: onPlayheadSeek,
|
|
5106
5655
|
onZoom,
|
|
5107
|
-
releaseUserPanHold
|
|
5656
|
+
releaseUserPanHold,
|
|
5657
|
+
seekTo
|
|
5108
5658
|
} = usePlayheadCamera({
|
|
5109
5659
|
mediaElRef,
|
|
5110
5660
|
onViewportCommit,
|
|
@@ -5160,6 +5710,60 @@ function WaveformView({
|
|
|
5160
5710
|
wavesurfer.setTime(timeSec);
|
|
5161
5711
|
}
|
|
5162
5712
|
}, [isFollowPinned]);
|
|
5713
|
+
|
|
5714
|
+
// Same zoom-window body as the zoom effect; extracted so resize can call it too.
|
|
5715
|
+
const applyZoomWindow = (0,external_react_.useCallback)(() => {
|
|
5716
|
+
const wavesurfer = wavesurferRef.current;
|
|
5717
|
+
const container = containerRef.current;
|
|
5718
|
+
if (!wavesurfer || !wavesurfer.setOptions || !container) {
|
|
5719
|
+
return;
|
|
5720
|
+
}
|
|
5721
|
+
const viewWidthPx = wavesurfer.getWidth ? wavesurfer.getWidth() : container.clientWidth;
|
|
5722
|
+
const minPxPerSec = getZoomedPixelsPerSecond({
|
|
5723
|
+
durationSec,
|
|
5724
|
+
maxZoom,
|
|
5725
|
+
viewWidthPx,
|
|
5726
|
+
zoomLevel
|
|
5727
|
+
});
|
|
5728
|
+
const origin = zoomOriginRef.current;
|
|
5729
|
+
zoomOriginRef.current = null;
|
|
5730
|
+
const didZoomChange = prevZoomRef.current !== zoomLevel;
|
|
5731
|
+
if (origin || didZoomChange) {
|
|
5732
|
+
onZoom();
|
|
5733
|
+
}
|
|
5734
|
+
suppressViewportSyncRef.current = true;
|
|
5735
|
+
try {
|
|
5736
|
+
wavesurfer.setOptions(WaveformView_objectSpread({
|
|
5737
|
+
autoScroll: false,
|
|
5738
|
+
minPxPerSec
|
|
5739
|
+
}, zoomLevel > constants/* WAVEFORM_ZOOM_MIN */.LW ? {
|
|
5740
|
+
progressColor: WAVEFORM_COLOR_PLAYED,
|
|
5741
|
+
waveColor: WAVEFORM_COLOR_UNPLAYED
|
|
5742
|
+
} : {}));
|
|
5743
|
+
if (minPxPerSec > 0) {
|
|
5744
|
+
if (origin) {
|
|
5745
|
+
applyScrollLeft(origin.timeSec * minPxPerSec - origin.pointerX, true);
|
|
5746
|
+
} else if (didZoomChange && !pointerZoomRef.current) {
|
|
5747
|
+
const zoomedViewport = createWaveformViewport({
|
|
5748
|
+
durationSec,
|
|
5749
|
+
heightPx: height,
|
|
5750
|
+
maxZoom,
|
|
5751
|
+
scrollLeftPx: 0,
|
|
5752
|
+
widthPx: viewWidthPx,
|
|
5753
|
+
zoomLevel
|
|
5754
|
+
});
|
|
5755
|
+
applyScrollLeft(Math.min(maxScrollLeft(zoomedViewport), Math.max(0, currentTimeRef.current * minPxPerSec - viewWidthPx / 2)), true);
|
|
5756
|
+
}
|
|
5757
|
+
}
|
|
5758
|
+
wavesurfer.setTime(currentTimeRef.current);
|
|
5759
|
+
} finally {
|
|
5760
|
+
suppressViewportSyncRef.current = false;
|
|
5761
|
+
prevZoomRef.current = zoomLevel;
|
|
5762
|
+
}
|
|
5763
|
+
syncViewport();
|
|
5764
|
+
updatePlayheadPosition(currentTimeRef.current);
|
|
5765
|
+
}, [applyScrollLeft, durationSec, height, maxZoom, onZoom, syncViewport, updatePlayheadPosition, zoomLevel]);
|
|
5766
|
+
applyZoomWindowRef.current = applyZoomWindow;
|
|
5163
5767
|
(0,external_react_.useEffect)(() => {
|
|
5164
5768
|
const container = containerRef.current;
|
|
5165
5769
|
if (!container) {
|
|
@@ -5190,11 +5794,17 @@ function WaveformView({
|
|
|
5190
5794
|
onSeekRef.current?.(relativeX * durationSecRef.current);
|
|
5191
5795
|
});
|
|
5192
5796
|
const unsubscribeScroll = wavesurfer.on('scroll', () => {
|
|
5797
|
+
if (suppressViewportSyncRef.current) {
|
|
5798
|
+
return;
|
|
5799
|
+
}
|
|
5193
5800
|
handleCameraScroll(() => {
|
|
5194
5801
|
syncViewport();
|
|
5195
5802
|
});
|
|
5196
5803
|
});
|
|
5197
5804
|
const unsubscribeZoom = wavesurfer.on('zoom', () => {
|
|
5805
|
+
if (suppressViewportSyncRef.current) {
|
|
5806
|
+
return;
|
|
5807
|
+
}
|
|
5198
5808
|
syncViewport();
|
|
5199
5809
|
});
|
|
5200
5810
|
const unsubscribeRedraw = wavesurfer.on('redrawcomplete', () => {
|
|
@@ -5208,7 +5818,9 @@ function WaveformView({
|
|
|
5208
5818
|
});
|
|
5209
5819
|
wavesurferRef.current = wavesurfer;
|
|
5210
5820
|
displayedPeaksRef.current = peaksRef.current;
|
|
5821
|
+
disableScrollOverscroll(container);
|
|
5211
5822
|
syncViewport();
|
|
5823
|
+
applyZoomWindowRef.current?.();
|
|
5212
5824
|
return () => {
|
|
5213
5825
|
releaseUserPanHold();
|
|
5214
5826
|
cancelJump();
|
|
@@ -5248,7 +5860,8 @@ function WaveformView({
|
|
|
5248
5860
|
}
|
|
5249
5861
|
}, [internalZoom, isControlled, maxZoom, zoomLevelProp]);
|
|
5250
5862
|
(0,external_react_.useEffect)(() => {
|
|
5251
|
-
|
|
5863
|
+
// Follow skips React scrollLeft; emit the layout-refreshed live window instead.
|
|
5864
|
+
onViewportChange?.(viewportRef.current);
|
|
5252
5865
|
}, [onViewportChange, viewport]);
|
|
5253
5866
|
(0,external_react_.useEffect)(() => {
|
|
5254
5867
|
const wavesurfer = wavesurferRef.current;
|
|
@@ -5259,52 +5872,9 @@ function WaveformView({
|
|
|
5259
5872
|
interact: interactive
|
|
5260
5873
|
});
|
|
5261
5874
|
}, [interactive]);
|
|
5262
|
-
(0,external_react_.
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
if (!wavesurfer || !wavesurfer.setOptions || !container) {
|
|
5266
|
-
return;
|
|
5267
|
-
}
|
|
5268
|
-
const viewWidthPx = wavesurfer.getWidth ? wavesurfer.getWidth() : container.clientWidth;
|
|
5269
|
-
const minPxPerSec = getZoomedPixelsPerSecond({
|
|
5270
|
-
durationSec,
|
|
5271
|
-
maxZoom,
|
|
5272
|
-
viewWidthPx,
|
|
5273
|
-
zoomLevel
|
|
5274
|
-
});
|
|
5275
|
-
wavesurfer.setOptions(WaveformView_objectSpread({
|
|
5276
|
-
autoScroll: false,
|
|
5277
|
-
minPxPerSec
|
|
5278
|
-
}, zoomLevel > constants/* WAVEFORM_ZOOM_MIN */.LW ? {
|
|
5279
|
-
progressColor: WAVEFORM_COLOR_PLAYED,
|
|
5280
|
-
waveColor: WAVEFORM_COLOR_UNPLAYED
|
|
5281
|
-
} : {}));
|
|
5282
|
-
const origin = zoomOriginRef.current;
|
|
5283
|
-
zoomOriginRef.current = null;
|
|
5284
|
-
const didZoomChange = prevZoomRef.current !== zoomLevel;
|
|
5285
|
-
prevZoomRef.current = zoomLevel;
|
|
5286
|
-
if (origin || didZoomChange) {
|
|
5287
|
-
onZoom();
|
|
5288
|
-
}
|
|
5289
|
-
if (minPxPerSec > 0) {
|
|
5290
|
-
if (origin) {
|
|
5291
|
-
applyScrollLeft(origin.timeSec * minPxPerSec - origin.pointerX, true);
|
|
5292
|
-
} else if (didZoomChange && !pointerZoomRef.current) {
|
|
5293
|
-
const zoomedViewport = createWaveformViewport({
|
|
5294
|
-
durationSec,
|
|
5295
|
-
heightPx: height,
|
|
5296
|
-
maxZoom,
|
|
5297
|
-
scrollLeftPx: 0,
|
|
5298
|
-
widthPx: viewWidthPx,
|
|
5299
|
-
zoomLevel
|
|
5300
|
-
});
|
|
5301
|
-
applyScrollLeft(Math.min(maxScrollLeft(zoomedViewport), Math.max(0, currentTimeRef.current * minPxPerSec - viewWidthPx / 2)), true);
|
|
5302
|
-
}
|
|
5303
|
-
}
|
|
5304
|
-
wavesurfer.setTime(currentTimeRef.current);
|
|
5305
|
-
syncViewport();
|
|
5306
|
-
updatePlayheadPosition(currentTimeRef.current);
|
|
5307
|
-
}, [applyScrollLeft, durationSec, height, maxZoom, onZoom, syncViewport, updatePlayheadPosition, zoomLevel]);
|
|
5875
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
5876
|
+
applyZoomWindow();
|
|
5877
|
+
}, [applyZoomWindow]);
|
|
5308
5878
|
(0,external_react_.useLayoutEffect)(() => {
|
|
5309
5879
|
updatePlayheadPosition(mediaEl ? mediaEl.currentTime : currentTime);
|
|
5310
5880
|
}, [currentTime, durationSec, mediaEl, updatePlayheadPosition, viewport]);
|
|
@@ -5336,6 +5906,7 @@ function WaveformView({
|
|
|
5336
5906
|
};
|
|
5337
5907
|
const handleSeeked = () => {
|
|
5338
5908
|
onPlayheadSeek(media.currentTime);
|
|
5909
|
+
seekTo(media.currentTime);
|
|
5339
5910
|
updatePlayheadPosition(media.currentTime);
|
|
5340
5911
|
};
|
|
5341
5912
|
if (!media.paused) {
|
|
@@ -5354,7 +5925,7 @@ function WaveformView({
|
|
|
5354
5925
|
media.removeEventListener('pause', stopLoop);
|
|
5355
5926
|
media.removeEventListener('seeked', handleSeeked);
|
|
5356
5927
|
};
|
|
5357
|
-
}, [applyPlayheadCamera, cancelJump, clearFollowPin, mediaEl, onPlayheadSeek, releaseUserPanHold, syncViewport, updatePlayheadPosition]);
|
|
5928
|
+
}, [applyPlayheadCamera, cancelJump, clearFollowPin, mediaEl, onPlayheadSeek, releaseUserPanHold, seekTo, syncViewport, updatePlayheadPosition]);
|
|
5358
5929
|
(0,external_react_.useEffect)(() => {
|
|
5359
5930
|
const wavesurfer = wavesurferRef.current;
|
|
5360
5931
|
if (!wavesurfer || !wavesurfer.setOptions || !(durationSec > 0)) {
|
|
@@ -5530,6 +6101,7 @@ function WaveformView({
|
|
|
5530
6101
|
"data-testid": "bp-waveform-hover-time"
|
|
5531
6102
|
}, formatTime(hoverProgress * durationSec)))));
|
|
5532
6103
|
}
|
|
6104
|
+
/* harmony default export */ const waveform_WaveformView = (/*#__PURE__*/external_react_["default"].memo(WaveformView));
|
|
5533
6105
|
// EXTERNAL MODULE: ./node_modules/classnames/index.js
|
|
5534
6106
|
var classnames = __webpack_require__(2485);
|
|
5535
6107
|
var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
|
|
@@ -5680,15 +6252,18 @@ function WaveformZoomControl({
|
|
|
5680
6252
|
|
|
5681
6253
|
|
|
5682
6254
|
|
|
6255
|
+
|
|
5683
6256
|
const PLACEHOLDER_PEAKS = placeholderPeaks();
|
|
5684
6257
|
function MP3ControlsV2({
|
|
5685
6258
|
autoplay,
|
|
5686
6259
|
bufferedRange,
|
|
6260
|
+
commentMarkers,
|
|
5687
6261
|
currentTime,
|
|
5688
6262
|
durationTime,
|
|
5689
6263
|
isPlaying,
|
|
5690
6264
|
mediaEl,
|
|
5691
6265
|
onAutoplayChange,
|
|
6266
|
+
onCommentMarkerClick,
|
|
5692
6267
|
onMuteChange,
|
|
5693
6268
|
onPlayPause,
|
|
5694
6269
|
onRateChange,
|
|
@@ -5708,8 +6283,10 @@ function MP3ControlsV2({
|
|
|
5708
6283
|
const hasMetadata = durationValue > 0;
|
|
5709
6284
|
const waveformDurationSec = hasMetadata ? durationValue : PLACEHOLDER_DURATION_SEC;
|
|
5710
6285
|
const [playRequested, setPlayRequested] = (0,external_react_.useState)(false);
|
|
5711
|
-
const
|
|
5712
|
-
|
|
6286
|
+
const [viewport, setViewport] = (0,external_react_.useState)(null);
|
|
6287
|
+
const handleViewportChange = (0,external_react_.useCallback)(next => {
|
|
6288
|
+
setMaxZoom(prev => prev === next.maxZoom ? prev : next.maxZoom);
|
|
6289
|
+
setViewport(prev => viewportEquals(prev, next) ? prev : next);
|
|
5713
6290
|
}, []);
|
|
5714
6291
|
const revealZoomControl = (0,external_react_.useCallback)(() => {
|
|
5715
6292
|
setIsZoomRevealed(true);
|
|
@@ -5735,7 +6312,20 @@ function MP3ControlsV2({
|
|
|
5735
6312
|
const handlePlayOverlayClick = (0,external_react_.useCallback)(() => {
|
|
5736
6313
|
setPlayRequested(true);
|
|
5737
6314
|
onPlayPause(true);
|
|
5738
|
-
|
|
6315
|
+
// Overlay unmounts on click; without this, focus lands on body and Space is lost.
|
|
6316
|
+
mediaEl?.closest('.bp-media-container')?.focus();
|
|
6317
|
+
}, [mediaEl, onPlayPause]);
|
|
6318
|
+
const waveformMarkers = (0,external_react_.useMemo)(() => commentMarkers || [], [commentMarkers]);
|
|
6319
|
+
const selectedMarkerId = (0,external_react_.useMemo)(() => waveformMarkers.find(marker => marker.isSelected)?.id ?? null, [waveformMarkers]);
|
|
6320
|
+
const handleCommentMarkerClick = (0,external_react_.useCallback)(marker => {
|
|
6321
|
+
setPlayRequested(true);
|
|
6322
|
+
onPlayPause(false);
|
|
6323
|
+
if (onCommentMarkerClick) {
|
|
6324
|
+
onCommentMarkerClick(marker);
|
|
6325
|
+
return;
|
|
6326
|
+
}
|
|
6327
|
+
onTimeChange(marker.time);
|
|
6328
|
+
}, [onCommentMarkerClick, onPlayPause, onTimeChange]);
|
|
5739
6329
|
const isWaveformInteractive = playRequested && hasMetadata;
|
|
5740
6330
|
const isWaitingToPlay = playRequested && !hasMetadata;
|
|
5741
6331
|
const showPlayOverlay = !playRequested && !isPlaying;
|
|
@@ -5746,7 +6336,9 @@ function MP3ControlsV2({
|
|
|
5746
6336
|
"data-testid": "media-controls-wrapper-v2"
|
|
5747
6337
|
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5748
6338
|
className: "bp-MP3ControlsV2-stage"
|
|
5749
|
-
}, /*#__PURE__*/external_react_["default"].createElement(
|
|
6339
|
+
}, /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
6340
|
+
className: "bp-MP3ControlsV2-waveform"
|
|
6341
|
+
}, /*#__PURE__*/external_react_["default"].createElement(waveform_WaveformView, {
|
|
5750
6342
|
bufferedRange: bufferedRange,
|
|
5751
6343
|
currentTime: currentTime,
|
|
5752
6344
|
durationSec: waveformDurationSec,
|
|
@@ -5757,7 +6349,13 @@ function MP3ControlsV2({
|
|
|
5757
6349
|
onZoomChange: hasZoomHandlers ? handleWaveformZoom : undefined,
|
|
5758
6350
|
peaks: waveformPeaks,
|
|
5759
6351
|
zoomLevel: hasZoomHandlers ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW
|
|
5760
|
-
}),
|
|
6352
|
+
}), /*#__PURE__*/external_react_["default"].createElement(WaveformCommentMarkers, {
|
|
6353
|
+
commentMarkers: waveformMarkers,
|
|
6354
|
+
durationSec: hasMetadata ? durationValue : 0,
|
|
6355
|
+
onCommentMarkerClick: handleCommentMarkerClick,
|
|
6356
|
+
selectedId: selectedMarkerId,
|
|
6357
|
+
viewport: viewport
|
|
6358
|
+
})), hasZoomControl && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
5761
6359
|
className: "bp-MP3ControlsV2-waveformZoom"
|
|
5762
6360
|
}, /*#__PURE__*/external_react_["default"].createElement(WaveformZoomControl, {
|
|
5763
6361
|
isRevealed: isZoomRevealed,
|
|
@@ -5774,6 +6372,7 @@ function MP3ControlsV2({
|
|
|
5774
6372
|
},
|
|
5775
6373
|
"data-testid": "bp-MP3ControlsV2-play-overlay",
|
|
5776
6374
|
onClick: handlePlayOverlayClick,
|
|
6375
|
+
onMouseDown: event => event.preventDefault(),
|
|
5777
6376
|
title: "Play",
|
|
5778
6377
|
type: "button"
|
|
5779
6378
|
}), isWaitingToPlay && /*#__PURE__*/external_react_["default"].createElement("div", {
|
|
@@ -22321,7 +22920,7 @@ class Browser {
|
|
|
22321
22920
|
;// ./src/lib/Logger.js
|
|
22322
22921
|
/* eslint-disable no-undef */
|
|
22323
22922
|
const CLIENT_NAME = "box-content-preview";
|
|
22324
|
-
const CLIENT_VERSION = "3.
|
|
22923
|
+
const CLIENT_VERSION = "3.87.0";
|
|
22325
22924
|
/* eslint-enable no-undef */
|
|
22326
22925
|
|
|
22327
22926
|
class Logger {
|
|
@@ -35041,6 +35640,49 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35041
35640
|
this.startClientWaveformDecode();
|
|
35042
35641
|
}
|
|
35043
35642
|
});
|
|
35643
|
+
/**
|
|
35644
|
+
* Honor the requested play/pause state. The play button passes the next state;
|
|
35645
|
+
* comment markers pass false so a click always pauses instead of toggling.
|
|
35646
|
+
*
|
|
35647
|
+
* @param {boolean} shouldPlay
|
|
35648
|
+
* @return {void}
|
|
35649
|
+
*/
|
|
35650
|
+
MP3Viewer_defineProperty(this, "handlePlayPause", shouldPlay => {
|
|
35651
|
+
if (shouldPlay) {
|
|
35652
|
+
this.handlePlayRequest();
|
|
35653
|
+
return;
|
|
35654
|
+
}
|
|
35655
|
+
this.pause(undefined, true);
|
|
35656
|
+
});
|
|
35657
|
+
MP3Viewer_defineProperty(this, "handleCommentMarkersUpdated", (markers = []) => {
|
|
35658
|
+
this.commentMarkers = markers;
|
|
35659
|
+
const selected = markers.find(marker => marker.isSelected);
|
|
35660
|
+
const selectedId = selected ? selected.id : null;
|
|
35661
|
+
if (selectedId !== this.hostSelectedMarkerId) {
|
|
35662
|
+
this.hostSelectedMarkerId = selectedId;
|
|
35663
|
+
if (selected && Number.isFinite(selected.time)) {
|
|
35664
|
+
this.pendingHostSelectedSeek = selected;
|
|
35665
|
+
this.applyPendingHostSelectedSeek();
|
|
35666
|
+
} else {
|
|
35667
|
+
this.pendingHostSelectedSeek = null;
|
|
35668
|
+
}
|
|
35669
|
+
}
|
|
35670
|
+
this.renderUI();
|
|
35671
|
+
});
|
|
35672
|
+
MP3Viewer_defineProperty(this, "handleCommentMarkerClick", marker => {
|
|
35673
|
+
this.hostSelectedMarkerId = marker.id;
|
|
35674
|
+
this.pendingHostSelectedSeek = null;
|
|
35675
|
+
if (this.mediaEl) {
|
|
35676
|
+
this.mediaEl.pause();
|
|
35677
|
+
this.mediaEl.currentTime = marker.time;
|
|
35678
|
+
}
|
|
35679
|
+
// Overlay paints the ring from click optimism until the host re-emits selected.
|
|
35680
|
+
this.emit('comment_marker_select', {
|
|
35681
|
+
id: marker.id,
|
|
35682
|
+
time: marker.time
|
|
35683
|
+
});
|
|
35684
|
+
this.renderUI();
|
|
35685
|
+
});
|
|
35044
35686
|
/**
|
|
35045
35687
|
* Auto-play was prevented, pause the audio
|
|
35046
35688
|
*
|
|
@@ -35075,6 +35717,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35075
35717
|
// Audio element
|
|
35076
35718
|
this.mediaEl = this.mediaContainerEl.appendChild(document.createElement('audio'));
|
|
35077
35719
|
this.mediaEl.setAttribute('preload', 'auto');
|
|
35720
|
+
this.commentMarkers = [];
|
|
35078
35721
|
}
|
|
35079
35722
|
|
|
35080
35723
|
/**
|
|
@@ -35128,7 +35771,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35128
35771
|
* @return {Promise<{ default: Function }>} MP3ControlsV2 module
|
|
35129
35772
|
*/
|
|
35130
35773
|
importV2Controls() {
|
|
35131
|
-
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
35774
|
+
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 9286));
|
|
35132
35775
|
}
|
|
35133
35776
|
|
|
35134
35777
|
/**
|
|
@@ -35150,6 +35793,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35150
35793
|
* @inheritdoc
|
|
35151
35794
|
*/
|
|
35152
35795
|
destroy() {
|
|
35796
|
+
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
35153
35797
|
this.abortClientWaveformDecode();
|
|
35154
35798
|
super.destroy();
|
|
35155
35799
|
}
|
|
@@ -35201,6 +35845,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35201
35845
|
if (!this.isAudioPlayerV2) {
|
|
35202
35846
|
return;
|
|
35203
35847
|
}
|
|
35848
|
+
this.applyPendingHostSelectedSeek();
|
|
35204
35849
|
|
|
35205
35850
|
// Play first so Safari has a user gesture before AudioContext is created.
|
|
35206
35851
|
if (this.userRequestedPlay) {
|
|
@@ -35337,9 +35982,30 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35337
35982
|
containerEl: this.mediaContainerEl
|
|
35338
35983
|
});
|
|
35339
35984
|
}
|
|
35985
|
+
if (this.isAudioPlayerV2) {
|
|
35986
|
+
this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
35987
|
+
this.addListener('comment_markers', this.handleCommentMarkersUpdated);
|
|
35988
|
+
}
|
|
35340
35989
|
this.renderUI();
|
|
35341
35990
|
}
|
|
35342
|
-
|
|
35991
|
+
/**
|
|
35992
|
+
* Seek+pause to a host-selected comment (feed / deeplink). Audio-only; video does not
|
|
35993
|
+
* seek on comment_markers. No-ops until duration is known. Skips currentTime if the
|
|
35994
|
+
* element is already there so a feed seek does not fire a second `seeked`.
|
|
35995
|
+
*
|
|
35996
|
+
* @return {void}
|
|
35997
|
+
*/
|
|
35998
|
+
applyPendingHostSelectedSeek() {
|
|
35999
|
+
const marker = this.pendingHostSelectedSeek;
|
|
36000
|
+
if (!marker || !this.mediaEl || !(this.mediaEl.duration > 0) || !Number.isFinite(marker.time)) {
|
|
36001
|
+
return;
|
|
36002
|
+
}
|
|
36003
|
+
this.pendingHostSelectedSeek = null;
|
|
36004
|
+
this.mediaEl.pause();
|
|
36005
|
+
if (this.mediaEl.currentTime !== marker.time) {
|
|
36006
|
+
this.mediaEl.currentTime = marker.time;
|
|
36007
|
+
}
|
|
36008
|
+
}
|
|
35343
36009
|
/**
|
|
35344
36010
|
* @inheritdoc
|
|
35345
36011
|
*/
|
|
@@ -35356,7 +36022,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35356
36022
|
movePlayback: this.movePlayback,
|
|
35357
36023
|
onAutoplayChange: this.setAutoplay,
|
|
35358
36024
|
onMuteChange: this.toggleMute,
|
|
35359
|
-
onPlayPause: this.isAudioPlayerV2 ? this.
|
|
36025
|
+
onPlayPause: this.isAudioPlayerV2 ? this.handlePlayPause : this.togglePlay,
|
|
35360
36026
|
onRateChange: this.setRate,
|
|
35361
36027
|
onTimeChange: this.handleTimeupdateFromMediaControls,
|
|
35362
36028
|
onVolumeChange: this.setVolume,
|
|
@@ -35374,7 +36040,9 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
35374
36040
|
}
|
|
35375
36041
|
const Mp3ControlsV2 = this.MP3ControlsV2;
|
|
35376
36042
|
this.controls.render(/*#__PURE__*/external_react_["default"].createElement(Mp3ControlsV2, MP3Viewer_extends({}, sharedProps, {
|
|
36043
|
+
commentMarkers: this.commentMarkers || [],
|
|
35377
36044
|
mediaEl: this.mediaEl,
|
|
36045
|
+
onCommentMarkerClick: this.handleCommentMarkerClick,
|
|
35378
36046
|
peaks: this.waveformPeaks
|
|
35379
36047
|
})));
|
|
35380
36048
|
return;
|
|
@@ -37002,57 +37670,8 @@ function VideoControls({
|
|
|
37002
37670
|
}
|
|
37003
37671
|
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/TimestampControl.tsx + 1 modules
|
|
37004
37672
|
var TimestampControl = __webpack_require__(3904);
|
|
37005
|
-
|
|
37006
|
-
|
|
37007
|
-
return +value.toFixed(4);
|
|
37008
|
-
};
|
|
37009
|
-
const utils_percent = (value1, value2) => {
|
|
37010
|
-
return utils_round(value1 / value2 * 100);
|
|
37011
|
-
};
|
|
37012
|
-
;// ./src/lib/viewers/controls/media/buildClusters.ts
|
|
37013
|
-
|
|
37014
|
-
|
|
37015
|
-
/** Max pixel distance between adjacent markers (sorted by time) for them to be grouped into a single cluster. */
|
|
37016
|
-
const CLUSTER_THRESHOLD_PX = 2;
|
|
37017
|
-
|
|
37018
|
-
/** Converts a group of markers into a ClusterData object with computed positions and metadata. */
|
|
37019
|
-
function finalizeCluster(group, durationValue) {
|
|
37020
|
-
const leftPercent = utils_percent(group[0].time, durationValue);
|
|
37021
|
-
const rightPercent = utils_percent(group[group.length - 1].time, durationValue);
|
|
37022
|
-
const isSinglePoint = leftPercent === rightPercent;
|
|
37023
|
-
return {
|
|
37024
|
-
id: group.map(m => m.id).join('|'),
|
|
37025
|
-
isSinglePoint,
|
|
37026
|
-
leftPercent,
|
|
37027
|
-
markers: group,
|
|
37028
|
-
rightPercent
|
|
37029
|
-
};
|
|
37030
|
-
}
|
|
37031
|
-
|
|
37032
|
-
/**
|
|
37033
|
-
* Groups comment markers into clusters based on their pixel proximity on the scrubber track.
|
|
37034
|
-
* Markers are sorted by time, then chained: each marker that is within CLUSTER_THRESHOLD_PX
|
|
37035
|
-
* of its neighbor joins the same cluster. This means distant markers can end up in one cluster
|
|
37036
|
-
* if intermediate markers bridge the gap.
|
|
37037
|
-
*/
|
|
37038
|
-
function buildClusters(markers, durationValue, trackWidth, thresholdPx = CLUSTER_THRESHOLD_PX) {
|
|
37039
|
-
if (durationValue <= 0 || markers.length === 0 || trackWidth <= 0) return [];
|
|
37040
|
-
const sorted = [...markers].sort((a, b) => a.time - b.time);
|
|
37041
|
-
const clusters = [];
|
|
37042
|
-
let currentGroup = [sorted[0]];
|
|
37043
|
-
for (let i = 1; i < sorted.length; i += 1) {
|
|
37044
|
-
const prevPx = sorted[i - 1].time / durationValue * trackWidth;
|
|
37045
|
-
const currPx = sorted[i].time / durationValue * trackWidth;
|
|
37046
|
-
if (currPx - prevPx <= thresholdPx) {
|
|
37047
|
-
currentGroup.push(sorted[i]);
|
|
37048
|
-
} else {
|
|
37049
|
-
clusters.push(finalizeCluster(currentGroup, durationValue));
|
|
37050
|
-
currentGroup = [sorted[i]];
|
|
37051
|
-
}
|
|
37052
|
-
}
|
|
37053
|
-
clusters.push(finalizeCluster(currentGroup, durationValue));
|
|
37054
|
-
return clusters;
|
|
37055
|
-
}
|
|
37673
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/buildClusters.ts
|
|
37674
|
+
var buildClusters = __webpack_require__(2400);
|
|
37056
37675
|
// EXTERNAL MODULE: ./src/lib/viewers/media/formatTimecode.ts
|
|
37057
37676
|
var formatTimecode = __webpack_require__(4179);
|
|
37058
37677
|
;// ./src/lib/viewers/controls/media/FilmstripV2.scss
|
|
@@ -37133,156 +37752,8 @@ function FilmstripV2({
|
|
|
37133
37752
|
"data-testid": "bp-FilmstripV2-time"
|
|
37134
37753
|
}, fps ? (0,formatTimecode/* default */.A)(time, fps) : (0,DurationLabels/* formatTime */.f)(time)));
|
|
37135
37754
|
}
|
|
37136
|
-
|
|
37137
|
-
|
|
37138
|
-
|
|
37139
|
-
;// ./src/lib/viewers/controls/media/MarkerAvatar.tsx
|
|
37140
|
-
|
|
37141
|
-
|
|
37142
|
-
const AVATAR_PALETTE = [{
|
|
37143
|
-
bg: '#7fb0ea',
|
|
37144
|
-
fg: '#222'
|
|
37145
|
-
}, {
|
|
37146
|
-
bg: '#003c84',
|
|
37147
|
-
fg: '#fff'
|
|
37148
|
-
}, {
|
|
37149
|
-
bg: '#ffeb7f',
|
|
37150
|
-
fg: '#222'
|
|
37151
|
-
}, {
|
|
37152
|
-
bg: '#92e0c0',
|
|
37153
|
-
fg: '#222'
|
|
37154
|
-
}, {
|
|
37155
|
-
bg: '#fad98d',
|
|
37156
|
-
fg: '#222'
|
|
37157
|
-
}, {
|
|
37158
|
-
bg: '#91c2fd',
|
|
37159
|
-
fg: '#222'
|
|
37160
|
-
}, {
|
|
37161
|
-
bg: '#f69bab',
|
|
37162
|
-
fg: '#222'
|
|
37163
|
-
}, {
|
|
37164
|
-
bg: '#cf9ff6',
|
|
37165
|
-
fg: '#222'
|
|
37166
|
-
}, {
|
|
37167
|
-
bg: '#f8c08c',
|
|
37168
|
-
fg: '#222'
|
|
37169
|
-
}, {
|
|
37170
|
-
bg: '#a392e0',
|
|
37171
|
-
fg: '#222'
|
|
37172
|
-
}];
|
|
37173
|
-
function AnonymousAvatarIcon() {
|
|
37174
|
-
return /*#__PURE__*/external_react_["default"].createElement("svg", {
|
|
37175
|
-
"aria-hidden": "true",
|
|
37176
|
-
className: "bp-MarkerAvatar-anonymousIcon",
|
|
37177
|
-
focusable: "false",
|
|
37178
|
-
viewBox: "0 0 16 16"
|
|
37179
|
-
}, /*#__PURE__*/external_react_["default"].createElement("path", {
|
|
37180
|
-
d: "M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm0 1.5c-2.5 0-5 1.25-5 3.75V14h10v-.75c0-2.5-2.5-3.75-5-3.75Z",
|
|
37181
|
-
fill: "currentColor"
|
|
37182
|
-
}));
|
|
37183
|
-
}
|
|
37184
|
-
function MarkerAvatar({
|
|
37185
|
-
avatarUrl,
|
|
37186
|
-
colorIndex = 0,
|
|
37187
|
-
initial,
|
|
37188
|
-
size
|
|
37189
|
-
}) {
|
|
37190
|
-
const safeIndex = Number.isFinite(colorIndex) ? Math.abs(colorIndex) % AVATAR_PALETTE.length : 0;
|
|
37191
|
-
const {
|
|
37192
|
-
bg: bgColor,
|
|
37193
|
-
fg: textColor
|
|
37194
|
-
} = AVATAR_PALETTE[safeIndex];
|
|
37195
|
-
const [imgFailed, setImgFailed] = external_react_["default"].useState(false);
|
|
37196
|
-
const showImage = Boolean(avatarUrl) && !imgFailed;
|
|
37197
|
-
let avatar = /*#__PURE__*/external_react_["default"].createElement(AnonymousAvatarIcon, null);
|
|
37198
|
-
if (showImage) {
|
|
37199
|
-
avatar = /*#__PURE__*/external_react_["default"].createElement("img", {
|
|
37200
|
-
alt: "",
|
|
37201
|
-
onError: () => setImgFailed(true),
|
|
37202
|
-
src: avatarUrl
|
|
37203
|
-
});
|
|
37204
|
-
} else if (initial) {
|
|
37205
|
-
avatar = /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
37206
|
-
className: "bp-MarkerAvatar-initial",
|
|
37207
|
-
style: {
|
|
37208
|
-
color: textColor
|
|
37209
|
-
}
|
|
37210
|
-
}, initial);
|
|
37211
|
-
}
|
|
37212
|
-
const style = {};
|
|
37213
|
-
if (!showImage) {
|
|
37214
|
-
style.backgroundColor = bgColor;
|
|
37215
|
-
}
|
|
37216
|
-
if (size) {
|
|
37217
|
-
style.width = size;
|
|
37218
|
-
style.height = size;
|
|
37219
|
-
}
|
|
37220
|
-
return /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
37221
|
-
className: "bp-MarkerAvatar",
|
|
37222
|
-
style: Object.keys(style).length > 0 ? style : undefined
|
|
37223
|
-
}, avatar);
|
|
37224
|
-
}
|
|
37225
|
-
;// ./src/lib/viewers/controls/media/MarkerAvatarStack.scss
|
|
37226
|
-
// extracted by mini-css-extract-plugin
|
|
37227
|
-
|
|
37228
|
-
;// ./src/lib/viewers/controls/media/MarkerAvatarStack.tsx
|
|
37229
|
-
|
|
37230
|
-
|
|
37231
|
-
|
|
37232
|
-
const MAX_VISIBLE_AVATARS = 4;
|
|
37233
|
-
function MarkerAvatarStack({
|
|
37234
|
-
markers,
|
|
37235
|
-
onMarkerClick,
|
|
37236
|
-
overlapPx,
|
|
37237
|
-
selectedId,
|
|
37238
|
-
size
|
|
37239
|
-
}) {
|
|
37240
|
-
const hasOverflow = markers.length > MAX_VISIBLE_AVATARS;
|
|
37241
|
-
const visibleMarkers = hasOverflow ? markers.slice(0, MAX_VISIBLE_AVATARS - 1) : markers;
|
|
37242
|
-
const overflowMarkers = hasOverflow ? markers.slice(MAX_VISIBLE_AVATARS - 1) : [];
|
|
37243
|
-
const isOverflowSelected = overflowMarkers.some(marker => marker.id === selectedId);
|
|
37244
|
-
const style = overlapPx != null ? {
|
|
37245
|
-
'--bp-marker-stack-overlap': `-${overlapPx}px`
|
|
37246
|
-
} : undefined;
|
|
37247
|
-
return /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
37248
|
-
className: "bp-MarkerAvatarStack",
|
|
37249
|
-
style: style
|
|
37250
|
-
}, visibleMarkers.map(marker => /*#__PURE__*/external_react_["default"].createElement("button", {
|
|
37251
|
-
key: marker.id,
|
|
37252
|
-
"aria-label": "Comment marker",
|
|
37253
|
-
"aria-pressed": marker.id === selectedId,
|
|
37254
|
-
className: `bp-MarkerAvatarStack-item${marker.id === selectedId ? ' bp-MarkerAvatarStack-item--selected' : ''}`,
|
|
37255
|
-
"data-resin-target": "commentMarkerStackAvatar",
|
|
37256
|
-
onClick: e => {
|
|
37257
|
-
e.stopPropagation();
|
|
37258
|
-
onMarkerClick?.(marker);
|
|
37259
|
-
},
|
|
37260
|
-
type: "button"
|
|
37261
|
-
}, /*#__PURE__*/external_react_["default"].createElement(MarkerAvatar, {
|
|
37262
|
-
avatarUrl: marker.avatarUrl,
|
|
37263
|
-
colorIndex: marker.colorIndex,
|
|
37264
|
-
initial: marker.initial,
|
|
37265
|
-
size: size
|
|
37266
|
-
}))), hasOverflow && /*#__PURE__*/external_react_["default"].createElement("button", {
|
|
37267
|
-
"aria-label": "Comment marker",
|
|
37268
|
-
"aria-pressed": isOverflowSelected,
|
|
37269
|
-
className: `bp-MarkerAvatarStack-item bp-MarkerAvatarStack-overflow${isOverflowSelected ? ' bp-MarkerAvatarStack-item--selected' : ''}`,
|
|
37270
|
-
"data-resin-target": "commentMarkerStackAvatarOverflow",
|
|
37271
|
-
onClick: e => {
|
|
37272
|
-
e.stopPropagation();
|
|
37273
|
-
onMarkerClick?.(markers[MAX_VISIBLE_AVATARS - 1]);
|
|
37274
|
-
},
|
|
37275
|
-
type: "button"
|
|
37276
|
-
}, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
37277
|
-
className: "bp-MarkerAvatar bp-MarkerAvatarStack-overflowBadge",
|
|
37278
|
-
style: size ? {
|
|
37279
|
-
width: size,
|
|
37280
|
-
height: size
|
|
37281
|
-
} : undefined
|
|
37282
|
-
}, /*#__PURE__*/external_react_["default"].createElement("span", {
|
|
37283
|
-
className: "bp-MarkerAvatar-initial"
|
|
37284
|
-
}, "+", markers.length - (MAX_VISIBLE_AVATARS - 1)))));
|
|
37285
|
-
}
|
|
37755
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MarkerAvatarStack.tsx + 1 modules
|
|
37756
|
+
var MarkerAvatarStack = __webpack_require__(9232);
|
|
37286
37757
|
;// ./src/lib/viewers/controls/media/MarkerCluster.scss
|
|
37287
37758
|
// extracted by mini-css-extract-plugin
|
|
37288
37759
|
|
|
@@ -37316,11 +37787,13 @@ function MarkerCluster({
|
|
|
37316
37787
|
onMarkerClick?.(markers[0]);
|
|
37317
37788
|
},
|
|
37318
37789
|
type: "button"
|
|
37319
|
-
}), /*#__PURE__*/external_react_["default"].createElement(MarkerAvatarStack, {
|
|
37790
|
+
}), /*#__PURE__*/external_react_["default"].createElement(MarkerAvatarStack/* default */.A, {
|
|
37320
37791
|
markers: markers,
|
|
37321
37792
|
onMarkerClick: onMarkerClick
|
|
37322
37793
|
}));
|
|
37323
37794
|
}
|
|
37795
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/MarkerAvatar.tsx + 1 modules
|
|
37796
|
+
var MarkerAvatar = __webpack_require__(3524);
|
|
37324
37797
|
;// ./src/lib/viewers/controls/media/MarkerTick.tsx
|
|
37325
37798
|
|
|
37326
37799
|
|
|
@@ -37344,15 +37817,17 @@ function MarkerTick({
|
|
|
37344
37817
|
left: `${position}%`
|
|
37345
37818
|
},
|
|
37346
37819
|
type: "button"
|
|
37347
|
-
}, isGroup ? /*#__PURE__*/external_react_["default"].createElement(MarkerAvatarStack, {
|
|
37820
|
+
}, isGroup ? /*#__PURE__*/external_react_["default"].createElement(MarkerAvatarStack/* default */.A, {
|
|
37348
37821
|
markers: markers,
|
|
37349
37822
|
onMarkerClick: onMarkerClick
|
|
37350
|
-
}) : /*#__PURE__*/external_react_["default"].createElement(MarkerAvatar, {
|
|
37823
|
+
}) : /*#__PURE__*/external_react_["default"].createElement(MarkerAvatar/* default */.A, {
|
|
37351
37824
|
avatarUrl: markers[0].avatarUrl,
|
|
37352
37825
|
colorIndex: markers[0].colorIndex,
|
|
37353
37826
|
initial: markers[0].initial
|
|
37354
37827
|
}));
|
|
37355
37828
|
}
|
|
37829
|
+
// EXTERNAL MODULE: ./src/lib/viewers/controls/media/utils.ts
|
|
37830
|
+
var utils = __webpack_require__(5346);
|
|
37356
37831
|
;// ./src/lib/viewers/controls/media/TimeControlsV2.scss
|
|
37357
37832
|
// extracted by mini-css-extract-plugin
|
|
37358
37833
|
|
|
@@ -37390,9 +37865,9 @@ function TimeControlsV2({
|
|
|
37390
37865
|
const scrubberRef = external_react_["default"].useRef(null);
|
|
37391
37866
|
const currentValue = isFinite_default()(currentTime) ? currentTime : 0;
|
|
37392
37867
|
const durationValue = isFinite_default()(durationTime) ? durationTime : 0;
|
|
37393
|
-
const currentPercentage =
|
|
37868
|
+
const currentPercentage = (0,utils/* percent */.K)(currentValue, durationValue);
|
|
37394
37869
|
const bufferedAmount = bufferedRange && bufferedRange.length ? bufferedRange.end(bufferedRange.length - 1) : 0;
|
|
37395
|
-
const bufferedPercentage =
|
|
37870
|
+
const bufferedPercentage = (0,utils/* percent */.K)(bufferedAmount, durationValue);
|
|
37396
37871
|
external_react_["default"].useLayoutEffect(() => {
|
|
37397
37872
|
const el = scrubberRef.current;
|
|
37398
37873
|
if (!el) return undefined;
|
|
@@ -37405,7 +37880,7 @@ function TimeControlsV2({
|
|
|
37405
37880
|
observer.observe(el);
|
|
37406
37881
|
return () => observer.disconnect();
|
|
37407
37882
|
}, []);
|
|
37408
|
-
const clusters = external_react_["default"].useMemo(() => buildClusters(commentMarkers, durationValue, trackWidth), [commentMarkers, durationValue, trackWidth]);
|
|
37883
|
+
const clusters = external_react_["default"].useMemo(() => (0,buildClusters/* default */.A)(commentMarkers, durationValue, trackWidth), [commentMarkers, durationValue, trackWidth]);
|
|
37409
37884
|
const trackMask = external_react_["default"].useMemo(() => {
|
|
37410
37885
|
if (durationValue <= 0 || clusters.length === 0) return undefined;
|
|
37411
37886
|
const HALF_GAP = 2;
|