mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Added anonymous telemetry
This commit is contained in:
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Kernel:",
|
||||
"system-loading": "Systeminformationen werden geladen...",
|
||||
"system-memory": "Speicher",
|
||||
"system-monitor": "Monitor:",
|
||||
"system-not-installed": "fastfetch ist nicht installiert",
|
||||
"system-os": "Betriebssystem:",
|
||||
"system-packages": "Pakete:",
|
||||
"system-title": "Systeminformationen",
|
||||
"system-uptime": "Betriebszeit:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Telemetriedaten in die Zwischenablage kopiert",
|
||||
"telemetry-desc": "Helfen Sie mit, Noctalia zu verbessern, indem Sie beim Start vollständig anonyme Systeminformationen senden.",
|
||||
"telemetry-enabled": "Anonyme Systeminformationen senden",
|
||||
"telemetry-show-data": "Daten anzeigen",
|
||||
"telemetry-title": "Datenschutz",
|
||||
"title": "Über",
|
||||
"up-to-date": "Auf dem neuesten Stand!",
|
||||
"update-available": "Update verfügbar",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Kernel:",
|
||||
"system-loading": "Loading system info...",
|
||||
"system-memory": "Memory:",
|
||||
"system-monitor": "Monitor:",
|
||||
"system-not-installed": "fastfetch is not installed",
|
||||
"system-os": "OS:",
|
||||
"system-packages": "Packages:",
|
||||
"system-title": "System Information",
|
||||
"system-uptime": "Uptime:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Telemetry data copied to clipboard",
|
||||
"telemetry-desc": "Help improve Noctalia by sending completely anonymous system information on startup.",
|
||||
"telemetry-enabled": "Send anonymous system information",
|
||||
"telemetry-show-data": "View data",
|
||||
"telemetry-title": "Privacy",
|
||||
"title": "About",
|
||||
"up-to-date": "You're up to date!",
|
||||
"update-available": "Update available",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Núcleo:",
|
||||
"system-loading": "Cargando información del sistema...",
|
||||
"system-memory": "Memoria:",
|
||||
"system-monitor": "Monitor:",
|
||||
"system-not-installed": "fastfetch no está instalado",
|
||||
"system-os": "SO:",
|
||||
"system-packages": "Paquetes:",
|
||||
"system-title": "Información del sistema",
|
||||
"system-uptime": "Tiempo de actividad:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Datos de telemetría copiados al portapapeles",
|
||||
"telemetry-desc": "Ayuda a mejorar Noctalia enviando información del sistema completamente anónima al inicio.",
|
||||
"telemetry-enabled": "Enviar información anónima del sistema",
|
||||
"telemetry-show-data": "Ver datos",
|
||||
"telemetry-title": "Privacidad",
|
||||
"title": "Acerca de",
|
||||
"up-to-date": "¡Estás al día!",
|
||||
"update-available": "Actualización disponible",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Noyau :",
|
||||
"system-loading": "Chargement des informations système...",
|
||||
"system-memory": "Mémoire :",
|
||||
"system-monitor": "Moniteur",
|
||||
"system-not-installed": "fastfetch n'est pas installé",
|
||||
"system-os": "Système d'exploitation :",
|
||||
"system-packages": "Paquets :",
|
||||
"system-title": "Informations système",
|
||||
"system-uptime": "Temps de disponibilité :",
|
||||
"system-wm": "WM :",
|
||||
"telemetry-data-copied": "Données de télémétrie copiées dans le presse-papiers",
|
||||
"telemetry-desc": "Aidez à améliorer Noctalia en envoyant des informations système complètement anonymes au démarrage.",
|
||||
"telemetry-enabled": "Envoyer des informations système anonymes",
|
||||
"telemetry-show-data": "Afficher les données",
|
||||
"telemetry-title": "Confidentialité",
|
||||
"title": "À propos",
|
||||
"up-to-date": "Vous êtes à jour !",
|
||||
"update-available": "Mise à jour disponible",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Kernel:",
|
||||
"system-loading": "Rendszerinformációk betöltése...",
|
||||
"system-memory": "Memória:",
|
||||
"system-monitor": "Monitor:",
|
||||
"system-not-installed": "A fastfetch nincs telepítve",
|
||||
"system-os": "Operációs rendszer:",
|
||||
"system-packages": "Csomagok:",
|
||||
"system-title": "Rendszerinformációk",
|
||||
"system-uptime": "Üzemidő:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Telemetriai adatok a vágólapra másolva",
|
||||
"telemetry-desc": "Segíts fejleszteni a Noctaliát azzal, hogy teljesen anonim rendszerinformációkat küldesz indításkor.",
|
||||
"telemetry-enabled": "Névtelen rendszerinformációk küldése",
|
||||
"telemetry-show-data": "Adatok megtekintése",
|
||||
"telemetry-title": "Adatvédelem",
|
||||
"title": "Névjegy",
|
||||
"up-to-date": "Naprakész vagy!",
|
||||
"update-available": "Frissítés elérhető",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "カーネル",
|
||||
"system-loading": "システム情報を読み込み中...",
|
||||
"system-memory": "記憶",
|
||||
"system-monitor": "モニター",
|
||||
"system-not-installed": "fastfetch がインストールされていません",
|
||||
"system-os": "OS:",
|
||||
"system-packages": "パッケージ:",
|
||||
"system-title": "システム情報",
|
||||
"system-uptime": "稼働時間:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "テレメトリーデータをクリップボードにコピーしました。",
|
||||
"telemetry-desc": "起動時に完全に匿名化されたシステム情報を送信して、Noctaliaの改善にご協力ください。",
|
||||
"telemetry-enabled": "匿名でシステム情報を送信する",
|
||||
"telemetry-show-data": "データの表示",
|
||||
"telemetry-title": "プライバシー",
|
||||
"title": "バージョン情報",
|
||||
"up-to-date": "最新の状態です!",
|
||||
"update-available": "アップデートがあります",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Kernel:",
|
||||
"system-loading": "Agahiyên pergalê bar dikin...",
|
||||
"system-memory": "Bîr:",
|
||||
"system-monitor": "Çavdêr:",
|
||||
"system-not-installed": "fastfetch nehatiye sazkirin",
|
||||
"system-os": "OS: OS",
|
||||
"system-packages": "Pakkêtan:",
|
||||
"system-title": "Agahiyên Sîstemê",
|
||||
"system-uptime": "Demdirêjî:",
|
||||
"system-wm": "WM: WM:",
|
||||
"telemetry-data-copied": "Daneyên telemetriyê hatin kopîkirin bo clipboardê",
|
||||
"telemetry-desc": "Alîkariya baştirkirina Noctalia bi şandina agahiyên pergalê yên bi tevahî anonîm di destpêkê de.",
|
||||
"telemetry-enabled": "Agahiyên pergalê yên nenas bişîne",
|
||||
"telemetry-show-data": "Dîtina daneyan",
|
||||
"telemetry-title": "Nepênî",
|
||||
"title": "Derbar",
|
||||
"up-to-date": "Tu nû ye!",
|
||||
"update-available": "Nûvekirin heye",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Kernel:",
|
||||
"system-loading": "Systeeminformatie laden...",
|
||||
"system-memory": "Geheugen:",
|
||||
"system-monitor": "Monitor:",
|
||||
"system-not-installed": "fastfetch is niet geïnstalleerd",
|
||||
"system-os": "Besturingssysteem:",
|
||||
"system-packages": "Pakketten:",
|
||||
"system-title": "Systeeminformatie",
|
||||
"system-uptime": "Uptime:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Telemetriegegevens gekopieerd naar klembord",
|
||||
"telemetry-desc": "Help Noctalia te verbeteren door bij het opstarten volledig anonieme systeeminformatie te verzenden.",
|
||||
"telemetry-enabled": "Anonieme systeeminformatie verzenden",
|
||||
"telemetry-show-data": "Gegevens bekijken",
|
||||
"telemetry-title": "Privacy",
|
||||
"title": "Over",
|
||||
"up-to-date": "Je bent up-to-date!",
|
||||
"update-available": "Update beschikbaar",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Jądro:",
|
||||
"system-loading": "Ładowanie informacji o systemie...",
|
||||
"system-memory": "Pamięć:",
|
||||
"system-monitor": "Monitor: Monitor",
|
||||
"system-not-installed": "fastfetch nie jest zainstalowany",
|
||||
"system-os": "System operacyjny:",
|
||||
"system-packages": "Paczki:",
|
||||
"system-title": "Informacje o systemie",
|
||||
"system-uptime": "Czas pracy:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Dane telemetryczne skopiowane do schowka.",
|
||||
"telemetry-desc": "Pomóż ulepszyć Noctalię, wysyłając całkowicie anonimowe informacje o systemie podczas uruchamiania.",
|
||||
"telemetry-enabled": "Wyślij anonimowe informacje o systemie.",
|
||||
"telemetry-show-data": "Wyświetl dane",
|
||||
"telemetry-title": "Prywatność",
|
||||
"title": "O programie",
|
||||
"up-to-date": "Jesteś na bieżąco!",
|
||||
"update-available": "Dostępna aktualizacja",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Kernel:",
|
||||
"system-loading": "Carregando informações do sistema...",
|
||||
"system-memory": "Memória:",
|
||||
"system-monitor": "Monitor:",
|
||||
"system-not-installed": "fastfetch não está instalado",
|
||||
"system-os": "SO:",
|
||||
"system-packages": "Pacotes:",
|
||||
"system-title": "Informações do Sistema",
|
||||
"system-uptime": "Tempo de atividade:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Dados de telemetria copiados para a área de transferência.",
|
||||
"telemetry-desc": "Ajude a melhorar o Noctalia enviando informações de sistema completamente anônimas na inicialização.",
|
||||
"telemetry-enabled": "Enviar informações anônimas do sistema",
|
||||
"telemetry-show-data": "Visualizar dados",
|
||||
"telemetry-title": "Privacidade",
|
||||
"title": "Sobre",
|
||||
"up-to-date": "Você está atualizado!",
|
||||
"update-available": "Atualização disponível",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Ядро:",
|
||||
"system-loading": "Загрузка системной информации...",
|
||||
"system-memory": "Память:",
|
||||
"system-monitor": "Монитор",
|
||||
"system-not-installed": "fastfetch не установлен",
|
||||
"system-os": "ОС:",
|
||||
"system-packages": "Пакеты:",
|
||||
"system-title": "Системная информация",
|
||||
"system-uptime": "Время работы:",
|
||||
"system-wm": "ВМ:",
|
||||
"telemetry-data-copied": "Данные телеметрии скопированы в буфер обмена.",
|
||||
"telemetry-desc": "Помогите улучшить Noctalia, отправляя полностью анонимную системную информацию при запуске.",
|
||||
"telemetry-enabled": "Отправить анонимную системную информацию",
|
||||
"telemetry-show-data": "Просмотр данных",
|
||||
"telemetry-title": "Конфиденциальность",
|
||||
"title": "О программе",
|
||||
"up-to-date": "У вас всё актуально!",
|
||||
"update-available": "Доступно обновление",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Çekirdek:",
|
||||
"system-loading": "Sistem bilgileri yükleniyor...",
|
||||
"system-memory": "Hafıza:",
|
||||
"system-monitor": "Monitör",
|
||||
"system-not-installed": "fastfetch kurulu değil",
|
||||
"system-os": "İşletim sistemi:",
|
||||
"system-packages": "Paketler:",
|
||||
"system-title": "Sistem Bilgisi",
|
||||
"system-uptime": "Çalışma süresi:",
|
||||
"system-wm": "WM:",
|
||||
"telemetry-data-copied": "Telemetri verileri panoya kopyalandı.",
|
||||
"telemetry-desc": "Noctalia'yı başlatılırken tamamen anonim sistem bilgileri göndererek geliştirmeye yardımcı olun.",
|
||||
"telemetry-enabled": "Anonim sistem bilgisi gönder.",
|
||||
"telemetry-show-data": "Verileri görüntüle",
|
||||
"telemetry-title": "Gizlilik",
|
||||
"title": "Hakkında",
|
||||
"up-to-date": "Güncelsiniz!",
|
||||
"update-available": "Güncelleme mevcut",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "Ядро:",
|
||||
"system-loading": "Завантаження системної інформації...",
|
||||
"system-memory": "Пам'ять:",
|
||||
"system-monitor": "Монітор:",
|
||||
"system-not-installed": "fastfetch не встановлено",
|
||||
"system-os": "ОС:",
|
||||
"system-packages": "Пакунки:",
|
||||
"system-title": "Інформація про систему",
|
||||
"system-uptime": "Час безперебійної роботи:",
|
||||
"system-wm": "WM:\nВМ:",
|
||||
"telemetry-data-copied": "Дані телеметрії скопійовано до буфера обміну",
|
||||
"telemetry-desc": "Допоможіть покращити Noctalia, надсилаючи повністю анонімну системну інформацію під час запуску.",
|
||||
"telemetry-enabled": "Відправити анонімну системну інформацію",
|
||||
"telemetry-show-data": "Перегляд даних",
|
||||
"telemetry-title": "Конфіденційність",
|
||||
"title": "Про Noctalia",
|
||||
"up-to-date": "У вас остання версія!",
|
||||
"update-available": "Доступне оновлення",
|
||||
|
||||
@@ -609,12 +609,18 @@
|
||||
"system-kernel": "内核:",
|
||||
"system-loading": "正在加载系统信息...",
|
||||
"system-memory": "内存:",
|
||||
"system-monitor": "监视器",
|
||||
"system-not-installed": "未安装 fastfetch",
|
||||
"system-os": "操作系统:",
|
||||
"system-packages": "软件包:",
|
||||
"system-title": "系统信息",
|
||||
"system-uptime": "正常运行时间:",
|
||||
"system-wm": "窗口管理器:",
|
||||
"telemetry-data-copied": "遥测数据已复制到剪贴板",
|
||||
"telemetry-desc": "启动时发送完全匿名的系统信息,以帮助改进 Noctalia。",
|
||||
"telemetry-enabled": "发送匿名系统信息",
|
||||
"telemetry-show-data": "查看数据",
|
||||
"telemetry-title": "隐私",
|
||||
"title": "关于",
|
||||
"up-to-date": "您已是最新版本!",
|
||||
"update-available": "有可用更新",
|
||||
|
||||
@@ -81,7 +81,8 @@
|
||||
"shadowOffsetY": 3,
|
||||
"language": "",
|
||||
"allowPanelsOnScreenWithoutBar": true,
|
||||
"showChangelogOnStartup": true
|
||||
"showChangelogOnStartup": true,
|
||||
"telemetryEnabled": true
|
||||
},
|
||||
"ui": {
|
||||
"fontDefault": "",
|
||||
|
||||
@@ -281,6 +281,7 @@ Singleton {
|
||||
property string language: ""
|
||||
property bool allowPanelsOnScreenWithoutBar: true
|
||||
property bool showChangelogOnStartup: true
|
||||
property bool telemetryEnabled: true
|
||||
}
|
||||
|
||||
// ui
|
||||
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Services.Compositor
|
||||
import qs.Services.Noctalia
|
||||
import qs.Services.System
|
||||
import qs.Services.UI
|
||||
@@ -17,6 +18,7 @@ ColumnLayout {
|
||||
property string commitInfo: ""
|
||||
|
||||
readonly property bool isGitVersion: root.currentVersion.endsWith("-git")
|
||||
readonly property int giga: (1024 * 1024 * 1024)
|
||||
|
||||
// Update status: compare versions (strip -git suffix for comparison)
|
||||
readonly property string installedBase: root.currentVersion.replace("-git", "")
|
||||
@@ -44,10 +46,63 @@ ColumnLayout {
|
||||
return root.systemInfo.find(m => m.type === type);
|
||||
}
|
||||
|
||||
function getMonitorsText(separator) {
|
||||
const sep = separator || "\n";
|
||||
const screens = Quickshell.screens || [];
|
||||
const scales = CompositorService.displayScales || {};
|
||||
let lines = [];
|
||||
for (let i = 0; i < screens.length; i++) {
|
||||
const screen = screens[i];
|
||||
const name = screen.name || "Unknown";
|
||||
const scaleData = scales[name];
|
||||
const scaleValue = (typeof scaleData === "object" && scaleData !== null) ? (scaleData.scale || 1.0) : (scaleData || 1.0);
|
||||
lines.push(name + ": " + screen.width + "x" + screen.height + " @ " + scaleValue + "x");
|
||||
}
|
||||
return lines.join(sep);
|
||||
}
|
||||
|
||||
function getTelemetryPayload() {
|
||||
const screens = Quickshell.screens || [];
|
||||
const scales = CompositorService.displayScales || {};
|
||||
const monitors = [];
|
||||
for (let i = 0; i < screens.length; i++) {
|
||||
const screen = screens[i];
|
||||
const name = screen.name || "Unknown";
|
||||
const scaleData = scales[name];
|
||||
const scaleValue = (typeof scaleData === "object" && scaleData !== null) ? (scaleData.scale || 1.0) : (scaleData || 1.0);
|
||||
monitors.push({
|
||||
width: screen.width || 0,
|
||||
height: screen.height || 0,
|
||||
scale: scaleValue
|
||||
});
|
||||
}
|
||||
return {
|
||||
instanceId: TelemetryService.getInstanceId(),
|
||||
version: UpdateService.currentVersion,
|
||||
compositor: CompositorService.isHyprland ? "Hyprland" : CompositorService.isNiri ? "Niri" : CompositorService.isSway ? "Sway" : CompositorService.isMango ? "MangoWC" : CompositorService.isLabwc ? "LabWC" : "Unknown",
|
||||
os: HostService.osPretty || "Unknown",
|
||||
ramGb: Math.round((root.getModule("Memory")?.result?.total || 0) / root.giga),
|
||||
monitors: monitors,
|
||||
ui: {
|
||||
scaleRatio: Settings.data.general.scaleRatio,
|
||||
fontDefault: Settings.data.ui.fontDefault || "default",
|
||||
fontDefaultScale: Settings.data.ui.fontDefaultScale,
|
||||
fontFixed: Settings.data.ui.fontFixed || "default",
|
||||
fontFixedScale: Settings.data.ui.fontFixedScale
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function copyTelemetryData() {
|
||||
const payload = getTelemetryPayload();
|
||||
const json = JSON.stringify(payload, null, 2);
|
||||
Quickshell.execDetached(["wl-copy", json]);
|
||||
ToastService.showNotice(I18n.tr("panels.about.telemetry-title"), I18n.tr("panels.about.telemetry-data-copied"));
|
||||
}
|
||||
|
||||
function copyInfoToClipboard() {
|
||||
let info = "Noctalia Shell\n";
|
||||
info += "==============\n";
|
||||
info += "Latest version: " + root.latestVersion + "\n";
|
||||
info += "Installed version: " + root.currentVersion + "\n";
|
||||
if (root.isGitVersion && root.commitInfo) {
|
||||
info += "Git commit: " + root.commitInfo + "\n";
|
||||
@@ -70,12 +125,21 @@ ColumnLayout {
|
||||
info += "GPU: " + gpu.result.map(g => g.name || "Unknown").join(", ") + "\n";
|
||||
}
|
||||
if (mem?.result) {
|
||||
info += "Memory: " + root.formatBytes(mem.result.total) + "\n";
|
||||
info += "Memory: " + SystemStatService.formatMemoryGb(mem.result.total / root.giga) + "\n";
|
||||
}
|
||||
if (wm?.result) {
|
||||
info += "WM: " + (wm.result.prettyName || wm.result.processName || "N/A") + "\n";
|
||||
}
|
||||
}
|
||||
const monitors = getMonitorsText("\n").split("\n");
|
||||
for (const mon of monitors) {
|
||||
info += "Monitor: " + mon + "\n";
|
||||
}
|
||||
info += "\nSettings\n";
|
||||
info += "========\n";
|
||||
info += "UI Scale: " + Settings.data.general.scaleRatio + "\n";
|
||||
info += "Default Font: " + (Settings.data.ui.fontDefault || "default") + " @ " + Settings.data.ui.fontDefaultScale + "x\n";
|
||||
info += "Fixed Font: " + (Settings.data.ui.fontFixed || "default") + " @ " + Settings.data.ui.fontFixedScale + "x\n";
|
||||
Quickshell.execDetached(["wl-copy", info]);
|
||||
ToastService.showNotice(I18n.tr("panels.about.title"), I18n.tr("panels.about.info-copied"));
|
||||
}
|
||||
@@ -567,9 +631,8 @@ ColumnLayout {
|
||||
const mem = root.getModule("Memory");
|
||||
if (!mem?.result)
|
||||
return "N/A";
|
||||
const giga = (1024 * 1024 * 1024);
|
||||
const used = SystemStatService.formatMemoryGb(mem.result.used / giga);
|
||||
const total = SystemStatService.formatMemoryGb(mem.result.total / giga);
|
||||
const used = SystemStatService.formatMemoryGb(mem.result.used / root.giga);
|
||||
const total = SystemStatService.formatMemoryGb(mem.result.total / root.giga);
|
||||
return used + " / " + total;
|
||||
}
|
||||
color: Color.mOnSurface
|
||||
@@ -590,9 +653,8 @@ ColumnLayout {
|
||||
const rootDisk = disk.result.find(d => d.mountpoint === "/");
|
||||
if (!rootDisk?.bytes)
|
||||
return "N/A";
|
||||
const giga = (1024 * 1024 * 1024);
|
||||
const used = SystemStatService.formatMemoryGb(rootDisk.bytes.used / giga);
|
||||
const total = SystemStatService.formatMemoryGb(rootDisk.bytes.total / giga);
|
||||
const used = SystemStatService.formatMemoryGb(rootDisk.bytes.used / root.giga);
|
||||
const total = SystemStatService.formatMemoryGb(rootDisk.bytes.total / root.giga);
|
||||
return used + " / " + total + " (" + rootDisk.filesystem + ")";
|
||||
}
|
||||
color: Color.mOnSurface
|
||||
@@ -663,5 +725,54 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
// Monitors (2 items per screen: label + value)
|
||||
Repeater {
|
||||
model: Quickshell.screens.length * 2
|
||||
|
||||
NText {
|
||||
readonly property int screenIndex: Math.floor(index / 2)
|
||||
readonly property bool isLabel: index % 2 === 0
|
||||
readonly property var screen: Quickshell.screens[screenIndex]
|
||||
|
||||
text: {
|
||||
if (isLabel)
|
||||
return I18n.tr("panels.about.system-monitor");
|
||||
const name = screen?.name || "Unknown";
|
||||
const scales = CompositorService.displayScales || {};
|
||||
const scaleData = scales[name];
|
||||
const scaleValue = (typeof scaleData === "object" && scaleData !== null) ? (scaleData.scale || 1.0) : (scaleData || 1.0);
|
||||
return name + ": " + (screen?.width || 0) + "x" + (screen?.height || 0) + " @ " + scaleValue + "x";
|
||||
}
|
||||
color: isLabel ? Color.mOnSurfaceVariant : Color.mOnSurface
|
||||
Layout.fillWidth: !isLabel
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Telemetry Section
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginL
|
||||
}
|
||||
|
||||
NHeader {
|
||||
label: I18n.tr("panels.about.telemetry-title")
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.about.telemetry-enabled")
|
||||
description: I18n.tr("panels.about.telemetry-desc")
|
||||
checked: Settings.data.general.telemetryEnabled
|
||||
onCheckedChanged: Settings.data.general.telemetryEnabled = checked
|
||||
}
|
||||
|
||||
NButton {
|
||||
icon: "eye"
|
||||
text: I18n.tr("panels.about.telemetry-show-data")
|
||||
outlined: true
|
||||
onClicked: root.copyTelemetryData()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Services.Compositor
|
||||
import qs.Services.Noctalia
|
||||
import qs.Services.System
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property bool initialized: false
|
||||
property bool isSending: false
|
||||
property int totalRamGb: 0
|
||||
property string instanceId: ""
|
||||
|
||||
readonly property string telemetryEndpoint: Quickshell.env("NOCTALIA_TELEMETRY_ENDPOINT") || "https://noctalia.dev:7777/ping"
|
||||
readonly property string instanceIdSalt: "noctalia-telemetry-2025"
|
||||
|
||||
function init() {
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
initialized = true;
|
||||
|
||||
if (!Settings.data.general.telemetryEnabled) {
|
||||
Logger.d("Telemetry", "Telemetry disabled by user");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read machine-id to generate instance ID, then read RAM, then send ping
|
||||
machineIdProcess.running = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: machineIdProcess
|
||||
command: ["cat", "/etc/machine-id"]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const machineId = text.trim();
|
||||
if (machineId && machineId.length > 0) {
|
||||
root.instanceId = root.hashString(machineId + root.instanceIdSalt);
|
||||
Logger.d("Telemetry", "Generated instance ID from machine-id");
|
||||
} else {
|
||||
root.instanceId = root.generateRandomId();
|
||||
Logger.d("Telemetry", "Using random instance ID (machine-id unavailable)");
|
||||
}
|
||||
memInfoProcess.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
onExited: function (exitCode) {
|
||||
if (exitCode !== 0) {
|
||||
root.instanceId = root.generateRandomId();
|
||||
Logger.d("Telemetry", "Using random instance ID (machine-id read failed)");
|
||||
memInfoProcess.running = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hashString(str) {
|
||||
// Simple hash function that produces a UUID-like string
|
||||
let hash = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const c = str.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + c;
|
||||
hash = hash & hash;
|
||||
}
|
||||
// Convert to hex and pad to create UUID-like format
|
||||
const hex = Math.abs(hash).toString(16).padStart(8, '0');
|
||||
const hex2 = Math.abs(hash * 31).toString(16).padStart(8, '0');
|
||||
const hex3 = Math.abs(hash * 37).toString(16).padStart(8, '0');
|
||||
const hex4 = Math.abs(hash * 41).toString(16).padStart(8, '0');
|
||||
return `${hex.slice(0, 8)}-${hex2.slice(0, 4)}-${hex2.slice(4, 8)}-${hex3.slice(0, 4)}-${hex3.slice(4, 8)}${hex4.slice(0, 4)}`;
|
||||
}
|
||||
|
||||
function generateRandomId() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
function getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: memInfoProcess
|
||||
command: ["sh", "-c", "grep MemTotal /proc/meminfo | awk '{print int($2/1048576)}'"]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const ramGb = parseInt(text.trim()) || 0;
|
||||
root.totalRamGb = ramGb;
|
||||
root.sendPing();
|
||||
}
|
||||
}
|
||||
|
||||
onExited: function (exitCode) {
|
||||
if (exitCode !== 0) {
|
||||
// Still send ping even if RAM detection fails
|
||||
root.sendPing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendPing() {
|
||||
if (isSending)
|
||||
return;
|
||||
|
||||
isSending = true;
|
||||
|
||||
const payload = {
|
||||
instanceId: instanceId,
|
||||
version: UpdateService.currentVersion,
|
||||
compositor: getCompositorType(),
|
||||
os: HostService.osPretty || "Unknown",
|
||||
ramGb: totalRamGb,
|
||||
monitors: getMonitorInfo(),
|
||||
ui: {
|
||||
scaleRatio: Settings.data.general.scaleRatio,
|
||||
fontDefault: Settings.data.ui.fontDefault || "default",
|
||||
fontDefaultScale: Settings.data.ui.fontDefaultScale,
|
||||
fontFixed: Settings.data.ui.fontFixed || "default",
|
||||
fontFixedScale: Settings.data.ui.fontFixedScale
|
||||
}
|
||||
};
|
||||
|
||||
Logger.d("Telemetry", "Sending anonymous ping:", JSON.stringify(payload));
|
||||
|
||||
const request = new XMLHttpRequest();
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === XMLHttpRequest.DONE) {
|
||||
if (request.status >= 200 && request.status < 300) {
|
||||
Logger.d("Telemetry", "Ping sent successfully");
|
||||
} else {
|
||||
Logger.d("Telemetry", "Ping failed with status:", request.status);
|
||||
}
|
||||
isSending = false;
|
||||
}
|
||||
};
|
||||
|
||||
request.open("POST", telemetryEndpoint);
|
||||
request.setRequestHeader("Content-Type", "application/json");
|
||||
request.send(JSON.stringify(payload));
|
||||
}
|
||||
|
||||
function getMonitorInfo() {
|
||||
const monitors = [];
|
||||
const screens = Quickshell.screens || [];
|
||||
const scales = CompositorService.displayScales || {};
|
||||
|
||||
for (let i = 0; i < screens.length; i++) {
|
||||
const screen = screens[i];
|
||||
const name = screen.name || "Unknown";
|
||||
const scaleData = scales[name];
|
||||
// Extract just the numeric scale value
|
||||
const scaleValue = (typeof scaleData === "object" && scaleData !== null) ? (scaleData.scale || 1.0) : (scaleData || 1.0);
|
||||
monitors.push({
|
||||
width: screen.width || 0,
|
||||
height: screen.height || 0,
|
||||
scale: scaleValue
|
||||
});
|
||||
}
|
||||
|
||||
return monitors;
|
||||
}
|
||||
|
||||
function getCompositorType() {
|
||||
if (CompositorService.isHyprland)
|
||||
return "Hyprland";
|
||||
if (CompositorService.isNiri)
|
||||
return "Niri";
|
||||
if (CompositorService.isSway)
|
||||
return "Sway";
|
||||
if (CompositorService.isMango)
|
||||
return "MangoWC";
|
||||
if (CompositorService.isLabwc)
|
||||
return "LabWC";
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user