Fix dynamic theming: enable filesystem writes and add theme switching

- Add LD_LIBRARY_PATH and ILLOGICAL_IMPULSE_VIRTUAL_ENV to quickshell service
- Set ProtectSystem=false to allow color generation scripts to write files
- Fix MaterialThemeLoader to properly detect file changes with onFileChanged
- Add switchwall-wrapper.sh to source environment variables dynamically
- Fix light/dark mode buttons to use Process with current wallpaper
- Add --choose flag to switchwall.sh for wallpaper selection dialog
- Add IPC commands 'dark' and 'light' for console theme switching
- Update keybinds: Ctrl+Super+T (choose), Ctrl+Super+Shift+T (random)
- Fix terminal color application in applycolor.sh
This commit is contained in:
Celes Renata
2025-11-29 18:57:23 -08:00
parent 3655e7aaee
commit d192bee3d9
9 changed files with 333 additions and 70 deletions
@@ -2,6 +2,7 @@ pragma Singleton
pragma ComponentBehavior: Bound
import qs.modules.common
import qs.modules.common.functions
import QtQuick
import Quickshell
import Quickshell.Io
@@ -14,31 +15,37 @@ Singleton {
id: root
property string filePath: Directories.generatedMaterialThemePath
function reapplyTheme() {
themeFileView.reload()
}
Component.onCompleted: delayedFileRead.restart()
function applyColors(fileContent) {
const json = JSON.parse(fileContent)
for (const key in json) {
if (json.hasOwnProperty(key)) {
// Convert snake_case to CamelCase
const camelCaseKey = key.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
const m3Key = `m3${camelCaseKey}`
Appearance.m3colors[m3Key] = json[key]
}
}
Appearance.m3colors.darkmode = (Appearance.m3colors.m3background.hslLightness < 0.5)
function reapplyTheme() {
delayedFileRead.restart()
}
Timer {
id: delayedFileRead
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 300
repeat: false
running: false
onTriggered: {
root.applyColors(themeFileView.text())
console.log("MaterialThemeLoader: Timer triggered")
const fileContent = themeFileView.text()
console.log("MaterialThemeLoader: Read", fileContent.length, "bytes")
const json = JSON.parse(fileContent)
let colorCount = 0
for (const key in json) {
if (json.hasOwnProperty(key)) {
if (key === 'darkmode' || key === 'transparent' || key.includes('paletteKeyColor') || key.startsWith('term')) {
continue
}
const camelCaseKey = key.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
const m3Key = `m3${camelCaseKey}`
Appearance.m3colors[m3Key] = json[key]
colorCount++
}
}
console.log("MaterialThemeLoader: Applied", colorCount, "colors")
console.log("MaterialThemeLoader: m3primary =", Appearance.m3colors.m3primary)
Appearance.m3colors.darkmode = (Appearance.m3colors.m3background.hslLightness < 0.5)
}
}
@@ -48,11 +55,8 @@ Singleton {
watchChanges: true
onFileChanged: {
this.reload()
delayedFileRead.start()
}
onLoadedChanged: {
const fileContent = themeFileView.text()
root.applyColors(fileContent)
delayedFileRead.restart()
}
onLoadedChanged: if (loaded) delayedFileRead.restart()
}
}