Skip to content

OMNI-2, multiple issues - #73

Draft
MrSurly wants to merge 12 commits into
tmacinc:devfrom
MrSurly:omni-2
Draft

OMNI-2, multiple issues#73
MrSurly wants to merge 12 commits into
tmacinc:devfrom
MrSurly:omni-2

Conversation

@MrSurly

@MrSurly MrSurly commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Shows per-message routing detail: hop count, multi-path, and named repeaters when correlated from live radio packets.
Closes #65

Switches message ordering from the untrusted sender-embedded clock to strict local receive order, with a separate local receivedAt display time.
Closes #71

Adds a Report Bug action to the About dialog, pre-seeded with app version and platform.
Closes #68

Remembers desktop window size and position across launches.
Closes #67

Makes URLs in chat messages tappable, opening them in the external browser.
Closes #52

MrSurly added 8 commits July 18, 2026 16:00
Extends the existing #hashtag/@mention token parser in
ChatMessageText to detect http(s):// and www. URLs, trimming
trailing sentence punctuation from the tappable span. Tapping
opens the link via url_launcher in the external browser.
Persists path length and SNR from the existing V3 message-receive
responses (previously parsed then discarded) onto each Messages row.
Adds a (d)/(N) badge next to the sender name and a long-press
"Message path" sheet showing a simple sender -> hop count -> you
timeline.

Named per-hop routing and multi-path duplicate detection (richer
data from the raw PUSH_LOG_RX_DATA frame) are deferred -- correlating
that frame to a specific decoded message isn't safe with the current
sync loop, which can drain multiple queued messages per push.
Adds a message_paths table (one row per distinct radio path a channel
message was observed on) populated by correlating raw PUSH_LOG_RX_DATA
frames -- previously received but entirely discarded -- against
already-decoded channel messages.

Correlation works by re-encrypting a message's known plaintext (using
its channel's PSK) and finding an exact ciphertext match against
buffered raw frames, brute-forcing the 4 possible `attempt` retry
values since firmware's decoded response doesn't expose that field.
An exact match is unambiguous; no heuristics. Frames sharing the
matched packet's hash (payload type + ciphertext, independent of
path) are its multi-path siblings -- the same logical packet heard
via another route (e.g. direct and relayed at once).

Verified end-to-end against live traffic: correctly captured both a
direct reception and a relayed one (via a specific repeater hop) for
the same message, with real per-hop SNR/RSSI. A DB-level unique
constraint on (messageId, pathBytes) makes duplicate-delivery
correlation (the same message arriving via push then sync, an
existing pattern elsewhere in this file) safe without an
application-side race.

Also adds getContactsByPublicKeyPrefix (all-matches variant, for
later ambiguity display) alongside the existing first-match lookup.

UI display of this data is a follow-up; the badge/sheet from the
prior commit still uses the single-path Messages.hopCount/snr
summary and is unaffected if correlation never matches.
Wires the correlated MessagePaths data (from the previous commit)
into the chat UI:

- Message path sheet shows every distinct path a message was
  received on -- each with real SNR/RSSI and named hop(s) resolved
  against known contacts, falling back to the raw hex identifier
  when a hop isn't a known contact and to the message-level
  hopCount/snr summary when no raw-frame correlation exists at all
  (DMs, or a channel message that never matched).
- Ambiguous hops (a short hash prefix matching more than one known
  contact) show all candidates and are visually flagged.
- Chat bubbles now show a MessageHopBadge: the reliable single-value
  (d)/(N) summary immediately, swapping to a real multi-path summary
  like (d/1) once correlation data loads for that message -- this
  was the actual point of the whole effort, not just the detail
  sheet.
- getContactsByPublicKeyPrefix (all-matches) and
  MessageRepository.getMessagePaths added as plumbing.
Adds window_manager and a small WindowStateService, desktop-only
(not Android/iOS). Restores saved bounds on launch; persists on
resize/move via a debounced SharedPreferences write, reusing the
same prefs instance the rest of startup already fetches.

Uses the continuous onWindowResize/onWindowMove events rather than
the "finished" variants, since those are macOS/Windows only in
window_manager and this needs to work on Linux.
Pre-fills a new GitHub issue with the app version and platform so
bug reports don't start from a blank form. Uses url_launcher (also
adds the Android 11+ manifest query it needs).
The sheet's content wasn't scrollable, so a path with several hops
(e.g. 8) overflowed the bottom of the screen. Caps the sheet at 80%
of screen height and wraps content in a scrollable view with a
visible scrollbar.
Ordering now uses SQLite's implicit rowid instead of the untrusted
sender-embedded timestamp column. Adds receivedAt (local device
clock) as the displayed message time; timestamp is kept as the raw
sender-reported value. Unread-divider lookups now key off message id
instead of the removed sequence column.
…omni-2

# Conflicts:
#	pubspec.lock
#	pubspec.yaml
@MrSurly MrSurly changed the title Message routing info and strict local receive ordering OMNI-2, multiple issues Jul 19, 2026
…into omni-2

# Conflicts:
#	macos/Flutter/GeneratedPluginRegistrant.swift
#	pubspec.lock
#	pubspec.yaml
PR tmacinc#68 and tmacinc#64 each added this key independently; git's merge kept
both non-conflicting insertions, which silently dropped the key from
codegen entirely. Removed the duplicate and regenerated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant