From 19bb1399e8d20e956f1a1cb4510d22b8eb08fefb Mon Sep 17 00:00:00 2001 From: Sho Date: Sat, 1 Aug 2026 23:43:56 +0900 Subject: [PATCH] feat: implement generic get_app_config_dirs helper to dynamically discover and sync themes for all Flatpak applications --- quickshell/services/python/theme_sync.py | 76 ++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/quickshell/services/python/theme_sync.py b/quickshell/services/python/theme_sync.py index 9fc8c2a..971bade 100644 --- a/quickshell/services/python/theme_sync.py +++ b/quickshell/services/python/theme_sync.py @@ -1,6 +1,55 @@ #!/usr/bin/env python3 import os, sys, argparse, re +def get_app_config_dirs(app_names): + """ + Dynamically discover all config and data directories for any native or Flatpak application. + Checks ~/.config/, ~/.local/share/, ~/.var/app/* (Flatpak sandboxes), and system paths. + """ + if isinstance(app_names, str): + app_names = [app_names] + + dirs = set() + home = os.path.expanduser('~') + + for name in app_names: + c1 = os.path.join(home, '.config', name) + c2 = os.path.join(home, '.local', 'share', name) + if os.path.exists(c1): + dirs.add(c1) + if os.path.exists(c2): + dirs.add(c2) + + var_app = os.path.join(home, '.var', 'app') + if os.path.exists(var_app): + try: + for entry in os.scandir(var_app): + if not entry.is_dir(): + continue + sub_locations = [ + os.path.join(entry.path, 'config'), + os.path.join(entry.path, 'data'), + os.path.join(entry.path, '.config'), + os.path.join(entry.path, '.local', 'share') + ] + for sub_loc in sub_locations: + if not os.path.exists(sub_loc): + continue + for name in app_names: + target = os.path.join(sub_loc, name) + if os.path.exists(target): + dirs.add(target) + try: + for item in os.scandir(sub_loc): + if any(n.lower() in item.name.lower() for n in app_names): + dirs.add(item.path) + except Exception: + pass + except Exception: + pass + + return list(dirs) + def sync_gtk(bg, surface, current_line, fg, accent, is_dark): css_content = f"""/* Auto-generated by Quickshell Theme Engine */ @define-color window_bg_color {bg}; @@ -705,12 +754,15 @@ def sync_feishin(bg, surface, current_line, fg, accent, sub_accent, is_dark, var import json, glob active_slug = slugify(variant_name) - feishin_dirs = [ + feishin_dirs = get_app_config_dirs(['feishin', 'Feishin']) + for fb in [ os.path.expanduser('~/.config/feishin'), os.path.expanduser('~/.var/app/io.github.jeffvli.feishin/config/feishin'), os.path.expanduser('~/.var/app/org.jeffvli.feishin/config/feishin'), os.path.expanduser('~/.var/app/feishin/config/feishin') - ] + ]: + if fb not in feishin_dirs: + feishin_dirs.append(fb) for base_dir in feishin_dirs: try: @@ -733,15 +785,29 @@ def sync_feishin(bg, surface, current_line, fg, accent, sub_accent, is_dark, var v_slug = slugify(v["name"]) v_json = make_feishin_json(v["bg"], v["surface"], v["currentLine"], v["fg"], v["accent"], v["isDark"], v["name"], v_slug) v_path = os.path.join(themes_dir, f"{v_slug}.json") - with open(v_path, 'w') as f: + with open(v_path, 'w', encoding='utf-8') as f: json.dump(v_json, f, indent=2) - # 3. Write active variant JSON with runtime parameters + # 3. Write active variant JSON with runtime parameters + quickshell.json active_json = make_feishin_json(bg, surface, current_line, fg, accent, is_dark, variant_name, active_slug) active_path = os.path.join(themes_dir, f"{active_slug}.json") - with open(active_path, 'w') as f: + with open(active_path, 'w', encoding='utf-8') as f: json.dump(active_json, f, indent=2) + with open(os.path.join(themes_dir, "quickshell.json"), 'w', encoding='utf-8') as f: + json.dump(active_json, f, indent=2) + + # 4. Auto-update preferences.json in Feishin config directory if present + pref_file = os.path.join(base_dir, 'preferences.json') + if os.path.exists(pref_file): + try: + with open(pref_file, 'r', encoding='utf-8') as f: + pref_data = json.load(f) + pref_data["theme"] = active_slug + with open(pref_file, 'w', encoding='utf-8') as f: + json.dump(pref_data, f, indent=2) + except Exception: + pass except Exception: pass