JavaScript köprü API'si
Ana ekran widget'ı
Sayfanızın bir başlık, bir değer ve birkaç satırla doldurduğu, ana ekrandaki küçük bir Android kartı - AppMint.widget.
AppMint.widget yardımcı#
AppMint.widget.set(card) / update(partial) / clear() / placedCount() / requestPin()
Örnek
Uygulamanızın ana ekran widget'ını doldurur: bir başlık, tek büyük bir değer, bir alt yazı, on ikiye kadar satır (isterseniz her birinin kendi rengi, işareti ve dokunma yolu ile), renkleriniz ve dokunulduğunda açılan bir yol içeren yerel bir kart. Kullanıcı widget'ı büyüttüğünde daha fazla satır gösterir; textSize: 'auto' ile de metin, her satır hâlâ sığdığı sürece büyüyerek alanı doldurur - uzun bir satır kesilmek yerine iki satıra yayılır. Bir widget HTML gösteremez - ona metni gönderirsiniz.
Döndürür: her yöntem bir Promise döndürür. set(card) → {ok: true, placed} (placed = ana ekranda kaç kopya olduğu) veya {ok: false, error}. clear() → undefined. placedCount() → bir sayı. requestPin() → başlatıcının "Ekle" sayfası açıldıysa true. Gerektirir: hiçbir şey - her derlemede widget vardır.
Kartı ayarlayın - başlangıçta bir kez ve gösterdiği veri her değiştiğinde:
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);
}Widget'ı dolduran bir ajanda - şeffaf arka plan, widget yeniden boyutlandırıldığında büyüyen metin, işaretli renkli satırlar, kırmızı bir gecikmiş satır ve bir satıra dokunulduğunda o günü açan bir yol:
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
});Bir satır bir dizedir veya { text, color?, marker?, bold?, wrap?, route? }; marker metnin önüne renkli bir ● koyar, bir satırda (veya kartta) wrap: true uzun bir satırın her metin boyutunda iki satır kaplamasını sağlar; textSize: 'auto' ile satırlar zaten böyledir ve wrap: false bir satırı tek satırda tutar. İlk altı satır her zaman görünür; yedinci ile on ikinci arasındaki satırlar widget yeterince uzunsa görünür.
Daha zengin widget'lar - bir liste, ilerleme çubuklu büyük bir sayı, bir arka plan resmi ve düğmeler. Bir kart yalnızca bu anahtarlardan birine sahipse böyle çizilir; bunlar olmayan bir kart eskisi gibi görünür:
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 keysKendi yazı tipiniz - yazı tipi dosyasını uygulamanıza koyun (.ttf veya .otf, örn. Google Fonts'un "Download family" seçeneğinden) ve bir <img> verir gibi yolunu belirtin; karttaki tüm metinler onunla çizilir:
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: …"'RocknRoll One' gibi bir yazı tipi ADI çalışamaz: widget'ları ana ekran çizer ve elinde yalnızca telefonun kendi yazı tipleri vardır - set() bunu söyleyen {ok: false, error} yanıtını verir. Bu yerleşik aileler dosya gerektirmez: 'serif', 'monospace', 'sans-serif-condensed', 'sans-serif-light', 'sans-serif-medium', 'sans-serif-black', 'casual', 'cursive', 'sans-serif-smallcaps'. WOFF / WOFF2 dosyaları reddedilir (Android bunları okuyamaz) - bunun yerine .ttf kullanın. Bir yazı tipi dosyasıyla kart, widget boyutunda bir resim olarak çizilir ve yeniden boyutlandırıldığında yeniden çizilir; satırlara, sıralara ve düğmelere dokunma ve ekran okuyucular her kartta olduğu gibi çalışır.
Uygulama kapalıyken yenileme - aynı JSON'u döndüren bir https adresi verin; ana ekranda bir widget olduğu sürece, yeniden başlatmadan sonra bile Android onu her refreshMinutes dakikada bir (30 veya daha fazla, varsayılan 60) alır:
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"}]}Görseller: uygulamanızdaki bir yol (sayfadaki bir <img src> gibi çözülür), bir https adresi veya bir data:image/… URL'si; küçültülür ve telefonda saklanır. Yenileme JSON'unda göreli bir yol, uygulamanın bir dosyası anlamına gelir. refreshUrl: '' yenilemeyi durdurur; clear() de durdurur. Her yenilemenin tam anını Android belirler (pil tasarrufu için arka plan işlerini toplu çalıştırır).
Bir "Ana ekrana ekle" düğmesi:
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.');
}Boşaltın (örneğin kullanıcı çıkış yaptıktan sonra):
if (window.AppMint && AppMint.widget) AppMint.widget.clear(); // shows "Nothing to show yet"Widget'a dokunmak uygulamayı başlatma bağlantısı olarak appmint-shortcut://<package><route> ile açar - başlangıçta WebToApk.getLaunchUrl() ile, çalışırken appmint:deep-link olayıyla okuyun:
window.addEventListener('appmint:deep-link', function (e) {
var m = /^appmint-shortcut:\/\/[^\/?#]*([^#]*)/i.exec(e.detail.url);
if (m) goTo(m[1] || '/');
});Renkler: #RRGGBB, #RGB, rgb(20, 38, 74), rgba(20, 38, 74, 0.6) (ayrıca rgb(20 38 74 / 60%)), transparent ve red gibi düz adlar. Sekiz haneli hex, Android sırasıdır, alfa BAŞTA: #AARRGGBB. #9914264A %60 opaktır; CSS'in #14264A99 değeri burada 14 alfa (%8) olarak okunur, yani neredeyse görünmez bir kart. Şeffaf arka planlar için rgba() karışıklığı önler. Çizgi renkleri (color, marker) aynı biçimleri alır; hatalı bir çizgi rengi {ok: false, error: 'lines[2].color is not a colour'} ile reddedilir, hatalı bir kart rengi varsayılanı kullanır.
Notlar: Tüm kart alanları isteğe bağlıdır: boş bir title uygulama adını gösterir; boş value, caption veya satırlar gizlenir; on ikinciden sonraki satırlar atılır. textSize ve align karttaki tüm metinlere uygulanır; bilinmeyen bir değer {ok: false, error} ile reddedilir. Yeni anahtarları (caption, textSize, align, wrap, biçimlendirilmiş satırlar) içermeyen bir kart eskisi gibi görünür. Widget son kartı yeniden başlatmadan sonra bile tutar ve yalnızca sayfanız set() çağırdığında değişir. requestPin() Android 8+ ve bunu destekleyen bir başlatıcı gerektirir. Yapay zekayla oluşturulan uygulamalar @/lib/appmintNative içinden widget kullanabilir. Biçimlendirilmiş satırlar, caption, textSize, align, wrap ve rgba(), AppMint 1.11.38 veya daha yeni bir sürümle derlenmiş uygulama gerektirir - satır nesneleri göndermeden önce uygulamayı yeniden derleyin, çünkü eski bir derleme bunları ham metin olarak gösterir. font, AppMint 1.11.41 veya daha yeni bir sürümle derlenmiş uygulama gerektirir (eski derleme bunu yok sayar). Web sitesi modundaki uygulamalar: bir dokunuş, web sitenizdeki yolu açar - /#/today, https://<your site>/#/today adresini yükler - ve getLaunchUrl() yine appmint-shortcut:// bağlantısını döndürür.
widgetClear köprü#
window.WebToApk.widgetClear()
Kartı kaldırır; yerleştirilmiş widget'lar boş durumlarına döner.
Örnek
AppMint.widget.clear() arkasındaki dahili altyapı - widget'ın kartını kaldırır; yerleştirilmiş her widget "Henüz gösterilecek bir şey yok" durumuna döner.
Döndürür: hiçbir şey. Gerekenler: hiçbir şey.
Önce genel API:
async function onSignOut() {
if (window.AppMint && AppMint.widget) await AppMint.widget.clear();
}Ham çağrı:
if (window.WebToApk && typeof window.WebToApk.widgetClear === 'function') {
window.WebToApk.widgetClear();
}Widget'ı ayarlarınızdaki bir "Ana ekranda göster" anahtarına bağlayın - kapatınca boşalır, açınca yeniden dolar:
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();
}
};Hesabı sildikten sonra widget'ı boşaltın ve ana ekranda hâlâ bir kopya varsa kullanıcıya söyleyin:
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.');
}
}Notlar: Widget ana ekranda kalır; yalnızca içeriği kaldırılır. Yeniden doldurmak için AppMint.widget.set() çağırın.
widgetPlacedCount köprü#
window.WebToApk.widgetPlacedCount(): Int
Kullanıcının ana ekrana widget'tan kaç kopya yerleştirdiği.
Örnek
AppMint.widget.placedCount() arkasındaki dahili altyapı - kullanıcının ana ekrana widget'ınızdan kaç kopya yerleştirdiği.
Döndürür: eşzamanlı olarak bir sayı (hiç yoksa 0). Gerektirir: hiçbir şey.
Önce herkese açık API - "Widget ekle" düğmesini yalnızca widget henüz yerleştirilmemişse gösterin:
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;
}Ham çağrı:
if (window.WebToApk && typeof window.WebToApk.widgetPlacedCount === 'function') {
var n = window.WebToApk.widgetPlacedCount();
console.log('Widgets on the home screen: ' + n);
}Kullanıcı başlatıcıdan her döndüğünde yeniden kontrol edin ve widget yerleştirildiğinde ona teşekkür edin:
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;
});Widget'ın durumunu, eşzamanlı ham çağrıyla bir ayarlar sayfasında gösterin:
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';
}Notlar: Uygulama ön plana geldiğinde yeniden kontrol edin (visibilitychange); çünkü kullanıcı widget'ları uygulamanızın dışında, başlatıcıdan ekler.
widgetRequestPin köprü#
window.WebToApk.widgetRequestPin(): Boolean
Widget için başlatıcının "Ana ekrana ekle" sayfasını açar (Android 8+). Başlatıcının yapamadığı yerlerde false.
Örnek
AppMint.widget.requestPin() arkasındaki dahili altyapı - widget'ınız için başlatıcının "Ana ekrana ekle" sayfasını açar.
Döndürür: sayfa açıldıysa true, başlatıcının yapamadığı yerlerde false (eşzamanlı olarak). Gerektirir: Android 8+ ve widget sabitlemeyi destekleyen bir başlatıcı.
Önce herkese açık API, bir düğme dokunuşundan:
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.');
}
};Ham çağrı:
if (window.WebToApk && typeof window.WebToApk.widgetRequestPin === 'function') {
if (!window.WebToApk.widgetRequestPin()) showManualSteps();
}Önce kartı doldurun, sonra sayfayı açın; böylece widget yerleştiği anda gerçek içeriği gösterir:
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
}
};Kullanıcının kabul edip etmediğini öğrenin: sayfadan önceki ve kullanıcı döndükten sonraki yerleştirme sayısını karşılaştırın:
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');
});
};Notlar: true yalnızca sayfanın açıldığı anlamına gelir - kullanıcı yine de iptal edebilir. Eklenip eklenmediğini görmek için daha sonra AppMint.widget.placedCount() kullanın. Yeni widget boş kalmasın diye önce kartı AppMint.widget.set() ile doldurun.
widgetSet köprü#
window.WebToApk.widgetSet(cardJson: String): String
Widget kartını [cardJson] `{title?, value?, lines?, route?, bg?, ink?, accent?}` kaydeder ve yerleştirilmiş her widget'ı yeniden çizer. `{ok, placed}` döndürür.
Örnek
AppMint.widget.set(card) arkasındaki dahili altyapı - sayfalar ana ekran widget'ını doldurmak için bu yardımcıyı kullanır.
Döndürür: bir JSON dizesi: {"ok":true,"placed":<number>} veya {"ok":false,"error":"…"} (eşzamanlı olarak). Gerektirir: hiçbir şey - her derlemede widget vardır.
Önce genel API:
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); });
}Ham çağrı kartı bir JSON dizesi olarak alır ve JSON metni döndürür:
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);
}Widget'ı bir yapılacaklar listesiyle eşleştirin - değer olarak açık görev sayısı, satırlar olarak ilk altı görev ve dokunulunca görevler ekranını açan bir yol:
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);
}Kullanıcı uygulamadan ayrılırken en son durumu yazın; ham çağrı eşzamanlıdır, bu yüzden sayfa duraklatılmadan önce biter:
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'
}));
});Notlar: Kart anahtarları: title, value, caption, lines (on ikiye kadar; bir satır dizedir veya {text, color, marker, bold, wrap, route}), route (eksikse bir / eklenir), bg, ink, accent, textSize, align, wrap, font (uygulamanızdaki bir .ttf/.otf dosyası veya serif gibi bir sistem ailesi) ve zengin düzen anahtarları - bkz. AppMint.widget. Renkler: #RRGGBB, #AARRGGBB (alfa önce), rgba(). Yerleştirilmiş her widget aynı anda yeniden çizilir. Kullanıcı widget'ı henüz eklemediyse placed değeri 0 olur - kart yine de kaydedilir ve eklediğinde görünür.
widgetUpdate köprü#
window.WebToApk.widgetUpdate(partialJson: String): String
[partialJson] değerini kayıtlı widget kartıyla birleştirir (adı geçen anahtarlar yerine geçer, geri kalanı kalır) ve yeniden çizer. `{ok, placed}` döndürür.
Örnek
Ana ekran widget'ının bir bölümünü değiştirir: geçtiğiniz anahtarlar kayıtlı olanların yerini alır, geri kalan her şey kalır. Sayfalar normalde şunu çağırır: AppMint.widget.update(partial).
Döndürür: bir JSON dizesi: {"ok":true,"placed":<n>} veya {"ok":false,"error":"…"}. Gerektirir: hiçbir şey - her derlemede widget vardır.
// 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);
}Çıkış yaparken kartı temizleyin ve bir hatayı şuradan bildirin: 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);
}Yerleştirme kontrolüyle birleştirin: kartı yalnızca ana ekranda bir kopya varken yenileyin.
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() });
}Notlar: Kayıtlı kart yoksa update(), set() gibi davranır. Tüm kart anahtarları için bkz. AppMint.widget.