box-content-preview 3.84.0 → 3.85.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.js +436 -60
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://mergify.io)
|
|
3
3
|
[](https://github.com/prettier/prettier)
|
|
4
4
|
[](https://travis-ci.org/box/box-content-preview)
|
|
5
|
-
[](https://github.com/box/box-content-preview)
|
|
6
6
|
[](https://www.npmjs.com/package/box-ui-elements)
|
|
7
7
|
|
|
8
8
|
# [Box Content Preview](https://developer.box.com/docs/box-content-preview)
|
|
@@ -22,11 +22,11 @@ We encourage all users to update their applications to utilize modern browsers f
|
|
|
22
22
|
|
|
23
23
|
## Current Version
|
|
24
24
|
|
|
25
|
-
- Version: v3.
|
|
25
|
+
- Version: v3.85.0
|
|
26
26
|
- Locale: en-US
|
|
27
27
|
|
|
28
|
-
https://cdn01.boxcdn.net/platform/preview/3.
|
|
29
|
-
https://cdn01.boxcdn.net/platform/preview/3.
|
|
28
|
+
https://cdn01.boxcdn.net/platform/preview/3.85.0/en-US/preview.js
|
|
29
|
+
https://cdn01.boxcdn.net/platform/preview/3.85.0/en-US/preview.css
|
|
30
30
|
|
|
31
31
|
## Supported Locales
|
|
32
32
|
|
|
@@ -52,10 +52,10 @@ You can self-host the Box Content Preview library or reference the versions avai
|
|
|
52
52
|
<title>Box Content Preview Demo</title>
|
|
53
53
|
|
|
54
54
|
<!-- Latest version of Preview SDK for your locale -->
|
|
55
|
-
<script src="https://cdn01.boxcdn.net/platform/preview/3.
|
|
55
|
+
<script src="https://cdn01.boxcdn.net/platform/preview/3.85.0/en-US/preview.js"></script>
|
|
56
56
|
<link
|
|
57
57
|
rel="stylesheet"
|
|
58
|
-
href="https://cdn01.boxcdn.net/platform/preview/3.
|
|
58
|
+
href="https://cdn01.boxcdn.net/platform/preview/3.85.0/en-US/preview.css"
|
|
59
59
|
/>
|
|
60
60
|
</head>
|
|
61
61
|
<body>
|
|
@@ -76,7 +76,7 @@ To self-host the Box Content Preview library, follow these steps:
|
|
|
76
76
|
|
|
77
77
|
1. Either fork the repo and check out the version you want to host or download the specific version as a zip:
|
|
78
78
|
|
|
79
|
-
- Check out a specific version with `git checkout v3.
|
|
79
|
+
- Check out a specific version with `git checkout v3.85.0`
|
|
80
80
|
- Download a specific version as a zip from https://github.com/box/box-content-preview/releases
|
|
81
81
|
|
|
82
82
|
2. Install dependencies and build the library with `yarn install && yarn build:i18n && yarn build:prod`
|
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.85.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 = {};
|
|
@@ -4118,7 +4118,7 @@ function getPdfjsWorkerSrc() {
|
|
|
4118
4118
|
|
|
4119
4119
|
/***/ },
|
|
4120
4120
|
|
|
4121
|
-
/***/
|
|
4121
|
+
/***/ 3678
|
|
4122
4122
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
4123
4123
|
|
|
4124
4124
|
|
|
@@ -4249,6 +4249,7 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
|
|
|
4249
4249
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
4250
4250
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4251
4251
|
|
|
4252
|
+
/** Visible window: start/end times, pixels-per-second, and the current zoom. */
|
|
4252
4253
|
function createWaveformViewport({
|
|
4253
4254
|
durationSec,
|
|
4254
4255
|
heightPx,
|
|
@@ -4356,6 +4357,96 @@ function zoomFromSliderValue(value, maxZoom = constants/* WAVEFORM_ZOOM_MIN */.L
|
|
|
4356
4357
|
const t = Math.min(constants/* WAVEFORM_ZOOM_SLIDER_MAX */.nh, Math.max(0, value)) / constants/* WAVEFORM_ZOOM_SLIDER_MAX */.nh;
|
|
4357
4358
|
return clampWaveformZoom(constants/* WAVEFORM_ZOOM_MIN */.LW + t * (max - constants/* WAVEFORM_ZOOM_MIN */.LW), max);
|
|
4358
4359
|
}
|
|
4360
|
+
|
|
4361
|
+
/** Max scroll that still shows a full window (no overscroll). */
|
|
4362
|
+
function maxScrollLeft(viewport) {
|
|
4363
|
+
return Math.max(0, viewport.durationSec * viewport.pixelsPerSecond - viewport.widthPx);
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
/** Scroll offset that still shows a full window (no overscroll). */
|
|
4367
|
+
function clampScrollLeft(scrollLeftPx, viewport) {
|
|
4368
|
+
if (!Number.isFinite(scrollLeftPx)) {
|
|
4369
|
+
return 0;
|
|
4370
|
+
}
|
|
4371
|
+
return Math.min(maxScrollLeft(viewport), Math.max(0, scrollLeftPx));
|
|
4372
|
+
}
|
|
4373
|
+
|
|
4374
|
+
/** Follow inset in CSS px, capped at one third of the view so a narrow player still has room. */
|
|
4375
|
+
function getFollowInsetPx(widthPx, insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM) {
|
|
4376
|
+
if (!(widthPx > 0)) {
|
|
4377
|
+
return 0;
|
|
4378
|
+
}
|
|
4379
|
+
return Math.min(Math.max(0, insetPx), widthPx / 3);
|
|
4380
|
+
}
|
|
4381
|
+
|
|
4382
|
+
/** CSS left for a playhead pinned to the follow inset. */
|
|
4383
|
+
function getPinnedPlayheadLeft(widthPx, insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM) {
|
|
4384
|
+
const inset = getFollowInsetPx(widthPx, insetPx);
|
|
4385
|
+
if (!(widthPx > 0)) {
|
|
4386
|
+
return '0%';
|
|
4387
|
+
}
|
|
4388
|
+
return `${(widthPx - inset) / widthPx * 100}%`;
|
|
4389
|
+
}
|
|
4390
|
+
|
|
4391
|
+
/** CSS left % of the playhead from the left of the visible window. */
|
|
4392
|
+
function timeLeftPercent(timeSec, durationSec, viewport) {
|
|
4393
|
+
if (viewport.widthPx > 0 && viewport.pixelsPerSecond > 0) {
|
|
4394
|
+
return `${positionPxFromTime(timeSec, viewport) / viewport.widthPx * 100}%`;
|
|
4395
|
+
}
|
|
4396
|
+
const progress = durationSec > 0 ? Math.min(1, Math.max(0, timeSec / durationSec)) : 0;
|
|
4397
|
+
return `${progress * 100}%`;
|
|
4398
|
+
}
|
|
4399
|
+
|
|
4400
|
+
/**
|
|
4401
|
+
* Walk across the view until the playhead nears the right edge, then follow.
|
|
4402
|
+
* Off-screen at play start jumps in; off-screen right while playing keeps following.
|
|
4403
|
+
*/
|
|
4404
|
+
function getPlayheadCameraAction({
|
|
4405
|
+
insetPx = constants/* WAVEFORM_FOLLOW_INSET_PX */.NM,
|
|
4406
|
+
isPlaying,
|
|
4407
|
+
playJustStarted,
|
|
4408
|
+
timeSec,
|
|
4409
|
+
viewport
|
|
4410
|
+
}) {
|
|
4411
|
+
if (!isPlaying || viewport.zoomLevel <= constants/* WAVEFORM_ZOOM_MIN */.LW || !(viewport.widthPx > 0) || !(viewport.pixelsPerSecond > 0)) {
|
|
4412
|
+
return {
|
|
4413
|
+
type: 'none'
|
|
4414
|
+
};
|
|
4415
|
+
}
|
|
4416
|
+
const inset = getFollowInsetPx(viewport.widthPx, insetPx);
|
|
4417
|
+
const viewX = positionPxFromTime(timeSec, viewport);
|
|
4418
|
+
const playheadCanvasX = timeSec * viewport.pixelsPerSecond;
|
|
4419
|
+
const followX = viewport.widthPx - inset;
|
|
4420
|
+
if (viewX < 0) {
|
|
4421
|
+
if (!playJustStarted) {
|
|
4422
|
+
return {
|
|
4423
|
+
type: 'none'
|
|
4424
|
+
};
|
|
4425
|
+
}
|
|
4426
|
+
return {
|
|
4427
|
+
type: 'jump',
|
|
4428
|
+
scrollLeftPx: clampScrollLeft(playheadCanvasX - inset, viewport)
|
|
4429
|
+
};
|
|
4430
|
+
}
|
|
4431
|
+
if (viewX >= followX) {
|
|
4432
|
+
const unclampedScroll = playheadCanvasX - followX;
|
|
4433
|
+
const scrollLeftPx = clampScrollLeft(unclampedScroll, viewport);
|
|
4434
|
+
if (playJustStarted && viewX > viewport.widthPx) {
|
|
4435
|
+
return {
|
|
4436
|
+
type: 'jump',
|
|
4437
|
+
scrollLeftPx
|
|
4438
|
+
};
|
|
4439
|
+
}
|
|
4440
|
+
return {
|
|
4441
|
+
type: 'followRight',
|
|
4442
|
+
isPlayheadPinned: unclampedScroll <= maxScrollLeft(viewport),
|
|
4443
|
+
scrollLeftPx
|
|
4444
|
+
};
|
|
4445
|
+
}
|
|
4446
|
+
return {
|
|
4447
|
+
type: 'none'
|
|
4448
|
+
};
|
|
4449
|
+
}
|
|
4359
4450
|
;// ./node_modules/wavesurfer.js/dist/wavesurfer.esm.js
|
|
4360
4451
|
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
|
|
4361
4452
|
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;
|
|
@@ -4612,6 +4703,241 @@ function tintWaveformTiles({
|
|
|
4612
4703
|
});
|
|
4613
4704
|
});
|
|
4614
4705
|
}
|
|
4706
|
+
;// ./src/lib/viewers/media/waveform/usePlayheadCamera.ts
|
|
4707
|
+
|
|
4708
|
+
|
|
4709
|
+
|
|
4710
|
+
|
|
4711
|
+
function getScrollLeft(wavesurfer, fallback = 0) {
|
|
4712
|
+
return wavesurfer && wavesurfer.getScroll ? wavesurfer.getScroll() : fallback;
|
|
4713
|
+
}
|
|
4714
|
+
function prefersReducedMotion() {
|
|
4715
|
+
return typeof window !== 'undefined' && typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
4716
|
+
}
|
|
4717
|
+
/**
|
|
4718
|
+
* Pin/follow vs user pan. Refs, not state: rAF and WaveSurfer `scroll` read these
|
|
4719
|
+
* every frame. WaveformView owns WaveSurfer, zoom, and the media rAF loop.
|
|
4720
|
+
*/
|
|
4721
|
+
function usePlayheadCamera({
|
|
4722
|
+
mediaElRef,
|
|
4723
|
+
onViewportCommit,
|
|
4724
|
+
playheadRef,
|
|
4725
|
+
viewportRef,
|
|
4726
|
+
wavesurferRef
|
|
4727
|
+
}) {
|
|
4728
|
+
const onViewportCommitRef = (0,external_react_.useRef)(onViewportCommit);
|
|
4729
|
+
onViewportCommitRef.current = onViewportCommit;
|
|
4730
|
+
const programmaticScrollRef = (0,external_react_.useRef)(false);
|
|
4731
|
+
const jumpAnimationRef = (0,external_react_.useRef)(0);
|
|
4732
|
+
const lastCameraScrollRef = (0,external_react_.useRef)(null);
|
|
4733
|
+
const mediaTimeRef = (0,external_react_.useRef)(0);
|
|
4734
|
+
const isFollowPinnedRef = (0,external_react_.useRef)(false);
|
|
4735
|
+
const userIsScrollingRef = (0,external_react_.useRef)(false);
|
|
4736
|
+
const holdFollowUntilInsetRef = (0,external_react_.useRef)(false);
|
|
4737
|
+
const scrollSettleTimerRef = (0,external_react_.useRef)(0);
|
|
4738
|
+
const applyRef = (0,external_react_.useRef)(null);
|
|
4739
|
+
const isFollowPinned = (0,external_react_.useCallback)(() => isFollowPinnedRef.current, []);
|
|
4740
|
+
const cancelJump = (0,external_react_.useCallback)(() => {
|
|
4741
|
+
if (!jumpAnimationRef.current) {
|
|
4742
|
+
return;
|
|
4743
|
+
}
|
|
4744
|
+
window.cancelAnimationFrame(jumpAnimationRef.current);
|
|
4745
|
+
jumpAnimationRef.current = 0;
|
|
4746
|
+
}, []);
|
|
4747
|
+
const clearFollowPin = (0,external_react_.useCallback)(() => {
|
|
4748
|
+
isFollowPinnedRef.current = false;
|
|
4749
|
+
programmaticScrollRef.current = false;
|
|
4750
|
+
}, []);
|
|
4751
|
+
const releaseUserPanHold = (0,external_react_.useCallback)(() => {
|
|
4752
|
+
window.clearTimeout(scrollSettleTimerRef.current);
|
|
4753
|
+
scrollSettleTimerRef.current = 0;
|
|
4754
|
+
userIsScrollingRef.current = false;
|
|
4755
|
+
holdFollowUntilInsetRef.current = false;
|
|
4756
|
+
}, []);
|
|
4757
|
+
const readMediaTime = (0,external_react_.useCallback)(() => {
|
|
4758
|
+
const live = mediaElRef.current?.currentTime;
|
|
4759
|
+
if (typeof live === 'number' && Number.isFinite(live)) {
|
|
4760
|
+
mediaTimeRef.current = live;
|
|
4761
|
+
return live;
|
|
4762
|
+
}
|
|
4763
|
+
return mediaTimeRef.current;
|
|
4764
|
+
}, [mediaElRef]);
|
|
4765
|
+
const onSeek = (0,external_react_.useCallback)(timeSec => {
|
|
4766
|
+
mediaTimeRef.current = timeSec;
|
|
4767
|
+
cancelJump();
|
|
4768
|
+
clearFollowPin();
|
|
4769
|
+
}, [cancelJump, clearFollowPin]);
|
|
4770
|
+
|
|
4771
|
+
/** Unpin and hold follow so zoom setScroll (slider center or pinch origin) is not stolen. */
|
|
4772
|
+
const onZoom = (0,external_react_.useCallback)(() => {
|
|
4773
|
+
cancelJump();
|
|
4774
|
+
isFollowPinnedRef.current = false;
|
|
4775
|
+
holdFollowUntilInsetRef.current = true;
|
|
4776
|
+
}, [cancelJump]);
|
|
4777
|
+
const applyScrollLeft = (0,external_react_.useCallback)((scrollLeftPx, shouldCommitState) => {
|
|
4778
|
+
const wavesurfer = wavesurferRef.current;
|
|
4779
|
+
if (!wavesurfer || !wavesurfer.setScroll) {
|
|
4780
|
+
return;
|
|
4781
|
+
}
|
|
4782
|
+
programmaticScrollRef.current = true;
|
|
4783
|
+
lastCameraScrollRef.current = scrollLeftPx;
|
|
4784
|
+
wavesurfer.setScroll(scrollLeftPx);
|
|
4785
|
+
const appliedScrollLeft = getScrollLeft(wavesurfer, scrollLeftPx);
|
|
4786
|
+
lastCameraScrollRef.current = appliedScrollLeft;
|
|
4787
|
+
viewportRef.current = getViewportAtScroll(viewportRef.current, appliedScrollLeft);
|
|
4788
|
+
window.requestAnimationFrame(() => {
|
|
4789
|
+
// Keep the flag through delayed `scroll` while the camera is driving.
|
|
4790
|
+
if (jumpAnimationRef.current || isFollowPinnedRef.current) {
|
|
4791
|
+
return;
|
|
4792
|
+
}
|
|
4793
|
+
programmaticScrollRef.current = false;
|
|
4794
|
+
});
|
|
4795
|
+
if (shouldCommitState) {
|
|
4796
|
+
onViewportCommitRef.current(appliedScrollLeft, viewportRef.current);
|
|
4797
|
+
}
|
|
4798
|
+
}, [viewportRef, wavesurferRef]);
|
|
4799
|
+
const pinFollowPlayhead = (0,external_react_.useCallback)((playhead, viewport, isPinned) => {
|
|
4800
|
+
isFollowPinnedRef.current = isPinned;
|
|
4801
|
+
if (!playhead || !isPinned || !(viewport.widthPx > 0)) {
|
|
4802
|
+
return;
|
|
4803
|
+
}
|
|
4804
|
+
playhead.style.left = getPinnedPlayheadLeft(viewport.widthPx);
|
|
4805
|
+
}, []);
|
|
4806
|
+
const apply = (0,external_react_.useCallback)((timeSec, playJustStarted = false) => {
|
|
4807
|
+
mediaTimeRef.current = timeSec;
|
|
4808
|
+
const wavesurfer = wavesurferRef.current;
|
|
4809
|
+
const viewport = viewportRef.current;
|
|
4810
|
+
if (!wavesurfer) {
|
|
4811
|
+
return;
|
|
4812
|
+
}
|
|
4813
|
+
if (viewport.zoomLevel <= constants/* WAVEFORM_ZOOM_MIN */.LW) {
|
|
4814
|
+
clearFollowPin();
|
|
4815
|
+
return;
|
|
4816
|
+
}
|
|
4817
|
+
if (userIsScrollingRef.current && !playJustStarted) {
|
|
4818
|
+
return;
|
|
4819
|
+
}
|
|
4820
|
+
if (jumpAnimationRef.current && !playJustStarted) {
|
|
4821
|
+
return;
|
|
4822
|
+
}
|
|
4823
|
+
const liveViewport = getViewportAtScroll(viewport, getScrollLeft(wavesurfer, viewport.scrollLeftPx));
|
|
4824
|
+
const action = getPlayheadCameraAction({
|
|
4825
|
+
isPlaying: true,
|
|
4826
|
+
playJustStarted,
|
|
4827
|
+
timeSec,
|
|
4828
|
+
viewport: liveViewport
|
|
4829
|
+
});
|
|
4830
|
+
if (holdFollowUntilInsetRef.current && !playJustStarted) {
|
|
4831
|
+
if (action.type !== 'none') {
|
|
4832
|
+
return;
|
|
4833
|
+
}
|
|
4834
|
+
holdFollowUntilInsetRef.current = false;
|
|
4835
|
+
}
|
|
4836
|
+
if (action.type === 'none') {
|
|
4837
|
+
if (isFollowPinnedRef.current) {
|
|
4838
|
+
isFollowPinnedRef.current = false;
|
|
4839
|
+
applyScrollLeft(liveViewport.scrollLeftPx, true);
|
|
4840
|
+
}
|
|
4841
|
+
programmaticScrollRef.current = false;
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
cancelJump();
|
|
4845
|
+
if (action.type === 'followRight') {
|
|
4846
|
+
pinFollowPlayhead(playheadRef.current, liveViewport, action.isPlayheadPinned);
|
|
4847
|
+
applyScrollLeft(action.scrollLeftPx, !action.isPlayheadPinned);
|
|
4848
|
+
return;
|
|
4849
|
+
}
|
|
4850
|
+
isFollowPinnedRef.current = false;
|
|
4851
|
+
const from = getScrollLeft(wavesurfer, liveViewport.scrollLeftPx);
|
|
4852
|
+
if (prefersReducedMotion() || typeof window.requestAnimationFrame !== 'function') {
|
|
4853
|
+
applyScrollLeft(action.scrollLeftPx, true);
|
|
4854
|
+
apply(timeSec, false);
|
|
4855
|
+
return;
|
|
4856
|
+
}
|
|
4857
|
+
programmaticScrollRef.current = true;
|
|
4858
|
+
const start = (0,util/* getCurrentTimeMs */.RU)();
|
|
4859
|
+
const tick = now => {
|
|
4860
|
+
const t = Math.min(1, (now - start) / constants/* WAVEFORM_PLAYHEAD_JUMP_MS */.Bq);
|
|
4861
|
+
const liveAction = getPlayheadCameraAction({
|
|
4862
|
+
isPlaying: true,
|
|
4863
|
+
playJustStarted: true,
|
|
4864
|
+
timeSec: mediaTimeRef.current,
|
|
4865
|
+
viewport: getViewportAtScroll(viewportRef.current, getScrollLeft(wavesurfer, from))
|
|
4866
|
+
});
|
|
4867
|
+
const to = liveAction.type === 'none' ? action.scrollLeftPx : liveAction.scrollLeftPx;
|
|
4868
|
+
applyScrollLeft(from + (to - from) * (1 - (1 - t) * (1 - t)), false);
|
|
4869
|
+
if (t < 1) {
|
|
4870
|
+
jumpAnimationRef.current = window.requestAnimationFrame(tick);
|
|
4871
|
+
return;
|
|
4872
|
+
}
|
|
4873
|
+
jumpAnimationRef.current = 0;
|
|
4874
|
+
applyScrollLeft(to, true);
|
|
4875
|
+
apply(mediaTimeRef.current, false);
|
|
4876
|
+
};
|
|
4877
|
+
jumpAnimationRef.current = window.requestAnimationFrame(tick);
|
|
4878
|
+
}, [applyScrollLeft, cancelJump, clearFollowPin, pinFollowPlayhead, playheadRef, viewportRef, wavesurferRef]);
|
|
4879
|
+
applyRef.current = apply;
|
|
4880
|
+
|
|
4881
|
+
/**
|
|
4882
|
+
* Camera-owned: jumping; matching follow scroll; unpinned programmatic; clamp-to-max.
|
|
4883
|
+
* User pan: pinned and |scroll - lastCamera| > 1, or any non-programmatic scroll while not jumping.
|
|
4884
|
+
*/
|
|
4885
|
+
const isUserPan = (0,external_react_.useCallback)(scrollLeftPx => {
|
|
4886
|
+
const isCameraOwnedScroll = programmaticScrollRef.current || jumpAnimationRef.current !== 0;
|
|
4887
|
+
const lastCameraScroll = lastCameraScrollRef.current;
|
|
4888
|
+
const maxScroll = maxScrollLeft(viewportRef.current);
|
|
4889
|
+
const isClampedToMax = lastCameraScroll != null && scrollLeftPx >= maxScroll - 1 && lastCameraScroll >= maxScroll - 1;
|
|
4890
|
+
const isFollowCameraScroll = isFollowPinnedRef.current && lastCameraScroll != null && Math.abs(scrollLeftPx - lastCameraScroll) <= 1;
|
|
4891
|
+
return !(isCameraOwnedScroll && (jumpAnimationRef.current !== 0 || isFollowCameraScroll || isClampedToMax || !isFollowPinnedRef.current));
|
|
4892
|
+
}, [viewportRef]);
|
|
4893
|
+
const handleScroll = (0,external_react_.useCallback)(onUserPan => {
|
|
4894
|
+
const wavesurfer = wavesurferRef.current;
|
|
4895
|
+
if (!wavesurfer) {
|
|
4896
|
+
return;
|
|
4897
|
+
}
|
|
4898
|
+
const scrollLeftPx = getScrollLeft(wavesurfer);
|
|
4899
|
+
if (!isUserPan(scrollLeftPx)) {
|
|
4900
|
+
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
4901
|
+
return;
|
|
4902
|
+
}
|
|
4903
|
+
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
4904
|
+
const timeSec = readMediaTime();
|
|
4905
|
+
const playhead = playheadRef.current;
|
|
4906
|
+
if (playhead) {
|
|
4907
|
+
playhead.style.left = timeLeftPercent(timeSec, viewportRef.current.durationSec, viewportRef.current);
|
|
4908
|
+
}
|
|
4909
|
+
userIsScrollingRef.current = true;
|
|
4910
|
+
holdFollowUntilInsetRef.current = true;
|
|
4911
|
+
window.clearTimeout(scrollSettleTimerRef.current);
|
|
4912
|
+
scrollSettleTimerRef.current = window.setTimeout(() => {
|
|
4913
|
+
userIsScrollingRef.current = false;
|
|
4914
|
+
scrollSettleTimerRef.current = 0;
|
|
4915
|
+
if (!mediaElRef.current || mediaElRef.current.paused) {
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
applyRef.current?.(readMediaTime(), false);
|
|
4919
|
+
}, constants/* WAVEFORM_FOLLOW_SCROLL_SETTLE_MS */.Zs);
|
|
4920
|
+
cancelJump();
|
|
4921
|
+
isFollowPinnedRef.current = false;
|
|
4922
|
+
programmaticScrollRef.current = false;
|
|
4923
|
+
onUserPan(timeSec);
|
|
4924
|
+
}, [cancelJump, isUserPan, mediaElRef, playheadRef, readMediaTime, viewportRef, wavesurferRef]);
|
|
4925
|
+
(0,external_react_.useEffect)(() => () => {
|
|
4926
|
+
releaseUserPanHold();
|
|
4927
|
+
cancelJump();
|
|
4928
|
+
}, [cancelJump, releaseUserPanHold]);
|
|
4929
|
+
return {
|
|
4930
|
+
apply,
|
|
4931
|
+
applyScrollLeft,
|
|
4932
|
+
cancelJump,
|
|
4933
|
+
clearFollowPin,
|
|
4934
|
+
handleScroll,
|
|
4935
|
+
isFollowPinned,
|
|
4936
|
+
onSeek,
|
|
4937
|
+
onZoom,
|
|
4938
|
+
releaseUserPanHold
|
|
4939
|
+
};
|
|
4940
|
+
}
|
|
4615
4941
|
;// ./src/lib/viewers/media/waveform/WaveformView.scss
|
|
4616
4942
|
// extracted by mini-css-extract-plugin
|
|
4617
4943
|
|
|
@@ -4630,6 +4956,7 @@ function WaveformView_toPrimitive(t, r) { if ("object" != typeof t || !t) return
|
|
|
4630
4956
|
|
|
4631
4957
|
|
|
4632
4958
|
|
|
4959
|
+
|
|
4633
4960
|
/** Pointer X in the view and the media time under it; zoom keeps this point fixed. */
|
|
4634
4961
|
|
|
4635
4962
|
/** CSS width × devicePixelRatio, for canvas gradient fills. */
|
|
@@ -4637,21 +4964,12 @@ function devicePixelWidth(widthCssPx) {
|
|
|
4637
4964
|
const pixelRatio = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;
|
|
4638
4965
|
return widthCssPx * pixelRatio;
|
|
4639
4966
|
}
|
|
4640
|
-
function
|
|
4967
|
+
function WaveformView_prefersReducedMotion() {
|
|
4641
4968
|
return typeof window !== 'undefined' && typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
4642
4969
|
}
|
|
4643
|
-
function
|
|
4970
|
+
function WaveformView_getScrollLeft(wavesurfer, fallback = 0) {
|
|
4644
4971
|
return wavesurfer && wavesurfer.getScroll ? wavesurfer.getScroll() : fallback;
|
|
4645
4972
|
}
|
|
4646
|
-
|
|
4647
|
-
/** CSS left % of the playhead from the left of the visible window. */
|
|
4648
|
-
function timeLeftPercent(timeSec, durationSec, viewport) {
|
|
4649
|
-
if (viewport.widthPx > 0 && viewport.pixelsPerSecond > 0) {
|
|
4650
|
-
return `${positionPxFromTime(timeSec, viewport) / viewport.widthPx * 100}%`;
|
|
4651
|
-
}
|
|
4652
|
-
const progress = durationSec > 0 ? Math.min(1, Math.max(0, timeSec / durationSec)) : 0;
|
|
4653
|
-
return `${progress * 100}%`;
|
|
4654
|
-
}
|
|
4655
4973
|
function applyPeaks(wavesurfer, peaks, durationSec) {
|
|
4656
4974
|
if (!wavesurfer.load) {
|
|
4657
4975
|
return;
|
|
@@ -4693,7 +5011,7 @@ function zoomOriginAtPointer(pointerX, wavesurfer, durationSec, fallbackWidth) {
|
|
|
4693
5011
|
}
|
|
4694
5012
|
return {
|
|
4695
5013
|
pointerX,
|
|
4696
|
-
timeSec: (
|
|
5014
|
+
timeSec: (WaveformView_getScrollLeft(wavesurfer) + pointerX) / fullWidth * durationSec
|
|
4697
5015
|
};
|
|
4698
5016
|
}
|
|
4699
5017
|
|
|
@@ -4713,30 +5031,37 @@ function WaveformView({
|
|
|
4713
5031
|
peaks,
|
|
4714
5032
|
zoomLevel: zoomLevelProp
|
|
4715
5033
|
}) {
|
|
5034
|
+
// DOM / WaveSurfer
|
|
4716
5035
|
const containerRef = (0,external_react_.useRef)(null);
|
|
4717
5036
|
const trackRef = (0,external_react_.useRef)(null);
|
|
4718
5037
|
const playheadRef = (0,external_react_.useRef)(null);
|
|
4719
5038
|
const playheadAnimationRef = (0,external_react_.useRef)(0);
|
|
4720
5039
|
const wavesurferRef = (0,external_react_.useRef)(null);
|
|
5040
|
+
|
|
5041
|
+
// Latest props for WaveSurfer + media listeners that must not re-subscribe each render.
|
|
4721
5042
|
const onSeekRef = (0,external_react_.useRef)(onSeek);
|
|
4722
5043
|
const interactiveRef = (0,external_react_.useRef)(interactive);
|
|
4723
5044
|
const hasZoomHandlersRef = (0,external_react_.useRef)(false);
|
|
4724
5045
|
const currentTimeRef = (0,external_react_.useRef)(currentTime);
|
|
4725
5046
|
const peaksRef = (0,external_react_.useRef)(peaks);
|
|
5047
|
+
const durationSecRef = (0,external_react_.useRef)(durationSec);
|
|
5048
|
+
const mediaElRef = (0,external_react_.useRef)(mediaEl);
|
|
5049
|
+
const onViewportChangeRef = (0,external_react_.useRef)(onViewportChange);
|
|
4726
5050
|
const displayedPeaksRef = (0,external_react_.useRef)(null);
|
|
4727
5051
|
const peakTransitionAnimationRef = (0,external_react_.useRef)(0);
|
|
4728
|
-
|
|
5052
|
+
// Zoom / pinch / tile tint (read from pointer + WaveSurfer handlers)
|
|
4729
5053
|
const zoomOriginRef = (0,external_react_.useRef)(null);
|
|
4730
5054
|
const pinchStartRef = (0,external_react_.useRef)(null);
|
|
5055
|
+
const pointerZoomRef = (0,external_react_.useRef)(false);
|
|
5056
|
+
const pointerZoomClearTimerRef = (0,external_react_.useRef)(0);
|
|
4731
5057
|
const bufferProgressRef = (0,external_react_.useRef)(0);
|
|
4732
5058
|
const hoverProgressRef = (0,external_react_.useRef)(null);
|
|
4733
|
-
const programmaticScrollRef = (0,external_react_.useRef)(false);
|
|
4734
|
-
const onViewportChangeRef = (0,external_react_.useRef)(onViewportChange);
|
|
4735
5059
|
onSeekRef.current = onSeek;
|
|
4736
5060
|
interactiveRef.current = interactive;
|
|
4737
5061
|
currentTimeRef.current = currentTime;
|
|
4738
5062
|
peaksRef.current = peaks;
|
|
4739
5063
|
durationSecRef.current = durationSec;
|
|
5064
|
+
mediaElRef.current = mediaEl;
|
|
4740
5065
|
onViewportChangeRef.current = onViewportChange;
|
|
4741
5066
|
const [internalZoom, setInternalZoom] = (0,external_react_.useState)(constants/* WAVEFORM_ZOOM_MIN */.LW);
|
|
4742
5067
|
const [hoverProgress, setHoverProgress] = (0,external_react_.useState)(null);
|
|
@@ -4750,7 +5075,7 @@ function WaveformView({
|
|
|
4750
5075
|
});
|
|
4751
5076
|
hasZoomHandlersRef.current = maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW && (typeof onZoomChange === 'function' || typeof zoomLevelProp !== 'number');
|
|
4752
5077
|
const zoomLevel = clampWaveformZoom(isControlled ? zoomLevelProp : internalZoom, maxZoom);
|
|
4753
|
-
const zoomRef = (0,external_react_.useRef)(zoomLevel);
|
|
5078
|
+
const zoomRef = (0,external_react_.useRef)(zoomLevel); // latest zoom for WaveSurfer redraw/zoom handlers
|
|
4754
5079
|
zoomRef.current = zoomLevel;
|
|
4755
5080
|
const prevZoomRef = (0,external_react_.useRef)(null);
|
|
4756
5081
|
const isZoomed = zoomLevel > constants/* WAVEFORM_ZOOM_MIN */.LW;
|
|
@@ -4765,8 +5090,38 @@ function WaveformView({
|
|
|
4765
5090
|
widthPx: canvasWidthPx,
|
|
4766
5091
|
zoomLevel
|
|
4767
5092
|
}), [canvasWidthPx, durationSec, height, maxZoom, scrollLeft, zoomLevel]);
|
|
4768
|
-
const viewportRef = (0,external_react_.useRef)(viewport);
|
|
4769
|
-
|
|
5093
|
+
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) => {
|
|
5095
|
+
onViewportChangeRef.current?.(nextViewport);
|
|
5096
|
+
setScrollLeft(scrollLeftPx);
|
|
5097
|
+
}, []);
|
|
5098
|
+
const {
|
|
5099
|
+
apply: applyPlayheadCamera,
|
|
5100
|
+
applyScrollLeft,
|
|
5101
|
+
cancelJump,
|
|
5102
|
+
clearFollowPin,
|
|
5103
|
+
handleScroll: handleCameraScroll,
|
|
5104
|
+
isFollowPinned,
|
|
5105
|
+
onSeek: onPlayheadSeek,
|
|
5106
|
+
onZoom,
|
|
5107
|
+
releaseUserPanHold
|
|
5108
|
+
} = usePlayheadCamera({
|
|
5109
|
+
mediaElRef,
|
|
5110
|
+
onViewportCommit,
|
|
5111
|
+
playheadRef,
|
|
5112
|
+
viewportRef,
|
|
5113
|
+
wavesurferRef
|
|
5114
|
+
});
|
|
5115
|
+
(0,external_react_.useLayoutEffect)(() => {
|
|
5116
|
+
viewportRef.current = createWaveformViewport({
|
|
5117
|
+
durationSec: viewport.durationSec,
|
|
5118
|
+
heightPx: viewport.heightPx,
|
|
5119
|
+
maxZoom: viewport.maxZoom,
|
|
5120
|
+
scrollLeftPx: viewportRef.current.scrollLeftPx,
|
|
5121
|
+
widthPx: viewport.widthPx,
|
|
5122
|
+
zoomLevel: viewport.zoomLevel
|
|
5123
|
+
});
|
|
5124
|
+
}, [viewport]);
|
|
4770
5125
|
const setZoomLevel = (0,external_react_.useCallback)(nextZoom => {
|
|
4771
5126
|
const zoom = clampWaveformZoom(nextZoom, maxZoom);
|
|
4772
5127
|
if (!isControlled) {
|
|
@@ -4774,12 +5129,20 @@ function WaveformView({
|
|
|
4774
5129
|
}
|
|
4775
5130
|
onZoomChange?.(zoom);
|
|
4776
5131
|
}, [isControlled, maxZoom, onZoomChange]);
|
|
5132
|
+
const markPointerZoom = (0,external_react_.useCallback)(() => {
|
|
5133
|
+
pointerZoomRef.current = true;
|
|
5134
|
+
window.clearTimeout(pointerZoomClearTimerRef.current);
|
|
5135
|
+
pointerZoomClearTimerRef.current = window.setTimeout(() => {
|
|
5136
|
+
pointerZoomRef.current = false;
|
|
5137
|
+
pointerZoomClearTimerRef.current = 0;
|
|
5138
|
+
}, constants/* WAVEFORM_ZOOM_DISMISS_MS */.m6);
|
|
5139
|
+
}, []);
|
|
4777
5140
|
const syncViewport = (0,external_react_.useCallback)(() => {
|
|
4778
5141
|
const wavesurfer = wavesurferRef.current;
|
|
4779
5142
|
if (!wavesurfer) {
|
|
4780
5143
|
return;
|
|
4781
5144
|
}
|
|
4782
|
-
const scrollLeftPx =
|
|
5145
|
+
const scrollLeftPx = WaveformView_getScrollLeft(wavesurfer);
|
|
4783
5146
|
viewportRef.current = getViewportAtScroll(viewportRef.current, scrollLeftPx);
|
|
4784
5147
|
onViewportChangeRef.current?.(viewportRef.current);
|
|
4785
5148
|
setScrollLeft(scrollLeftPx);
|
|
@@ -4789,29 +5152,14 @@ function WaveformView({
|
|
|
4789
5152
|
if (!playhead) {
|
|
4790
5153
|
return;
|
|
4791
5154
|
}
|
|
4792
|
-
|
|
5155
|
+
if (!isFollowPinned()) {
|
|
5156
|
+
playhead.style.left = timeLeftPercent(timeSec, durationSecRef.current, viewportRef.current);
|
|
5157
|
+
}
|
|
4793
5158
|
const wavesurfer = wavesurferRef.current;
|
|
4794
5159
|
if (wavesurfer && wavesurfer.setTime) {
|
|
4795
5160
|
wavesurfer.setTime(timeSec);
|
|
4796
5161
|
}
|
|
4797
|
-
}, []);
|
|
4798
|
-
const applyScrollLeft = (0,external_react_.useCallback)((scrollLeftPx, shouldCommitState) => {
|
|
4799
|
-
const wavesurfer = wavesurferRef.current;
|
|
4800
|
-
if (!wavesurfer || !wavesurfer.setScroll) {
|
|
4801
|
-
return;
|
|
4802
|
-
}
|
|
4803
|
-
programmaticScrollRef.current = true;
|
|
4804
|
-
wavesurfer.setScroll(scrollLeftPx);
|
|
4805
|
-
viewportRef.current = getViewportAtScroll(viewportRef.current, getScrollLeft(wavesurfer, scrollLeftPx));
|
|
4806
|
-
window.requestAnimationFrame(() => {
|
|
4807
|
-
// Keep the flag through delayed `scroll` after a zoom setScroll.
|
|
4808
|
-
programmaticScrollRef.current = false;
|
|
4809
|
-
});
|
|
4810
|
-
if (shouldCommitState) {
|
|
4811
|
-
onViewportChangeRef.current?.(viewportRef.current);
|
|
4812
|
-
setScrollLeft(getScrollLeft(wavesurfer, scrollLeftPx));
|
|
4813
|
-
}
|
|
4814
|
-
}, []);
|
|
5162
|
+
}, [isFollowPinned]);
|
|
4815
5163
|
(0,external_react_.useEffect)(() => {
|
|
4816
5164
|
const container = containerRef.current;
|
|
4817
5165
|
if (!container) {
|
|
@@ -4842,11 +5190,9 @@ function WaveformView({
|
|
|
4842
5190
|
onSeekRef.current?.(relativeX * durationSecRef.current);
|
|
4843
5191
|
});
|
|
4844
5192
|
const unsubscribeScroll = wavesurfer.on('scroll', () => {
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
}
|
|
4849
|
-
syncViewport();
|
|
5193
|
+
handleCameraScroll(() => {
|
|
5194
|
+
syncViewport();
|
|
5195
|
+
});
|
|
4850
5196
|
});
|
|
4851
5197
|
const unsubscribeZoom = wavesurfer.on('zoom', () => {
|
|
4852
5198
|
syncViewport();
|
|
@@ -4864,6 +5210,8 @@ function WaveformView({
|
|
|
4864
5210
|
displayedPeaksRef.current = peaksRef.current;
|
|
4865
5211
|
syncViewport();
|
|
4866
5212
|
return () => {
|
|
5213
|
+
releaseUserPanHold();
|
|
5214
|
+
cancelJump();
|
|
4867
5215
|
window.cancelAnimationFrame(peakTransitionAnimationRef.current);
|
|
4868
5216
|
unsubscribeClick();
|
|
4869
5217
|
unsubscribeScroll();
|
|
@@ -4873,7 +5221,7 @@ function WaveformView({
|
|
|
4873
5221
|
wavesurferRef.current = null;
|
|
4874
5222
|
displayedPeaksRef.current = null;
|
|
4875
5223
|
};
|
|
4876
|
-
}, [height, syncViewport]);
|
|
5224
|
+
}, [cancelJump, handleCameraScroll, height, releaseUserPanHold, syncViewport]);
|
|
4877
5225
|
(0,external_react_.useLayoutEffect)(() => {
|
|
4878
5226
|
const el = containerRef.current;
|
|
4879
5227
|
if (!el) {
|
|
@@ -4935,23 +5283,30 @@ function WaveformView({
|
|
|
4935
5283
|
zoomOriginRef.current = null;
|
|
4936
5284
|
const didZoomChange = prevZoomRef.current !== zoomLevel;
|
|
4937
5285
|
prevZoomRef.current = zoomLevel;
|
|
5286
|
+
if (origin || didZoomChange) {
|
|
5287
|
+
onZoom();
|
|
5288
|
+
}
|
|
4938
5289
|
if (minPxPerSec > 0) {
|
|
4939
5290
|
if (origin) {
|
|
4940
5291
|
applyScrollLeft(origin.timeSec * minPxPerSec - origin.pointerX, true);
|
|
4941
|
-
} else if (didZoomChange) {
|
|
4942
|
-
const
|
|
4943
|
-
|
|
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);
|
|
4944
5302
|
}
|
|
4945
5303
|
}
|
|
4946
5304
|
wavesurfer.setTime(currentTimeRef.current);
|
|
4947
5305
|
syncViewport();
|
|
4948
|
-
|
|
5306
|
+
updatePlayheadPosition(currentTimeRef.current);
|
|
5307
|
+
}, [applyScrollLeft, durationSec, height, maxZoom, onZoom, syncViewport, updatePlayheadPosition, zoomLevel]);
|
|
4949
5308
|
(0,external_react_.useLayoutEffect)(() => {
|
|
4950
|
-
|
|
4951
|
-
updatePlayheadPosition(mediaEl.currentTime);
|
|
4952
|
-
return;
|
|
4953
|
-
}
|
|
4954
|
-
updatePlayheadPosition(currentTime);
|
|
5309
|
+
updatePlayheadPosition(mediaEl ? mediaEl.currentTime : currentTime);
|
|
4955
5310
|
}, [currentTime, durationSec, mediaEl, updatePlayheadPosition, viewport]);
|
|
4956
5311
|
(0,external_react_.useEffect)(() => {
|
|
4957
5312
|
const media = mediaEl;
|
|
@@ -4961,18 +5316,26 @@ function WaveformView({
|
|
|
4961
5316
|
const tick = () => {
|
|
4962
5317
|
if (!media.paused) {
|
|
4963
5318
|
updatePlayheadPosition(media.currentTime);
|
|
5319
|
+
applyPlayheadCamera(media.currentTime, false);
|
|
4964
5320
|
}
|
|
4965
5321
|
playheadAnimationRef.current = window.requestAnimationFrame(tick);
|
|
4966
5322
|
};
|
|
4967
5323
|
const startLoop = () => {
|
|
4968
5324
|
window.cancelAnimationFrame(playheadAnimationRef.current);
|
|
5325
|
+
releaseUserPanHold();
|
|
5326
|
+
applyPlayheadCamera(media.currentTime, true);
|
|
4969
5327
|
playheadAnimationRef.current = window.requestAnimationFrame(tick);
|
|
4970
5328
|
};
|
|
4971
5329
|
const stopLoop = () => {
|
|
4972
5330
|
window.cancelAnimationFrame(playheadAnimationRef.current);
|
|
5331
|
+
cancelJump();
|
|
5332
|
+
releaseUserPanHold();
|
|
5333
|
+
clearFollowPin();
|
|
5334
|
+
syncViewport();
|
|
4973
5335
|
updatePlayheadPosition(media.currentTime);
|
|
4974
5336
|
};
|
|
4975
5337
|
const handleSeeked = () => {
|
|
5338
|
+
onPlayheadSeek(media.currentTime);
|
|
4976
5339
|
updatePlayheadPosition(media.currentTime);
|
|
4977
5340
|
};
|
|
4978
5341
|
if (!media.paused) {
|
|
@@ -4984,12 +5347,14 @@ function WaveformView({
|
|
|
4984
5347
|
media.addEventListener('seeked', handleSeeked);
|
|
4985
5348
|
return () => {
|
|
4986
5349
|
window.cancelAnimationFrame(playheadAnimationRef.current);
|
|
5350
|
+
cancelJump();
|
|
5351
|
+
releaseUserPanHold();
|
|
4987
5352
|
media.removeEventListener('play', startLoop);
|
|
4988
5353
|
media.removeEventListener('playing', startLoop);
|
|
4989
5354
|
media.removeEventListener('pause', stopLoop);
|
|
4990
5355
|
media.removeEventListener('seeked', handleSeeked);
|
|
4991
5356
|
};
|
|
4992
|
-
}, [mediaEl, updatePlayheadPosition]);
|
|
5357
|
+
}, [applyPlayheadCamera, cancelJump, clearFollowPin, mediaEl, onPlayheadSeek, releaseUserPanHold, syncViewport, updatePlayheadPosition]);
|
|
4993
5358
|
(0,external_react_.useEffect)(() => {
|
|
4994
5359
|
const wavesurfer = wavesurferRef.current;
|
|
4995
5360
|
if (!wavesurfer || !wavesurfer.setOptions || !(durationSec > 0)) {
|
|
@@ -4997,7 +5362,7 @@ function WaveformView({
|
|
|
4997
5362
|
}
|
|
4998
5363
|
window.cancelAnimationFrame(peakTransitionAnimationRef.current);
|
|
4999
5364
|
const fromPeaks = displayedPeaksRef.current;
|
|
5000
|
-
if (!fromPeaks || fromPeaks === peaks ||
|
|
5365
|
+
if (!fromPeaks || fromPeaks === peaks || WaveformView_prefersReducedMotion()) {
|
|
5001
5366
|
displayedPeaksRef.current = peaks;
|
|
5002
5367
|
applyPeaks(wavesurfer, peaks, durationSec);
|
|
5003
5368
|
return undefined;
|
|
@@ -5046,6 +5411,7 @@ function WaveformView({
|
|
|
5046
5411
|
const captureZoomOrigin = clientX => {
|
|
5047
5412
|
const rect = track.getBoundingClientRect();
|
|
5048
5413
|
zoomOriginRef.current = zoomOriginAtPointer(clientX - rect.left, wavesurferRef.current, durationSec, rect.width);
|
|
5414
|
+
markPointerZoom();
|
|
5049
5415
|
};
|
|
5050
5416
|
|
|
5051
5417
|
/** Zoom origin at the midpoint of a two-finger pinch. */
|
|
@@ -5077,6 +5443,7 @@ function WaveformView({
|
|
|
5077
5443
|
distance: touchDistance(event.touches),
|
|
5078
5444
|
zoom: zoomRef.current
|
|
5079
5445
|
};
|
|
5446
|
+
markPointerZoom();
|
|
5080
5447
|
};
|
|
5081
5448
|
const onTouchMove = event => {
|
|
5082
5449
|
const pinch = pinchStartRef.current;
|
|
@@ -5085,6 +5452,7 @@ function WaveformView({
|
|
|
5085
5452
|
}
|
|
5086
5453
|
event.preventDefault();
|
|
5087
5454
|
zoomOriginRef.current = zoomOriginFromPinch(event.touches);
|
|
5455
|
+
markPointerZoom();
|
|
5088
5456
|
setZoomLevel(pinch.zoom * (touchDistance(event.touches) / pinch.distance));
|
|
5089
5457
|
};
|
|
5090
5458
|
const onTouchEnd = event => {
|
|
@@ -5104,13 +5472,14 @@ function WaveformView({
|
|
|
5104
5472
|
track.addEventListener('touchend', onTouchEnd);
|
|
5105
5473
|
track.addEventListener('touchcancel', onTouchEnd);
|
|
5106
5474
|
return () => {
|
|
5475
|
+
window.clearTimeout(pointerZoomClearTimerRef.current);
|
|
5107
5476
|
track.removeEventListener('wheel', onZoomWheel);
|
|
5108
5477
|
track.removeEventListener('touchstart', onTouchStart);
|
|
5109
5478
|
track.removeEventListener('touchmove', onTouchMove);
|
|
5110
5479
|
track.removeEventListener('touchend', onTouchEnd);
|
|
5111
5480
|
track.removeEventListener('touchcancel', onTouchEnd);
|
|
5112
5481
|
};
|
|
5113
|
-
}, [durationSec, setZoomLevel]);
|
|
5482
|
+
}, [durationSec, markPointerZoom, setZoomLevel]);
|
|
5114
5483
|
const onHoverMove = (0,external_react_.useCallback)(event => {
|
|
5115
5484
|
if (!interactive) {
|
|
5116
5485
|
return;
|
|
@@ -5512,6 +5881,7 @@ function isFpsAvailable(player) {
|
|
|
5512
5881
|
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
5513
5882
|
|
|
5514
5883
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
5884
|
+
/* harmony export */ Bq: () => (/* binding */ WAVEFORM_PLAYHEAD_JUMP_MS),
|
|
5515
5885
|
/* harmony export */ DY: () => (/* binding */ WAVEFORM_BAR_RADIUS),
|
|
5516
5886
|
/* harmony export */ EB: () => (/* binding */ CLIENT_DECODE_MAX_COMPRESSED_BYTES),
|
|
5517
5887
|
/* harmony export */ FY: () => (/* binding */ MAX_PEAK_COUNT),
|
|
@@ -5519,7 +5889,9 @@ function isFpsAvailable(player) {
|
|
|
5519
5889
|
/* harmony export */ Kl: () => (/* binding */ WAVEFORM_MIN_VIEW_WINDOW_SEC),
|
|
5520
5890
|
/* harmony export */ LW: () => (/* binding */ WAVEFORM_ZOOM_MIN),
|
|
5521
5891
|
/* harmony export */ Lu: () => (/* binding */ WAVEFORM_BAR_GAP),
|
|
5892
|
+
/* harmony export */ NM: () => (/* binding */ WAVEFORM_FOLLOW_INSET_PX),
|
|
5522
5893
|
/* harmony export */ XS: () => (/* binding */ WAVEFORM_BAR_MIN_HEIGHT),
|
|
5894
|
+
/* harmony export */ Zs: () => (/* binding */ WAVEFORM_FOLLOW_SCROLL_SETTLE_MS),
|
|
5523
5895
|
/* harmony export */ f3: () => (/* binding */ CLIENT_DECODE_PEAK_COUNT),
|
|
5524
5896
|
/* harmony export */ i8: () => (/* binding */ PEAK_UNIT_MAX),
|
|
5525
5897
|
/* harmony export */ m6: () => (/* binding */ WAVEFORM_ZOOM_DISMISS_MS),
|
|
@@ -5562,6 +5934,10 @@ const WAVEFORM_ZOOM_MAX = 24;
|
|
|
5562
5934
|
const WAVEFORM_MIN_VIEW_WINDOW_SEC = 4;
|
|
5563
5935
|
const WAVEFORM_ZOOM_SLIDER_MAX = 100;
|
|
5564
5936
|
const WAVEFORM_ZOOM_DISMISS_MS = 250;
|
|
5937
|
+
const WAVEFORM_FOLLOW_INSET_PX = 200;
|
|
5938
|
+
const WAVEFORM_PLAYHEAD_JUMP_MS = 400;
|
|
5939
|
+
/** After the last user pan, wait this long before the camera may pin again. */
|
|
5940
|
+
const WAVEFORM_FOLLOW_SCROLL_SETTLE_MS = 150;
|
|
5565
5941
|
const WAVEFORM_BAR_GAP = 2;
|
|
5566
5942
|
const WAVEFORM_BAR_WIDTH = 2;
|
|
5567
5943
|
const WAVEFORM_BAR_RADIUS = WAVEFORM_BAR_WIDTH / 2;
|
|
@@ -21945,7 +22321,7 @@ class Browser {
|
|
|
21945
22321
|
;// ./src/lib/Logger.js
|
|
21946
22322
|
/* eslint-disable no-undef */
|
|
21947
22323
|
const CLIENT_NAME = "box-content-preview";
|
|
21948
|
-
const CLIENT_VERSION = "3.
|
|
22324
|
+
const CLIENT_VERSION = "3.85.0";
|
|
21949
22325
|
/* eslint-enable no-undef */
|
|
21950
22326
|
|
|
21951
22327
|
class Logger {
|
|
@@ -34752,7 +35128,7 @@ class MP3Viewer extends media_MediaBaseViewer {
|
|
|
34752
35128
|
* @return {Promise<{ default: Function }>} MP3ControlsV2 module
|
|
34753
35129
|
*/
|
|
34754
35130
|
importV2Controls() {
|
|
34755
|
-
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__,
|
|
35131
|
+
return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 3678));
|
|
34756
35132
|
}
|
|
34757
35133
|
|
|
34758
35134
|
/**
|