mirror of
https://github.com/celesrenata/end-4-flakes.git
synced 2026-06-18 15:19:56 -05:00
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:
@@ -0,0 +1 @@
|
|||||||
|
export LD_LIBRARY_PATH="/nix/store/xm08aqdd7pxcdhm0ak6aqb1v7hw5q6ri-gcc-14.3.0-lib/lib:/nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib:/nix/store/l7xwm1f6f3zj2x8jwdbi8gdyfbx07sh7-zlib-1.3.1/lib:/nix/store/b9p0zpa93hwvh4d0r1rmgc2500yx2ldn-libffi-3.5.2/lib:/nix/store/61i74yjkj9p1qphfl7018ja4sdwkipx0-openssl-3.6.0/lib:/nix/store/xgavznqg1ay2hycpp7yy9ia1n751jcla-bzip2-1.0.8/lib:/nix/store/q5vlz5jl6p7mv220s2vf6z5pqi1n935z-xz-5.8.1/lib:/nix/store/yijhn548p2589pkybgvbhll09bqsxy0q-ncurses-6.5/lib:/nix/store/41cgbkwax6pd1sgi8l81mamv6rvarryj-readline-8.3p1/lib:/nix/store/l30c488dws7z5mazacqsmj25izb9jlp2-sqlite-3.50.4/lib"
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import qs.modules.common
|
||||||
|
import qs
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
@@ -15,34 +17,19 @@ Singleton {
|
|||||||
property bool osdVolumeOpen: false
|
property bool osdVolumeOpen: false
|
||||||
property bool oskOpen: false
|
property bool oskOpen: false
|
||||||
property bool overviewOpen: false
|
property bool overviewOpen: false
|
||||||
property bool sessionOpen: false
|
|
||||||
property bool workspaceShowNumbers: false
|
|
||||||
property bool superReleaseMightTrigger: true
|
|
||||||
property bool screenLocked: false
|
property bool screenLocked: false
|
||||||
property bool screenLockContainsCharacters: false
|
property bool screenLockContainsCharacters: false
|
||||||
|
property bool sessionOpen: false
|
||||||
|
property bool superDown: false
|
||||||
|
property bool superReleaseMightTrigger: true
|
||||||
|
property bool workspaceShowNumbers: false
|
||||||
|
|
||||||
property real screenZoom: 1
|
property real screenZoom: 1
|
||||||
onScreenZoomChanged: {
|
onScreenZoomChanged: {
|
||||||
Quickshell.execDetached(["hyprctl", "keyword", "cursor:zoom_factor", root.screenZoom.toString()]);
|
Quickshell.execDetached(["hyprctl", "keyword", "cursor:zoom_factor", root.screenZoom.toString()]);
|
||||||
}
|
}
|
||||||
Behavior on screenZoom {
|
Behavior on screenZoom {
|
||||||
NumberAnimation { duration: 200; easing.type: Easing.OutCubic }
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
// animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
// When user is not reluctant while pressing super, they probably don't need to see workspace numbers
|
|
||||||
onSuperReleaseMightTriggerChanged: {
|
|
||||||
workspaceShowNumbersTimer.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: workspaceShowNumbersTimer
|
|
||||||
interval: 500 // Config.options.bar.workspaces.showNumberDelay
|
|
||||||
// interval: 0
|
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
workspaceShowNumbers = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalShortcut {
|
GlobalShortcut {
|
||||||
@@ -50,11 +37,10 @@ Singleton {
|
|||||||
description: "Hold to show workspace numbers, release to show icons"
|
description: "Hold to show workspace numbers, release to show icons"
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
workspaceShowNumbersTimer.start()
|
root.superDown = true
|
||||||
}
|
}
|
||||||
onReleased: {
|
onReleased: {
|
||||||
workspaceShowNumbersTimer.stop()
|
root.superDown = false
|
||||||
workspaceShowNumbers = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,4 +55,18 @@ Singleton {
|
|||||||
screenZoom = Math.max(screenZoom - 0.4, 1)
|
screenZoom = Math.max(screenZoom - 0.4, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
target: "theme"
|
||||||
|
|
||||||
|
function dark() {
|
||||||
|
const wallpaper = Config.options.background.wallpaperPath || `${Quickshell.env("HOME")}/Pictures/Wallpapers/konachan_random_image.png`
|
||||||
|
Quickshell.execDetached(["bash", `${Quickshell.env("HOME")}/.config/quickshell/scripts/colors/switchwall-wrapper.sh`, wallpaper, "--mode", "dark"])
|
||||||
|
}
|
||||||
|
|
||||||
|
function light() {
|
||||||
|
const wallpaper = Config.options.background.wallpaperPath || `${Quickshell.env("HOME")}/Pictures/Wallpapers/konachan_random_image.png`
|
||||||
|
Quickshell.execDetached(["bash", `${Quickshell.env("HOME")}/.config/quickshell/scripts/colors/switchwall-wrapper.sh`, wallpaper, "--mode", "light"])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import QtQuick
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
|
import Quickshell.Io
|
||||||
import Quickshell.Services.Pipewire
|
import Quickshell.Services.Pipewire
|
||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
|
|
||||||
@@ -14,6 +15,20 @@ Item {
|
|||||||
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
|
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
|
||||||
implicitHeight: rowLayout.implicitHeight
|
implicitHeight: rowLayout.implicitHeight
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: themeSwitchProcess
|
||||||
|
running: false
|
||||||
|
stdout: SplitParser {
|
||||||
|
onRead: data => console.log("switchwall:", data)
|
||||||
|
}
|
||||||
|
stderr: SplitParser {
|
||||||
|
onRead: data => console.log("switchwall err:", data)
|
||||||
|
}
|
||||||
|
onExited: (code, status) => {
|
||||||
|
console.log("switchwall exited:", code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: rowLayout
|
id: rowLayout
|
||||||
|
|
||||||
@@ -25,7 +40,7 @@ Item {
|
|||||||
visible: Config.options.bar.utilButtons.showScreenSnip
|
visible: Config.options.bar.utilButtons.showScreenSnip
|
||||||
sourceComponent: CircleUtilButton {
|
sourceComponent: CircleUtilButton {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
onClicked: Quickshell.execDetached(["qs", "-p", Quickshell.shellPath("screenshot.qml")])
|
onClicked: Quickshell.execDetached(["quickshell", "-p", Quickshell.shellPath("screenshot.qml")])
|
||||||
MaterialSymbol {
|
MaterialSymbol {
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
fill: 1
|
fill: 1
|
||||||
@@ -90,11 +105,11 @@ Item {
|
|||||||
sourceComponent: CircleUtilButton {
|
sourceComponent: CircleUtilButton {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
onClicked: event => {
|
onClicked: event => {
|
||||||
if (Appearance.m3colors.darkmode) {
|
const mode = Appearance.m3colors.darkmode ? "light" : "dark"
|
||||||
Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode light --noswitch`);
|
const wallpaper = Config.options.background.wallpaperPath || `${Quickshell.env("HOME")}/Pictures/Wallpapers/konachan_random_image.png`
|
||||||
} else {
|
themeSwitchProcess.command = ["bash", `${Directories.scriptPath}/colors/switchwall-wrapper.sh`, wallpaper, "--mode", mode]
|
||||||
Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode dark --noswitch`);
|
themeSwitchProcess.running = false
|
||||||
}
|
themeSwitchProcess.running = true
|
||||||
}
|
}
|
||||||
MaterialSymbol {
|
MaterialSymbol {
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
@@ -129,9 +144,9 @@ Item {
|
|||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
fill: 0
|
fill: 0
|
||||||
text: switch(PowerProfiles.profile) {
|
text: switch(PowerProfiles.profile) {
|
||||||
case PowerProfile.PowerSaver: return "battery_saver"
|
case PowerProfile.PowerSaver: return "energy_savings_leaf"
|
||||||
case PowerProfile.Balanced: return "dynamic_form"
|
case PowerProfile.Balanced: return "settings_slow_motion"
|
||||||
case PowerProfile.Performance: return "speed"
|
case PowerProfile.Performance: return "local_fire_department"
|
||||||
}
|
}
|
||||||
iconSize: Appearance.font.pixelSize.large
|
iconSize: Appearance.font.pixelSize.large
|
||||||
color: Appearance.colors.colOnLayer2
|
color: Appearance.colors.colOnLayer2
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ GroupButton {
|
|||||||
colBackground: Appearance.colors.colLayer2
|
colBackground: Appearance.colors.colLayer2
|
||||||
toggled: Appearance.m3colors.darkmode === dark
|
toggled: Appearance.m3colors.darkmode === dark
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`])
|
Quickshell.execDetached(["bash", `${Directories.scriptPath}/colors/switchwall-wrapper.sh`, "--mode", dark ? "dark" : "light", "--noswitch"])
|
||||||
}
|
}
|
||||||
contentItem: Item {
|
contentItem: Item {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import math
|
import math
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from materialyoucolor.quantize import QuantizeCelebi
|
from materialyoucolor.quantize import QuantizeCelebi
|
||||||
from materialyoucolor.score.score import Score
|
from materialyoucolor.score.score import Score
|
||||||
@@ -86,6 +87,11 @@ if args.path is not None:
|
|||||||
elif args.color is not None:
|
elif args.color is not None:
|
||||||
argb = hex_to_argb(args.color)
|
argb = hex_to_argb(args.color)
|
||||||
hct = Hct.from_int(argb)
|
hct = Hct.from_int(argb)
|
||||||
|
elif args.cache is not None and os.path.exists(args.cache):
|
||||||
|
with open(args.cache, 'r') as file:
|
||||||
|
cached_color = file.read().strip()
|
||||||
|
argb = hex_to_argb(cached_color)
|
||||||
|
hct = Hct.from_int(argb)
|
||||||
|
|
||||||
if args.scheme == 'scheme-fruit-salad':
|
if args.scheme == 'scheme-fruit-salad':
|
||||||
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
|
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Wrapper to set up environment for switchwall.sh
|
||||||
|
|
||||||
|
# Source environment config
|
||||||
|
[ -f "$HOME/.config/quickshell/env.sh" ] && source "$HOME/.config/quickshell/env.sh"
|
||||||
|
|
||||||
|
export ILLOGICAL_IMPULSE_VIRTUAL_ENV="${ILLOGICAL_IMPULSE_VIRTUAL_ENV:-$HOME/.local/state/quickshell/.venv}"
|
||||||
|
|
||||||
|
echo "[wrapper] Called with args: $@" >> /tmp/switchwall-wrapper.log
|
||||||
|
echo "[wrapper] LD_LIBRARY_PATH: $LD_LIBRARY_PATH" >> /tmp/switchwall-wrapper.log
|
||||||
|
|
||||||
|
# Run switchwall.sh with all arguments
|
||||||
|
exec "$(dirname "$0")/switchwall.sh" "$@"
|
||||||
@@ -1,5 +1,16 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Log execution
|
||||||
|
LOG="/tmp/switchwall.log"
|
||||||
|
echo "[$(date)] switchwall.sh started" >> "$LOG"
|
||||||
|
echo "ILLOGICAL_IMPULSE_VIRTUAL_ENV=$ILLOGICAL_IMPULSE_VIRTUAL_ENV" >> "$LOG"
|
||||||
|
|
||||||
|
# Ensure LD_LIBRARY_PATH is set for Python venv
|
||||||
|
if [ -z "$LD_LIBRARY_PATH" ]; then
|
||||||
|
export LD_LIBRARY_PATH="/run/current-system/sw/lib"
|
||||||
|
echo "Set LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> "$LOG"
|
||||||
|
fi
|
||||||
|
|
||||||
QUICKSHELL_CONFIG_NAME="ii"
|
QUICKSHELL_CONFIG_NAME="ii"
|
||||||
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||||
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
|
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
|
||||||
@@ -84,9 +95,10 @@ check_and_prompt_upscale() {
|
|||||||
img_height=$(identify -format "%h" "$img" 2>/dev/null)
|
img_height=$(identify -format "%h" "$img" 2>/dev/null)
|
||||||
fi
|
fi
|
||||||
if [[ "$img_width" -lt "$min_width_desired" || "$img_height" -lt "$min_height_desired" ]]; then
|
if [[ "$img_width" -lt "$min_width_desired" || "$img_height" -lt "$min_height_desired" ]]; then
|
||||||
action=$(notify-send "Upscale?" \
|
action=$(timeout 5 notify-send "Upscale?" \
|
||||||
"Image resolution (${img_width}x${img_height}) is lower than screen resolution (${min_width_desired}x${min_height_desired})" \
|
"Image resolution (${img_width}x${img_height}) is lower than screen resolution (${min_width_desired}x${min_height_desired})" \
|
||||||
-A "open_upscayl=Open Upscayl"\
|
-A "open_upscayl=Open Upscayl"\
|
||||||
|
-t 5000 \
|
||||||
-a "Wallpaper switcher")
|
-a "Wallpaper switcher")
|
||||||
if [[ "$action" == "open_upscayl" ]]; then
|
if [[ "$action" == "open_upscayl" ]]; then
|
||||||
if command -v upscayl &>/dev/null; then
|
if command -v upscayl &>/dev/null; then
|
||||||
@@ -187,7 +199,10 @@ switch() {
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
check_and_prompt_upscale "$imgpath" &
|
# Only check upscale if not using --noswitch
|
||||||
|
if [[ -z "$noswitch_flag" ]]; then
|
||||||
|
check_and_prompt_upscale "$imgpath" &
|
||||||
|
fi
|
||||||
kill_existing_mpvpaper
|
kill_existing_mpvpaper
|
||||||
|
|
||||||
if is_video "$imgpath"; then
|
if is_video "$imgpath"; then
|
||||||
@@ -281,11 +296,34 @@ switch() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
matugen "${matugen_args[@]}"
|
matugen "${matugen_args[@]}"
|
||||||
source "$(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate"
|
echo "[$(date)] Running python script" >> "$LOG"
|
||||||
python3 "$SCRIPT_DIR/generate_colors_material.py" "${generate_colors_material_args[@]}" \
|
"$(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/python3" "$SCRIPT_DIR/generate_colors_material.py" "${generate_colors_material_args[@]}" \
|
||||||
> "$STATE_DIR"/user/generated/material_colors.scss
|
> "$STATE_DIR"/user/generated/material_colors.scss 2>> "$LOG"
|
||||||
"$SCRIPT_DIR"/applycolor.sh
|
echo "[$(date)] Python done, scss size: $(wc -l < "$STATE_DIR"/user/generated/material_colors.scss)" >> "$LOG"
|
||||||
deactivate
|
|
||||||
|
# Only convert to JSON if SCSS was generated successfully
|
||||||
|
if [ -s "$STATE_DIR"/user/generated/material_colors.scss ]; then
|
||||||
|
# Convert SCSS to JSON for quickshell MaterialThemeLoader
|
||||||
|
echo "[$(date)] Converting SCSS to JSON" >> "$LOG"
|
||||||
|
awk -F': ' '/^\$/ {gsub(/\$|;/, "", $0); print "\"" $1 "\": \"" $2 "\","}' \
|
||||||
|
"$STATE_DIR"/user/generated/material_colors.scss | \
|
||||||
|
sed '$ s/,$//' | \
|
||||||
|
(echo "{"; cat; echo "}") > "$STATE_DIR"/user/generated/colors.json.tmp
|
||||||
|
mv "$STATE_DIR"/user/generated/colors.json.tmp "$STATE_DIR"/user/generated/colors.json
|
||||||
|
sync "$STATE_DIR"/user/generated/colors.json
|
||||||
|
echo "[$(date)] JSON created, size: $(wc -l < "$STATE_DIR"/user/generated/colors.json)" >> "$LOG"
|
||||||
|
else
|
||||||
|
echo "[$(date)] SCSS generation failed, skipping JSON creation" >> "$LOG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$XDG_CONFIG_HOME/quickshell/scripts/colors/applycolor.sh"
|
||||||
|
|
||||||
|
# Wait for all file operations to complete
|
||||||
|
wait
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Trigger quickshell to reload theme via IPC (doesn't restart the process)
|
||||||
|
quickshell ipc -c ii call materialTheme reload 2>/dev/null || true
|
||||||
|
|
||||||
# Pass screen width, height, and wallpaper path to post_process
|
# Pass screen width, height, and wallpaper path to post_process
|
||||||
max_width_desired="$(hyprctl monitors -j | jq '([.[].width] | min)' | xargs)"
|
max_width_desired="$(hyprctl monitors -j | jq '([.[].width] | min)' | xargs)"
|
||||||
@@ -300,6 +338,7 @@ main() {
|
|||||||
color_flag=""
|
color_flag=""
|
||||||
color=""
|
color=""
|
||||||
noswitch_flag=""
|
noswitch_flag=""
|
||||||
|
choose_flag=""
|
||||||
|
|
||||||
get_type_from_config() {
|
get_type_from_config() {
|
||||||
jq -r '.appearance.palette.type' "$SHELL_CONFIG_FILE" 2>/dev/null || echo "auto"
|
jq -r '.appearance.palette.type' "$SHELL_CONFIG_FILE" 2>/dev/null || echo "auto"
|
||||||
@@ -339,6 +378,10 @@ main() {
|
|||||||
imgpath=$(jq -r '.background.wallpaperPath' "$SHELL_CONFIG_FILE" 2>/dev/null || echo "")
|
imgpath=$(jq -r '.background.wallpaperPath' "$SHELL_CONFIG_FILE" 2>/dev/null || echo "")
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--choose)
|
||||||
|
choose_flag="1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if [[ -z "$imgpath" ]]; then
|
if [[ -z "$imgpath" ]]; then
|
||||||
imgpath="$1"
|
imgpath="$1"
|
||||||
@@ -369,8 +412,17 @@ main() {
|
|||||||
|
|
||||||
# Only prompt for wallpaper if not using --color and not using --noswitch and no imgpath set
|
# Only prompt for wallpaper if not using --color and not using --noswitch and no imgpath set
|
||||||
if [[ -z "$imgpath" && -z "$color_flag" && -z "$noswitch_flag" ]]; then
|
if [[ -z "$imgpath" && -z "$color_flag" && -z "$noswitch_flag" ]]; then
|
||||||
cd "$(xdg-user-dir PICTURES)/Wallpapers/showcase" 2>/dev/null || cd "$(xdg-user-dir PICTURES)/Wallpapers" 2>/dev/null || cd "$(xdg-user-dir PICTURES)" || return 1
|
# Try to pick a random wallpaper from Wallpapers directory
|
||||||
imgpath="$(kdialog --getopenfilename . --title 'Choose wallpaper')"
|
WALLPAPER_DIR="$(xdg-user-dir PICTURES)/Wallpapers"
|
||||||
|
if [[ -d "$WALLPAPER_DIR" ]] && [[ -z "$choose_flag" ]]; then
|
||||||
|
imgpath=$(find "$WALLPAPER_DIR" -type f \( -name "*.jpg" -o -name "*.png" \) 2>/dev/null | shuf -n 1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If --choose flag is set or still no wallpaper, prompt with kdialog
|
||||||
|
if [[ -n "$choose_flag" ]] || [[ -z "$imgpath" ]]; then
|
||||||
|
cd "$(xdg-user-dir PICTURES)/Wallpapers/showcase" 2>/dev/null || cd "$(xdg-user-dir PICTURES)/Wallpapers" 2>/dev/null || cd "$(xdg-user-dir PICTURES)" || return 1
|
||||||
|
imgpath="$(kdialog --getopenfilename . --title 'Choose wallpaper')"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If type_flag is 'auto', detect scheme type from image (after imgpath is set)
|
# If type_flag is 'auto', detect scheme type from image (after imgpath is set)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pragma Singleton
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import qs.modules.common
|
import qs.modules.common
|
||||||
|
import qs.modules.common.functions
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
@@ -14,31 +15,37 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
property string filePath: Directories.generatedMaterialThemePath
|
property string filePath: Directories.generatedMaterialThemePath
|
||||||
|
|
||||||
function reapplyTheme() {
|
Component.onCompleted: delayedFileRead.restart()
|
||||||
themeFileView.reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyColors(fileContent) {
|
function reapplyTheme() {
|
||||||
const json = JSON.parse(fileContent)
|
delayedFileRead.restart()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: delayedFileRead
|
id: delayedFileRead
|
||||||
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
|
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 300
|
||||||
repeat: false
|
repeat: false
|
||||||
running: false
|
running: false
|
||||||
onTriggered: {
|
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
|
watchChanges: true
|
||||||
onFileChanged: {
|
onFileChanged: {
|
||||||
this.reload()
|
this.reload()
|
||||||
delayedFileRead.start()
|
delayedFileRead.restart()
|
||||||
}
|
|
||||||
onLoadedChanged: {
|
|
||||||
const fileContent = themeFileView.text()
|
|
||||||
root.applyColors(fileContent)
|
|
||||||
}
|
}
|
||||||
|
onLoadedChanged: if (loaded) delayedFileRead.restart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,22 @@ CACHE_DIR="$XDG_CACHE_HOME/quickshell"
|
|||||||
STATE_DIR="$XDG_STATE_HOME/quickshell"
|
STATE_DIR="$XDG_STATE_HOME/quickshell"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
term_alpha=100 #Set this to < 100 make all your terminals transparent
|
term_alpha=60
|
||||||
|
|
||||||
|
# Check transparency setting and adjust term_alpha accordingly
|
||||||
|
if [ -f "$STATE_DIR/user/generated/terminal/transparency" ]; then
|
||||||
|
transparency_mode=$(cat "$STATE_DIR/user/generated/terminal/transparency")
|
||||||
|
if [ "$transparency_mode" = "opaque" ]; then
|
||||||
|
term_alpha=100
|
||||||
|
else
|
||||||
|
# For transparent mode, use the opacity setting from config or default to 80
|
||||||
|
if [ -f "$STATE_DIR/user/generated/terminal/opacity" ]; then
|
||||||
|
term_alpha=$(cat "$STATE_DIR/user/generated/terminal/opacity")
|
||||||
|
else
|
||||||
|
term_alpha=80
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
# sleep 0 # idk i wanted some delay or colors dont get applied properly
|
# sleep 0 # idk i wanted some delay or colors dont get applied properly
|
||||||
if [ ! -d "$STATE_DIR"/user/generated ]; then
|
if [ ! -d "$STATE_DIR"/user/generated ]; then
|
||||||
mkdir -p "$STATE_DIR"/user/generated
|
mkdir -p "$STATE_DIR"/user/generated
|
||||||
@@ -26,6 +41,7 @@ colorstrings=$(cat $STATE_DIR/user/generated/material_colors.scss | cut -d: -f2
|
|||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
colorlist=($colornames) # Array of color names
|
colorlist=($colornames) # Array of color names
|
||||||
colorvalues=($colorstrings) # Array of color values
|
colorvalues=($colorstrings) # Array of color values
|
||||||
|
export colorlist colorvalues
|
||||||
|
|
||||||
apply_term() {
|
apply_term() {
|
||||||
# Check if terminal escape sequence template exists
|
# Check if terminal escape sequence template exists
|
||||||
@@ -43,13 +59,13 @@ apply_term() {
|
|||||||
|
|
||||||
sed -i "s/\$alpha/$term_alpha/g" "$STATE_DIR/user/generated/terminal/sequences.txt"
|
sed -i "s/\$alpha/$term_alpha/g" "$STATE_DIR/user/generated/terminal/sequences.txt"
|
||||||
|
|
||||||
|
# Send escape sequences to all terminals
|
||||||
for file in /dev/pts/*; do
|
for file in /dev/pts/*; do
|
||||||
if [[ $file =~ ^/dev/pts/[0-9]+$ ]]; then
|
if [[ $file =~ ^/dev/pts/[0-9]+$ ]]; then
|
||||||
{
|
cat "$STATE_DIR"/user/generated/terminal/sequences.txt >"$file" 2>/dev/null &
|
||||||
cat "$STATE_DIR"/user/generated/terminal/sequences.txt >"$file"
|
|
||||||
} & disown || true
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
wait
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_qt() {
|
apply_qt() {
|
||||||
@@ -57,16 +73,172 @@ apply_qt() {
|
|||||||
python "$CONFIG_DIR/scripts/kvantum/changeAdwColors.py" # apply config colors
|
python "$CONFIG_DIR/scripts/kvantum/changeAdwColors.py" # apply config colors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply_foot() {
|
||||||
|
# Check if foot template exists
|
||||||
|
if [ ! -f "$SCRIPT_DIR/foot/foot.ini" ]; then
|
||||||
|
echo "Template file not found for Foot. Skipping that."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy template
|
||||||
|
mkdir -p "$STATE_DIR/user/generated/foot"
|
||||||
|
cp "$SCRIPT_DIR/foot/foot.ini" "$STATE_DIR/user/generated/foot/foot.ini"
|
||||||
|
|
||||||
|
# Apply colors (skip non-color variables like $darkmode, $transparent)
|
||||||
|
# Sort by variable name length (longest first) to avoid partial replacement issues
|
||||||
|
# e.g., $term10 must be replaced before $term1 to avoid "AC72FF0" malformed colors
|
||||||
|
filtered_indices=()
|
||||||
|
for i in "${!colorlist[@]}"; do
|
||||||
|
# Skip variables that don't start with color names or contain special values
|
||||||
|
if [[ "${colorlist[$i]}" == *"darkmode"* ]] || [[ "${colorlist[$i]}" == *"transparent"* ]] || [[ "${colorlist[$i]}" == *"palette"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
filtered_indices+=($i)
|
||||||
|
done
|
||||||
|
|
||||||
|
# Sort indices by variable name length (longest first)
|
||||||
|
IFS=$'\n' sorted_indices=($(for idx in "${filtered_indices[@]}"; do
|
||||||
|
echo "${#colorlist[$idx]} $idx"
|
||||||
|
done | sort -rn | cut -d' ' -f2))
|
||||||
|
|
||||||
|
for i in "${sorted_indices[@]}"; do
|
||||||
|
# Escape the $ in the color name for sed
|
||||||
|
color_name="${colorlist[$i]//$/\\$}"
|
||||||
|
# Remove # prefix from color value for foot compatibility
|
||||||
|
color_value="${colorvalues[$i]}"
|
||||||
|
color_value="${color_value#\#}" # Remove leading # if present
|
||||||
|
sed -i "s/${color_name}/${color_value}/g" "$STATE_DIR/user/generated/foot/foot.ini"
|
||||||
|
done
|
||||||
|
|
||||||
|
# After all color replacements, ensure no # prefixes remain in color values
|
||||||
|
# This handles any edge cases where # prefixes weren't removed properly
|
||||||
|
sed -i 's/=\s*#\([0-9A-Fa-f]\{6\}\)/=\1/g' "$STATE_DIR/user/generated/foot/foot.ini"
|
||||||
|
|
||||||
|
# Convert term_alpha percentage to decimal for foot (e.g., 70 -> 0.7)
|
||||||
|
foot_alpha=$(echo "scale=2; $term_alpha / 100" | bc)
|
||||||
|
# Use line number replacement to avoid sed pattern issues
|
||||||
|
sed -i "/^alpha=/c\\alpha=$foot_alpha" "$STATE_DIR/user/generated/foot/foot.ini"
|
||||||
|
|
||||||
|
# Copy to actual config location
|
||||||
|
mkdir -p "$XDG_CONFIG_HOME/foot"
|
||||||
|
cp "$STATE_DIR/user/generated/foot/foot.ini" "$XDG_CONFIG_HOME/foot/foot.ini"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_fuzzel() {
|
||||||
|
# Check if fuzzel template exists
|
||||||
|
if [ ! -f "$SCRIPT_DIR/fuzzel/fuzzel.ini" ]; then
|
||||||
|
echo "Template file not found for Fuzzel. Skipping that."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy template
|
||||||
|
mkdir -p "$STATE_DIR/user/generated/fuzzel"
|
||||||
|
cp "$SCRIPT_DIR/fuzzel/fuzzel.ini" "$STATE_DIR/user/generated/fuzzel/fuzzel.ini"
|
||||||
|
|
||||||
|
# Apply colors (skip non-color variables like $darkmode, $transparent)
|
||||||
|
# Sort by variable name length (longest first) to avoid partial replacement issues
|
||||||
|
filtered_indices=()
|
||||||
|
for i in "${!colorlist[@]}"; do
|
||||||
|
# Skip variables that don't start with color names or contain special values
|
||||||
|
if [[ "${colorlist[$i]}" == *"darkmode"* ]] || [[ "${colorlist[$i]}" == *"transparent"* ]] || [[ "${colorlist[$i]}" == *"palette"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
filtered_indices+=($i)
|
||||||
|
done
|
||||||
|
|
||||||
|
# Sort indices by variable name length (longest first)
|
||||||
|
IFS=$'\n' sorted_indices=($(for idx in "${filtered_indices[@]}"; do
|
||||||
|
echo "${#colorlist[$idx]} $idx"
|
||||||
|
done | sort -rn | cut -d' ' -f2))
|
||||||
|
|
||||||
|
for i in "${sorted_indices[@]}"; do
|
||||||
|
# Escape the $ in the color name for sed
|
||||||
|
color_name="${colorlist[$i]//$/\\$}"
|
||||||
|
# Keep # prefix for fuzzel (unlike foot)
|
||||||
|
color_value="${colorvalues[$i]}"
|
||||||
|
sed -i "s/${color_name}/${color_value}/g" "$STATE_DIR/user/generated/fuzzel/fuzzel.ini"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy to actual config location
|
||||||
|
mkdir -p "$XDG_CONFIG_HOME/fuzzel"
|
||||||
|
cp "$STATE_DIR/user/generated/fuzzel/fuzzel.ini" "$XDG_CONFIG_HOME/fuzzel/fuzzel.ini"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to convert hex color to RGB values
|
||||||
|
dehex() {
|
||||||
|
local hex="$1"
|
||||||
|
# Remove # if present
|
||||||
|
hex="${hex#\#}"
|
||||||
|
# Convert to RGB
|
||||||
|
printf "%d, %d, %d" "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_wofi() {
|
||||||
|
# Check if wofi template exists
|
||||||
|
if [ ! -f "$SCRIPT_DIR/wofi/style.css" ]; then
|
||||||
|
echo "Template file not found for Wofi colors. Skipping that."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy template
|
||||||
|
mkdir -p "$XDG_CONFIG_HOME/wofi"
|
||||||
|
cp "$SCRIPT_DIR/wofi/style.css" "$XDG_CONFIG_HOME/wofi/style_new.css"
|
||||||
|
chmod +w "$XDG_CONFIG_HOME/wofi/style_new.css"
|
||||||
|
|
||||||
|
# Apply colors (skip non-color variables like $darkmode, $transparent)
|
||||||
|
# Sort by variable name length (longest first) to avoid partial replacement issues
|
||||||
|
filtered_indices=()
|
||||||
|
for i in "${!colorlist[@]}"; do
|
||||||
|
# Skip variables that don't start with color names or contain special values
|
||||||
|
if [[ "${colorlist[$i]}" == *"darkmode"* ]] || [[ "${colorlist[$i]}" == *"transparent"* ]] || [[ "${colorlist[$i]}" == *"palette"* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
filtered_indices+=($i)
|
||||||
|
done
|
||||||
|
|
||||||
|
# Sort indices by variable name length (longest first)
|
||||||
|
IFS=$'\n' sorted_indices=($(for idx in "${filtered_indices[@]}"; do
|
||||||
|
echo "${#colorlist[$idx]} $idx"
|
||||||
|
done | sort -rn | cut -d' ' -f2))
|
||||||
|
|
||||||
|
# Apply hex colors (without # prefix) - use {{ $variable }} syntax
|
||||||
|
for i in "${sorted_indices[@]}"; do
|
||||||
|
# Remove $ prefix for the template pattern
|
||||||
|
color_name="${colorlist[$i]#\$}"
|
||||||
|
# Remove # prefix for wofi
|
||||||
|
color_value="${colorvalues[$i]}"
|
||||||
|
color_value="${color_value#\#}"
|
||||||
|
sed -i "s/{{ \$${color_name} }}/${color_value}/g" "$XDG_CONFIG_HOME/wofi/style_new.css"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Apply RGB colors - use {{ $variable-rgb }} syntax
|
||||||
|
for i in "${sorted_indices[@]}"; do
|
||||||
|
# Remove $ prefix for the template pattern
|
||||||
|
color_name="${colorlist[$i]#\$}"
|
||||||
|
# Convert to RGB
|
||||||
|
dehexed=$(dehex "${colorvalues[$i]}")
|
||||||
|
sed -i "s/{{ \$${color_name}-rgb }}/${dehexed}/g" "$XDG_CONFIG_HOME/wofi/style_new.css"
|
||||||
|
done
|
||||||
|
|
||||||
|
mv "$XDG_CONFIG_HOME/wofi/style_new.css" "$XDG_CONFIG_HOME/wofi/style.css"
|
||||||
|
}
|
||||||
|
|
||||||
# Check if terminal theming is enabled in config
|
# Check if terminal theming is enabled in config
|
||||||
CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json"
|
CONFIG_FILE="$XDG_CONFIG_HOME/illogical-impulse/config.json"
|
||||||
if [ -f "$CONFIG_FILE" ]; then
|
if [ -f "$CONFIG_FILE" ]; then
|
||||||
enable_terminal=$(jq -r '.appearance.wallpaperTheming.enableTerminal' "$CONFIG_FILE")
|
enable_terminal=$(jq -r '.appearance.wallpaperTheming.enableTerminal' "$CONFIG_FILE")
|
||||||
if [ "$enable_terminal" = "true" ]; then
|
if [ "$enable_terminal" = "true" ]; then
|
||||||
apply_term &
|
apply_term
|
||||||
|
apply_foot
|
||||||
|
apply_fuzzel
|
||||||
|
apply_wofi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "Config file not found at $CONFIG_FILE. Applying terminal theming by default."
|
echo "Config file not found at $CONFIG_FILE. Applying terminal theming by default."
|
||||||
apply_term &
|
apply_term
|
||||||
|
apply_foot
|
||||||
|
apply_fuzzel
|
||||||
|
apply_wofi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# apply_qt & # Qt theming is already handled by kde-material-colors
|
# apply_qt & # Qt theming is already handled by kde-material-colors
|
||||||
|
|||||||
Reference in New Issue
Block a user