515 Commits

Author SHA1 Message Date
MarekWo
bf00e7c7d3 feat(paths): add repeater map picker for path configuration
Adds a map button (geo icon) next to the list picker in the path form.
Clicking it opens a modal with a Leaflet map showing repeater locations.
User clicks a repeater marker, then clicks Add to append its ID prefix
to the path hex. Includes Cached toggle to show all DB repeaters vs
only device-known ones. Respects current hash size setting (1B/2B/3B).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 08:13:20 +01:00
MarekWo
8aff9be570 fix(map): show correct "Last seen" for cached contacts
Used c.last_advert (numeric Unix timestamp) instead of c.last_seen
(ISO 8601 string) which caused formatTimeAgo() to return "Invalid Date".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 07:50:46 +01:00
MarekWo
aa1a1b203c feat(paths): add import button for current device path
Shows a download icon next to the device path display in Contact Info.
Clicking it imports the current device path into configured paths as
primary, with hash_size properly decoded from out_path_len.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:51:53 +01:00
MarekWo
b6dc03dce5 feat(paths): add Name/ID search mode toggle in repeater picker
ID mode searches by first N hex chars of public key (2/4/6 chars
depending on selected hash size). Placeholder updates dynamically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:38:41 +01:00
MarekWo
d6b2d01e2c fix(paths): use correct type=2 for repeater contacts
Type 1 is COM (companion), type 2 is REP (repeater).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:25:24 +01:00
MarekWo
8cc67f77d5 feat(dm): add multi-path management and per-contact no-flood toggle
- New `contact_paths` table for storing multiple user-configured paths per contact
- New `no_auto_flood` column on contacts to prevent automatic DIRECT→FLOOD reset
- Path rotation during DM retry: cycles through configured paths before optional flood fallback
- REST API for path CRUD, reorder, reset-to-flood, repeater listing
- Path management UI in Contact Info modal: add/delete/reorder paths, repeater picker with uniqueness warnings, hash size selector (1B/2B/3B)
- "No Flood" per-contact toggle in modal footer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:20:51 +01:00
MarekWo
dd81fbf0b7 fix(console): add min_timeout=15s to binary repeater requests
req_status, req_acl, req_neighbours, req_mma use send_binary_req
which calculates timeout from suggested_timeout/800. After firmware
updates this can be too short, causing instant timeouts. Adding
min_timeout=15 ensures we wait at least 15 seconds for a response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:01:44 +01:00
MarekWo
88d805dd3a docs: upgrade diagram 2026-03-21 16:37:35 +01:00
MarekWo
66ada3d03c docs: comprehensive documentation update for v2 features
Update all documentation to reflect features added since last doc update:
- README: new features list, gallery screenshots, development status
- User Guide: global search, console commands, device dashboard, settings,
  system log, backup, updated DM and contact management sections
- Architecture: complete API reference, WebSocket namespaces, updated
  project structure and database tables
- Troubleshooting: remove v1 bridge references, add UI-based backup,
  system log references
- Gallery: add 4 new screenshots (search, filtering, settings, system log),
  update 12 existing screenshots

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 16:26:52 +01:00
MarekWo
ce8227247f feat(chat): add quote dialog with configurable quote length
Add Group Chat tab in Settings with configurable quote byte limit.
When quoting a message longer than the limit, a dialog asks whether
to use full or truncated quote (with editable byte count).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 15:25:38 +01:00
MarekWo
33a71bed17 refactor(ui): rename contact type label CLI to COM (companion)
The MeshCore community uses "companion" not "client" for type 1 nodes.
Rename the CLI label to COM across all UI, API, JS, and docs to align
with official terminology. Includes cache migration for old CLI entries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 14:37:30 +01:00
MarekWo
8ba5381921 fix(settings): add note clarifying retry count includes initial send
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 13:57:23 +01:00
MarekWo
9e90e30d9f refactor(settings): compact table layout with tooltip info icons
Replace vertical form fields with table rows for less screen space.
Descriptions moved to (i) tooltip icons on hover/touch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 13:33:19 +01:00
MarekWo
6f1a5462e9 feat(settings): add Settings modal with configurable DM retry parameters
Replace hardcoded DM retry logic with user-configurable settings stored
in app_settings DB. Settings modal opens from menu with tab-based UI
(ready for future settings tabs). Defaults: 3 direct + 1 flood retries
(was 8+2), 30s/60s intervals, 60s grace period.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 13:18:03 +01:00
MarekWo
0108ea9149 refactor(menu): reorganize menu into logical sections + larger touch targets
Reorganize menu from 2 sections (Network Commands, Configuration) into 4:
- Messages (top, no header) - daily actions
- Network - advert commands
- Tools - Map, Console
- System - Device Info, System Log, Backup, Settings placeholder

