9.3 KiB
CHANGELOG
All notable changes to MeshCore GUI are documented in this file. Format follows Keep a Changelog and Semantic Versioning.
[5.4.0] - 2026-02-08 — Contact Maintenance Feature
Added
-
✅ Pin/Unpin contacts (Iteratie A) — Toggle to pin individual contacts, protecting them from bulk deletion
- Persistent pin state stored in
~/.meshcore-gui/cache/<ADDRESS>_pins.json - Pinned contacts visually marked with yellow background
- Pinned contacts sorted to top of contact list
- Pin state survives app restart
- New service:
services/pin_store.py— JSON-backed persistent pin storage
- Persistent pin state stored in
-
✅ Bulk delete unpinned contacts (Iteratie B) — Remove all unpinned contacts from device in one action
- "🧹 Clean up" button in contacts panel with confirmation dialog
- Shows count of contacts to be removed vs. pinned contacts kept
- Progress status updates during removal
- Automatic device resync after completion
- New service:
services/contact_cleaner.py— ContactCleanerService with purge statistics
-
✅ Auto-add contacts toggle (Iteratie C) — Control whether device automatically adds new contacts from mesh adverts
- "📥 Auto-add" checkbox in contacts panel (next to Clean up button)
- Syncs with device via
set_manual_add_contacts()SDK call - Inverted logic handled internally (UI "Auto-add ON" =
set_manual_add_contacts(false)) - Optimistic update with automatic rollback on BLE failure
- State synchronized from device on each GUI update cycle
Changed
- 🔄
contacts_panel.py: Added pin checkbox per contact, purge button, auto-add toggle, DM dialog (all existing functionality preserved) - 🔄
commands.py: Addedpurge_unpinnedandset_auto_addcommand handlers - 🔄
shared_data.py: Addedauto_add_enabledfield with thread-safe getter/setter - 🔄
protocols.py: Addedset_auto_add_enabledandis_auto_add_enabledto Writer and Reader protocols - 🔄
dashboard.py: PassesPinStoreandset_auto_add_enabledcallback to ContactsPanel - 🔄 UI language: All Dutch strings in
contacts_panel.pyandcommands.pytranslated to English
Fixed
- 🐛 Route table names and IDs not displayed — Route tables in both current messages (RoutePage) and archive messages (ArchivePage) now correctly show node names and public key IDs for sender, repeaters and receiver
Changed
- 🔄 CHANGELOG.md: Corrected version numbering (v1.0.x → v5.x), fixed inaccurate references (archive button location, filter state persistence)
- 🔄 README.md: Added Message Archive feature, updated project structure, configuration table and architecture diagram
- 🔄 MeshCore_GUI_Design.docx: Added ArchivePage, MessageArchive, Models components; updated project structure, protocols, configuration and version history
[5.2.0] - 2026-02-07 — Archive Viewer Feature
Added
- ✅ Archive Viewer Page (
/archive) — Full-featured message archive browser- Pagination (50 messages per page, configurable)
- Channel filter dropdown (All + configured channels)
- Time range filter (24h, 7d, 30d, 90d, All time)
- Text search (case-insensitive)
- Filter state stored in instance variables (reset on page reload)
- Message cards with same styling as main messages panel
- Clickable messages for route visualization (where available)
- 💬 Reply functionality — Expandable reply panel per message
- 🗺️ Inline route table — Expandable route display per archive message with sender, repeaters and receiver (names, IDs, node types)
-
✅ MessageArchive.query_messages() method
- Filter by: time range, channel, text search, sender
- Pagination support (limit, offset)
- Returns tuple: (messages, total_count)
- Sorting: Newest first
-
✅ UI Integration
- "📚 Archive" button in Messages panel header (opens in new tab)
- Back to Dashboard button in archive page
- ✅ Reply Panel
- Expandable reply per message (💬 Reply button)
- Pre-filled with @sender mention
- Channel selector
- Send button with success notification
- Auto-close expansion after send
Changed
- 🔄
SharedData.get_snapshot(): Now includes'archive'field - 🔄
MessagesPanel: Added archive button in header row - 🔄 Both entry points (
__main__.pyandmeshcore_gui.py): Register/archiveroute
Performance
- Query: ~10ms for 10k messages with filters
- Memory: ~10KB per page (50 messages)
- No impact on main UI (separate page)
Known Limitations
- Route visualization only works for messages in recent buffer (last 100)
- Archived-only messages show warning notification
- Text search is linear scan (no indexing yet)
- Sender filter exists in API but not in UI yet
[5.1.3] - 2026-02-07 — Critical Bugfix: Archive Overwrite Prevention
Fixed
- 🐛 CRITICAL: Fixed bug where archive was overwritten instead of appended on restart
- 🐛 Archive now preserves existing data when read errors occur
- 🐛 Buffer is retained for retry if existing archive cannot be read
Changed
- 🔄
_flush_messages(): Early return on read error instead of overwriting - 🔄
_flush_rxlog(): Early return on read error instead of overwriting - 🔄 Better error messages for version mismatch and JSON decode errors
Details
Problem: If the existing archive file had a JSON parse error or version mismatch,
the flush operation would proceed with existing_messages = [], effectively
overwriting all historical data with only the new buffered messages.
Solution: The flush methods now:
- Try to read existing archive first
- If read fails (JSON error, version mismatch, IO error), abort the flush
- Keep buffer intact for next retry
- Only clear buffer after successful write
Impact: No data loss on restart or when archive files have issues.
Testing
- ✅ Added
test_append_on_restart_not_overwrite()integration test - ✅ Verifies data is appended across multiple sessions
- ✅ All existing tests still pass
[5.1.2] - 2026-02-07 — RxLog message_hash Enhancement
Added
- ✅
message_hashfield added toRxLogEntrymodel - ✅ RxLog entries now include message_hash for correlation with messages
- ✅ Archive JSON includes message_hash in rxlog entries
Changed
- 🔄
events.py: Restructuredon_rx_log()to extract message_hash before creating RxLogEntry - 🔄
message_archive.py: Updated rxlog archiving to include message_hash field - 🔄 Tests updated to verify message_hash persistence
Benefits
- Correlation: Link RX log entries to their corresponding messages
- Analysis: Track which packets resulted in messages
- Debugging: Better troubleshooting of packet processing
[5.1.1] - 2026-02-07 — Entry Point Fix
Fixed
- ✅
meshcore_gui.py(root entry point) now passes ble_address to SharedData - ✅ Archive works correctly regardless of how application is started
Changed
- 🔄 Both entry points (
meshcore_gui.pyandmeshcore_gui/__main__.py) updated
[5.1.0] - 2026-02-07 — Message & Metadata Persistence
Added
- ✅ MessageArchive class for persistent storage
- ✅ Configurable retention periods (MESSAGE_RETENTION_DAYS, RXLOG_RETENTION_DAYS, CONTACT_RETENTION_DAYS)
- ✅ Automatic daily cleanup of old data
- ✅ Batch writes for performance
- ✅ Thread-safe with separate locks
- ✅ Atomic file writes
- ✅ Contact retention in DeviceCache
- ✅ Archive statistics API
- ✅ Comprehensive tests (20+ unit, 8+ integration)
- ✅ Full documentation
Storage Locations
~/.meshcore-gui/archive/<ADDRESS>_messages.json~/.meshcore-gui/archive/<ADDRESS>_rxlog.json
Requirements Completed
- R1: All incoming messages persistent ✅
- R2: All incoming RxLog entries persistent ✅
- R3: Configurable retention ✅
- R4: Automatic cleanup ✅
- R5: Backward compatibility ✅
- R6: Contact retention ✅
- R7: Archive stats API ✅