v0.22.0 — Health checks editor : icon picker + per-check refresh

Settings → Avancés → Bandeau de santé : liste éditable des checks (Add /
Edit / Delete) avec dialog modal pour chaque entry. Picker d'emoji parmi
28 icônes curatées (VR / streaming / réseau / système). Édition du nom,
type (Process / Ping), cible, intervalle de refresh en ms (per-check),
et seuils Ping (warn / error / timeout) sous une section Avancé.

La config est persistée dans %LocalAppData%\PSLauncher\config.json donc
elle survit aux auto-updates du launcher. Modifiable aussi à la main
dans le json pour les power-users.

Le bandeau hot-reload après Save : cancel des boucles de polling
existantes, reconstruction des HealthIndicators depuis la config fraîche,
puis relance d'une boucle dédiée par check (chacune cadencée sur son
propre RefreshIntervalMs — Process check rapide peut tourner à 1 s,
Ping reste à 5-10 s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 19:09:39 +02:00
parent 741e30b7ae
commit 211af9dd85
9 changed files with 794 additions and 30 deletions

View File

@@ -946,6 +946,109 @@ public static class Strings
$"تاريخ الإصدار: {date} • {size}"
);
// ==================== HEALTH BANNER ====================
public static string SettingsHealthChecks => T(
"BANDEAU DE SANTÉ SYSTÈME",
"SYSTEM HEALTH BANNER",
"系统健康状态栏",
"แถบสถานะระบบ",
"شريط حالة النظام"
);
public static string SettingsHealthChecksHint => T(
"Pings et processus surveillés sous la top bar (Library uniquement). Édité ici, sauvegardé dans config.json — survit à un auto-update.",
"Pings and processes monitored below the top bar (Library only). Edited here, saved to config.json — survives auto-updates.",
"在顶部栏下监控的 Ping 和进程(仅库视图)。在此编辑,保存到 config.json — 在自动更新后保留。",
"Ping และโปรเซสที่ติดตามใต้แถบบนสุด (เฉพาะ Library) แก้ไขที่นี่ บันทึกใน config.json — คงอยู่หลังการอัปเดตอัตโนมัติ",
"Ping والعمليات المراقَبة أسفل الشريط العلوي (المكتبة فقط). يُحرَّر هنا، ويُحفَظ في config.json — يبقى بعد التحديث التلقائي."
);
public static string SettingsHealthAdd => T(" Ajouter", " Add", " 添加", " เพิ่ม", " إضافة");
public static string SettingsHealthEdit => T("✎ Éditer", "✎ Edit", "✎ 编辑", "✎ แก้ไข", "✎ تحرير");
public static string SettingsHealthDelete => T("🗑 Supprimer", "🗑 Delete", "🗑 删除", "🗑 ลบ", "🗑 حذف");
public static string SettingsHealthEmpty => T(
"Aucun check configuré. Le bandeau ne s'affichera pas tant qu'aucune entrée n'aura été ajoutée.",
"No checks configured. The banner stays hidden until at least one entry is added.",
"未配置任何检查。在添加至少一项之前,状态栏将保持隐藏。",
"ยังไม่มีการตรวจสอบที่ตั้งค่าไว้ แถบจะถูกซ่อนจนกว่าจะมีการเพิ่มอย่างน้อยหนึ่งรายการ",
"لم يُهيَّأ أي فحص. سيبقى الشريط مخفياً حتى تتم إضافة إدخال واحد على الأقل."
);
public static string SettingsHealthDeleteConfirm(string name) => T(
$"Supprimer le check « {name} » ?",
$"Delete check « {name} »?",
$"删除检查 \"{name}\"",
$"ลบการตรวจสอบ « {name} »?",
$"حذف الفحص « {name} »؟"
);
public static string HealthEditorTitle => T("Éditer le check", "Edit check", "编辑检查", "แก้ไขการตรวจสอบ", "تحرير الفحص");
public static string HealthEditorTitleNew => T("Nouveau check", "New check", "新建检查", "การตรวจสอบใหม่", "فحص جديد");
public static string HealthEditorName => T("NOM", "NAME", "名称", "ชื่อ", "الاسم");
public static string HealthEditorNameHint => T(
"Libellé court affiché dans la pill du bandeau, ex. « SteamVR ».",
"Short label shown in the banner pill, e.g. \"SteamVR\".",
"状态栏胶囊中显示的简短标签,例如 \"SteamVR\"。",
"ชื่อย่อที่แสดงในป้ายของแถบ เช่น \"SteamVR\"",
"تسمية قصيرة تظهر في الشريط، مثل \"SteamVR\"."
);
public static string HealthEditorKind => T("TYPE DE VÉRIFICATION", "CHECK TYPE", "检查类型", "ประเภทการตรวจสอบ", "نوع الفحص");
public static string HealthEditorKindProcess => T("Processus (Windows)", "Process (Windows)", "进程 (Windows)", "โปรเซส (Windows)", "عملية (Windows)");
public static string HealthEditorKindPing => T("Ping (réseau ICMP)", "Ping (ICMP network)", "Ping (ICMP 网络)", "Ping (เครือข่าย ICMP)", "Ping (شبكة ICMP)");
public static string HealthEditorTargetProcess => T("CIBLE — NOM DE PROCESSUS", "TARGET — PROCESS NAME", "目标 — 进程名", "เป้าหมาย — ชื่อโปรเซส", "الهدف — اسم العملية");
public static string HealthEditorTargetPing => T("CIBLE — IP OU HOSTNAME", "TARGET — IP OR HOSTNAME", "目标 — IP 或主机名", "เป้าหมาย — IP หรือชื่อโฮสต์", "الهدف — IP أو اسم المضيف");
public static string HealthEditorTargetProcessHint => T(
"Nom de l'exécutable sans .exe, ex. « vrserver » ou « HtcConnectionUtility ». Insensible à la casse.",
"Executable name without .exe, e.g. \"vrserver\" or \"HtcConnectionUtility\". Case-insensitive.",
"可执行文件名(不含 .exe例如 \"vrserver\" 或 \"HtcConnectionUtility\"。不区分大小写。",
"ชื่อไฟล์ปฏิบัติการโดยไม่มี .exe เช่น \"vrserver\" หรือ \"HtcConnectionUtility\" ไม่คำนึงถึงตัวพิมพ์",
"اسم الملف التنفيذي بدون .exe، مثل \"vrserver\" أو \"HtcConnectionUtility\". غير حساس لحالة الأحرف."
);
public static string HealthEditorTargetPingHint => T(
"Adresse IP (ex. 192.168.1.42) ou hostname résolvable. Vide = check ignoré (statut Inconnu).",
"IP address (e.g. 192.168.1.42) or resolvable hostname. Empty = check skipped (Unknown status).",
"IP 地址(例如 192.168.1.42)或可解析的主机名。空 = 跳过检查(未知状态)。",
"ที่อยู่ IP (เช่น 192.168.1.42) หรือชื่อโฮสต์ที่แก้ได้ ว่างเปล่า = ข้ามการตรวจสอบ (สถานะไม่ทราบ)",
"عنوان IP (مثل 192.168.1.42) أو اسم مضيف قابل للحل. فارغ = تخطّي الفحص (الحالة غير معروفة)."
);
public static string HealthEditorRefresh => T("INTERVALLE DE RAFRAÎCHISSEMENT", "REFRESH INTERVAL", "刷新间隔", "ช่วงเวลารีเฟรช", "فاصل التحديث");
public static string HealthEditorRefreshHint => T(
"Délai entre 2 vérifications, en millisecondes. Process ~1 ms (1000 OK) ; Ping = round-trip réseau (5000-10000 conseillé). Min 200 ms.",
"Delay between 2 checks, in milliseconds. Process ~1 ms (1000 OK); Ping = network round-trip (5000-10000 recommended). Min 200 ms.",
"两次检查之间的延迟(毫秒)。进程约 1 毫秒1000 即可Ping = 网络往返(建议 5000-10000。最小 200 毫秒。",
"ระยะเวลาระหว่าง 2 การตรวจสอบเป็นมิลลิวินาที โปรเซส ~1 ms (1000 OK); Ping = round-trip เครือข่าย (แนะนำ 5000-10000). ขั้นต่ำ 200 ms.",
"التأخير بين فحصين بالمللي ثانية. عملية ~1 ms (1000 جيدة)؛ Ping = ذهاب وعودة الشبكة (يوصى 5000-10000). الحد الأدنى 200 ms."
);
public static string HealthEditorIcon => T("PICTOGRAMME", "ICON", "图标", "ไอคอน", "أيقونة");
public static string HealthEditorIconHint => T(
"Affiché à gauche du nom dans la pill. Choisis-en un dans la liste.",
"Displayed to the left of the name in the pill. Pick one from the list.",
"显示在胶囊中名称的左侧。从列表中选择一个。",
"แสดงทางซ้ายของชื่อในป้าย เลือกหนึ่งจากรายการ",
"تُعرض على يسار الاسم في الشارة. اختر واحدةً من القائمة."
);
public static string HealthEditorPingAdvanced => T(
"Avancé — seuils Ping",
"Advanced — Ping thresholds",
"高级 — Ping 阈值",
"ขั้นสูง — เกณฑ์ Ping",
"متقدم — حدود Ping"
);
public static string HealthEditorPingWarn => T("Warning ms — RTT au-dessus = orange", "Warning ms — RTT above = amber", "警告 ms — 高于此值 = 橙色", "Warning ms — RTT เกินค่านี้ = ส้ม", "تحذير ms — RTT فوق ذلك = برتقالي");
public static string HealthEditorPingError => T("Error ms — RTT au-dessus = rouge", "Error ms — RTT above = red", "错误 ms — 高于此值 = 红色", "Error ms — RTT เกินค่านี้ = แดง", "خطأ ms — RTT فوق ذلك = أحمر");
public static string HealthEditorPingTimeout => T("Timeout ms — abandon de la requête", "Timeout ms — abort the request", "超时 ms — 中止请求", "Timeout ms — ยกเลิกคำขอ", "مهلة ms — إلغاء الطلب");
public static string HealthEditorErrorName => T(
"Le nom est requis.",
"Name is required.",
"需要名称。",
"ต้องระบุชื่อ",
"الاسم مطلوب."
);
public static string HealthEditorErrorRefresh => T(
"Intervalle invalide. Saisis un entier ≥ 200 (millisecondes).",
"Invalid interval. Enter an integer ≥ 200 (milliseconds).",
"间隔无效。请输入 ≥ 200 的整数(毫秒)。",
"ช่วงเวลาไม่ถูกต้อง ใส่จำนวนเต็ม ≥ 200 (มิลลิวินาที)",
"فاصل غير صالح. أدخل عدداً صحيحاً ≥ 200 (مللي ثانية)."
);
// ==================== COPYRIGHT ====================
public static string Copyright => T(
"© 2026 ASTERION VR — Tous droits réservés",