Increase navbar button/select touch targets (min 40px) for mobile usability.
Widen offcanvas menu from 280px to 300px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 07:55:59 +01:00
MarekWo
c48666843a fix(contacts): show ignored/blocked contacts in All Sources filter
Previously ignored and blocked contacts were hidden from the "All Sources"
view, making them only discoverable via dedicated Ignored/Blocked filters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 21:22:52 +01:00
MarekWo
a1f2a1c5ef feat: name database file after device name for multi-device support
Database file is now named {device_name}.db (e.g. MarWoj.db) instead of
the generic mc-webui.db. On first boot, mc-webui.db is automatically
renamed once the device name is detected. On subsequent boots, the
existing device-named DB is found by scanning the config directory.

This enables future multi-device support where each MeshCore device
has its own separate database file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 21:07:58 +01:00
MarekWo
ca0ba37be5 fix(logs): open System Log as fullscreen modal like Console
Changed from target="_blank" link to fullscreen modal with iframe,
matching the pattern used by Console, DM, and Contacts modals.
Iframe loads on open and clears on close to manage WebSocket lifecycle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 20:41:20 +01:00
MarekWo
0110e65b97 feat: add System Log viewer with real-time streaming
In-memory ring buffer (2000 entries) captures all Python log records.
New /logs page streams entries via WebSocket in real-time with:
- Level filter (DEBUG/INFO/WARNING/ERROR)
- Module filter (auto-populated from seen loggers)
- Text search with highlighting
- Auto-scroll with pause/resume
- Dark theme matching Console style

Menu entry added under Configuration section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 20:34:29 +01:00
MarekWo
4f25d244b1 refactor: migrate .webui_settings.json to database + fix NEW_CONTACT edge case
All settings (protected_contacts, cleanup_settings, retention_settings,
manual_add_contacts) moved from .webui_settings.json file to SQLite database.
Startup migration auto-imports existing file and renames it to .json.bak.

Added safeguard in _on_new_contact: if firmware fires NEW_CONTACT for a
contact already on the device, skip pending and log a warning. Also added
diagnostic logging showing previous DB state (source, protected) when
contacts reappear as pending.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 20:14:15 +01:00
MarekWo
e106b5493b fix(contacts): dynamic list height and tighter card spacing
- Replace fixed calc() heights with flexbox layout so the contact list
  fills all remaining viewport space on any screen size
- Make body/main/container chain flex columns so the list can grow
- Reduce vertical spacing between contact name, public key, and
  last advert rows for more compact cards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 12:55:33 +01:00
MarekWo
670715f57f fix(contacts): disable ignore/block buttons for protected contacts
- Existing Contacts: Ignore and Block buttons are now disabled when
  contact is protected, matching the existing Delete button behavior
- updateProtectionUI: toggling protection now also enables/disables
  Ignore, Block, and Delete buttons dynamically
- Chat: Ignore and Block buttons are hidden in message bubbles for
  protected contacts (loads protected pubkeys on init)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 09:15:44 +01:00
MarekWo
3337e3fdff feat(contacts): compact pending filters with batch ignore
- Remove redundant 'Contact Types:' label
- Move type badges above search input
- Place search, Approve, and Ignore buttons in single responsive row
- Add tooltip (i) on Filters header with usage hint
- Add batch Ignore button to ignore all filtered pending contacts
- Remove duplicate filtered count badge from Approve button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 08:30:32 +01:00
MarekWo
39a0e944a7 fix(console): correct trace display order
SNR precedes the hop hash: 12.50 > [5e]12.25 > [d1]-8.25 > [e7]-3.00
(each SNR shows link quality, hash shows the next relay node)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 17:29:53 +01:00
MarekWo
4b4e71f5bd fix(console): correct trace output format
Format: 12.50 > [5e]12.25 > [d1]-8.25 > [e7]-3.00
(SNR first, then each hop shows [hash]SNR)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 17:17:40 +01:00
MarekWo
20924d134d fix(console): trace path support, stats field names, self_telemetry format
- trace: accepts comma-separated hex path (e.g. "trace 5e,d1,e7"),
  waits for TRACE_DATA response with proper timeout from device
- stats: fix field names (uptime_secs, queue_len, battery_mv, etc.),
  show all radio/packet stats with detail breakdown
- self_telemetry: format LPP sensor data nicely instead of raw dict

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 17:03:35 +01:00
MarekWo
019d351ab7 fix(console): req_regions and req_owner output formatting
- req_regions: library returns string, not dict — was crashing
  with "'str' object has no attribute 'items'"
- req_owner: format like meshcore-cli ("X is owned by Y")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 16:17:42 +01:00
MarekWo
3057882f20 fix(console): get/set help formatting, fix get path_hash_mode
- get help / set help: detailed parameter descriptions with
  explanations, matching meshcore-cli style
