API du pont JavaScript
La fenêtre
Plein écran, image dans l'image, couleurs des barres système, blocage des captures d'écran, indication de la protection contre la copie dans la compilation (AppMint.copyProtection), écran de démarrage et fermeture d'une fenêtre.
AppMint.copyProtection assistant#
AppMint.copyProtection
Exemple
true lorsque l'application a été compilée avec Protection contre la copie activée ; absent (undefined) sinon. Lecture seule : une page ne peut pas activer ni désactiver la protection, seulement demander si elle est active.
Renvoie : true, ou undefined lorsque la protection est désactivée (et dans un navigateur). Nécessite : Protection contre la copie activée à l'étape 3 (Intégrer), sous Options d'affichage, lors de la compilation. Désactivée par défaut.
Lorsque la protection est active, le texte de l'application ne peut être ni sélectionné, ni copié, ni coupé ; copier / couper, l'événement contextmenu et Ctrl/Cmd + C, X et A sont annulés hors des champs modifiables ; et aucun menu d'appui long n'apparaît. Les champs de saisie, zones de texte, listes déroulantes et régions contenteditable restent entièrement modifiables : les formulaires continuent donc de fonctionner.
Masquez vos propres boutons « Copier » lorsque la protection est active : ils ne copieraient rien et sembleraient défectueux :
const protectedApp = !!(window.AppMint && window.AppMint.copyProtection === true);
document.querySelectorAll('[data-copy-button]').forEach((btn) => {
btn.hidden = protectedApp;
});Ou choisissez une fois, au démarrage, la formulation d'une indication :
const hint = document.getElementById('share-hint');
hint.textContent = (window.AppMint && window.AppMint.copyProtection === true)
? 'Tap Share to send this lesson to a friend.'
: 'Select any text to copy it, or tap Share.';Combinez-le avec le verrouillage des captures d'écran pour une page qui ne doit pas quitter l'application :
if (window.AppMint && AppMint.copyProtection === true && window.WebToApk && WebToApk.setSecureScreen) {
WebToApk.setSecureScreen(true); // also blocks screenshots and recents thumbnails
document.body.classList.add('protected');
}Remarques : le menu d'appui long sur les liens et les images (ouvrir, copier, partager ou télécharger) est un interrupteur de compilation distinct, Menu d'appui long sur les liens et les images, au même endroit. Il est désactivé par défaut : un appui long sur un lien ne fait donc rien tant que vous ne l'activez pas ; la protection contre la copie le garde toujours désactivé. Une page peut tout de même refuser le menu sur un élément en annulant contextmenu (el.addEventListener('contextmenu', (e) => e.preventDefault())). La protection empêche la copie dans l'application ; elle n'empêche pas une capture d'écran : pour cela, voir WebToApk.setSecureScreen(true).
screen.orientation standard web#
screen.orientation.lock(type) / unlock()
Exemple
Le verrouillage d'orientation d'écran standard, qu'une WebView ordinaire refuse : passe l'application en paysage pour une vidéo ou un jeu, puis la remet comme avant.
Renvoie : lock(type) → une Promise qui se résout une fois l'orientation demandée ; rejetée avec TypeError pour un type inconnu et NotSupportedError sur Android TV. unlock() revient à l'orientation avec laquelle l'application a été compilée. Nécessite : rien.
const player = document.getElementById('player');
document.getElementById('fullscreen').addEventListener('click', async () => {
try {
await screen.orientation.lock('landscape'); // either landscape, follows the sensor
} catch (e) {
console.log('Could not rotate:', e.name);
}
player.classList.add('wide');
});
document.getElementById('done').addEventListener('click', () => {
screen.orientation.unlock();
player.classList.remove('wide');
});
screen.orientation.addEventListener('change', () => console.log(screen.orientation.type));Passez un jeu en paysage au démarrage ; sur Android TV, l'écran est déjà en paysage : continuez donc :
async function startGame() {
try {
await screen.orientation.lock('landscape');
} catch (e) {
if (e.name !== 'NotSupportedError') console.log('Could not rotate:', e.name);
}
runGame();
}
function quitGame() {
screen.orientation.unlock(); // back to the orientation the app was built with
showMenu();
}Suivez la forme de la vidéo en cours de lecture, et revenez en arrière à la fin :
const video = document.getElementById('clip');
video.addEventListener('play', () => {
const wide = video.videoWidth >= video.videoHeight;
screen.orientation.lock(wide ? 'landscape' : 'portrait').catch((e) => console.log(e.name));
});
video.addEventListener('ended', () => screen.orientation.unlock());Remarques : types : any, natural, portrait, portrait-primary, portrait-secondary, landscape, landscape-primary, landscape-secondary. Contrairement à Chrome, la page n'a pas besoin d'être d'abord en plein écran. Les applications créées par IA utilisent lockOrientation() de @/lib/appmintNative.
window.close standard web#
window.close()
Exemple
Ferme l'écran principal de l'application. La coque remplace window.close() afin qu'un bouton « Fermer » ou « Quitter » dans votre page fonctionne dans l'application.
Retourne : rien. Nécessite : rien.
document.getElementById('exit-btn').onclick = function () {
saveDraft(); // anything unsaved — the screen closes at once
window.close(); // in the app: WebToApk.closeWindow(); in a browser: normal behaviour
};Masquez le bouton dans un navigateur, où window.close() ne fait généralement rien sur un onglet ouvert par l'utilisateur :
if (!window.WebToApk) document.getElementById('exit-btn').hidden = true;Demandez d'abord, car l'application se ferme dès que window.close() s'exécute :
document.getElementById('quit').addEventListener('click', function () {
if (hasUnsavedChanges() && !confirm('You have unsaved changes. Close the app anyway?')) {
return;
}
window.close();
});Remarques : le remplacement est installé après le chargement complet de chaque page ; un appel pendant la toute première exécution de script de la page utilise donc le window.close() propre à la WebView (qui ne fait rien). Il n'y a pas de confirmation de sortie sur ce chemin. Une fenêtre de connexion qui appelle window.close() est traitée séparément : elle ferme la fenêtre, pas l'application.
__lockOrientation pont#
window.WebToApk.__lockOrientation(type: String): String
screen.orientation.lock(type) : "ok", "type" pour une chaîne qui n'est pas un OrientationLockType, ou "unsupported" (Android TV est toujours en paysage).
Exemple
Transport interne derrière screen.orientation.lock(type). Les pages utilisent l'API standard ; n'appelez jamais ceci directement - les méthodes __ peuvent changer sans préavis.
Renvoie : 'ok', 'type' pour une chaîne qui n'est pas un type de verrouillage d'orientation, ou 'unsupported' (Android TV). Nécessite : rien à activer.
Utilisez l'API publique :
document.getElementById('play').addEventListener('click', async () => {
try { await screen.orientation.lock('landscape'); } catch (e) { /* NotSupportedError on TV */ }
});
document.getElementById('exit').addEventListener('click', () => screen.orientation.unlock());Distinguez un mauvais type de verrouillage d'un appareil qui ne peut pas pivoter :
async function lockTo(type) {
if (!screen.orientation || typeof screen.orientation.lock !== 'function') return 'unsupported';
try {
await screen.orientation.lock(type);
return 'ok';
} catch (e) {
if (e instanceof TypeError) return 'bad-type'; // not an OrientationLockType string
return 'unsupported'; // NotSupportedError (Android TV)
}
}
lockTo('portrait-primary').then((r) => console.log('orientation lock:', r));Figez l'écran dans la position où l'utilisateur le tient pendant qu'il signe, puis rendez la rotation :
async function startSigning() {
const current = screen.orientation.type; // e.g. 'landscape-primary'
try { await screen.orientation.lock(current); } catch (e) { /* keep going unlocked */ }
showSignaturePad();
}
function finishSigning() {
hideSignaturePad();
screen.orientation.unlock();
}Remarques : Implémenté dans le shell de l'application (WebApiPolyfills.kt). Le même code de page fonctionne sans changement dans Chrome.
__unlockOrientation pont#
window.WebToApk.__unlockOrientation()
screen.orientation.unlock() : retour à l'orientation avec laquelle le créateur a compilé l'application.
Exemple
Transport interne derrière screen.orientation.unlock(). Les pages utilisent l'API standard ; n'appelez jamais ceci directement - les méthodes __ peuvent changer sans préavis.
Renvoie : rien ; l'application revient à l'orientation choisie à la compilation. Nécessite : rien à activer.
Utilisez l'API publique :
document.getElementById('play').addEventListener('click', async () => {
try { await screen.orientation.lock('landscape'); } catch (e) { /* NotSupportedError on TV */ }
});
document.getElementById('exit').addEventListener('click', () => screen.orientation.unlock());Seule la route du jeu est en paysage ; toutes les autres routes reviennent à l'orientation propre de l'application :
function onRouteChange(path) {
if (path.startsWith('/play')) {
screen.orientation.lock('landscape').catch(() => {});
} else if (screen.orientation && typeof screen.orientation.unlock === 'function') {
screen.orientation.unlock(); // menus, settings and the store
}
}
window.addEventListener('popstate', () => onRouteChange(location.pathname));
onRouteChange(location.pathname);Gardez les diapositives d'accueil à la verticale, puis déverrouillez une fois terminé :
async function showOnboarding() {
try { await screen.orientation.lock('portrait'); } catch (e) { /* TV: no lock */ }
await runOnboardingSlides(); // your own flow
screen.orientation.unlock(); // back to the orientation the app was built with
}Remarques : Implémenté dans le shell de l'application (WebApiPolyfills.kt). Le même code de page fonctionne sans changement dans Chrome.
__wakeLock pont#
window.WebToApk.__wakeLock(docId: String, held: Boolean): Boolean
Screen Wake Lock : [held] true garde l'écran allumé tant que le document [docId] détient un sentinel. Renvoie false lorsque le verrou n'a pas pu être pris.
Exemple
Transport interne derrière navigator.wakeLock.request('screen') et WakeLockSentinel.release(). Les pages utilisent l'API standard ; n'appelez jamais ceci directement - les méthodes __ peuvent changer sans préavis.
Renvoie : true lorsque l'indicateur d'écran allumé a été appliqué pour ce document. Nécessite : rien à activer.
Utilisez l'API publique :
let lock = null;
async function keepScreenOn() {
if (!('wakeLock' in navigator)) return;
lock = await navigator.wakeLock.request('screen');
lock.addEventListener('release', () => { lock = null; });
}Reprenez le verrou lorsque l'utilisateur revient dans l'application, car tous les verrous sont abandonnés en arrière-plan :
let lock = null;
let wantLock = false;
async function acquire() {
if (!('wakeLock' in navigator)) return;
try {
lock = await navigator.wakeLock.request('screen');
lock.addEventListener('release', () => { lock = null; });
} catch (e) {
lock = null; // NotAllowedError: the page was not visible
}
}
function startRecipeMode() { wantLock = true; acquire(); }
function stopRecipeMode() { wantLock = false; if (lock) lock.release(); }
document.addEventListener('visibilitychange', () => {
if (wantLock && !lock && document.visibilityState === 'visible') acquire();
});Gardez l'écran allumé uniquement pendant qu'un minuteur d'entraînement tourne, et laissez-le se mettre en veille à la fin du minuteur :
async function runTimer(seconds) {
const lock = ('wakeLock' in navigator)
? await navigator.wakeLock.request('screen').catch(() => null)
: null;
try {
for (let left = seconds; left > 0; left--) {
showRemaining(left);
await new Promise((r) => setTimeout(r, 1000));
}
} finally {
if (lock && !lock.released) await lock.release();
}
}Remarques : l'application abandonne chaque verrou lorsqu'elle passe en arrière-plan et déclenche appmint:wakelock-lost, ce qui libère les sentinels (leur événement release se déclenche).
closeWindow pont#
window.WebToApk.closeWindow()
Utilisez l'encapsulation à base de promesse : const r = await AppMint.requestReview(); // {result, openedStore} const r = await AppMint.requestReview({ openStore: true }); // fiche de l'application s'il n'y a pas de fenêtre r.result : 'shown' | 'not_from_play' | 'quota' | 'error'. Voir RatePrompt.
Décrit par son groupe, Fenêtre d'avis intégrée de Google Play, plutôt que seul.
Exemple
Ferme l'écran principal de l'application (comme appuyer sur Retour sur la dernière page). Les pages appellent normalement le window.close() standard, que la coque redirige ici.
Retourne : rien. Nécessite : rien.
document.getElementById('quit').onclick = function () {
if (confirm('Close the app?')) window.close(); // in the app: the screen closes
};L'appel brut fait la même chose :
if (window.WebToApk && typeof window.WebToApk.closeWindow === 'function') {
window.WebToApk.closeWindow();
}Un bouton « Quitter » qui enregistre d'abord, et qui est masqué dans un navigateur où il n'y a pas d'écran d'application à fermer :
var exitBtn = document.getElementById('exit-btn');
if (!(window.WebToApk && typeof window.WebToApk.closeWindow === 'function')) {
exitBtn.hidden = true;
} else {
exitBtn.onclick = async function () {
exitBtn.disabled = true;
await saveDraft(); // your own save; closing does not wait for anything
window.WebToApk.closeWindow();
};
}Remarques : il termine l'écran de l'application immédiatement : sans confirmation de sortie, même si la compilation en prévoit une. Enregistrez d'abord tout ce qui ne l'est pas. Dans un navigateur, window.close() ne ferme qu'un onglet que le script a lui-même ouvert.
enterPip pont#
window.WebToApk.enterPip(): Boolean
Réduit toute l'application en une fenêtre flottante image dans l'image, tout de suite : une vidéo ou un appel que l'utilisateur veut continuer à regarder en quittant l'application. Android 8+ et uniquement si la compilation a activé le PiP (l'indicateur de manifeste nécessaire) ; renvoie si la fenêtre s'est ouverte. Quitter l'application avec le PiP activé le fait de lui-même ; ceci est le bouton « réduire » explicite.
Exemple
Réduit toute l'application en une petite fenêtre flottante image dans l'image, tout de suite : un bouton « réduire » pour une vidéo ou un appel.
Renvoie : true si la fenêtre flottante s'est ouverte, false sinon (de façon synchrone). Nécessite : Image dans l'image (PiP) activée à l'étape 3 (Intégrer), sous Options d'affichage, lors de la compilation. Android 8+.
var pipBtn = document.getElementById('pip-btn');
pipBtn.onclick = function () {
if (!(window.WebToApk && typeof window.WebToApk.enterPip === 'function')) return;
var ok = window.WebToApk.enterPip();
if (!ok) pipBtn.hidden = true; // PiP not enabled in this build, or Android 7 and older
};Adaptez la page à la petite fenêtre : la fenêtre devient très étroite, donc un écouteur resize peut tout masquer sauf la vidéo.
window.addEventListener('resize', function () {
var small = window.innerWidth < 300;
document.querySelector('nav').style.display = small ? 'none' : '';
});Suivez l'ouverture et la fermeture de la fenêtre flottante avec l'événement appmint:pip (detail.inPip), par exemple pour masquer les commandes d'un appel :
window.addEventListener('appmint:pip', function (e) {
var inPip = !!(e.detail && e.detail.inPip);
document.body.classList.toggle('pip', inPip); // CSS: .pip .call-controls { display: none; }
if (!inPip) {
document.getElementById('chat-panel').hidden = false; // back to the full-size screen
}
});
document.getElementById('minimise').onclick = function () {
if (window.WebToApk && typeof window.WebToApk.enterPip === 'function') {
document.getElementById('chat-panel').hidden = true;
window.WebToApk.enterPip();
}
};Remarques : avec le PiP activé, appuyer sur Accueil fait déjà entrer dans la fenêtre flottante de lui-même ; cette méthode ne sert que pour un bouton explicite. Elle renvoie false dans une compilation sans l'interrupteur PiP, car l'indicateur de manifeste nécessaire est absent. La taille de la fenêtre PiP est choisie par Android. Les applications créées par IA peuvent utiliser pip de @/lib/appmintNative.
isFullscreen pont#
window.WebToApk.isFullscreen(): Boolean
Permet à la page de masquer elle-même la barre d'état (heure/batterie) et la barre de navigation, par ex. un jeu qui passe à son écran de jeu : WebToApk.setFullscreen(true) // masquer les barres système WebToApk.setFullscreen(false) // les ramener WebToApk.toggleFullscreen() WebToApk.isFullscreen() Le choix est conservé d'un lancement à l'autre. Sans effet dans les applications que le créateur a déjà verrouillées en plein écran/kiosque : il n'y a rien à restaurer. L'élément de menu latéral « Plein écran » est l'équivalent pour les utilisateurs finaux et dépend de l'option enableFullscreenToggle du créateur ; ce pont est toujours disponible pour la page propre de l'application.
Décrit par son groupe, Pont plein écran, plutôt que seul.
Exemple
Indique si les barres d'état et de navigation d'Android sont masquées en ce moment.
Renvoie : true / false, de façon synchrone. Nécessite : rien.
function barsHidden() {
if (window.WebToApk && typeof window.WebToApk.isFullscreen === 'function') {
return window.WebToApk.isFullscreen();
}
return false; // in a browser
}
if (barsHidden()) {
document.getElementById('fs-btn').textContent = 'Exit fullscreen';
}Disposez la page selon le choix mémorisé au démarrage, puisqu'il survit aux redémarrages :
document.addEventListener('DOMContentLoaded', function () {
var hidden = !!(window.WebToApk && typeof window.WebToApk.isFullscreen === 'function' &&
window.WebToApk.isFullscreen());
document.documentElement.classList.toggle('bars-hidden', hidden);
// CSS: .bars-hidden header { padding-top: env(safe-area-inset-top); }
});Ajoutez un bouton « Afficher les barres » lorsque l'application a été compilée en plein écran et que les barres ne peuvent pas revenir :
function showBars() {
var W = window.WebToApk;
if (!(W && typeof W.isFullscreen === 'function')) return;
W.setFullscreen(false);
setTimeout(function () { // the change is applied on the UI thread
if (W.isFullscreen()) {
document.getElementById('bars-btn').hidden = true;
}
}, 100);
}Remarques : renvoie true lorsque le créateur a compilé l'application avec Plein écran ou Mode kiosque immersif, OU lorsque la page a appelé setFullscreen(true) / toggleFullscreen(). Dans le premier cas, setFullscreen(false) ne peut pas faire revenir les barres.
isSecureScreen pont#
window.WebToApk.isSecureScreen(): Boolean
WebToApk.setSecureScreen(true) // bloquer les captures d'écran sur CETTE page WebToApk.setSecureScreen(false) // la lever plus tôt WebToApk.isSecureScreen() // -> boolean La protection appartient à la page qui l'a demandée. Elle est levée dès que l'application navigue ailleurs : nouveau document, route pushState, route #hash : ainsi, un écran protégé ne peut pas laisser le reste de l'application verrouillé, et une page qui veut retrouver la protection après un rechargement la redemande simplement. Ce qu'elle fait : captures d'écran, enregistrement d'écran, diffusion et miniature de l'écran des applications récentes sont tous bloqués tant qu'elle est active. Ce qu'elle ne peut pas faire : empêcher un appareil photo pointé sur l'écran. Rien sous Android ne le peut, et aucun pont ici ne prétendra le contraire.
Décrit par son groupe, Protection contre la capture d'écran, plutôt que seul.
Exemple
Indique si la protection contre les captures d'écran (setSecureScreen) est active en ce moment.
Renvoie : un booléen, immédiatement. Nécessite : rien.
function updateLockIcon() {
var on = !!window.WebToApk &&
typeof window.WebToApk.isSecureScreen === 'function' &&
window.WebToApk.isSecureScreen();
document.getElementById('shield').hidden = !on;
}Vérifiez avant d'afficher un numéro de carte, et activez d'abord la protection si cette page ne l'a pas encore demandée :
function revealCardNumber(full) {
var W = window.WebToApk;
if (W && typeof W.isSecureScreen === 'function' && !W.isSecureScreen()) {
W.setSecureScreen(true); // the new state is committed when this returns
}
document.getElementById('card-number').textContent = full;
}Un interrupteur « Masquer des captures d'écran » qui part de l'état réel et le bascule :
var toggle = document.getElementById('privacy-toggle');
var W = window.WebToApk;
if (!W || typeof W.isSecureScreen !== 'function') {
toggle.hidden = true;
} else {
toggle.checked = W.isSecureScreen();
toggle.addEventListener('change', function () {
toggle.checked = W.setSecureScreen(!W.isSecureScreen());
});
}Remarques : il revient de lui-même à false lorsque l'application passe à une autre page ou route, car la protection appartient à la page qui l'a demandée.
setFullscreen pont#
window.WebToApk.setFullscreen(enabled: Boolean)
Permet à la page de masquer elle-même la barre d'état (heure/batterie) et la barre de navigation, par ex. un jeu qui passe à son écran de jeu : WebToApk.setFullscreen(true) // masquer les barres système WebToApk.setFullscreen(false) // les ramener WebToApk.toggleFullscreen() WebToApk.isFullscreen() Le choix est conservé d'un lancement à l'autre. Sans effet dans les applications que le créateur a déjà verrouillées en plein écran/kiosque : il n'y a rien à restaurer. L'élément de menu latéral « Plein écran » est l'équivalent pour les utilisateurs finaux et dépend de l'option enableFullscreenToggle du créateur ; ce pont est toujours disponible pour la page propre de l'application.
Décrit par son groupe, Pont plein écran, plutôt que seul.
Exemple
Masque (true) ou affiche (false) la barre d'état et la barre de navigation d'Android, par exemple lorsqu'un jeu passe à son écran de jeu.
Renvoie : rien. Nécessite : rien : toujours disponible pour votre page. Le choix est conservé d'un lancement à l'autre.
function enterPlayScreen() {
if (window.WebToApk && typeof window.WebToApk.setFullscreen === 'function') {
window.WebToApk.setFullscreen(true); // hide clock/battery and the nav bar
}
}
function leavePlayScreen() {
if (window.WebToApk && window.WebToApk.setFullscreen) {
window.WebToApk.setFullscreen(false); // bring the bars back
}
}Gardez votre contenu hors de l'encoche de l'appareil photo lorsque les barres sont masquées :
document.body.style.paddingTop = 'env(safe-area-inset-top)';
document.body.style.paddingBottom = 'env(safe-area-inset-bottom)';Masquez les barres pendant la lecture d'une vidéo et ramenez-les lorsqu'elle est en pause ou terminée :
var video = document.getElementById('movie');
function hideBars(hidden) {
if (window.WebToApk && typeof window.WebToApk.setFullscreen === 'function') {
window.WebToApk.setFullscreen(hidden);
}
}
video.addEventListener('play', function () { hideBars(true); });
video.addEventListener('pause', function () { hideBars(false); });
video.addEventListener('ended', function () { hideBars(false); });Remarques : sans effet dans une application compilée avec Plein écran (ou Mode kiosque immersif) activé à l'étape 3 (Intégrer) : le créateur a verrouillé ce choix. Il ne masque que les barres Android ; la barre supérieure propre de l'application (celle avec le bouton du menu latéral) relève de l'interrupteur Afficher la barre supérieure. Lorsqu'il est activé, la coque ajoute viewport-fit=cover à votre balise meta viewport afin que la page occupe tout l'écran. Voir toggleFullscreen et isFullscreen. Les applications créées par IA peuvent utiliser fullscreen de @/lib/appmintNative.
setSecureScreen pont#
window.WebToApk.setSecureScreen(enabled: Boolean): Boolean
Définit la protection pour la page ACTUELLE et renvoie l'état désormais en vigueur. L'indicateur de fenêtre lui-même est appliqué sur le thread d'interface, mais l'état renvoyé est déjà validé : une page peut donc appeler ceci et révéler aussitôt son contenu sensible sans attendre de rappel.
Exemple
Bloque les captures d'écran, l'enregistrement d'écran, la diffusion et l'aperçu de l'écran des applications récentes tant que la page ACTUELLE affiche quelque chose de privé.
Renvoie : un booléen immédiatement : l'état désormais en vigueur (la valeur que vous avez passée). Vous pouvez révéler le contenu privé juste après l'appel. Nécessite : rien.
function showStatement() {
if (window.WebToApk && typeof window.WebToApk.setSecureScreen === 'function') {
window.WebToApk.setSecureScreen(true);
}
render(statementView);
}Ne le libérez vous-même que lorsque vous masquez le contenu privé SANS naviguer (une fenêtre modale se ferme, un onglet change dans une même page) :
function closeCardDetails() {
hide(cardDetailsModal);
if (window.WebToApk && typeof window.WebToApk.setSecureScreen === 'function') {
window.WebToApk.setSecureScreen(false);
}
}N'affichez un code de récupération à usage unique qu'une fois la capture bloquée, puisque l'appel répond avec l'état en vigueur :
function revealRecoveryCode(code) {
var W = window.WebToApk;
if (!(W && typeof W.setSecureScreen === 'function')) {
alert('Open the app to see your recovery code.');
return;
}
if (W.setSecureScreen(true)) {
document.getElementById('recovery-code').textContent = code;
}
}Remarques : la protection appartient à la page qui l'a demandée. Elle est levée dès que l'application navigue ailleurs : nouvelle page, route pushState ou route #hash : il n'y a donc rien à nettoyer à la sortie, et après un rechargement la page doit la redemander. Ne la réappliquez pas à intervalle régulier : l'indicateur doit déjà être actif quand l'utilisateur appuie sur les boutons de capture d'écran. Rien ne peut empêcher un appareil photo pointé sur l'écran.
setStatusBarColor pont#
window.WebToApk.setStatusBarColor(color: String, style: String): Boolean
Peint les barres d'état et de navigation de la couleur [color] et choisit la teinte des icônes : [style] 'light' signifie des icônes claires sur une barre sombre, 'dark' l'inverse, '' laisse la luminance décider. [color] est `#RGB`, `#RGBA`, `#RRGGBB`, `#AARRGGBB` (alpha EN PREMIER ; l'ordre CSS `#RRGGBBAA` est aussi lu avec l'alpha en premier) ou un nom de couleur de base ('black', 'navy'…) ; `rgb()`/`hsl()` ne sont pas lus. Renvoie false lorsque la couleur n'est pas analysable.
Exemple
Peint la barre d'état d'Android d'une couleur et choisit des icônes claires ou sombres dessus.
Renvoie : true, ou false lorsque la couleur ne peut pas être analysée (de façon synchrone). Nécessite : rien.
style vaut 'light' (icônes claires, pour une barre sombre), 'dark' (icônes sombres, pour une barre claire) ou '' (la coque choisit selon la luminosité de la couleur) :
function paintBar(color, style) {
if (window.WebToApk && typeof window.WebToApk.setStatusBarColor === 'function') {
return window.WebToApk.setStatusBarColor(color, style);
}
return false; // in a browser
}
paintBar('#0B0F1A', 'light'); // dark bar, light icons
paintBar('#FFFFFF', 'dark'); // white bar, dark icons
paintBar('#0E7C86', ''); // icons chosen automaticallyAdaptez la barre à chaque écran :
function showScreen(name) {
var colors = { home: '#0B0F1A', settings: '#FFFFFF' };
paintBar(colors[name] || '#0B0F1A', name === 'settings' ? 'dark' : 'light');
}Suivez le thème clair ou sombre du téléphone, y compris un interrupteur pendant que l'application est ouverte :
var darkTheme = window.matchMedia('(prefers-color-scheme: dark)');
function matchTheme() {
if (!(window.WebToApk && typeof window.WebToApk.setStatusBarColor === 'function')) return;
if (darkTheme.matches) {
window.WebToApk.setStatusBarColor('#121212', 'light');
} else {
window.WebToApk.setStatusBarColor('#F5F5F5', 'dark');
}
}
matchTheme();
darkTheme.addEventListener('change', matchTheme);Remarques : les couleurs sont des chaînes de couleur Android : #RRGGBB ou #AARRGGBB (et des noms comme red). Les formes CSS telles que rgb(...) ou #RGB renvoient false. Cela fonctionne aussi sous Android 15+, où le plugin StatusBar de Capacitor ne peut pas colorer la barre. Tant que les barres sont masquées (plein écran), la couleur est conservée pour leur retour. Les applications créées par IA peuvent utiliser setStatusBar de @/lib/appmintNative.
splashHold pont#
window.WebToApk.splashHold()
Maintient l'écran de démarrage de marque jusqu'à l'appel de [splashReady]. Par défaut, l'écran de démarrage se masque dès que le corps de la page a des enfants mis en page, ce qui, pour une application qui affiche un squelette puis charge son premier écran, donne « écran de démarrage, puis un squelette ». Une application qui préfère révéler un premier écran terminé l'appelle à l'import, puis [splashReady] une fois cet écran affiché. Plafonné au même filet de sécurité de 6 s que la vérification d'affichage : une page qui ne signale jamais être prête s'ouvre donc quand même.
Exemple
Maintient l'écran de démarrage de l'application à l'écran jusqu'à ce que vous appeliez splashReady() : l'utilisateur voit ainsi votre premier écran terminé, et non « écran de démarrage, puis un squelette de chargement ».
Retourne : rien. Nécessite : rien.
Appelez-le le plus tôt possible (en haut de votre premier script), puis appelez splashReady() une fois le premier écran dessiné :
if (window.WebToApk && typeof window.WebToApk.splashHold === 'function') {
window.WebToApk.splashHold();
}
loadFirstScreen() // your own async start-up (fetch data, render)
.catch(function (err) { showError(err); })
.then(function () {
if (window.WebToApk && window.WebToApk.splashReady) window.WebToApk.splashReady();
});Retenez l'écran de démarrage jusqu'à ce que l'image principale du premier écran soit chargée, afin que l'application s'ouvre sur une image terminée :
if (window.WebToApk && typeof window.WebToApk.splashHold === 'function') {
window.WebToApk.splashHold();
}
function releaseSplash() {
if (window.WebToApk && window.WebToApk.splashReady) window.WebToApk.splashReady();
}
var hero = document.getElementById('hero');
if (hero.complete) {
releaseSplash();
} else {
hero.addEventListener('load', releaseSplash);
hero.addEventListener('error', releaseSplash); // a broken image must not keep the splash up
}Ne retenez l'écran de démarrage que lorsque le premier écran a besoin de données, et laissez s'ouvrir normalement un écran qui s'affiche tout de suite :
var signedIn = !!localStorage.getItem('session');
if (signedIn && window.WebToApk && typeof window.WebToApk.splashHold === 'function') {
window.WebToApk.splashHold(); // the dashboard needs its data before it looks right
}
if (signedIn) {
loadDashboard().finally(function () {
if (window.WebToApk && window.WebToApk.splashReady) window.WebToApk.splashReady();
});
} else {
showLoginScreen(); // paints at once; the splash hides by itself
}Remarques : sans splashHold(), l'écran de démarrage se masque dès que le corps de la page a des enfants visibles. Un écran de démarrage retenu se masque tout de même de lui-même au bout de quelques secondes (le même filet de sécurité que la vérification d'affichage normale) : une page qui n'appelle jamais splashReady() s'ouvre donc quand même. Appelez toujours splashReady() aussi dans le chemin d'erreur. La durée minimale d'écran de démarrage choisie par le créateur s'applique toujours. Les applications créées par IA peuvent utiliser splash de @/lib/appmintNative.
splashReady pont#
window.WebToApk.splashReady()
Le premier écran est affiché : masquez l'écran de démarrage maintenant (sous réserve de la durée minimale d'écran de démarrage du créateur). Idempotent ; sans effet lorsque rien n'était retenu.
Exemple
Indique à la coque que votre premier écran est affiché, afin que l'écran de démarrage se masque maintenant.
Renvoie : rien. Nécessite : rien. Peut être appelé plusieurs fois sans danger, et sans effet lorsque rien n'était retenu.
Il s'associe à splashHold():
if (window.WebToApk && window.WebToApk.splashHold) window.WebToApk.splashHold();
async function start() {
try {
var res = await fetch('/api/today');
renderToday(await res.json());
} catch (e) {
renderOfflineMessage();
} finally {
if (window.WebToApk && typeof window.WebToApk.splashReady === 'function') {
window.WebToApk.splashReady(); // hide the splash in every case
}
}
}
start();Ne révélez l'écran qu'une fois que le navigateur a affiché ce que vous venez de générer (deux images d'animation) :
renderApp(document.getElementById('root'));
requestAnimationFrame(function () {
requestAnimationFrame(function () {
if (window.WebToApk && typeof window.WebToApk.splashReady === 'function') {
window.WebToApk.splashReady();
}
});
});Attendez plusieurs tâches de démarrage, et masquez l'écran de démarrage même si l'une d'elles échoue :
if (window.WebToApk && window.WebToApk.splashHold) window.WebToApk.splashHold();
Promise.allSettled([
loadProfile(), // your own start-up requests
loadFeed(),
document.fonts.ready // no flash of the wrong font
]).then(function (results) {
results.forEach(function (r) { if (r.status === 'rejected') console.warn(r.reason); });
if (window.WebToApk && typeof window.WebToApk.splashReady === 'function') {
window.WebToApk.splashReady();
}
});Remarques : la durée minimale d'écran de démarrage choisie par le créateur est toujours respectée. Si vous n'appelez jamais splashHold(), l'écran de démarrage se masque de lui-même lorsque la page s'affiche, et splashReady() ne fait rien de plus.
toggleFullscreen pont#
window.WebToApk.toggleFullscreen()
Permet à la page de masquer elle-même la barre d'état (heure/batterie) et la barre de navigation, par ex. un jeu qui passe à son écran de jeu : WebToApk.setFullscreen(true) // masquer les barres système WebToApk.setFullscreen(false) // les ramener WebToApk.toggleFullscreen() WebToApk.isFullscreen() Le choix est conservé d'un lancement à l'autre. Sans effet dans les applications que le créateur a déjà verrouillées en plein écran/kiosque : il n'y a rien à restaurer. L'élément de menu latéral « Plein écran » est l'équivalent pour les utilisateurs finaux et dépend de l'option enableFullscreenToggle du créateur ; ce pont est toujours disponible pour la page propre de l'application.
Décrit par son groupe, Pont plein écran, plutôt que seul.
Exemple
Bascule les barres d'état et de navigation d'Android entre masquées et affichées.
Renvoie : rien. Nécessite : rien. Le nouvel état est conservé d'un lancement à l'autre.
Un bouton « plein écran » qui met aussi à jour son propre libellé :
var btn = document.getElementById('fs-btn');
if (window.WebToApk && typeof window.WebToApk.toggleFullscreen === 'function') {
btn.onclick = function () {
window.WebToApk.toggleFullscreen();
// The change is applied on the UI thread; read the state a moment later.
setTimeout(function () {
btn.textContent = window.WebToApk.isFullscreen() ? 'Exit fullscreen' : 'Fullscreen';
}, 100);
};
} else {
btn.hidden = true; // in a browser
}Touchez deux fois une photo ou une vue de lecture pour masquer ou afficher les barres :
var viewer = document.getElementById('photo-viewer');
viewer.addEventListener('dblclick', function () {
if (window.WebToApk && typeof window.WebToApk.toggleFullscreen === 'function') {
window.WebToApk.toggleFullscreen();
}
});Basculez avec la touche F d'un clavier physique, mais pas pendant que l'utilisateur saisit du texte dans un champ :
document.addEventListener('keydown', function (e) {
if (e.key !== 'f' || e.target.closest('input, textarea, [contenteditable]')) return;
if (window.WebToApk && typeof window.WebToApk.toggleFullscreen === 'function') {
e.preventDefault();
window.WebToApk.toggleFullscreen();
}
});Remarques : sans effet dans une application compilée avec Plein écran ou Mode kiosque immersif activé (les barres restent masquées). L'élément de menu latéral « Plein écran » pour les utilisateurs finaux est un interrupteur de compilation distinct (Bouton plein écran à l'étape 3, sous Options d'affichage) ; cette méthode du pont fonctionne sans lui.