واجهة JavaScript bridge API
الاهتزاز والصوت
ردود فعل لمسية، ونقرة التطبيق الصوتية تُطلق على أحداثك الدلالية بدل كل لمسة عابرة، ومقطع الموسيقى الخلفية الذي اختاره المنشئ عند الإنشاء - getMusicVolume يُرجع -1 عندما لا يحمل التطبيق موسيقى، فتستطيع شاشة الإعدادات إخفاء الشريط بدل عرض شريط ميت.
cancelVibrate الجسر (bridge)#
window.WebToApk.cancelVibrate()
اهتزازات لمسية بسيطة للصفحة (navigator.vibrate وصيغة النمط). يُتجاهل كلاهما ما لم يفعّل الإنشاء إذن الاهتزاز.
موصوف ضمن مجموعته، الاهتزاز، وليس وحده.
مثال
يوقف اهتزازًا ما يزال يعمل. تستخدم معظم الصفحات navigator.vibrate(0) القياسي، الذي يستدعي هذا نيابةً عنك.
يعيد: لا شيء. يتطلب: فعّل الاهتزاز في الخطوة 4 (الوصول) عند الإنشاء.
الطريقة القياسية:
if ('vibrate' in navigator) navigator.vibrate(0); // or navigator.vibrate([])الاستدعاء الخام، مثلًا لإيقاف نمط منبّه طويل عندما ينقر المستخدم "تجاهل":
if (window.WebToApk && window.WebToApk.vibratePattern) {
window.WebToApk.vibratePattern(JSON.stringify([1000, 500, 1000, 500, 1000]));
}
document.getElementById('dismiss').addEventListener('click', function () {
if (window.WebToApk && typeof window.WebToApk.cancelVibrate === 'function') {
window.WebToApk.cancelVibrate();
}
});أوقف اهتزازًا جاريًا عندما يغادر المستخدم الشاشة، حتى لا يستمر الهاتف في الاهتزاز في جيبه:
document.addEventListener('visibilitychange', function () {
if (!document.hidden) return;
if (window.WebToApk && typeof window.WebToApk.cancelVibrate === 'function') {
window.WebToApk.cancelVibrate();
}
});ملاحظات: يمكن استدعاؤه بأمان عندما لا يكون هناك اهتزاز جارٍ.
getMusicVolume الجسر (bridge)#
window.WebToApk.getMusicVolume(): Int
المستوى الحالي من 0 إلى 100، أو -1 عندما لا يتضمن هذا التطبيق موسيقى خلفية.
مثال
يقرأ مستوى الموسيقى الخلفية المتكررة للتطبيق، من 0 إلى 100.
يُرجع: رقمًا، بشكل متزامن: 0-100، أو -1 عندما بُني هذا التطبيق بدون ملف موسيقى. المتطلبات: ملف مختار ضمن الموسيقى الخلفية في الخطوة 3 (Integrate)، ضمن خيارات العرض، عند الإنشاء.
أظهر شريط تمرير للموسيقى فقط عندما توجد موسيقى:
var slider = document.getElementById('music-slider');
var level = -1;
if (window.WebToApk && typeof window.WebToApk.getMusicVolume === 'function') {
level = window.WebToApk.getMusicVolume();
}
if (level < 0) {
slider.parentNode.hidden = true; // no music in this app: hide the setting
} else {
slider.value = level;
slider.addEventListener('input', function () {
window.WebToApk.setMusicVolume(parseInt(slider.value, 10));
});
}زر كتم يعود إلى مستوى المستخدم نفسه عند إلغاء الكتم (يتذكر التطبيق 0 أيضًا، فاحتفظ بالمستوى القديم بنفسك):
function musicLevel() {
return window.WebToApk && typeof window.WebToApk.getMusicVolume === 'function'
? window.WebToApk.getMusicVolume() : -1;
}
var muteBtn = document.getElementById('mute');
function paint() {
var v = musicLevel();
muteBtn.hidden = v < 0;
muteBtn.textContent = v === 0 ? 'Unmute' : 'Mute';
}
muteBtn.addEventListener('click', function () {
var v = musicLevel();
if (v < 0) return;
if (v > 0) {
try { localStorage.setItem('musicBefore', String(v)); } catch (e) {}
window.WebToApk.setMusicVolume(0);
} else {
var back = 40;
try { back = parseInt(localStorage.getItem('musicBefore') || '40', 10); } catch (e) {}
window.WebToApk.setMusicVolume(back);
}
paint();
});
paint();اخفت الموسيقى من مستواها الحالي إلى مستوى جديد، مثلًا تحت مشهد حوار:
function fadeMusicTo(target, ms) {
if (!window.WebToApk || typeof window.WebToApk.getMusicVolume !== 'function') return;
var start = window.WebToApk.getMusicVolume();
if (start < 0 || start === target) return;
var steps = 10, i = 0;
var t = setInterval(function () {
i++;
window.WebToApk.setMusicVolume(Math.round(start + (target - start) * i / steps));
if (i === steps) clearInterval(t);
}, ms / steps);
}
fadeMusicTo(10, 800); // dim under the dialogue
// later: fadeMusicTo(60, 800); the last level set is the one kept for the next launchملاحظات: يعيد المستوى الذي حدده شريط التمرير عند الإنشاء أو آخر استدعاء لـ setMusicVolume. عندما يستخدم تطبيق آخر أو مكالمة الصوت، تخفت الموسيقى أو تتوقف مؤقتًا من تلقاء نفسها؛ ولا يتغير الرقم الذي تقرأه.
getVolume الجسر (bridge)#
window.WebToApk.getVolume(stream: String): String
مستوى مجرى صوت واحد: `{stream, current, max, percent, muted}` كسلسلة JSON. stream: 'media' | 'alarm' | 'ring' | 'notification' | 'call'.
مثال
يقرأ أحد مستويات الصوت الخاصة بالهاتف.
يُرجع: سلسلة JSON، بشكل متزامن: {"stream":"alarm","current":5,"max":7,"percent":71,"muted":false} - current/max هما خطوات الهاتف نفسه (تختلف بين الهواتف)، وpercent بين 0 و100. stream هو 'media' أو 'alarm' أو 'ring' أو 'notification' أو 'call'؛ وأي اسم آخر يعطي {"error":"unknown_stream"}. المتطلبات: لا شيء.
function warnIfAlarmSilent() {
if (!(window.WebToApk && window.WebToApk.getVolume)) return;
const v = JSON.parse(WebToApk.getVolume('alarm'));
if (!v.error && v.percent === 0) {
showMessage('Your alarm volume is off, so the alarm will not be heard.');
}
}
warnIfAlarmSilent();اعرض كل المستويات في شاشة الإعدادات:
['media', 'alarm', 'ring', 'notification'].forEach(function (s) {
const v = JSON.parse(WebToApk.getVolume(s));
document.getElementById('vol-' + s).value = v.percent;
});اضبط مستوى صوت واقرأ النتيجة. setVolume(stream, percent, showUi) يُجيب بسلسلة JSON.
function setAlarmVolume(percent) {
if (!(window.WebToApk && WebToApk.setVolume)) return;
const r = JSON.parse(WebToApk.setVolume('alarm', percent, true));
if (!r.ok) showMessage('Could not change the volume: ' + r.error); // fixed_volume, muted, ...
else document.getElementById('vol-alarm').value = r.percent;
}playClick الجسر (bridge)#
window.WebToApk.playClick()
يشغّل صوت النقر الخاص بالتطبيق عند الطلب، لتطلقه الصفحة على أحداثها الدلالية (ضغطة زر) بدل كل نقرة عشوائية - وهو ما يفعله التطبيق الأصلي فعلًا، ولهذا يمكن أن يكون clickSoundMode بقيمة "off" ويظل هذا يعمل. لا يفعل شيئًا فقط إذا بُني التطبيق بدون صوت النقر (enableClickSound معطّل). في clickSoundMode "off" - بلا صوت تلقائي لكل نقرة - يظل الاستدعاء الصريح يعمل: هذا الوضع للتطبيقات التي تصدر صوتًا على أحداثها. وإلا فإنه يشغّل الملاحظة الصوتية التي ضبطها المنشئ.
مثال
يشغّل صوت النقر الخاص بالتطبيق مرة واحدة، لتصدر أزرارك صوت نقر كالتطبيق الأصلي.
يُرجع: لا شيء. المتطلبات: مفتاح صوت النقر في الخطوة 3 (Integrate)، ضمن خيارات العرض، عند الإنشاء (مفعّل افتراضيًا). عند إيقاف المفتاح لا يفعل هذا شيئًا.
function clickSound() {
if (window.WebToApk && typeof window.WebToApk.playClick === 'function') {
window.WebToApk.playClick();
}
}
document.querySelectorAll('button, .tab').forEach(function (el) {
el.addEventListener('click', clickSound);
});مستمع واحد للوحة لعبة كاملة، ينقر فقط عند لمسة تفعل شيئًا:
document.getElementById('board').addEventListener('click', function (e) {
var cell = e.target.closest('.cell');
if (!cell || cell.classList.contains('taken')) return; // a dead tap stays silent
if (window.WebToApk && typeof window.WebToApk.playClick === 'function') {
window.WebToApk.playClick();
}
placeMark(cell);
});امنح مستخدميك مفتاح "الأصوات" خاصًا بهم فوق إعداد الإنشاء:
var toggle = document.getElementById('sounds-toggle');
var soundsOn = true;
try { soundsOn = localStorage.getItem('sounds') !== 'off'; } catch (e) {}
toggle.checked = soundsOn;
toggle.addEventListener('change', function () {
soundsOn = toggle.checked;
try { localStorage.setItem('sounds', soundsOn ? 'on' : 'off'); } catch (e) {}
});
function tapSound() {
if (soundsOn && window.WebToApk && typeof window.WebToApk.playClick === 'function') {
window.WebToApk.playClick();
}
}ملاحظات: ما تسمعه يعتمد على خيار صوت النقر:
- اتبع إعداد الهاتف (موصى به): نقرة النظام. تكون صامتة إذا أوقف المستخدم "أصوات اللمس" في إعدادات الهاتف. وهذا مقصود.
- التشغيل دائمًا عند كل نقرة: نقرة التطبيق نفسه، مسموعة دائمًا. وكل نقرة على الصفحة تُصدر نقرة أيضًا، فلا تحتاج عادةً إلى
playClick()في هذا الوضع.
استدعِه من ضغطة زر حقيقية، لا من مؤقّت.
requestDndAccess الجسر (bridge)#
window.WebToApk.requestDndAccess(): String
وصول عدم الإزعاج، لازم لتغيير مستوى الرنين / الإشعارات أثناء تفعيل DND. "granted" | "opened" (فُتحت شاشة الإعدادات) | "not_declared".
مثال
يطلب صلاحية عدم الإزعاج، التي يشترطها Android قبل أن يتمكن التطبيق من تغيير مستوى صوت الرنين أو الإشعارات أثناء تفعيل عدم الإزعاج (يرد setVolume عندها بـ dnd_access_required).
يُرجع: سلسلة: 'granted' (مسموح بالفعل)، أو 'opened' (فُتحت شاشة النظام التي يسمح فيها المستخدم - أعد الفحص عند عودته)، أو 'not_declared' (هذا الإنشاء لا يحمل الإذن، فلن يدرجه Android هناك). المتطلبات: استدعاء requestDndAccess في كود تطبيقك: فيعلن الإنشاء حينها عن ACCESS_NOTIFICATION_POLICY تلقائيًا.
function allowRingVolume() {
if (!(window.WebToApk && window.WebToApk.requestDndAccess)) return;
const r = WebToApk.requestDndAccess();
if (r === 'opened') showMessage('Allow Do Not Disturb access for this app, then come back.');
if (r === 'not_declared') showMessage('Turn off Do Not Disturb to change the ring volume.');
}أعد محاولة تغيير مستوى الصوت بعد أن يسمح المستخدم بالوصول:
function setRing(percent) {
const r = JSON.parse(WebToApk.setVolume('ring', percent, true));
if (r.ok || r.error !== 'dnd_access_required') return r;
const a = WebToApk.requestDndAccess(); // 'granted' | 'opened' | 'not_declared'
if (a === 'granted') return JSON.parse(WebToApk.setVolume('ring', percent, true));
showMessage(a === 'opened' ? 'Allow access, then press the button again.' : 'Turn off Do Not Disturb first.');
return r;
}اكتم الرنين من مفتاح "وضع الاجتماع"، واذكر السبب عندما يتعذر ذلك:
function meetingMode(on) {
if (!(window.WebToApk && WebToApk.setVolume)) return;
const r = JSON.parse(WebToApk.setVolume('ring', on ? 0 : 70, false));
if (!r.ok && r.error === 'dnd_access_required') {
const a = WebToApk.requestDndAccess();
if (a === 'not_declared') showMessage('This build cannot change the ring volume while Do Not Disturb is on.');
}
}setMusicVolume الجسر (bridge)#
window.WebToApk.setMusicVolume(percent: Int)
اضبط مستوى موسيقى الخلفية من الصفحة، من 0 إلى 100. يحدد شريط المعالج كيف يبدأ التطبيق؛ وهذه هي الطريقة التي يمنح بها التطبيق مستخدميه تحكمًا بالموسيقى، وهو ما يُتوقع من أي لعبة لها شاشة إعدادات. يُقيَّد في [BackgroundMusic.setVolume]، فلا تستطيع صفحة تمرير 500 أو -1 أن تمنح MediaPlayer مستوى خارج النطاق المقبول. المستوى يُحفظ: يبدأ التشغيل التالي به، لا بمستوى المعالج. لا يفعل شيئًا إذا بُني التطبيق بلا مقطع - فلا شيء لضبطه، والجواب الصادق هو أن [getMusicVolume] يعيد -1 لتخفي الصفحة شريطها بدل عرض شريط لا يفعل شيئًا.
مثال
يغيّر مستوى موسيقى الخلفية المتكررة في التطبيق، من 0 إلى 100، مثلًا من شاشة إعدادات لعبتك.
يعيد: لا شيء. يتطلب: ملفًا مختارًا ضمن موسيقى الخلفية في الخطوة 3 (التكامل)، تحت خيارات العرض، عند الإنشاء. بدون موسيقى لا يفعل هذا شيئًا (تحقق من getMusicVolume() لمعرفة -1).
زر كتم - يتذكر التطبيق المستوى للتشغيل التالي:
function hasMusic() {
return !!(window.WebToApk && window.WebToApk.getMusicVolume) && window.WebToApk.getMusicVolume() >= 0;
}
if (!hasMusic()) document.getElementById('mute').hidden = true;
document.getElementById('mute').addEventListener('click', function () {
if (!hasMusic()) return;
// clamped to 0..100 by the app, and kept for the next launch
window.WebToApk.setMusicVolume(window.WebToApk.getMusicVolume() > 0 ? 0 : 40);
});أزرار إيقاف / منخفض / مرتفع في شاشة الإعدادات:
var LEVELS = { off: 0, low: 25, high: 70 };
document.querySelectorAll('[data-music]').forEach(function (btn) {
btn.addEventListener('click', function () {
if (!window.WebToApk || typeof window.WebToApk.setMusicVolume !== 'function') return;
if (window.WebToApk.getMusicVolume() < 0) return; // built without music
window.WebToApk.setMusicVolume(LEVELS[btn.dataset.music]);
markSelected(btn);
});
});اخفض الموسيقى أثناء تشغيل الفيديو الخاص بك ثم أعدها (المستوى محفوظ، لذا استعده دائمًا):
var video = document.getElementById('intro-video');
var before = -1;
video.addEventListener('play', function () {
if (!window.WebToApk || typeof window.WebToApk.getMusicVolume !== 'function') return;
before = window.WebToApk.getMusicVolume();
if (before > 0) window.WebToApk.setMusicVolume(Math.round(before / 4));
});
function restoreMusic() {
if (before > 0) window.WebToApk.setMusicVolume(before);
before = -1;
}
video.addEventListener('pause', restoreMusic);
video.addEventListener('ended', restoreMusic);ملاحظات: المستوى الذي تحدده يُحفظ: يبدأ التشغيل التالي به بدلًا من مستوى شريط الإنشاء (حتى يمسح المستخدم بيانات التطبيق). يجعل 0 الموسيقى صامتة لكنها تستمر في التشغيل.
setVolume الجسر (bridge)#
window.WebToApk.setVolume(stream: String, percent: Double, showUi: Boolean): String
يضبط مجرى على [percent] (0-100)؛ [showUi] يعرض شريط صوت الهاتف. `{ok:true, stream, current, max, percent}` أو `{ok:false, error}` - الخطأ هو unknown_stream | bad_percent | fixed_volume | dnd_access_required | muted | not_applied | failed | foreign_origin (صفحة خارج موقع التطبيق نفسه).
مثال
يضبط أحد مستويات صوت الهاتف، 0-100 - مثل رفع مجرى المنبّه لمنبّه استيقاظ، أو شريط وسائط في تطبيق موسيقى.
يعيد: سلسلة JSON: {"ok":true,"stream":"alarm","current":6,"max":7,"percent":86}، أو {"ok":false,"error":"…"} حيث يكون error هو unknown_stream، bad_percent، fixed_volume (هذا الجهاز بلا مستوى صوت قابل للضبط)، dnd_access_required (عدم الإزعاج مفعّل ويمنع مستوى الرنين / الإشعارات - انظر requestDndAccess())، foreign_origin (صفحة خارج موقع تطبيقك) أو failed. يعرض showUi: true شريط مستوى الصوت الخاص بالهاتف أثناء تحركه. يتطلب: لا شيء للوسائط والمنبّه والمكالمات؛ وقد يحتاج الرنين والإشعارات إلى صلاحية عدم الإزعاج أثناء تفعيله.
function setAlarmLoud() {
if (!(window.WebToApk && window.WebToApk.setVolume)) return;
const r = JSON.parse(WebToApk.setVolume('alarm', 80, true));
if (!r.ok) showMessage('Could not change the alarm volume: ' + r.error);
}
document.getElementById('ring-slider').oninput = function (e) {
const r = JSON.parse(WebToApk.setVolume('ring', Number(e.target.value), false));
if (r.error === 'dnd_access_required' && WebToApk.requestDndAccess() === 'not_declared') {
showMessage('Turn off Do Not Disturb to change the ring volume.');
}
};اقرأ مستوى، ثم اضبط شريط وسائط:
if (window.WebToApk && WebToApk.setVolume) {
const now = JSON.parse(WebToApk.getVolume('media')); // {stream, current, max, percent, muted}
slider.value = now.percent;
slider.oninput = () => {
const r = JSON.parse(WebToApk.setVolume('media', Number(slider.value), false));
if (r.ok) label.textContent = r.percent + '%';
else if (r.error === 'fixed_volume') slider.disabled = true; // this phone has no adjustable volume
};
}اعرض مستوى الرنين الحالي وتفاعل عند تغيّره:
if (window.WebToApk && WebToApk.getVolume) {
const ring = JSON.parse(WebToApk.getVolume('ring')); // {stream, current, max, percent, muted}
document.getElementById('ring-slider').value = ring.percent;
WebToApk.watchVolume(true);
window.addEventListener('appmint:volume', (e) => {
if (e.detail.stream === 'ring') document.getElementById('ring-slider').value = e.detail.percent;
});
}ملاحظات: تُقرَّب القيمة إلى أقرب خطوة في الهاتف، وتحمل الإجابة المستوى الذي ضُبط فعلًا. لا ينخفض مجرى المكالمات عن حده الأدنى (عادةً 1).
vibrate الجسر (bridge)#
window.WebToApk.vibrate(durationMs: Long)
اهتزازات لمسية بسيطة للصفحة (navigator.vibrate وصيغة النمط). يُتجاهل كلاهما ما لم يفعّل الإنشاء إذن الاهتزاز.
موصوف ضمن مجموعته، الاهتزاز، وليس وحده.
مثال
يهزّ الهاتف مرة واحدة للمدة المحددة بالمللي ثانية. تستخدم معظم الصفحات navigator.vibrate(ms) القياسي الذي يستدعي هذا نيابةً عنك.
يعيد: لا شيء. يتطلب: فعّل الاهتزاز في الخطوة 4 (الوصول) عند الإنشاء. بدونه لا يفعل الاستدعاء شيئًا.
الطريقة القياسية (تعمل بالطريقة نفسها في المتصفح):
if ('vibrate' in navigator) navigator.vibrate(50);الاستدعاء الخام:
document.getElementById('like').addEventListener('click', function () {
if (window.WebToApk && typeof window.WebToApk.vibrate === 'function') {
window.WebToApk.vibrate(40); // 40 ms
}
});
// 0 (or any value <= 0) stops a running vibration
if (window.WebToApk && window.WebToApk.vibrate) window.WebToApk.vibrate(0);نقرة صغيرة عند كل مرة ينتقل فيها شريط التمرير إلى خطوة جديدة، مثل أداة اختيار أصلية:
var slider = document.getElementById('size');
var last = slider.value;
slider.addEventListener('input', function () {
if (slider.value === last) return; // same step, no tick
last = slider.value;
if (window.WebToApk && typeof window.WebToApk.vibrate === 'function') {
window.WebToApk.vibrate(10); // 10 ms: a light tick
}
});اهتزاز أطول عندما يتعذر إرسال نموذج، ليشعر المستخدم بالخطأ:
document.getElementById('signup').addEventListener('submit', function (e) {
if (this.checkValidity()) return;
e.preventDefault();
if (window.WebToApk && typeof window.WebToApk.vibrate === 'function') {
window.WebToApk.vibrate(250);
}
this.reportValidity();
});ملاحظات: مرّر عددًا صحيحًا. القوة هي الافتراضية للهاتف؛ للنقرات الأقوى/الأضعف استخدم Capacitor.Plugins.Haptics.impact أو Capacitor.Plugins.AppwrightHaptics.play. لنمط اهتزاز-توقف-اهتزاز استخدم vibratePattern.
vibratePattern الجسر (bridge)#
window.WebToApk.vibratePattern(patternJson: String)
يهتز بنمط تشغيل/إيقاف، مثل "[100,50,100]" = اهتزاز 100 مللي ثانية، توقف 50، اهتزاز 100. يدعم navigator.vibrate(array)؛ ويُفضَّل استخدام الواجهة القياسية. لا يفعل شيئًا ما لم يفعّل المنشئ إذن الاهتزاز.
مثال
يهزّ بنمط تشغيل/إيقاف، يُعطى كسلسلة JSON. تستخدم معظم الصفحات navigator.vibrate([...]) القياسي الذي يستدعي هذا نيابةً عنك.
يعيد: لا شيء. يتطلب: فعّل الاهتزاز في الخطوة 4 (الوصول) عند الإنشاء. بدونه لا يفعل الاستدعاء شيئًا.
الطريقة القياسية:
if ('vibrate' in navigator) navigator.vibrate([100, 50, 100]); // buzz, pause, buzzيقبل الاستدعاء الخام النمط نفسه بأسلوب الويب كـ سلسلة JSON:
function pattern(list) {
if (window.WebToApk && typeof window.WebToApk.vibratePattern === 'function') {
window.WebToApk.vibratePattern(JSON.stringify(list));
}
}
pattern([200]); // one 200 ms buzz
pattern([100, 50, 100, 50, 300]); // short, short, long
pattern([]); // empty list stops a running vibrationيُشغَّل النمط مرة واحدة، فيكرره المنبّه بنفسه حتى يوقفه المستخدم:
var alarm = null;
var ALARM = JSON.stringify([500, 300, 500, 300, 500]); // about 2.1 s
function startAlarm() {
if (!window.WebToApk || typeof window.WebToApk.vibratePattern !== 'function') return;
window.WebToApk.vibratePattern(ALARM);
alarm = setInterval(function () { window.WebToApk.vibratePattern(ALARM); }, 3000);
}
function stopAlarm() {
if (alarm === null) return;
clearInterval(alarm);
alarm = null;
window.WebToApk.vibratePattern('[]'); // stop the buzz that is still running
}ملاحظات: الرقم الأول هو اهتزاز، ثم توقف، اهتزاز، توقف ... (بترتيب الويب). يضيف التطبيق "الانتظار" الأولي الخاص بـ Android نيابةً عنك، فلا تضع 0 في البداية بنفسك: فـ [0, 100] تعني "اهتزاز 0 مللي ثانية، توقف 100 مللي ثانية" ولن تشعر بشيء. الأرقام السالبة تُعامل كـ 0. يُشغَّل النمط مرة واحدة.
watchVolume الجسر (bridge)#
window.WebToApk.watchVolume(on: Boolean): Boolean
يشغّل أحداث `appmint:volume` (true) أو يوقفها (false).
مثال
يشغّل أحداث تغيّر الصوت المباشرة أو يوقفها: أثناء التشغيل، يصل كل تغيير في مستوى الصوت (أزرار الجهاز، شريط النظام، تطبيق آخر) إلى الصفحة كـ appmint:volume.
يُرجع: true عندما سرى التغيير. المتطلبات: لا شيء.
if (window.WebToApk && window.WebToApk.watchVolume) {
window.addEventListener('appmint:volume', function (e) {
// e.detail = { stream: 'media', current: 9, max: 15, percent: 60, muted: false }
document.getElementById('vol-' + e.detail.stream).value = e.detail.percent;
});
WebToApk.watchVolume(true);
window.addEventListener('pagehide', function () { WebToApk.watchVolume(false); });
}يصل الكائن نفسه أيضًا إلى خطّاف الصفحة، إن فضّلت ذلك:
window.onAppMintVolume = function (level) {
if (level.stream === 'alarm' && level.percent === 0) showMessage('Alarm volume is now off.');
};
WebToApk.watchVolume(true);اعرض المستوى مرة واحدة بـ getVolume، ثم أبقِه حيًا فقط بينما الشاشة ظاهرة:
if (window.WebToApk && WebToApk.watchVolume && WebToApk.getVolume) {
const meter = document.getElementById('media-meter');
meter.value = JSON.parse(WebToApk.getVolume('media')).percent;
const onVol = function (e) { if (e.detail.stream === 'media') meter.value = e.detail.percent; };
document.addEventListener('visibilitychange', function () {
if (document.hidden) { WebToApk.watchVolume(false); window.removeEventListener('appmint:volume', onVol); }
else { window.addEventListener('appmint:volume', onVol); WebToApk.watchVolume(true); }
});
}ملاحظات: حدث واحد لكل مجرى صوت تغيّر (media، alarm، ring، notification، call). أوقفه عند إغلاق الشاشة التي تعرض المستويات.