From 1f24c5c3e8a81ddd82028e56c76aa5fff57092ed Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:51:54 +0545 Subject: [PATCH 01/14] feat(dock): replace MAX_SCALE constant with config-backed max_scale() function --- src/window/dock/constants.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/window/dock/constants.py b/src/window/dock/constants.py index 39343d7d..f0eab6d0 100644 --- a/src/window/dock/constants.py +++ b/src/window/dock/constants.py @@ -1,3 +1,4 @@ +from services.config import config from utils.gtk_utils import toml_file PINNED_APPS_FILE = toml_file("dock.toml") @@ -7,7 +8,11 @@ ANIM_FPS = 60 ANIM_INTERVAL_MS = 1000 // ANIM_FPS -MAX_SCALE = 2.0 + +def max_scale() -> float: + return float(config().get("dock.hover_scale", 2.0)) + + MIN_SCALE = 1.0 SIGMA_FACTOR = 1.3 From c94dbff55e0c3e778a3399a2aa3e9ca54e9d6de0 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:51:59 +0545 Subject: [PATCH 02/14] feat(dock): call max_scale() instead of MAX_SCALE constant in layout --- src/window/dock/layout.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/window/dock/layout.py b/src/window/dock/layout.py index 3e9caa93..d7729b98 100644 --- a/src/window/dock/layout.py +++ b/src/window/dock/layout.py @@ -5,9 +5,9 @@ BG_PADDING_V, ICON_GAP, INDICATOR_H, - MAX_SCALE, MIN_SCALE, SIGMA_FACTOR, + max_scale, ) from .items import DockItem @@ -27,7 +27,7 @@ def compute( return sigma = base_icon_size * SIGMA_FACTOR - amplitude = MAX_SCALE - MIN_SCALE + amplitude = max_scale() - MIN_SCALE n = len(items) base_w = base_icon_size + ICON_GAP From 3ad4221a9ae622bf764002f08faa05c6069f3a15 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:52:00 +0545 Subject: [PATCH 03/14] feat(dock): use max_scale() for icon cache size and drop custom cairo filter --- src/window/dock/canvas.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/window/dock/canvas.py b/src/window/dock/canvas.py index 5c3d8274..b84f5ff1 100644 --- a/src/window/dock/canvas.py +++ b/src/window/dock/canvas.py @@ -41,11 +41,11 @@ INDICATOR_COLOR, INDICATOR_H, INDICATOR_RADIUS, - MAX_SCALE, MIN_SCALE, PINNED_APPS_FILE, SEPARATOR_COLOR, SEPARATOR_WIDTH, + max_scale, ) from .items import DockHitTest, DockItem, DockModel from .layout import DockLayout @@ -126,7 +126,7 @@ def _base_icon_size(self) -> int: return int(config().get("dock.icon_size", 52)) def _icon_cache_size(self) -> int: - return int(self._base_icon_size() * MAX_SCALE) + return int(self._base_icon_size() * max_scale()) def _get_desktop_apps(self) -> list: if not self._desktop_apps: @@ -140,7 +140,7 @@ def _get_desktop_apps(self) -> list: def _canvas_height(self) -> int: size = self._base_icon_size() return int( - size * MAX_SCALE + CANVAS_TOP_PAD + 2 * BG_PADDING_V + INDICATOR_H + 4 + size * max_scale() + CANVAS_TOP_PAD + 2 * BG_PADDING_V + INDICATOR_H + 4 ) def _canvas_max_width(self) -> int: @@ -149,7 +149,7 @@ def _canvas_max_width(self) -> int: return 200 size = self._base_icon_size() return int( - n * size * MAX_SCALE + max(n - 1, 0) * ICON_GAP + 2 * BG_PADDING_H + 40 + n * size * max_scale() + max(n - 1, 0) * ICON_GAP + 2 * BG_PADDING_H + 40 ) def _canvas_min_width(self) -> int: @@ -655,7 +655,7 @@ def _on_motion(self, widget, event: Gdk.EventMotion) -> bool: bg_h = size + 2 * BG_PADDING_V bg_y = h - INDICATOR_H - bg_h baseline_y = bg_y + BG_PADDING_V + size - icon_top_y = baseline_y - size * MAX_SCALE + icon_top_y = baseline_y - size * max_scale() self._mouse_inside = ( base_start_x <= event.x <= base_start_x + total_base and icon_top_y <= event.y <= baseline_y From f93f5f89429294bba5dcf584de9e1824a712fe6d Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:52:00 +0545 Subject: [PATCH 04/14] feat(dock): add hover_scale config change handler --- src/window/dock/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/window/dock/main.py b/src/window/dock/main.py index 4c02cd6b..6de01a6d 100644 --- a/src/window/dock/main.py +++ b/src/window/dock/main.py @@ -135,6 +135,9 @@ def _on_config_change(self, new_config, old_config) -> None: if config().has_changed("dock.hide_special_workspace_apps", old_config): self.canvas._rebuild_model() + if config().has_changed("dock.hover_scale", old_config): + self.canvas.update_icon_size() + def _update_visibility(self) -> None: if config().get("dock.enabled", True): self.show() From 4a9f8fc1b8b8a40774d696f7272fce7f759aeb55 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:52:00 +0545 Subject: [PATCH 05/14] refactor(config): use generate_default_toml() from constants for initial config --- src/services/config.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/services/config.py b/src/services/config.py index 1fdbbd78..1f445b57 100644 --- a/src/services/config.py +++ b/src/services/config.py @@ -14,6 +14,7 @@ from tomlkit import dump as toml_dump from tomlkit import item as toml_item from tomlkit import load as toml_load +from tomlkit import loads as toml_loads from utils.gtk_utils import toml_file @@ -126,12 +127,13 @@ def _load_config(self) -> None: self._config = toml_load(f) else: try: - from utils.constants import DEFAULT + from utils.constants import generate_default_toml os.makedirs(os.path.dirname(self._config_file), exist_ok=True) - self._config = self._dict_to_toml(DEFAULT) + raw = generate_default_toml() + self._config = toml_loads(raw) with open(self._config_file, "w") as f: - toml_dump(self._config, f) + f.write(raw) logger.info( f"[ConfigService] Generated default config at {self._config_file}" ) From 3aa0d34fea3052633b36a470cb09d348180ab32b Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:52:01 +0545 Subject: [PATCH 06/14] feat(config): set hover_scale default to 1.6 with range comment, add generate_default_toml() --- src/utils/constants.py | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/utils/constants.py b/src/utils/constants.py index bfc79b31..a877eff7 100644 --- a/src/utils/constants.py +++ b/src/utils/constants.py @@ -1,3 +1,7 @@ +from tomlkit import document as _document +from tomlkit import dumps as _dumps +from tomlkit import table as _table + DEFAULT = { "general": { "debug": False, @@ -11,6 +15,7 @@ "always_occluded": False, "icon_size": 52, "hide_special_workspace_apps": True, + "hover_scale": 1.6, }, "panel": { "imac_button": True, @@ -42,3 +47,61 @@ "limited_apps_history": ["Spotify"], }, } + + +def generate_default_toml() -> str: + """Build default config.toml with inline comments.""" + doc = _document() + + general = _table() + general.add("debug", False) + general.add("wallpapers_dir", "src/assets/wallpaper_example/") + general.add("keyboard_layouts", ["us"]) + general.add("weather_location", "") + doc.add("general", general) + + dock = _table() + dock.add("enabled", True) + dock.add("auto_hide", True) + dock.add("always_occluded", False) + dock.add("icon_size", 52) + dock.add("hide_special_workspace_apps", True) + dock.add("hover_scale", 1.6) + dock["hover_scale"].comment( + "1.0 (min, no effect) to 2.0 (max) | >2.0 not recommended — icons get blurry/pixelated on hover" + ) + doc.add("dock", dock) + + panel = _table() + panel.add("imac_button", True) + panel.add("systray", True) + panel.add("systray_ignore", ["blueman", "network"]) + panel.add("control_center", True) + panel.add("search", True) + panel.add("global_menu", True) + panel.add("network", True) + panel.add("battery", True) + panel.add("notification_center", True) + panel.add("workspace_indicator", True) + panel.add("bluetooth", True) + panel.add("date_time", True) + panel.add("night_light_temperature", 4500) + panel.add("notch", True) + panel.add("osd", True) + panel.add("hide_special_workspace", True) + panel.add("custom_mods", True) + doc.add("panel", panel) + + switcher = _table() + switcher.add("live_preview", True) + switcher.add("live_preview_delay_ms", 200) + switcher.add("window_switcher", True) + doc.add("switcher", switcher) + + notification = _table() + notification.add("timeout", "5s") + notification.add("ignored_apps", ["Hyprshot"]) + notification.add("limited_apps_history", ["Spotify"]) + doc.add("notification", notification) + + return _dumps(doc) From 514868fe51813dc91d5bc157db751fbefa81b786 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:52:01 +0545 Subject: [PATCH 07/14] feat(data): use generate_default_toml() in load_config fallback --- src/shared/data.py | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/shared/data.py b/src/shared/data.py index 5754aba7..c8d773e1 100644 --- a/src/shared/data.py +++ b/src/shared/data.py @@ -49,19 +49,35 @@ def load_config(): service = start_config_service() return service.get_all() except ImportError: - # Fallback to direct file loading - config = {} + pass - if os.path.exists(CONFIG_FILE): - try: - import tomlkit - - with open(CONFIG_FILE) as f: - config = dict(tomlkit.load(f)) - except Exception as e: - logger.error(f"Error loading config: {e}") - - return config + try: + from utils.constants import generate_default_toml + except ImportError: + generate_default_toml = None + + config = {} + + if os.path.exists(CONFIG_FILE): + try: + import tomlkit + + with open(CONFIG_FILE) as f: + config = dict(tomlkit.load(f)) + except Exception as e: + logger.error(f"Error loading config: {e}") + elif generate_default_toml: + try: + raw = generate_default_toml() + with open(CONFIG_FILE, "w") as f: + f.write(raw) + import tomlkit + + config = dict(tomlkit.loads(raw)) + except Exception as e: + logger.error(f"Error generating default config: {e}") + + return config NOTIFICATION_TIMEOUT_STR = "5s" From 1d7a94f15451e5a9bd6b4c0effdb1d6190d602a8 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:52:02 +0545 Subject: [PATCH 08/14] chore(clipboard): remove noisy INFO logs from _load_history --- src/window/spotlight/plugins/clipboard.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/window/spotlight/plugins/clipboard.py b/src/window/spotlight/plugins/clipboard.py index 6ab32204..d29faf91 100644 --- a/src/window/spotlight/plugins/clipboard.py +++ b/src/window/spotlight/plugins/clipboard.py @@ -99,11 +99,7 @@ def _on_debounced_db_change(self): def _load_history(self) -> None: result = run_command(["cliphist", "list"], timeout=5) raw = result.stdout if isinstance(result.stdout, str) else "" - logger.info( - f"[Clipboard] _load_history: stdout type={type(result.stdout).__name__} len={len(raw)} returncode={result.returncode}" - ) lines = raw.splitlines() - logger.info(f"[Clipboard] _load_history: {len(lines)} lines from cliphist") new_entries = [] for line in lines[:100]: if "\t" not in line: @@ -122,13 +118,9 @@ def _load_history(self) -> None: if "binary data" in content: entry["type"] = "image" new_entries.append(entry) - logger.info(f"[Clipboard] _load_history: parsed {len(new_entries)} entries") with self._history_lock: self._history.clear() self._history.extend(new_entries) - logger.info( - f"[Clipboard] _load_history: history now has {len(self._history)} entries" - ) def _filter_entries(self, query: str) -> list[dict]: q = query.strip().lower() From 251d924df7dc2510180db0c493ab80ec50275807 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:53:10 +0545 Subject: [PATCH 09/14] ci: update branch triggers main->macos, drop dev --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/commitlint.yml | 2 +- .github/workflows/install-test.yml | 4 ++-- .github/workflows/pre-commit.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 67c65331..74bc76e1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,9 +2,9 @@ name: CodeQL on: push: - branches: [main, dev] + branches: [macos] pull_request: - branches: [main, dev] + branches: [macos] schedule: - cron: "0 6 * * 1" diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 64c26c27..4db277c1 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -2,7 +2,7 @@ name: Commit Lint on: pull_request: - branches: [main, dev] + branches: [macos] permissions: contents: read diff --git a/.github/workflows/install-test.yml b/.github/workflows/install-test.yml index d74a95a0..2c9eb741 100644 --- a/.github/workflows/install-test.yml +++ b/.github/workflows/install-test.yml @@ -2,7 +2,7 @@ name: Install Script Test on: push: - branches: [main, dev] + branches: [macos] paths: - "install.sh" - "src/window/globalmenu/**" @@ -10,7 +10,7 @@ on: - "pyproject.toml" - "uv.lock" pull_request: - branches: [main, dev] + branches: [macos] paths: - "install.sh" - "src/window/globalmenu/**" diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index af38932f..3452357c 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -2,9 +2,9 @@ name: Pre-commit on: push: - branches: [main, dev] + branches: [macos] pull_request: - branches: [main, dev] + branches: [macos] permissions: contents: read From 4285c1a0b844adf274423cc0483a8c234f4ddb26 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:53:54 +0545 Subject: [PATCH 10/14] ci: run workflows on all PRs (drop branch filter) --- .github/workflows/codeql.yml | 1 - .github/workflows/commitlint.yml | 1 - .github/workflows/install-test.yml | 1 - .github/workflows/pre-commit.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 74bc76e1..aadc93e2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -4,7 +4,6 @@ on: push: branches: [macos] pull_request: - branches: [macos] schedule: - cron: "0 6 * * 1" diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 4db277c1..3fa0305b 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -2,7 +2,6 @@ name: Commit Lint on: pull_request: - branches: [macos] permissions: contents: read diff --git a/.github/workflows/install-test.yml b/.github/workflows/install-test.yml index 2c9eb741..13049942 100644 --- a/.github/workflows/install-test.yml +++ b/.github/workflows/install-test.yml @@ -10,7 +10,6 @@ on: - "pyproject.toml" - "uv.lock" pull_request: - branches: [macos] paths: - "install.sh" - "src/window/globalmenu/**" diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 3452357c..c5880d01 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -4,7 +4,6 @@ on: push: branches: [macos] pull_request: - branches: [macos] permissions: contents: read From 3bc086596a622d444bf95fe3d90520e9cd6bc7cd Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 22:59:11 +0545 Subject: [PATCH 11/14] feat(settings): add hover_scale entry, fix SettingsEntry float handling --- src/window/settings/main.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/window/settings/main.py b/src/window/settings/main.py index 103b84fa..41a1d04a 100644 --- a/src/window/settings/main.py +++ b/src/window/settings/main.py @@ -1,4 +1,4 @@ -from fabric.utils import Gdk, Gtk, logger +from fabric.utils import Gdk, Gtk from fabric.widgets.box import Box from fabric.widgets.button import Button from fabric.widgets.centerbox import CenterBox @@ -90,12 +90,13 @@ def _on_config_change(self, new_config, old_config): def on_change(self, entry, *args): value = entry.get_text() - # Try to convert to int if possible try: if value.isdigit(): value = int(value) - except Exception as e: - logger.error(f"An error occurred: {e}") + else: + value = float(value) + except (ValueError, TypeError): + pass config().set(self.config_key, value) config().save() @@ -400,6 +401,11 @@ def _create_dock_page(self): SettingsSwitch("dock.hide_special_workspace_apps"), "Hide apps from special workspace in dock", ), + SettingsRow( + "Hover Scale", + SettingsEntry("dock.hover_scale"), + "Icon scale on hover (1.0 = off, 1.6 = default, 2.0 = max)", + ), ], ) From a258732528966eb4e56f8648f58cc43b52a4b412 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 23:05:23 +0545 Subject: [PATCH 12/14] ci: add commitlint config extending @commitlint/config-conventional --- commitlint.config.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 commitlint.config.js diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..5073c20d --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = { extends: ["@commitlint/config-conventional"] }; From 7925bf3cfb3fa2968d9785c0017f82d5b74c4fd0 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 23:09:29 +0545 Subject: [PATCH 13/14] docs: add LLM assistance note to documentation section --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3bce0417..b871e3d7 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,8 @@ See [Desktop Widgets Guide](docs/desktop_widgets.md) for full docs and examples. ## Documentation +> **Note:** These docs were written with the assistance of LLM tools. Some phrasing may reflect that. + | Doc | What's inside | | --------------------------------------------- | -------------------------------------------------- | | [Installation Guide](docs/installation.md) | Automated & manual install, dependencies | From a3dc4491cdebdaa0f753469f09afce5ee399f1ba Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Thu, 30 Jul 2026 23:17:53 +0545 Subject: [PATCH 14/14] ci: add CODEOWNERS to auto-request review on PRs --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..8f1b162d --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @S4NKALP