Crea APK gratis

API del bridge JavaScript

Widget della schermata Home

Una piccola scheda Android nella schermata Home che la tua pagina riempie con un titolo, un valore e qualche riga - AppMint.widget.

AppMint.widget helper#

AppMint.widget.set(card) / update(partial) / clear() / placedCount() / requestPin()

Esempio

Riempie il widget della schermata Home della tua app: una scheda nativa con un titolo, un grande valore, una didascalia, fino a dodici righe (ciascuna con il proprio colore, indicatore e percorso di tocco, se vuoi), i tuoi colori e un percorso che si apre al tocco. Quando l'utente ingrandisce il widget, mostra più righe e con textSize: 'auto' il testo cresce per riempirlo, finché ogni riga ci sta ancora, con una riga lunga che occupa due righe invece di essere tagliata. Un widget non può mostrare HTML: gli invii il testo.

Restituisce: ogni metodo restituisce una Promise. set(card) → {ok: true, placed} (placed = quante copie ci sono nella schermata Home) oppure {ok: false, error}. clear() → undefined. placedCount() → un numero. requestPin() → true se la schermata «Aggiungi» del launcher si è aperta. Richiede: niente: ogni build ha il widget.

Imposta la scheda: una volta all'avvio e di nuovo ogni volta che cambiano i dati che mostra:

async function updateWidget(events) {
  if (!(window.AppMint && AppMint.widget)) return;          // in a browser
  var r = await AppMint.widget.set({
    title: 'Today',
    value: events.length + ' events',
    lines: events.slice(0, 6).map(function (ev) { return ev.time + ' ' + ev.name; }),
    route: '/calendar',      // a tap opens the app at this route
    bg: '#0E7C86',           // background
    ink: '#FFFFFF',          // title and lines
    accent: '#FFE08A'        // the big value
  });
  if (!r.ok) console.log('Widget not updated: ' + r.error);
}

Un'agenda che riempie il widget: sfondo trasparente, testo che cresce quando il widget viene ridimensionato, righe colorate con indicatore, una riga in ritardo in rosso e un tocco su una riga che apre quel giorno:

AppMint.widget.set({
  title: 'Agenda',
  value: 'Sun 18 Oct',
  caption: '5 events, 1 overdue',          // small text under the value
  bg: 'rgba(20, 38, 74, 0.6)',             // 60 % opaque — the wallpaper shows through
  ink: '#FFFFFF', accent: '#FFE08A',
  textSize: 'auto',                        // 'auto' | 'small' | 'normal' | 'large' | 'xl' | a number 0.6–3
  align: 'start',                          // 'start' (left) | 'center' | 'end'
  lines: [
    { text: '09:00 Stand-up', marker: '#29B6F6', route: '/#/day/2026-10-18' },
    { text: '10:30 Dentist, Dr Rao', marker: '#43A047', route: '/#/day/2026-10-18' },
    { text: 'Overdue: renew the car insurance', color: '#FF5252', marker: '#FF5252', bold: true, route: '/#/tasks/overdue' },
    { text: 'Tue 20: Team lunch', route: '/#/day/2026-10-20' },
    'Wed 21: Gym'                           // a plain string is still a line
  ],
  route: '/#/today'                         // a tap anywhere else on the card
});

Una riga è una stringa o { text, color?, marker?, bold?, wrap?, route? }; marker mette un ● colorato davanti al testo, wrap: true su una riga (o sulla scheda) permette a una riga lunga di occupare due righe a qualsiasi dimensione del testo; con textSize: 'auto' le righe lo fanno già, e wrap: false mantiene una riga su un'unica riga. Le prime sei righe si vedono sempre; le righe da sette a dodici compaiono quando il widget è abbastanza alto.

Widget più ricchi: un elenco, un grande numero con barra di avanzamento, un'immagine di sfondo e pulsanti. Una scheda viene disegnata così solo quando ha una di queste chiavi; una scheda senza di esse appare esattamente come prima:

AppMint.widget.set({
  layout: 'list',                 // 'list' | 'progress' | 'card'
  title: 'Today', subtitle: 'Tue 30 Sep',
  items: [                         // up to 5 rows; a row tap opens its own route
    { text: '09:00 Dentist', secondary: 'Dr Rao, 2nd floor', image: 'img/tooth.png', route: '/event/41' },
    { text: '13:30 Lunch with Sam', image: 'https://example.com/sam.jpg', route: '/event/42' }
  ],
  buttons: [{ label: 'Add', route: '/new' }, { label: 'Week', route: '/week' }],   // up to 2
  bgImage: 'img/widget-bg.jpg', bg: '#101820', ink: '#FFFFFF', accent: '#FFB000'
});

