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,7 @@
/* XXX Bug 1018269
* animation keyframes have to be specified outside of the shadow DOM.
*/
@keyframes rotate {
from { transform: rotate(1deg); }
to { transform: rotate(360deg); }
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84"><path opacity=".85" fill="#5F5F5F" d="M42 0c23.3 0 42 18.7 42 42S65.3 84 42 84 0 65.3 0 42 18.7 0 42 0z"/><path fill="#FFF" d="M60.7 40.1c-.9-9.3-9.3-16.8-18.7-16.8-10.3 0-18.7 8.4-18.7 18.7S31.7 60.7 42 60.7c3.7 0 7.5-.9 10.3-2.8l-2.8-3.7C46.7 56.1 44.8 57 42 57c-8.4 0-14.9-6.5-14.9-14.9s6.5-15 14.9-15c7.5 0 13.1 5.6 14 13.1h-6.5l7.5 7.5c.9.9 2.8.9 3.7 0l7.5-7.5h-7.5z"/></svg>

After

Width:  |  Height:  |  Size: 443 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84"><path opacity=".85" fill="#E51E1E" d="M42 0c23.3 0 42 18.7 42 42S65.3 84 42 84 0 65.3 0 42 18.7 0 42 0z"/><path fill="#FFF" d="M60.7 40.1c-.9-9.3-9.3-16.8-18.7-16.8-10.3 0-18.7 8.4-18.7 18.7S31.7 60.7 42 60.7c3.7 0 7.5-.9 10.3-2.8l-2.8-3.7C46.7 56.1 44.8 57 42 57c-8.4 0-14.9-6.5-14.9-14.9s6.5-15 14.9-15c7.5 0 13.1 5.6 14 13.1h-6.5l7.5 7.5c.9.9 2.8.9 3.7 0l7.5-7.5h-7.5z"/></svg>

After

Width:  |  Height:  |  Size: 443 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="24.134" y1="31.414" x2="81.176" y2="46.699"><stop offset="0" stop-color="#00B4CF"/><stop offset=".979" stop-color="#00B4CF" stop-opacity="0"/></linearGradient><path fill-rule="evenodd" clip-rule="evenodd" fill="url(#a)" d="M83.9 39.5v2.6h-3.3c0 21.3-17.3 38.6-38.7 38.6C20.6 80.7 3.3 63.4 3.3 42 3.3 20.6 20.6 3.3 42 3.3V0C18.8 0 0 18.8 0 42s18.8 42 42 42 42-18.8 42-42c0-.8 0-1.7-.1-2.5z"/></svg>

After

Width:  |  Height:  |  Size: 518 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84"><path opacity=".85" fill="#E51E1E" d="M42 0c23.3 0 42 18.8 42 42 0 23.3-18.8 42-42 42-23.1.1-42-18.7-42-42C0 18.8 18.9 0 42 0z"/><path fill="#FFF" d="M42 25.4c-.9 0-2.5 2.5-3.4 5.5 1.1-.2 2.3-.3 3.5-.3s2.3.1 3.3.3c-.9-3-2.5-5.5-3.4-5.5M27.1 39.1l5.7-5.7c1.7-8.3 6.7-16.7 9.2-16.7s7.5 8.4 9.2 16.7l5.7 5.7V54h-4l-5.6-5.6c-.6.6-1.2 1.1-1.9 1.5h-7c-.7-.4-1.3-.9-1.9-1.5L31.1 54h-4V39.1M16.6 59.2c.4.9 1.3 1.5 2.4 1.5h46c1 0 1.9-.6 2.4-1.5H16.6z"/></svg>

After

Width:  |  Height:  |  Size: 513 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84"><path opacity=".85" fill="#333" d="M42 0c23.3 0 42 18.8 42 42 0 23.3-18.8 42-42 42-23.1.1-42-18.7-42-42C0 18.8 18.9 0 42 0z"/><path fill="#FFF" d="M29.9 50c.4.9 1.3 1.5 2.4 1.5h19.3c1 0 1.9-.6 2.4-1.5H29.9zm22.3-17.8L51 33.4v.1L42.4 42c-.3.3-.7.3-1 0l-8.6-8.6v-.1l-1.2-1.2c-1.6.3-3.1.6-4.6.9.2.5.4 1 .9 1.5l11.3 11.3c1.5 1.5 3.8 1.5 5.3 0l11.3-11.3c.4-.4.7-.9.9-1.5-1.4-.3-2.9-.6-4.5-.8z"/></svg>

After

Width:  |  Height:  |  Size: 459 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="42" x2="42" y2="84"><stop offset="0" stop-color="#E5EBEF"/><stop offset="1" stop-color="#EDF1F4"/></linearGradient><path fill="url(#a)" d="M42 0c23.3 0 42 18.8 42 42 0 23.3-18.8 42-42 42-23.1.1-42-18.7-42-42C0 18.8 18.9 0 42 0z"/><path fill="#9AB0C0" d="M41.5 25.9c-.9 0-2.5 2.6-3.5 5.7 1.1-.2 2.3-.3 3.6-.3 1.2 0 2.4.1 3.4.3-1-3.1-2.6-5.7-3.5-5.7M43 53.3h2.2c.3.9.4 2 .4 3.1 0 4-3.1 7.2-4.1 7.2s-4.1-3.2-4.1-7.2c0-1.1.1-2.2.4-3.1H40c-.2.5-.3 1.2-.3 1.9 0 1.8 1.4 3.3 1.9 3.3s1.9-1.5 1.9-3.3c-.2-.7-.3-1.4-.5-1.9M26.1 40l5.9-5.9c1.7-8.6 6.9-17.2 9.5-17.2s7.8 8.7 9.5 17.2l5.9 5.9v15.4h-4.1l-5.7-5.7c-.6.6-1.2 1.1-1.9 1.5h-7.3c-.7-.4-1.3-.9-1.9-1.5l-5.7 5.7h-4.1L26.1 40"/></svg>

After

Width:  |  Height:  |  Size: 799 B

View file

@ -0,0 +1,32 @@
;'use strict';window.GaiaAppIcon=(function(exports){const LAUNCH_TIMEOUT=500;const PREDEFINED_ICONS={default:'default_icon.svg',unrecoverable:'app_install_unrecoverable.svg',installing:'app_installing.svg',paused:'app_install_canceled.svg',failed:'app_install_failed.svg'};const SHADOW_BLUR=1;const SHADOW_OFFSET={x:1,y:1};const SHADOW_COLOR='rgba(0, 0, 0, 0.2)';const DEFAULT_BACKGROUND_COLOR='rgb(228, 234, 238)';const CANVAS_PADDING=2*window.devicePixelRatio;const FAVICON_SCALE=0.55;var proto=Object.create(HTMLElement.prototype);var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';var baseurl=window.GaiaAppIconBaseurl||base+'gaia-site-icon/';proto.createdCallback=function(){this._template=template.content.cloneNode(true);var shadow=this.createShadowRoot();shadow.appendChild(this._template);this._container=shadow.getElementById('image-container');this._titleContainer=shadow.getElementById('title-container');this._subtitle=shadow.getElementById('subtitle');this._showName=true;this._image=null;this._app=null;this._bookmark=null;this._entryPoint='';this._size=-1;this._hasIcon=false;this._hasUserSetIcon=false;this._hasPredefinedIcon=false;this._iconUrl=null;this._pendingIconUrl=null;this._pendingIconRefresh=false;this._lastState=null;this._predefinedIcons={};for(var key in PREDEFINED_ICONS){this._predefinedIcons[key]=baseurl+'images/'+PREDEFINED_ICONS[key];}
this.tabIndex=0;this.setAttribute('role','link');var activate=()=>{if(!this.dispatchEvent(new CustomEvent('activated',{cancelable:true}))){return;}
this.launch();};this.addEventListener('keydown',(e)=>{switch(e.keyCode){case 32:case 13:activate();}});this.addEventListener('click',activate);this.refresh();};Object.defineProperty(proto,'app',{get:function(){return this._app;},set:function(app){if(this._app){this._app.removeEventListener('progress',this);this._app.removeEventListener('downloaderror',this);this._app.removeEventListener('downloadsuccess',this);this._app.removeEventListener('downloadapplied',this);}
delete this.dataset.testIconUrl;this._cancelIconLoad();this._removeOldIcon();this._hasIcon=false;this._app=app;if(!app){return;}
this._bookmark=null;this._app.addEventListener('progress',this);this._app.addEventListener('downloaderror',this);this._app.addEventListener('downloadsuccess',this);this._app.addEventListener('downloadapplied',this);this._container.classList.add('initial-load');},enumerable:true});Object.defineProperty(proto,'entryPoint',{get:function(){return this._entryPoint;},set:function(entryPoint){this._entryPoint=entryPoint?entryPoint:'';this.refresh();},enumerable:true});Object.defineProperty(proto,'state',{get:function(){if(!this.app){return'unavailable';}
if(this.app.installState==='pending'&&!this.app.downloadAvailable&&!this.app.readyToApplyDownload){return'unrecoverable';}
if(this.app.downloading){return'installing';}
if(this.app.downloadError){if(this.app.downloadError.name==='DOWNLOAD_CANCELED'){return'paused';}else{return'error';}}
if(this.app.installState==='pending'){return'paused';}
return'installed';},enumberable:true});Object.defineProperty(proto,'name',{get:function(){return this._subtitle?this._subtitle.textContent:'';},enumberable:true});Object.defineProperty(proto,'size',{get:function(){return(this._size===-1)?this.clientWidth:this._size;},set:function(size){this._size=size>=0?size:-1;},enumerable:true});Object.defineProperty(proto,'bookmark',{get:function(){return this._bookmark;},set:function(bookmark){if(!this._bookmark||this._bookmark.id!==bookmark.id){this.app=null;}
this._bookmark=bookmark;},enumerable:true});Object.defineProperty(proto,'icon',{get:function(){if(window.VulpesCompat&&this.app&&this._vulpesSourceIcon)return Promise.resolve(this._vulpesSourceIcon);return new Promise((resolve,reject)=>{if(!this._hasIcon||this._hasPredefinedIcon){return reject();}
var image=this._container.querySelector('img');if(!image){return reject();}
var canvas=document.createElement('canvas');var size=this.size*window.devicePixelRatio;canvas.width=canvas.height=size;var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.drawImage(image,0,0,size,size);try{canvas.toBlob((blob)=>{resolve(blob);});}catch(e){console.error('Failed to get canvas data for icon');reject(e);}});},set:function(blob){if(blob){this._prepareIconLoader();this._hasUserSetIcon=true;this._pendingIconUrl='user-set';this._image.src=URL.createObjectURL(blob);}else{this._pendingIconUrl=null;delete this.dataset.testIconUrl;this._cancelIconLoad();this._removeOldIcon();}},enumerable:true});Object.defineProperty(proto,'showName',{get:function(){return this._showName;},set:function(show){show=show?true:false;if(this._showName!==show){this._showName=show;this._titleContainer.classList.toggle('hidden',!show);}},enumerable:true});Object.defineProperty(proto,'isUserSet',{get:function(){return this._iconUrl==='user-set';},enumerable:true});proto._cancelIconLoad=function(){if(!this._image){return;}
this._pendingIconUrl=null;this._image.onload=null;this._image.src='';this._image=null;};proto._removeOldIcon=function(){while(this._container.children.length>1){this._container.removeChild(this._container.lastChild);}};proto.launch=function(){if(!this.app&&!this.bookmark){return;}
this.classList.add('launching');setTimeout(()=>{this.classList.remove('launching');},LAUNCH_TIMEOUT);if(this.app){window.performance.mark('appLaunch@'+this.app.origin);this.app.launch(this.entryPoint);}else{var features={name:this.bookmark.name,remote:true};if(this.bookmark.scope){features.scope=this.bookmark.scope;}
window.open(this.bookmark.url,'_samescope',Object.keys(features).map(function eachFeature(key){return encodeURIComponent(key)+'='+
encodeURIComponent(features[key]);}).join(','));}};proto._prepareIconLoader=function(){this._cancelIconLoad();this._hasPredefinedIcon=false;this._hasUserSetIcon=false;this._image=document.createElement('img');this._image.setAttribute('role','presentation');this._image.onload=()=>{this._image.onload=()=>{this._removeOldIcon();this._container.appendChild(this._image);this._container.classList.remove('initial-load');this._image=null;this._hasIcon=true;if(this._pendingIconUrl){this._iconUrl=this.dataset.testIconUrl=this._pendingIconUrl;this._pendingIconUrl=null;}
if(!this._hasPredefinedIcon){this.dispatchEvent(new CustomEvent('icon-loaded'));}
if(this._pendingIconRefresh){this._image=null;this._pendingIconRefresh=false;this.refresh();}};if(!this._hasUserSetIcon){var canvas=document.createElement('canvas');var size=this.size*window.devicePixelRatio;canvas.width=canvas.height=size;var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.shadowColor=SHADOW_COLOR;ctx.shadowBlur=SHADOW_BLUR;ctx.shadowOffsetX=SHADOW_OFFSET.x;ctx.shadowOffsetY=SHADOW_OFFSET.y;if(this.bookmark&&!this._hasPredefinedIcon){if(this._image.width<=size/2){ctx.beginPath();ctx.arc(size/2,size/2,size/2-CANVAS_PADDING,0,2*Math.PI);ctx.fillStyle=DEFAULT_BACKGROUND_COLOR;ctx.fill();ctx.shadowBlur=0;ctx.shadowOffsetY=0;ctx.mozImageSmoothingEnabled=false;var iconSize=size*FAVICON_SCALE;ctx.drawImage(this._image,(size-iconSize)/2,(size-iconSize)/2,iconSize,iconSize);}else{var clipCanvas=document.createElement('canvas');clipCanvas.width=clipCanvas.height=size;var clipCtx=clipCanvas.getContext('2d',{willReadFrequently:true});clipCtx.beginPath();clipCtx.arc(size/2,size/2,size/2-CANVAS_PADDING,0,2*Math.PI);clipCtx.clip();clipCtx.drawImage(this._image,CANVAS_PADDING,CANVAS_PADDING,size-CANVAS_PADDING*2,size-CANVAS_PADDING*2);ctx.drawImage(clipCanvas,0,0);}}else{ctx.drawImage(this._image,CANVAS_PADDING,CANVAS_PADDING,size-CANVAS_PADDING*2,size-CANVAS_PADDING*2);}
canvas.toBlob(function(image,blob){if(image.onload){image.src=URL.createObjectURL(blob);}}.bind(this,this._image));}
if(this._hasUserSetIcon){this._image.onload();}};this._image.onerror=(e)=>{console.error('Failed to load icon',e);this._pendingIconUrl=null;if(this._pendingIconRefresh){this._pendingIconRefresh=false;this._image=null;this.refresh();}else if(!this._hasIcon){this._image.onerror=null;this._setPredefinedIcon('default');}else{this._image=null;}};};proto._setPredefinedIcon=function(name){this._hasPredefinedIcon=true;this._image.src=this._pendingIconUrl=this._predefinedIcons[name];};proto._localizeString=function(str){var userLang=document.documentElement.lang;if(navigator.mozL10n&&navigator.mozL10n.ctx.qps.indexOf(userLang)!==-1){return navigator.mozL10n.qps[userLang].translate(str);}
return str;};proto.updateName=function(){if(this.app){var userLang=document.documentElement.lang;var ep=this.entryPoint||undefined;this.app.getLocalizedValue('short_name',userLang,ep).then((shortName)=>{this._subtitle.textContent=this._localizeString(shortName);},()=>{this.app.getLocalizedValue('name',userLang,ep).then((name)=>{this._subtitle.textContent=this._localizeString(name);},(e)=>{var manifest=this.app.manifest||this.app.updateManifest;if(manifest){var nameObject=(manifest.entry_points&&this.entryPoint)?manifest.entry_points[this.entryPoint]:manifest;this._subtitle.textContent=this._localizeString(nameObject.short_name||nameObject.name);}else{console.error('Error retrieving app name',e);this._subtitle.textContent='';}});});}else if(this.bookmark){this._subtitle.textContent=this.bookmark.name;}else{this._subtitle.textContent='';}};proto.refresh=function(){if(!this._template){return;}
this.updateName();this._container.classList.remove('downloading');if(this.app){this.dataset.identifier=this.app.manifestURL+
(this.entryPoint?'/'+this.entryPoint:'');}else if(this.bookmark){this.dataset.identifier=this.bookmark.id;}else{delete this.dataset.identifier;}
if(this._image){this._pendingIconRefresh=true;return;}
var size=this.size*window.devicePixelRatio;if(size<1){return;}
this._prepareIconLoader();if(this.bookmark){if(!this._hasIcon){this._setPredefinedIcon('default');}
return;}
var state=this._lastState=this.state;switch(state){case'unrecoverable':this._setPredefinedIcon('unrecoverable');break;case'installing':this._setPredefinedIcon('installing');this._container.classList.add('downloading');break;case'paused':this._setPredefinedIcon('paused');break;case'error':this._setPredefinedIcon('failed');break;case'installed':var handleError=function(image,e){if(e.message!=='NO_ICON'&&e.name!=='NO_ICON'){console.error('Failed to retrieve icon',e);}if(image.onload&&!this._hasIcon){this._setPredefinedIcon('default');}else{this._image=null;}};var getImage=()=>{navigator.mozApps.mgmt.getIcon(this.app,size,this.entryPoint).then(function(image,blob){this._pendingIconUrl='app-icon';if(window.VulpesCompat){this._vulpesSourceIcon=blob;this._hasUserSetIcon=true;}if(image.onload){image.src=URL.createObjectURL(blob);}}.bind(this,this._image),handleError.bind(this,this._image));};getImage();break;}};proto.handleEvent=function(e){switch(e.type){case'progress':case'downloadsuccess':if(this.state!==this._lastState){this.refresh();}
break;case'downloaderror':case'downloadapplied':this.refresh();break;}};var template=document.createElement('template');var stylesheet=baseurl+'style.css';template.innerHTML=`<style>@import url(${stylesheet});</style>
<div id="image-container"><div id="spinner"></div></div>
<div id="title-container"><div dir="auto" id="subtitle"></div></div>`;return document.registerElement('gaia-app-icon',{prototype:proto});})(window);

View file

@ -0,0 +1,54 @@
gaia-app-icon {
display: flex;
flex-direction: column;
font-size: 0;
}
#image-container {
position: relative;
transition: visibility 0.2s, opacity 0.2s;
}
#image-container.initial-load {
opacity: 0;
visibility: hidden;
}
#image-container > #spinner {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#image-container.downloading > #spinner {
display: block;
background: no-repeat center center url('images/app_install_spinner.svg');
background-size: contain;
animation: rotate 2s infinite linear;
}
#image-container,
#image-container > * {
width: 100%;
}
#subtitle {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
margin-top: 0.3rem;
}
#title-container {
transition: opacity 0.2s, visibility 0.2s;
}
#title-container.hidden {
opacity: 0;
visibility: hidden;
height: 0;
}