diff --git a/public/assets/components/dropdown.css b/public/assets/components/dropdown.css new file mode 100644 index 00000000..2edab593 --- /dev/null +++ b/public/assets/components/dropdown.css @@ -0,0 +1,64 @@ +.component_dropdown { + position: relative; +} +.component_dropdown .dropdown_container { + display: none; + position: absolute; + right: 0; +} +.component_dropdown .dropdown_button { + border: 1px solid rgba(0, 0, 0, 0); + border-radius: 4px; + padding: 5px; + min-width: 20px; + text-align: center; +} +.component_dropdown .dropdown_container { + padding-top: 5px; + z-index: 3; +} +.component_dropdown .dropdown_container:before { + content: ' '; + position: absolute; + right: 10px; + top: 1px; + width: 0; + height: 0; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; +} +.component_dropdown .dropdown_container ul { + margin: 0; + list-style-type: none; + background: white; + border: 1px solid var(--border); + box-shadow: 1px 1px 2px var(--border); + color: rgba(0,10,20,0.85); + border-radius: 3px; + padding: 3px 0px; + font-size: 0.92em; +} +.component_dropdown .dropdown_container ul li { + display: flex; +} +.component_dropdown .dropdown_container ul li > div { + width: 160px; + padding: 8px 5px 8px 10px; +} + +.component_dropdown.active .dropdown_container { + display: block; +} +.component_dropdown.active .dropdown_container li { + background: white; + transition: background 0.1s ease-out; +} +.component_dropdown.active .dropdown_container li:hover { + background: rgba(0, 0, 0, 0.05); +} + +.component_dropdown.active .dropdown_button { + border-color: var(--bg-color); + box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); +} diff --git a/public/assets/components/dropdown.js b/public/assets/components/dropdown.js new file mode 100644 index 00000000..8a8ad836 --- /dev/null +++ b/public/assets/components/dropdown.js @@ -0,0 +1,88 @@ +import { createFragment } from "../lib/skeleton/index.js"; +import { animate, slideYIn } from "../lib/animate.js"; +import { loadCSS } from "../helpers/loader.js"; + +await loadCSS(import.meta.url, "./dropdown.css"); + +export default class ComponentDropdown extends HTMLDivElement { + constructor() { + super(); + this.render(); + } + + static get observedAttributes() { + return ["options"]; + } + + render() { + this.classList.add("component_dropdown", "view", "sort") + this.appendChild(createFragment(` + `)); + + this.appendChild(createFragment(` + + + `)); + + const setActive = () => this.classList.toggle("active"); + this.querySelector(".dropdown_button").onclick = () => { + setActive(); + animate(this.querySelector(".dropdown_container"), { + time: 100, + keyframes: slideYIn(2), + }); + }; + } +} + +customElements.define("component-dropdown", ComponentDropdown, { extends: "div" }); diff --git a/public/assets/components/fab.css b/public/assets/components/fab.css index 1bcc46f6..07dbf093 100644 --- a/public/assets/components/fab.css +++ b/public/assets/components/fab.css @@ -3,6 +3,7 @@ bottom: 20px; right: 20px; z-index: 2; + background: transparent; } .component_fab .content { height: 25px; diff --git a/public/assets/components/menubar.css b/public/assets/components/menubar.css index 1caf6e0a..88d5d566 100644 --- a/public/assets/components/menubar.css +++ b/public/assets/components/menubar.css @@ -75,3 +75,11 @@ google-cast-launcher { transition: all 0.25s ease-out; transition-delay: 0.30s; } + + +/* icons in additional menu */ +.component_menubar .action-item [is="component-dropdown"] .dropdown_button { + border: none; + padding: 2px 0px; + margin: 0; +} diff --git a/public/assets/components/menubar.js b/public/assets/components/menubar.js index aad11a5c..aae63c62 100644 --- a/public/assets/components/menubar.js +++ b/public/assets/components/menubar.js @@ -1,7 +1,12 @@ import { createElement } from "../lib/skeleton/index.js"; import { basename } from "../lib/path.js"; +import assert from "../lib/assert.js"; import { loadCSS } from "../helpers/loader.js"; +await loadCSS(import.meta.url, "./menubar.css"); + +import "./dropdown.js"; + export default class ComponentMenubar extends window.HTMLElement { constructor() { super(); @@ -13,33 +18,23 @@ export default class ComponentMenubar extends window.HTMLElement {
${basename(decodeURIComponent(location.pathname + location.hash)) || " "}
-
+
+
+
`; - this.render(); } - async render(html) { - await loadCSS(import.meta.url, "./menubar.css"); - html = ` - - - - - - download_white - - - `; - this.querySelector(".action-item").appendChild(createElement(html)); + render($fragment) { + this.querySelector(".action-item").appendChild($fragment); } } -export function render(html = "") { - const $el = document.body.querySelector("component-menubar"); - if (!$el) throw new Error("component::menubar.js missing element"); - $el.render(html); +export async function render($fragment, $root = document.body) { + const $el = $root.querySelector("component-menubar"); + assert.truthy($el, "component::menubar.js missing element"); + $el.render($fragment); } customElements.define("component-menubar", ComponentMenubar); diff --git a/public/assets/lib/assert.js b/public/assets/lib/assert.js index 9a396bce..1d8b8c0f 100644 --- a/public/assets/lib/assert.js +++ b/public/assets/lib/assert.js @@ -1,15 +1,15 @@ export default class assert { - static type(object, type) { + static type(object, type, msg) { if (object instanceof type) return; - throw new Error(`assertion failed - unexpected type for ${object.toString()}`); + throw new Error(msg ? msg : `assertion failed - unexpected type for ${object.toString()}`); } - static truthy(object) { + static truthy(object, msg) { if (object) return; - throw new Error(`assertion failed - object is not truthy`); + throw new Error(msg ? msg : `assertion failed - object is not truthy`); } - static fail(object) { - throw new Error(`assertion failed - ${object}`); + static fail(object, msg) { + throw new Error(msg ? msg : `assertion failed - ${object}`); } } diff --git a/public/assets/lib/skeleton/index.js b/public/assets/lib/skeleton/index.js index 5cf8df95..3965cc16 100644 --- a/public/assets/lib/skeleton/index.js +++ b/public/assets/lib/skeleton/index.js @@ -67,9 +67,7 @@ export function createFragment(str) { const $n = window.document.createElement("div"); $n.innerHTML = str; const $doc = document.createDocumentFragment(); - for (let i=0; i<$n.children.length; i++) { - $doc.appendChild($n.children[i].cloneNode(true)); - } + for (let i=0; i<$n.children.length; i++) $doc.appendChild($n.children[i].cloneNode(true)); $n.remove(); return $doc; } diff --git a/public/assets/lib/vendor/wavesurfer.js b/public/assets/lib/vendor/wavesurfer.js index 5024db3a..8f222fc8 100644 --- a/public/assets/lib/vendor/wavesurfer.js +++ b/public/assets/lib/vendor/wavesurfer.js @@ -1 +1,6 @@ -function t(t,e,i,s){return new(i||(i=Promise))((function(n,r){function o(t){try{h(s.next(t))}catch(t){r(t)}}function a(t){try{h(s.throw(t))}catch(t){r(t)}}function h(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(o,a)}h((s=s.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const e={decode:function(e,i){return t(this,void 0,void 0,(function*(){const t=new AudioContext({sampleRate:i});return t.decodeAudioData(e).finally((()=>t.close()))}))},createBuffer:function(t,e){return"number"==typeof t[0]&&(t=[t]),function(t){const e=t[0];if(e.some((t=>t>1||t<-1))){const i=e.length;let s=0;for(let t=0;ts&&(s=i)}for(const e of t)for(let t=0;tnull==t?void 0:t[e],copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};const i={fetchBlob:function(e,i,s){return t(this,void 0,void 0,(function*(){const n=yield fetch(e,s);if(!n.ok)throw new Error(`Failed to fetch ${e}: ${n.status} (${n.statusText})`);return function(e,i){t(this,void 0,void 0,(function*(){if(!e.body||!e.headers)return;const s=e.body.getReader(),n=Number(e.headers.get("Content-Length"))||0;let r=0;const o=e=>t(this,void 0,void 0,(function*(){r+=(null==e?void 0:e.length)||0;const t=Math.round(r/n*100);i(t)})),a=()=>t(this,void 0,void 0,(function*(){let t;try{t=yield s.read()}catch(t){return}t.done||(o(t.value),yield a())}));a()}))}(n.clone(),i),n.blob()}))}};class s{constructor(){this.listeners={},this.on=this.addEventListener,this.un=this.removeEventListener}addEventListener(t,e,i){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==i?void 0:i.once){const i=()=>{this.removeEventListener(t,i),this.removeEventListener(t,e)};return this.addEventListener(t,i),i}return()=>this.removeEventListener(t,e)}removeEventListener(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)))}}class n extends s{constructor(t){super(),this.isExternalMedia=!1,t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),t.mediaControls&&(this.media.controls=!0),t.autoplay&&(this.media.autoplay=!0),null!=t.playbackRate&&this.onceMediaEvent("canplay",(()=>{null!=t.playbackRate&&(this.media.playbackRate=t.playbackRate)}))}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e)}onceMediaEvent(t,e){return this.onMediaEvent(t,e,{once:!0})}getSrc(){return this.media.currentSrc||this.media.src||""}revokeSrc(){const t=this.getSrc();t.startsWith("blob:")&&URL.revokeObjectURL(t)}setSrc(t,e){if(this.getSrc()===t)return;this.revokeSrc();const i=e instanceof Blob?URL.createObjectURL(e):t;this.media.src=i,this.media.load()}destroy(){this.media.pause(),this.isExternalMedia||(this.media.remove(),this.revokeSrc(),this.media.src="",this.media.load())}setMediaElement(t){this.media=t}play(){return this.media.play()}pause(){this.media.pause()}isPlaying(){return!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=t}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}setPlaybackRate(t,e){null!=e&&(this.media.preservesPitch=e),this.media.playbackRate=t}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}}class r extends s{constructor(t,e){super(),this.timeouts=[],this.isScrollable=!1,this.audioData=null,this.resizeObserver=null,this.isDragging=!1,this.options=t;const i=this.parentFromOptionsContainer(t.container);this.parent=i;const[s,n]=this.initHtml();i.appendChild(s),this.container=s,this.scrollContainer=n.querySelector(".scroll"),this.wrapper=n.querySelector(".wrapper"),this.canvasWrapper=n.querySelector(".canvases"),this.progressWrapper=n.querySelector(".progress"),this.cursor=n.querySelector(".cursor"),e&&n.appendChild(e),this.initEvents()}parentFromOptionsContainer(t){let e;if("string"==typeof t?e=document.querySelector(t):t instanceof HTMLElement&&(e=t),!e)throw new Error("Container not found");return e}initEvents(){const t=t=>{const e=this.wrapper.getBoundingClientRect(),i=t.clientX-e.left,s=t.clientX-e.left;return[i/e.width,s/e.height]};this.wrapper.addEventListener("click",(e=>{const[i,s]=t(e);this.emit("click",i,s)})),this.wrapper.addEventListener("dblclick",(e=>{const[i,s]=t(e);this.emit("dblclick",i,s)})),this.options.dragToSeek&&this.initDrag(),this.scrollContainer.addEventListener("scroll",(()=>{const{scrollLeft:t,scrollWidth:e,clientWidth:i}=this.scrollContainer,s=t/e,n=(t+i)/e;this.emit("scroll",s,n)}));const e=this.createDelay(100);this.resizeObserver=new ResizeObserver((()=>{e((()=>this.reRender()))})),this.resizeObserver.observe(this.scrollContainer)}initDrag(){!function(t,e,i,s,n=3,r=0){if(!t)return()=>{};let o=()=>{};const a=a=>{if(a.button!==r)return;a.preventDefault(),a.stopPropagation();let h=a.clientX,l=a.clientY,d=!1;const c=s=>{s.preventDefault(),s.stopPropagation();const r=s.clientX,o=s.clientY,a=r-h,c=o-l;if(h=r,l=o,d||Math.abs(a)>n||Math.abs(c)>n){const s=t.getBoundingClientRect(),{left:n,top:u}=s;d||(null==i||i(h-n,l-u),d=!0),e(a,c,r-n,o-u)}},u=()=>{d&&(null==s||s()),o()},p=t=>{d&&(t.stopPropagation(),t.preventDefault())},m=t=>{d&&t.preventDefault()};document.addEventListener("pointermove",c),document.addEventListener("pointerup",u),document.addEventListener("pointerout",u),document.addEventListener("pointercancel",u),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("click",p,{capture:!0}),o=()=>{document.removeEventListener("pointermove",c),document.removeEventListener("pointerup",u),document.removeEventListener("pointerout",u),document.removeEventListener("pointercancel",u),document.removeEventListener("touchmove",m),setTimeout((()=>{document.removeEventListener("click",p,{capture:!0})}),10)}};t.addEventListener("pointerdown",a)}(this.wrapper,((t,e,i)=>{this.emit("drag",Math.max(0,Math.min(1,i/this.wrapper.getBoundingClientRect().width)))}),(()=>this.isDragging=!0),(()=>this.isDragging=!1))}getHeight(t){return null==t?128:isNaN(Number(t))?"auto"===t&&this.parent.clientHeight||128:Number(t)}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"});return e.innerHTML=`\n \n\n
\n
\n
\n
\n
\n
\n
\n `,[t,e]}setOptions(t){if(this.options.container!==t.container){const e=this.parentFromOptionsContainer(t.container);e.appendChild(this.container),this.parent=e}t.dragToSeek&&!this.options.dragToSeek&&this.initDrag(),this.options=t,this.reRender()}getWrapper(){return this.wrapper}getScroll(){return this.scrollContainer.scrollLeft}destroy(){var t;this.container.remove(),null===(t=this.resizeObserver)||void 0===t||t.disconnect()}createDelay(t=10){const e={};return this.timeouts.push(e),i=>{e.timeout&&clearTimeout(e.timeout),e.timeout=setTimeout(i,t)}}convertColorValues(t){if(!Array.isArray(t))return t||"";if(t.length<2)return t[0]||"";const e=document.createElement("canvas"),i=e.getContext("2d"),s=e.height*(window.devicePixelRatio||1),n=i.createLinearGradient(0,0,0,s),r=1/(t.length-1);return t.forEach(((t,e)=>{const i=e*r;n.addColorStop(i,t)})),n}renderBarWaveform(t,e,i,s){const n=t[0],r=t[1]||t[0],o=n.length,{width:a,height:h}=i.canvas,l=h/2,d=window.devicePixelRatio||1,c=e.barWidth?e.barWidth*d:1,u=e.barGap?e.barGap*d:e.barWidth?c/2:0,p=e.barRadius||0,m=a/(c+u)/o,v=p&&"roundRect"in i?"roundRect":"rect";i.beginPath();let g=0,f=0,b=0;for(let t=0;t<=o;t++){const o=Math.round(t*m);if(o>g){const t=Math.round(f*l*s),n=t+Math.round(b*l*s)||1;let r=l-t;"top"===e.barAlign?r=0:"bottom"===e.barAlign&&(r=h-n),i[v](g*(c+u),r,c,n,p),g=o,f=0,b=0}const a=Math.abs(n[t]||0),d=Math.abs(r[t]||0);a>f&&(f=a),d>b&&(b=d)}i.fill(),i.closePath()}renderLineWaveform(t,e,i,s){const n=e=>{const n=t[e]||t[0],r=n.length,{height:o}=i.canvas,a=o/2,h=i.canvas.width/r;i.moveTo(0,a);let l=0,d=0;for(let t=0;t<=r;t++){const r=Math.round(t*h);if(r>l){const t=a+(Math.round(d*a*s)||1)*(0===e?-1:1);i.lineTo(l,t),l=r,d=0}const o=Math.abs(n[t]||0);o>d&&(d=o)}i.lineTo(l,a)};i.beginPath(),n(0),n(1),i.fill(),i.closePath()}renderWaveform(t,e,i){if(i.fillStyle=this.convertColorValues(e.waveColor),e.renderFunction)return void e.renderFunction(t,i);let s=e.barHeight||1;if(e.normalize){const e=Array.from(t[0]).reduce(((t,e)=>Math.max(t,Math.abs(e))),0);s=e?1/e:1}e.barWidth||e.barGap||e.barAlign?this.renderBarWaveform(t,e,i,s):this.renderLineWaveform(t,e,i,s)}renderSingleCanvas(t,e,i,s,n,r,o,a){const h=window.devicePixelRatio||1,l=document.createElement("canvas"),d=t[0].length;l.width=Math.round(i*(r-n)/d),l.height=s*h,l.style.width=`${Math.floor(l.width/h)}px`,l.style.height=`${s}px`,l.style.left=`${Math.floor(n*i/h/d)}px`,o.appendChild(l);const c=l.getContext("2d");if(this.renderWaveform(t.map((t=>t.slice(n,r))),e,c),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.fillRect(0,0,l.width,l.height),a.appendChild(t)}}renderChannel(t,e,i){const s=document.createElement("div"),n=this.getHeight(e.height);s.style.height=`${n}px`,this.canvasWrapper.style.minHeight=`${n}px`,this.canvasWrapper.appendChild(s);const o=s.cloneNode();this.progressWrapper.appendChild(o);const{scrollLeft:a,scrollWidth:h,clientWidth:l}=this.scrollContainer,d=t[0].length,c=d/h;let u=Math.min(r.MAX_CANVAS_WIDTH,l);if(e.barWidth||e.barGap){const t=e.barWidth||.5,i=t+(e.barGap||t/2);u%i!=0&&(u=Math.floor(u/i)*i)}const p=Math.floor(Math.abs(a)*c),m=Math.floor(p+u*c),v=m-p,g=(r,a)=>{this.renderSingleCanvas(t,e,i,n,Math.max(0,r),Math.min(a,d),s,o)},f=this.createDelay(),b=this.createDelay(),y=(t,e)=>{g(t,e),t>0&&f((()=>{y(t-v,e-v)}))},C=(t,e)=>{g(t,e),e{C(t+v,e+v)}))};y(p,m),mt.timeout&&clearTimeout(t.timeout))),this.timeouts=[],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 e=window.devicePixelRatio||1,i=this.scrollContainer.clientWidth,s=Math.ceil(t.duration*(this.options.minPxPerSec||0));this.isScrollable=s>i;const n=this.options.fillParent&&!this.isScrollable,r=(n?i:s)*e;if(this.wrapper.style.width=n?"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.options.splitChannels)for(let e=0;e1&&e.push(t.getChannelData(1)),this.renderChannel(e,this.options,r)}this.audioData=t,this.emit("render")}reRender(){if(!this.audioData)return;const{scrollWidth:t}=this.scrollContainer,e=this.progressWrapper.clientWidth;if(this.render(this.audioData),this.isScrollable&&t!==this.scrollContainer.scrollWidth){const t=this.progressWrapper.clientWidth;this.scrollContainer.scrollLeft+=t-e}}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){const{clientWidth:i,scrollLeft:s,scrollWidth:n}=this.scrollContainer,r=n*t,o=i/2;if(r>s+(e&&this.options.autoCenter&&!this.isDragging?o:i)||r=t&&rt.toDataURL(e,i)));return Promise.resolve(s)}return Promise.all(Array.from(t).map((t=>new Promise(((s,n)=>{t.toBlob((t=>{t?s(t):n(new Error("Could not export image"))}),e,i)})))))}))}}r.MAX_CANVAS_WIDTH=4e3;class o extends s{constructor(){super(...arguments),this.unsubscribe=()=>{}}start(){this.unsubscribe=this.on("tick",(()=>{requestAnimationFrame((()=>{this.emit("tick")}))})),this.emit("tick")}stop(){this.unsubscribe()}destroy(){this.unsubscribe()}}class a extends s{constructor(t=new AudioContext){super(),this.bufferNode=null,this.autoplay=!1,this.playStartTime=0,this.playedDuration=0,this._muted=!1,this.buffer=null,this.currentSrc="",this.paused=!0,this.crossOrigin=null,this.audioContext=t,this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination)}load(){return t(this,void 0,void 0,(function*(){}))}get src(){return this.currentSrc}set src(t){this.currentSrc=t,fetch(t).then((t=>t.arrayBuffer())).then((t=>this.audioContext.decodeAudioData(t))).then((t=>{this.buffer=t,this.emit("loadedmetadata"),this.emit("canplay"),this.autoplay&&this.play()}))}_play(){var t;this.paused&&(this.paused=!1,null===(t=this.bufferNode)||void 0===t||t.disconnect(),this.bufferNode=this.audioContext.createBufferSource(),this.bufferNode.buffer=this.buffer,this.bufferNode.connect(this.gainNode),this.playedDuration>=this.duration&&(this.playedDuration=0),this.bufferNode.start(this.audioContext.currentTime,this.playedDuration),this.playStartTime=this.audioContext.currentTime,this.bufferNode.onended=()=>{this.currentTime>=this.duration&&(this.pause(),this.emit("ended"))})}_pause(){var t;this.paused||(this.paused=!0,null===(t=this.bufferNode)||void 0===t||t.stop(),this.playedDuration+=this.audioContext.currentTime-this.playStartTime)}play(){return t(this,void 0,void 0,(function*(){this._play(),this.emit("play")}))}pause(){this._pause(),this.emit("pause")}stopAt(t){var e,i;const s=t-this.currentTime;null===(e=this.bufferNode)||void 0===e||e.stop(this.audioContext.currentTime+s),null===(i=this.bufferNode)||void 0===i||i.addEventListener("ended",(()=>{this.bufferNode=null,this.pause()}),{once:!0})}setSinkId(e){return t(this,void 0,void 0,(function*(){return this.audioContext.setSinkId(e)}))}get playbackRate(){var t,e;return null!==(e=null===(t=this.bufferNode)||void 0===t?void 0:t.playbackRate.value)&&void 0!==e?e:1}set playbackRate(t){this.bufferNode&&(this.bufferNode.playbackRate.value=t)}get currentTime(){return this.paused?this.playedDuration:this.playedDuration+this.audioContext.currentTime-this.playStartTime}set currentTime(t){this.emit("seeking"),this.paused?this.playedDuration=t:(this._pause(),this.playedDuration=t,this._play()),this.emit("timeupdate")}get duration(){var t;return(null===(t=this.buffer)||void 0===t?void 0:t.duration)||0}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))}getGainNode(){return this.gainNode}}const h={waveColor:"#999",progressColor:"#555",cursorWidth:1,minPxPerSec:0,fillParent:!0,interact:!0,dragToSeek:!1,autoScroll:!0,autoCenter:!0,sampleRate:8e3};class l extends n{static create(t){return new l(t)}constructor(t){const e=t.media||("WebAudio"===t.backend?new a:void 0);super({media:e,mediaControls:t.mediaControls,autoplay:t.autoplay,playbackRate:t.audioRate}),this.plugins=[],this.decodedData=null,this.subscriptions=[],this.mediaSubscriptions=[],this.options=Object.assign({},h,t),this.timer=new o;const i=e?void 0:this.getMediaElement();this.renderer=new r(this.options,i),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initPlugins();const s=this.options.url||this.getSrc()||"";(s||this.options.peaks&&this.options.duration)&&this.load(s,this.options.peaks,this.options.duration)}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),!0),this.emit("timeupdate",t),this.emit("audioprocess",t)})))}initPlayerEvents(){this.isPlaying()&&(this.emit("play"),this.timer.start()),this.mediaSubscriptions.push(this.onMediaEvent("timeupdate",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),this.emit("timeupdate",t)})),this.onMediaEvent("play",(()=>{this.emit("play"),this.timer.start()})),this.onMediaEvent("pause",(()=>{this.emit("pause"),this.timer.stop()})),this.onMediaEvent("emptied",(()=>{this.timer.stop()})),this.onMediaEvent("ended",(()=>{this.emit("finish")})),this.onMediaEvent("seeking",(()=>{this.emit("seeking",this.getCurrentTime())})))}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)=>{const i=this.getDuration();this.emit("scroll",t*i,e*i)})),this.renderer.on("render",(()=>{this.emit("redraw")})));{let t;this.subscriptions.push(this.renderer.on("drag",(e=>{this.options.interact&&(this.renderer.renderProgress(e),clearTimeout(t),t=setTimeout((()=>{this.seekTo(e)}),this.isPlaying()?0:200),this.emit("interaction",e*this.getDuration()),this.emit("drag",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),this.renderer.setOptions(this.options),t.audioRate&&this.setPlaybackRate(t.audioRate),null!=t.mediaControls&&(this.getMediaElement().controls=t.mediaControls)}registerPlugin(t){return t.init(this),this.plugins.push(t),this.subscriptions.push(t.once("destroy",(()=>{this.plugins=this.plugins.filter((e=>e!==t))}))),t}getWrapper(){return this.renderer.getWrapper()}getScroll(){return this.renderer.getScroll()}getActivePlugins(){return this.plugins}loadAudio(s,n,r,o){return t(this,void 0,void 0,(function*(){if(this.emit("load",s),!this.options.media&&this.isPlaying()&&this.pause(),this.decodedData=null,!n&&!r){const t=t=>this.emit("loading",t);n=yield i.fetchBlob(s,t,this.options.fetchParams)}this.setSrc(s,n);const t=(yield Promise.resolve(o||this.getDuration()))||(yield new Promise((t=>{this.onceMediaEvent("loadedmetadata",(()=>t(this.getDuration())))})));if(r)this.decodedData=e.createBuffer(r,t||0);else if(n){const t=yield n.arrayBuffer();this.decodedData=yield e.decode(t,this.options.sampleRate)}this.decodedData&&(this.emit("decode",this.getDuration()),this.renderer.render(this.decodedData)),this.emit("ready",this.getDuration())}))}load(e,i,s){return t(this,void 0,void 0,(function*(){yield this.loadAudio(e,void 0,i,s)}))}loadBlob(e,i,s){return t(this,void 0,void 0,(function*(){yield this.loadAudio("blob",e,i,s)}))}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 s=Math.min(t,this.decodedData.numberOfChannels),n=[];for(let t=0;tMath.abs(n)&&(n=i)}r.push(Math.round(n*i)/i)}n.push(r)}return n}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}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}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(e="image/png",i=1,s="dataURL"){return t(this,void 0,void 0,(function*(){return this.renderer.exportImage(e,i,s)}))}destroy(){this.emit("destroy"),this.plugins.forEach((t=>t.destroy())),this.subscriptions.forEach((t=>t())),this.unsubscribePlayerEvents(),this.timer.destroy(),this.renderer.destroy(),super.destroy()}}export{l as default}; +/*! wavesurfer.js 1.4.0 (Mon, 10 Apr 2017 08:55:35 GMT) +* https://github.com/katspaugh/wavesurfer.js +* @license BSD-3-Clause */ +!function(a,b){"function"==typeof define&&define.amd?define("wavesurfer",[],function(){return a.WaveSurfer=b()}):"object"==typeof exports?module.exports=b():a.WaveSurfer=b()}(this,function(){"use strict";var a={defaultParams:{audioContext:null,audioRate:1,autoCenter:!0,backend:"WebAudio",barHeight:1,closeAudioContext:!1,container:null,cursorColor:"#333",cursorWidth:1,dragSelection:!0,fillParent:!0,forceDecode:!1,height:128,hideScrollbar:!1,interact:!0,loopSelection:!0,mediaContainer:null,mediaControls:!1,mediaType:"audio",minPxPerSec:20,partialRender:!1,pixelRatio:window.devicePixelRatio||screen.deviceXDPI/screen.logicalXDPI,progressColor:"#555",normalize:!1,renderer:"MultiCanvas",scrollParent:!1,skipLength:2,splitChannels:!1,waveColor:"#999"},init:function(b){if(this.params=a.util.extend({},this.defaultParams,b),this.container="string"==typeof b.container?document.querySelector(this.params.container):this.params.container,!this.container)throw new Error("Container element not found");if(null==this.params.mediaContainer?this.mediaContainer=this.container:"string"==typeof this.params.mediaContainer?this.mediaContainer=document.querySelector(this.params.mediaContainer):this.mediaContainer=this.params.mediaContainer,!this.mediaContainer)throw new Error("Media Container element not found");this.savedVolume=0,this.isMuted=!1,this.tmpEvents=[],this.currentAjax=null,this.createDrawer(),this.createBackend(),this.createPeakCache(),this.isDestroyed=!1},createDrawer:function(){var b=this;this.drawer=Object.create(a.Drawer[this.params.renderer]),this.drawer.init(this.container,this.params),this.drawer.on("redraw",function(){b.drawBuffer(),b.drawer.progress(b.backend.getPlayedPercents())}),this.drawer.on("click",function(a,c){setTimeout(function(){b.seekTo(c)},0)}),this.drawer.on("scroll",function(a){b.params.partialRender&&b.drawBuffer(),b.fireEvent("scroll",a)})},createBackend:function(){var b=this;this.backend&&this.backend.destroy(),"AudioElement"==this.params.backend&&(this.params.backend="MediaElement"),"WebAudio"!=this.params.backend||a.WebAudio.supportsWebAudio()||(this.params.backend="MediaElement"),this.backend=Object.create(a[this.params.backend]),this.backend.init(this.params),this.backend.on("finish",function(){b.fireEvent("finish")}),this.backend.on("play",function(){b.fireEvent("play")}),this.backend.on("pause",function(){b.fireEvent("pause")}),this.backend.on("audioprocess",function(a){b.drawer.progress(b.backend.getPlayedPercents()),b.fireEvent("audioprocess",a)})},createPeakCache:function(){this.params.partialRender&&(this.peakCache=Object.create(a.PeakCache),this.peakCache.init())},getDuration:function(){return this.backend.getDuration()},getCurrentTime:function(){return this.backend.getCurrentTime()},play:function(a,b){this.fireEvent("interaction",this.play.bind(this,a,b)),this.backend.play(a,b)},pause:function(){this.backend.isPaused()||this.backend.pause()},playPause:function(){this.backend.isPaused()?this.play():this.pause()},isPlaying:function(){return!this.backend.isPaused()},skipBackward:function(a){this.skip(-a||-this.params.skipLength)},skipForward:function(a){this.skip(a||this.params.skipLength)},skip:function(a){var b=this.getCurrentTime()||0,c=this.getDuration()||1;b=Math.max(0,Math.min(c,b+(a||0))),this.seekAndCenter(b/c)},seekAndCenter:function(a){this.seekTo(a),this.drawer.recenter(a)},seekTo:function(a){this.fireEvent("interaction",this.seekTo.bind(this,a));var b=this.backend.isPaused();b||this.backend.pause();var c=this.params.scrollParent;this.params.scrollParent=!1,this.backend.seekTo(a*this.getDuration()),this.drawer.progress(this.backend.getPlayedPercents()),b||this.backend.play(),this.params.scrollParent=c,this.fireEvent("seek",a)},stop:function(){this.pause(),this.seekTo(0),this.drawer.progress(0)},setVolume:function(a){this.backend.setVolume(a)},getVolume:function(){return this.backend.getVolume()},setPlaybackRate:function(a){this.backend.setPlaybackRate(a)},getPlaybackRate:function(){return this.backend.getPlaybackRate()},toggleMute:function(){this.setMute(!this.isMuted)},setMute:function(a){a!==this.isMuted&&(a?(this.savedVolume=this.backend.getVolume(),this.backend.setVolume(0),this.isMuted=!0):(this.backend.setVolume(this.savedVolume),this.isMuted=!1))},getMute:function(){return this.isMuted},getFilters:function(){return this.backend.filters||[]},toggleScroll:function(){this.params.scrollParent=!this.params.scrollParent,this.drawBuffer()},toggleInteraction:function(){this.params.interact=!this.params.interact},drawBuffer:function(){var a=Math.round(this.getDuration()*this.params.minPxPerSec*this.params.pixelRatio),b=this.drawer.getWidth(),c=a,d=this.drawer.getScrollX(),e=Math.min(d+b,c);if(this.params.fillParent&&(!this.params.scrollParent||ab&&(b=a[c]);return b},getId:function(){return"wavesurfer_"+Math.random().toString(32).substring(2)},ajax:function(b){var c=Object.create(a.Observer),d=new XMLHttpRequest,e=!1;return d.open(b.method||"GET",b.url,!0),d.responseType=b.responseType||"json",d.addEventListener("progress",function(a){c.fireEvent("progress",a),a.lengthComputable&&a.loaded==a.total&&(e=!0)}),d.addEventListener("load",function(a){e||c.fireEvent("progress",a),c.fireEvent("load",a),200==d.status||206==d.status?c.fireEvent("success",d.response,a):c.fireEvent("error",a)}),d.addEventListener("error",function(a){c.fireEvent("error",a)}),d.send(),c.xhr=d,c}},a.Observer={on:function(a,b){this.handlers||(this.handlers={});var c=this.handlers[a];return c||(c=this.handlers[a]=[]),c.push(b),{name:a,callback:b,un:this.un.bind(this,a,b)}},un:function(a,b){if(this.handlers){var c=this.handlers[a];if(c)if(b)for(var d=c.length-1;d>=0;d--)c[d]==b&&c.splice(d,1);else c.length=0}},unAll:function(){this.handlers=null},once:function(a,b){var c=this,d=function(){b.apply(this,arguments),setTimeout(function(){c.un(a,d)},0)};return this.on(a,d)},fireEvent:function(a){if(this.handlers){var b=this.handlers[a],c=Array.prototype.slice.call(arguments,1);b&&b.forEach(function(a){a.apply(null,c)})}}},a.util.extend(a,a.Observer),a.WebAudio={scriptBufferSize:256,PLAYING_STATE:0,PAUSED_STATE:1,FINISHED_STATE:2,supportsWebAudio:function(){return!(!window.AudioContext&&!window.webkitAudioContext)},getAudioContext:function(){return a.WebAudio.audioContext||(a.WebAudio.audioContext=new(window.AudioContext||window.webkitAudioContext)),a.WebAudio.audioContext},getOfflineAudioContext:function(b){return a.WebAudio.offlineAudioContext||(a.WebAudio.offlineAudioContext=new(window.OfflineAudioContext||window.webkitOfflineAudioContext)(1,2,b)),a.WebAudio.offlineAudioContext},init:function(b){this.params=b,this.ac=b.audioContext||this.getAudioContext(),this.lastPlay=this.ac.currentTime,this.startPosition=0,this.scheduledPause=null,this.states=[Object.create(a.WebAudio.state.playing),Object.create(a.WebAudio.state.paused),Object.create(a.WebAudio.state.finished)],this.createVolumeNode(),this.createScriptNode(),this.createAnalyserNode(),this.setState(this.PAUSED_STATE),this.setPlaybackRate(this.params.audioRate),this.setLength(0)},disconnectFilters:function(){this.filters&&(this.filters.forEach(function(a){a&&a.disconnect()}),this.filters=null,this.analyser.connect(this.gainNode))},setState:function(a){this.state!==this.states[a]&&(this.state=this.states[a],this.state.init.call(this))},setFilter:function(){this.setFilters([].slice.call(arguments))},setFilters:function(a){this.disconnectFilters(),a&&a.length&&(this.filters=a,this.analyser.disconnect(),a.reduce(function(a,b){return a.connect(b),b},this.analyser).connect(this.gainNode))},createScriptNode:function(){this.ac.createScriptProcessor?this.scriptNode=this.ac.createScriptProcessor(this.scriptBufferSize):this.scriptNode=this.ac.createJavaScriptNode(this.scriptBufferSize),this.scriptNode.connect(this.ac.destination)},addOnAudioProcess:function(){var a=this;this.scriptNode.onaudioprocess=function(){var b=a.getCurrentTime();b>=a.getDuration()?(a.setState(a.FINISHED_STATE),a.fireEvent("pause")):b>=a.scheduledPause?a.pause():a.state===a.states[a.PLAYING_STATE]&&a.fireEvent("audioprocess",b)}},removeOnAudioProcess:function(){this.scriptNode.onaudioprocess=null},createAnalyserNode:function(){this.analyser=this.ac.createAnalyser(),this.analyser.connect(this.gainNode)},createVolumeNode:function(){this.ac.createGain?this.gainNode=this.ac.createGain():this.gainNode=this.ac.createGainNode(),this.gainNode.connect(this.ac.destination)},setVolume:function(a){this.gainNode.gain.value=a},getVolume:function(){return this.gainNode.gain.value},decodeArrayBuffer:function(a,b,c){this.offlineAc||(this.offlineAc=this.getOfflineAudioContext(this.ac?this.ac.sampleRate:44100)),this.offlineAc.decodeAudioData(a,function(a){b(a)}.bind(this),c)},setPeaks:function(a){this.peaks=a},setLength:function(a){if(!this.mergedPeaks||a!=2*this.mergedPeaks.length-1+2){this.splitPeaks=[],this.mergedPeaks=[];for(var b=this.buffer?this.buffer.numberOfChannels:1,c=0;cn&&(n=p),pthis.mergedPeaks[2*j])&&(this.mergedPeaks[2*j]=n),(0==g||m=this.getDuration()&&(a=0)),null==b&&(b=this.getDuration()),this.startPosition=a,this.lastPlay=this.ac.currentTime,this.state===this.states[this.FINISHED_STATE]&&this.setState(this.PAUSED_STATE),{start:a,end:b}},getPlayedTime:function(){return(this.ac.currentTime-this.lastPlay)*this.playbackRate},play:function(a,b){if(this.buffer){this.createSource();var c=this.seekTo(a,b);a=c.start,b=c.end,this.scheduledPause=b,this.source.start(0,a,b-a),"suspended"==this.ac.state&&this.ac.resume&&this.ac.resume(),this.setState(this.PLAYING_STATE),this.fireEvent("play")}},pause:function(){this.scheduledPause=null,this.startPosition+=this.getPlayedTime(),this.source&&this.source.stop(0),this.setState(this.PAUSED_STATE),this.fireEvent("pause")},getCurrentTime:function(){return this.state.getCurrentTime.call(this)},getPlaybackRate:function(){return this.playbackRate},setPlaybackRate:function(a){a=a||1,this.isPaused()?this.playbackRate=a:(this.pause(),this.playbackRate=a,this.play())}},a.WebAudio.state={},a.WebAudio.state.playing={init:function(){this.addOnAudioProcess()},getPlayedPercents:function(){var a=this.getDuration();return this.getCurrentTime()/a||0},getCurrentTime:function(){return this.startPosition+this.getPlayedTime()}},a.WebAudio.state.paused={init:function(){this.removeOnAudioProcess()},getPlayedPercents:function(){var a=this.getDuration();return this.getCurrentTime()/a||0},getCurrentTime:function(){return this.startPosition}},a.WebAudio.state.finished={init:function(){this.removeOnAudioProcess(),this.fireEvent("finish")},getPlayedPercents:function(){return 1},getCurrentTime:function(){return this.getDuration()}},a.util.extend(a.WebAudio,a.Observer),a.MediaElement=Object.create(a.WebAudio),a.util.extend(a.MediaElement,{init:function(a){this.params=a,this.media={currentTime:0,duration:0,paused:!0,playbackRate:1,play:function(){},pause:function(){}},this.mediaType=a.mediaType.toLowerCase(),this.elementPosition=a.elementPosition,this.setPlaybackRate(this.params.audioRate),this.createTimer()},createTimer:function(){var a=this,b=function(){if(!a.isPaused()){a.fireEvent("audioprocess",a.getCurrentTime());var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame;c(b)}};this.on("play",b)},load:function(a,b,c,d){var e=document.createElement(this.mediaType);e.controls=this.params.mediaControls,e.autoplay=this.params.autoplay||!1,e.preload=null==d?"auto":d,e.src=a,e.style.width="100%";var f=b.querySelector(this.mediaType);f&&b.removeChild(f),b.appendChild(e),this._load(e,c)},loadElt:function(a,b){var c=a;c.controls=this.params.mediaControls,c.autoplay=this.params.autoplay||!1,this._load(c,b)},_load:function(a,b){var c=this;"function"==typeof a.load&&a.load(),a.addEventListener("error",function(){c.fireEvent("error","Error loading media element")}),a.addEventListener("canplay",function(){c.fireEvent("canplay")}),a.addEventListener("ended",function(){c.fireEvent("finish")}),this.media=a,this.peaks=b,this.onPlayEnd=null,this.buffer=null,this.setPlaybackRate(this.playbackRate)},isPaused:function(){return!this.media||this.media.paused},getDuration:function(){var a=(this.buffer||this.media).duration;return a>=1/0&&(a=this.media.seekable.end(0)),a},getCurrentTime:function(){return this.media&&this.media.currentTime},getPlayedPercents:function(){return this.getCurrentTime()/this.getDuration()||0},getPlaybackRate:function(){return this.playbackRate||this.media.playbackRate},setPlaybackRate:function(a){this.playbackRate=a||1,this.media.playbackRate=this.playbackRate},seekTo:function(a){null!=a&&(this.media.currentTime=a),this.clearPlayEnd()},play:function(a,b){this.seekTo(a),this.media.play(),b&&this.setPlayEnd(b),this.fireEvent("play")},pause:function(){this.media&&this.media.pause(),this.clearPlayEnd(),this.fireEvent("pause")},setPlayEnd:function(a){var b=this;this.onPlayEnd=function(c){c>=a&&(b.pause(),b.seekTo(a))},this.on("audioprocess",this.onPlayEnd)},clearPlayEnd:function(){this.onPlayEnd&&(this.un("audioprocess",this.onPlayEnd),this.onPlayEnd=null)},getPeaks:function(b,c,d){return this.buffer?a.WebAudio.getPeaks.call(this,b,c,d):this.peaks||[]},getVolume:function(){return this.media.volume},setVolume:function(a){this.media.volume=a},destroy:function(){this.pause(),this.unAll(),this.media&&this.media.parentNode&&this.media.parentNode.removeChild(this.media),this.media=null}}),a.AudioElement=a.MediaElement,a.Drawer={init:function(a,b){this.container=a,this.params=b,this.width=0,this.height=b.height*this.params.pixelRatio,this.lastPos=0,this.initDrawer(b),this.createWrapper(),this.createElements()},createWrapper:function(){this.wrapper=this.container.appendChild(document.createElement("wave")),this.style(this.wrapper,{display:"block",position:"relative",userSelect:"none",webkitUserSelect:"none",height:this.params.height+"px"}),(this.params.fillParent||this.params.scrollParent)&&this.style(this.wrapper,{width:"100%",overflowX:this.params.hideScrollbar?"hidden":"auto",overflowY:"hidden"}),this.setupWrapperEvents()},handleEvent:function(a,b){!b&&a.preventDefault();var c,d=a.targetTouches?a.targetTouches[0].clientX:a.clientX,e=this.wrapper.getBoundingClientRect(),f=this.width,g=this.getWidth();return!this.params.fillParent&&f1&&(c=1)):c=(d-e.left+this.wrapper.scrollLeft)/this.wrapper.scrollWidth||0,c},setupWrapperEvents:function(){var a=this;this.wrapper.addEventListener("click",function(b){var c=a.wrapper.offsetHeight-a.wrapper.clientHeight;if(0!=c){var d=a.wrapper.getBoundingClientRect();if(b.clientY>=d.bottom-c)return}a.params.interact&&a.fireEvent("click",b,a.handleEvent(b))}),this.wrapper.addEventListener("scroll",function(b){a.fireEvent("scroll",b)})},drawPeaks:function(a,b,c,d){this.setWidth(b),this.params.barWidth?this.drawBars(a,0,c,d):this.drawWave(a,0,c,d)},style:function(a,b){return Object.keys(b).forEach(function(c){a.style[c]!==b[c]&&(a.style[c]=b[c])}),a},resetScroll:function(){null!==this.wrapper&&(this.wrapper.scrollLeft=0)},recenter:function(a){var b=this.wrapper.scrollWidth*a;this.recenterOnPosition(b,!0)},recenterOnPosition:function(a,b){var c=this.wrapper.scrollLeft,d=~~(this.wrapper.clientWidth/2),e=a-d,f=e-c,g=this.wrapper.scrollWidth-this.wrapper.clientWidth;if(0!=g){if(!b&&-d<=f&&f=b){if(this.lastPos=c,this.params.scrollParent&&this.params.autoCenter){var d=~~(this.wrapper.scrollWidth*a);this.recenterOnPosition(d)}this.updateProgress(c)}},destroy:function(){this.unAll(),this.wrapper&&(this.container.removeChild(this.wrapper),this.wrapper=null)},initDrawer:function(){},createElements:function(){},updateSize:function(){},drawWave:function(a,b){},clearWave:function(){},updateProgress:function(a){}},a.util.extend(a.Drawer,a.Observer),a.Drawer.Canvas=Object.create(a.Drawer),a.util.extend(a.Drawer.Canvas,{createElements:function(){var a=this.wrapper.appendChild(this.style(document.createElement("canvas"),{position:"absolute",zIndex:1,left:0,top:0,bottom:0}));if(this.waveCc=a.getContext("2d"),this.progressWave=this.wrapper.appendChild(this.style(document.createElement("wave"),{position:"absolute",zIndex:2,left:0,top:0,bottom:0,overflow:"hidden",width:"0",display:"none",boxSizing:"border-box",borderRightStyle:"solid",borderRightWidth:this.params.cursorWidth+"px",borderRightColor:this.params.cursorColor})),this.params.waveColor!=this.params.progressColor){var b=this.progressWave.appendChild(document.createElement("canvas"));this.progressCc=b.getContext("2d")}},updateSize:function(){var a=Math.round(this.width/this.params.pixelRatio);this.waveCc.canvas.width=this.width,this.waveCc.canvas.height=this.height,this.style(this.waveCc.canvas,{width:a+"px"}),this.style(this.progressWave,{display:"block"}),this.progressCc&&(this.progressCc.canvas.width=this.width,this.progressCc.canvas.height=this.height,this.style(this.progressCc.canvas,{width:a+"px"})),this.clearWave()},clearWave:function(){this.waveCc.clearRect(0,0,this.width,this.height),this.progressCc&&this.progressCc.clearRect(0,0,this.width,this.height)},drawBars:function(b,c,d,e){var f=this;if(b[0]instanceof Array){var g=b;if(this.params.splitChannels)return this.setHeight(g.length*this.params.height*this.params.pixelRatio),void g.forEach(function(a,b){f.drawBars(a,b,d,e)});b=g[0]}var h=[].some.call(b,function(a){return a<0}),i=1;h&&(i=2);var j=.5/this.params.pixelRatio,k=this.width,l=this.params.height*this.params.pixelRatio,m=l*c||0,n=l/2,o=b.length/i,p=this.params.barWidth*this.params.pixelRatio,q=Math.max(this.params.pixelRatio,~~(p/2)),r=p+q,s=1/this.params.barHeight;if(this.params.normalize){var t=a.util.max(b),u=a.util.min(b);s=-u>t?-u:t}var v=o/k;this.waveCc.fillStyle=this.params.waveColor,this.progressCc&&(this.progressCc.fillStyle=this.params.progressColor),[this.waveCc,this.progressCc].forEach(function(a){if(a)for(var c=d/v;cs?-t:s}this.waveCc.fillStyle=this.params.waveColor,this.progressCc&&(this.progressCc.fillStyle=this.params.progressColor),[this.waveCc,this.progressCc].forEach(function(a){if(a){a.beginPath(),a.moveTo(d*q+l,o+n);for(var c=d;c=d;c--){var f=Math.round(b[2*c+1]/r*o);a.lineTo(c*q+l,o-f+n)}a.closePath(),a.fill(),a.fillRect(0,o+n-l,this.width,l)}},this)},updateProgress:function(a){this.style(this.progressWave,{width:a+"px"})},getImage:function(a,b){return this.waveCc.canvas.toDataURL(a,b)}}),a.Drawer.MultiCanvas=Object.create(a.Drawer),a.util.extend(a.Drawer.MultiCanvas,{initDrawer:function(a){if(this.maxCanvasWidth=null!=a.maxCanvasWidth?a.maxCanvasWidth:4e3,this.maxCanvasElementWidth=Math.round(this.maxCanvasWidth/this.params.pixelRatio),this.maxCanvasWidth<=1)throw"maxCanvasWidth must be greater than 1.";if(this.maxCanvasWidth%2==1)throw"maxCanvasWidth must be an even number.";this.hasProgressCanvas=this.params.waveColor!=this.params.progressColor,this.halfPixel=.5/this.params.pixelRatio,this.canvases=[]},createElements:function(){this.progressWave=this.wrapper.appendChild(this.style(document.createElement("wave"),{position:"absolute",zIndex:2,left:0,top:0,bottom:0,overflow:"hidden",width:"0",display:"none",boxSizing:"border-box",borderRightStyle:"solid",borderRightWidth:this.params.cursorWidth+"px",borderRightColor:this.params.cursorColor})),this.addCanvas()},updateSize:function(){for(var a=Math.round(this.width/this.params.pixelRatio),b=Math.ceil(a/this.maxCanvasElementWidth);this.canvases.lengthb;)this.removeCanvas();for(var c in this.canvases){var d=this.maxCanvasWidth+2*Math.ceil(this.params.pixelRatio/2);c==this.canvases.length-1&&(d=this.width-this.maxCanvasWidth*(this.canvases.length-1)),this.updateDimensions(this.canvases[c],d,this.height),this.clearWaveForEntry(this.canvases[c])}},addCanvas:function(){var a={},b=this.maxCanvasElementWidth*this.canvases.length;a.wave=this.wrapper.appendChild(this.style(document.createElement("canvas"),{position:"absolute",zIndex:1,left:b+"px",top:0,bottom:0,height:"100%"})),a.waveCtx=a.wave.getContext("2d"),this.hasProgressCanvas&&(a.progress=this.progressWave.appendChild(this.style(document.createElement("canvas"),{position:"absolute",left:b+"px",top:0,bottom:0,height:"100%"})),a.progressCtx=a.progress.getContext("2d")),this.canvases.push(a)},removeCanvas:function(){var a=this.canvases.pop();a.wave.parentElement.removeChild(a.wave),this.hasProgressCanvas&&a.progress.parentElement.removeChild(a.progress)},updateDimensions:function(a,b,c){var d=Math.round(b/this.params.pixelRatio),e=Math.round(this.width/this.params.pixelRatio);a.start=a.waveCtx.canvas.offsetLeft/e||0,a.end=a.start+d/e,a.waveCtx.canvas.width=b,a.waveCtx.canvas.height=c,this.style(a.waveCtx.canvas,{width:d+"px"}),this.style(this.progressWave,{display:"block"}),this.hasProgressCanvas&&(a.progressCtx.canvas.width=b,a.progressCtx.canvas.height=c,this.style(a.progressCtx.canvas,{width:d+"px"}))},clearWave:function(){for(var a in this.canvases)this.clearWaveForEntry(this.canvases[a])},clearWaveForEntry:function(a){a.waveCtx.clearRect(0,0,a.waveCtx.canvas.width,a.waveCtx.canvas.height),this.hasProgressCanvas&&a.progressCtx.clearRect(0,0,a.progressCtx.canvas.width,a.progressCtx.canvas.height)},drawBars:function(b,c,d,e){var f=this;if(b[0]instanceof Array){var g=b;if(this.params.splitChannels)return this.setHeight(g.length*this.params.height*this.params.pixelRatio),void g.forEach(function(a,b){f.drawBars(a,b,d,e)});b=g[0]}var h=[].some.call(b,function(a){return a<0}),i=1;h&&(i=2);var j=this.width,k=this.params.height*this.params.pixelRatio,l=k*c||0,m=k/2,n=b.length/i,o=this.params.barWidth*this.params.pixelRatio,p=Math.max(this.params.pixelRatio,~~(o/2)),q=o+p,r=1/this.params.barHeight;if(this.params.normalize){var s=a.util.max(b),t=a.util.min(b);r=-t>s?-t:s}for(var u=n/j,v=d/u;vp?-q:p}this.drawLine(b,o,n,m,d,e),this.fillRect(0,n+m-this.halfPixel,this.width,this.halfPixel)},drawLine:function(a,b,c,d,e,f){for(var g in this.canvases){var h=this.canvases[g];this.setFillStyles(h),this.drawLineToContext(h,h.waveCtx,a,b,c,d,e,f),this.drawLineToContext(h,h.progressCtx,a,b,c,d,e,f)}},drawLineToContext:function(a,b,c,d,e,f,g,h){if(b){var i=c.length/2,j=1;this.params.fillParent&&this.width!=i&&(j=this.width/i);var k=Math.round(i*a.start),l=Math.round(i*a.end);if(!(k>h||l=m;o--){var p=c[2*o+1]||0,q=Math.round(p/d*e);b.lineTo((o-k)*j+this.halfPixel,e-q+f)}b.closePath(),b.fill()}}},fillRect:function(a,b,c,d){for(var e=Math.floor(a/this.maxCanvasWidth),f=Math.min(Math.ceil((a+c)/this.maxCanvasWidth)+1,this.canvases.length),g=e;g1?c:c[0]}}),a.Drawer.SplitWavePointPlot=Object.create(a.Drawer.Canvas),a.util.extend(a.Drawer.SplitWavePointPlot,{defaultPlotParams:{plotNormalizeTo:"whole",plotTimeStart:0,plotMin:0, +plotMax:1,plotColor:"#f63",plotProgressColor:"#F00",plotPointHeight:2,plotPointWidth:2,plotSeparator:!0,plotSeparatorColor:"black",plotRangeDisplay:!1,plotRangeUnits:"",plotRangePrecision:4,plotRangeIgnoreOutliers:!1,plotRangeFontSize:12,plotRangeFontType:"Ariel",waveDrawMedianLine:!0,plotFileDelimiter:"\t"},plotTimeStart:0,plotTimeEnd:-1,plotArrayLoaded:!1,plotArray:[],plotPoints:[],plotMin:0,plotMax:1,initDrawer:function(a){var b=this;for(var c in this.defaultPlotParams)void 0===this.params[c]&&(this.params[c]=this.defaultPlotParams[c]);if(this.plotTimeStart=this.params.plotTimeStart,void 0!==this.params.plotTimeEnd&&(this.plotTimeEnd=this.params.plotTimeEnd),Array.isArray(a.plotArray))this.plotArray=a.plotArray,this.plotArrayLoaded=!0;else{var d=function(a){b.plotArray=a,b.plotArrayLoaded=!0,b.fireEvent("plot_array_loaded")};this.loadPlotArrayFromFile(a.plotFileUrl,d,this.params.plotFileDelimiter)}},drawPeaks:function(a,b,c,d){if(1==this.plotArrayLoaded)this.setWidth(b),this.splitChannels=!0,this.params.height=this.params.height/2,a[0]instanceof Array&&(a=a[0]),this.params.barWidth?this.drawBars(a,1,c,d):this.drawWave(a,1,c,d),this.params.height=2*this.params.height,this.calculatePlots(),this.drawPlots();else{var e=this;e.on("plot-array-loaded",function(){e.drawPeaks(a,b,c,d)})}},drawPlots:function(){var a=this.params.height*this.params.pixelRatio/2,b=.5/this.params.pixelRatio;this.waveCc.fillStyle=this.params.plotColor,this.progressCc&&(this.progressCc.fillStyle=this.params.plotProgressColor);for(var c in this.plotPoints){var d=parseInt(c),e=a-this.params.plotPointHeight-this.plotPoints[c]*(a-this.params.plotPointHeight),f=this.params.plotPointHeight;this.waveCc.fillRect(d,e,this.params.plotPointWidth,f),this.progressCc&&this.progressCc.fillRect(d,e,this.params.plotPointWidth,f)}this.params.plotSeparator&&(this.waveCc.fillStyle=this.params.plotSeparatorColor,this.waveCc.fillRect(0,a,this.width,b)),this.params.plotRangeDisplay&&this.displayPlotRange()},displayPlotRange:function(){var a=this.params.plotRangeFontSize*this.params.pixelRatio,b=this.plotMax.toPrecision(this.params.plotRangePrecision)+" "+this.params.plotRangeUnits,c=this.plotMin.toPrecision(this.params.plotRangePrecision)+" "+this.params.plotRangeUnits;this.waveCc.font=a.toString()+"px "+this.params.plotRangeFontType,this.waveCc.fillText(b,3,a),this.waveCc.fillText(c,3,this.height/2)},calculatePlots:function(){this.plotPoints={},this.calculatePlotTimeEnd();for(var a=[],b=-1,c=0,d=99999999999999,e=0,f=99999999999999,g=this.plotTimeEnd-this.plotTimeStart,h=0;hc&&(c=i.value),i.value=this.plotTimeStart&&i.time<=this.plotTimeEnd){var j=Math.round(this.width*(i.time-this.plotTimeStart)/g);if(a.push(i.value),j!==b&&a.length>0){var k=this.avg(a);k>e&&(e=k),k1?this.params.plotRangeIgnoreOutliers||(a[b]=1):c<0?this.params.plotRangeIgnoreOutliers||(a[b]=0):a[b]=c}this.plotPoints=a}},loadPlotArrayFromFile:function(b,c,d){void 0===d&&(d="\t");var e=[],f={url:b,responseType:"text"},g=a.util.ajax(f);g.on("load",function(a){if(200==a.currentTarget.status){for(var b=a.currentTarget.responseText.split("\n"),f=0;f`); render($page); @@ -38,7 +40,7 @@ export default async function(render) { color: var(--color); font-size: 0.8rem; "> - search_dark + search + `)), applyMutation($page, "replaceChildren"), diff --git a/public/assets/pages/viewerpage/application_audio.css b/public/assets/pages/viewerpage/application_audio.css index ee04bef2..6ab11f2f 100644 --- a/public/assets/pages/viewerpage/application_audio.css +++ b/public/assets/pages/viewerpage/application_audio.css @@ -28,7 +28,7 @@ body:not(.dark-mode) .component_audioplayer > .audioplayer_container { box-shadow: rgba(0, 0, 0, 0.14) 0px 4px 5px 0px, rgba(0, 0, 0, 0.12) 0px 1px 10px 0px, rgba(0, 0, 0, 0.2) 0px 2px 4px -1px; position: relative; border-radius: 3px; - padding: 10px 0 30px 0; + padding: 10px 0 15px 0; } .component_audioplayer > .audioplayer_container .audioplayer_box .audioplayer_control { padding-top: 20px; diff --git a/public/assets/pages/viewerpage/application_audio.js b/public/assets/pages/viewerpage/application_audio.js index 1c348f63..9675a621 100644 --- a/public/assets/pages/viewerpage/application_audio.js +++ b/public/assets/pages/viewerpage/application_audio.js @@ -1,37 +1,199 @@ import { createElement } from "../../lib/skeleton/index.js"; +import rxjs, { effect, onClick } from "../../lib/rx.js"; +import { qs } from "../../lib/dom.js"; import { onDestroy } from "../../lib/skeleton/lifecycle.js"; -import rxjs, { effect } from "../../lib/rx.js"; -import WaveSurfer from "../../lib/vendor/wavesurfer.js"; -import { loadCSS } from "../../helpers/loader.js"; +import { loadCSS, loadJS } from "../../helpers/loader.js"; +import { settings_get, settings_put } from "../../lib/settings.js"; -import { getDownloadUrl } from "./common.js"; +import ctrlError from "../ctrl_error.js"; + +import { ICON } from "./common_icon.js"; +import { transition, getDownloadUrl } from "./common.js"; import "../../components/menubar.js"; +const STATUS_PLAYING = "PLAYING"; +const STATUS_PAUSED = "PAUSED"; +const STATUS_BUFFERING = "BUFFERING"; + export default function(render) { const $page = createElement(` -
+
-
+
+
+
+
+ 31% + loading +
+
+
+
+ + play + + + + volume + + +
+
+ 00:00 + / + 02:13 +
+
+
+
`); render($page); + transition(qs($page, ".audioplayer_box")); - const wavesurfer = WaveSurfer.create({ - container: "#waveform", - interact: false, + const $control = { + play: qs($page, `.audioplayer_control [alt="play"]`), + pause: qs($page, `.audioplayer_control [alt="pause"]`), + // loading: qs($page, `.audioplayer_control component-icon[name="loading"]`), + }; + const $volume = { + range: qs($page, `input[type="range"]`), + // icon_mute: qs($page, `img[alt="volume_mute"]`), + // icon_low: qs($page, `img[alt="volume_low"]`), + // icon_normal: qs($page, `img[alt="volume"]`), + }; + const setVolume = (volume, wavesurfer) => { + wavesurfer.setVolume(volume / 100); + }; + const currentTime$ = new rxjs.BehaviorSubject([ + 0, // time of lastSeek: we want to start from the start + 0, // seek offset to align with wavesurfer currentTime in the audiocontext + ]); - waveColor: "#323639", - progressColor: "#808080", - cursorColor: "#6f6f6f", - cursorWidth: 3, - height: 200, - barWidth: 1, - }); - wavesurfer.load(getDownloadUrl()); - onDestroy(() => wavesurfer.destroy()); + // feature1: setup the dom + const setup$ = rxjs.of(qs($page, "#waveform")).pipe( + rxjs.mergeMap(($node) => Promise.resolve(WaveSurfer.create({ + container: $node, + interact: false, + + waveColor: "#323639", + progressColor: "#808080", + cursorColor: "#6f6f6f", + cursorWidth: 3, + height: 200, + barWidth: 1, + }))), + rxjs.tap((wavesurfer) => { + window.audio = wavesurfer; // TODO: remove + wavesurfer.load(getDownloadUrl()); + wavesurfer.on("error", (err) => { + throw new Error(err) + }); + }), + rxjs.tap((wavesurfer) => onDestroy(() => wavesurfer.destroy())), + rxjs.catchError(ctrlError()), + rxjs.shareReplay(1), + ); + effect(setup$); + + // feature2: loading animation + effect(setup$.pipe( + rxjs.mergeMap((wavesurfer) => new rxjs.Observable((observer) => { + wavesurfer.on("loading", (n) => observer.next(n)); + wavesurfer.on("ready", () => observer.next(100)); + })), + rxjs.mergeMap((n) => { + const $loader = qs($page, `[data-bind="loader"]`); + $loader.querySelector(".audioplayer_loader").style.width = `${n}%`; + $loader.querySelector(".percent").textContent = `${n}%`; + if (n !== 100) return rxjs.EMPTY; + return rxjs.of(null).pipe( + rxjs.delay(200), + rxjs.tap(() => $loader.classList.add("hidden")), + ); + }), + )); + + // feature3: prepare the data source + const ready$ = setup$.pipe( + rxjs.mergeMap((wavesurfer) => new rxjs.Observable((observer) => { + wavesurfer.on("ready", () => observer.next(wavesurfer)); + })), + rxjs.share(), + ) + effect(ready$.pipe(rxjs.tap((wavesurfer) => { + wavesurfer.backend.createSource(); + wavesurfer.backend.startPosition = 0; + wavesurfer.backend.lastPlay = 0; + wavesurfer.backend.source.start(0, 0); + }))); + + // feature: player control - volume + effect(setup$.pipe( + rxjs.switchMap(() => rxjs.fromEvent($volume.range, "input").pipe(rxjs.map((e) => e.target.value))), + rxjs.startWith(settings_get("volume") === null ? 80 : settings_get("volume")), + rxjs.mergeMap((volume) => setup$.pipe(rxjs.tap((wavesurfer) => setVolume(volume, wavesurfer)))), + )); + + // feature: player control - seek + effect(setup$.pipe( + rxjs.mergeMap((wavesurfer) => rxjs.fromEvent(qs($page, "#waveform"), "click").pipe( + rxjs.map((e) => ({ e, wavesurfer })), + )), + rxjs.map(({ e, wavesurfer }) => { + const rec = e.target.getBoundingClientRect(); + return { wavesurfer, progress: (e.clientX - rec.x) / rec.width }; + }), + rxjs.tap(({ progress, wavesurfer }) => { + wavesurfer.drawer.progress(progress); + + const newTime = wavesurfer.getDuration() * progress; + + currentTime$.next([newTime, wavesurfer.backend.ac.currentTime]); + wavesurfer.backend.source.stop(0); + wavesurfer.backend.disconnectSource(); + wavesurfer.backend.createSource(); + wavesurfer.backend.startPosition = newTime; + wavesurfer.backend.source.start(0, newTime); + }), + )); + + // feature4: time progression + effect(ready$.pipe( + rxjs.mergeMap(() => rxjs.merge( + onClick($control.play).pipe(rxjs.mapTo(STATUS_PLAYING)), + onClick($control.pause).pipe(rxjs.mapTo(STATUS_PAUSED)), + )), + rxjs.mergeMap((status) => setup$.pipe(rxjs.tap((wavesurfer) => { + switch (status) { + case STATUS_PLAYING: + wavesurfer.backend.ac.resume(); + $control.play.classList.add("hidden"); + $control.pause.classList.remove("hidden"); + break; + case STATUS_PAUSED: + wavesurfer.backend.ac.suspend(); + $control.play.classList.remove("hidden"); + $control.pause.classList.add("hidden"); + break; + default: + throw new Error("Unknown state"); + } + }))), + rxjs.switchMap((wavesurfer) => rxjs.animationFrames().pipe( + rxjs.tap(() => { + const percent = (currentTime$.value[0] + (wavesurfer.backend.ac.currentTime - currentTime$.value[1])) / wavesurfer.getDuration(); + if (percent > 1) return; + wavesurfer.drawer.progress(percent); + }), + )), + )); } export function init() { - return loadCSS(import.meta.url, "./application_audio.css"); + return Promise.all([ + loadJS(import.meta.url, "../../lib/vendor/wavesurfer.js"), + loadCSS(import.meta.url, "./application_audio.css"), + ]); } diff --git a/public/assets/pages/viewerpage/application_image.css b/public/assets/pages/viewerpage/application_image.css index 7581b5f1..1c8b06a2 100644 --- a/public/assets/pages/viewerpage/application_image.css +++ b/public/assets/pages/viewerpage/application_image.css @@ -174,11 +174,6 @@ body:not(.dark-mode) .component_imageviewer .component_image_container, body:not .component_imageviewer .component_image_container img[srcset].idle { transition: 0.2s ease transform; } -.component_imageviewer .component_image_container img.error { - filter: contrast(0.8); - width: 160px; - margin: 0 auto; -} .component_imageviewer .loader, .component_imageviewer .loader > span { height: 100%; @@ -200,3 +195,10 @@ body:not(.dark-mode) .component_imageviewer .component_image_container, body:not font-size: 1.3em; margin-top: 10px; } + + +.component_imageviewer .component_image_container img.error { + filter: contrast(0.8); + width: 160px; + margin: 0 auto; +} diff --git a/public/assets/pages/viewerpage/application_image.js b/public/assets/pages/viewerpage/application_image.js index fed82272..0e5e2ba6 100644 --- a/public/assets/pages/viewerpage/application_image.js +++ b/public/assets/pages/viewerpage/application_image.js @@ -61,13 +61,12 @@ export default function(render) { rxjs.catchError(ctrlError()), ); } - console.log(err) return ctrlError()(err); }), )); - // componentMetadata(createRender(qs($page, ".images_aside"))); - // componentPager(createRender(qs($page, ".component_pager"))); + componentMetadata(createRender(qs($page, ".images_aside"))); + componentPager(createRender(qs($page, ".component_pager"))); } export function init() { diff --git a/public/assets/pages/viewerpage/application_video.js b/public/assets/pages/viewerpage/application_video.js index 007e0ea9..de8bca2e 100644 --- a/public/assets/pages/viewerpage/application_video.js +++ b/public/assets/pages/viewerpage/application_video.js @@ -1,5 +1,6 @@ import { createElement } from "../../lib/skeleton/index.js"; import rxjs, { effect } from "../../lib/rx.js"; +import { animate, slideYIn } from "../../lib/animate.js"; import { loadCSS, loadJS } from "../../helpers/loader.js"; import { qs } from "../../lib/dom.js"; import { settings_get, settings_put } from "../../lib/settings.js"; @@ -10,8 +11,10 @@ import Hls from "../../lib/vendor/hlsjs/hls.js"; import ctrlError from "../ctrl_error.js"; import { transition, getDownloadUrl } from "./common.js"; +import { ICON } from "./common_icon.js"; +import { menubarDownload, buildMenubar } from "./common_menubar.js"; +import { render as renderMenubar } from "../../components/menubar.js"; -import "../../components/menubar.js"; import "../../components/icon.js"; const STATUS_PLAYING = "PLAYING"; @@ -45,13 +48,14 @@ export default function(render, { mime }) {
- play - + play + - - - + + + +
@@ -162,10 +166,25 @@ export default function(render, { mime }) { hls.attachMedia($video); }), rxjs.mergeMap(() => rxjs.fromEvent($video, "loadeddata")), - rxjs.tap(() => { - qs($page, ".loader").classList.add("hidden"); - qs($page, ".videoplayer_control").classList.remove("hidden"); + rxjs.mergeMap(() => { + const $loader = qs($page, ".loader"); + $loader.replaceChildren(createElement(``)); + animate($loader, { time: 150, keyframes: [ + { transform: "scale(0.7)" }, + { transform: "scale(1)" }, + ]}); setSeek(0); + return rxjs.fromEvent($loader, "click").pipe(rxjs.mapTo($loader)); + }), + // rxjs.tap(() => renderMenubar(buildMenubar( + // menubarDownload(), + // ))), + rxjs.tap(($loader) => { + $loader.classList.add("hidden") + const $control = qs($page, ".videoplayer_control"); + $control.classList.remove("hidden"); + animate($control, { time: 300, keyframes: slideYIn(5) }) + setStatus(STATUS_PLAYING); }), rxjs.share(), ); @@ -224,7 +243,7 @@ export default function(render, { mime }) { // feature5: player control - seek effect(setup$.pipe( rxjs.switchMap(() => rxjs.fromEvent(qs($page, ".progress"), "click").pipe( - rxjs.map((e) => { + rxjs.map((e) => { // TODO: use onClick instead? let $progress = e.target; if (e.target.classList.contains("progress") == false) { $progress = e.target.parentElement; @@ -321,7 +340,6 @@ export default function(render, { mime }) { }; const $container = qs($page, `[data-bind="progress-buffer"]`); if ($video.buffered.length !== $container.children.length ) { - console.log("RESET"); $container.innerHTML = ""; const $fragment = document.createDocumentFragment(); Array.apply(null, { length: $video.buffered.length }) diff --git a/public/assets/pages/viewerpage/common_icon.js b/public/assets/pages/viewerpage/common_icon.js new file mode 100644 index 00000000..6571ba3f --- /dev/null +++ b/public/assets/pages/viewerpage/common_icon.js @@ -0,0 +1,8 @@ +export const ICON = { + PLAY: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgdmlld0JveD0iMCAwIDU4Ljc1MiA1OC43NTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+Cgk8cGF0aCBkPSJNIDQ1LjYwNjkxMywyNS4xNzQ3MTIgMjIuNjkxNDAxLDYuMTA4OTgyNSBjIC0xLjQ2OTYyNSwtMC45MDc4NTI1IC0zLjM3MjM1NCwtMC45MDUzNzY2IC00LjgzNjU4NCwwIC0xLjQ5MzUxNSwwLjkyMTA1NzcgLTIuNDIyMTQ1LDIuNjQxODUxIC0yLjQyMjE0NSw0LjQ4OTc0MzUgViA0OC43MzI2NiBjIDAsMS44NDg3MTggMC45Mjc4NiwzLjU2OTUxMSAyLjQxMjg5Nyw0LjQ4NTYxNyAwLjczNDQyNywwLjQ1ODA1MyAxLjU3MzY2MywwLjY5OTg3MiAyLjQyNjc2OSwwLjY5OTg3MiAwLjg1MDc5NSwwIDEuNjg5MjYsLTAuMjQwOTk0IDIuNDIwNjA0LC0wLjY5NTc0NSBsIDIyLjkxNTUxMiwtMTkuMDY3MzggYyAxLjQ5MTk3NCwtMC45MjM1MzMgMi40MTgyOTIsLTIuNjQzNTAxIDIuNDE4MjkyLC00LjQ4ODkxOCAtNy43ZS00LC0xLjg0Mjk0MSAtMC45MjYzMTgsLTMuNTYyOTA5IC0yLjQxOTgzMywtNC40OTEzOTQgeiBNIDQzLjAwMTIxMSwyOS44NjgzMSAyMC42NzA5MDYsNDguNjQyNzU0IGMgLTAuMDYzMTksMC4wMzg3OSAtMC4xMzg3MTYsMC4wNDI5MiAtMC4yMTUwMSwtMC4wMDQxIC0wLjA2NDc0LC0wLjA0MDQ0IC0wLjEwNTU3OSwtMC4xMTcxOTYgLTAuMTA1NTc5LC0wLjE5OTcyOCBWIDEwLjg5MTY2MSBjIDAsLTAuMDgyNTMgMC4wNDAwNywtMC4xNTg0NjIgMC4xMDc4OTEsLTAuMjAwNTUzIDAuMDMyMzcsLTAuMDIwNjMgMC4wNjkzNiwtMC4wMzEzNiAwLjEwNzEyLC0wLjAzMTM2IDAuMDM5MywwIDAuMDc2MjksMC4wMTA3MyAwLjEwOTQzMiwwLjAzMTM2IGwgMjIuMzIyNTk3LDE4Ljc2OTQ5MyBjIDAuMDY4NTksMC4wNDI5MiAwLjExMTc0NCwwLjEyMTMyMiAwLjExMTc0NCwwLjIwNTUwNSAtNy43ZS00LDAuMDg1MDEgLTAuMDQwODQsMC4xNjAxMTIgLTAuMTA3ODksMC4yMDIyMDQgeiIgc3R5bGU9ImZpbGw6IzZmNmY2ZiIgLz4KPC9zdmc+Cg==", + PAUSE: "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgZmlsbD0iIzZmNmY2ZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNIDMyMCw4MS45ODc4NjggViA0MjcuNzY5MzEgYyAwLDkuMzQzMzYgNy42NDQ2LDE2Ljk4Nzg4IDE2Ljk4NzksMTYuOTg3ODggaCAyNS45NzU3IGMgOS4zNDMzLDAgMTYuOTg3OCwtNy42NDQ1MiAxNi45ODc4LC0xNi45ODc4OCBWIDgxLjk4Nzg2OCBDIDM3OS45NTE0LDcyLjY0NDUzNiAzNzIuMzA2OSw2NSAzNjIuOTYzNiw2NSBIIDMzNi45ODc5IEMgMzI3LjY0NDYsNjUgMzIwLDcyLjY0NDUzNiAzMjAsODEuOTg3ODY4IFoiIC8+CiAgPHBhdGggZD0iTSAxNTAsODEuOTg3ODY4IFYgNDI3Ljc2OTMxIGMgMCw5LjM0MzM2IDcuNjQ0NTUsMTYuOTg3ODggMTYuOTg3NzksMTYuOTg3ODggaCAyNS45NzU1MiBjIDkuMzQzMjQsMCAxNi45ODc2OSwtNy42NDQ1MiAxNi45ODc2OSwtMTYuOTg3ODggViA4MS45ODc4NjggQyAyMDkuOTUxLDcyLjY0NDUzNiAyMDIuMzA2NTUsNjUgMTkyLjk2MzMxLDY1IEggMTY2Ljk4Nzc5IEMgMTU3LjY0NDU1LDY1IDE1MCw3Mi42NDQ1MzYgMTUwLDgxLjk4Nzg2OCBaIiAvPgo8L3N2Zz4K", + + VOLUME_MUTE: "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzZmNmY2ZiIgc3Ryb2tlLXdpZHRoPSIyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0gMjEuOTgzODgzLDE0Ljg4Mzg4MyAtNiwtNS45OTk5OTk1IG0gNiwwIC02LDUuOTk5OTk5NSIgLz4KICA8cGF0aCBkPSJNIDEuMTI1MzM1NiwxNS4yMTc4OTcgViA4Ljc4MTAzMjggYyAwLC0wLjYyNDIyMDUgMC40ODcxOTY3LC0xLjEzMDk5MTcgMS4wODc0OTIzLC0xLjEzMDk5MTcgSCA2LjExMjU3NDggQSAxLjA2NTc0MjIsMS4wNjU3NDIyIDAgMCAwIDYuODgxNDMxOCw3LjMxODM1NjIgTCAxMC4xNDM5MDksMy42MzM5MzI4IGMgMC42ODUxMiwtMC43MTMzOTUgMS44NTYzNDUsLTAuMjA3NzExMSAxLjg1NjM0NSwwLjgwMDM5NDIgdiAxNS4xMzEzNjggYyAwLDEuMDE1NzE1IC0xLjE4NTM2MiwxLjUxNzA0NSAtMS44NjYxMzEsMC43ODk1MTMgTCA2Ljg4MjUxOSwxNi42OTE0NSBBIDEuMDY1NzQyMiwxLjA2NTc0MjIgMCAwIDAgNi4xMDM4NzQ4LDE2LjM0OTk3NSBIIDIuMjEyODI3OSBjIC0wLjYwMDI5NTYsMCAtMS4wODc0OTIzLC0wLjUwNjc2OCAtMS4wODc0OTIzLC0xLjEzMjA3OCB6IiAvPgo8L3N2Zz4K", + VOLUME_LOW: "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzZmNmY2ZiIgc3Ryb2tlLXdpZHRoPSIyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0gMTYuMzUwMjI1LDguMTkzNzg3IGMgMS40NDk2MjYsMS45MzM1NTkgMS40NDk2MjYsNS42Nzg4ODQgMCw3LjYxMjQ0NiIgLz4KICA8cGF0aCBkPSJNIDEuMTI1MzM1NiwxNS4yMTc4OTcgViA4Ljc4MTAzMjggYyAwLC0wLjYyNDIyMDUgMC40ODcxOTY3LC0xLjEzMDk5MTcgMS4wODc0OTIzLC0xLjEzMDk5MTcgSCA2LjExMjU3NDggQSAxLjA2NTc0MjIsMS4wNjU3NDIyIDAgMCAwIDYuODgxNDMxOCw3LjMxODM1NjIgTCAxMC4xNDM5MDksMy42MzM5MzI4IGMgMC42ODUxMiwtMC43MTMzOTUgMS44NTYzNDUsLTAuMjA3NzExMSAxLjg1NjM0NSwwLjgwMDM5NDIgdiAxNS4xMzEzNjggYyAwLDEuMDE1NzE1IC0xLjE4NTM2MiwxLjUxNzA0NSAtMS44NjYxMzEsMC43ODk1MTMgTCA2Ljg4MjUxOSwxNi42OTE0NSBBIDEuMDY1NzQyMiwxLjA2NTc0MjIgMCAwIDAgNi4xMDM4NzQ4LDE2LjM0OTk3NSBIIDIuMjEyODI3OSBjIC0wLjYwMDI5NTYsMCAtMS4wODc0OTIzLC0wLjUwNjc2OCAtMS4wODc0OTIzLC0xLjEzMjA3OCB6IiAvPgo8L3N2Zz4K", + VOLUME_NORMAL: "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzZmNmY2ZiIgc3Ryb2tlLXdpZHRoPSIyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Im0gMTYuMzUwMjI1LDguMTkzNzg3IGMgMS40NDk2MjYsMS45MzM1NTkgMS40NDk2MjYsNS42Nzg4ODQgMCw3LjYxMjQ0NiIgLz4KICA8cGF0aCBkPSJtIDE5LjYxMjcwMyw0LjM4NzU2NDQgYyA0LjMzNjkxOSw0LjE0MTE3MDQgNC4zNjMwMTQsMTEuMTEwOTA4NiAwLDE1LjIyNDg4NzYiIC8+CiAgPHBhdGggZD0iTSAxLjEyNTMzNTYsMTUuMjE3ODk3IFYgOC43ODEwMzI4IGMgMCwtMC42MjQyMjA1IDAuNDg3MTk2NywtMS4xMzA5OTE3IDEuMDg3NDkyMywtMS4xMzA5OTE3IEggNi4xMTI1NzQ4IEEgMS4wNjU3NDIyLDEuMDY1NzQyMiAwIDAgMCA2Ljg4MTQzMTgsNy4zMTgzNTYyIEwgMTAuMTQzOTA5LDMuNjMzOTMyOCBjIDAuNjg1MTIsLTAuNzEzMzk1IDEuODU2MzQ1LC0wLjIwNzcxMTEgMS44NTYzNDUsMC44MDAzOTQyIHYgMTUuMTMxMzY4IGMgMCwxLjAxNTcxNSAtMS4xODUzNjIsMS41MTcwNDUgLTEuODY2MTMxLDAuNzg5NTEzIEwgNi44ODI1MTksMTYuNjkxNDUgQSAxLjA2NTc0MjIsMS4wNjU3NDIyIDAgMCAwIDYuMTAzODc0OCwxNi4zNDk5NzUgSCAyLjIxMjgyNzkgYyAtMC42MDAyOTU2LDAgLTEuMDg3NDkyMywtMC41MDY3NjggLTEuMDg3NDkyMywtMS4xMzIwNzggeiIgLz4KPC9zdmc+Cg==", +}; diff --git a/public/assets/pages/viewerpage/common_menubar.js b/public/assets/pages/viewerpage/common_menubar.js new file mode 100644 index 00000000..41a93d51 --- /dev/null +++ b/public/assets/pages/viewerpage/common_menubar.js @@ -0,0 +1,33 @@ +import { createFragment } from "../../lib/skeleton/index.js"; + +export function menubarDownload() { + const $fragment = createFragment(` + + + + download_white + + + + `); + $fragment.querySelector(".download-button").onclick = () => { + console.log("CLICK"); + } + return $fragment; +} + +export function menubarChromecast() { + return createFragment(` + + + + `); +} + +export function buildMenubar(...$fragments) { + const $buttons = document.createDocumentFragment(); + for (let i=0; i<$fragments.length; i++) { + $buttons.appendChild($fragments[i]); + } + return $buttons; +}