Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,158 @@
;(function(window){'use strict';const HIDE_OVERLAY_TIMEOUT=5000;const REPEAT_VALUES=['off','list','song'];const SHUFFLE_VALUES=['off','on'];var proto=Object.create(HTMLElement.prototype);proto.createdCallback=function(){var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`<style>
[data-icon]:before { /* Copied from /components/gaia-icons/gaia-icons.css */
font-family: "gaia-icons";
content: attr(data-icon);
display: inline-block;
font-weight: 500;
font-style: normal;
text-decoration: inherit;
text-transform: none;
text-rendering: optimizeLegibility;
font-size: 30px;
-webkit-font-smoothing: antialiased;
}
#container {
background-color: #000;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
-moz-user-select: none;
}
#container > img {
background-color: #000;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
}
#container > img[data-layer="front"] {
opacity: 0;
visibility: hidden;
transition: opacity 150ms linear, visibility 0s linear 150ms;
}
#container > img[data-layer="front"].active {
opacity: 1;
visibility: visible;
transition-delay: 0s, 0s;
}
#container button {
background: none;
border: none;
border-radius: 0;
color: #fff;
flex: 0 0 auto;
margin: 0 1rem;
width: 6rem;
transition: background 200ms ease;
}
#container button:hover {
background: transparent;
}
#container button:active {
background: #00caf2;
transition-duration: 0s;
}
#container button:disabled,
#container button[data-value="off"] {
opacity: 0.3;
}
#container button:disabled:active {
background: transparent;
}
#container button[data-icon="repeat"][data-value="song"]:before {
content: 'repeat-once'
}
#caption,
#controls {
background-color: rgba(0, 0, 0, 0.5);
display: flex;
flex-flow: row nowrap;
position: absolute;
left: 0;
width: 100%;
height: 5rem;
visibility: hidden;
transition: transform 300ms ease-in-out, visibility 0s linear 300ms;
}
#caption {
top: 0;
transform: translateY(-5rem);
}
#controls {
bottom: 0;
transform: translateY(5rem);
}
.show-overlay > #caption,
.show-overlay > #controls {
transform: translateY(0);
visibility: visible;
transition-delay: 0s, 0s;
}
#caption-text {
position: relative;
flex: 0 0 auto;
width: calc(100% - 8rem);
}
#artist,
#album {
color: #fff;
font-weight: normal;
text-shadow: 0 0.1rem rgba(0, 0, 0, 0.5);
text-indent: 3rem;
position: relative;
margin: 0;
width: 100%;
height: 2.5rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#artist {
font-size: 1.9rem;
line-height: 3rem;
}
#album {
font-size: 1.7rem;
line-height: 2.5rem;
}
#rating {
flex: 1 0 auto;
}
</style>
<div id="container">
<img data-layer="back">
<img data-layer="front" class="active">
<div id="caption">
<div id="caption-text">
<h1 id="artist"></h1>
<h2 id="album"></h2>
</div>
<button type="button"
data-action="share"
data-icon="share"
data-l10n-id="share-song">
</button>
</div>
<div id="controls">
<button type="button"
data-action="repeat"
data-icon="repeat"
data-l10n-id="repeat-off">
</button>
<music-rating id="rating"></music-rating>
<button type="button"
data-action="shuffle"
data-icon="shuffle"
data-l10n-id="shuffle-toggle">
</button>
</div>
</div>`;var $=shadowRoot.querySelector.bind(shadowRoot);this.els={container:$('#container'),backImage:$('img[data-layer="back"]'),frontImage:$('img[data-layer="front"]'),caption:$('#caption'),controls:$('#controls'),artist:$('#artist'),album:$('#album'),share:$('[data-action="share"]'),repeat:$('[data-action="repeat"]'),shuffle:$('[data-action="shuffle"]'),rating:$('#rating')};var onImageLoad=(evt)=>{const image=evt.target;window.requestAnimationFrame(()=>{var newActiveImage=image.closest('img:not(.active)');if(!newActiveImage){return;}
var oldActiveImage=this.els.container.querySelector('img.active');newActiveImage.classList.add('active');oldActiveImage.classList.remove('active');});};[].forEach.call(this.els.container.querySelectorAll('img'),(img)=>{img.addEventListener('load',onImageLoad);});this.els.container.addEventListener('transitionend',(evt)=>{if(!evt.target.matches('img:not(.active)')){return;}
var oldActiveImage=evt.target;oldActiveImage.src=null;});this.els.container.addEventListener('click',(evt)=>{var button=evt.target.closest('button');if(!button){if(evt.target.closest('#rating')){this.overlayVisible=true;return;}
this.overlayVisible=!this.overlayVisible;return;}
var action=button.dataset.action;switch(action){case'repeat':this.nextRepeat();break;case'shuffle':this.nextShuffle();break;}
this.overlayVisible=true;this.dispatchEvent(new CustomEvent(action));});this.els.rating.addEventListener('change',(evt)=>{this.dispatchEvent(new CustomEvent('ratingchange',{detail:evt.detail}));});this.onDOMRetranslated=()=>{document.l10n.translateFragment(shadowRoot);};this.repeat=this.getAttribute('repeat');this.shuffle=this.getAttribute('shuffle');this.overlayVisible=true;};proto.attachedCallback=function(){document.addEventListener('DOMRetranslated',this.onDOMRetranslated);this.onDOMRetranslated();};proto.detachedCallback=function(){document.removeEventListener('DOMRetranslated',this.onDOMRetranslated);};proto.attributeChangedCallback=function(attr,oldVal,newVal){switch(attr){case'artist':this.els.artist.textContent=newVal;break;case'album':this.els.album.textContent=newVal;break;case'repeat':this.els.repeat.dataset.value=REPEAT_VALUES.indexOf(newVal)!==-1?newVal:REPEAT_VALUES[0];break;case'shuffle':this.els.shuffle.dataset.value=SHUFFLE_VALUES.indexOf(newVal)!==-1?newVal:SHUFFLE_VALUES[0];break;case'src':this.els.container.querySelector('img:not(.active)').src=newVal;break;}};proto.nextRepeat=function(){this.repeat=REPEAT_VALUES[REPEAT_VALUES.indexOf(this.repeat)+1];};proto.nextShuffle=function(){this.shuffle=SHUFFLE_VALUES[SHUFFLE_VALUES.indexOf(this.shuffle)+1];};['artist','album','src'].forEach(function(prop){Object.defineProperty(proto,prop,{get:function(){return this.getAttribute(prop);},set:function(value){this.setAttribute(prop,value||'');}});});Object.defineProperty(proto,'repeat',{get:function(){return this.getAttribute('repeat')||REPEAT_VALUES[0];},set:function(value){value=REPEAT_VALUES.indexOf(value)!==-1?value:REPEAT_VALUES[0];this.setAttribute('repeat',value);this.els.repeat.dataset.l10nId='repeat-'+value;this.onDOMRetranslated();}});Object.defineProperty(proto,'shuffle',{get:function(){return this.getAttribute('shuffle')||SHUFFLE_VALUES[0];},set:function(value){value=SHUFFLE_VALUES.indexOf(value)!==-1?value:SHUFFLE_VALUES[0];this.setAttribute('shuffle',value);}});Object.defineProperty(proto,'overlayVisible',{get:function(){return this.els.container.classList.contains('show-overlay');},set:function(value){var overlayVisible=!!value;clearTimeout(this._hideOverlayTimeout);if(overlayVisible){this.els.container.classList.add('show-overlay');this._hideOverlayTimeout=setTimeout(()=>{this.overlayVisible=false;},HIDE_OVERLAY_TIMEOUT);}
else{this.els.container.classList.remove('show-overlay');}}});try{window.MusicArtwork=document.registerElement('music-artwork',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,65 @@
;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);var isTouch='ontouchstart'in window;proto.createdCallback=function(){var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`<style>
[data-icon]:before { /* Copied from /components/gaia-icons/gaia-icons.css */
font-family: "gaia-icons";
content: attr(data-icon);
display: inline-block;
font-weight: 500;
font-style: normal;
text-decoration: inherit;
text-transform: none;
text-rendering: optimizeLegibility;
font-size: 30px;
-webkit-font-smoothing: antialiased;
}
#container {
background-color: #000;
border-top: 0.1rem solid rgba(255, 255, 255, 0.1);
direction: ltr;
display: flex;
flex-flow: row nowrap;
position: relative;
width: 100%;
height: 4.8rem;
-moz-user-select: none;
}
#container > button {
background: transparent;
border: none;
border-radius: 0;
color: #fff;
flex: 1 0 auto;
position: relative;
padding: 0;
height: 100%;
transition: background 0.2s ease;
}
#container > button:hover {
background: transparent;
}
#container > button:active {
background: #00caf2;
transition-duration: 0s;
}
#container > button:disabled {
opacity: 0.3;
}
#container > button:disabled:active {
background: transparent;
}
</style>
<div id="container">
<button type="button" id="previous"
data-icon="skip-back"
data-l10n-id="playbackPrevious">
</button>
<button type="button" id="toggle"
data-icon="play"
data-l10n-id="playbackPlay">
</button>
<button type="button" id="next"
data-icon="skip-forward"
data-l10n-id="playbackNext">
</button>
</div>`;var $id=shadowRoot.getElementById.bind(shadowRoot);this.els={container:$id('container'),previous:$id('previous'),toggle:$id('toggle'),next:$id('next')};var seeking=false;this.els.container.addEventListener('contextmenu',(evt)=>{evt.preventDefault();if(seeking){return;}
var button=evt.target.closest('button');if(button.id==='previous'||button.id==='next'){seeking=true;this.dispatchEvent(new CustomEvent('startseek',{detail:{reverse:button.id==='previous'}}));}});this.els.container.addEventListener(isTouch?'touchend':'mouseup',(evt)=>{if(seeking){evt.preventDefault();this.dispatchEvent(new CustomEvent('stopseek'));seeking=false;}});this.els.container.addEventListener('click',(evt)=>{var button=evt.target.closest('button');switch(button.id){case'previous':case'next':this.dispatchEvent(new CustomEvent(button.id));break;case'toggle':this.paused=!this.paused;this.dispatchEvent(new CustomEvent(this.paused?'pause':'play'));break;}});this.onDOMRetranslated=()=>{document.l10n.translateFragment(shadowRoot);};};proto.attachedCallback=function(){document.addEventListener('DOMRetranslated',this.onDOMRetranslated);this.onDOMRetranslated();};proto.detachedCallback=function(){document.removeEventListener('DOMRetranslated',this.onDOMRetranslated);};Object.defineProperty(proto,'paused',{get:function(){return this.els.toggle.dataset.icon!=='pause';},set:function(value){var paused=!!value;if(paused===this.paused){return;}
this.els.toggle.dataset.icon=paused?'play':'pause';this.els.toggle.dataset.l10nId=paused?'playbackPlay':'playbackPause';this.onDOMRetranslated();}});try{window.MusicControls=document.registerElement('music-controls',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,123 @@
;;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);proto.createdCallback=function(){var buttons=document.createDocumentFragment();[].forEach.call(this.querySelectorAll('button'),(button)=>{buttons.appendChild(button);});var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`<style>
#heading:empty,
#message:empty,
#menu:empty {
display: none;
}
#container {
background-color: #2d2d2d;
display: flex;
flex-flow: column nowrap;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
overflow: hidden;
-moz-user-select: none;
}
#content {
box-sizing: border-box;
display: flex;
flex-flow: column nowrap;
justify-content: center;
flex: 1 0 auto;
padding: 1rem 1.5rem;
width: 100%;
max-height: 100%;
overflow-y: auto;
vertical-align: middle;
word-wrap: break-word;
}
#heading {
color: #fff;
font-size: 1.6rem;
line-height: 1.6rem;
margin: 0;
padding: 0;
}
#message {
border-top: 0.1rem solid #686868;
color: #fafafa;
font-size: 2.2rem;
font-weight: 300;
line-height: 3rem;
margin: 1rem 0 0;
padding: 1rem 0 0;
}
#heading:empty + #message {
border: none;
padding: 0;
}
#menu {
box-sizing: border-box;
display: flex;
flex-flow: row nowrap;
flex: 0 0 auto;
margin: 0;
padding: 1.5rem;
width: 100%;
}
#menu > button {
background: #d8d8d8;
border: none;
border-radius: 2rem;
color: #333;
outline: none;
font-family: sans-serif;
font-size: 1.6rem;
font-style: italic;
line-height: 4rem;
box-sizing: border-box;
flex: 1 1 auto;
padding: 0 0.2rem;
height: 4rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: background 200ms 280ms, color 200ms 280ms;
}
#menu > button:active {
background: #00aacc;
color: #fff;
transition: none;
}
#menu > button.primary {
background: #00caf2;
color: #fff;
}
#menu > button.danger {
background: #e51e1e;
color: #fff;
}
#menu > button.primary:active {
background: #006579;
color: #c8c8c8;
}
#menu > button.danger:active {
background: #730f0f;
color: #c8c8c8;
}
#menu > button[disabled] {
background: #565656;
color: rgba(255, 255, 255, 0.4);
pointer-events: none;
}
#menu > button.primary[disabled] {
background: #006579;
}
#menu > button.danger[disabled] {
background: #730f0f;
}
#menu > button + button {
margin-left: 1rem;
}
</style>
<form id="container" role="dialog">
<section id="content">
<h1 id="heading"></h1>
<p id="message"></p>
</section>
<menu id="menu"></menu>
</form>`;var $id=shadowRoot.getElementById.bind(shadowRoot);this.els={container:$id('container'),content:$id('content'),heading:$id('heading'),message:$id('message'),menu:$id('menu')};this.els.menu.appendChild(buttons);this.els.menu.addEventListener('click',(evt)=>{var button=evt.target.closest('button[data-action]');if(button){this.dispatchEvent(new CustomEvent('action',{detail:button.dataset.action}));}});this.els.heading.textContent=this.getAttribute('heading');this.els.message.textContent=this.getAttribute('message');this.els.heading.dataset.l10nId=this.getAttribute('heading-l10n-id');this.els.message.dataset.l10nId=this.getAttribute('message-l10n-id');this.onDOMRetranslated=()=>{document.l10n.translateFragment(shadowRoot);};};proto.attachedCallback=function(){document.addEventListener('DOMRetranslated',this.onDOMRetranslated);this.onDOMRetranslated();};proto.detachedCallback=function(){document.removeEventListener('DOMRetranslated',this.onDOMRetranslated);};proto.attributeChangedCallback=function(attr,oldVal,newVal){switch(attr){case'heading':this.els.heading.textContent=newVal;break;case'message':this.els.message.textContent=newVal;break;case'heading-l10n-id':this.els.heading.dataset.l10nId=newVal;this.onDOMRetranslated();break;case'message-l10n-id':this.els.message.dataset.l10nId=newVal;this.onDOMRetranslated();break;}};proto.addActionButton=function(title,action,className=''){var button=document.createElement('button');button.type='button';button.textContent=title;button.dataset.action=action;button.className=className;this.els.menu.appendChild(button);};proto.removeActionButton=function(action){var buttons=this.els.menu.querySelectorAll(`[data-action="${action}"]`);[].forEach.call(buttons,button=>this.els.menu.removeChild(button));};['heading','message'].forEach((prop)=>{Object.defineProperty(proto,prop,{get:function(){return this.getAttribute(prop);},set:function(value){this.setAttribute(prop,value||'');}});});try{window.MusicOverlay=document.registerElement('music-overlay',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,37 @@
;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);proto.createdCallback=function(){var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`<style>
#container {
display: flex;
flex-flow: row nowrap;
width: 100%;
height: 100%;
-moz-user-select: none;
}
#container > button {
background-color: transparent;
background-image: url(/img/ui/music-rating-off.png);
background-position: center center;
background-repeat: no-repeat;
background-size: 2.2rem auto;
border: none;
flex: 1 0 auto;
width: 2.2rem;
height: 100%;
}
#container[data-value="1"] > :-moz-any([value="1"]),
#container[data-value="2"] > :-moz-any([value="1"],[value="2"]),
#container[data-value="3"] > :-moz-any([value="1"],[value="2"],[value="3"]),
#container[data-value="4"] > :-moz-any([value="1"],[value="2"],[value="3"],[value="4"]),
#container[data-value="5"] > * {
background-image: url(/img/ui/music-rating-on.png);
}
</style>
<div id="container">
<button type="button" value="1" data-l10n-id="rating-star" data-l10n-args='{"n":1}'></button>
<button type="button" value="2" data-l10n-id="rating-star" data-l10n-args='{"n":2}'></button>
<button type="button" value="3" data-l10n-id="rating-star" data-l10n-args='{"n":3}'></button>
<button type="button" value="4" data-l10n-id="rating-star" data-l10n-args='{"n":4}'></button>
<button type="button" value="5" data-l10n-id="rating-star" data-l10n-args='{"n":5}'></button>
</div>`;var $id=shadowRoot.getElementById.bind(shadowRoot);this.els={container:$id('container')};this.els.container.addEventListener('click',(evt)=>{var button=evt.target.closest('button');if(!button){return;}
var value=parseInt(button.value,10)||0;if(value===this.value){value--;}
this.value=value;this.dispatchEvent(new CustomEvent('change',{detail:value}));});this.onDOMRetranslated=()=>{document.l10n.translateFragment(shadowRoot);};};proto.attachedCallback=function(){document.addEventListener('DOMRetranslated',this.onDOMRetranslated);this.onDOMRetranslated();};proto.detachedCallback=function(){document.removeEventListener('DOMRetranslated',this.onDOMRetranslated);};proto.attributeChangedCallback=function(attr,oldVal,newVal){switch(attr){case'value':this.els.container.dataset.value=newVal;break;}};Object.defineProperty(proto,'value',{get:function(){return parseInt(this.getAttribute('value'),10)||0;},set:function(value){this.setAttribute('value',clamp(0,5,parseInt(value,10)||0));}});function clamp(min,max,value){return Math.min(Math.max(min,value),max);}
try{window.MusicRating=document.registerElement('music-rating',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,74 @@
;;;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);injectGlobalStyles();proto.createdCallback=function(){var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`<style scoped>
[hidden] {
display: none;
}
#container {
background-color: #333;
color: #fff;
position: relative;
width: 100%;
height: 5rem;
overflow: hidden;
-moz-user-select: none;
}
#spinner {
background: url('/img/ui/music-scan-progress.png') no-repeat center center / 100% auto;
border: none;
display: block;
position: absolute;
top: 1rem;
left: 1rem;
width: 2.9rem;
height: 2.9rem;
animation: 0.9s music-scan-progress-spinner infinite linear;
}
#spinner::-moz-progress-bar {
background: none;
}
#value {
font-size: 1.2rem;
font-weight: 700;
line-height: 5rem;
text-align: center;
display: block;
position: absolute;
top: 0;
left: 0;
width: 5rem;
height: 5rem;
}
#heading,
#subheading {
font-weight: normal;
box-sizing: border-box;
position: absolute;
margin: 0;
padding: 0 0.5rem;
left: 5rem;
width: calc(100% - 5rem);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#heading {
font-size: 1.9rem;
line-height: 3rem;
top: 0;
}
#subheading {
font-size: 1.4rem;
top: 3rem;
}
</style>
<div id="container">
<progress id="spinner"></progress>
<span id="value"></span>
<h1 id="heading"></h1>
<h2 id="subheading"></h2>
</div>`;var $id=shadowRoot.getElementById.bind(shadowRoot);this.els={container:$id('container'),spinner:$id('spinner'),value:$id('value'),heading:$id('heading'),subheading:$id('subheading')};if(!this.hasAttribute('value')&&!this.hasAttribute('heading')&&!this.hasAttribute('subheading')){this.els.container.hidden=true;}
this.value=this.getAttribute('value');this.heading=this.getAttribute('heading');this.subheading=this.getAttribute('subheading');this.onDOMRetranslated=()=>{document.l10n.translateFragment(shadowRoot);};};proto.attachedCallback=function(){document.addEventListener('DOMRetranslated',this.onDOMRetranslated);this.onDOMRetranslated();};proto.detachedCallback=function(){document.removeEventListener('DOMRetranslated',this.onDOMRetranslated);};proto.attributeChangedCallback=function(attr,oldVal,newVal){var promise;var l10nId=this.getAttribute(attr+'-l10n-id');if(!newVal&&l10nId){promise=document.l10n.formatValues(l10nId);}else{promise=Promise.resolve();}
promise.then(()=>{switch(attr){case'value':this.els.value.textContent=newVal;break;case'heading':this.els.heading.textContent=newVal;break;case'subheading':this.els.subheading.textContent=newVal;break;}});};proto.update=function(properties={}){this.value=properties.value||this.value;this.heading=properties.heading||this.heading;this.subheading=properties.subheading||this.subheading;this.els.container.hidden=false;};proto.clear=function(){this.els.container.hidden=true;};['value','heading','subheading'].forEach((prop)=>{Object.defineProperty(proto,prop,{get:function(){return this.getAttribute(prop);},set:function(value){this.setAttribute(prop,value||'');}});});function injectGlobalStyles(){var style=document.createElement('style');style.innerHTML=`@keyframes music-scan-progress-spinner {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}`;document.head.appendChild(style);}
try{window.MusicScanProgress=document.registerElement('music-scan-progress',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,33 @@
;;;;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);proto.HEIGHT=52;proto.createdCallback=function(){var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`
<style>
#inner {
display: flex;
}
gaia-text-input {
margin: 6px 0 !important;
flex: 1;
}
#close {
display: none;
padding: 0 14px;
-moz-margin-end: -14px;
border: 0;
background: none;
color: var(--highlight-color);
font-style: italic;
font-size: 17px;
}
.open #close {
display: block;
}
</style>
<div id="inner">
<gaia-text-input type="search" clearable id="input"></gaia-text-input>
<button id="close" data-l10n-id="search-close">Close</button>
</div>`;var $id=shadowRoot.getElementById.bind(shadowRoot);this.els={inner:$id('inner'),input:$id('input'),close:$id('close')};this.isOpen=false;this.els.results=document.querySelector(this.getAttribute('results'));var onSearch=debounce(()=>{this.emit('search',this.els.input.value);},500);this.els.input.addEventListener('focus',()=>this.open());this.els.close.addEventListener('click',()=>this.close());this.els.input.addEventListener('input',onSearch);this.addEventListener('touchmove',e=>e.preventDefault());this.localize=()=>{document.l10n.formatValues('search','search-close').then(([search,close])=>{this.els.input.placeholder=search;this.els.close.textContent=close;});};};proto.attachedCallback=function(){document.addEventListener('DOMRetranslated',this.localize);this.localize();};proto.detachedCallback=function(){document.removeEventListener('DOMRetranslated',this.localize);};proto.attributeChangedCallback=function(attr,oldVal,newVal){switch(attr){case'results':this.els.results=document.querySelector(newVal);break;}};proto.clear=function(){requestAnimationFrame(()=>{this.els.input.clear();});};proto.focus=function(){requestAnimationFrame(()=>{this.els.input.focus();});};proto.open=function(){if(this.isOpen){return;}
this.isOpen=true;this.els.inner.classList.add('open');this.focus();this.emit('open');if(this.els.results){this.els.results.open();}};proto.close=function(){if(!this.isOpen){return;}
this.isOpen=false;this.els.inner.classList.remove('open');this.clear();this.emit('close');if(this.els.results){this.els.results.close();}};proto.emit=function(name,detail){var evt=new CustomEvent(name,{detail:detail});this.dispatchEvent(evt);};Object.defineProperty(proto,'value',{get:function(){return this.els.input.value;},set:function(value){this.els.input.value=value;}});Object.defineProperty(proto,'results',{get:function(){return this.els.results;},set:function(value){this.els.results=value;}});window.MusicSearchBox=document.registerElement('music-search-box',{prototype:proto});function debounce(fn,ms){var timeout;return()=>{var args=arguments;clearTimeout(timeout);timeout=setTimeout(()=>fn.apply(this,args),ms);};}})(window);

View file

@ -0,0 +1,32 @@
;;;;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);proto.createdCallback=function(){this.innerHTML=`
<style scoped>
music-search-results {
opacity: 0;
visibility: hidden;
pointer-events: none;
background: var(--background);
}
music-search-results.transitions-on {
transition:
opacity 0.2s linear,
visibility 0s linear 0.2s;
}
music-search-results[active] {
opacity: 1;
visibility: visible;
transition-delay: 0s, 0s;
pointer-events: auto;
}
</style>
<gaia-fast-list id="list">
<template>
<a href="\${url}" data-file-path="\${name}" data-section="\${section}">
<div class="image"><img></div>
<h3 dir="auto">\${title}</h3>
<p dir="auto">\${subtitle}</p>
</a>
</template>
</gaia-fast-list>`;this.els={list:this.querySelector('#list')};this.els.list.configure({getSectionName:(item)=>item.section,getItemImageSrc:(item)=>this.getItemImageSrc(item)});this.els.list.addEventListener('click',(e)=>this.onLinkClick(e));};proto.attachedCallback=function(){setTimeout(()=>this.enableTransitions());};proto.enableTransitions=function(){this.classList.add('transitions-on');};proto.onLinkClick=function(evt){var link=evt.target.closest('a');if(!link)return;evt.preventDefault();this.close().then(()=>{this.emit('resultclick',link);});};proto.getItemImageSrc=function(){};proto.open=function(){return new Promise((resolve)=>{requestAnimationFrame(()=>{this.setAttribute('active',true);resolve();});this.emit('open');});};proto.close=function(){return new Promise((resolve)=>{requestAnimationFrame(()=>{this.removeAttribute('active');this.clearResults();resolve();});this.emit('close');});};proto.setResults=function(results){if(results.length===0){return document.l10n.formatValue('search-no-result').then((noResult)=>{return this.els.list.setModel([{title:noResult,subtitle:''}]);});}
return this.els.list.setModel(results);};proto.clearResults=function(){return this.els.list.setModel([]);};proto.emit=function(name,detail){var evt=new CustomEvent(name,{detail:detail});this.dispatchEvent(evt);};window.MusicSearchResults=document.registerElement('music-search-results',{prototype:proto});})(window);

View file

@ -0,0 +1,95 @@
;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);var isTouch='ontouchstart'in window;proto.createdCallback=function(){var shadowRoot=this.createShadowRoot();shadowRoot.innerHTML=`<style>
#container {
background-color: rgba(0, 0, 0, 0.85);
display: flex;
flex-flow: row nowrap;
position: relative;
width: 100%;
height: 4.2rem;
-moz-user-select: none;
}
#container > span {
display: inline-block;
position: relative;
height: 100%;
}
#elapsed-time,
#remaining-time {
color: #e7e7e7;
font-size: 1.4rem;
font-weight: 400;
line-height: 4.2rem;
direction: ltr;
vertical-align: top;
flex: 0 0 auto;
width: 5.3rem;
}
#elapsed-time {
padding-left: 1.5rem;
}
#remaining-time {
padding-right: 1.5rem;
text-align: right;
}
#seek-bar {
flex: 1 0 auto;
z-index: 1;
}
#seek-bar-progress {
background-color: #a6b4b7;
border: none;
border-radius: 0;
position: absolute;
top: calc(50% - 0.1rem);
left: 0;
width: 100%;
height: 0.1rem;
pointer-events: none;
-moz-appearance: none;
}
#seek-bar-progress::-moz-progress-bar {
background-color: #01c5ed;
}
#seek-bar-indicator {
background-color: transparent;
border-radius: 50%;
position: absolute;
top: calc(50% - 3rem);
left: -3rem;
width: 6rem;
height: 6rem;
pointer-events: none;
transition: transform 20ms linear;
will-change: transform;
}
#seek-bar-indicator:after {
content: '';
background-color: #fff;
border: 1px solid #fff;
border-radius: 50%;
position: absolute;
top: 1.85rem;
left: 1.85rem;
width: 2.1rem;
height: 2.1rem;
}
#seek-bar-indicator.highlight {
background-color: #00caf2;
}
</style>
<div id="container">
<span id="elapsed-time"></span>
<span id="seek-bar">
<progress id="seek-bar-progress"></progress>
<div id="seek-bar-indicator"></div>
</span>
<span id="remaining-time"></span>
</div>`;var $id=shadowRoot.getElementById.bind(shadowRoot);this.els={container:$id('container'),elapsedTime:$id('elapsed-time'),seekBar:$id('seek-bar'),seekBarProgress:$id('seek-bar-progress'),seekBarIndicator:$id('seek-bar-indicator'),remainingTime:$id('remaining-time')};var container=this.els.container;var seekBar=this.els.seekBar;var seekTimeout=null;container.addEventListener(isTouch?'touchstart':'mousedown',(evt)=>{clearTimeout(seekTimeout);container.addEventListener(isTouch?'touchmove':'mousemove',pointerMoveHandler);container.addEventListener(isTouch?'touchend':'mouseup',pointerEndHandler);this.els.seekBarIndicator.classList.add('highlight');pointerMoveHandler(evt);});var pointerMoveHandler=(evt)=>{var pointer=isTouch?evt.targetTouches[0]:evt;var percent=clamp(0,1,(pointer.clientX-seekBar.offsetLeft)/seekBar.offsetWidth);if(document.documentElement.dir==='rtl'){this.remainingTime=this._overrideRemainingTime=percent*this.duration;}
else{this.elapsedTime=this._overrideElapsedTime=percent*this.duration;}};var pointerEndHandler=(evt)=>{this.dispatchEvent(new CustomEvent('seek',{detail:{elapsedTime:this.elapsedTime}}));container.removeEventListener(isTouch?'touchmove':'mousemove',pointerMoveHandler);container.removeEventListener(isTouch?'touchend':'mouseup',pointerEndHandler);seekTimeout=setTimeout(()=>{this._overrideRemainingTime=null;this._overrideElapsedTime=null;this.els.seekBarIndicator.classList.remove('highlight');},100);};this._overrideRemainingTime=null;this._overrideElapsedTime=null;this.duration=null;this.elapsedTime=null;this.remainingTime=null;};Object.defineProperty(proto,'duration',{get:function(){return this._duration;},set:function(value){if(isNaN(value)){this._duration=null;this.remainingTime=null;return;}
this._duration=value;this.remainingTime=this._duration-this._elapsedTime;}});Object.defineProperty(proto,'elapsedTime',{get:function(){return this._elapsedTime;},set:function(value){if(isNaN(value)){this._elapsedTime=null;this.remainingTime=null;return;}
this._elapsedTime=this._overrideElapsedTime!==null?this._overrideElapsedTime:value;this.remainingTime=this._duration-this._elapsedTime;}});Object.defineProperty(proto,'remainingTime',{get:function(){return this._remainingTime;},set:function(value){var indeterminate=isNaN(value)||isNaN(this._duration);if(indeterminate){this._remainingTime=null;this._elapsedTime=null;}
else{this._remainingTime=this._overrideRemainingTime!==null?this._overrideRemainingTime:value;this._elapsedTime=this._duration-this._remainingTime;}
window.requestAnimationFrame(()=>{if(indeterminate){this.els.remainingTime.textContent='---:--';this.els.elapsedTime.textContent='--:--';return;}
var percent=this._duration?this._elapsedTime/this._duration:0;var x=this.els.seekBar.offsetWidth*percent;if(document.documentElement.dir==='rtl'){x=this.els.seekBar.offsetWidth-x;}
this.els.seekBarIndicator.style.transform='translateX('+x+'px)';IntlHelper.get('duration').then((duration)=>{this.els.remainingTime.textContent=duration.format(-this._remainingTime*1000);this.els.elapsedTime.textContent=duration.format(this._elapsedTime*1000);});});}});function clamp(min,max,value){return Math.min(Math.max(min,value),max);}
IntlHelper.define('duration','mozduration',{minUnit:'second',maxUnit:'minute'});try{window.MusicSeekBar=document.registerElement('music-seek-bar',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,24 @@
;(function(window){'use strict';var GaiaToolbar=window['gaia-toolbar'];var proto=Object.create(GaiaToolbar.prototype);proto.createdCallback=function(){GaiaToolbar.prototype.createdCallback.apply(this,arguments);this.querySelector('style').innerHTML+=`music-tab-bar {
background-color: var(--background-minus);
position: absolute;
bottom: 0;
left: 0;
width: 100%;
-moz-user-select: none;
}
.-content {
direction: ltr;
}
.-content > *,
.more-button {
transition: none;
}
.-content > .selected {
color: var(--highlight-color);
}`;this.addEventListener('click',(evt)=>{var tab=evt.target.closest('button');if(!tab||tab===this.selectedElement){return;}
this.selectedElement=tab;this.dispatchEvent(new CustomEvent('change',{detail:{selectedElement:this.selectedElement,selectedIndex:this.selectedIndex}}));});this.selectedIndex=0;this.reflow();};Object.defineProperty(proto,'selectedElement',{get:function(){return this.querySelectorAll('button')[this.selectedIndex];},set:function(value){var index=[].indexOf.call(this.querySelectorAll('button'),value);if(index!==-1){this.selectedIndex=index;}}});Object.defineProperty(proto,'selectedIndex',{get:function(){return this._selectedIndex||0;},set:function(value){var tabs=this.querySelectorAll('button');if(this._selectedIndex===value||value<0||value>=tabs.length){return;}
this._selectedIndex=value;[].forEach.call(tabs,(tab,index)=>{if(index===this._selectedIndex){tab.classList.add('selected');return;}
tab.classList.remove('selected');});}});try{window.MusicTabBar=document.registerElement('music-tab-bar',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}})(window);

View file

@ -0,0 +1,94 @@
;;;(function(window){'use strict';var proto=Object.create(HTMLElement.prototype);proto.createdCallback=function(){var style=document.createElement('style');style.innerHTML=`music-view-stack {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
-moz-user-select: none;
}
music-view-stack > iframe {
border: none;
visibility: hidden;
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
will-change: transform;
}
music-view-stack > iframe.active,
music-view-stack > iframe.fade,
music-view-stack > iframe.pop,
music-view-stack > iframe.push {
animation-duration: 0.2s;
animation-timing-function: linear;
visibility: visible;
}
music-view-stack > iframe.active {
pointer-events: auto;
}
music-view-stack > iframe.fade {
animation-duration: 0s;
}
music-view-stack > iframe.fade.in {
animation-name: fade-in;
}
music-view-stack > iframe.fade.out {
animation-name: fade-out;
}
music-view-stack > iframe.pop.in {
animation-name: pop-in;
}
music-view-stack > iframe.pop.out {
animation-name: pop-out;
}
music-view-stack > iframe.push.in {
animation-name: push-in;
}
music-view-stack > iframe.push.out {
animation-name: push-out;
}
[dir="rtl"] music-view-stack > iframe.pop.in {
animation-name: push-in;
}
[dir="rtl"] music-view-stack > iframe.pop.out {
animation-name: push-out;
}
[dir="rtl"] music-view-stack > iframe.push.in {
animation-name: pop-in;
}
[dir="rtl"] music-view-stack > iframe.push.out {
animation-name: pop-out;
}
@keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes fade-out {
0% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes pop-in {
0% { transform: translateX(-100%); }
100% { transform: translateX(0); }
}
@keyframes pop-out {
0% { transform: translateX(0); }
100% { transform: translateX(100%); }
}
@keyframes push-in {
0% { transform: translateX(100%); }
100% { transform: translateX(0); }
}
@keyframes push-out {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
}`;if(this.firstChild){this.insertBefore(style,this.firstChild);}else{this.appendChild(style);}
this.cachedViews={};[].forEach.call(this.querySelectorAll('iframe'),(frame)=>{var location=new URL(frame.src);var view={url:location.pathname+location.search,frame:frame,title:frame.contentDocument.title};this.initializeView(view).then((view)=>{if(this.activeView===view){this.dispatchEvent(new CustomEvent('titlechange',{detail:view.title}));}});this.cachedViews[view.url]=view;});this.addEventListener('animationend',(evt)=>{var classList=evt.target.classList;if(classList.contains('destroy')){this.destroyView(evt.target.src);}
classList.remove('fade','pop','push','in','out');});this.views=[];this.activeView=null;};proto.loadView=function(url){var view=this.cachedViews[url];if(view){return Promise.resolve(view);}
var frame=document.createElement('iframe');this.appendChild(frame);frame.src=url;view={url:url,frame:frame,title:''};return this.initializeView(view);};proto.initializeView=function(view){view.frame.addEventListener('rendered',()=>{this.dispatchEvent(new CustomEvent('rendered'));});view.frame.addEventListener('titlechange',(evt)=>{view.title=evt.detail;if(this.activeView===view){this.dispatchEvent(new CustomEvent('titlechange',{detail:evt.detail}));}});const onL10nReady=()=>{view.title=view.frame.contentDocument.title;this.cachedViews[view.url]=view;this.dispatchEvent(new CustomEvent('loaded'));return view;};return loaded(view.frame).then(()=>view.frame.contentDocument.l10n.ready).then(onL10nReady);};proto.destroyView=function(url){for(var key in this.cachedViews){var view=this.cachedViews[key];if(key===url||view.frame.src===url){view.frame.contentWindow.dispatchEvent(new CustomEvent('viewdestroy'));delete this.cachedViews[key];setTimeout(()=>this.removeChild(view.frame),5000);return;}}};proto.setRootView=function(url){return this.loadView(url).then((view)=>{var oldActiveView=this.activeView;if(oldActiveView){oldActiveView.frame.classList.add('fade','out');oldActiveView.frame.classList.remove('active');oldActiveView.frame.contentWindow.dispatchEvent(new CustomEvent('viewhidden'));}
this.views=[view];this.activeView=view;var newActiveView=this.activeView;newActiveView.frame.classList.add('fade','in');newActiveView.frame.classList.add('active');newActiveView.frame.contentWindow.dispatchEvent(new CustomEvent('viewvisible'));this.dispatchEvent(new CustomEvent('change',{detail:newActiveView}));});};proto.pushView=function(url){if(!this.activeView){return this.setRootView(url);}
return this.loadView(url).then((view)=>{requestAnimationFrame(()=>{var oldActiveView=this.activeView;oldActiveView.frame.classList.add('push','out');oldActiveView.frame.classList.remove('active');oldActiveView.frame.contentWindow.dispatchEvent(new CustomEvent('viewhidden'));this.views.push(view);this.activeView=view;var newActiveView=this.activeView;newActiveView.frame.classList.add('push','in','active');newActiveView.frame.contentWindow.dispatchEvent(new CustomEvent('viewvisible'));this.dispatchEvent(new CustomEvent('change',{detail:newActiveView}));});});};proto.popView=function(destroy){if(this.views.length<2){return Promise.reject();}
var oldActiveView=this.activeView;this.views.pop();this.activeView=this.views[this.views.length-1];var newActiveView=this.activeView;return new Promise((resolve)=>{requestAnimationFrame(()=>{oldActiveView.frame.classList.add('pop','out');oldActiveView.frame.classList.remove('active');oldActiveView.frame.contentWindow.dispatchEvent(new CustomEvent('viewhidden'));if(destroy){oldActiveView.frame.classList.add('destroy');}
newActiveView.frame.classList.add('pop','in','active');newActiveView.frame.contentWindow.dispatchEvent(new CustomEvent('viewvisible'));this.dispatchEvent(new CustomEvent('change',{detail:newActiveView}));resolve();});});};try{window.MusicViewStack=document.registerElement('music-view-stack',{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}
function loaded(frame){return new Promise((resolve)=>{frame.addEventListener('load',function onLoad(){frame.removeEventListener('load',onLoad);resolve();});});}})(window);