- get path_hash_mode: library returns int not Event, fixed check
- set help: now reachable (was behind len(args)>=3 guard)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:42:31 +01:00
MarekWo
5a4c259c0b fix(console): ver command now queries firmware info properly
Was using self_info (which has no firmware data). Now uses
send_device_query() like meshcore-cli, showing model, version,
build date and repeat mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:23:56 +01:00
MarekWo
3acdc7a402 feat(console): fix req_clock format, add req_neighbours command
- req_clock: parse timestamp from binary hex data (little-endian)
  and display as human-readable datetime, matching meshcore-cli
- req_neighbours: new command that fetches neighbour list from
  repeater with formatted output (name resolution from device
  contacts and DB cache, time ago, SNR)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 12:25:28 +01:00
MarekWo
3f9b6e54c8 fix(console): repeater req_* return value check
meshcore _sync methods return dict (data) or None (error/timeout),
not Event objects. hasattr(dict, 'payload') is always False, causing
instant "timeout" errors. Changed to check `result is not None`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 12:08:11 +01:00
MarekWo
fe7c67ee9a fix(console): human-readable clock, fix repeater timeouts
- Clock command now shows datetime like meshcore-cli: "Current time: 2026-03-19 11:39:07 (1773916747)"
- Repeater req_* commands: pass timeout=0 to meshcore library so it uses
  device's suggested_timeout instead of hardcoded 30s (matching meshcore-cli behavior)
- Execute timeout raised to 120s to accommodate slow repeater responses

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:58:46 +01:00
MarekWo
4f64cc92e5 feat(console): add device/channel management commands (Etap 3)
Add device management: get/set params, clock/clock sync, time,
reboot, ver, scope, self_telemetry, node_discover.
Add channel management: get_channel, set_channel, add_channel,
remove_channel. Update help text with all command categories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 08:10:46 +01:00
MarekWo
d80f9a7b3a feat(console): add contact management commands (Etap 2)
Add 14 console commands for contact management: contact_info,
path, disc_path, reset_path, change_path, advert_path,
share_contact, export_contact, import_contact, remove_contact,
change_flags, pending_contacts, add_pending, flush_pending.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 08:09:03 +01:00
MarekWo
d6b92e2754 feat(console): add repeater management commands (Etap 1)
Add 9 new console commands for repeater management:
login, logout, cmd, req_status, req_regions, req_owner,
req_acl, req_clock, req_mma. Add resolve_contact helper
and _parse_time_arg utility. Update help text with categories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 08:07:22 +01:00
MarekWo
f66e95ffa0 fix: contact delete by pubkey, cache contacts as pending, cache delete button
1. Delete button now sends public_key instead of name to avoid matching
   wrong contacts when multiple share similar names.
2. _on_advertisement adds cache-only contacts to mc.pending_contacts when
   manual approval is enabled, so they appear in the pending list after
   advertising (even if meshcore fires ADVERTISEMENT instead of NEW_CONTACT).
3. Added Delete button for cache-only contacts with dedicated
   /api/contacts/cached/delete endpoint and hard_delete_contact DB method.
4. approve_contact/reject_contact now handle DB-only pending contacts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 08:01:56 +01:00
MarekWo
eb19f3cf76 feat(dm): add clear search button (x) next to contact info
Shows an X button when a conversation is selected, allowing quick
clearing of the search field to find another contact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 19:35:31 +01:00
MarekWo
e1d3534624 fix(dm): resolve contact names from device, not backend pubkeys
- Add resolveConversationName() that prioritizes device contacts over
  backend display_name (which falls back to pubkey when DB JOIN fails)
- Add isPubkey() guard to prevent overwriting good names with hex strings
- Add arrow key navigation (Up/Down) in searchable contact dropdown
- Auto-focus message input after selecting contact from dropdown
- Skip filtering when search input contains a pubkey (show all contacts)
- Keep search input and placeholder in sync with best known name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 19:13:03 +01:00
MarekWo
50fdee05ed fix(dm): prevent dropdown close on mouse hover, ensure name after select
- Prevent mousedown on dropdown from stealing focus (which closed the
  dropdown before click could register on desktop)
- After selecting from dropdown, override search input with the known
  name to guarantee correct display even if prefix match fails

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 08:43:48 +01:00
MarekWo
1ecf2f60f0 fix(dm): resolve conversation name via prefix match for saved IDs
When restoring a conversation from localStorage, the saved ID may have
a different pubkey prefix length than the API returns (e.g. pk_e4ce0a07
vs pk_e4ce0a075359459f...). Now selectConversation() does prefix
matching against dmConversations and upgrades the stored ID, so the
display name is resolved correctly instead of showing raw pubkey prefix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 08:35:40 +01:00
MarekWo
8ce5fa85ba feat(dm): searchable contact selector, contact info modal, device-only contacts
Redesign DM chat contact selector:
- Replace <select> dropdown with searchable text input + filtered dropdown
- Show only device contacts (from /api/contacts/detailed), not all cached
- Sort contacts alphabetically, conversations by recency
- Type badge (CLI/REP/ROOM/SENS) shown in dropdown items
- Keyboard support: Enter selects first match, Escape closes

