Merge branch 'main' into auto-night-mode

This commit is contained in:
Leopold Luley
2025-10-16 17:42:47 +02:00
67 changed files with 372 additions and 376 deletions
+2 -2
View File
@@ -106,11 +106,11 @@ Singleton {
printErrors: false
watchChanges: true
onFileChanged: {
Logger.log("Color", "Reloading colors from disk")
Logger.i("Color", "Reloading colors from disk")
reload()
}
onAdapterUpdated: {
Logger.log("Color", "Writing colors to disk")
Logger.i("Color", "Writing colors to disk")
writeAdapter()
}
+30 -46
View File
@@ -7,8 +7,6 @@ import qs.Commons
Singleton {
id: root
property bool debug: false
property string debugForceLanguage: ""
property bool isLoaded: false
@@ -36,7 +34,7 @@ Singleton {
var output = stdoutCollector.text || ""
parseDirectoryListing(output)
} else {
Logger.error("I18n", `Failed to scan translation directory`)
Logger.e("I18n", `Failed to scan translation directory`)
// Fallback to default languages
availableLanguages = ["en"]
detectLanguage()
@@ -53,21 +51,19 @@ Singleton {
try {
var data = JSON.parse(text())
root.translations = data
Logger.log("I18n", `Loaded translations for "${root.langCode}"`)
if (debug) {
Logger.log("I18n", `Available root keys: ${Object.keys(data).join(", ")}`)
}
Logger.i("I18n", `Loaded translations for "${root.langCode}"`)
Logger.d("I18n", `Available root keys: ${Object.keys(data).join(", ")}`)
root.isLoaded = true
root.translationsLoaded()
} catch (e) {
Logger.error("I18n", `Failed to parse translation file: ${e}`)
Logger.e("I18n", `Failed to parse translation file: ${e}`)
setLanguage("en")
}
}
onLoadFailed: function (error) {
setLanguage("en")
Logger.error("I18n", `Failed to load translation file: ${error}`)
Logger.e("I18n", `Failed to load translation file: ${error}`)
}
}
@@ -80,24 +76,24 @@ Singleton {
try {
var data = JSON.parse(text())
root.fallbackTranslations = data
Logger.log("I18n", `Loaded english fallback translations`)
Logger.d("I18n", `Loaded english fallback translations`)
} catch (e) {
Logger.error("I18n", `Failed to parse fallback translation file: ${e}`)
Logger.e("I18n", `Failed to parse fallback translation file: ${e}`)
}
}
onLoadFailed: function (error) {
Logger.error("I18n", `Failed to load fallback translation file: ${error}`)
Logger.e("I18n", `Failed to load fallback translation file: ${error}`)
}
}
Component.onCompleted: {
Logger.log("I18n", "Service started")
Logger.i("I18n", "Service started")
scanAvailableLanguages()
}
// -------------------------------------------
function scanAvailableLanguages() {
Logger.log("I18n", "Scanning for available translation files...")
Logger.d("I18n", "Scanning for available translation files...")
directoryScanner.running = true
}
@@ -107,7 +103,7 @@ Singleton {
try {
if (!output || output.trim() === "") {
Logger.warn("I18n", "Empty directory listing output")
Logger.w("I18n", "Empty directory listing output")
availableLanguages = ["en"]
detectLanguage()
return
@@ -136,17 +132,17 @@ Singleton {
}
if (languages.length === 0) {
Logger.warn("I18n", "No translation files found, using fallback")
Logger.w("I18n", "No translation files found, using fallback")
languages = ["en"] // Fallback
}
availableLanguages = languages
Logger.log("I18n", `Found ${languages.length} available languages: ${languages.join(', ')}`)
Logger.d("I18n", `Found ${languages.length} available languages: ${languages.join(', ')}`)
// Detect language after scanning
detectLanguage()
} catch (e) {
Logger.error("I18n", `Failed to parse directory listing: ${e}`)
Logger.e("I18n", `Failed to parse directory listing: ${e}`)
// Fallback to default languages
availableLanguages = ["en"]
detectLanguage()
@@ -155,20 +151,20 @@ Singleton {
// -------------------------------------------
function detectLanguage() {
Logger.log("I18n", `detectLanguage() called. Available languages: [${availableLanguages.join(', ')}]`)
Logger.d("I18n", `detectLanguage() called. Available languages: [${availableLanguages.join(', ')}]`)
if (availableLanguages.length === 0) {
Logger.warn("I18n", "No available languages found")
Logger.w("I18n", "No available languages found")
return
}
if (debug && debugForceLanguage !== "") {
Logger.log("I18n", `Debug mode: forcing language to "${debugForceLanguage}"`)
if (Settings.isDebug && debugForceLanguage !== "") {
Logger.d("I18n", `Debug mode: forcing language to "${debugForceLanguage}"`)
if (availableLanguages.includes(debugForceLanguage)) {
setLanguage(debugForceLanguage)
return
} else {
Logger.warn("I18n", `Debug language "${debugForceLanguage}" not available in [${availableLanguages.join(', ')}]`)
Logger.w("I18n", `Debug language "${debugForceLanguage}" not available in [${availableLanguages.join(', ')}]`)
}
}
@@ -178,7 +174,7 @@ Singleton {
// Try full code match (such as zh CN, en US)
if (availableLanguages.includes(fullUserLang)) {
Logger.log("I18n", `Exact match found: "${fullUserLang}"`)
Logger.d("I18n", `Exact match found: "${fullUserLang}"`)
setLanguage(fullUserLang)
return
}
@@ -186,12 +182,12 @@ Singleton {
// If full code match fails, try short code matching (such as zh, en)
const shortUserLang = fullUserLang.substring(0, 2)
if (availableLanguages.includes(shortUserLang)) {
Logger.log("I18n", `Short code match found: "${shortUserLang}" from "${fullUserLang}"`)
Logger.d("I18n", `Short code match found: "${shortUserLang}" from "${fullUserLang}"`)
setLanguage(shortUserLang)
return
}
Logger.log("I18n", `No match for system language: "${fullUserLang}"`)
Logger.d("I18n", `No match for system language: "${fullUserLang}"`)
}
// Fallback to first available language (preferably "en" if available)
@@ -203,11 +199,11 @@ Singleton {
function setLanguage(newLangCode) {
if (newLangCode !== langCode && availableLanguages.includes(newLangCode)) {
langCode = newLangCode
Logger.log("I18n", `Language set to "${langCode}"`)
Logger.i("I18n", `Language set to "${langCode}"`)
languageChanged(langCode)
loadTranslations()
} else if (!availableLanguages.includes(newLangCode)) {
Logger.warn("I18n", `Language "${newLangCode}" is not available`)
Logger.w("I18n", `Language "${newLangCode}" is not available`)
}
}
@@ -219,7 +215,7 @@ Singleton {
const filePath = `file://${Quickshell.shellDir}/Assets/Translations/${langCode}.json`
fileView.path = filePath
isLoaded = false
Logger.log("I18n", `Loading translations: ${langCode}`)
Logger.d("I18n", `Loading translations: ${langCode}`)
// Only load fallback translations if we are not using english and english is available
if (langCode !== "en" && availableLanguages.includes("en")) {
@@ -271,7 +267,7 @@ Singleton {
// -------------------------------------------
// Reload translations (useful for development)
function reload() {
Logger.log("I18n", "Reloading translations")
Logger.d("I18n", "Reloading translations")
loadTranslations()
}
@@ -282,9 +278,7 @@ Singleton {
interpolations = {}
if (!isLoaded) {
if (debug) {
Logger.warn("I18n", "Translations not loaded yet")
}
Logger.d("I18n", "Translations not loaded yet")
return key
}
@@ -294,20 +288,12 @@ Singleton {
// Look-up translation in the active language
var value = translations
var notFound = false
if (debug) {
Logger.log("I18n", `Looking up key: "${key}"`)
}
for (var i = 0; i < keys.length; i++) {
if (value && typeof value === "object" && keys[i] in value) {
value = value[keys[i]]
if (debug) {
Logger.log("I18n", `Found key part "${keys[i]}"`)
}
} else {
if (debug) {
Logger.warn("I18n", `Translation key "${key}" not found at part "${keys[i]}"`)
Logger.warn("I18n", `Available keys: ${Object.keys(value || {}).join(", ")}`)
}
Logger.d("I18n", `Translation key "${key}" not found at part "${keys[i]}"`)
Logger.d("I18n", `Available keys: ${Object.keys(value || {}).join(", ")}`)
notFound = true
break
}
@@ -333,9 +319,7 @@ Singleton {
}
if (typeof value !== "string") {
if (debug) {
Logger.warn("I18n", `Translation key "${key}" is not a string`)
}
Logger.d("I18n", `Translation key "${key}" is not a string`)
return key
}
+6 -6
View File
@@ -26,14 +26,14 @@ Singleton {
signal fontReloaded
Component.onCompleted: {
Logger.log("Icons", "Service started")
Logger.i("Icons", "Service started")
loadFontWithCacheBusting()
}
Connections {
target: Quickshell
function onReloadCompleted() {
Logger.log("Icons", "Quickshell reload completed - forcing font reload")
Logger.d("Icons", "Quickshell reload completed - forcing font reload")
reloadFont()
}
}
@@ -50,7 +50,7 @@ Singleton {
}
function loadFontWithCacheBusting() {
Logger.log("Icons", "Loading font with cache busting")
Logger.d("Icons", "Loading font with cache busting")
// Destroy old loader first
if (currentFontLoader) {
@@ -69,16 +69,16 @@ Singleton {
// Connect to the new loader's status changes
currentFontLoader.statusChanged.connect(function () {
if (currentFontLoader.status === FontLoader.Ready) {
Logger.log("Icons", "Font loaded successfully:", currentFontLoader.name, "(version " + fontVersion + ")")
Logger.d("Icons", "Font loaded successfully:", currentFontLoader.name, "(version " + fontVersion + ")")
fontReloaded()
} else if (currentFontLoader.status === FontLoader.Error) {
Logger.error("Icons", "Font failed to load (version " + fontVersion + ")")
Logger.e("Icons", "Font failed to load (version " + fontVersion + ")")
}
})
}
function reloadFont() {
Logger.log("Icons", "Forcing font reload...")
Logger.d("Icons", "Forcing font reload...")
fontVersion++
loadFontWithCacheBusting()
}
+18 -7
View File
@@ -25,34 +25,45 @@ Singleton {
}
}
function log(...args) {
// Info log (always visible)
function i(...args) {
var msg = _formatMessage(...args)
console.log(msg)
}
function warn(...args) {
// Debug log (only when Settings.isDebug is true)
function d(...args) {
if (Settings && Settings.isDebug) {
var msg = _formatMessage(...args)
console.log(msg)
}
}
// Warning log
function w(...args) {
var msg = _formatMessage(...args)
console.warn(msg)
}
function error(...args) {
// Error log
function e(...args) {
var msg = _formatMessage(...args)
console.error(msg)
}
function callStack() {
var stack = _getStackTrace()
Logger.log("Debug", "--------------------------")
Logger.log("Debug", "Current call stack")
Logger.i("Debug", "--------------------------")
Logger.i("Debug", "Current call stack")
// Split the stack into lines and log each one
var stackLines = stack.split('\n')
for (var i = 0; i < stackLines.length; i++) {
var line = stackLines[i].trim() // Remove leading/trailing whitespace
if (line.length > 0) {
// Only log non-empty lines
Logger.log("Debug", `- ${line}`)
Logger.i("Debug", `- ${line}`)
}
}
Logger.log("Debug", "--------------------------")
Logger.i("Debug", "--------------------------")
}
}
+13 -12
View File
@@ -15,6 +15,7 @@ Singleton {
property bool isLoaded: false
property bool directoriesCreated: false
property int settingsVersion: 16
property bool isDebug: Quickshell.env("NOCTALIA_DEBUG") === "1"
// Define our app directories
// Default config directory: ~/.config/noctalia
@@ -93,7 +94,7 @@ Singleton {
}
onLoaded: function () {
if (!isLoaded) {
Logger.log("Settings", "Settings loaded")
Logger.i("Settings", "Settings loaded")
upgradeSettingsData()
validateMonitorConfigurations()
@@ -437,7 +438,7 @@ Singleton {
// Generate default settings at the root of the repo
function generateDefaultSettings() {
try {
Logger.log("Settings", "Generating settings-default.json")
Logger.d("Settings", "Generating settings-default.json")
// Prepare a clean JSON
var plainAdapter = QtObj2JS.qtObjectToPlainObject(adapter)
@@ -449,7 +450,7 @@ Singleton {
var base64Data = Qt.btoa(jsonData)
Quickshell.execDetached(["sh", "-c", `echo "${base64Data}" | base64 -d > "${defaultPath}"`])
} catch (error) {
Logger.error("Settings", "Failed to generate default settings file: " + error)
Logger.e("Settings", "Failed to generate default settings file: " + error)
}
}
@@ -461,8 +462,8 @@ Singleton {
availableScreenNames.push(Quickshell.screens[i].name)
}
Logger.log("Settings", "Available monitors: [" + availableScreenNames.join(", ") + "]")
Logger.log("Settings", "Configured bar monitors: [" + adapter.bar.monitors.join(", ") + "]")
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) {
@@ -474,15 +475,15 @@ Singleton {
}
}
if (!hasValidBarMonitor) {
Logger.warn("Settings", "No configured bar monitors found on system, clearing bar monitor list to show on all screens")
Logger.w("Settings", "No configured bar monitors found on system, clearing bar monitor list to show on all screens")
adapter.bar.monitors = []
} else {
//Logger.log("Settings", "Found valid bar monitors, keeping configuration")
//Logger.i("Settings", "Found valid bar monitors, keeping configuration")
}
} else {
//Logger.log("Settings", "Bar monitor list is empty, will show on all available screens")
//Logger.i("Settings", "Bar monitor list is empty, will show on all available screens")
}
}
@@ -492,7 +493,7 @@ Singleton {
function upgradeSettingsData() {
// Wait for BarWidgetRegistry to be ready
if (!BarWidgetRegistry.widgets || Object.keys(BarWidgetRegistry.widgets).length === 0) {
Logger.warn("Settings", "BarWidgetRegistry not ready, deferring upgrade")
Logger.w("Settings", "BarWidgetRegistry not ready, deferring upgrade")
Qt.callLater(upgradeSettingsData)
return
}
@@ -533,7 +534,7 @@ Singleton {
for (var i = widgets.length - 1; i >= 0; i--) {
var widget = widgets[i]
if (!BarWidgetRegistry.hasWidget(widget.id)) {
Logger.warn(`Settings`, `Deleted invalid widget ${widget.id}`)
Logger.w(`Settings`, `Deleted invalid widget ${widget.id}`)
widgets.splice(i, 1)
removedWidget = true
}
@@ -554,7 +555,7 @@ Singleton {
}
if (upgradeWidget(widget)) {
Logger.log("Settings", `Upgraded ${widget.id} widget:`, JSON.stringify(widget))
Logger.d("Settings", `Upgraded ${widget.id} widget:`, JSON.stringify(widget))
}
}
}
@@ -580,7 +581,7 @@ Singleton {
adapter.bar.widgets["right"].push(({
"id": "ControlCenter"
}))
Logger.warn("Settings", "Added a ControlCenter widget to the right section")
Logger.w("Settings", "Added a ControlCenter widget to the right section")
}
}
}