15 Commits

Author SHA1 Message Date
MarekWo
8ab19582cd fix(dm): Fix unread markers by deduping retries in all endpoints
Extracted dedup_retry_messages() helper (300s window, was 120s which
was too tight) and applied it in three places:
- GET /api/dm/messages - already had inline dedup, now uses helper
- get_dm_conversations() - fixes last_message_timestamp inflation
- GET /api/dm/updates - was missing dedup entirely, counted retries
  as unread messages (root cause of persistent unread markers)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 10:34:39 +01:00
MarekWo
c2acbb4ba1 fix(dm): Wait for msg JSON response and fix unread markers
Monitor: For .msg commands, keep waiting for expected_ack in response
instead of completing on silence timeout. Waits up to half of cmd_timeout
(5s) for the JSON to arrive before giving up.

Unread: Apply 120s time-window dedup to outgoing messages in conversation
listing, so retry messages don't inflate last_message_timestamp and cause
permanent unread markers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 10:19:28 +01:00
MarekWo
68b2166445 fix: Use unstripped raw_text for pkt_payload computation
The parser's .strip() was removing trailing whitespace from message
text, but the encrypted radio payload includes those trailing spaces.
This caused pkt_payload mismatches for messages ending with spaces
(e.g., "Dzień dobry "). Use original unstripped text for raw_text.

Also add debug logging for unmatched messages to help diagnose
remaining edge cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 08:09:28 +01:00
MarekWo
28148d32d8 feat: Deterministic echo-to-message matching via pkt_payload computation
Replace unreliable timestamp-based heuristic (±10s window) with exact
cryptographic matching for incoming channel message routes. Compute
pkt_payload by reconstructing the AES-128-ECB encrypted packet from
message data (sender_timestamp, txt_type, text) + channel secret, then
match against echo data by exact key lookup.

Also accumulate ALL route paths per message (previously only last path
was kept due to dict overwrite), and display them in a multi-path popup
showing SNR and hops for each route.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 07:29:49 +01:00
MarekWo
7a960f2556 feat: Add DM delivery tracking via ACK packet detection
Bridge captures ACK packets from meshcli stdout (json_log_rx),
persists to .acks.jsonl, and exposes /ack_status endpoint.
Delivery status is merged server-side into DM messages and
displayed as a green checkmark with SNR/route tooltip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:30:33 +01:00
MarekWo
c7163aa035 feat: Auto-detect device name from meshcli prompt
Bridge now detects device name from meshcli prompt ("DeviceName|*")
and exposes it via /health endpoint. mc-webui fetches this at startup
and uses RuntimeConfig for dynamic device name throughout the app.

Fallback chain: prompt detection → .infos command → MC_DEVICE_NAME env var

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 07:48:10 +01:00
MarekWo
3d681f57ee fix(parser): Use sender field for SENT_CHAN in meshcore-cli 1.3.12+
Fix channel message sender name display. In meshcore-cli 1.3.12, the 'name'
field in SENT_CHAN entries now contains the channel name instead of the
sender's device name. Update parser to use the 'sender' field instead.

Before: Sent messages showed "channel 0" as sender
After: Sent messages correctly show "MarWoj" (actual sender name)

This change is consistent with the SENT_MSG parsing for Direct Messages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 07:15:24 +01:00
MarekWo
879f7041e7 refactor(dm): Use native SENT_MSG from meshcore-cli 1.3.12+ instead of custom log
Remove workaround for meshcore-cli 1.3.11 bug where SENT_MSG contained
sender name instead of recipient. Now using native SENT_MSG entries from
.msgs file with correct recipient and sender fields (requires meshcore-cli >= 1.3.12).

Changes:
- Add _parse_sent_msg() to parse SENT_MSG from .msgs file
- Update read_dm_messages() to process both PRIV and SENT_MSG from .msgs
- Remove save_sent_dm(), _read_sent_dm_log(), _parse_sent_dm_entry()
- Remove dm_sent_log_path property from config
- Add _cleanup_old_dm_sent_log() to remove obsolete log file
- Update comments and documentation

Benefits:
- Single source of truth (.msgs file only)
- Simpler codebase (-95 lines)
- No custom workarounds
- Better data consistency

Related: meshcore-cli update to 1.3.12 (commit ad4a7b3)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 19:48:39 +01:00
MarekWo
2788b92687 fix(dm): Improve DM UI consistency and fix conversation merging
- Fix duplicate conversations in dropdown by merging pk_ and name_ IDs
- Add intelligent refresh (only reload when new messages arrive)
- Fix message alignment (own messages right, others left)
- Change sent message status from 'timeout' to 'pending'
- Add emoji picker button to DM page
- Change message limit from 200 to 140 bytes (consistent with channels)
- Update README.md with corrected DM documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 22:29:57 +01:00
MarekWo
83b51ab2b9 refactor(dm): Replace modal with full-page view and fix sent DM tracking
- Replace DM modal with full-page view at /dm route for better mobile UX
- Add workaround for meshcore-cli bug where SENT_MSG contains sender's
  name instead of recipient - now saving sent DMs to separate log file
