CMD_SEND_RAW_DATA (0x19) was passed the encoded MeshCore route descriptor
(e.g. 0x41 for a 1-hop 2-byte-hash route), but the v1.15 companion firmware
raw-data handler treats the path byte as a legacy literal hop count, not an
encoded descriptor. It misread 0x41 as "65 path bytes" and rejected the
command (ERROR: Unsupported command), so media fetch always failed while
normal messaging worked.
- Add ContactRouteCodec.toLegacyRawPath() converting encoded descriptor +
path into legacy format (literal hop count + first byte of each hop hash).
- Apply it in ConnectionProvider.sendRawVoicePacket, the single chokepoint
all raw media (voice/image fragments, swarm, route probes) flows through.
- Pace served fragments 350ms apart to avoid firmware "ERROR: Table full"
when bursting many raw packets.
- Tests for the descriptor conversion.
Fixes#43
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- i18n: translate connection screen + chat tab keys into 13 locales;
add "Send my contact" (advert) strings in all locales
- feat: move self-advert from home header into composer "+" action menu
(new lib/utils/advert_helper.dart, always shows Flood/Direct sheet)
- fix: hide-repeaters map toggle was bypassed in simple mode
- fix: simple mode map now shows only favourite chat contacts
- fix: wrap ListTiles in Material (contact_tile secondary actions,
inferred contact group card) to satisfy Flutter ink assertions
- device-authoritative contact/channel sync and UX review fixes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>