Weather: move networking, caching and scheduling out of the Weather widget
into a WeatherService singleton. Reuse one httpx.Client for the app lifetime,
drop the 4-worker pool and the multi-entry dict caches (single-value fields),
query Nominatim only on location change, remove debounce and the /tmp-style
polling. Widget now observes the `updated` signal and never hits the network.
GameMode: turn the standalone CLI script into a GameModeService (Service
singleton) exposing an `enabled` Property and `changed` signal. Drive Hyprland
via `hyprctl eval hl.config(...)` instead of the deprecated `hyprctl keyword`
batch (rejected under the Lua config in Hyprland 0.55+), read state via
`hl.get_config`, and keep `hyprctl reload` for disable. Fix game-mode state
parsing so unrecognized `hl.get_config` output no longer falsely reports
active. BatteryWidget's GameModeButton now subscribes to the service.
Remove now-unused LOCATION_CACHE_TIMEOUT.
Split the monolithic ScreenCapture service into focused Screenshot and
ScreenRecorder services behind a pluggable capture backend.
- Add shared/capture.py: CaptureBackend abstraction + HyprlandCaptureBackend
(hyprshot/grim/slurp/wf-recorder) and reusable CaptureNotifier
- Add services/screenshot.py and services/screenrecorder.py with Fabric
properties/signals; recording state kept in memory (no /tmp files)
- Keep services/screencapture.py as a backwards-compatible facade so
existing widgets and signals keep working
- Resolve monitors via Hyprland IPC helpers in services/modus.py instead of
spawning `hyprctl monitors -j` per capture
- Implement real window recording (slurp window boxes) and split the
record-window / record-region UI mappings
- Register screenshot_service / screen_recorder_service singletons
- Remove dead src/utils/inhibit.py duplicate; minor modus.lua quoting fix
- mpris: native MediaArt cache lookup, dedupe play/pause emission, safe
cleanup, artwork polling for already-playing browser players, drop
os.system seek fallback
- spotlight: scope plugin keyword and detect() matches to a single plugin
via search_single instead of global search; register clipboard keywords
(clip/clipboard)
- Update ruff to 0.15.2 in requirements.txt
- Add pre-commit to requirements.txt
- Update uv.lock with new dependencies
- Add config/plugins/ to gitignore, remove src/window/launcher
- Expand architecture overview with plugin system details
- Update configuration guide with new spotlight settings
- Improve FAQs with troubleshooting tips
- Remove docs/README.md (content merged into main README)
- Add on_clicked handler to search button in panel
- Add set_spotlight_toggle() method on Panel
- Connect spotlight.toggle in main.py after both are created
- Add -y/--yes flag to skip interactive prompts
- Replace cd/cd- with subshell in app-capture build
- Replace fragile grep -v pipe with stderr redirect for git output
- Total steps still matches progress calls
- Replace /home/sankalp/ with $INSTALL_DIR in MODUS_MODULE_LINE
- Fix TOTAL_STEPS 11→12 to match actual progress calls
- Move 'Launching Modus' to end (stop + start in one block)
- Remove orphaned 'Starting Modus' step from under Matugen
_check_icon_to_type now queries Gtk.IconTheme for the icon name
(with -symbolic suffix) before falling back to a hardcoded mapping.
_get_icon_for_device simplified since type property now returns
GTK icon names directly.
Add Pomodoro component with UI controls and state management,
modify Panel to instantiate and cache Pomodoro and TodoList widgets,
hook datetime button to toggle Pomodoro and handle right‑click on todo list,
extend destroy logic to cleanly close Pomodoro and Todo instances.
The lockscreen module in src/lock.py has been removed to clean up unused code and simplify the project structure. This change does not affect current functionality but prepares the codebase for future enhancements.