AppMint.widget.set({
  layout: 'progress', title: 'Steps', value: '8 214',
  progress: { value: 8214, max: 10000, label: '82% of today's goal' }
});

AppMint.widget.update({ value: '8 950', progress: { value: 8950, max: 10000 } });   // change only these keys

Il tuo font: metti il file del font nella tua app (.ttf o .otf, ad esempio da «Download family» di Google Fonts) e indica il suo percorso, come faresti con un <img>; ogni testo della scheda viene disegnato con quel font:

AppMint.widget.set({
  title: 'Score', value: '1 250',
  font: 'fonts/RocknRollOne-Regular.ttf',   // a file in your app, an https address, or a data: URL
  lines: ['Level 7', { text: 'New record!', bold: true }]
}).then(function (r) { if (!r.ok) console.log(r.error); });   // e.g. "font file not found in the app: …"

Un NOME di font come 'RocknRoll One' non può funzionare: la schermata Home disegna i widget e ha solo i font del telefono stesso; set() risponde {ok: false, error} dicendolo. Queste famiglie integrate non richiedono alcun file: 'serif', 'monospace', 'sans-serif-condensed', 'sans-serif-light', 'sans-serif-medium', 'sans-serif-black', 'casual', 'cursive', 'sans-serif-smallcaps'. I file WOFF / WOFF2 vengono rifiutati (Android non può leggerli): usa il .ttf. Con un file di font la scheda viene disegnata come immagine alla dimensione del widget e ridisegnata quando viene ridimensionata; i tocchi su righe, voci e pulsanti e gli screen reader funzionano come su qualsiasi scheda.

Aggiornamento con l'app chiusa: indica un indirizzo https che restituisce lo stesso JSON; Android lo scarica ogni refreshMinutes (30 o più, predefinito 60) mentre un widget è nella schermata Home, anche dopo un riavvio:

AppMint.widget.set({
  title: 'Orders', value: '…',
  refreshUrl: 'https://api.example.com/widget.json?user=42',
  refreshMinutes: 30
}).then(function (r) { console.log('refreshing every ' + r.refreshMinutes + ' min'); });
// widget.json answers e.g. {"title":"Orders","value":"12 new","layout":"list","items":[{"text":"#1042 paid"}]}

Immagini: un percorso nella tua app (risolto come un <img src> nella pagina), un indirizzo https o un URL data:image/…; vengono ridimensionate e conservate sul telefono. Nel JSON di aggiornamento un percorso relativo indica un file dell'app. refreshUrl: '' ferma l'aggiornamento; anche clear() lo ferma. Android decide il momento esatto di ogni aggiornamento (raggruppa il lavoro in background per risparmiare batteria).

Un pulsante «Aggiungi alla schermata Home»:

async function addWidget() {
  if (!(window.AppMint && AppMint.widget)) return;
  if ((await AppMint.widget.placedCount()) > 0) { alert('The widget is already on your home screen'); return; }
  var opened = await AppMint.widget.requestPin();
  if (!opened) alert('Touch and hold your home screen, tap Widgets, and pick this app.');
}

Svuotalo (ad esempio dopo che l'utente si è disconnesso):

if (window.AppMint && AppMint.widget) AppMint.widget.clear();   // shows "Nothing to show yet"

Un tocco sul widget apre l'app con appmint-shortcut://<package><route> come link di avvio: leggilo con WebToApk.getLaunchUrl() all'avvio e con l'evento appmint:deep-link mentre l'app è in esecuzione:

window.addEventListener('appmint:deep-link', function (e) {
  var m = /^appmint-shortcut:\/\/[^\/?#]*([^#]*)/i.exec(e.detail.url);
  if (m) goTo(m[1] || '/');
});

Colori: #RRGGBB, #RGB, rgb(20, 38, 74), rgba(20, 38, 74, 0.6) (anche rgb(20 38 74 / 60%)), transparent e nomi semplici come red. L'esadecimale a otto cifre segue l'ordine di Android, con alpha PER PRIMO: #AARRGGBB. #9914264A è opaco al 60 %; il #14264A99 del CSS qui viene letto come alpha 14 (8 %), una scheda quasi invisibile. Per gli sfondi trasparenti rgba() evita la confusione. I colori delle righe (color, marker) accettano le stesse forme; un colore di riga non valido viene rifiutato con {ok: false, error: 'lines[2].color is not a colour'}, un colore di scheda non valido usa quello predefinito.

Note: Tutti i campi della scheda sono facoltativi: un title vuoto mostra il nome dell'app; value, caption o righe vuote vengono nascosti; le righe dopo la dodicesima vengono scartate. textSize e align si applicano a ogni testo della scheda; un valore sconosciuto viene rifiutato con {ok: false, error}. Una scheda senza le nuove chiavi (caption, textSize, align, wrap, righe con stile) appare esattamente come prima. Il widget conserva l'ultima scheda, anche dopo un riavvio, e cambia solo quando la tua pagina chiama di nuovo set(). requestPin() richiede Android 8+ e un launcher che lo supporti. Le app create con l'AI possono usare widget da @/lib/appmintNative. Le righe con stile, caption, textSize, align, wrap e rgba() richiedono un'app creata con AppMint 1.11.38 o più recente: ricrea l'app prima di inviare oggetti riga, perché una build più vecchia li mostrerebbe come testo grezzo. font richiede un'app creata con AppMint 1.11.41 o più recente (una build più vecchia lo ignora). App in modalità sito web: un tocco apre il percorso sul tuo sito: /#/today carica https://<your site>/#/today e getLaunchUrl() restituisce comunque il link appmint-shortcut://.

widgetClear bridge#

window.WebToApk.widgetClear()

Rimuove la scheda; i widget aggiunti tornano allo stato vuoto.

Esempio

Meccanismo interno dietro AppMint.widget.clear(): rimuove la scheda del widget; ogni widget aggiunto torna a «Niente da mostrare per ora».

Restituisce: niente. Richiede: niente.

Prima l'API pubblica:

async function onSignOut() {
  if (window.AppMint && AppMint.widget) await AppMint.widget.clear();
}

La chiamata grezza:

if (window.WebToApk && typeof window.WebToApk.widgetClear === 'function') {
  window.WebToApk.widgetClear();
}

Collega il widget a un interruttore «Mostra nella schermata Home» nelle tue impostazioni: spento lo svuota, acceso lo riempie di nuovo:

document.getElementById('widget-toggle').onchange = async function (e) {
  if (!(window.AppMint && AppMint.widget)) return;
  if (e.target.checked) {
    await AppMint.widget.set(buildWidgetCard()); // your own card builder
  } else {
    await AppMint.widget.clear();
  }
};

Dopo aver eliminato l'account, svuota il widget e avvisa l'utente se una copia è ancora nella sua schermata Home:

function afterAccountDeleted() {
  var W = window.WebToApk;
  if (!W || typeof W.widgetClear !== 'function') return;
  W.widgetClear();
  if (W.widgetPlacedCount() > 0) {
    showMessage('Your widget is now empty. You can remove it from your home screen.');
  }
}

Note: Il widget resta nella schermata Home; viene rimosso solo il suo contenuto. Chiama AppMint.widget.set() per riempirlo di nuovo.

widgetPlacedCount bridge#

window.WebToApk.widgetPlacedCount(): Int

Quante copie del widget l'utente ha aggiunto alla schermata Home.

Esempio

Meccanismo interno dietro AppMint.widget.placedCount(): quante copie del tuo widget l'utente ha messo nella schermata Home.

Restituisce: un numero, in modo sincrono (0 se nessuno). Richiede: niente.

Prima l'API pubblica: mostra un pulsante «Aggiungi widget» solo quando il widget non è ancora stato aggiunto:

async function showAddWidgetButton() {
  var btn = document.getElementById('add-widget');
  if (!(window.AppMint && AppMint.widget)) { btn.hidden = true; return; }
  btn.hidden = (await AppMint.widget.placedCount()) > 0;
}

La chiamata grezza:

if (window.WebToApk && typeof window.WebToApk.widgetPlacedCount === 'function') {
  var n = window.WebToApk.widgetPlacedCount();
  console.log('Widgets on the home screen: ' + n);
}

Controlla di nuovo ogni volta che l'utente torna dal launcher e ringrazialo quando il widget è presente:

document.addEventListener('visibilitychange', async function () {
  if (document.visibilityState !== 'visible') return;
  if (!(window.AppMint && AppMint.widget)) return;
  var n = await AppMint.widget.placedCount();
  document.getElementById('widget-promo').hidden = n > 0;
  if (n > 0) document.getElementById('widget-thanks').hidden = false;
});

Mostra lo stato del widget in una pagina delle impostazioni con la chiamata grezza sincrona:

var status = document.getElementById('widget-status');
if (window.WebToApk && typeof window.WebToApk.widgetPlacedCount === 'function') {
  var n = window.WebToApk.widgetPlacedCount();
  status.textContent = n === 0 ? 'Not on your home screen'
    : n === 1 ? 'On your home screen' : 'On your home screen ' + n + ' times';
} else {
  status.textContent = 'Available in the installed app';
}

Note: Controlla di nuovo quando l'app torna in primo piano (visibilitychange), perché l'utente aggiunge i widget dal launcher, fuori dalla tua app.

widgetRequestPin bridge#

window.WebToApk.widgetRequestPin(): Boolean

Apre la schermata «Aggiungi alla schermata Home» del launcher per il widget (Android 8+). Falso dove il launcher non può farlo.

Esempio

Meccanismo interno dietro AppMint.widget.requestPin(): apre la schermata «Aggiungi alla schermata Home» del launcher per il tuo widget.

Restituisce: true se la schermata si è aperta, false dove il launcher non può farlo (in modo sincrono). Richiede: Android 8+ e un launcher che supporti il fissaggio dei widget.

Prima l'API pubblica, da un tocco su un pulsante:

document.getElementById('add-widget').onclick = async function () {
  if (!(window.AppMint && AppMint.widget)) return;
  var opened = await AppMint.widget.requestPin();
  if (!opened) {
    alert('Touch and hold your home screen, tap Widgets, then pick this app.');
  }
};

La chiamata grezza:

if (window.WebToApk && typeof window.WebToApk.widgetRequestPin === 'function') {
  if (!window.WebToApk.widgetRequestPin()) showManualSteps();
}

Riempi prima la scheda, poi apri la schermata, così il widget mostra contenuti reali nel momento in cui arriva:

document.getElementById('add-widget').onclick = async function () {
  if (!(window.AppMint && AppMint.widget)) return;
  await AppMint.widget.set({ title: 'Streak', value: '12 days', lines: ['Best 30'], route: '/streak' });
  if (!(await AppMint.widget.requestPin())) {
    document.getElementById('widget-help').hidden = false; // manual steps
  }
};

Scopri se l'utente ha accettato: confronta il numero di widget aggiunti prima della schermata e dopo il suo ritorno:

document.getElementById('add-widget').onclick = function () {
  var W = window.WebToApk;
  if (!W || typeof W.widgetRequestPin !== 'function') return;
  var before = W.widgetPlacedCount();
  if (!W.widgetRequestPin()) { showManualSteps(); return; }
  document.addEventListener('visibilitychange', function check() {
    if (document.visibilityState !== 'visible') return;
    document.removeEventListener('visibilitychange', check);
    if (W.widgetPlacedCount() > before) showToast('Widget added');
  });
};

Note: true significa solo che la schermata si è aperta: l'utente può ancora annullare. Usa AppMint.widget.placedCount() più tardi per vedere se è stato aggiunto. Riempi prima la scheda con AppMint.widget.set(), così il nuovo widget non è vuoto.

widgetSet bridge#

window.WebToApk.widgetSet(cardJson: String): String

Salva la scheda del widget [cardJson] `{title?, value?, lines?, route?, bg?, ink?, accent?}` e ridisegna ogni widget aggiunto. Restituisce `{ok, placed}`.

Esempio

Meccanismo interno dietro AppMint.widget.set(card): le pagine usano quell'helper per riempire il widget della schermata Home.

Restituisce: una stringa JSON {"ok":true,"placed":<number>} oppure {"ok":false,"error":"…"} (in modo sincrono). Richiede: niente: ogni build ha il widget.

Prima l'API pubblica:

if (window.AppMint && AppMint.widget) {
  AppMint.widget.set({ title: 'Steps', value: '8 214', lines: ['Goal 10 000'], route: '/' })
    .then(function (r) { if (!r.ok) console.log(r.error); });
}

La chiamata grezza riceve la scheda come stringa JSON e restituisce testo JSON:

if (window.WebToApk && typeof window.WebToApk.widgetSet === 'function') {
  var card = { title: 'Steps', value: '8 214', lines: ['Goal 10 000'], route: '/',
               bg: '#15161A', ink: '#FFFFFF', accent: '#22D3EE' };
  var r = JSON.parse(window.WebToApk.widgetSet(JSON.stringify(card)));
  console.log(r.ok ? 'on ' + r.placed + ' home screen(s)' : r.error);
}

Mantieni il widget allineato a una lista di cose da fare: il numero di attivitĂ  aperte come valore, le prime sei attivitĂ  come righe e un tocco apre la schermata delle attivitĂ :

async function syncTaskWidget(tasks) {
  if (!(window.AppMint && AppMint.widget)) return;
  var open = tasks.filter(function (t) { return !t.done; });
  var r = await AppMint.widget.set({
    title: 'To do',
    value: open.length ? open.length + ' left' : 'All done',
    lines: open.slice(0, 6).map(function (t) { return '• ' + t.title; }),
    route: '/tasks'
  });
  if (!r.ok) console.warn('Widget not updated: ' + r.error);
}

Scrivi l'ultimo stato quando l'utente lascia l'app; la chiamata grezza è sincrona, quindi termina prima che la pagina venga messa in pausa:

document.addEventListener('visibilitychange', function () {
  if (document.visibilityState !== 'hidden') return;
  if (!window.WebToApk || typeof window.WebToApk.widgetSet !== 'function') return;
  var s = getTodayStats(); // your app's own numbers
  window.WebToApk.widgetSet(JSON.stringify({
    title: 'Today', value: s.spent + ' spent',
    lines: ['Budget ' + s.budget, 'Left ' + (s.budget - s.spent)], route: '/budget'
  }));
});

Note: Chiavi della scheda: title, value, caption, lines (fino a dodici; una riga è una stringa o {text, color, marker, bold, wrap, route}), route (viene aggiunto un / se manca), bg, ink, accent, textSize, align, wrap, font (un file .ttf/.otf nella tua app o una famiglia di sistema come serif), più le chiavi del layout avanzato: vedi AppMint.widget. Colori: #RRGGBB, #AARRGGBB (alpha per primo), rgba(). Ogni widget aggiunto viene ridisegnato subito. placed è 0 quando l'utente non ha ancora aggiunto il widget: la scheda viene comunque salvata e compare quando lo aggiunge.

widgetUpdate bridge#

window.WebToApk.widgetUpdate(partialJson: String): String

Unisce [partialJson] alla scheda del widget salvata (le chiavi indicate sostituiscono, le altre restano) e ridisegna. Restituisce `{ok, placed}`.

Esempio

Modifica una parte del widget della schermata Home: le chiavi che passi sostituiscono quelle salvate, tutto il resto rimane. Le pagine normalmente chiamano AppMint.widget.update(partial).

Restituisce: una stringa JSON {"ok":true,"placed":<n>} oppure {"ok":false,"error":"…"}. Richiede: niente: ogni build ha il widget.

// Only the number and the progress bar change; title, rows and buttons stay as they were.
if (window.AppMint && AppMint.widget) {
  AppMint.widget.update({ value: '7 420', progress: { value: 7420, max: 10000, label: '74% of goal' } });
}

// Raw form:
if (window.WebToApk && typeof window.WebToApk.widgetUpdate === 'function') {
  var r = JSON.parse(window.WebToApk.widgetUpdate(JSON.stringify({ subtitle: 'Updated ' + new Date().toLocaleTimeString() })));
  if (!r.ok) console.warn(r.error);
}

Svuota la scheda alla disconnessione e segnala un errore da update:

async function onSignOut() {
  if (!(window.AppMint && AppMint.widget)) return;
  await AppMint.widget.clear();
}

async function bumpCount(n) {
  if (!(window.AppMint && AppMint.widget)) return;
  const r = await AppMint.widget.update({ value: String(n) });
  if (!r.ok) console.warn('Widget not updated: ' + r.error);
}

Combinalo con il controllo di presenza: aggiorna la scheda solo mentre una copia è nella schermata Home.

async function refreshWidget(stats) {
  if (!(window.AppMint && AppMint.widget)) return;
  if (await AppMint.widget.placedCount() === 0) return;
  AppMint.widget.update({ value: stats.total + ' today', subtitle: 'Updated ' + new Date().toLocaleTimeString() });
}

Note: Senza una scheda salvata, update() si comporta come set(). Vedi AppMint.widget per tutte le chiavi della scheda.

Generato dal runtime dell'app e dai suoi file di esempio a ogni build della documentazione. Leggilo in Markdown · Tutte le famiglie.

Verificato rispetto al bridge distribuito il 22/10/2026.