JavaScript ब्रिज API
होम-स्क्रीन विजेट
होम स्क्रीन पर एक छोटा Android कार्ड जिसे आपका पेज एक शीर्षक, एक वैल्यू और कुछ लाइनों से भरता है - AppMint.widget.
AppMint.widget हेल्पर#
AppMint.widget.set(card) / update(partial) / clear() / placedCount() / requestPin()
उदाहरण
आपके ऐप का होम-स्क्रीन विजेट भरता है: एक छोटा नेटिव कार्ड जिसमें एक शीर्षक, एक बड़ी वैल्यू, छह तक छोटी लाइनें, आपके रंग, और एक रूट होता है जो टैप करने पर खुलता है। विजेट HTML नहीं दिखा सकता - आप उसे टेक्स्ट भेजते हैं।
लौटाता है: हर मेथड एक Promise लौटाता है। set(card) → {ok: true, placed} (placed = होम स्क्रीन पर कितनी कॉपी हैं) या {ok: false, error}। clear() → undefined। placedCount() → एक संख्या। requestPin() → true अगर लॉन्चर की "जोड़ें" शीट खुली। ज़रूरत: कुछ नहीं - हर बिल्ड में विजेट होता है।
कार्ड सेट करें - शुरू में एक बार, और फिर हर बार जब उसका डेटा बदले:
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);
}और समृद्ध विजेट - एक सूची, प्रोग्रेस बार वाला बड़ा नंबर, बैकग्राउंड तस्वीर और बटन। कार्ड इस तरह तभी बनता है जब उसमें इनमें से कोई कुंजी हो; इनके बिना कार्ड पहले जैसा ही दिखता है:
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ऐप बंद होने पर रिफ़्रेश - ऐसा https पता दें जो वही JSON लौटाता हो; जब तक विजेट होम स्क्रीन पर है, Android उसे हर refreshMinutes (30 या ज़्यादा, डिफ़ॉल्ट 60) पर लाता है, रीस्टार्ट के बाद भी:
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"}]}इमेज: आपके ऐप में एक पाथ (पेज में <img src> की तरह हल होता है), एक https पता, या एक data:image/… URL; इन्हें छोटा करके फ़ोन पर रखा जाता है। रिफ़्रेश JSON में सापेक्ष पाथ का मतलब ऐप की फ़ाइल है। refreshUrl: '' रिफ़्रेश रोक देता है; clear() भी रोक देता है। हर रिफ़्रेश का सटीक पल Android तय करता है (वह बैटरी बचाने के लिए बैकग्राउंड काम इकट्ठा करके चलाता है)।
"होम स्क्रीन पर जोड़ें" बटन:
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.');
}इसे खाली करें (जैसे यूज़र के साइन आउट करने के बाद):
if (window.AppMint && AppMint.widget) AppMint.widget.clear(); // shows "Nothing to show yet"विजेट पर टैप ऐप को appmint-shortcut://<package><route> के साथ उसके लॉन्च लिंक के रूप में खोलता है - शुरू होने पर इसे WebToApk.getLaunchUrl() से और चलते समय appmint:deep-link इवेंट से पढ़ें:
window.addEventListener('appmint:deep-link', function (e) {
var m = /^appmint-shortcut:\/\/[^\/?#]*([^#]*)/i.exec(e.detail.url);
if (m) goTo(m[1] || '/');
});ध्यान दें: कार्ड के सभी फ़ील्ड वैकल्पिक हैं: खाली title ऐप का नाम दिखाता है; खाली value या लाइनें छिपी रहती हैं; छठी के बाद की लाइनें छोड़ दी जाती हैं; रंग #RRGGBB / #AARRGGBB होते हैं (गलत रंग पर डिफ़ॉल्ट इस्तेमाल होता है)। विजेट आख़िरी कार्ड रखता है, रीस्टार्ट के बाद भी, और तभी बदलता है जब आपका पेज फिर से set() बुलाए। requestPin() के लिए Android 8+ और इसे सपोर्ट करने वाला लॉन्चर चाहिए। AI से बने ऐप @/lib/appmintNative से widget इस्तेमाल कर सकते हैं। वेबसाइट-मोड वाले ऐप: विजेट टैप करने पर ऐप रीस्टार्ट होता है, और वेबसाइट मोड में शेल तब appmint-shortcut:// पते को पेज की तरह लोड करने की कोशिश करता है, जो विफल होती है (WebView ऐसा पता नहीं खोल सकता) - इसलिए टैप पर route सिर्फ़ HTML, ZIP और AI से बने ऐप में काम करता है।
widgetClear ब्रिज#
window.WebToApk.widgetClear()
कार्ड हटाता है; रखे हुए विजेट अपनी खाली स्थिति में लौट जाते हैं।
उदाहरण
AppMint.widget.clear() के पीछे की आंतरिक व्यवस्था - विजेट का कार्ड हटाती है; रखा हुआ हर विजेट "अभी दिखाने को कुछ नहीं" पर लौट आता है।
लौटाता है: कुछ नहीं। ज़रूरत: कुछ नहीं।
पहले पब्लिक API:
async function onSignOut() {
if (window.AppMint && AppMint.widget) await AppMint.widget.clear();
}सीधा कॉल:
if (window.WebToApk && typeof window.WebToApk.widgetClear === 'function') {
window.WebToApk.widgetClear();
}विजेट को अपनी सेटिंग्स में "होम स्क्रीन पर दिखाएँ" स्विच से जोड़ें - बंद करने पर वह खाली हो जाता है, चालू करने पर फिर भर जाता है:
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();
}
};अकाउंट डिलीट करने के बाद विजेट खाली करें, और अगर कोई कॉपी अब भी होम स्क्रीन पर है तो यूज़र को बताएँ:
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.');
}
}ध्यान दें: विजेट होम स्क्रीन पर बना रहता है; सिर्फ़ उसकी सामग्री हटती है। उसे फिर भरने के लिए AppMint.widget.set() बुलाएँ।
widgetPlacedCount ब्रिज#
window.WebToApk.widgetPlacedCount(): Int
यूज़र ने विजेट की कितनी कॉपी होम स्क्रीन पर रखी हैं।
उदाहरण
AppMint.widget.placedCount() के पीछे की आंतरिक व्यवस्था - यूज़र ने आपके विजेट की कितनी कॉपी होम स्क्रीन पर रखी हैं।
लौटाता है: एक संख्या, सिंक्रोनस तरीके से (कोई न हो तो 0)। ज़रूरत: कुछ नहीं।
पहले सार्वजनिक API - "विजेट जोड़ें" बटन तभी दिखाएँ जब विजेट अभी रखा न गया हो:
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;
}सीधा कॉल:
if (window.WebToApk && typeof window.WebToApk.widgetPlacedCount === 'function') {
var n = window.WebToApk.widgetPlacedCount();
console.log('Widgets on the home screen: ' + n);
}यूज़र के लॉन्चर से लौटने पर हर बार फिर जाँचें, और विजेट लगते ही उनका धन्यवाद करें:
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;
});सिंक्रोनस रॉ कॉल से सेटिंग्स पेज पर विजेट की स्थिति दिखाएँ:
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';
}ध्यान दें: ऐप के सामने लौटने पर (visibilitychange) इसे फिर जाँचें, क्योंकि यूज़र विजेट आपके ऐप के बाहर, लॉन्चर से जोड़ता है।
widgetRequestPin ब्रिज#
window.WebToApk.widgetRequestPin(): Boolean
विजेट के लिए लॉन्चर की "होम स्क्रीन पर जोड़ें" शीट खोलता है (Android 8+)। जहाँ लॉन्चर ऐसा नहीं कर सकता वहाँ False।
उदाहरण
AppMint.widget.requestPin() के पीछे का आंतरिक काम - यह आपके विजेट के लिए लॉन्चर की "होम स्क्रीन पर जोड़ें" शीट खोलता है।
लौटाता है: शीट खुलने पर true, जहाँ लॉन्चर ऐसा नहीं कर सकता वहाँ false (सिंक्रोनस तरीके से)। ज़रूरत: Android 8+ और ऐसा लॉन्चर जो विजेट पिन करना सपोर्ट करता हो।
पहले सार्वजनिक API, बटन टैप से:
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.');
}
};सीधा कॉल:
if (window.WebToApk && typeof window.WebToApk.widgetRequestPin === 'function') {
if (!window.WebToApk.widgetRequestPin()) showManualSteps();
}पहले कार्ड भरें, फिर शीट खोलें, ताकि विजेट जिस पल लगे उसमें असली सामग्री दिखे:
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
}
};पता लगाएँ कि यूज़र ने स्वीकार किया या नहीं: शीट से पहले और यूज़र के लौटने के बाद की रखी हुई गिनती की तुलना करें:
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');
});
};ध्यान दें: true का मतलब सिर्फ़ इतना है कि शीट खुली - यूज़र फिर भी उसे रद्द कर सकता है। यह देखने के लिए कि विजेट जुड़ा या नहीं, बाद में AppMint.widget.placedCount() इस्तेमाल करें। पहले कार्ड को AppMint.widget.set() से भरें, ताकि नया विजेट खाली न रहे।
widgetSet ब्रिज#
window.WebToApk.widgetSet(cardJson: String): String
विजेट कार्ड [cardJson] `{title?, value?, lines?, route?, bg?, ink?, accent?}` सेव करता है और रखे हुए हर विजेट को दोबारा बनाता है। `{ok, placed}` लौटाता है।
उदाहरण
AppMint.widget.set(card) के पीछे की आंतरिक व्यवस्था - पेज होम-स्क्रीन विजेट भरने के लिए उस हेल्पर का इस्तेमाल करते हैं।
लौटाता है: एक JSON स्ट्रिंग {"ok":true,"placed":<number>} या {"ok":false,"error":"…"} (सिंक्रोनस तरीके से)। ज़रूरत: कुछ नहीं - हर बिल्ड में विजेट होता है।
पहले पब्लिक 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); });
}रॉ कॉल कार्ड को JSON स्ट्रिंग के रूप में लेती है और 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);
}विजेट को टू-डू सूची के साथ तालमेल में रखें - खुले कामों की गिनती वैल्यू के रूप में, पहले छह काम लाइनों के रूप में, और टैप करने पर कामों की स्क्रीन खुलती है:
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);
}यूज़र के ऐप छोड़ते समय ताज़ा स्थिति लिख दें; रॉ कॉल सिंक्रोनस है, इसलिए पेज के रुकने से पहले पूरी हो जाती है:
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'
}));
});ध्यान दें: कार्ड कुंजियाँ: title, value, lines (छह तक), route (अगर न हो तो / जोड़ दिया जाता है), bg, ink, accent। रखा हुआ हर विजेट तुरंत दोबारा बनता है। यूज़र ने विजेट अभी जोड़ा न हो तो placed 0 होता है - कार्ड फिर भी सेव हो जाता है और जोड़ने पर दिखता है।
widgetUpdate ब्रिज#
window.WebToApk.widgetUpdate(partialJson: String): String
[partialJson] को सेव किए विजेट कार्ड में मिलाता है (नामित कुंजियाँ बदलती हैं, बाकी रहती हैं) और दोबारा बनाता है। `{ok, placed}` लौटाता है।
उदाहरण
होम-स्क्रीन विजेट का एक हिस्सा बदलता है: जो कुंजियाँ आप देते हैं वे सेव की हुई कुंजियों की जगह लेती हैं, बाकी सब वैसा ही रहता है। पेज आमतौर पर बुलाते हैं AppMint.widget.update(partial).
लौटाता है: एक JSON स्ट्रिंग {"ok":true,"placed":<n>} या {"ok":false,"error":"…"}। ज़रूरत: कुछ नहीं - हर बिल्ड में विजेट होता है।
// 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);
}साइन-आउट पर कार्ड साफ़ करें और इससे त्रुटि की सूचना दें 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);
}इसे प्लेसमेंट की जाँच के साथ जोड़ें: कार्ड तभी रिफ़्रेश करें जब उसकी कॉपी होम स्क्रीन पर हो।
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() });
}ध्यान दें: सेव किया कार्ड न होने पर update() set() की तरह काम करता है। हर कार्ड कुंजी के लिए AppMint.widget देखें।