diff --git a/Assets/MatugenTemplates/vesktop.css b/Assets/MatugenTemplates/vesktop.css
index 6a85df16..a509fdcd 100644
--- a/Assets/MatugenTemplates/vesktop.css
+++ b/Assets/MatugenTemplates/vesktop.css
@@ -42,7 +42,7 @@ body {
/* dms button options */
--custom-dms-icon: custom; /* off: use default discord icon, hide: remove icon entirely, custom: use custom icon */
- --dms-icon-svg-url: url('https://raw.githubusercontent.com/noctalia-dev/noctalia-shell/main/Assets/noctalia-shape.svg'); /* icon svg url. MUST BE A SVG. */
+ --dms-icon-svg-url: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB3aWR0aD0iMjU2IgogICBoZWlnaHQ9IjI1NiIKICAgdmlld0JveD0iMCAwIDY3LjczMzMzNCA2Ny43MzMzMzQiCiAgIHZlcnNpb249IjEuMSIKICAgaWQ9InN2ZzEiCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGRlZnMKICAgICBpZD0iZGVmczEiIC8+CiAgPGcKICAgICBpZD0iZzEiCiAgICAgdHJhbnNmb3JtPSJtYXRyaXgoMS4xMDEwODY5LDAsMCwxLjEwMTA4NjksLTMuNDIzODM0NywtMy40MjM0ODkzKSI+CiAgICA8ZwogICAgICAgaWQ9Imc1NSIKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICB0cmFuc2Zvcm09Im1hdHJpeCg0LjIwNTU5MDUsMCwwLDQuMjA1NTkwNSwtMTQuNzg4ODk4LC0xODAuNDMzNjIpIj4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg1NSIKICAgICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6OS4xO3N0cm9rZS1kYXNoYXJyYXk6bm9uZTtwYWludC1vcmRlcjpmaWxsIG1hcmtlcnMgc3Ryb2tlIgogICAgICAgICBkPSJtIDExLjY0NjQ4NCw0My42NDI1NzggYSA3LjMxNDEzNTYsNy4zMTQxMzU2IDAgMCAwIC03LjMxMjQ5OTYsNy4zMTI1IDcuMzE0MTM1Niw3LjMxNDEzNTYgMCAwIDAgNy4zMTI0OTk2LDcuMzE0NDUzIDcuMzE0MTM1Niw3LjMxNDEzNTYgMCAwIDAgNy4xNTgyMDQsLTUuODk4NDM3IDYuMjIwMzMwMiw2LjIyMDMzMDIgMCAwIDEgLTMuNDE2MDE2LDMuNDY0ODQ0IGMgMC4wMDE1LDAuMjc3NDA2IDAuMDAzOSwwLjUzMjU1IDAuMDAzOSwwLjcyNjU2MiAtMC43Mzk0NDUsMCAtMS4zNzU4MzUsLTAuMTAxODg2IC0xLjkyMTg3NSwtMC4yNzE0ODQgYSA2LjIyMDMzMDIsNi4yMjAzMzAyIDAgMCAxIC0wLjQ0MTQwNiwwLjAzNTE2IDYuMjIwMzMwMiw2LjIyMDMzMDIgMCAwIDEgLTYuMjIwNzAzMiwtNi4yMjA3MDMgNi4yMjAzMzAyLDYuMjIwMzMwMiAwIDAgMSA2LjIyMDcwMzIsLTYuMjIwNzAzIDYuMjIwMzMwMiw2LjIyMDMzMDIgMCAwIDEgMC41NzYxNzIsMC4wMjczNCA3LjMxNDEzNTYsNy4zMTQxMzU2IDAgMCAwIC0xLjk1ODk4NSwtMC4yNjk1MzEgeiIgLz4KICAgIDwvZz4KICAgIDxwYXRoCiAgICAgICBpZD0icGF0aDU2IgogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MS4zNDYwODtzdHJva2UtbWl0ZXJsaW1pdDo5LjE7cGFpbnQtb3JkZXI6ZmlsbCBtYXJrZXJzIHN0cm9rZSIKICAgICAgIGQ9Im0gNDIuNjY0NDQsMzEuMjkxNDc0IGMgLTEuODAyODgyLDIuMDIzMTA1IC00Ljk1MDEzOSwyLjQ5MjY2MSAtOC41MjU0LDIuNTAyOCAtMi43MTgxNiwtMC4wMDc3IC01LjQ1MDQ3NiwtMC4xMjgyMjcgLTcuMjY5NTYsLTEuMzg5NTUxIC0xLjgxNjU0MiwwLjMyNDE4MiAtMi41NzkxNTcsMi4zNDQwMzMgLTIuNDE1ODY2LDQuNzAyNzc3IDEuMTY0NjQ3LDE2LjgyMjk2NyAxMS44MTY3MiwxNS43MzQ2NDUgMTEuOTEyMTk4LDE1LjcwNzE0NSAtNy43OTMzNjYsLTMuODAyNDQ3IC02LjUxNjQ5OCwtMTAuMDAwNDggLTYuNzcyNjIyLC0xMS45NzUyOTMgMC4zMjA5MjgsMy4zNDIzMyAzLjg5NTkyNiwxMi44NTY3NjQgMTcuMjM1NDk0LDEyLjg1Njc2NCAwLC00LjAwOTY1NSAwLjAxOTkyLC0xNC4zMTEwMzUgLTEuMjc5MDgsLTE3LjQ4NzAyNCAtMC40MDkxMjQsLTEuMjM3MzEyIC0xLjUyNTI2LC00LjU0Njk2MyAtMi44ODUxNjQsLTQuOTE3NjE4IHoiIC8+CiAgICA8cGF0aAogICAgICAgaWQ9InBhdGg1NyIKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjMuNzY1NjU7c3Ryb2tlLW1pdGVybGltaXQ6OS4xO3BhaW50LW9yZGVyOmZpbGwgbWFya2VycyBzdHJva2UiCiAgICAgICBkPSJtIDIwLjk5MjAxMywxNi4wODcwMDQgYyAwLjYwODk0NCwxLjg2NTU0NSAxLjgzNTMzNCwzLjcwNDMxNCAzLjQ4MDA4Niw0LjQwMTc0NSAtMC40NTg3ODEsMS4zODI4MDQgLTAuNDYwODMxLDMuMDI0OTQ5IC0wLjQ2MDgzMSw0Ljc4MzEyNiAwLDQuOTI3ODk1IDQuNTMzNjk4LDguOTE5NDEzIDEwLjEzMDM1OSw4LjkzODU1OSA1LjU5NjY2NCwtMC4wMTkxMiAxMC4xMzAzNjcsLTQuMDEwNjY3IDEwLjEzMDM2NywtOC45Mzg1NTkgMCwtMS43NTgxNzcgLTAuMDAyMSwtMy40MDAzMjIgLTAuNDYwODMzLC00Ljc4MzEyNiAxLjY0NDc1MywtMC42OTc0MzEgMi44NzExNDIsLTIuNTM2MiAzLjQ4MDA4NCwtNC40MDE3NDUgLTEuOTg3Nzc2LC0wLjAzMDUgLTUuMTUwOTA4LDAuNzAwNzU3IC03Ljg1MDA0NywwLjc4NjU5NSAtMS4zNTE1MzksLTAuMzUxODQ1IC0zLjA4NjEzNywtMC41NDU4NjggLTUuMjk5NTcxLC0wLjU0ODIzMyAtMi4yMTM0MzEsMC4wMDI0IC0zLjk0ODAyNywwLjE5NjM2NyAtNS4yOTk1NjgsMC41NDgyMzMgLTIuNjk5MTM1LC0wLjA4NTg0IC01Ljg2MjI2NiwtMC44MTcxODcgLTcuODUwMDQ2LC0wLjc4NjU5NSB6IG0gNi43Nzc0MTksNC42NDgwNTMgYyAwLjU1NTQ3LC0wLjAxMzgzIDEuMjk5Nzc5LDAuMDYyMDQgMi4zMDQxNjEsMC4yNDYzMTkgMC42NzIxOTgsMC4xMjMzMDIgMS41MjM1MzYsMC40NTI0MDIgMi4wMzQwMTksMC43NTQ4MTMgMC45NTA4MDcsMC41NjMyNjQgMS4wNzM1OTUsMS4yMDc2OTcgMi4wMzQwMTUsMS4yMDc2OTcgMC45NjA0MiwwIDEuMDgzMjA3LC0wLjY0NDQzMyAyLjAzNDAxOCwtMS4yMDc2OTcgMC41MTA0ODMsLTAuMzAyNDE4IDEuMzYxODIyLC0wLjYzMTUxMSAyLjAzNDAyMSwtMC43NTQ4MTMgNC41OTE0NTksLTAuODQyMzI4IDMuODIxNzMyLDAuNTIzOTYyIDMuODIxNzMyLDIuODM2NTA1IDAsMi4zODcxMzIgLTEuOTM1MTU1LDQuMzIyMjkgLTQuMzIyMjkxLDQuMzIyMjkgLTAuNzYyOTUsLTAuMDAzNyAtMS41MTEzMzIsLTAuMjA5MzQgLTIuMTY5MDkxLC0wLjU5NTkwNSAtMC4wMTU0NiwwLjAzMzc1IC0wLjAyODg3LDAuMDY0ODQgLTAuMDQ3NjgsMC4wOTUzNSBsIC0wLjk2OTMzOCwxLjU3MzE4OSBjIC0wLjEwNTIzOSwwLjE3MTIyMiAtMC4yNDM3OTcsMC4yNTc0NjcgLTAuMzgxMzc4LDAuMjU0MjUxIC0wLjEzNzU4LDAuMDAzMSAtMC4yNzYxMzksLTAuMDgzMDMgLTAuMzgxMzc4LC0wLjI1NDI1MSBsIC0wLjk2OTMzOCwtMS41NzMxODkgYyAtMC4wMTg3MSwtMC4wMzA1IC0wLjAzMjEyLC0wLjA2MTU5IC0wLjA0NzY4LC0wLjA5NTM1IC0wLjY1Nzc2MywwLjM4NjU4NSAtMS40MDYxNDIsMC41OTIxODggLTIuMTY5MDkxLDAuNTk1OTA1IC0yLjM4NzEzNywwIC00LjMyMjI5LC0xLjkzNTE1OCAtNC4zMjIyOSwtNC4zMjIyOSAwLC0xLjgwNjY3MyAtMC40NjYyNzEsLTMuMDMzMTczIDEuNTE3NTY5LC0zLjA4MjgxNCB6IiAvPgogICAgPHBhdGgKICAgICAgIGlkPSJwYXRoNTgiCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoxLjIyMDUyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjkuMTtzdHJva2UtZGFzaGFycmF5Om5vbmU7c3Ryb2tlLW9wYWNpdHk6MTtwYWludC1vcmRlcjpmaWxsIG1hcmtlcnMgc3Ryb2tlIgogICAgICAgZD0iTSAzMi4zMDQyLDI1LjMwMDU5NiBBIDEuOTkxNDQzOCwxLjk5MTQ0MzggMCAwIDEgMzAuNTc5NTU5LDI2LjI5NjMyIDEuOTkxNDQzOCwxLjk5MTQ0MzggMCAwIDEgMjguODU0OTE4LDI1LjMwMDU5NiIgLz4KICAgIDxwYXRoCiAgICAgICBpZD0icGF0aDU5IgogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MS4yMjA1MjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDo5LjE7c3Ryb2tlLWRhc2hhcnJheTpub25lO3N0cm9rZS1vcGFjaXR5OjE7cGFpbnQtb3JkZXI6ZmlsbCBtYXJrZXJzIHN0cm9rZSIKICAgICAgIGQ9Ik0gMzkuNDI4MzM0LDI1LjMwMDU5NiBBIDEuOTkxNDQzOCwxLjk5MTQ0MzggMCAwIDEgMzcuNzAzNjk2LDI2LjI5NjMyIDEuOTkxNDQzOCwxLjk5MTQ0MzggMCAwIDEgMzUuOTc5MDUzLDI1LjMwMDU5NiIgLz4KICA8L2c+Cjwvc3ZnPg=='); /* icon svg url. MUST BE A SVG. */
--dms-icon-svg-size: 90%; /* size of the svg (css mask-size property) */
--dms-icon-color-before: var(--icon-secondary); /* normal icon color */
--dms-icon-color-after: var(--white); /* icon color when button is hovered/selected */
@@ -173,3 +173,21 @@ body {
.timestampInline_c19a55 time {
color: var(--text-4) !important;
}
+
+.postTitleText_faa96b {
+ color: var(--text-3) !important;
+}
+
+.postTitleText_faa96b .highlight {
+ color: var(--text-2) !important;
+}
+
+.messageContent_c19a55,
+.messageContent_faa96b {
+ color: var(--text-3) !important;
+}
+
+.messageContent_c19a55 .highlight,
+.messageContent_faa96b .highlight {
+ color: var(--text-2) !important;
+}
diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json
index bbb6094a..6d4f7d8f 100644
--- a/Assets/Translations/de.json
+++ b/Assets/Translations/de.json
@@ -227,14 +227,14 @@
"description": "Künstler - Titel anstatt Titel - Künstler anzeigen.",
"label": "Künstler zuerst anzeigen"
},
- "show-visualizer": {
- "description": "Audio-Visualizer anzeigen, wenn Musik abgespielt wird.",
- "label": "Visualizer anzeigen"
- },
"show-progress-ring": {
"description": "Runden Fortschrittsindikator anzeigen, der den Titelfortschritt anzeigt.",
"label": "Fortschrittsring anzeigen"
},
+ "show-visualizer": {
+ "description": "Audio-Visualizer anzeigen, wenn Musik abgespielt wird.",
+ "label": "Visualizer anzeigen"
+ },
"use-fixed-width": {
"description": "Wenn aktiviert, verwendet das Widget immer die maximale Breite, anstatt sich dynamisch an den Inhalt anzupassen.",
"label": "Feste Breite verwenden"
@@ -345,14 +345,14 @@
"description": "Anzahl der Zeichen, die von Arbeitsbereichsnamen angezeigt werden (1-10).",
"label": "Zeichenanzahl"
},
- "hide-unoccupied": {
- "description": "Arbeitsbereiche ohne Fenster nicht anzeigen.",
- "label": "Unbesetzte ausblenden"
- },
"follow-focused-screen": {
"description": "Zeigt Arbeitsbereiche vom aktuell fokussierten Bildschirm an, statt vom Bildschirm, auf dem sich die Leiste befindet.",
"label": "Fokussiertem Bildschirm folgen"
},
+ "hide-unoccupied": {
+ "description": "Arbeitsbereiche ohne Fenster nicht anzeigen.",
+ "label": "Unbesetzte ausblenden"
+ },
"label-mode": {
"description": "Wählen Sie, wie Arbeitsbereichs-Beschriftungen angezeigt werden.",
"label": "Beschriftungsmodus"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Akkustand",
"brightness": "Helligkeit",
- "charge-level": "Ladestand",
"charging": "Wird geladen.",
"charging-rate": "Laderate: {rate} W.",
"discharging": "Wird entladen.",
@@ -492,13 +492,13 @@
"title": "Benachrichtigungen"
},
"time": {
- "now": "jetzt",
- "diffM": "vor 1 Minute",
- "diffMM": "vor {diff} Minuten",
+ "diffD": "vor 1 Tag",
+ "diffDD": "vor {diff} Tagen",
"diffH": "vor 1 Stunde",
"diffHH": "vor {diff} Stunden",
- "diffD": "vor 1 Tag",
- "diffDD": "vor {diff} Tagen"
+ "diffM": "vor 1 Minute",
+ "diffMM": "vor {diff} Minuten",
+ "now": "jetzt"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Schreibe {filepath}.",
+ "description-missing": "Benötigt die Installation von {app}"
+ },
"code": {
"description": "Schreibe {Dateipfad}. Das Hyprluna-Theme muss manuell installiert und aktiviert werden",
"description-missing": "Kein Code-Client erkannt. Installieren Sie VSCode oder VSCodium"
@@ -1048,10 +1052,6 @@
"description": "Schreibe {filepath}",
"description-missing": "Benötigt die Installation von {app}"
},
- "cava": {
- "description": "Schreibe {filepath}",
- "description-missing": "Benötigt die Installation von {app}"
- },
"vicinae": {
"description": "Schreibt {filepath} und lädt neu",
"description-missing": "Erfordert die Installation von {app}"
@@ -1419,14 +1419,14 @@
"description": "Verwenden Sie ein benutzerdefiniertes Präfix zum Starten von Anwendungen anstelle der Standardmethode.",
"label": "Benutzerdefiniertes Start-Präfix aktivieren"
},
- "position": {
- "description": "Wählen Sie, wo das Starter-Panel erscheint.",
- "label": "Position"
- },
"grid-view": {
"description": "Elemente in einem Raster statt in einer Liste anzeigen.",
"label": "Rasteransicht"
},
+ "position": {
+ "description": "Wählen Sie, wo das Starter-Panel erscheint.",
+ "label": "Position"
+ },
"section": {
"description": "Verhalten und Erscheinungsbild des Starters anpassen.",
"label": "Erscheinungsbild"
@@ -1648,6 +1648,7 @@
"label": "Allgemein"
}
},
+ "title": "On-Screen Display",
"types": {
"brightness": {
"description": "OSD anzeigen, wenn sich die Bildschirmhelligkeit ändert.",
@@ -1662,19 +1663,14 @@
"label": "Feststelltasten"
},
"section": {
- "description": "Wähle, welche Ereignisse das On-Screen Display auslösen.",
- "label": "OSD-Typen"
+ "description": "Wählen Sie die Ereignisse aus, die das OSD auslösen. Wenn keine Ereignisse ausgewählt werden, lösen alle verfügbaren Ereignisse das OSD aus.",
+ "label": "OSD-Auslöseereignisse"
},
"volume": {
"description": "OSD anzeigen, wenn sich die Ausgabelautstärke ändert.",
"label": "Ausgangslautstärke"
}
- },
- "show-lock-key-notifications": {
- "description": "Benachrichtigungen anzeigen, wenn sich der Status von Feststelltaste, Num-Taste oder Rollen-Taste ändert.",
- "label": "Tastensperr-Benachrichtigungen anzeigen"
- },
- "title": "On-Screen Display"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json
index 0e40cef2..7328806a 100644
--- a/Assets/Translations/en.json
+++ b/Assets/Translations/en.json
@@ -227,14 +227,14 @@
"description": "Display artist - title instead of title - artist.",
"label": "Show artist first"
},
- "show-visualizer": {
- "description": "Display an audio visualizer when music is playing.",
- "label": "Show visualizer"
- },
"show-progress-ring": {
"description": "Display a circular progress indicator showing track progress.",
"label": "Show progress ring"
},
+ "show-visualizer": {
+ "description": "Display an audio visualizer when music is playing.",
+ "label": "Show visualizer"
+ },
"use-fixed-width": {
"description": "When enabled, the widget will always use the maximum width instead of dynamically adjusting to content.",
"label": "Use fixed width"
@@ -345,14 +345,14 @@
"description": "Number of characters to display from workspace names (1-10).",
"label": "Character count"
},
- "hide-unoccupied": {
- "description": "Don't display workspaces without windows.",
- "label": "Hide unoccupied"
- },
"follow-focused-screen": {
"description": "Display workspaces from the currently focused screen, rather than the screen where the bar is located.",
"label": "Follow focused screen"
},
+ "hide-unoccupied": {
+ "description": "Don't display workspaces without windows.",
+ "label": "Hide unoccupied"
+ },
"label-mode": {
"description": "Choose how workspace labels are displayed.",
"label": "Label mode"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Battery level",
"brightness": "Brightness",
- "charge-level": "Charge level",
"charging": "Charging",
"charging-rate": "Charging rate: {rate} W",
"discharging": "Discharging",
@@ -492,13 +492,13 @@
"title": "Notifications"
},
"time": {
- "now": "now",
- "diffM": "1 minute ago",
- "diffMM": "{diff} minutes ago",
+ "diffD": "1 day ago",
+ "diffDD": "{diff} days ago",
"diffH": "1 hour ago",
"diffHH": "{diff} hours ago",
- "diffD": "1 day ago",
- "diffDD": "{diff} days ago"
+ "diffM": "1 minute ago",
+ "diffMM": "{diff} minutes ago",
+ "now": "now"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Write {filepath}.",
+ "description-missing": "Requires {app} to be installed"
+ },
"code": {
"description": "Write {filepath}. Hyprluna theme needs to be installed and activated manually",
"description-missing": "No Code client detected. Install VSCode or VSCodium"
@@ -1048,10 +1052,6 @@
"description": "Write {filepath}",
"description-missing": "Requires {app} to be installed"
},
- "cava": {
- "description": "Write {filepath}",
- "description-missing": "Requires {app} to be installed"
- },
"vicinae": {
"description": "Write {filepath} and reload",
"description-missing": "Requires {app} to be installed"
@@ -1419,14 +1419,14 @@
"description": "Use a custom prefix for launching applications instead of the default method.",
"label": "Enable custom launch prefix"
},
- "position": {
- "description": "Choose where the launcher panel appears.",
- "label": "Position"
- },
"grid-view": {
"description": "Display items in a grid layout instead of a list.",
"label": "Grid view"
},
+ "position": {
+ "description": "Choose where the launcher panel appears.",
+ "label": "Position"
+ },
"section": {
"description": "Customize the launcher's behavior and appearance.",
"label": "Appearance"
@@ -1663,8 +1663,8 @@
"label": "Lock keys"
},
"section": {
- "description": "Choose which events trigger the on-screen display.",
- "label": "OSD types"
+ "description": "Select the events that trigger the OSD. If no events are selected, all available events will trigger the OSD.",
+ "label": "OSD trigger events"
},
"volume": {
"description": "Show OSD when audio output volume changes.",
diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json
index 271aa54e..1f021f6f 100644
--- a/Assets/Translations/es.json
+++ b/Assets/Translations/es.json
@@ -227,14 +227,14 @@
"description": "Mostrar artista - título en lugar de título - artista.",
"label": "Mostrar primero al artista"
},
- "show-visualizer": {
- "description": "Mostrar un visualizador de audio cuando se reproduce música.",
- "label": "Mostrar visualizador"
- },
"show-progress-ring": {
"description": "Mostrar un indicador de progreso circular que muestre el progreso de la pista.",
"label": "Mostrar anillo de progreso"
},
+ "show-visualizer": {
+ "description": "Mostrar un visualizador de audio cuando se reproduce música.",
+ "label": "Mostrar visualizador"
+ },
"use-fixed-width": {
"description": "Cuando está activado, el widget siempre usará el ancho máximo en lugar de ajustarse dinámicamente al contenido.",
"label": "Usar Ancho Fijo"
@@ -345,14 +345,14 @@
"description": "Número de caracteres a mostrar de los nombres de espacios de trabajo (1-10).",
"label": "Número de caracteres"
},
- "hide-unoccupied": {
- "description": "No mostrar espacios de trabajo sin ventanas.",
- "label": "Ocultar desocupados"
- },
"follow-focused-screen": {
"description": "Mostrar espacios de trabajo de la pantalla actualmente enfocada, en lugar de la pantalla donde se encuentra la barra.",
"label": "Seguir Pantalla Enfocada"
},
+ "hide-unoccupied": {
+ "description": "No mostrar espacios de trabajo sin ventanas.",
+ "label": "Ocultar desocupados"
+ },
"label-mode": {
"description": "Elegir cómo se muestran las etiquetas de los espacios de trabajo.",
"label": "Modo de etiqueta"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Nivel de batería",
"brightness": "Brillo",
- "charge-level": "Nivel de carga",
"charging": "Cargando.",
"charging-rate": "Tasa de carga: {rate} W.",
"discharging": "Descargando.",
@@ -452,7 +452,7 @@
"open-mixer": "Mezclador de audio",
"open-settings": "Abrir ajustes",
"pause": "Pausa",
- "play": "Jugar",
+ "play": "Reproducir",
"previous": "Anterior",
"random-wallpaper": "Fondo de pantalla aleatorio",
"toggle-mute": "Activar/desactivar silencio",
@@ -492,13 +492,13 @@
"title": "Notificaciones"
},
"time": {
- "now": "ahora",
- "diffM": "hace 1 minuto",
- "diffMM": "hace {diff} minutos",
+ "diffD": "hace 1 día",
+ "diffDD": "hace {diff} días",
"diffH": "hace 1 hora",
"diffHH": "hace {diff} horas",
- "diffD": "hace 1 día",
- "diffDD": "hace {diff} días"
+ "diffM": "hace 1 minuto",
+ "diffMM": "hace {diff} minutos",
+ "now": "ahora"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Escribe {filepath}.",
+ "description-missing": "Requiere que {app} esté instalado/a."
+ },
"code": {
"description": "Escribe {filepath}. El tema Hyprluna debe ser instalado y activado manualmente.",
"description-missing": "No se detectó cliente de Code. Instala VSCode o VSCodium."
@@ -1048,10 +1052,6 @@
"description": "Escribe {filepath}.",
"description-missing": "Requiere que {app} esté instalado/a."
},
- "cava": {
- "description": "Escribe {filepath}.",
- "description-missing": "Requiere que {app} esté instalado/a."
- },
"vicinae": {
"description": "Escribir {filepath} y recargar",
"description-missing": "Requiere que {app} esté instalado"
@@ -1419,14 +1419,14 @@
"description": "Usar un prefijo personalizado para lanzar aplicaciones en lugar del método predeterminado.",
"label": "Habilitar prefijo de lanzamiento personalizado"
},
- "position": {
- "description": "Elige dónde aparece el panel del lanzador.",
- "label": "Posición"
- },
"grid-view": {
"description": "Mostrar elementos en una cuadrícula en lugar de una lista.",
"label": "Vista de cuadrícula"
},
+ "position": {
+ "description": "Elige dónde aparece el panel del lanzador.",
+ "label": "Posición"
+ },
"section": {
"description": "Personaliza el comportamiento y la apariencia del lanzador.",
"label": "Apariencia"
@@ -1648,6 +1648,7 @@
"label": "General"
}
},
+ "title": "Visualización en pantalla",
"types": {
"brightness": {
"description": "Mostrar el OSD cuando cambie el brillo de la pantalla.",
@@ -1662,19 +1663,14 @@
"label": "Teclas de bloqueo"
},
"section": {
- "description": "Elige qué eventos activan la visualización en pantalla.",
- "label": "Tipos de OSD"
+ "description": "Seleccione los eventos que activan el OSD. Si no se selecciona ningún evento, todos los eventos disponibles activarán el OSD.",
+ "label": "Eventos de activación OSD"
},
"volume": {
"description": "Mostrar el OSD cuando cambie el volumen de salida de audio.",
"label": "Volumen de salida"
}
- },
- "show-lock-key-notifications": {
- "description": "Mostrar notificaciones cuando se activen o desactiven las teclas Bloq Mayús, Bloq Num o Bloq Despl.",
- "label": "Mostrar notificaciones de teclas de bloqueo"
- },
- "title": "Visualización en pantalla"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json
index 1aaa6898..2b8a33c4 100644
--- a/Assets/Translations/fr.json
+++ b/Assets/Translations/fr.json
@@ -227,14 +227,14 @@
"description": "Afficher artiste - titre au lieu de titre - artiste.",
"label": "Afficher l'artiste en premier"
},
- "show-visualizer": {
- "description": "Afficher un visualiseur audio quand la musique est en cours de lecture.",
- "label": "Afficher le visualiseur"
- },
"show-progress-ring": {
"description": "Afficher un indicateur de progression circulaire montrant la progression de la piste.",
"label": "Afficher l'anneau de progression"
},
+ "show-visualizer": {
+ "description": "Afficher un visualiseur audio quand la musique est en cours de lecture.",
+ "label": "Afficher le visualiseur"
+ },
"use-fixed-width": {
"description": "Lorsque activé, le widget utilisera toujours la largeur maximale au lieu de s'ajuster dynamiquement au contenu.",
"label": "Utiliser une Largeur Fixe"
@@ -345,14 +345,14 @@
"description": "Nombre de caractères à afficher des noms d'espaces de travail (1-10).",
"label": "Nombre de caractères"
},
- "hide-unoccupied": {
- "description": "Ne pas afficher les espaces de travail sans fenêtres.",
- "label": "Masquer les inoccupés"
- },
"follow-focused-screen": {
"description": "Afficher les espaces de travail de l'écran actuellement ciblé, plutôt que de l'écran où se trouve la barre.",
"label": "Suivre l'Écran Ciblé"
},
+ "hide-unoccupied": {
+ "description": "Ne pas afficher les espaces de travail sans fenêtres.",
+ "label": "Masquer les inoccupés"
+ },
"label-mode": {
"description": "Choisir comment les étiquettes d'espace de travail sont affichées.",
"label": "Mode d'étiquette"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Niveau de batterie",
"brightness": "Luminosité",
- "charge-level": "Niveau de charge",
"charging": "En charge.",
"charging-rate": "Taux de charge : {rate} W.",
"discharging": "En décharge.",
@@ -492,13 +492,13 @@
"title": "Notifications"
},
"time": {
- "now": "maintenant",
- "diffM": "il y a 1 minute",
- "diffMM": "il y a {diff} minutes",
+ "diffD": "il y a 1 jour",
+ "diffDD": "il y a {diff} jours",
"diffH": "il y a 1 heure",
"diffHH": "il y a {diff} heures",
- "diffD": "il y a 1 jour",
- "diffDD": "il y a {diff} jours"
+ "diffM": "il y a 1 minute",
+ "diffMM": "il y a {diff} minutes",
+ "now": "maintenant"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Écrire {filepath}.",
+ "description-missing": "Nécessite l'installation de {app}"
+ },
"code": {
"description": "Écrire {filepath}. Le thème Hyprluna doit être installé et activé manuellement.",
"description-missing": "Aucun client Code détecté. Installez VSCode ou VSCodium."
@@ -1048,10 +1052,6 @@
"description": "Écrire {filepath}.",
"description-missing": "Nécessite l'installation de {app}"
},
- "cava": {
- "description": "Écrire {filepath}.",
- "description-missing": "Nécessite l'installation de {app}"
- },
"vicinae": {
"description": "Écrire {filepath} et recharger",
"description-missing": "Nécessite que le lanceur {app} soit installé"
@@ -1419,14 +1419,14 @@
"description": "Utiliser un préfixe personnalisé pour lancer les applications au lieu de la méthode par défaut.",
"label": "Activer le préfixe de lancement personnalisé"
},
- "position": {
- "description": "Choisissez où le panneau du lanceur apparaît.",
- "label": "Position"
- },
"grid-view": {
"description": "Afficher les éléments dans une grille au lieu d'une liste.",
"label": "Vue grille"
},
+ "position": {
+ "description": "Choisissez où le panneau du lanceur apparaît.",
+ "label": "Position"
+ },
"section": {
"description": "Personnalisez le comportement et l'apparence du lanceur.",
"label": "Apparence"
@@ -1648,6 +1648,7 @@
"label": "Général"
}
},
+ "title": "Affichage à l'écran",
"types": {
"brightness": {
"description": "Afficher l'OSD lorsque la luminosité de l'écran change.",
@@ -1662,19 +1663,14 @@
"label": "Touches de verrouillage"
},
"section": {
- "description": "Choisissez quels événements déclenchent l'affichage à l'écran.",
- "label": "Types d'OSD"
+ "description": "Sélectionnez les événements qui déclenchent l'OSD. Si aucun événement n'est sélectionné, tous les événements disponibles déclencheront l'OSD.",
+ "label": "Événements de déclenchement OSD"
},
"volume": {
"description": "Afficher l'OSD lorsque le volume de sortie audio change.",
"label": "Volume de sortie"
}
- },
- "show-lock-key-notifications": {
- "description": "Afficher les notifications lorsque les touches Verr. Maj., Verr. Num. ou Arrêt défil. sont activées/désactivées.",
- "label": "Afficher les notifications des touches de verrouillage"
- },
- "title": "Affichage à l'écran"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/nl.json b/Assets/Translations/nl.json
index 7a4dac43..e4a9e3f6 100644
--- a/Assets/Translations/nl.json
+++ b/Assets/Translations/nl.json
@@ -227,14 +227,14 @@
"description": "Toon artiest - titel in plaats van titel - artiest.",
"label": "Toon eerst de artiest"
},
- "show-visualizer": {
- "description": "Toon een audiovisualizer wanneer muziek wordt afgespeeld.",
- "label": "Visualizer tonen"
- },
"show-progress-ring": {
"description": "Toon een circulaire voortgangsindicator die het bestandsspoor voortgang toont.",
"label": "Voortgangscirkel tonen"
},
+ "show-visualizer": {
+ "description": "Toon een audiovisualizer wanneer muziek wordt afgespeeld.",
+ "label": "Visualizer tonen"
+ },
"use-fixed-width": {
"description": "Indien ingeschakeld gebruikt de widget altijd de maximale breedte in plaats van zich aan te passen aan de inhoud.",
"label": "Vaste breedte gebruiken"
@@ -345,14 +345,14 @@
"description": "Aantal tekens dat wordt weergegeven van werkruimtenamen (1-10).",
"label": "Aantal tekens"
},
- "hide-unoccupied": {
- "description": "Werkruimten zonder vensters niet weergeven.",
- "label": "Ongebruikte verbergen"
- },
"follow-focused-screen": {
"description": "Werkruimten weergeven van het momenteel gefocuste scherm, in plaats van het scherm waar de balk zich bevindt.",
"label": "Gefocust Scherm Volgen"
},
+ "hide-unoccupied": {
+ "description": "Werkruimten zonder vensters niet weergeven.",
+ "label": "Ongebruikte verbergen"
+ },
"label-mode": {
"description": "Kies hoe labels van werkruimten worden weergegeven.",
"label": "Labelmodus"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Batterijniveau",
"brightness": "Helderheid",
- "charge-level": "Laadniveau",
"charging": "Opladen.",
"charging-rate": "Laadsnelheid: {rate} W.",
"discharging": "Ontladen.",
@@ -492,13 +492,13 @@
"title": "Meldingen"
},
"time": {
- "now": "nu",
- "diffM": "1 minuut geleden",
- "diffMM": "{diff} minuten geleden",
+ "diffD": "1 dag geleden",
+ "diffDD": "{diff} dagen geleden",
"diffH": "1 uur geleden",
"diffHH": "{diff} uur geleden",
- "diffD": "1 dag geleden",
- "diffDD": "{diff} dagen geleden"
+ "diffM": "1 minuut geleden",
+ "diffMM": "{diff} minuten geleden",
+ "now": "nu"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Schrijf {filepath}.",
+ "description-missing": "Vereist dat {app} is geïnstalleerd."
+ },
"code": {
"description": "Schrijf {filepath}. Het Hyprluna-thema moet handmatig worden geïnstalleerd en geactiveerd.",
"description-missing": "Geen Code-client gedetecteerd. Installeer VSCode of VSCodium."
@@ -1048,10 +1052,6 @@
"description": "Schrijf {filepath}.",
"description-missing": "Vereist dat {app} is geïnstalleerd."
},
- "cava": {
- "description": "Schrijf {filepath}.",
- "description-missing": "Vereist dat {app} is geïnstalleerd."
- },
"vicinae": {
"description": "Schrijf {filepath} en herlaad.",
"description-missing": "Vereist dat {app} is geïnstalleerd."
@@ -1419,14 +1419,14 @@
"description": "Gebruik een aangepaste prefix om applicaties te starten in plaats van de standaardmethode.",
"label": "Aangepaste startprefix inschakelen"
},
- "position": {
- "description": "Kies waar het launcher-paneel verschijnt.",
- "label": "Positie"
- },
"grid-view": {
"description": "Items in een raster weergeven in plaats van een lijst.",
"label": "Rasterweergave"
},
+ "position": {
+ "description": "Kies waar het launcher-paneel verschijnt.",
+ "label": "Positie"
+ },
"section": {
"description": "Pas het gedrag en uiterlijk van de launcher aan.",
"label": "Uiterlijk"
@@ -1648,6 +1648,7 @@
"label": "Algemeen"
}
},
+ "title": "On-screenweergave",
"types": {
"brightness": {
"description": "Toon het OSD wanneer de schermhelderheid verandert.",
@@ -1662,19 +1663,14 @@
"label": "Vergrendeltoetsen"
},
"section": {
- "description": "Kies welke gebeurtenissen de on-screenweergave activeren.",
- "label": "OSD-typen"
+ "description": "Selecteer de gebeurtenissen die de OSD activeren. Als er geen gebeurtenissen zijn geselecteerd, activeren alle beschikbare gebeurtenissen de OSD.",
+ "label": "OSD triggergebeurtenissen"
},
"volume": {
"description": "Toon het OSD wanneer het uitvoervolume verandert.",
"label": "Uitvoervolume"
}
- },
- "show-lock-key-notifications": {
- "description": "Toon meldingen wanneer Caps Lock, Num Lock of Scroll Lock toetsen worden omgeschakeld.",
- "label": "Vergrendeltoetsmeldingen tonen"
- },
- "title": "On-screenweergave"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json
index 28d8b37f..8da723cc 100644
--- a/Assets/Translations/pt.json
+++ b/Assets/Translations/pt.json
@@ -227,14 +227,14 @@
"description": "Exibir artista - título em vez de título - artista.",
"label": "Mostrar o artista primeiro"
},
- "show-visualizer": {
- "description": "Exibir um visualizador de áudio quando música está sendo reproduzida.",
- "label": "Mostrar visualizador"
- },
"show-progress-ring": {
"description": "Exibir um indicador de progresso circular mostrando o progresso da faixa.",
"label": "Mostrar anel de progresso"
},
+ "show-visualizer": {
+ "description": "Exibir um visualizador de áudio quando música está sendo reproduzida.",
+ "label": "Mostrar visualizador"
+ },
"use-fixed-width": {
"description": "Quando ativado, o widget sempre usará a largura máxima em vez de ajustar dinamicamente ao conteúdo.",
"label": "Usar Largura Fixa"
@@ -345,14 +345,14 @@
"description": "Número de caracteres a exibir dos nomes de espaços de trabalho (1-10).",
"label": "Número de caracteres"
},
- "hide-unoccupied": {
- "description": "Não exibir áreas de trabalho sem janelas.",
- "label": "Ocultar desocupados"
- },
"follow-focused-screen": {
"description": "Exibir áreas de trabalho da tela atualmente em foco, em vez da tela onde a barra está localizada.",
"label": "Seguir Tela em Foco"
},
+ "hide-unoccupied": {
+ "description": "Não exibir áreas de trabalho sem janelas.",
+ "label": "Ocultar desocupados"
+ },
"label-mode": {
"description": "Escolher como os rótulos de espaço de trabalho são exibidos.",
"label": "Modo de rótulo"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Nível da bateria",
"brightness": "Brilho",
- "charge-level": "Nível de carga",
"charging": "Carregando.",
"charging-rate": "Taxa de carregamento: {rate} W.",
"discharging": "Descarregando.",
@@ -492,13 +492,13 @@
"title": "Notificações"
},
"time": {
- "now": "agora",
- "diffM": "há 1 minuto",
- "diffMM": "há {diff} minutos",
+ "diffD": "há 1 dia",
+ "diffDD": "há {diff} dias",
"diffH": "há 1 hora",
"diffHH": "há {diff} horas",
- "diffD": "há 1 dia",
- "diffDD": "há {diff} dias"
+ "diffM": "há 1 minuto",
+ "diffMM": "há {diff} minutos",
+ "now": "agora"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Escreva em {filepath}.",
+ "description-missing": "Requer que o {app} esteja instalado."
+ },
"code": {
"description": "Escreva em {filepath}. O tema Hyprluna precisa ser instalado e ativado manualmente.",
"description-missing": "Nenhum cliente Code detectado. Instale VSCode ou VSCodium."
@@ -1048,10 +1052,6 @@
"description": "Escreva em {filepath}.",
"description-missing": "Requer que o {app} esteja instalado."
},
- "cava": {
- "description": "Escreva em {filepath}.",
- "description-missing": "Requer que o {app} esteja instalado."
- },
"vicinae": {
"description": "Escrever {filepath} e recarregar",
"description-missing": "Requer que o {app} esteja instalado"
@@ -1419,14 +1419,14 @@
"description": "Usar um prefixo personalizado para inicializar aplicativos em vez do método padrão.",
"label": "Habilitar prefixo de inicialização personalizado"
},
- "position": {
- "description": "Escolha onde o painel do lançador aparece.",
- "label": "Posição"
- },
"grid-view": {
"description": "Exibir itens em uma grade em vez de uma lista.",
"label": "Visualização em grade"
},
+ "position": {
+ "description": "Escolha onde o painel do lançador aparece.",
+ "label": "Posição"
+ },
"section": {
"description": "Personalize o comportamento e a aparência do lançador.",
"label": "Aparência"
@@ -1648,6 +1648,7 @@
"label": "Geral"
}
},
+ "title": "Exibição na tela",
"types": {
"brightness": {
"description": "Mostrar o OSD quando o brilho da tela mudar.",
@@ -1662,19 +1663,14 @@
"label": "Teclas de bloqueio"
},
"section": {
- "description": "Escolha quais eventos disparam a exibição na tela.",
- "label": "Tipos de OSD"
+ "description": "Selecione os eventos que acionam o OSD. Se nenhum evento for selecionado, todos os eventos disponíveis acionarão o OSD.",
+ "label": "Eventos de disparo OSD"
},
"volume": {
"description": "Mostrar o OSD quando o volume de saída de áudio mudar.",
"label": "Volume de saída"
}
- },
- "show-lock-key-notifications": {
- "description": "Mostrar notificações quando as teclas Caps Lock, Num Lock ou Scroll Lock forem alternadas.",
- "label": "Mostrar notificações das teclas de bloqueio"
- },
- "title": "Exibição na tela"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/ru.json b/Assets/Translations/ru.json
index ef5c2207..6a0ee906 100644
--- a/Assets/Translations/ru.json
+++ b/Assets/Translations/ru.json
@@ -227,14 +227,14 @@
"description": "Исполнитель - название вместо название - исполнитель.",
"label": "Сначала исполнитель"
},
- "show-visualizer": {
- "description": "Отображать аудиовизуализатор при воспроизведении музыки.",
- "label": "Показывать визуализатор"
- },
"show-progress-ring": {
"description": "Отображать круговой индикатор прогресса воспроизведения трека.",
"label": "Показывать кольцо прогресса"
},
+ "show-visualizer": {
+ "description": "Отображать аудиовизуализатор при воспроизведении музыки.",
+ "label": "Показывать визуализатор"
+ },
"use-fixed-width": {
"description": "Если включено, виджет всегда будет использовать максимальную ширину вместо динамической подстройки под содержимое.",
"label": "Использовать фиксированную ширину"
@@ -345,14 +345,14 @@
"description": "Количество символов для отображения из имен рабочих пространств (1-10).",
"label": "Количество символов"
},
- "hide-unoccupied": {
- "description": "Не отображать рабочие пространства без окон.",
- "label": "Скрыть незанятые"
- },
"follow-focused-screen": {
"description": "Отображать рабочие пространства с текущего активного экрана, а не с экрана, на котором расположена панель.",
"label": "Следовать за Активным Экраном"
},
+ "hide-unoccupied": {
+ "description": "Не отображать рабочие пространства без окон.",
+ "label": "Скрыть незанятые"
+ },
"label-mode": {
"description": "Выберите, как отображаются метки рабочих пространств.",
"label": "Режим метки"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Уровень заряда батареи",
"brightness": "Яркость",
- "charge-level": "Уровень заряда",
"charging": "Зарядка.",
"charging-rate": "Скорость зарядки: {rate} Вт.",
"discharging": "Разрядка.",
@@ -492,13 +492,13 @@
"title": "Уведомления"
},
"time": {
- "now": "сейчас",
- "diffM": "1 минуту назад",
- "diffMM": "{diff} минут назад",
+ "diffD": "1 день назад",
+ "diffDD": "{diff} дней назад",
"diffH": "1 час назад",
"diffHH": "{diff} часов назад",
- "diffD": "1 день назад",
- "diffDD": "{diff} дней назад"
+ "diffM": "1 минуту назад",
+ "diffMM": "{diff} минут назад",
+ "now": "сейчас"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Записать {filepath}.",
+ "description-missing": "Требуется установка {app}"
+ },
"code": {
"description": "Записать {filepath}. Тему Hyprluna нужно установить и активировать вручную.",
"description-missing": "Клиент Code не обнаружен. Установите VSCode или VSCodium."
@@ -1048,10 +1052,6 @@
"description": "Записать {filepath}.",
"description-missing": "Требуется установка {app}"
},
- "cava": {
- "description": "Записать {filepath}.",
- "description-missing": "Требуется установка {app}"
- },
"vicinae": {
"description": "Записать {filepath} и перезагрузить",
"description-missing": "Требуется установка {app}"
@@ -1419,14 +1419,14 @@
"description": "Использовать пользовательский префикс для запуска приложений вместо метода по умолчанию.",
"label": "Включить пользовательский префикс запуска"
},
- "position": {
- "description": "Выберите, где появляется панель запуска.",
- "label": "Положение"
- },
"grid-view": {
"description": "Показывать элементы в виде сетки вместо списка.",
"label": "Вид сетки"
},
+ "position": {
+ "description": "Выберите, где появляется панель запуска.",
+ "label": "Положение"
+ },
"section": {
"description": "Настройка поведения и внешнего вида запуска.",
"label": "Внешний вид"
@@ -1648,6 +1648,7 @@
"label": "Общие"
}
},
+ "title": "Экранное отображение (OSD)",
"types": {
"brightness": {
"description": "Показывать OSD при изменении яркости экрана.",
@@ -1662,19 +1663,14 @@
"label": "Клавиши блокировки"
},
"section": {
- "description": "Выберите события, которые запускают экранное отображение.",
- "label": "Типы OSD"
+ "description": "Выберите события, которые должны запускать экранное меню (OSD). Если события не выбраны, экранное меню будет запускаться при любом доступном событии.",
+ "label": "События, запускающие экранное меню"
},
"volume": {
"description": "Показывать OSD при изменении громкости аудиовыхода.",
"label": "Выходная громкость"
}
- },
- "show-lock-key-notifications": {
- "description": "Показывать уведомления при переключении клавиш Caps Lock, Num Lock или Scroll Lock.",
- "label": "Показывать уведомления о состоянии клавиш"
- },
- "title": "Экранное отображение (OSD)"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/tr.json b/Assets/Translations/tr.json
index af4af640..445353fa 100644
--- a/Assets/Translations/tr.json
+++ b/Assets/Translations/tr.json
@@ -227,14 +227,14 @@
"description": "Sanatçı - başlık yerine başlık - sanatçı olarak göster.",
"label": "Önce sanatçıyı göster"
},
- "show-visualizer": {
- "description": "Müzik çalarken bir ses görselleştirici göster.",
- "label": "Görselleştiriciyi göster"
- },
"show-progress-ring": {
"description": "Parça ilerlemesini gösteren dairesel bir ilerleme göstergesi gösterin.",
"label": "İlerleme halkası göster"
},
+ "show-visualizer": {
+ "description": "Müzik çalarken bir ses görselleştirici göster.",
+ "label": "Görselleştiriciyi göster"
+ },
"use-fixed-width": {
"description": "Etkinleştirildiğinde, widget dinamik olarak içerik göre ayarlamak yerine her zaman maksimum genişliği kullanır.",
"label": "Sabit Genişlik Kullan"
@@ -345,14 +345,14 @@
"description": "Çalışma alanı adlarından gösterilecek karakter sayısı (1-10).",
"label": "Karakter sayısı"
},
- "hide-unoccupied": {
- "description": "Penceresi olmayan çalışma alanlarını gösterme.",
- "label": "Dolu olmayanları gizle"
- },
"follow-focused-screen": {
"description": "Çubuğun bulunduğu ekran yerine, şu anda odaklanmış ekrandaki çalışma alanlarını göster.",
"label": "Odaklanmış Ekranı Takip Et"
},
+ "hide-unoccupied": {
+ "description": "Penceresi olmayan çalışma alanlarını gösterme.",
+ "label": "Dolu olmayanları gizle"
+ },
"label-mode": {
"description": "Çalışma alanı etiketlerinin nasıl gösterileceğini seçin.",
"label": "Etiket Modu"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Pil seviyesi",
"brightness": "Parlaklık",
- "charge-level": "Şarj seviyesi",
"charging": "Şarj oluyor.",
"charging-rate": "Şarj oranı: {rate} W.",
"discharging": "Deşarj oluyor.",
@@ -492,13 +492,13 @@
"title": "Bildirimler"
},
"time": {
- "now": "şimdi",
- "diffM": "1 dakika önce",
- "diffMM": "{diff} dakika önce",
+ "diffD": "1 gün önce",
+ "diffDD": "{diff} gün önce",
"diffH": "1 saat önce",
"diffHH": "{diff} saat önce",
- "diffD": "1 gün önce",
- "diffDD": "{diff} gün önce"
+ "diffM": "1 dakika önce",
+ "diffMM": "{diff} dakika önce",
+ "now": "şimdi"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "{filepath} dosyasına yaz.",
+ "description-missing": "Kurulum için {app} gereklidir"
+ },
"code": {
"description": "{filepath} dosyasına yaz. Hyprluna temasının kurulu ve manuel olarak etkinleştirilmiş olması gerekir.",
"description-missing": "Code istemcisi tespit edilmedi. VSCode veya VSCodium kurun."
@@ -1048,10 +1052,6 @@
"description": "{filepath} dosyasına yaz.",
"description-missing": "Kurulum için {app} gereklidir"
},
- "cava": {
- "description": "{filepath} dosyasına yaz.",
- "description-missing": "Kurulum için {app} gereklidir"
- },
"vicinae": {
"description": "{filepath} dosyasına yaz ve yeniden yükle",
"description-missing": "Kurulum için {app} gereklidir"
@@ -1419,14 +1419,14 @@
"description": "Uygulamaları başlatmak için varsayılan yöntem yerine özel bir ön ek kullanın.",
"label": "Özel başlatma önekini etkinleştir"
},
- "position": {
- "description": "Başlatıcı panelinin nerede görüneceğini seçin.",
- "label": "Konum"
- },
"grid-view": {
"description": "Öğeleri liste yerine ızgara düzeninde görüntüle.",
"label": "Izgara görünümü"
},
+ "position": {
+ "description": "Başlatıcı panelinin nerede görüneceğini seçin.",
+ "label": "Konum"
+ },
"section": {
"description": "Başlatıcının davranışını ve görünümünü özelleştirin.",
"label": "Görünüm"
@@ -1648,6 +1648,7 @@
"label": "Genel"
}
},
+ "title": "Ekran Görüntüsü",
"types": {
"brightness": {
"description": "Ekran parlaklığı değiştiğinde OSD'yi göster.",
@@ -1662,19 +1663,14 @@
"label": "Kilit tuşları"
},
"section": {
- "description": "Ekran göstergesini tetikleyen olayları seçin.",
- "label": "OSD türleri"
+ "description": "OSD'yi tetikleyecek olayları seçin. Hiçbir olay seçilmezse, mevcut tüm olaylar OSD'yi tetikleyecektir.",
+ "label": "OSD tetikleme olayları"
},
"volume": {
"description": "Ses çıkış düzeyi değiştiğinde OSD'yi göster.",
"label": "Çıkış sesi"
}
- },
- "show-lock-key-notifications": {
- "description": "Caps Lock, Num Lock veya Scroll Lock tuşları değiştirildiğinde bildirimleri göster.",
- "label": "Kilit tuşu bildirimlerini göster"
- },
- "title": "Ekran Görüntüsü"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/uk-UA.json b/Assets/Translations/uk-UA.json
index d4862922..0bee7885 100644
--- a/Assets/Translations/uk-UA.json
+++ b/Assets/Translations/uk-UA.json
@@ -227,14 +227,14 @@
"description": "Відображати виконавець - назва замість назва - виконавець.",
"label": "Показувати спочатку виконавця"
},
- "show-visualizer": {
- "description": "Відображати аудіовізуалізатор під час відтворення музики.",
- "label": "Показувати візуалізатор"
- },
"show-progress-ring": {
"description": "Відображати круговий індикатор прогресу, що показує просування треку.",
"label": "Показувати кільце прогресу"
},
+ "show-visualizer": {
+ "description": "Відображати аудіовізуалізатор під час відтворення музики.",
+ "label": "Показувати візуалізатор"
+ },
"use-fixed-width": {
"description": "Коли увімкнено, віджет завжди використовуватиме максимальну ширину замість динамічного налаштування до вмісту.",
"label": "Використовувати фіксовану ширину"
@@ -345,14 +345,14 @@
"description": "Кількість символів для відображення з назв робочих просторів (1-10).",
"label": "Кількість символів"
},
- "hide-unoccupied": {
- "description": "Не відображати робочі простори без вікон.",
- "label": "Приховати незайняті"
- },
"follow-focused-screen": {
"description": "Відображати робочі простори з поточного активного екрана, а не з екрана, на якому розташована панель.",
"label": "Слідувати за Активним Екраном"
},
+ "hide-unoccupied": {
+ "description": "Не відображати робочі простори без вікон.",
+ "label": "Приховати незайняті"
+ },
"label-mode": {
"description": "Виберіть, як відображаються мітки робочих просторів.",
"label": "Режим міток"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "Рівень заряду акумулятора",
"brightness": "Яскравість",
- "charge-level": "Рівень заряду",
"charging": "Зарядка.",
"charging-rate": "Швидкість зарядки: {rate} Вт.",
"discharging": "Розрядка.",
@@ -492,13 +492,13 @@
"title": "Сповіщення"
},
"time": {
- "now": "зараз",
- "diffM": "1 хвилину тому",
- "diffMM": "{diff} хвилин тому",
+ "diffD": "1 день тому",
+ "diffDD": "{diff} днів тому",
"diffH": "1 годину тому",
"diffHH": "{diff} годин тому",
- "diffD": "1 день тому",
- "diffDD": "{diff} днів тому"
+ "diffM": "1 хвилину тому",
+ "diffMM": "{diff} хвилин тому",
+ "now": "зараз"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "Записати {filepath}.",
+ "description-missing": "Потрібна установка {app}"
+ },
"code": {
"description": "Записати {filepath}. Тему Hyprluna потрібно встановити та активувати вручну.",
"description-missing": "Клієнт Code не виявлено. Встановіть VSCode або VSCodium."
@@ -1048,10 +1052,6 @@
"description": "Записати {filepath}.",
"description-missing": "Потрібна установка {app}"
},
- "cava": {
- "description": "Записати {filepath}.",
- "description-missing": "Потрібна установка {app}"
- },
"vicinae": {
"description": "Записати {filepath} та перезавантажити",
"description-missing": "Потрібна установка {app}"
@@ -1419,14 +1419,14 @@
"description": "Використовувати власний префікс для запуску програм замість стандартного методу.",
"label": "Увімкнути власний префікс запуску"
},
- "position": {
- "description": "Виберіть, де з'являється панель запускача.",
- "label": "Положення"
- },
"grid-view": {
"description": "Показувати елементи у вигляді сітки замість списку.",
"label": "Вигляд сітки"
},
+ "position": {
+ "description": "Виберіть, де з'являється панель запускача.",
+ "label": "Положення"
+ },
"section": {
"description": "Налаштуйте поведінку та зовнішній вигляд запускача.",
"label": "Зовнішній вигляд"
@@ -1648,6 +1648,7 @@
"label": "Загальні"
}
},
+ "title": "Екранна індикація",
"types": {
"brightness": {
"description": "Показувати OSD, коли змінюється яскравість екрана.",
@@ -1662,19 +1663,14 @@
"label": "Клавіші блокування"
},
"section": {
- "description": "Виберіть події, які запускають екранну індикацію.",
- "label": "Типи OSD"
+ "description": "Виберіть події, які запускають екранне меню. Якщо жодну подію не вибрано, екранне меню запускатиметься всіма доступними подіями.",
+ "label": "Події, що запускають OSD"
},
"volume": {
"description": "Показувати OSD, коли змінюється гучність аудіовиходу.",
"label": "Вихідна гучність"
}
- },
- "show-lock-key-notifications": {
- "description": "Показувати сповіщення, коли перемикаються клавіші Caps Lock, Num Lock або Scroll Lock.",
- "label": "Показувати сповіщення про стан клавіш"
- },
- "title": "Екранна індикація"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json
index aab06a56..3cc2ade2 100644
--- a/Assets/Translations/zh-CN.json
+++ b/Assets/Translations/zh-CN.json
@@ -227,14 +227,14 @@
"description": "显示艺术家 - 标题,而不是标题 - 艺术家。",
"label": "先显示艺术家"
},
- "show-visualizer": {
- "description": "播放音乐时显示音频可视化器。",
- "label": "显示可视化器"
- },
"show-progress-ring": {
"description": "显示显示曲目进度的圆形进度指示器。",
"label": "显示进度环"
},
+ "show-visualizer": {
+ "description": "播放音乐时显示音频可视化器。",
+ "label": "显示可视化器"
+ },
"use-fixed-width": {
"description": "启用后,小部件将始终使用最大宽度,而不根据内容动态调整。",
"label": "使用固定宽度"
@@ -345,14 +345,14 @@
"description": "显示工作区名称的字符数量(1-10)。",
"label": "字符数量"
},
- "hide-unoccupied": {
- "description": "不显示没有窗口的工作区。",
- "label": "隐藏未占用"
- },
"follow-focused-screen": {
"description": "显示当前焦点屏幕的工作区,而不是任务栏所在屏幕的工作区。",
"label": "跟随焦点屏幕"
},
+ "hide-unoccupied": {
+ "description": "不显示没有窗口的工作区。",
+ "label": "隐藏未占用"
+ },
"label-mode": {
"description": "选择工作区标签的显示方式。",
"label": "标签模式"
@@ -361,8 +361,8 @@
}
},
"battery": {
+ "battery-level": "电池电量",
"brightness": "亮度",
- "charge-level": "电量",
"charging": "正在充电。",
"charging-rate": "充电速率:{rate} W。",
"discharging": "正在放电。",
@@ -492,13 +492,13 @@
"title": "通知"
},
"time": {
- "now": "现在",
- "diffM": "1 分钟前",
- "diffMM": "{diff} 分钟前",
+ "diffD": "1 天前",
+ "diffDD": "{diff} 天前",
"diffH": "1 小时前",
"diffHH": "{diff} 小时前",
- "diffD": "1 天前",
- "diffDD": "{diff} 天前"
+ "diffM": "1 分钟前",
+ "diffMM": "{diff} 分钟前",
+ "now": "现在"
}
},
"options": {
@@ -1022,6 +1022,10 @@
}
},
"programs": {
+ "cava": {
+ "description": "写入 {filepath}。",
+ "description-missing": "需要安装 {app}"
+ },
"code": {
"description": "写入 {filepath}。Hyprluna 主题需要手动安装和激活。",
"description-missing": "未检测到 Code 客户端。请安装 VSCode 或 VSCodium。"
@@ -1048,10 +1052,6 @@
"description": "写入 {filepath}。",
"description-missing": "需要安装 {app}"
},
- "cava": {
- "description": "写入 {filepath}。",
- "description-missing": "需要安装 {app}"
- },
"vicinae": {
"description": "写入 {filepath} 并重新加载",
"description-missing": "需要安装 {app}"
@@ -1419,14 +1419,14 @@
"description": "使用自定义前缀启动应用程序,而不是默认方法。",
"label": "启用自定义启动前缀"
},
- "position": {
- "description": "选择启动器面板出现的位置。",
- "label": "位置"
- },
"grid-view": {
"description": "以网格布局而非列表显示项目。",
"label": "网格视图"
},
+ "position": {
+ "description": "选择启动器面板出现的位置。",
+ "label": "位置"
+ },
"section": {
"description": "自定义启动器的行为和外观。",
"label": "外观"
@@ -1648,6 +1648,7 @@
"label": "常规"
}
},
+ "title": "屏显菜单",
"types": {
"brightness": {
"description": "当屏幕亮度发生变化时显示 OSD。",
@@ -1662,19 +1663,14 @@
"label": "锁定键"
},
"section": {
- "description": "选择哪些事件会触发屏显菜单。",
- "label": "OSD 类型"
+ "description": "选择触发OSD的事件。如果未选择任何事件,则所有可用事件都将触发OSD。",
+ "label": "OSD触发事件"
},
"volume": {
"description": "当音频输出音量发生变化时显示 OSD。",
"label": "输出音量"
}
- },
- "show-lock-key-notifications": {
- "description": "当大写锁定键、数字锁定键或滚动锁定键被切换时显示通知。",
- "label": "显示锁定键通知"
- },
- "title": "屏显菜单"
+ }
},
"screen-recorder": {
"audio": {
diff --git a/Assets/noctalia-shape.svg b/Assets/noctalia-shape.svg
deleted file mode 100644
index 631dabf5..00000000
--- a/Assets/noctalia-shape.svg
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
diff --git a/Assets/settings-default.json b/Assets/settings-default.json
index ec5773a1..2f8907a2 100644
--- a/Assets/settings-default.json
+++ b/Assets/settings-default.json
@@ -1,6 +1,5 @@
{
- "settingsVersion": 24,
- "setupCompleted": false,
+ "settingsVersion": 25,
"bar": {
"position": "top",
"backgroundOpacity": 1,
@@ -118,7 +117,6 @@
"enableMultiMonitorDirectories": false,
"recursiveSearch": false,
"setWallpaperOnAllMonitors": true,
- "defaultWallpaper": "",
"fillMode": "crop",
"fillColor": "#000000",
"randomEnabled": false,
@@ -126,7 +124,6 @@
"transitionDuration": 1500,
"transitionType": "random",
"transitionEdgeSmoothness": 0.05,
- "monitors": [],
"panelPosition": "follow_bar",
"hideWallpaperFilenames": false,
"useWallhaven": false,
@@ -137,7 +134,9 @@
"wallhavenPurity": "100",
"wallhavenResolutionMode": "atleast",
"wallhavenResolutionWidth": "",
- "wallhavenResolutionHeight": ""
+ "wallhavenResolutionHeight": "",
+ "defaultWallpaper": "",
+ "monitors": []
},
"appLauncher": {
"enableClipboardHistory": false,
@@ -221,7 +220,7 @@
},
"dock": {
"enabled": true,
- "displayMode": "always_visible",
+ "displayMode": "auto_hide",
"backgroundOpacity": 1,
"radiusRatio": 0.1,
"floatingRatio": 1,
@@ -280,12 +279,12 @@
},
"osd": {
"enabled": true,
- "enabledTypes": [0, 1, 2, 3],
"location": "top_right",
- "monitors": [],
"autoHideMs": 2000,
"overlayLayer": true,
- "backgroundOpacity": 1
+ "backgroundOpacity": 1,
+ "enabledTypes": [],
+ "monitors": []
},
"audio": {
"volumeStep": 5,
diff --git a/CREDITS.md b/CREDITS.md
new file mode 100644
index 00000000..a71a8368
--- /dev/null
+++ b/CREDITS.md
@@ -0,0 +1,50 @@
+# Credits
+
+Noctalia Shell is made possible by the incredible work of many open-source projects and contributors.
+
+## Design & Branding
+
+- **MrDowntempo** - Creator of the Noctalia Owl and moon logo
+- **[SaberJ2X](https://www.reddit.com/user/SaberJ64/)** - Creator of Talia, the Noctalia mascot
+
+## Core Framework
+
+- **[Quickshell](https://github.com/outfoxxed/quickshell)** - The Qt/QML-based Wayland shell framework that powers Noctalia
+
+## Runtime Dependencies
+
+### System Integration
+- **[brightnessctl](https://github.com/Hummer12007/brightnessctl)** - Screen brightness control
+- **[wlsunset](https://sr.ht/~kennylevinsen/wlsunset/)** - Night light and blue light filter support
+- **[wl-clipboard](https://github.com/bugaevc/wl-clipboard)** - Wayland clipboard utilities
+- **[ddcutil](https://www.ddcutil.com/)** - External display brightness control
+- **[power-profiles-daemon](https://gitlab.freedesktop.org/upower/power-profiles-daemon)** - Power profile management
+
+### Media & Audio
+- **[gpu-screen-recorder](https://git.dec05eba.com/gpu-screen-recorder/about/)** - Hardware-accelerated screen recording
+- **[Cava](https://github.com/karlstav/cava)** - Audio visualizer component
+
+### Theming & Appearance
+- **[Matugen](https://github.com/InioX/matugen)** - Material You color scheme generation from wallpapers
+- **[Inter Font](https://rsms.me/inter/)** - UI font family
+- **[Roboto](https://fonts.google.com/specimen/Roboto)** - Additional UI font family
+
+### Utilities
+- **[cliphist](https://github.com/sentriz/cliphist)** - Clipboard history support
+
+## Audio Assets
+
+- **[DrNI on Freesound](https://freesound.org/people/DrNI/sounds/34562/)** - Notification sound effect
+
+
+## Special Thanks
+
+- The **Wayland** community for building the future of Linux desktop graphics
+- The **Niri**, **Hyprland**, **Sway**, and **MangoWC** teams for their excellent Wayland compositors
+- All the contributors and users who have helped make Noctalia better
+
+## License
+
+Noctalia Shell is licensed under the MIT License. See [LICENSE](LICENSE) for details.
+
+Each dependency listed above is governed by its own respective license. Please refer to their individual projects for licensing information.
diff --git a/Commons/IconsTabler.qml b/Commons/IconsTabler.qml
index 7a0b5e80..21c7aa67 100644
--- a/Commons/IconsTabler.qml
+++ b/Commons/IconsTabler.qml
@@ -92,6 +92,7 @@ Singleton {
"microphone": "microphone",
"microphone-mute": "microphone-off",
"volume-mute": "volume-off",
+ "volume-x": "volume-3",
"volume-zero": "volume-3",
"volume-low": "volume-2",
"volume-high": "volume",
diff --git a/Commons/Settings.qml b/Commons/Settings.qml
index 0ec81bd3..69eb2c97 100644
--- a/Commons/Settings.qml
+++ b/Commons/Settings.qml
@@ -5,33 +5,37 @@ import Quickshell
import Quickshell.Io
import "../Helpers/QtObj2JS.js" as QtObj2JS
import qs.Commons
+import qs.Services.Power
+import qs.Services.System
import qs.Services.UI
Singleton {
id: root
- // Used to access via Settings.data.xxx.yyy
- readonly property alias data: adapter
property bool isLoaded: false
property bool directoriesCreated: false
- property int settingsVersion: 24
- property bool isDebug: Quickshell.env("NOCTALIA_DEBUG") === "1"
+ property bool shouldOpenSetupWizard: false
- // Define our app directories
- // Default config directory: ~/.config/noctalia
- // Default cache directory: ~/.cache/noctalia
- property string shellName: "noctalia"
- property string configDir: Quickshell.env("NOCTALIA_CONFIG_DIR") || (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/" + shellName + "/"
- property string cacheDir: Quickshell.env("NOCTALIA_CACHE_DIR") || (Quickshell.env("XDG_CACHE_HOME") || Quickshell.env("HOME") + "/.cache") + "/" + shellName + "/"
- property string cacheDirImages: cacheDir + "images/"
- property string cacheDirImagesWallpapers: cacheDir + "images/wallpapers/"
- property string cacheDirImagesNotifications: cacheDir + "images/notifications/"
- property string settingsFile: Quickshell.env("NOCTALIA_SETTINGS_FILE") || (configDir + "settings.json")
-
- property string defaultLocation: "Tokyo"
- property string defaultAvatar: Quickshell.env("HOME") + "/.face"
- property string defaultVideosDirectory: Quickshell.env("HOME") + "/Videos"
- property string defaultWallpapersDirectory: Quickshell.env("HOME") + "/Pictures/Wallpapers"
+ /*
+ Shell directories.
+ - Default config directory: ~/.config/noctalia
+ - Default cache directory: ~/.cache/noctalia
+ */
+ readonly property alias data: adapter // Used to access via Settings.data.xxx.yyy
+ readonly property int settingsVersion: 25
+ readonly property bool isDebug: Quickshell.env("NOCTALIA_DEBUG") === "1"
+ readonly property string shellName: "noctalia"
+ readonly property string configDir: Quickshell.env("NOCTALIA_CONFIG_DIR") || (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/" + shellName + "/"
+ readonly property string cacheDir: Quickshell.env("NOCTALIA_CACHE_DIR") || (Quickshell.env("XDG_CACHE_HOME") || Quickshell.env("HOME") + "/.cache") + "/" + shellName + "/"
+ readonly property string cacheDirImages: cacheDir + "images/"
+ readonly property string cacheDirImagesWallpapers: cacheDir + "images/wallpapers/"
+ readonly property string cacheDirImagesNotifications: cacheDir + "images/notifications/"
+ readonly property string settingsFile: Quickshell.env("NOCTALIA_SETTINGS_FILE") || (configDir + "settings.json")
+ readonly property string defaultLocation: "Tokyo"
+ readonly property string defaultAvatar: Quickshell.env("HOME") + "/.face"
+ readonly property string defaultVideosDirectory: Quickshell.env("HOME") + "/Videos"
+ readonly property string defaultWallpapersDirectory: Quickshell.env("HOME") + "/Pictures/Wallpapers"
+ readonly property string defaultWallpaper: Quickshell.shellDir + "/Assets/Wallpaper/noctalia.png"
// Signal emitted when settings are loaded after startupcale changes
signal settingsLoaded
@@ -62,7 +66,6 @@ Singleton {
adapter.general.avatarImage = defaultAvatar;
adapter.screenRecorder.directory = defaultVideosDirectory;
adapter.wallpaper.directory = defaultWallpapersDirectory;
- adapter.wallpaper.defaultWallpaper = Quickshell.shellDir + "/Assets/Wallpaper/noctalia.png";
// Set the adapter to the settingsFileView to trigger the real settings load
settingsFileView.adapter = adapter;
@@ -98,8 +101,8 @@ Singleton {
Logger.i("Settings", "Settings loaded");
upgradeSettingsData();
- validateMonitorConfigurations();
- isLoaded = true;
+
+ root.isLoaded = true;
// Emit the signal
root.settingsLoaded();
@@ -112,10 +115,14 @@ Singleton {
if (error.toString().includes("No such file") || error === 2) {
// File doesn't exist, create it with default values
writeAdapter();
+
// Also write to fallback if set
if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) {
settingsFallbackFileView.writeAdapter();
}
+
+ // We started without settings, we should open the setupWizard
+ root.shouldOpenSetupWizard = true;
}
}
}
@@ -128,11 +135,11 @@ Singleton {
printErrors: false
watchChanges: false
}
+
JsonAdapter {
id: adapter
property int settingsVersion: root.settingsVersion
- property bool setupCompleted: false
// bar
property JsonObject bar: JsonObject {
@@ -271,7 +278,6 @@ Singleton {
property bool enableMultiMonitorDirectories: false
property bool recursiveSearch: false
property bool setWallpaperOnAllMonitors: true
- property string defaultWallpaper: ""
property string fillMode: "crop"
property color fillColor: "#000000"
property bool randomEnabled: false
@@ -279,7 +285,6 @@ Singleton {
property int transitionDuration: 1500 // 1500 ms
property string transitionType: "random"
property real transitionEdgeSmoothness: 0.05
- property list monitors: []
property string panelPosition: "follow_bar"
property bool hideWallpaperFilenames: false
// Wallhaven settings
@@ -292,6 +297,9 @@ Singleton {
property string wallhavenResolutionMode: "atleast" // "atleast" or "exact"
property string wallhavenResolutionWidth: ""
property string wallhavenResolutionHeight: ""
+
+ property string defaultWallpaper: "" // TODO REMOVE
+ property list monitors: [] // TODO REMOVE
}
// applauncher
@@ -387,7 +395,7 @@ Singleton {
// dock
property JsonObject dock: JsonObject {
property bool enabled: true
- property string displayMode: "always_visible" // "always_visible", "auto_hide", "exclusive"
+ property string displayMode: "auto_hide" // "always_visible", "auto_hide", "exclusive"
property real backgroundOpacity: 1.0
property real radiusRatio: 0.1
property real floatingRatio: 1.0
@@ -455,12 +463,12 @@ Singleton {
// on-screen display
property JsonObject osd: JsonObject {
property bool enabled: true
- property var enabledTypes: [0, 1, 2, 3]
property string location: "top_right"
- property list monitors: []
property int autoHideMs: 2000
property bool overlayLayer: true
property real backgroundOpacity: 1.0
+ property list enabledTypes: []
+ property list monitors: []
}
// audio
@@ -587,36 +595,39 @@ Singleton {
}
// -----------------------------------------------------
- // Function to validate monitor configurations
- function validateMonitorConfigurations() {
- var availableScreenNames = [];
- for (var i = 0; i < Quickshell.screens.length; i++) {
- availableScreenNames.push(Quickshell.screens[i].name);
+ // Function to clean up deprecated user/custom bar widgets settings
+ function upgradeWidget(widget) {
+ // Backup the widget definition before altering
+ const widgetBefore = JSON.stringify(widget);
+
+ // Get all existing custom settings keys
+ const keys = Object.keys(BarWidgetRegistry.widgetMetadata[widget.id]);
+
+ // Delete deprecated user settings from the wiget
+ for (const k of Object.keys(widget)) {
+ if (k === "id" || k === "allowUserSettings") {
+ continue;
+ }
+ if (!keys.includes(k)) {
+ delete widget[k];
+ }
}
- Logger.d("Settings", "Available monitors: [" + availableScreenNames.join(", ") + "]");
- Logger.d("Settings", "Configured bar monitors: [" + adapter.bar.monitors.join(", ") + "]");
-
- // Check bar monitors
- if (adapter.bar.monitors.length > 0) {
- var hasValidBarMonitor = false;
- for (var j = 0; j < adapter.bar.monitors.length; j++) {
- if (availableScreenNames.includes(adapter.bar.monitors[j])) {
- hasValidBarMonitor = true;
- break;
- }
+ // Inject missing default setting (metaData) from BarWidgetRegistry
+ for (var i = 0; i < keys.length; i++) {
+ const k = keys[i];
+ if (k === "id" || k === "allowUserSettings") {
+ continue;
}
- if (!hasValidBarMonitor) {
- Logger.w("Settings", "No configured bar monitors found on system, clearing bar monitor list to show on all screens");
- adapter.bar.monitors = [];
- } else
- //Logger.i("Settings", "Found valid bar monitors, keeping configuration")
- {}
- } else
+ if (widget[k] === undefined) {
+ widget[k] = BarWidgetRegistry.widgetMetadata[widget.id][k];
+ }
+ }
- //Logger.i("Settings", "Bar monitor list is empty, will show on all available screens")
- {}
+ // Compare settings, to detect if something has been upgraded
+ const widgetAfter = JSON.stringify(widget);
+ return (widgetAfter !== widgetBefore);
}
// -----------------------------------------------------
@@ -718,91 +729,7 @@ Singleton {
}
// -----------------
- // 5th. Migrate Discord templates (version 20 → 21)
- // Consolidate individual discord_* properties into unified discord property
- if (adapter.settingsVersion < 21) {
- // Read raw JSON file to access properties not in adapter schema
- try {
- var rawJson = settingsFileView.text();
-
- if (rawJson) {
- var parsed = JSON.parse(rawJson);
- var anyDiscordEnabled = false;
-
- // Check if any Discord client was enabled
- const discordClients = ["discord_vesktop", "discord_webcord", "discord_armcord", "discord_equibop", "discord_lightcord", "discord_dorion", "discord_vencord"];
-
- if (parsed.templates) {
- for (var i = 0; i < discordClients.length; i++) {
- if (parsed.templates[discordClients[i]]) {
- anyDiscordEnabled = true;
- break;
- }
- }
- }
-
- // Set unified discord property
- adapter.templates.discord = anyDiscordEnabled;
-
- Logger.i("Settings", "Migrated Discord templates to unified 'discord' property (enabled:", anyDiscordEnabled + ")");
- }
- } catch (error) {
- Logger.w("Settings", "Failed to read raw JSON for Discord migration:", error);
- }
- }
-
- // -----------------
- // 6th. Migrate panel background opacity (version 21 → 22)
- // Move appLauncher.backgroundOpacity to ui.panelBackgroundOpacity
- if (adapter.settingsVersion < 22) {
- // Read raw JSON file to access properties not in adapter schema
- try {
- var rawJson = settingsFileView.text();
-
- if (rawJson) {
- var parsed = JSON.parse(rawJson);
- if (parsed.appLauncher && parsed.appLauncher.backgroundOpacity !== undefined) {
- var oldOpacity = parsed.appLauncher.backgroundOpacity;
- if (adapter.ui) {
- adapter.ui.panelBackgroundOpacity = oldOpacity;
- Logger.i("Settings", "Migrated appLauncher.backgroundOpacity to ui.panelBackgroundOpacity (value:", oldOpacity + ")");
- }
- }
- }
- } catch (error) {
- Logger.w("Settings", "Failed to read raw JSON for migration:", error);
- }
- }
-
- // -----------------
- // 7th. Migrate dim desktop settings (version 22 → 23)
- // If dimDesktop is enabled, set dimmerOpacity to 0.8 if it's not already set or is 0
- // Then remove dimDesktop property as it's no longer needed
- if (adapter.settingsVersion < 23) {
- // Read raw JSON file to access dimDesktop property
- try {
- var rawJson = settingsFileView.text();
-
- if (rawJson) {
- var parsed = JSON.parse(rawJson);
- if (parsed.general && parsed.general.dimDesktop === true) {
- // Check if dimmerOpacity exists in raw JSON (not adapter default)
- var dimmerOpacityInJson = parsed.general.dimmerOpacity;
-
- // If dimmerOpacity wasn't explicitly set in JSON or was 0, set it to 0.8 (80% dimming)
- if (dimmerOpacityInJson === undefined || dimmerOpacityInJson === 0) {
- adapter.general.dimmerOpacity = 0.8;
- Logger.i("Settings", "Migrated dimDesktop=true: set dimmerOpacity to 0.8 (80% dimming)");
- }
- }
- }
- } catch (error) {
- Logger.w("Settings", "Failed to read raw JSON for dimDesktop migration:", error);
- }
- }
-
- // -----------------
- // 9th. Normalize OSD enabled types and migrate legacy show* toggles
+ // TEMP Normalize OSD enabled types and migrate legacy show* toggles
try {
var osdRawJson = settingsFileView.text();
if (osdRawJson) {
@@ -896,19 +823,49 @@ Singleton {
// -----------------
// Migrate ShellState-related files from old cache files to ShellState
- // This consolidates migrations that were previously in individual service files
- if (typeof ShellState !== 'undefined' && ShellState.isLoaded) {
- migrateShellStateFiles();
- } else {
- // Wait for ShellState to be ready
- Qt.callLater(() => {
- if (typeof ShellState !== 'undefined' && ShellState.isLoaded) {
- migrateShellStateFiles();
- }
- });
+ // This consolidates migrations that were previously in individual files
+ if (adapter.settingsVersion < 25) {
+ // Only migrate the settings once!
+ if (ShellState?.isLoaded) {
+ migrateShellStateFiles();
+ } else {
+ // Wait for ShellState to be ready
+ Qt.callLater(() => {
+ if (ShellState?.isLoaded) {
+ migrateShellStateFiles();
+ }
+ });
+ }
}
}
+ // -----------------------------------------------------
+ function buildStateSnapshot() {
+ try {
+ const settingsData = QtObj2JS.qtObjectToPlainObject(adapter);
+ const shellStateData = ShellState?.data ? QtObj2JS.qtObjectToPlainObject(ShellState.data) || {} : {};
+
+ return {
+ settings: settingsData,
+ state: {
+ doNotDisturb: NotificationService.doNotDisturb,
+ noctaliaPerformanceMode: PowerProfileService.noctaliaPerformanceMode,
+ barVisible: BarService.isVisible,
+ display: shellStateData.display || {},
+ wallpapers: shellStateData.wallpapers || {},
+ notificationsState: shellStateData.notificationsState || {},
+ changelogState: shellStateData.changelogState || {},
+ colorSchemesList: shellStateData.colorSchemesList || {}
+ }
+ };
+ } catch (error) {
+ Logger.e("Settings", "Failed to build state snapshot:", error);
+ return null;
+ }
+ }
+
+ // -----------------------------------------------------
+ // --- TO BE REMOVED
// -----------------------------------------------------
// Migrate old cache files to ShellState
function migrateShellStateFiles() {
@@ -928,6 +885,7 @@ Singleton {
migrateWallpaperPaths();
}
+ // -----------------------------------------------------
function migrateDisplayFile() {
// Check if ShellState already has display data
const cached = ShellState.getDisplay();
@@ -961,6 +919,7 @@ Singleton {
`, root, "displayMigrationView");
}
+ // -----------------------------------------------------
function migrateNotificationsStateFile() {
// Check if ShellState already has notifications state
const cached = ShellState.getNotificationsState();
@@ -1108,39 +1067,4 @@ Singleton {
}
}
}
-
- // -----------------------------------------------------
- function upgradeWidget(widget) {
- // Backup the widget definition before altering
- const widgetBefore = JSON.stringify(widget);
-
- // Get all existing custom settings keys
- const keys = Object.keys(BarWidgetRegistry.widgetMetadata[widget.id]);
-
- // Delete deprecated user settings from the wiget
- for (const k of Object.keys(widget)) {
- if (k === "id" || k === "allowUserSettings") {
- continue;
- }
- if (!keys.includes(k)) {
- delete widget[k];
- }
- }
-
- // Inject missing default setting (metaData) from BarWidgetRegistry
- for (var i = 0; i < keys.length; i++) {
- const k = keys[i];
- if (k === "id" || k === "allowUserSettings") {
- continue;
- }
-
- if (widget[k] === undefined) {
- widget[k] = BarWidgetRegistry.widgetMetadata[widget.id][k];
- }
- }
-
- // Compare settings, to detect if something has been upgraded
- const widgetAfter = JSON.stringify(widget);
- return (widgetAfter !== widgetBefore);
- }
}
diff --git a/Modules/Bar/Extras/BarPillHorizontal.qml b/Modules/Bar/Extras/BarPillHorizontal.qml
index cd9358b9..107dc96c 100644
--- a/Modules/Bar/Extras/BarPillHorizontal.qml
+++ b/Modules/Bar/Extras/BarPillHorizontal.qml
@@ -23,6 +23,8 @@ Item {
property color customBackgroundColor: Color.transparent
property color customTextIconColor: Color.transparent
+ readonly property bool collapseToIcon: forceClose && !forceOpen
+
// Effective shown state (true if hovered/animated open or forced)
readonly property bool revealed: !forceClose && (forceOpen || showPill)
@@ -66,7 +68,7 @@ Item {
}
}
- width: pillHeight + Math.max(0, pill.width - pillOverlap)
+ width: collapseToIcon ? pillHeight : pillHeight + Math.max(0, pill.width - pillOverlap)
height: pillHeight
Connections {
@@ -81,7 +83,7 @@ Item {
// Unified background for the entire pill area to avoid overlapping opacity
Rectangle {
id: pillBackground
- width: root.width
+ width: collapseToIcon ? pillHeight : root.width
height: pillHeight
radius: halfPillHeight
color: root.bgColor
@@ -290,6 +292,8 @@ Item {
}
function show() {
+ if (collapseToIcon)
+ return;
if (!showPill) {
shouldAnimateHide = autoHide;
showAnim.start();
@@ -300,6 +304,8 @@ Item {
}
function hide() {
+ if (collapseToIcon)
+ return;
if (forceOpen) {
return;
}
@@ -310,6 +316,8 @@ Item {
}
function showDelayed() {
+ if (collapseToIcon)
+ return;
if (!showPill) {
shouldAnimateHide = autoHide;
showTimer.start();
diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Modules/Bar/Extras/BarPillVertical.qml
index 494d47d7..b8ab6859 100644
--- a/Modules/Bar/Extras/BarPillVertical.qml
+++ b/Modules/Bar/Extras/BarPillVertical.qml
@@ -24,6 +24,8 @@ Item {
property color customBackgroundColor: Color.transparent
property color customTextIconColor: Color.transparent
+ readonly property bool collapseToIcon: forceClose && !forceOpen
+
signal shown
signal hidden
signal entered
@@ -76,7 +78,7 @@ Item {
// For vertical bars: width is just icon size, height includes pill space
width: buttonSize
- height: revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize
+ height: collapseToIcon ? buttonSize : (revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize)
Connections {
target: root
@@ -91,7 +93,7 @@ Item {
Rectangle {
id: pillBackground
width: buttonSize
- height: revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize
+ height: collapseToIcon ? buttonSize : (revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize)
radius: halfButtonSize
color: root.bgColor
@@ -321,6 +323,8 @@ Item {
}
function show() {
+ if (collapseToIcon)
+ return;
if (!showPill) {
shouldAnimateHide = autoHide;
showAnim.start();
@@ -331,6 +335,8 @@ Item {
}
function hide() {
+ if (collapseToIcon)
+ return;
if (forceOpen) {
return;
}
@@ -341,6 +347,8 @@ Item {
}
function showDelayed() {
+ if (collapseToIcon)
+ return;
if (!showPill) {
shouldAnimateHide = autoHide;
showTimer.start();
diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml
index 1fa1e28d..e57f01b7 100644
--- a/Modules/Bar/Widgets/Bluetooth.qml
+++ b/Modules/Bar/Widgets/Bluetooth.qml
@@ -87,7 +87,7 @@ Item {
}
autoHide: false
forceOpen: !isBarVertical && root.displayMode === "alwaysShow"
- forceClose: isBarVertical || root.displayMode === "alwaysHide" || BluetoothService.connectedDevices.length === 0
+ forceClose: isBarVertical || root.displayMode === "alwaysHide"
onClicked: PanelService.getPanel("bluetoothPanel", screen)?.toggle(this)
onRightClicked: {
var popupMenuWindow = PanelService.getPopupMenuWindow(screen);
diff --git a/Modules/Bar/Widgets/Brightness.qml b/Modules/Bar/Widgets/Brightness.qml
index bd0f5d08..160d02c6 100644
--- a/Modules/Bar/Widgets/Brightness.qml
+++ b/Modules/Bar/Widgets/Brightness.qml
@@ -47,6 +47,8 @@ Item {
function getIcon() {
var monitor = getMonitor();
var brightness = monitor ? monitor.brightness : 0;
+ if (brightness <= 0.001)
+ return "sun-off";
return brightness <= 0.5 ? "brightness-low" : "brightness-high";
}
diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml
index 43dca611..a4ca5f1b 100644
--- a/Modules/Bar/Widgets/MediaMini.qml
+++ b/Modules/Bar/Widgets/MediaMini.qml
@@ -409,16 +409,17 @@ Item {
anchors.fill: parent
anchors.margins: showProgressRing ? (3 * scaling) : 0.5 // Adjusted to align with progress circle better
- NImageCircled {
+ NImageRounded {
id: trackArt
anchors.fill: parent
anchors.margins: showProgressRing ? 0 : -1 * scaling // Add negative margin to make album art larger when no progress ring
+ radius: width * 0.5
visible: showAlbumArt && hasActivePlayer
imagePath: MediaService.trackArtUrl
fallbackIcon: MediaService.isPlaying ? "media-pause" : "media-play"
fallbackIconSize: showProgressRing ? 10 : 12 // Larger fallback icon when no progress ring
borderWidth: 0
- border.color: Color.transparent
+ borderColor: Color.transparent
z: 1 // In front of the progress circle
}
@@ -649,9 +650,10 @@ Item {
z: 1 // Above the visualizer and progress ring
// Album Art
- NImageCircled {
+ NImageRounded {
anchors.fill: parent
visible: showAlbumArt && hasActivePlayer
+ radius: width * 0.5
imagePath: MediaService.trackArtUrl
fallbackIcon: MediaService.isPlaying ? "media-pause" : "media-play"
fallbackIconSize: 12
diff --git a/Modules/Bar/Widgets/Tray.qml b/Modules/Bar/Widgets/Tray.qml
index dfd98fee..c3fd3307 100644
--- a/Modules/Bar/Widgets/Tray.qml
+++ b/Modules/Bar/Widgets/Tray.qml
@@ -161,10 +161,14 @@ Rectangle {
}
//Logger.d("Tray", "wildCardMatch - Input str:", str, "rule:", rule)
- // Escape all special regex characters in the rule
- let escapedRule = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- // Convert '*' to '.*' for wildcard matching
- let pattern = escapedRule.replace(/\\\*/g, '.*');
+ // First, convert '*' to a placeholder to preserve it, then escape other special regex characters
+ // Use a unique placeholder that won't appear in normal strings
+ const placeholder = '\uE000'; // Private use character
+ let processedRule = rule.replace(/\*/g, placeholder);
+ // Escape all special regex characters (but placeholder won't match this)
+ let escapedRule = processedRule.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
+ // Convert placeholder back to '.*' for wildcard matching
+ let pattern = escapedRule.replace(new RegExp(placeholder, 'g'), '.*');
// Add ^ and $ to match the entire string
pattern = '^' + pattern + '$';
diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml
index 26f699b7..f2832a1d 100644
--- a/Modules/Bar/Widgets/WiFi.qml
+++ b/Modules/Bar/Widgets/WiFi.qml
@@ -109,7 +109,7 @@ Item {
}
autoHide: false
forceOpen: !isBarVertical && root.displayMode === "alwaysShow"
- forceClose: isBarVertical || root.displayMode === "alwaysHide" || !pill.text
+ forceClose: isBarVertical || root.displayMode === "alwaysHide"
onClicked: PanelService.getPanel("wifiPanel", screen)?.toggle(this)
onRightClicked: {
var popupMenuWindow = PanelService.getPopupMenuWindow(screen);
diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml
index 1612017d..325395b4 100644
--- a/Modules/LockScreen/LockScreen.qml
+++ b/Modules/LockScreen/LockScreen.qml
@@ -301,10 +301,11 @@ Loader {
}
}
- NImageCircled {
+ NImageRounded {
anchors.centerIn: parent
width: 66
height: 66
+ radius: width * 0.5
imagePath: Settings.preprocessPath(Settings.data.general.avatarImage)
fallbackIcon: "person"
@@ -631,9 +632,10 @@ Loader {
color: Color.transparent
clip: true
- NImageCircled {
+ NImageRounded {
anchors.fill: parent
anchors.margins: 2
+ radius: width * 0.5
imagePath: MediaService.trackArtUrl
fallbackIcon: "disc"
fallbackIconSize: Style.fontSizeM
diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml
index 6d39860a..d4d69db4 100644
--- a/Modules/Notification/Notification.qml
+++ b/Modules/Notification/Notification.qml
@@ -398,17 +398,16 @@ Variants {
Layout.topMargin: Style.marginM
Layout.bottomMargin: Style.marginM
- ColumnLayout {
- NImageCircled {
- Layout.preferredWidth: Math.round(40 * Style.uiScaleRatio)
- Layout.preferredHeight: Math.round(40 * Style.uiScaleRatio)
- Layout.alignment: Qt.AlignVCenter
- imagePath: model.originalImage || ""
- borderColor: Color.transparent
- borderWidth: 0
- fallbackIcon: "bell"
- fallbackIconSize: 24
- }
+ NImageRounded {
+ Layout.preferredWidth: Math.round(40 * Style.uiScaleRatio)
+ Layout.preferredHeight: Math.round(40 * Style.uiScaleRatio)
+ Layout.alignment: Qt.AlignVCenter
+ radius: width * 0.5
+ imagePath: model.originalImage || ""
+ borderColor: Color.transparent
+ borderWidth: 0
+ fallbackIcon: "bell"
+ fallbackIconSize: 24
}
ColumnLayout {
diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml
index b73a749b..bde8b597 100644
--- a/Modules/OSD/OSD.qml
+++ b/Modules/OSD/OSD.qml
@@ -49,12 +49,16 @@ Variants {
case OSD.Type.Volume:
if (isMuted)
return "volume-mute";
- if (currentVolume <= Number.EPSILON)
- return "volume-zero";
+ // Show volume-x icon when volume is effectively 0% (within rounding threshold)
+ if (currentVolume < 0.005)
+ return "volume-x";
return currentVolume <= 0.5 ? "volume-low" : "volume-high";
case OSD.Type.InputVolume:
return isInputMuted ? "microphone-off" : "microphone";
case OSD.Type.Brightness:
+ // Show sun-off icon when brightness is effectively 0% (within rounding threshold)
+ if (currentBrightness < 0.005)
+ return "sun-off";
return currentBrightness <= 0.5 ? "brightness-low" : "brightness-high";
case OSD.Type.LockKey:
return "keyboard";
@@ -488,7 +492,7 @@ Variants {
color: root.currentOSDType === OSD.Type.LockKey ? root.getProgressColor() : Color.mOnSurface
pointSize: root.currentOSDType === OSD.Type.LockKey ? Style.fontSizeM : Style.fontSizeS
family: Settings.data.ui.fontFixed
- font.weight: root.currentOSDType === OSD.Type.LockKey ? Style.fontWeightMedium : Style.fontWeightNormal
+ font.weight: root.currentOSDType === OSD.Type.LockKey ? Style.fontWeightMedium : Style.fontWeightRegular
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
diff --git a/Modules/Panels/Battery/BatteryPanel.qml b/Modules/Panels/Battery/BatteryPanel.qml
index dcac2cbd..c554120b 100644
--- a/Modules/Panels/Battery/BatteryPanel.qml
+++ b/Modules/Panels/Battery/BatteryPanel.qml
@@ -19,8 +19,7 @@ SmartPanel {
readonly property bool isReady: battery && battery.ready && battery.isLaptopBattery && battery.isPresent
readonly property int percent: isReady ? Math.round(battery.percentage * 100) : -1
readonly property bool charging: isReady ? battery.state === UPowerDeviceState.Charging : false
- readonly property bool healthSupported: isReady && battery.healthSupported
- readonly property bool healthAvailable: healthSupported
+ readonly property bool healthAvailable: isReady && battery.healthSupported
readonly property int healthPercent: healthAvailable ? Math.round(battery.healthPercentage) : -1
readonly property bool powerProfileAvailable: PowerProfileService.available
readonly property var powerProfiles: [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]
@@ -117,7 +116,7 @@ SmartPanel {
ColumnLayout {
NText {
- text: I18n.tr("battery.charge-level")
+ text: I18n.tr("battery.battery-level")
color: Color.mOnSurface
pointSize: Style.fontSizeS
}
diff --git a/Modules/Panels/ControlCenter/Cards/ProfileCard.qml b/Modules/Panels/ControlCenter/Cards/ProfileCard.qml
index b37231ed..f827b506 100644
--- a/Modules/Panels/ControlCenter/Cards/ProfileCard.qml
+++ b/Modules/Panels/ControlCenter/Cards/ProfileCard.qml
@@ -25,9 +25,10 @@ NBox {
anchors.margins: Style.marginM
spacing: Style.marginM
- NImageCircled {
+ NImageRounded {
Layout.preferredWidth: Math.round(Style.baseWidgetSize * 1.25 * Style.uiScaleRatio)
Layout.preferredHeight: Math.round(Style.baseWidgetSize * 1.25 * Style.uiScaleRatio)
+ radius: width * 0.5
imagePath: Settings.preprocessPath(Settings.data.general.avatarImage)
fallbackIcon: "person"
borderColor: Color.mPrimary
diff --git a/Modules/Panels/Launcher/Launcher.qml b/Modules/Panels/Launcher/Launcher.qml
index e8dfdcda..00537379 100644
--- a/Modules/Panels/Launcher/Launcher.qml
+++ b/Modules/Panels/Launcher/Launcher.qml
@@ -689,7 +689,7 @@ SmartPanel {
id: imagePreview
anchors.fill: parent
visible: modelData.isImage && !modelData.emojiChar
- imageRadius: Style.radiusM
+ radius: Style.radiusM
// This property creates a dependency on the service's revision counter
readonly property int _rev: ClipboardService.revision
@@ -934,7 +934,7 @@ SmartPanel {
id: gridImagePreview
anchors.fill: parent
visible: modelData.isImage && !modelData.emojiChar
- imageRadius: Style.radiusM
+ radius: Style.radiusM
readonly property int _rev: ClipboardService.revision
diff --git a/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml b/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml
index 8efde22c..4e25642c 100644
--- a/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml
+++ b/Modules/Panels/NotificationHistory/NotificationHistoryPanel.qml
@@ -197,10 +197,11 @@ SmartPanel {
spacing: Style.marginM
// Icon
- NImageCircled {
+ NImageRounded {
+ anchors.verticalCenter: parent.verticalCenter
width: Math.round(40 * Style.uiScaleRatio)
height: Math.round(40 * Style.uiScaleRatio)
- anchors.verticalCenter: parent.verticalCenter
+ radius: width * 0.5
imagePath: model.cachedImage || model.originalImage || ""
borderColor: Color.transparent
borderWidth: 0
diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml
index 7a0aa453..5f9eb339 100644
--- a/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml
+++ b/Modules/Panels/Settings/Bar/WidgetSettings/ControlCenterSettings.qml
@@ -59,10 +59,11 @@ ColumnLayout {
description: I18n.tr("bar.widget-settings.control-center.icon.description")
}
- NImageCircled {
+ NImageRounded {
Layout.preferredWidth: Style.fontSizeXL * 2
Layout.preferredHeight: Style.fontSizeXL * 2
Layout.alignment: Qt.AlignVCenter
+ radius: width * 0.5
imagePath: valueCustomIconPath
visible: valueCustomIconPath !== ""
}
diff --git a/Modules/Panels/Settings/Tabs/AboutTab.qml b/Modules/Panels/Settings/Tabs/AboutTab.qml
index 127ab7f5..f226afe6 100644
--- a/Modules/Panels/Settings/Tabs/AboutTab.qml
+++ b/Modules/Panels/Settings/Tabs/AboutTab.qml
@@ -189,10 +189,11 @@ ColumnLayout {
Layout.preferredWidth: Style.baseWidgetSize * 2 * Style.uiScaleRatio
Layout.preferredHeight: Style.baseWidgetSize * 2 * Style.uiScaleRatio
- NImageCircled {
- imagePath: modelData.avatar_url || ""
+ NImageRounded {
anchors.fill: parent
anchors.margins: Style.marginXS
+ radius: width * 0.5
+ imagePath: modelData.avatar_url || ""
fallbackIcon: "person"
borderColor: contributorArea.containsMouse ? Color.mOnHover : Color.mPrimary
borderWidth: Style.borderM
diff --git a/Modules/Panels/Settings/Tabs/GeneralTab.qml b/Modules/Panels/Settings/Tabs/GeneralTab.qml
index 481f4013..f111222b 100644
--- a/Modules/Panels/Settings/Tabs/GeneralTab.qml
+++ b/Modules/Panels/Settings/Tabs/GeneralTab.qml
@@ -21,9 +21,10 @@ ColumnLayout {
spacing: Style.marginL
// Avatar preview
- NImageCircled {
+ NImageRounded {
Layout.preferredWidth: 88 * Style.uiScaleRatio
Layout.preferredHeight: width
+ radius: width * 0.5
imagePath: Settings.preprocessPath(Settings.data.general.avatarImage)
fallbackIcon: "person"
borderColor: Color.mPrimary
diff --git a/Modules/Panels/SetupWizard/SetupWizard.qml b/Modules/Panels/SetupWizard/SetupWizard.qml
index fc64cc86..7addb49f 100644
--- a/Modules/Panels/SetupWizard/SetupWizard.qml
+++ b/Modules/Panels/SetupWizard/SetupWizard.qml
@@ -401,7 +401,6 @@ SmartPanel {
Settings.data.general.scaleRatio = selectedScaleRatio;
Settings.data.bar.position = selectedBarPosition;
- Settings.data.setupCompleted = true;
// Save settings immediately and wait for settingsSaved signal before closing
Settings.saveImmediate();
diff --git a/Modules/Panels/Tray/TrayDrawerPanel.qml b/Modules/Panels/Tray/TrayDrawerPanel.qml
index 2573f439..c114c74c 100644
--- a/Modules/Panels/Tray/TrayDrawerPanel.qml
+++ b/Modules/Panels/Tray/TrayDrawerPanel.qml
@@ -43,8 +43,14 @@ SmartPanel {
function wildCardMatch(str, rule) {
if (!str || !rule)
return false;
- let escaped = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- let pattern = '^' + escaped.replace(/\\\*/g, '.*') + '$';
+ // First, convert '*' to a placeholder to preserve it, then escape other special regex characters
+ // Use a unique placeholder that won't appear in normal strings
+ const placeholder = '\uE000'; // Private use character
+ let processedRule = rule.replace(/\*/g, placeholder);
+ // Escape all special regex characters (but placeholder won't match this)
+ let escaped = processedRule.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
+ // Convert placeholder back to '.*' for wildcard matching
+ let pattern = '^' + escaped.replace(new RegExp(placeholder, 'g'), '.*') + '$';
try {
return new RegExp(pattern, 'i').test(str);
} catch (e) {
diff --git a/Services/Control/IPCService.qml b/Services/Control/IPCService.qml
index 4b3a51b4..856311d3 100644
--- a/Services/Control/IPCService.qml
+++ b/Services/Control/IPCService.qml
@@ -96,7 +96,7 @@ Item {
root.withTargetScreen(screen => {
var launcherPanel = PanelService.getPanel("launcherPanel", screen);
if (!launcherPanel?.windowActive || (launcherPanel?.windowActive && !launcherPanel?.activePlugin))
- launcherPanel?.toggle();
+ launcherPanel?.toggle();
launcherPanel?.setSearchText("");
});
}
@@ -104,7 +104,7 @@ Item {
root.withTargetScreen(screen => {
var launcherPanel = PanelService.getPanel("launcherPanel", screen);
if (!launcherPanel?.windowActive || (launcherPanel?.windowActive && launcherPanel?.searchText.startsWith(">clip")))
- launcherPanel?.toggle();
+ launcherPanel?.toggle();
launcherPanel?.setSearchText(">clip ");
});
}
@@ -112,7 +112,7 @@ Item {
root.withTargetScreen(screen => {
var launcherPanel = PanelService.getPanel("launcherPanel", screen);
if (!launcherPanel?.windowActive || (launcherPanel?.windowActive && launcherPanel?.searchText.startsWith(">calc")))
- launcherPanel?.toggle();
+ launcherPanel?.toggle();
launcherPanel?.setSearchText(">calc ");
});
}
@@ -120,7 +120,7 @@ Item {
root.withTargetScreen(screen => {
var launcherPanel = PanelService.getPanel("launcherPanel", screen);
if (!launcherPanel?.windowActive || (launcherPanel?.windowActive && launcherPanel?.searchText.startsWith(">emoji")))
- launcherPanel?.toggle();
+ launcherPanel?.toggle();
launcherPanel?.setSearchText(">emoji ");
});
}
@@ -380,6 +380,26 @@ Item {
}
}
+ IpcHandler {
+ target: "state"
+
+ // Returns all settings and shell state as JSON
+ function all(): string {
+ try {
+ var snapshot = Settings.buildStateSnapshot();
+ if (!snapshot) {
+ throw new Error("State snapshot unavailable");
+ }
+ return JSON.stringify(snapshot, null, 2);
+ } catch (error) {
+ Logger.e("IPC", "Failed to serialize state:", error);
+ return JSON.stringify({
+ "error": "Failed to serialize state: " + error
+ }, null, 2);
+ }
+ }
+ }
+
/**
* For IPC calls on multi-monitors setup that will open panels on screen,
* we need to open a QS PanelWindow and wait for it's "screen" property to stabilize.
diff --git a/Services/Media/AudioService.qml b/Services/Media/AudioService.qml
index 6fb76e29..efd7a287 100644
--- a/Services/Media/AudioService.qml
+++ b/Services/Media/AudioService.qml
@@ -169,11 +169,14 @@ Singleton {
if (volume >= maxVolume) {
return;
}
- setVolume(volume + stepVolume);
+ setVolume(Math.min(maxVolume, volume + stepVolume));
}
function decreaseVolume() {
- setVolume(volume - stepVolume);
+ if (volume <= 0) {
+ return;
+ }
+ setVolume(Math.max(0, volume - stepVolume));
}
function setVolume(newVolume: real) {
@@ -199,9 +202,14 @@ Singleton {
function getOutputIcon() {
if (muted)
return "volume-mute";
- if (volume <= Number.EPSILON)
- return "volume-zero";
- if (volume <= 0.5)
+
+ const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
+ const clampedVolume = Math.max(0, Math.min(volume, maxVolume));
+
+ // Show volume-x icon when volume is effectively 0% (within rounding threshold)
+ if (clampedVolume < 0.005)
+ return "volume-x";
+ if (clampedVolume <= 0.5)
return "volume-low";
return "volume-high";
}
diff --git a/Services/Noctalia/UpdateService.qml b/Services/Noctalia/UpdateService.qml
index ce8fc292..bfee6f67 100644
--- a/Services/Noctalia/UpdateService.qml
+++ b/Services/Noctalia/UpdateService.qml
@@ -79,6 +79,12 @@ Singleton {
const fromVersion = changelogFromVersion || "";
const toVersion = changelogToVersion || "";
+ if (Settings.shouldOpenSetupWizard) {
+ // If you'll see the setup wizard then you don't need to see the changelog
+ markChangelogSeen(toVersion);
+ return;
+ }
+
if (!toVersion)
return;
@@ -116,7 +122,7 @@ Singleton {
// 'from' always need to be before 'to'
// handle edge case that will show up as we changed -dev to -git
- if (from === to) {
+ if (from >= to) {
from = "v3.0.0";
}
diff --git a/Services/System/ProgramCheckerService.qml b/Services/System/ProgramCheckerService.qml
index a4d2f71a..da49fbc8 100644
--- a/Services/System/ProgramCheckerService.qml
+++ b/Services/System/ProgramCheckerService.qml
@@ -184,7 +184,7 @@ Singleton {
"codeAvailable": ["which", "code"],
"gnomeCalendarAvailable": ["which", "gnome-calendar"],
"spicetifyAvailable": ["which", "spicetify"],
- "telegramAvailable": ["sh", "-c", "which telegram-desktop || which Telegram"],
+ "telegramAvailable": ["sh", "-c", "command -v telegram-desktop >/dev/null 2>&1 || command -v Telegram >/dev/null 2>&1 || (command -v flatpak >/dev/null 2>&1 && flatpak list --app | grep -q 'org.telegram.desktop')"],
"cavaAvailable": ["which", "cava"]
})
diff --git a/Services/UI/WallpaperService.qml b/Services/UI/WallpaperService.qml
index a5487596..f6c5cc4a 100644
--- a/Services/UI/WallpaperService.qml
+++ b/Services/UI/WallpaperService.qml
@@ -250,7 +250,7 @@ Singleton {
// -------------------------------------------------------------------
// Get specific monitor wallpaper - now from cache
function getWallpaper(screenName) {
- return currentWallpapers[screenName] || Settings.data.wallpaper.defaultWallpaper;
+ return currentWallpapers[screenName] || Settings.defaultWallpaper;
}
// -------------------------------------------------------------------
diff --git a/Shaders/frag/circled_image.frag b/Shaders/frag/circled_image.frag
deleted file mode 100644
index 308a9c5b..00000000
--- a/Shaders/frag/circled_image.frag
+++ /dev/null
@@ -1,30 +0,0 @@
-#version 450
-
-layout(location = 0) in vec2 qt_TexCoord0;
-layout(location = 0) out vec4 fragColor;
-
-layout(binding = 1) uniform sampler2D source;
-
-layout(std140, binding = 0) uniform buf {
- mat4 qt_Matrix;
- float qt_Opacity;
- float imageOpacity;
-} ubuf;
-
-void main() {
- // Center coordinates around (0, 0)
- vec2 uv = qt_TexCoord0 - 0.5;
-
- // Calculate distance from center
- float distance = length(uv);
-
- // Create circular mask - anything beyond radius 0.5 is transparent
- float mask = 1.0 - smoothstep(0.48, 0.52, distance);
-
- // Sample the texture
- vec4 color = texture(source, qt_TexCoord0);
-
- // Apply the circular mask and opacity
- float finalAlpha = color.a * mask * ubuf.imageOpacity * ubuf.qt_Opacity;
- fragColor = vec4(color.rgb * finalAlpha, finalAlpha);
-}
\ No newline at end of file
diff --git a/Shaders/frag/progress_border.frag b/Shaders/frag/progress_border.frag
new file mode 100644
index 00000000..331386c4
--- /dev/null
+++ b/Shaders/frag/progress_border.frag
@@ -0,0 +1,67 @@
+#version 450
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+ float progress;
+ float borderWidth;
+ vec4 progressColor;
+ vec4 borderColor;
+ vec4 backgroundColor;
+ float borderRadius;
+} ubuf;
+
+void main() {
+ vec2 coord = qt_TexCoord0;
+ float p = clamp(ubuf.progress, 0.0, 1.0);
+
+ if (ubuf.borderRadius > 0.0) {
+ // Circular progress
+ vec2 center = vec2(0.5, 0.5);
+ vec2 dir = coord - center;
+ float dist = length(dir);
+
+ float outerRadius = 0.5;
+ float innerRadius = outerRadius - ubuf.borderWidth;
+
+ float angle = atan(dir.y, dir.x) + radians(90.0);
+ if (angle < 0.0) angle += radians(360.0);
+ float maxAngle = radians(360.0) * p;
+
+ bool inBorder = dist >= innerRadius && dist <= outerRadius;
+ bool inProgress = inBorder && angle <= maxAngle;
+
+ if (inProgress) {
+ fragColor = ubuf.progressColor * ubuf.qt_Opacity;
+ } else if (inBorder) {
+ fragColor = ubuf.borderColor * ubuf.qt_Opacity;
+ } else if (dist < innerRadius) {
+ fragColor = ubuf.backgroundColor * ubuf.qt_Opacity;
+ } else {
+ fragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ }
+ } else {
+ // Rectangular progress
+ bool inBorder =
+ coord.x < ubuf.borderWidth ||
+ coord.x > (1.0 - ubuf.borderWidth) ||
+ coord.y < ubuf.borderWidth ||
+ coord.y > (1.0 - ubuf.borderWidth);
+
+ float progressPos = p;
+ bool inProgress = inBorder && coord.x <= progressPos;
+
+ if (inProgress) {
+ fragColor = ubuf.progressColor * ubuf.qt_Opacity;
+ } else if (inBorder) {
+ fragColor = ubuf.borderColor * ubuf.qt_Opacity;
+ } else {
+ fragColor = ubuf.backgroundColor * ubuf.qt_Opacity;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shaders/qsb/circled_image.frag.qsb b/Shaders/qsb/circled_image.frag.qsb
deleted file mode 100644
index 4faa90f9..00000000
Binary files a/Shaders/qsb/circled_image.frag.qsb and /dev/null differ
diff --git a/Shaders/qsb/progress_border.frag.qsb b/Shaders/qsb/progress_border.frag.qsb
index e6e8f315..94e1628d 100644
Binary files a/Shaders/qsb/progress_border.frag.qsb and b/Shaders/qsb/progress_border.frag.qsb differ
diff --git a/Widgets/NIcon.qml b/Widgets/NIcon.qml
index 371c1867..eeabc712 100644
--- a/Widgets/NIcon.qml
+++ b/Widgets/NIcon.qml
@@ -26,4 +26,5 @@ Text {
font.pointSize: applyUiScale ? root.pointSize * Style.uiScaleRatio : root.pointSize
color: Color.mOnSurface
verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
}
diff --git a/Widgets/NImageCircled.qml b/Widgets/NImageCircled.qml
deleted file mode 100644
index c97e4440..00000000
--- a/Widgets/NImageCircled.qml
+++ /dev/null
@@ -1,76 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import Quickshell
-import Quickshell.Widgets
-import qs.Commons
-
-Rectangle {
- id: root
-
- property string imagePath: ""
- property color borderColor: Color.transparent
- property real borderWidth: 0
- property string fallbackIcon: ""
- property real fallbackIconSize: Style.fontSizeXXL
-
- color: Color.transparent
- radius: parent.width * 0.5
- anchors.margins: Style.marginXXS
-
- Rectangle {
- color: Color.transparent
- anchors.fill: parent
-
- Image {
- id: img
- anchors.fill: parent
- source: imagePath
- visible: false // Hide since we're using it as shader source
- mipmap: true
- smooth: true
- asynchronous: true
- antialiasing: true
- fillMode: Image.PreserveAspectCrop
- }
-
- ShaderEffect {
- anchors.fill: parent
-
- property var source: ShaderEffectSource {
- sourceItem: img
- hideSource: true
- live: true
- recursive: false
- format: ShaderEffectSource.RGBA
- }
-
- property real imageOpacity: root.opacity
- fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/circled_image.frag.qsb")
- supportsAtlasTextures: false
- blending: true
- }
-
- // Fallback icon
- Loader {
- active: fallbackIcon !== undefined && fallbackIcon !== "" && (imagePath === undefined || imagePath === "")
- anchors.centerIn: parent
- sourceComponent: NIcon {
- anchors.centerIn: parent
- icon: fallbackIcon
- pointSize: fallbackIconSize
- z: 0
- }
- }
- }
-
- // Border
- Rectangle {
- anchors.fill: parent
- radius: parent.radius
- color: Color.transparent
- border.color: parent.borderColor
- border.width: parent.borderWidth
- antialiasing: true
- z: 10
- }
-}
diff --git a/Widgets/NImageRounded.qml b/Widgets/NImageRounded.qml
index 67d3a178..588f5c60 100644
--- a/Widgets/NImageRounded.qml
+++ b/Widgets/NImageRounded.qml
@@ -4,91 +4,44 @@ import Quickshell
import Quickshell.Widgets
import qs.Commons
-Rectangle {
+Item {
id: root
+ property real radius: 0
property string imagePath: ""
- property color borderColor: Color.transparent
- property real borderWidth: 0
- property real imageRadius: width * 0.5
- property int imageFillMode: Image.PreserveAspectCrop
property string fallbackIcon: ""
property real fallbackIconSize: Style.fontSizeXXL
+ property real borderWidth: 0
+ property color borderColor: Color.transparent
- property real scaledRadius: imageRadius * Settings.data.general.radiusRatio
+ readonly property bool showFallback: (fallbackIcon !== undefined && fallbackIcon !== "") && (imagePath === undefined || imagePath === "")
signal statusChanged(int status)
- color: Color.transparent
- radius: scaledRadius
- anchors.margins: Style.marginXXS
-
- Rectangle {
- color: Color.transparent
+ ClippingRectangle {
anchors.fill: parent
+ color: Color.transparent
+ radius: root.radius
+ border.color: root.borderColor
+ border.width: root.borderWidth
Image {
- id: img
anchors.fill: parent
+ visible: !showFallback
source: imagePath
- visible: false
mipmap: true
smooth: true
asynchronous: true
antialiasing: true
- fillMode: root.imageFillMode
- horizontalAlignment: Image.AlignHCenter
- verticalAlignment: Image.AlignVCenter
-
+ fillMode: Image.PreserveAspectCrop
onStatusChanged: root.statusChanged(status)
}
- ShaderEffect {
- anchors.fill: parent
-
- property var source: ShaderEffectSource {
- sourceItem: img
- hideSource: true
- live: true
- recursive: false
- format: ShaderEffectSource.RGBA
- }
-
- property real itemWidth: root.width
- property real itemHeight: root.height
- property real cornerRadius: root.radius
- property real imageOpacity: root.opacity
- fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/rounded_image.frag.qsb")
-
- supportsAtlasTextures: false
- blending: true
- Rectangle {
- id: background
- anchors.fill: parent
- color: Color.transparent
- z: -1
- }
- }
-
- Loader {
- active: fallbackIcon !== undefined && fallbackIcon !== "" && (imagePath === undefined || imagePath === "")
+ NIcon {
anchors.centerIn: parent
- sourceComponent: NIcon {
- anchors.centerIn: parent
- icon: fallbackIcon
- pointSize: fallbackIconSize
- z: 0
- }
+ visible: showFallback
+ icon: fallbackIcon
+ pointSize: fallbackIconSize
}
}
-
- Rectangle {
- anchors.fill: parent
- radius: parent.radius
- color: Color.transparent
- border.color: parent.borderColor
- border.width: parent.borderWidth
- antialiasing: true
- z: 10
- }
}
diff --git a/shell.qml b/shell.qml
index 19f35a29..8f750704 100644
--- a/shell.qml
+++ b/shell.qml
@@ -49,6 +49,11 @@ ShellRoot {
function onReloadCompleted() {
Quickshell.inhibitReloadPopup();
}
+ function onReloadFailed() {
+ if (!Settings?.isDebug) {
+ Quickshell.inhibitReloadPopup();
+ }
+ }
}
Connections {
@@ -66,7 +71,7 @@ ShellRoot {
}
Connections {
- target: typeof ShellState !== 'undefined' ? ShellState : null
+ target: ShellState ? ShellState : null
function onIsLoadedChanged() {
if (ShellState.isLoaded) {
shellStateLoaded = true;
@@ -95,10 +100,7 @@ ShellRoot {
UpdateService.init();
UpdateService.showLatestChangelog();
- // Only open the setup wizard for new users
- if (!Settings.data.setupCompleted) {
- checkSetupWizard();
- }
+ checkSetupWizard();
}
Overview {}
@@ -129,7 +131,12 @@ ShellRoot {
}
function checkSetupWizard() {
- // Wait for distro service
+ // Only open the setup wizard for new users
+ if (!Settings.shouldOpenSetupWizard) {
+ return;
+ }
+
+ // Wait for HostService to be fully ready
if (!HostService.isReady) {
Qt.callLater(checkSetupWizard);
return;
@@ -137,16 +144,10 @@ ShellRoot {
// No setup wizard on NixOS
if (HostService.isNixOS) {
- Settings.data.setupCompleted = true;
return;
}
- if (Settings.data.settingsVersion >= Settings.settingsVersion) {
- setupWizardTimer.start();
- } else {
- Settings.data.setupCompleted = true;
- Settings.saveImmediate();
- }
+ setupWizardTimer.start();
}
function showSetupWizard() {