Commit Graph

36 Commits

Author SHA1 Message Date
edd1416407 refactor: Make EffectPlugin an abstract base class, update effects to inherit from it, and improve plugin discovery. 2026-03-18 23:06:04 -07:00
1b29e91f9d fix: use theme-aware msg_gradient for ntfy messages
Replace lr_gradient_opposite() with msg_gradient() in render_message_overlay().
Messages now render in complementary colors matching the active theme:
- Green theme → magenta messages
- Orange theme → blue messages
- Purple theme → yellow messages
2026-03-16 03:25:52 -07:00
31f5d9f171 Merge origin/main into feat/color-pick
Resolved conflicts in tests/test_config.py by keeping TestActiveTheme tests.
Main branch has new architecture components (controller, events, layers, effects).
Color scheme feature preserved and compatible.
2026-03-16 03:13:13 -07:00
bc20a35ea9 refactor: Fix import ordering and code formatting with ruff
Organize imports in render.py and scroll.py to meet ruff style requirements.
Add blank lines for code formatting compliance.
2026-03-16 03:01:22 -07:00
d4d0344a12 feat: add pick_color_theme() UI and integration 2026-03-16 02:58:18 -07:00
84cb16d463 feat: update scroll.py to use theme message gradient
Add msg_gradient() helper function to render.py that applies message
(ntfy) gradient using the active theme's message_gradient property.
This replaces hardcoded magenta gradient in scroll.py with a theme-aware
approach that uses complementary colors from the active theme.

- Add msg_gradient(rows, offset) helper in render.py with fallback to
  default magenta gradient when no theme is active
- Update scroll.py imports to use msg_gradient instead of
  lr_gradient_opposite
- Replace lr_gradient_opposite() call with msg_gradient() in message
  overlay rendering
- Add 6 comprehensive tests for msg_gradient covering theme usage,
  fallback behavior, and edge cases

All tests pass (121 passed), no regressions detected.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-16 02:55:17 -07:00
d67423fe4c feat: update lr_gradient to use config.ACTIVE_THEME
- Remove hardcoded GRAD_COLS and MSG_GRAD_COLS module constants
- Add _default_green_gradient() and _default_magenta_gradient() fallback functions
- Add _color_codes_to_ansi() to convert integer color codes from themes to ANSI escape strings
- Update lr_gradient() signature: cols parameter (was grad_cols)
- lr_gradient() now pulls colors from config.ACTIVE_THEME when available
- Falls back to default green gradient when no theme is active
- Existing calls with explicit cols parameter continue to work
- Add comprehensive tests for new functionality

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-16 02:53:22 -07:00
ebe7b04ba5 feat: add ACTIVE_THEME global and set_active_theme() to config 2026-03-16 02:50:36 -07:00
abc4483859 feat: create Theme class and registry with finalized color gradients 2026-03-16 02:49:15 -07:00
72d21459ca Merge branch 'main' into feat/code-scroll 2026-03-16 09:16:36 +00:00
2229ccdea4 feat: introduce a 'code' mode to display source code lines, add new font assets, and include dedicated tests for code fetching. 2026-03-16 02:09:56 -07:00
4228400c43 feat(daemon): add display abstraction and daemon mode with C&C 2026-03-15 19:17:23 -07:00
cfd7e8931e feat(effects): add plugin architecture with performance monitoring 2026-03-15 19:17:10 -07:00
15de46722a refactor: phase 4 - event-driven architecture foundation
- Add EventBus class with pub/sub messaging (thread-safe)
- Add emitter Protocol classes (EventEmitter, Startable, Stoppable)
- Add event emission to NtfyPoller (NtfyMessageEvent)
- Add event emission to MicMonitor (MicLevelEvent)
- Update StreamController to publish stream start/end events
- Add comprehensive tests for eventbus and emitters modules
2026-03-15 19:15:08 -07:00
35e5c8d38b refactor: phase 3 - API efficiency improvements
Add typed dataclasses for tuple returns:
- types.py: HeadlineItem, FetchResult, Block dataclasses with legacy tuple converters
- fetch.py: Add type hints and HeadlineTuple type alias

Add pyright for static type checking:
- Add pyright to dependencies
- Verify type coverage with pyright (0 errors in core modules)

This enables:
- Named types instead of raw tuples (better IDE support, self-documenting)
- Type-safe APIs across modules
- Backward compatibility via to_tuple/from_tuple methods

Note: Lazy imports skipped for render.py - startup impact is minimal.
2026-03-15 19:13:32 -07:00
cdc8094de2 refactor: phase 2 - modularization of scroll engine
Split monolithic scroll.py into focused modules:
- viewport.py: terminal size (tw/th), ANSI positioning helpers
- frame.py: FrameTimer class, scroll step calculation
- layers.py: message overlay, ticker zone, firehose rendering
- scroll.py: simplified orchestrator, imports from new modules

Add stream controller and event types for future event-driven architecture:
- controller.py: StreamController for source initialization and stream lifecycle
- events.py: EventType enum and event dataclasses (HeadlineEvent, FrameTickEvent, etc.)