- Fix DM button styling to match Reply button (btn-outline-secondary)
- Add dm.js for DM page functionality
- Add dm.html template with green navbar for visual distinction
- Update menu link to navigate to /dm instead of opening modal
- Remove unused DM modal functions from app.js
- Update documentation with new DM workflow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:27:02 +01:00
MarekWo
1d2cc7fe18 feat: Add direct messages (DM) support
- Parse PRIV (incoming) and SENT_MSG (outgoing) message types
- Add DM API endpoints: conversations, messages, updates
- Implement conversation grouping by pubkey_prefix or name
- Add timeout-based delivery status (pending → timeout)
- Add DM modal with conversation list and thread views
- Add dual notification badge (blue=channels, green=DM)
- Add DM button next to Reply on channel messages
- Include message deduplication for both incoming and outgoing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 17:29:06 +01:00
MarekWo
6c3551cd2d feat: Add support for public channels and auto-cleanup on channel deletion
- Allow joining public channels (starting with #) without encryption key
  - Frontend: Make key field optional with validation for # channels
  - Backend: Update API to accept optional key parameter
  - CLI wrapper: Build meshcli command dynamically based on key presence

- Implement automatic message cleanup when deleting channels
  - Add delete_channel_messages() function to remove channel history
  - Integrate cleanup into DELETE /api/channels endpoint
  - Prevents message leakage when reusing channel slots

- Update documentation with new features and usage instructions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 12:34:14 +01:00
MarekWo
761e4eac25 feat: Implement full channel management functionality
Add comprehensive channel management features to mc-webui:
- Create new channels with auto-generated encryption keys
- Share channels via QR code or copy-to-clipboard
- Join existing channels with name and key
- Switch between channels in chat interface
- Filter messages by channel
- Persistent channel selection (localStorage)

Backend changes:
- Add CLI wrapper functions: get_channels, add_channel, set_channel, remove_channel
- Modify send_message() to support channel targeting
- Parametrize parser channel filtering (channel_idx parameter)
- Add QR code generation with qrcode + Pillow libraries

API endpoints:
- GET /api/channels - List all channels
- POST /api/channels - Create new channel
- POST /api/channels/join - Join existing channel (auto-detect free slot)
- DELETE /api/channels/<index> - Remove channel
- GET /api/channels/<index>/qr - Generate QR code (JSON or PNG)
- Modified GET /api/messages - Add channel_idx filtering
- Modified POST /api/messages - Add channel_idx targeting

Frontend changes:
- Add channel selector dropdown in navbar
- Add Channels Management modal (create, join, list)
- Add Share Channel modal (QR code, copy key)
- Implement JavaScript channel management logic
- Add event handlers for channel switching
- Persist selected channel in localStorage

QR code format:
{"type":"meshcore_channel","name":"...","key":"..."}

Protection:
- Block deletion of Public channel (index 0)
- Validate channel names (alphanumeric, _, - only)
- Validate encryption keys (32 hex chars)
- Auto-detect free channel slots (1-7)

Backward compatibility:
- Default channel_idx=0 (Public) in all functions
- Existing Public-only code continues to work

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 19:04:00 +01:00
MarekWo
f5fedbc96c Feature: Add message archiving system with browse-by-date selector
Implements automatic daily archiving of messages to improve performance
and enable browsing historical chat by date.

Backend changes:
- Add APScheduler for daily archiving at midnight (00:00 UTC)
- Create app/archiver/manager.py with archive logic and scheduler
- Extend parser.py to read from archive files and filter by days
- Add archive configuration to config.py (MC_ARCHIVE_*)

API changes:
- Extend GET /api/messages with archive_date and days parameters
- Add GET /api/archives endpoint to list available archives
- Add POST /api/archive/trigger for manual archiving

Frontend changes:
- Add date selector dropdown in navbar for archive browsing
- Implement archive list loading and date selection
- Update formatTime() to show full dates in archive view
- Live view now shows only last 7 days (configurable)

Docker & Config:
- Add archive volume mount in docker-compose.yml
- Add MC_ARCHIVE_DIR, MC_ARCHIVE_ENABLED, MC_ARCHIVE_RETENTION_DAYS env vars
- Update .env.example with archive configuration section

Documentation:
- Update README.md with archive feature and usage instructions
- Update .claude/instructions.md with archive endpoints

Key features:
- Automatic daily archiving (midnight UTC)
- Live view filtered to last 7 days for better performance
- Browse historical messages by date via dropdown selector
- Archives stored as dated files: {device}.YYYY-MM-DD.msgs
- Original .msgs file never modified (safe, read-only approach)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 20:21:33 +01:00
MarekWo
cf456422e2 Phase 1: Backend basics - Complete Flask application with REST API
Implemented core backend functionality:
- Flask application structure with blueprints
- Configuration module loading from environment variables
- MeshCore CLI wrapper with subprocess execution and timeout handling
- Message parser for .msgs JSON Lines file format
- REST API endpoints (messages, status, sync, contacts cleanup)
- HTML views with Bootstrap 5 responsive design
- Frontend JavaScript with auto-refresh and live updates
- Custom CSS styling for chat interface

API Endpoints:
- GET  /api/messages - List messages with pagination
- POST /api/messages - Send message with optional reply-to
- GET  /api/status - Device connection status
- POST /api/sync - Trigger message sync
- POST /api/contacts/cleanup - Remove inactive contacts
- GET  /api/device/info - Device information

Features:
- Auto-refresh every 60s (configurable)
- Reply to messages with @[UserName] format
- Toast notifications for feedback
- Settings modal for contact management
- Responsive design (mobile-friendly)
- Message bubbles with sender, timestamp, SNR, hop count

Ready for testing on production server (192.168.131.80:5000)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 14:02:46 +01:00