اصنع واجهتك الخاصة
ابنِ واجهات مؤشراتك الخاصة بـ HTML وCSS وJavaScript. كل واجهة تعمل مع كل مصدر، من البطارية إلى الأرقام التي ترسلها بنفسك.
بداية سريعة
- أنشئ واجهة: في الإعدادات، انقر إنشاء واجهة… (Option-Command-N). ينشئ Multimeter مجلدًا من ملفات البداية تستخدم بيانات الإصدار 2 مسبقًا.
- عدّل الملفات: يعرض Multimeter المجلد في Finder. عدّل الملفات في أي محرر شيفرة.
- شاهد التغييرات فورًا: يعيد Multimeter تحميل واجهتك في كل مرة تحفظ فيها. جرّبها على مصادر مختلفة في إضافة مؤشر… أو تخصيص هذا المؤشر….
- شاركه: اضغط المجلد في Finder، وغيّر اسم ملف .zip إلى
.multimeter، وأرسله إلى المعرض. يمكن لأي شخص إضافته عبر استيراد… (Command-O) أو بالنقر المزدوج على الملف.
كيف يعمل المؤشر
المؤشر في شريط القوائم هو واجهة ومصدر وإعدادات الشخص. الواجهة هي مجلدك: صفحة ويب صغيرة يحمّلها Multimeter في عرض شفاف ارتفاعه 22 نقطة، وعرضه بقدر width في ملف البيان. والمصدر هو ما يقيسه المؤشر، ويختاره الشخص عند إضافة المؤشر.
كلما تغيّر شيء، يضبط Multimeter قيمة window.meterData ويرسل حدث meterUpdate. لا تحتاج واجهتك إلى معرفة مصدر الأرقام: ارسم level (من 0 إلى 1) واعرض formatted، وستعمل مع المعالج والشبكة والمؤقت والبطارية على حد سواء.
بنية الملفات
كل واجهة مجلد يحتوي على:
my-meter/
├── manifest.json # name, size, which sources it's made for
├── index.html # the page Multimeter loads
├── styles.css
└── meter.js # listens for meterUpdate and drawsmanifest.json
يصف ملف البيان واجهتك، ويخبر Multimeter بعرضها والغرض الذي صُنعت له:
{
"name": "My Meter",
"description": "What it shows, in one line.",
"version": "1.0.0",
"author": "Your Name",
"apiVersion": 2,
"sources": ["any"],
"defaultSource": "cpu",
"width": 60,
"minWidth": 40,
"maxWidth": 100,
"supportsLightMode": true,
"supportsDarkMode": true
}| المفتاح | النوع | المعنى |
|---|---|---|
name | string | يظهر في قائمة الواجهات وفي المعرض. |
description | string | سطر واحد عمّا تعرضه الواجهة. |
version | string | رقم إصدارك، مثل 1.0.0. |
author | string | اسمك، ويظهر في المعرض. |
apiVersion | 2 | اضبطه على 2 للبيانات الموصوفة في هذه الصفحة. |
sources | string[] | ["any"] لواجهة تستطيع رسم أي مصدر، أو قائمة بمعرّفات المصادر مثل ["battery"] أو ["battery", "countdown", "timer"]. لا يعرض Multimeter واجهتك إلا لتلك المصادر. |
defaultSource | string | المصدر الذي يُختار عندما يضيف أحدهم واجهتك أول مرة، مثل "cpu". |
width | number | العرض بالنقاط. الارتفاع دائمًا 22. |
minWidth / maxWidth | number | أضيق وأعرض ما يمكن للشخص ضبطه في تخصيص. |
supportsLightMode / supportsDarkMode | boolean | هل الواجهة مصممة لشريط القوائم الفاتح والداكن. |
ملف البيان الذي لا يحتوي على apiVersion وsources يُعامَل كواجهة مخصصة للبطارية أولًا تعمل مع أي مصدر رغم ذلك، فتستمر المؤشرات المصنوعة للإصدارات السابقة في العمل.
بيانات المؤشر
يضع Multimeter البيانات الحالية في window.meterData ويرسلها من جديد عند كل تغيير. إليك كل ما فيها (الإصدار 2 من الواجهة البرمجية):
window.meterData = {
apiVersion: 2,
source: "cpu", // what this meter measures
sourceName: "CPU", // that source's name, translated
label: "CPU", // the meter's label ("" if the person cleared it)
value: 23.4, // raw value in `unit` (null if unavailable)
min: 0, max: 100, // the range `level` is measured against
level: 0.234, // value placed in the range, 0 to 1
formatted: "23%", // ready to show, unit included, in the person's language
unit: "%", // "%", "W", "B/s", "rpm", "s", or your own
state: "normal", // "normal", "warning" or "critical"
tint: null, // "#30D158" if the person picked a color
history: [0.21, 0.25], // up to 60 recent levels, oldest first
warningLevel: 0.7, // alert levels on the same 0 to 1 scale (or null)
criticalLevel: 0.9,
alertDirection: "above", // "above" or "below" (or null)
available: true, // false when the source can't be read right now
colorScheme: "dark", // the menu bar: "light" or "dark"
reduceMotion: false, // System Settings > Accessibility > Reduce motion
strings: { timeLeft: "left" },
battery: { // always the Mac's battery, whatever the source
level: 0.82, percentage: 82, isCharging: false, isPluggedIn: false,
hasBattery: true, timeRemaining: 312, timeToFullCharge: null,
formattedTime: "5:12", cycleCount: 212, health: 0.94, temperature: 30.5
},
// Version 1 fields, so battery meters keep working with any source:
percentage: 23, isCharging: false, isPluggedIn: false,
timeRemaining: null, timeToFullCharge: null, formattedTime: null,
cycleCount: 212, health: 0.94, temperature: 30.5, hasBattery: true
}| الحقل | المعنى |
|---|---|
source | معرّف المصدر (انظر الجدول أدناه). وsourceName اسمه المترجم. |
label | تسمية المؤشر، مثل CPU أو DOWN. يمكن للشخص تغييرها أو مسحها، لذا قد تكون نصًا فارغًا. |
value | القراءة الخام بوحدة unit، أو null. ومع min وmax تحصل على الصورة كاملة. |
level | القيمة موضوعة في النطاق من 0 إلى 1، ومحصورة فيه. معظم الواجهات لا تحتاج إلا إلى هذه. |
formatted | القراءة كنص مع الوحدة، منسقة حسب لغة الشخص: 23%، 12.4 W، 1.2 MB/s، 4:12. |
unit | %، W، B/s، rpm، s (للمؤقتات والعد التنازلي)، أو نص فارغ، أو وحدة يحددها الشخص. |
state | normal أو warning أو critical، حسب مستويات التنبيه التي ضبطها الشخص. لوّن واجهتك بناءً عليها. |
tint | لون مثل #30D158 اختاره الشخص، أو null لاستخدام ألوان واجهتك. |
history | حتى 60 مستوى حديثًا (من 0 إلى 1)، الأقدم أولًا، للرسوم البيانية. |
warningLevel | يضع warningLevel وcriticalLevel مستويات التنبيه على مقياس 0 إلى 1 نفسه الذي يستخدمه level، ويحدد alertDirection هل تنطلق التنبيهات above (فوقها) أو below (تحتها). الثلاثة تكون null إذا لم يكن للمؤشر تنبيهات. |
available | false عندما يتعذر قراءة المصدر الآن: لا توجد بطارية، أو الملحق مطفأ، أو عنوان الويب لا يستجيب. اعرض شرطة. |
colorScheme | مظهر شريط القوائم، light أو dark. يتبع الخلفية، لا إعداد النظام وحده. |
reduceMotion | true عند تشغيل تقليل الحركة. تخطَّ الحركات. |
battery | بطارية جهاز Mac، موجودة دائمًا أيًّا كان ما يقيسه المؤشر: الشحن، وقيد الشحن، والتوصيل بالكهرباء، والوقت المتبقي، والوقت حتى الامتلاء، والدورات، والصحة، ودرجة الحرارة. |
الاستماع إلى التحديثات
ارسم مرة بما هو موجود في window.meterData، ثم من جديد عند كل meterUpdate. اضبط window.meterReady = true عندما تكون جاهزًا لاستقبال البيانات.
function render(data) {
// draw the meter from data.level, data.formatted, data.state ...
}
window.addEventListener('meterUpdate', (e) => render(e.detail));
render(window.meterData || { level: 0.5, formatted: '50%', state: 'normal' });
window.meterReady = true;المصادر
هذه هي المصادر التي يمكن أن تكون للمؤشر. ترى واجهتك المعرّف في source وتحصل على formatted مكتوبًا مسبقًا، لذا نادرًا ما تحتاج إلى معاملتها بشكل مختلف.
| المصدر | source | unit | شكل formatted |
|---|---|---|---|
| البطارية | battery | "%" | 82% |
| ملحق Bluetooth | bluetooth | "%" | 64% |
| استهلاك الطاقة | power | "W" | 12.4 W |
| المعالج | cpu | "%" | 23% |
| الذاكرة | memory | "%" | 71% |
| مساحة القرص | disk | "%" | 58% |
| الضغط الحراري | thermal | "" | عادي, مقبول, مرتفع, حرج |
| سرعة المروحة* | fan | "rpm" | 2,400 rpm |
| الشبكة | network | "B/s" | 1.2 MB/s, 340 KB/s |
| المؤقت | timer | "s" | 24:51 |
| العد التنازلي | countdown | "s" | 3d 4h, 4:12, 12:05 |
| تقدّم اليوم | progress | "%" | 63% |
| القيمة المرسلة | push | "" | 42 |
| عنوان ويب | url | "" | 1,284 |
| ملف | file | "" | 12 |
| سكربت* | script | "" | 412 |
* تحتاج سرعة المروحة والسكربتات إلى إصدار التنزيل المباشر من Multimeter. لا يستطيع إصدار Mac App Store قراءة مستشعرات المروحة ولا تشغيل سكربتاتك؛ استخدم هناك قيمة مرسلة أو ملفًا بدلًا منها.
تمتد النسب المئوية دائمًا من 0 إلى 100. يتدرج استهلاك الطاقة والشبكة وسرعة المروحة حسب ذروتها الأخيرة ما لم يضبط الشخص نطاقًا. للضغط الحراري أربع درجات، لذا يكون level إما 0 أو 0.33 أو 0.67 أو 1. في المؤقتات والعد التنازلي، level هو نسبة الوقت المتبقي وvalue هو الثواني المتبقية.
التنبيهات والألوان
يمكن أن يكون لكل مؤشر مستوى تحذير ومستوى حرج يضبطهما الشخص (البطارية افتراضيًا تحت 20% و10%، والمعالج فوق 70% و90%، والقرص فوق 85% و95%). يحسب Multimeter قيمة state نيابة عنك. يجب أن تبدو الواجهة هادئة عندما تكون normal، وأن يعلو صوتها كلما انتقلت إلى warning وcritical، وأن تستخدم tint عندما يختار الشخص لونًا:
document.body.classList.remove('warning', 'critical');
if (data.state !== 'normal') document.body.classList.add(data.state);
// The person's color wins over the face's own
if (data.tint) document.body.style.setProperty('--accent', data.tint);
else document.body.style.removeProperty('--accent');body.warning { --accent: #ff9f0a; }
body.critical { --accent: #ff453a; }تريد رسم مناطق التنبيه على مقياس، مثل قرص ينتهي بالأحمر؟ استخدم warningLevel وcriticalLevel وalertDirection.
السجل
يحتوي history على ما يصل إلى 60 مستوى حديثًا، الأقدم أولًا، على مقياس 0 إلى 1 مسبقًا. أضف level الحالي إلى النهاية فيصبح لديك رسم بياني. مثال History Graph أدناه يرسم واحدًا.
تفاصيل البطارية
ما زالت البطارية مميزة. data.battery هي دائمًا بطارية جهاز Mac، أيًّا كان ما يقيسه المؤشر، لذا تستطيع أي واجهة عرض رمز الشحن. يجب أن تذكر الواجهة المصنوعة للبطارية فقط "sources": ["battery"] في ملف البيان. القيمتان timeRemaining وtimeToFullCharge بالدقائق، وتكونان null ما دام macOS يقدّر الوقت.
// A battery-only face: "sources": ["battery"] in manifest.json
const b = data.battery;
bolt.hidden = !b.isCharging;
time.textContent = b.isCharging
? (b.timeToFullCharge ? `${b.timeToFullCharge} min to full` : '')
: (b.formattedTime ?? '');الواجهات المكتوبة للإصدار 1 تقرأ percentage وisCharging وformattedTime في المستوى الأعلى. وما زالت تُرسل: في مصدر البطارية هي قيم البطارية نفسها، وفي المصادر الأخرى تكون isCharging هي false وformattedTime هو الوقت المتبقي في المؤقت أو العد التنازلي (h:mm)، وإلا فهي null.
بياناتك الخاصة
أربعة مصادر تعرض أرقامًا تقدمها أنت: قيمة مرسلة، أو عنوان ويب، أو ملف، أو سكربت. تتعامل معها واجهتك مثل أي مصدر آخر.
أرسل قيمة برابط
افتح رابط multimeter://set من أي مكان: Terminal، أو سكربت shell، أو الاختصارات (فتح عناوين URL)، أو Raycast، أو مهمة cron، أو سكربت بناء. أضف مؤشرًا بمصدر القيمة المرسلة وبالمفتاح نفسه، فيتحدّث لحظة فتح الرابط. يُبقي open -g تطبيق Multimeter في الخلفية.
# Set a value (the meter shows the "deploys" key)
open -g "multimeter://set?key=deploys&value=42"
# Range, label, unit and your own text ride along
open -g "multimeter://set?key=coffee&value=3&min=0&max=5&label=Coffee&unit=cups"
open -g "multimeter://set?key=build&value=0.8&max=1&formatted=80%25%20done"| المعامل | المعنى |
|---|---|
key | المؤشر المقصود. لا تفرّق المفاتيح بين الأحرف الكبيرة والصغيرة. |
value | الرقم. إلزامي. |
min / max | النطاق، حتى يخرج level صحيحًا. الافتراضي من 0 إلى 100. |
label | نص تسمية المؤشر. |
unit | وحدة تُضاف بعد الرقم، مثل cups. استخدم % للنسبة المئوية. |
formatted | نصك الخاص لـ formatted، ويُستخدم بدلًا من الرقم. |
القيم المرسلة تعمل في إصدار Mac App Store أيضًا. يتذكر Multimeter آخر قيمة لكل مفتاح.
عناوين الويب والملفات والسكربتات
الثلاثة تقرأ المخرجات نفسها: رقمًا عاديًا، أو JSON يحتوي على value وأي من الإضافات. كل شيء ما عدا value اختياري.
42
42.5
42%
{"value": 42, "min": 0, "max": 100, "label": "Deploys", "unit": "", "formatted": "42 left"}تشير إلى JSON أكبر، مثل استجابة API؟ أعطِ المؤشر مسار مفتاح وسيستخرج الرقم:
{"data": {"count": 17}} → key path data.count
{"items": [{"value": 9.5}]} → key path items.0.value- عنوان الويب: يُجلب كل فترة تختارها، بحد أقصى مرة كل 30 ثانية (كل 5 دقائق ما لم تغيّر ذلك).
- الملف: يُقرأ من جديد كلما تغيّر. مفيد لأي شيء يستطيع كتابة ملف.
- السكربت: أمر shell يعمل عبر
zshكل فترة تختارها (كل 30 ثانية ما لم تغيّر ذلك). يعرض Multimeter الرقم الذي يطبعه. مجلدات Homebrew موجودة فيPATH، والأمر الذي يستغرق أكثر من 10 ثوانٍ يُوقف.
# Open pull requests waiting on you (direct download version)
gh pr list --search "review-requested:@me" --json number --jq length
# Free memory pressure as a percentage
memory_pressure | awk '/percentage/ {print 100 - $5}'يستطيع إصدار Mac App Store استخدام عناوين الويب والملفات، لكن ليس السكربتات. للسكربتات هناك، اجعل سكربتك يرسل رابطًا أو يكتب ملفًا.
شريط القوائم الفاتح والداكن
يكون شريط القوائم فاتحًا أو داكنًا حسب الخلفية. يضيف Multimeter الصنف light-mode أو dark-mode إلى body، ويضبط colorScheme في البيانات، كما يطابق prefers-color-scheme شريط القوائم أيضًا. استخدم ما يناسبك:
/* Dark menu bar (the default) */
body { color: white; }
/* Light menu bar */
body.light-mode { color: black; }
/* Same thing with the media query, which follows the menu bar too */
@media (prefers-color-scheme: light) {
body { color: black; }
}تقليل الحركة
عند تشغيل تقليل الحركة، تكون reduceMotion هي true ويتطابق prefers-reduced-motion. أبقِ المؤشر مقروءًا وتخلَّ عن الارتدادات والنبضات والمسحات:
body.reduce-motion * { transition: none !important; animation: none !important; }
@media (prefers-reduced-motion: reduce) {
* { transition: none !important; animation: none !important; }
}أمثلة كاملة
واجهتان كاملتان تعملان مباشرة في هذه الصفحة عبر البيانات نفسها التي يرسلها Multimeter. انسخ الملفات إلى مجلد واستورده.
واجهة البداية من إنشاء واجهة
ما يكتبه إنشاء واجهة… بالضبط: تسمية، وشريط، والقيمة المنسقة، مع شرح الواجهة البرمجية في تعليقاتها. تلوّن نفسها حسب state، وتحترم tint، وتتبع مظهر شريط القوائم.
starter/manifest.json
{
"name": "My Face",
"description": "A label, a bar and the value. Works with any source.",
"version": "1.0.0",
"author": "Your Name",
"apiVersion": 2,
"sources": ["any"],
"defaultSource": "cpu",
"width": 70,
"minWidth": 50,
"maxWidth": 120,
"supportsLightMode": true,
"supportsDarkMode": true
}starter/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="meter">
<span id="label"></span>
<span id="track"><span id="fill"></span></span>
<span id="value">--</span>
</div>
<script src="meter.js"></script>
</body>
</html>starter/styles.css
* { margin: 0; padding: 0; box-sizing: border-box; }
/* The meter is 22 points tall and as wide as manifest.json says. */
body {
font: 600 11px/1 -apple-system, BlinkMacSystemFont, sans-serif;
font-variant-numeric: tabular-nums;
color: white; /* dark menu bar */
background: transparent;
height: 22px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
--accent: #30d158; /* replaced by the meter's color, if one is set */
}
/* Light menu bar: the system setting, or the preview's light mode. */
#track { background: rgba(255, 255, 255, 0.25); }
@media (prefers-color-scheme: light) { body { color: black; } #track { background: rgba(0, 0, 0, 0.18); } }
body.light-mode { color: black; }
body.light-mode #track { background: rgba(0, 0, 0, 0.18); }
body.dark-mode { color: white; }
body.dark-mode #track { background: rgba(255, 255, 255, 0.25); }
#meter { display: flex; align-items: center; gap: 4px; }
#label { font-size: 8px; letter-spacing: 0.04em; opacity: 0.7; }
#track { width: 18px; height: 6px; border-radius: 3px; position: relative; overflow: hidden; }
#fill { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--accent); border-radius: 3px; transition: width 0.4s ease; }
/* state is "normal", "warning" or "critical" (from the meter's alert levels). */
body.warning { --accent: #ffd60a; }
body.critical { --accent: #ff453a; }
@media (prefers-reduced-motion: reduce) { #fill { transition: none; } }starter/meter.js
// Multimeter meter API, version 2. The app sets window.meterData and fires
// a 'meterUpdate' event whenever anything changes. The fields you'll use most:
//
// level 0.0 to 1.0, the value within the meter's range
// formatted ready-to-show text with its unit: "23%", "1.2 MB/s", "4:12"
// label short label ("CPU"), may be "" if hidden
// value, unit, min, max the raw number and its range
// state "normal", "warning" or "critical"
// tint the color picked in Customize ("#30D158"), or null
// history up to 60 recent levels (0 to 1), oldest first, for graphs
// source what it measures: "battery", "cpu", "memory", "network", "timer"...
// available false when there's nothing to read (no battery, URL failing)
// battery the Mac's battery, always: level, isCharging, isPluggedIn,
// hasBattery, timeRemaining, timeToFullCharge, health...
// isCharging true only when this meter shows the battery and it's charging
// colorScheme "light" or "dark"; reduceMotion true if animations should stop
//
// Full reference: https://multimeterapp.com/creating-meters
class Meter {
constructor() {
this.label = document.getElementById('label');
this.fill = document.getElementById('fill');
this.value = document.getElementById('value');
window.addEventListener('meterUpdate', (e) => this.render(e.detail));
if (window.meterData) this.render(window.meterData);
window.meterReady = true;
}
render(data) {
const level = Math.max(0, Math.min(1, data.level || 0));
this.label.textContent = data.label || '';
this.label.style.display = data.label ? '' : 'none';
this.value.textContent = data.available === false ? '\u2013' : (data.formatted || Math.round(level * 100) + '%');
this.fill.style.width = (level * 100) + '%';
document.body.classList.toggle('warning', data.state === 'warning');
document.body.classList.toggle('critical', data.state === 'critical');
if (data.tint) document.body.style.setProperty('--accent', data.tint);
else document.body.style.removeProperty('--accent');
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => new Meter());
} else {
new Meter();
}رسم السجل
رسم خطي لآخر دقيقة من history، مرسوم على canvas بدقة الشاشة الحقيقية.
history-graph/manifest.json
{
"name": "History Graph",
"description": "The last minute as a little line graph.",
"version": "1.0.0",
"author": "Your Name",
"apiVersion": 2,
"sources": ["any"],
"defaultSource": "network",
"width": 44,
"minWidth": 30,
"maxWidth": 80,
"supportsLightMode": true,
"supportsDarkMode": true
}history-graph/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
html, body { margin: 0; height: 22px; background: transparent; overflow: hidden; }
canvas { display: block; width: 100%; height: 22px; }
</style>
</head>
<body>
<canvas id="graph"></canvas>
<script src="meter.js"></script>
</body>
</html>history-graph/meter.js
const canvas = document.getElementById('graph');
const ctx = canvas.getContext('2d');
function render(data) {
// Draw at the screen's real resolution so the line stays sharp
const scale = window.devicePixelRatio || 1;
const w = canvas.clientWidth, h = 22;
canvas.width = w * scale;
canvas.height = h * scale;
ctx.setTransform(scale, 0, 0, scale, 0, 0);
ctx.clearRect(0, 0, w, h);
const points = (data.history || []).concat(data.level ?? 0);
if (points.length < 2) return;
const dark = data.colorScheme !== 'light';
const color = data.tint
|| (data.state === 'critical' ? '#ff453a' : data.state === 'warning' ? '#ff9f0a' : dark ? '#fff' : '#1d1d1f');
const x = (i) => (i / (points.length - 1)) * (w - 2) + 1;
const y = (v) => h - 3 - v * (h - 6);
// Soft fill under the line, then the line
ctx.beginPath();
points.forEach((v, i) => (i ? ctx.lineTo(x(i), y(v)) : ctx.moveTo(x(i), y(v))));
ctx.lineTo(x(points.length - 1), h);
ctx.lineTo(x(0), h);
ctx.closePath();
ctx.globalAlpha = 0.22;
ctx.fillStyle = color;
ctx.fill();
ctx.globalAlpha = 1;
ctx.beginPath();
points.forEach((v, i) => (i ? ctx.lineTo(x(i), y(v)) : ctx.moveTo(x(i), y(v))));
ctx.strokeStyle = color;
ctx.lineWidth = 1.5;
ctx.lineJoin = 'round';
ctx.stroke();
}
window.addEventListener('meterUpdate', (e) => render(e.detail));
render(window.meterData || { history: [0.2, 0.4, 0.3, 0.6, 0.5], level: 0.7 });
window.meterReady = true;نصائح للاختبار
- أبقِ كل شيء ضمن ارتفاع 22 نقطة، وافحص واجهتك عند
minWidthوmaxWidth. - استخدم خط النظام (
-apple-system) وfont-variant-numeric: tabular-numsحتى لا تهتز الأرقام. - جرّب واجهتك مع عدة مصادر في إضافة مؤشر… وتخصيص هذا المؤشر…: نسبة مئوية، وسرعة الشبكة، ومؤقت، ومصدر غير متاح.
- افحص شريط القوائم الفاتح والداكن، ولونًا مخصصًا، وحالتي التحذير والحرج.
- تظهر أخطاء JavaScript في Console.app. يمكنك أيضًا فتح
index.htmlفي Safari وإرسال البيانات إليه من وحدة التحكم: - أبقِ الملفات صغيرة وتجنّب طلبات الشبكة، حتى تُرسم الواجهة فورًا.
// Paste in Safari's console with your index.html open to try a value
window.meterData = { level: 0.92, formatted: '92%', label: 'CPU', state: 'critical',
available: true, colorScheme: 'dark', history: [] };
window.dispatchEvent(new CustomEvent('meterUpdate', { detail: window.meterData }));مستعد للإنشاء؟
$19.99 دفعة واحدة. بلا اشتراك. استرداد خلال 30 يومًا.
اشترِ مقابل $19.99