Files
meshcore-gui/RELEASE.md
T
2026-02-04 10:00:20 +01:00

143 lines
5.8 KiB
Markdown

# Release Notes — MeshCore GUI
**Date:** 4 February 2026
---
## Summary
This release replaces the single-file monolith (`meshcore_gui.py`, 1,395 lines, 3 classes, 51 methods) with a modular package of 16 files (1,955 lines, 10 classes, 90 methods). The refactoring introduces a `meshcore_gui/` package with Protocol-based dependency inversion, a `widgets/` subpackage with six independent UI components, a message route visualisation page, and full type coverage.
---
## Starting point
The repository contained one file with everything in it:
**`meshcore_gui.py`** — 1,395 lines, 3 classes, 51 methods
| Section | Lines | Methods | Responsibility |
|---------|-------|---------|----------------|
| Config + `debug_print` | 80 | 1 | Constants, debug helper |
| `SharedData` | 225 | 12 | Thread-safe data store |
| `BLEWorker` | 268 | 11 | BLE communication thread |
| `MeshCoreGUI` | 740 | 24 | All GUI: rendering, data updates, user actions |
| Main entry | 74 | 3 | Page handler, `main()` |
All three classes lived in one file. BLEWorker and MeshCoreGUI both depended directly on the concrete SharedData class. MeshCoreGUI handled everything: 8 render methods, 7 data-update methods, 5 user-action methods, the 500ms update timer, and the DM dialog.
---
## Current state
16 files across a package with a `widgets/` subpackage:
| File | Lines | Class | Depends on |
|------|-------|-------|------------|
| `meshcore_gui.py` | 101 | *(entry point)* | concrete SharedData (composition root) |
| `meshcore_gui/__init__.py` | 8 | — | — |
| `meshcore_gui/config.py` | 54 | — | — |
| `meshcore_gui/protocols.py` | 83 | 4 Protocol classes | — |
| `meshcore_gui/shared_data.py` | 263 | SharedData | config |
| `meshcore_gui/ble_worker.py` | 252 | BLEWorker | SharedDataWriter protocol |
| `meshcore_gui/main_page.py` | 148 | DashboardPage | SharedDataReader protocol |
| `meshcore_gui/route_builder.py` | 174 | RouteBuilder | ContactLookup protocol |
| `meshcore_gui/route_page.py` | 258 | RoutePage | SharedDataReadAndLookup protocol |
| `meshcore_gui/widgets/__init__.py` | 22 | — | — |
| `meshcore_gui/widgets/device_panel.py` | 100 | DevicePanel | config |
| `meshcore_gui/widgets/map_panel.py` | 80 | MapPanel | — |
| `meshcore_gui/widgets/contacts_panel.py` | 114 | ContactsPanel | config |
| `meshcore_gui/widgets/message_input.py` | 83 | MessageInput | — |
| `meshcore_gui/widgets/message_list.py` | 156 | MessageList | — |
| `meshcore_gui/widgets/rx_log_panel.py` | 59 | RxLogPanel | — |
| **Total** | **1,955** | **10 classes** | |
---
## What changed
### 1. Monolith → package
The single file was split into a `meshcore_gui/` package. Each class got its own module. Constants and `debug_print` moved to `config.py`. The original `meshcore_gui.py` became a thin entry point (101 lines) that wires components and starts the server.
### 2. Protocol-based dependency inversion
Four `typing.Protocol` interfaces were introduced in `protocols.py`:
| Protocol | Consumer | Methods |
|----------|----------|---------|
| SharedDataWriter | BLEWorker | 10 |
| SharedDataReader | DashboardPage | 4 |
| ContactLookup | RouteBuilder | 1 |
| SharedDataReadAndLookup | RoutePage | 5 |
No consumer imports `shared_data.py` directly. Only the entry point knows the concrete class.
### 3. MeshCoreGUI decomposed into DashboardPage + 6 widgets
The 740-line MeshCoreGUI class was split:
| Old (MeshCoreGUI) | New | Lines |
|--------------------|-----|-------|
| 8 `_render_*` methods | 6 widget classes in `widgets/` | 592 total |
| 7 `_update_*` methods | Widget `update()` methods | *(inside widgets)* |
| 5 user-action methods | Widget `on_command` callbacks | *(inside widgets)* |
| `render()` + `_update_ui()` | DashboardPage (orchestrator) | 148 |
DashboardPage now has 4 methods. It composes widgets and drives the timer. Widgets have zero knowledge of SharedData — they receive plain `Dict` snapshots and callbacks.
### 4. Route visualisation (new feature)
Two new modules that did not exist in the monolith:
| Module | Lines | Purpose |
|--------|-------|---------|
| `route_builder.py` | 174 | Constructs route data from message metadata (pure logic) |
| `route_page.py` | 258 | Renders route on a Leaflet map in a separate browser tab |
Clicking a message in the message list opens `/route/{msg_index}` showing sender → repeater hops → receiver on a map.
### 5. SharedData extended
SharedData gained 4 new methods to support the protocol interfaces and route feature:
| New method | Purpose |
|------------|---------|
| `set_connected()` | Explicit setter (was direct attribute access) |
| `put_command()` | Queue command from GUI (was `cmd_queue.put()` directly) |
| `get_next_command()` | Dequeue command for BLE worker (was `cmd_queue.get_nowait()` directly) |
| `get_contact_by_prefix()` | Contact lookup for route building |
| `get_contact_name_by_prefix()` | Contact name lookup for DM display |
The direct `self.shared.lock` and `self.shared.cmd_queue` access from BLEWorker and MeshCoreGUI was replaced with proper method calls through protocol interfaces.
### 6. Full type coverage
All 90 methods now have complete type annotations (parameters and return types). The old monolith had 51 methods with partial coverage.
---
## Metrics
| Metric | Old | Current |
|--------|-----|---------|
| Files | 1 | 16 |
| Lines | 1,395 | 1,955 |
| Classes | 3 | 10 |
| Methods | 51 | 90 |
| Largest class (lines) | MeshCoreGUI (740) | SharedData (263) |
| Protocol interfaces | 0 | 4 |
| Type-annotated methods | partial | 90/90 |
| Widget classes | 0 | 6 |
---
## Documentation
| Document | Status |
|----------|--------|
| `README.md` | Updated: architecture diagram, project structure, features |
| `docs/MeshCore_GUI_Design.docx` | Updated: widget tables, component descriptions, version history |
| `docs/SOLID_ANALYSIS.md` | Updated: widget SRP, dependency tree, metrics |
| `docs/RELEASE.md` | New (this document) |