Added tests for new modules:
- test_viewport.py: 8 tests for viewport utilities
- test_frame.py: 10 tests for frame timing
- test_layers.py: 13 tests for layer compositing
- test_events.py: 11 tests for event types
- test_controller.py: 6 tests for stream controller

This enables:
- Testable chunks with clear responsibilities
- Reusable viewport utilities across modules
- Better separation of concerns in render pipeline
- Foundation for future event-driven architecture

Also includes Phase 1 documentation updates in code comments.
2026-03-15 19:13:32 -07:00
f170143939 refactor: phase 1 - testability improvements
- Add Config dataclass with get_config()/set_config() for injection
- Add Config.from_args() for CLI argument parsing (testable)
- Add platform font path detection (Darwin/Linux)
- Bound translate cache with @lru_cache(maxsize=500)
- Add fixtures for external dependencies (network, feeds, config)
- Add 15 tests for Config class, from_args, and platform detection

This enables testability by:
- Allowing config injection instead of global mutable state
- Supporting custom argv in from_args() for testing
- Providing reusable fixtures for mocking network/filesystem
- Preventing unbounded memory growth in translation cache

Fixes: _arg_value/_arg_int not accepting custom argv
2026-03-15 19:13:32 -07:00
9ae4dc2b07 fix: update ntfy tests for SSE API (reconnect_delay) 2026-03-15 15:16:37 -07:00
757c854584 fix: apply ruff auto-fixes and add hk git hooks
- Fix pre-existing lint errors in engine/ modules using ruff --unsafe-fixes
- Add hk.pkl with pre-commit and pre-push hooks using ruff builtin
- Configure hooks to use 'uv run' prefix for tool execution
- Update mise.toml to include hk and pkl tools
- All 73 tests pass

fix: apply ruff auto-fixes and add hk git hooks

- Fix pre-existing lint errors in engine/ modules using ruff --unsafe-fixes
- Add hk.pkl with pre-commit and pre-push hooks using ruff builtin
- Configure hooks to use 'uv run' prefix for tool execution
- Update mise.toml to include hk and pkl tools
- Use 'hk install --mise' for proper mise integration
- All 73 tests pass
2026-03-15 15:16:37 -07:00
4844a64203 style: apply ruff auto-fixes across codebase
- Fix import sorting (isort) across all engine modules
- Fix SIM105 try-except-pass patterns (contextlib.suppress)
- Fix nested with statements in tests
- Fix unused loop variables

Run 'uv run pytest' to verify tests still pass.
2026-03-15 15:16:37 -07:00
6e39a2dad2 feat: migrate Ntfy message retrieval from polling to SSE streaming, replacing poll_interval with reconnect_delay for continuous updates. 2026-03-15 13:44:26 -07:00
11226872a1 feat: Implement interactive font selection by scanning the fonts/ directory for .otf, .ttf, and .ttc files, adding new fonts and updating documentation. 2026-03-15 03:52:10 -07:00
e6826c884c feat: Implement an interactive font face picker at startup, allowing selection of specific font faces from a font file. 2026-03-15 03:38:14 -07:00
9140bfd32b feat: Introduce a complementary color gradient for queue messages. 2026-03-15 02:44:38 -07:00
66c13b5829 refactor: Change firehose from a drifting overlay to a fixed bottom strip and message display from a top-pinned section to a centered overlay. 2026-03-15 02:26:44 -07:00
086214f05e style: remove firehose opaque row backdrop and background color 2026-03-15 01:31:44 -07:00
0f762475b5 feat: Apply a distinct background color to firehose lines. 2026-03-15 01:08:17 -07:00
b00b612da0 refactor: rename rendering components and variables for clarity, distinguishing between message, ticker, and scroll motion layers. 2026-03-15 00:58:36 -07:00
39dab4b22b feat: Implement a drifting firehose overlay that scrolls independently over the main ticker content. 2026-03-15 00:49:58 -07:00
9bd8115c55 feat: introduce the scroll engine with a main rendering loop for headlines, messages, and visual effects. 2026-03-14 23:36:56 -07:00
2c777729f5 feat: Introduce ntfy.sh message polling, content fetching with caching, and microphone input monitoring. 2026-03-14 23:34:23 -07:00
2e6b2c48bd feat: Introduce visual effects module, enhance text rendering with SSAA, and add shifting gradient support. 2026-03-14 22:15:48 -07:00
f6ad89769f feat: Implement OTF to terminal half-block rendering pipeline including font loading, text rasterization, word-wrap, and gradient coloring. 2026-03-14 21:53:47 -07:00
d3c403848c feat: Introduce translate module for Google Translate integration and location-based language detection, and add a new filter module. 2026-03-14 21:00:24 -07:00
119ed193c0 feat: Add terminal module. 2026-03-14 20:57:53 -07:00
dcc3718012 refactor: Create engine package, extracting data sources to sources.py, and add refactoring documentation. 2026-03-14 20:56:24 -07:00