|
| 1 | +# Event Architecture |
| 2 | + |
| 3 | +This document tracks the event orchestration introduced in the 2026 refactor. |
| 4 | + |
| 5 | +## Files and Responsibilities |
| 6 | + |
| 7 | +- `src/Events/AppEventBus.vala` |
| 8 | + - Defines typed cross-component application signals. |
| 9 | + - Current signals: |
| 10 | + - `connectivity_changed(bool is_online, bool is_offline)` |
| 11 | + |
| 12 | +- `src/Coordinators/StartupCoordinator.vala` |
| 13 | + - Owns startup workflow orchestration. |
| 14 | + - Current workflow: |
| 15 | + - deferred autoplay of last station |
| 16 | + - waits for online connectivity before autoplay attempt |
| 17 | + - attempts autoplay once per app start |
| 18 | + |
| 19 | +- `src/Coordinators/PlaybackRecoveryCoordinator.vala` |
| 20 | + - Owns restart-after-outage playback behavior. |
| 21 | + - Tracks whether playback was active before loss of connectivity. |
| 22 | + - Restarts playback on reconnect when `settings.play_restart` is enabled. |
| 23 | + |
| 24 | +- `src/Coordinators/UsageTrackingCoordinator.vala` |
| 25 | + - Owns provider click/vote updates driven by player events. |
| 26 | + - Handles both play-start click tracking and periodic tape-counter tracking. |
| 27 | + |
| 28 | +- `src/Application.vala` |
| 29 | + - Owns the shared `events` bus instance. |
| 30 | + - Emits `connectivity_changed` when `is_online`/`is_offline` changes. |
| 31 | + - Instantiates coordinators: |
| 32 | + - `PlaybackRecoveryCoordinator` during app construction. |
| 33 | + - `UsageTrackingCoordinator` during app construction. |
| 34 | + - `StartupCoordinator` after creating the main window. |
| 35 | + |
| 36 | +- `src/Widgets/Window.vala` |
| 37 | + - Consumes app-level connectivity events to update interactive window state. |
| 38 | + - No longer owns autoplay orchestration. |
| 39 | + |
| 40 | +- `src/Widgets/HeaderBar.vala` |
| 41 | + - Consumes app-level connectivity and player-state events for control-state updates. |
| 42 | + - No longer owns restart-after-outage orchestration. |
| 43 | + |
| 44 | +- `src/meson.build` |
| 45 | + - Registers the new event/coordinator source files in build inputs. |
| 46 | + |
| 47 | +## Event Flow (Connectivity) |
| 48 | + |
| 49 | +1. `Application` detects network change. |
| 50 | +2. `Application` updates `is_online` and `is_offline`. |
| 51 | +3. `Application` emits `events.connectivity_changed(...)`. |
| 52 | +4. Subscribers react: |
| 53 | + - `Window` updates active UI state. |
| 54 | + - `HeaderBar` updates visual controls. |
| 55 | + - `PlaybackRecoveryCoordinator` manages restart-after-outage behavior. |
| 56 | + - `StartupCoordinator` tries deferred autoplay when online. |
| 57 | + |
| 58 | +## Design Notes |
| 59 | + |
| 60 | +- Keep local widget events in widget files. |
| 61 | +- Use `AppEventBus` for cross-component events that otherwise create tight coupling. |
| 62 | +- Use coordinators for workflows that span UI + services + application state. |
| 63 | + |
| 64 | +## Window Action Handling |
| 65 | + |
| 66 | +- `src/Widgets/Window.vala` now centralizes action-state initialization with: |
| 67 | + - `sync_action_states_from_settings()` |
| 68 | +- Boolean toggle actions now use a shared path: |
| 69 | + - `toggle_setting_action(...)` |
| 70 | +- This reduces copy/paste logic across action handlers and lowers the chance of mismatched setting/action wiring. |
| 71 | + |
| 72 | +## Search Debounce Ownership |
| 73 | + |
| 74 | +- `src/Widgets/HeaderBar.vala` |
| 75 | + - Emits `searching_for_sig` immediately on text change. |
| 76 | + - No longer owns debounce timers. |
| 77 | +- `src/Controllers/SearchController.vala` |
| 78 | + - Owns debounce and pending-search cancellation. |
| 79 | + - Uses configured `_max_search_results` instead of a hardcoded limit. |
| 80 | +- `src/Widgets/Display.vala` |
| 81 | + - Receives search focus/query via explicit methods: |
| 82 | + - `on_search_focused()` |
| 83 | + - `on_search_requested(string text)` |
| 84 | + - No longer routes search input through internal self-signals. |
| 85 | + |
| 86 | +## Application Bootstrap Decomposition |
| 87 | + |
| 88 | +- `src/Application.vala` |
| 89 | + - Keeps construct-only property assignment in the `construct` block. |
| 90 | + - Splits initialization responsibilities into helper methods: |
| 91 | + - runtime storage preparation + migration |
| 92 | + - connectivity monitoring setup |
| 93 | + - core service factory helpers |
| 94 | + - coordinator initialization |
| 95 | + - action registration helpers |
| 96 | + - Activation flow is split into explicit lifecycle helpers: |
| 97 | + - `initialize_runtime_presentation()` |
| 98 | + - `apply_runtime_preferences()` |
| 99 | + - `create_main_window()` |
| 100 | + |
| 101 | +## Window Connectivity UI State |
| 102 | + |
| 103 | +- `src/Widgets/Window.vala` |
| 104 | + - `check_online_status()` now delegates UI transitions to: |
| 105 | + - `apply_offline_ui_state()` |
| 106 | + - `apply_online_ui_state()` |
| 107 | + - Keeps online/offline behavior explicit and reduces branching complexity. |
| 108 | + |
| 109 | +## Display API Cleanup |
| 110 | + |
| 111 | +- `src/Widgets/Display.vala` |
| 112 | + - Removed unused public signals: |
| 113 | + - `favourites_changed_sig` |
| 114 | + - `refresh_starred_stations_sig` |
| 115 | + - Keeps the public event surface aligned with active call paths. |
| 116 | + |
| 117 | +## Dependency Injection Sweep |
| 118 | + |
| 119 | +- Replaced singleton `app()` lookups with injected references in: |
| 120 | + - `src/Widgets/HeaderBar.vala` |
| 121 | + - `src/Widgets/Display.vala` |
| 122 | + - `src/Services/DBusMediaPlayer.vala` |
| 123 | +- Constructors and initializers now receive required collaborators explicitly |
| 124 | + (`Application`, `PlayerController`, `DataProvider.API`, `StarStore`), reducing |
| 125 | + hidden coupling and startup-order risk. |
| 126 | + |
| 127 | +## Coordinator Connectivity Injection |
| 128 | + |
| 129 | +- Removed remaining coordinator singleton lookups by injecting `Application` |
| 130 | + explicitly into: |
| 131 | + - `src/Coordinators/StartupCoordinator.vala` |
| 132 | + - `src/Coordinators/PlaybackRecoveryCoordinator.vala` |
| 133 | +- `StartupCoordinator.try_autoplay()` now checks `_app.is_offline`. |
| 134 | +- `PlaybackRecoveryCoordinator.on_player_state_changed()` now checks |
| 135 | + `_app.is_online`. |
| 136 | +- `src/Application.vala` constructor wiring now passes `this` into coordinator |
| 137 | + constructors, making coordinator connectivity decisions explicit and testable. |
0 commit comments