API del bridge JavaScript
La finestra
Schermo intero, picture-in-picture, i colori delle barre di sistema, il blocco degli screenshot, se la build ha la protezione dalla copia attiva (AppMint.copyProtection), la splash screen e la chiusura di una finestra.
AppMint.copyProtection helper#
AppMint.copyProtection
Esempio
true quando l'app è stata creata con la Protezione dalla copia attivata; assente (undefined) altrimenti. Sola lettura: una pagina non può attivare o disattivare la protezione, può solo chiedere se è attiva.
Restituisce: true, oppure undefined quando la protezione è disattivata (e in un browser). Richiede: Protezione dalla copia attivata nel Passaggio 3 (Integra), sotto Opzioni di visualizzazione, quando crei l'app. Disattivata per impostazione predefinita.
Con la protezione attiva, il testo dell'app non può essere selezionato, copiato o tagliato; copia / taglia, l'evento contextmenu e Ctrl/Cmd + C, X e A vengono annullati fuori dai campi modificabili; e non compare nessun menu al tocco prolungato. Input, textarea, select e le aree contenteditable restano pienamente modificabili, quindi i moduli continuano a funzionare.
Nascondi i tuoi pulsanti "Copia" quando la protezione è attiva: non copierebbero nulla e sembrerebbero rotti:
const protectedApp = !!(window.AppMint && window.AppMint.copyProtection === true);
document.querySelectorAll('[data-copy-button]').forEach((btn) => {
btn.hidden = protectedApp;
});Oppure scegli una volta sola, all'avvio, la formulazione di un suggerimento:
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.';Combinalo con il blocco degli screenshot per una pagina che non deve uscire dall'app:
if (window.AppMint && AppMint.copyProtection === true && window.WebToApk && WebToApk.setSecureScreen) {
WebToApk.setSecureScreen(true); // also blocks screenshots and recents thumbnails
document.body.classList.add('protected');
}Note: il menu al tocco prolungato su link e immagini (apri, copia, condividi o scarica) è un interruttore di build separato, Menu al tocco prolungato su link e immagini, nello stesso punto. È disattivato per impostazione predefinita, quindi un tocco prolungato su un link non fa nulla finché non lo attivi; la protezione dalla copia lo tiene sempre spento. Una pagina può comunque rifiutare il menu su un singolo elemento annullando contextmenu (el.addEventListener('contextmenu', (e) => e.preventDefault())). La protezione impedisce la copia dentro l'app; non impedisce uno screenshot: per quello, vedi WebToApk.setSecureScreen(true).
screen.orientation standard web#
screen.orientation.lock(type) / unlock()
Esempio
Il blocco standard Screen Orientation, che una semplice WebView rifiuta: ruota l'app in orizzontale per un video o un gioco e poi la riporta com'era.
Restituisce: lock(type) → una Promise che si risolve quando l'orientamento è stato richiesto; viene rifiutata con TypeError per un tipo sconosciuto e con NotSupportedError su Android TV. unlock() riporta all'orientamento con cui l'app è stata creata. Richiede: nulla.
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));Ruota un gioco in orizzontale quando parte; su Android TV lo schermo è già orizzontale, quindi prosegui:
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();
}Segui la forma del video in riproduzione, e torna indietro quando finisce:
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());Note: tipi: any, natural, portrait, portrait-primary, portrait-secondary, landscape, landscape-primary, landscape-secondary. A differenza di Chrome, la pagina non deve essere prima a schermo intero. Le app create con l'AI usano lockOrientation() da @/lib/appmintNative.
window.close standard web#
window.close()
Esempio
Chiude la schermata principale dell'app. La shell sostituisce window.close() così un pulsante "Chiudi" o "Esci" nella tua pagina funziona dentro l'app.
Restituisce: niente. Richiede: niente.
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
};Nascondi il pulsante in un browser, dove window.close() di solito non fa nulla su una scheda aperta dall'utente:
if (!window.WebToApk) document.getElementById('exit-btn').hidden = true;Chiedi prima, perché l'app si chiude nel momento in cui window.close() viene eseguito:
document.getElementById('quit').addEventListener('click', function () {
if (hasUnsavedChanges() && !confirm('You have unsaved changes. Close the app anyway?')) {
return;
}
window.close();
});Note: la sostituzione viene installata dopo il caricamento di ogni pagina, quindi una chiamata durante la primissima esecuzione di script della pagina usa il window.close() della WebView stessa (che non fa nulla). Su questo percorso non c'è conferma di uscita. Un popup di accesso che chiama window.close() viene gestito a parte: chiude il popup, non l'app.
__lockOrientation bridge#
window.WebToApk.__lockOrientation(type: String): String
screen.orientation.lock(type): "ok", "type" per una stringa che non è un OrientationLockType, oppure "unsupported" (Android TV è sempre in orizzontale).
Esempio
Trasporto interno dietro screen.orientation.lock(type). Le pagine usano l'API standard; non chiamare mai questo direttamente: i metodi __ possono cambiare senza preavviso.
Restituisce: 'ok', 'type' per una stringa che non è un tipo di blocco dell'orientamento, oppure 'unsupported' (Android TV). Richiede: nulla da attivare.
Usa l'API pubblica:
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());Distingui un tipo di blocco non valido da un dispositivo che non può ruotare:
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));Blocca lo schermo nel modo in cui l'utente lo tiene mentre firma, poi restituisci la rotazione:
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();
}Note: Implementato nella shell dell'app (WebApiPolyfills.kt). Lo stesso codice della pagina funziona senza modifiche in Chrome.
__unlockOrientation bridge#
window.WebToApk.__unlockOrientation()
screen.orientation.unlock(): torna all'orientamento con cui il creatore ha creato l'app.
Esempio
Trasporto interno dietro screen.orientation.unlock(). Le pagine usano l'API standard; non chiamare mai questo direttamente: i metodi __ possono cambiare senza preavviso.
Restituisce: niente; l'app torna all'orientamento scelto in fase di creazione. Richiede: nulla da attivare.
Usa l'API pubblica:
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());Solo il percorso del gioco è orizzontale; ogni altro percorso torna all'orientamento proprio dell'app:
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);Tieni dritte le slide di introduzione, poi sblocca quando sono finite:
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
}Note: Implementato nella shell dell'app (WebApiPolyfills.kt). Lo stesso codice della pagina funziona senza modifiche in Chrome.
__wakeLock bridge#
window.WebToApk.__wakeLock(docId: String, held: Boolean): Boolean
Screen Wake Lock: [held] true mantiene lo schermo acceso finché il documento [docId] detiene un sentinel. Restituisce false quando il blocco non ha potuto essere ottenuto.
Esempio
Trasporto interno dietro a navigator.wakeLock.request('screen') e WakeLockSentinel.release(). Le pagine usano l'API standard; non chiamarlo mai direttamente: i metodi __ possono cambiare senza preavviso.
Restituisce: true quando il flag di schermo acceso è stato applicato per quel documento. Richiede: nulla da attivare.
Usa l'API pubblica:
let lock = null;
async function keepScreenOn() {
if (!('wakeLock' in navigator)) return;
lock = await navigator.wakeLock.request('screen');
lock.addEventListener('release', () => { lock = null; });
}Riprendi il blocco quando l'utente torna nell'app, perché ogni blocco viene rilasciato in background:
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();
});Tieni lo schermo acceso solo mentre un timer di allenamento è in corso, e lascialo spegnere di nuovo quando finisce:
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();
}
}Note: l'app rilascia ogni blocco quando va in background e invia appmint:wakelock-lost, che rilascia i sentinel (scatta il loro evento release).
closeWindow bridge#
window.WebToApk.closeWindow()
Usa il wrapper basato su promise: const r = await AppMint.requestReview(); // {result, openedStore} const r = await AppMint.requestReview({ openStore: true }); // scheda del negozio se non c'è la finestra r.result: 'shown' | 'not_from_play' | 'quota' | 'error'. Vedi RatePrompt.
Descritto dal suo gruppo, Finestra di recensione in-app di Google Play, e non da solo.
Esempio
Chiude la schermata principale dell'app (come premere Indietro sull'ultima pagina). Le pagine di solito chiamano il window.close() standard, che la shell indirizza qui.
Restituisce: niente. Richiede: niente.
document.getElementById('quit').onclick = function () {
if (confirm('Close the app?')) window.close(); // in the app: the screen closes
};La chiamata grezza fa la stessa cosa:
if (window.WebToApk && typeof window.WebToApk.closeWindow === 'function') {
window.WebToApk.closeWindow();
}Un pulsante "Esci" che prima salva, e che è nascosto in un browser dove non c'è nessuna schermata dell'app da chiudere:
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();
};
}Note: chiude subito la schermata dell'app, senza conferma di uscita, anche se la build ne ha una. Salva prima tutto ciò che non è stato salvato. In un browser window.close() chiude solo una scheda aperta dallo script stesso.
enterPip bridge#
window.WebToApk.enterPip(): Boolean
Riduce subito l'intera app in una finestra mobile picture-in-picture: un video o una chiamata che l'utente vuole continuare a guardare mentre esce. Android 8+ e solo se la build ha attivato il PiP (il flag del manifest che serve); restituisce se la finestra si è aperta. Uscire dall'app con il PiP attivo lo fa già da solo; questo è il pulsante esplicito "riduci a icona".
Esempio
Riduce subito l'intera app in una piccola finestra mobile picture-in-picture: un pulsante "riduci a icona" per un video o una chiamata.
Restituisce: true se la finestra mobile si è aperta, false altrimenti (in modo sincrono). Richiede: Picture-in-Picture (PiP) attivato nel Passaggio 3 (Integra), sotto Opzioni di visualizzazione, quando crei l'app. 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
};Adatta la pagina alla piccola finestra: la finestra diventa molto stretta, quindi un listener resize può nascondere tutto tranne il video.
window.addEventListener('resize', function () {
var small = window.innerWidth < 300;
document.querySelector('nav').style.display = small ? 'none' : '';
});Segui l'apertura e la chiusura della finestra mobile con l'evento appmint:pip (detail.inPip), ad esempio per nascondere i controlli di una chiamata:
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();
}
};Note: con il PiP attivo, premere Home entra già da solo nella finestra mobile; questo metodo serve solo per un pulsante esplicito. Restituisce false in una build senza l'interruttore PiP, perché manca il flag del manifest che serve. La dimensione della finestra PiP è scelta da Android. Le app create con l'AI possono usare pip da @/lib/appmintNative.
isFullscreen bridge#
window.WebToApk.isFullscreen(): Boolean
Permette alla pagina di nascondere da sola la barra di stato (orologio/batteria) e la barra di navigazione, ad es. un gioco che entra nella sua schermata di gioco: WebToApk.setFullscreen(true) // nascondi le barre di sistema WebToApk.setFullscreen(false) // riportale WebToApk.toggleFullscreen() WebToApk.isFullscreen() La scelta viene ricordata tra un avvio e l'altro. Non fa nulla nelle app che il creatore ha già bloccato a schermo intero/kiosk: lì non c'è nulla da ripristinare. La voce "Schermo intero" del menu laterale è l'equivalente per gli utenti finali ed è controllata dall'opzione enableFullscreenToggle del creatore; questo bridge è sempre disponibile per la pagina dell'app stessa.
Descritto dal suo gruppo, Bridge schermo intero, e non da solo.
Esempio
Ti dice se la barra di stato e la barra di navigazione di Android sono nascoste in questo momento.
Restituisce: true / false, in modo sincrono. Richiede: nulla.
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';
}Imposta il layout della pagina in base alla scelta ricordata all'avvio, perché sopravvive ai riavvii:
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); }
});Inserisci un pulsante "mostra barre" quando l'app è stata creata a schermo intero e le barre non possono tornare:
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);
}Note: restituisce true quando il creatore ha creato l'app con Schermo intero o Modalità Kiosk immersiva, OPPURE quando la pagina ha chiamato setFullscreen(true) / toggleFullscreen(). Nel primo caso setFullscreen(false) non può riportare le barre.
isSecureScreen bridge#
window.WebToApk.isSecureScreen(): Boolean
WebToApk.setSecureScreen(true) // blocca gli screenshot su QUESTA pagina WebToApk.setSecureScreen(false) // rilascialo in anticipo WebToApk.isSecureScreen() // -> boolean La protezione appartiene alla pagina che l'ha richiesta. Viene rilasciata nel momento in cui l'app passa a qualsiasi altro posto - un nuovo documento, un percorso pushState, un percorso #hash - così una schermata protetta non può lasciare il resto dell'app bloccato, e una pagina che vuole di nuovo la protezione dopo un ricaricamento la richiede semplicemente un'altra volta. Cosa fa: screenshot, registrazione dello schermo, trasmissione (cast) e miniatura nella schermata delle app recenti si fermano finché è attiva. Cosa non può fare: fermare una fotocamera puntata sullo schermo. Su Android niente può, e nessun bridge qui finge il contrario.
Descritto dal suo gruppo, Protezione dalla cattura dello schermo, e non da solo.
Esempio
Ti dice se la protezione dagli screenshot (setSecureScreen) è attiva in questo momento.
Restituisce: un booleano, subito. Richiede: nulla.
function updateLockIcon() {
var on = !!window.WebToApk &&
typeof window.WebToApk.isSecureScreen === 'function' &&
window.WebToApk.isSecureScreen();
document.getElementById('shield').hidden = !on;
}Controlla prima di mostrare il numero di una carta, e attiva prima la protezione se questa pagina non l'ha ancora richiesta:
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 interruttore "Nascondi dagli screenshot" che parte dallo stato reale e lo inverte:
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());
});
}Note: torna da solo a false quando l'app passa a un'altra pagina o a un altro percorso, perché la protezione appartiene alla pagina che l'ha richiesta.
setFullscreen bridge#
window.WebToApk.setFullscreen(enabled: Boolean)
Permette alla pagina di nascondere da sola la barra di stato (orologio/batteria) e la barra di navigazione, ad es. un gioco che entra nella sua schermata di gioco: WebToApk.setFullscreen(true) // nascondi le barre di sistema WebToApk.setFullscreen(false) // riportale WebToApk.toggleFullscreen() WebToApk.isFullscreen() La scelta viene ricordata tra un avvio e l'altro. Non fa nulla nelle app che il creatore ha già bloccato a schermo intero/kiosk: lì non c'è nulla da ripristinare. La voce "Schermo intero" del menu laterale è l'equivalente per gli utenti finali ed è controllata dall'opzione enableFullscreenToggle del creatore; questo bridge è sempre disponibile per la pagina dell'app stessa.
Descritto dal suo gruppo, Bridge schermo intero, e non da solo.
Esempio
Nasconde (true) o mostra (false) la barra di stato e la barra di navigazione di Android, ad esempio quando un gioco entra nella sua schermata di gioco.
Restituisce: niente. Richiede: nulla: è sempre disponibile per la tua pagina. La scelta viene ricordata tra un avvio e l'altro.
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
}
}Tieni i tuoi contenuti lontano dal foro della fotocamera quando le barre sono nascoste:
document.body.style.paddingTop = 'env(safe-area-inset-top)';
document.body.style.paddingBottom = 'env(safe-area-inset-bottom)';Nascondi le barre mentre un video è in riproduzione e riportale quando va in pausa o finisce:
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); });Note: non fa nulla in un'app creata con Schermo intero (o Modalità Kiosk immersiva) attivato nel Passaggio 3 (Integra): il creatore ha bloccato quella scelta. Nasconde solo le barre di Android; la barra superiore dell'app (quella con il pulsante del menu laterale) è l'interruttore Mostra barra superiore. Quando è attivato, la shell aggiunge viewport-fit=cover al meta viewport così la pagina si estende a tutto lo schermo. Vedi toggleFullscreen e isFullscreen. Le app create con l'AI possono usare fullscreen da @/lib/appmintNative.
setSecureScreen bridge#
window.WebToApk.setSecureScreen(enabled: Boolean): Boolean
Imposta la protezione per la pagina ATTUALE e restituisce lo stato ora in vigore. Il flag della finestra viene applicato sul thread dell'interfaccia, ma lo stato restituito è già confermato, quindi una pagina può chiamarlo e mostrare subito il proprio contenuto sensibile senza aspettare una callback.
Esempio
Blocca screenshot, registrazione dello schermo, trasmissione (cast) e anteprima nella schermata delle app recenti mentre la pagina ATTUALE mostra qualcosa di privato.
Restituisce: un booleano subito: lo stato ora in vigore (il valore che hai passato). Puoi mostrare il contenuto privato subito dopo la chiamata. Richiede: nulla.
function showStatement() {
if (window.WebToApk && typeof window.WebToApk.setSecureScreen === 'function') {
window.WebToApk.setSecureScreen(true);
}
render(statementView);
}Rilascialo tu solo quando nascondi il contenuto privato SENZA cambiare pagina (si chiude un modale, cambia una scheda dentro una stessa pagina):
function closeCardDetails() {
hide(cardDetailsModal);
if (window.WebToApk && typeof window.WebToApk.setSecureScreen === 'function') {
window.WebToApk.setSecureScreen(false);
}
}Mostra un codice di recupero monouso solo dopo che la cattura è bloccata, poiché la chiamata risponde con lo stato in vigore:
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;
}
}Note: la protezione appartiene alla pagina che l'ha richiesta. Viene rilasciata appena l'app passa a qualsiasi altro posto - una nuova pagina, un percorso pushState o un percorso #hash - quindi non c'è nulla da ripulire all'uscita, e dopo un ricaricamento la pagina deve richiederla di nuovo. Non riapplicarla con un timer: il flag deve essere già attivo quando l'utente preme i tasti dello screenshot. Niente può fermare una fotocamera puntata sullo schermo.
setStatusBarColor bridge#
window.WebToApk.setStatusBarColor(color: String, style: String): Boolean
Colora la barra di stato e la barra di navigazione con [color] e sceglie la tinta delle icone: [style] 'light' significa icone chiare su una barra scura, 'dark' il contrario, '' lascia decidere alla luminosità. [color] è `#RGB`, `#RGBA`, `#RRGGBB`, `#AARRGGBB` (alpha PER PRIMO: anche l'ordine CSS `#RRGGBBAA` viene letto con alpha per primo) o un nome di colore di base ('black', 'navy'…); `rgb()`/`hsl()` non vengono letti. Restituisce false quando il colore non viene interpretato.
Esempio
Colora la barra di stato di Android e sceglie icone chiare o scure su di essa.
Restituisce: true, oppure false quando il colore non può essere interpretato (in modo sincrono). Richiede: nulla.
style è 'light' (icone chiare, per una barra scura), 'dark' (icone scure, per una barra chiara), oppure '' (la shell sceglie in base alla luminosità del colore):
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 automaticallyAbbina la barra a ogni schermata:
function showScreen(name) {
var colors = { home: '#0B0F1A', settings: '#FFFFFF' };
paintBar(colors[name] || '#0B0F1A', name === 'settings' ? 'dark' : 'light');
}Segui il tema chiaro o scuro del telefono, incluso un interruttore mentre l'app è aperta:
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);Note: i colori sono stringhe di colore Android: #RRGGBB o #AARRGGBB (e nomi come red). Forme CSS come rgb(...) o #RGB restituiscono false. Funziona anche su Android 15+, dove il plugin StatusBar di Capacitor non può colorare la barra. Mentre le barre sono nascoste (schermo intero) il colore viene conservato per quando tornano. Le app create con l'AI possono usare setStatusBar da @/lib/appmintNative.
splashHold bridge#
window.WebToApk.splashHold()
Mantiene la splash di avvio con il marchio finché non viene chiamato [splashReady]. Per impostazione predefinita la splash si nasconde appena il corpo ha elementi già disposti, il che per un'app che disegna uno scheletro e poi carica la prima schermata significa "splash, poi uno scheletro". Un'app che preferisce mostrare una prima schermata già pronta chiama questo all'importazione e [splashReady] quando quella schermata è a posto. Limitato alla stessa rete di sicurezza di 6 s del controllo del disegno, quindi una pagina che non segnala mai di essere pronta si apre comunque.
Esempio
Mantiene a schermo la splash di avvio dell'app finché non chiami splashReady(), così l'utente vede la tua prima schermata già pronta, non "splash, poi uno scheletro di caricamento".
Restituisce: niente. Richiede: niente.
Chiamalo il prima possibile (all'inizio del tuo primo script), poi chiama splashReady() quando la prima schermata è disegnata:
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();
});Trattieni la splash finché l'immagine principale della prima schermata non è caricata, così l'app si apre su un'immagine completa:
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
}Trattieni solo quando la prima schermata ha bisogno di dati, e lascia che una schermata che si disegna subito si apra normalmente:
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
}Note: senza splashHold() la splash si nasconde appena il corpo della pagina ha elementi visibili. Una splash trattenuta si nasconde comunque da sola dopo qualche secondo (la stessa rete di sicurezza del normale controllo del disegno), quindi una pagina che non chiama mai splashReady() si apre comunque. Chiama splashReady() anche nel percorso di errore. Il tempo minimo di splash scelto dal creatore vale ancora. Le app create con l'AI possono usare splash da @/lib/appmintNative.
splashReady bridge#
window.WebToApk.splashReady()
La prima schermata è pronta: nascondi ora la splash di avvio (nel rispetto della durata minima della splash scelta dal creatore). Idempotente; innocuo quando non era stato trattenuto nulla.
Esempio
Dice alla shell che la tua prima schermata è pronta, così la splash di avvio si nasconde adesso.
Restituisce: niente. Richiede: nulla. Si può chiamare più volte senza problemi, ed è innocuo quando non era stato tenuto alcun blocco.
Si abbina con 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();Mostra lo schermo solo dopo che il browser ha disegnato ciò che hai appena generato (due frame di animazione):
renderApp(document.getElementById('root'));
requestAnimationFrame(function () {
requestAnimationFrame(function () {
if (window.WebToApk && typeof window.WebToApk.splashReady === 'function') {
window.WebToApk.splashReady();
}
});
});Attendi più operazioni di avvio, e nascondi la splash anche quando una di esse fallisce:
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();
}
});Note: la durata minima della splash scelta dal creatore viene comunque rispettata. Se non chiami mai splashHold(), la splash si nasconde da sola quando la pagina viene disegnata, e splashReady() non fa nulla di più.
toggleFullscreen bridge#
window.WebToApk.toggleFullscreen()
Permette alla pagina di nascondere da sola la barra di stato (orologio/batteria) e la barra di navigazione, ad es. un gioco che entra nella sua schermata di gioco: WebToApk.setFullscreen(true) // nascondi le barre di sistema WebToApk.setFullscreen(false) // riportale WebToApk.toggleFullscreen() WebToApk.isFullscreen() La scelta viene ricordata tra un avvio e l'altro. Non fa nulla nelle app che il creatore ha già bloccato a schermo intero/kiosk: lì non c'è nulla da ripristinare. La voce "Schermo intero" del menu laterale è l'equivalente per gli utenti finali ed è controllata dall'opzione enableFullscreenToggle del creatore; questo bridge è sempre disponibile per la pagina dell'app stessa.
Descritto dal suo gruppo, Bridge schermo intero, e non da solo.
Esempio
Alterna la barra di stato e la barra di navigazione di Android tra nascoste e visibili.
Restituisce: niente. Richiede: nulla. Il nuovo stato viene ricordato tra un avvio e l'altro.
Un pulsante "schermo intero" che aggiorna anche la propria etichetta:
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
}Tocca due volte una foto o una vista di lettura per nascondere o mostrare le barre:
var viewer = document.getElementById('photo-viewer');
viewer.addEventListener('dblclick', function () {
if (window.WebToApk && typeof window.WebToApk.toggleFullscreen === 'function') {
window.WebToApk.toggleFullscreen();
}
});Alterna con il tasto F su una tastiera fisica, ma non mentre l'utente scrive in un campo:
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();
}
});Note: non fa nulla in un'app creata con Schermo intero o Modalità Kiosk immersiva attivato (le barre restano nascoste). La voce "Schermo intero" del menu laterale per gli utenti finali è un interruttore di build separato (Pulsante schermo intero nel Passaggio 3, sotto Opzioni di visualizzazione); questo metodo del bridge funziona anche senza.