Update shared Gaia workflows and Sargo development tooling

Fix camera switching and Contacts/SMS activity routing across shared hosts.
Integrate Marketplace installation and native standalone recovery tools,
Bluetooth runtime packages and trusted certificates.

Update English/French READMEs and the shared changelog with tested scope
and remaining radio/audio/Bluetooth limitations. Preview17 remains the
existing APK; no new native image is released.

Validation: shared JavaScript and native Python tests; Android packaging
and payload parity from an isolated publication checkout.
This commit is contained in:
OverSu 2026-10-08 14:27:17 +02:00
commit 0041cd9660
101 changed files with 3883 additions and 335 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

View file

@ -0,0 +1,5 @@
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Marketplace</title><link rel="stylesheet" href="/shared/style/confirm.css"><link rel="stylesheet" href="marketplace.css"><script defer src="marketplace.js"></script></head><body>
<iframe id="catalogue" mozbrowser title="Marketplace"></iframe>
<section id="message" hidden><img src="icon.png" alt="" width="96" height="96"><p id="status" role="status"></p><button id="browse" type="button"></button><button id="open" type="button" hidden></button></section>
<form id="confirm" role="dialog" data-type="confirm" hidden><section><h1 id="title"></h1><p id="question"></p><p id="permissions"></p></section><menu><button id="cancel" type="button"></button><button id="install" type="submit" class="recommend"></button></menu></form>
</body></html>

View file

@ -0,0 +1,19 @@
{
"name": "Marketplace",
"description": "Vulpes OS application catalogue",
"launch_path": "/index.html",
"type": "certified",
"icons": {
"512": "/icon.png"
},
"permissions": {
"browser": {},
"webapps-manage": {}
},
"locales": {
"fr": {
"name": "Marketplace",
"description": "Catalogue des applications Vulpes OS"
}
}
}

View file

@ -0,0 +1 @@
html,body{width:100%;height:100%;margin:0;background:#f4f4f4;font-family:Fira Sans,sans-serif}#catalogue{position:absolute;inset:0;width:100%;height:100%;border:0}#message{padding:3rem 2rem;text-align:center;font-size:1.8rem}#message button{display:block;width:100%;padding:1rem;margin:1rem 0;font:inherit}#open[hidden],[hidden]{display:none!important}#confirm{z-index:10}#confirm section{overflow:auto}#permissions{font-size:1.5rem}

View file

@ -0,0 +1,32 @@
(async()=>{
const frame=document.getElementById('catalogue'),message=document.getElementById('message'),dialog=document.getElementById('confirm');
let attempt=0,busy=false,prepared=null,installed=null,language=await VulpesCompat.call('locale.current');
const fr=()=>/^fr(?:-|$)/i.test(language);
const text=(f,e)=>fr()?f:e;
function labels(){document.getElementById('browse').textContent=text('Ouvrir le catalogue','Open catalogue');document.getElementById('open').textContent=text('Ouvrir','Open');document.getElementById('install').textContent=text('Installer','Install');document.getElementById('cancel').textContent=text('Annuler','Cancel');}
function loadFailed(){status(text('Catalogue inaccessible. Vérifiez la connexion Internet, puis réessayez.','Catalogue unavailable. Check your Internet connection, then try again.'));document.getElementById('open').hidden=true;}
frame.addEventListener('mozbrowsererror',loadFailed);
function browse(){labels();message.hidden=true;dialog.hidden=true;frame.style.visibility='visible';frame.src='https://vulpes-os.org/marketplace/?mode=app&lang='+(fr()?'fr':'en');}
function status(value){frame.style.visibility='hidden';message.hidden=false;document.getElementById('status').textContent=value;}
async function prepare(url){
if(busy)return;const current=++attempt;busy=true;prepared=null;installed=null;document.getElementById('open').hidden=true;
status(text('Vérification de l’application…','Checking application…'));
try {const value=await VulpesCompat.call('marketplace.prepare',{url});if(current!==attempt)return;prepared=value;
document.getElementById('title').textContent=prepared.name;
document.getElementById('question').textContent=text('Installer cette application archivée ?','Install this archived application?')+' ('+(prepared.bytes/1048576).toFixed(1)+' Mio)';
document.getElementById('permissions').textContent=text('Elle sera exécutée comme une application web, sans accès aux fonctions système. Certains anciens services peuvent ne plus fonctionner.','It will run as a web application without system access. Some old services may no longer work.');
message.hidden=true;dialog.hidden=false;
}catch(error){if(current!==attempt)return;status(text('Installation impossible : ','Cannot install: ')+error.message);busy=false;}
}
dialog.addEventListener('submit',async event=>{event.preventDefault();if(!prepared)return;const token=prepared.token;prepared=null;dialog.hidden=true;status(text('Installation…','Installing…'));
try {installed=await VulpesCompat.call('marketplace.install',{token});status(text('Application ajoutée à l’accueil.','Application added to Home.'));document.getElementById('open').hidden=false;}
catch(error){status(text('Installation impossible : ','Cannot install: ')+error.message);}finally{busy=false;}
});
const cancel=()=>{attempt++;prepared=null;busy=false;VulpesCompat.call('marketplace.cancel').catch(console.error);browse();};
document.getElementById('cancel').onclick=cancel;
document.getElementById('browse').onclick=cancel;
document.getElementById('open').onclick=()=>installed && VulpesCompat.call('apps.launch',{manifestURL:installed.manifestURL});
addEventListener('languagechange',()=>{language=navigator.language;if(!busy)browse();});
browse();
setInterval(async()=>{if(busy)return;try{const url=await VulpesCompat.call('marketplace.poll');if(url)await prepare(url);}catch(error){console.error(error);}},750);
})();