Add Contact Info modal (replaces Retry toggle in header):
- Shows contact name, type, public key, last advert, path/route, GPS
- Auto Retry toggle moved into modal footer
- Designed for future extensibility (manual path setting etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 08:27:01 +01:00
MarekWo
21b1c0510f fix(dm): emit original expected_ack on retry ACK for frontend matching
When a DM is retried, the retry send generates a NEW ack code. The
backend correctly maps retry ack → dm_id via _pending_acks, but
the WebSocket emit was sending the retry ack code. The frontend DOM
still has data-ack="<original_ack>" from the first send, so it could
never match retry ACKs → delivery checkmark never appeared.

Now both _on_ack() and _confirm_delivery() look up the original
expected_ack from the database before emitting to the frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:54:50 +01:00
MarekWo
5ecb48c772 fix(api): fix NameError on out_path variable rename
Variable was renamed to out_path_raw but one reference was missed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:30:32 +01:00
MarekWo
3622619ba4 fix(contacts): decode path correctly using MeshCore V1 encoding
Path buffer from firmware contains trailing garbage bytes beyond the
actual hop data. out_path_len encodes both hop count (lower 6 bits)
and hash size (upper 2 bits). Now we:
- Truncate out_path to meaningful bytes (hop_count * hash_size)
- Format as readable E7→DE→54→54→D8 instead of raw hex string
- Show hop count derived from actual path arrows

Example: out_path_len=5 with out_path="e7de5454d81c49dfb86f8a"
now correctly displays as "E7→DE→54→54→D8 (5 hops)" instead of
showing the full 11-byte buffer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:26:06 +01:00
MarekWo
5f72f40742 feat(contacts): show path/route info in UI and split console commands
- Console `contacts` now shows device-only contacts with path info
  (matching meshcore-cli format: name, type, pubkey, path)
- New `contacts_all` command shows all contacts (device + cached from DB)
- Contact cards in UI now always show routing mode for device contacts
  (Flood, Direct 0 hop, or hex path with hop count)
- Fix path_or_mode computation: prioritize out_path over out_path_len
  to handle firmware edge case where out_path exists but out_path_len=-1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:01:15 +01:00
MarekWo
fa8190923f fix(dm): adjust retry strategy based on DIRECT vs FLOOD routing
- DIRECT (known path): 10 attempts (8 DIRECT + 2 FLOOD), 30s wait between
- FLOOD (no path): 3 attempts only, 60s wait between
- Prevents flooding the mesh with rapid retries when no path is known
- Longer DIRECT wait gives ACKs more time to return through multi-hop paths
- Log retry mode at task start for easier debugging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:21:02 +01:00
MarekWo
e473cbf495 fix(dm): cancel retry on early ACK/PATH, add 60s grace period for late ACKs
- Cancel retry task immediately when _on_ack or PATH handler confirms delivery
- Keep pending_acks for 60s after retry exhaustion so late ACKs are matched
- Prevents orphaned ACKs (no dm_id) when ACK arrives shortly after exhaustion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:10:10 +01:00
MarekWo
3a26da18fd fix(websocket): update message metadata in-place without full chat reload
Instead of reloading the entire message list when echo data arrives,
now updates only the affected message elements in the DOM:

- Add data-msg-id attribute to message wrappers for targeted lookup
- Add GET /api/messages/<id>/meta endpoint returning metadata for a
  single message (computes pkt_payload, looks up echoes, analyzer URL)
- Replace loadMessages() echo handler with refreshMessagesMeta() that
  finds messages missing metadata and updates them individually
- Fix path_len=0 treated as falsy (use ?? instead of ||)

Flow: message appears instantly via WebSocket (with SNR + hops), then
~2s later echo data triggers targeted meta fetch → route info and
analyzer button appear smoothly without any chat window reload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:49:56 +01:00
MarekWo
0e15df430f fix(websocket): listen for echo events to update message metadata in real-time
The backend already emits 'echo' SocketIO events when RX_LOG_DATA arrives
with route/path data, but the frontend wasn't listening. Now the frontend
handles echo events with a debounced loadMessages() refresh (2s delay) to
pick up computed pkt_payload, analyzer_url, hops, and route info.

This fixes messages appearing without metadata until manual page refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:38:46 +01:00
MarekWo
e817181261 fix(websocket): include SNR, hops, route and analyzer URL in channel message events
The SocketIO new_message emit for channel messages was missing snr,
path_len, pkt_payload and analyzer_url fields, causing messages received
via WebSocket to render without metadata until a full page refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:12:41 +01:00