Skip to content

v2.74.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 19:25
· 98 commits to main since this release

2.74.0 (2026-09-30)

Features

  • a silent radio's chosen board can take Meshtastic instead of MeshCore (1605692)
  • app: keep the lifetime stats (693bad4)
  • backup: back up a MeshCore radio, contacts and all (2c223d8)
  • backup: compare two backups of a radio, and list and remove them on the card (433e331)
  • backup: keep a radio's settings on the card, starting with Meshtastic (ac48b3a)
  • backup: plan a Meshtastic restore and send it as one edit transaction (6a5aa73)
  • backups: carry a radio's identity key in a backup asked for with it (a4184a5)
  • backups: restore a MeshCore radio from a backup and check it took (500960b)
  • backups: restore a MeshCore radio's contacts from a backup (e6fd5ea)
  • backups: restore a Meshtastic radio from a backup and check it took (e340447)
  • backup: take backups on first connect, before writes and firmware, and on request (0c38aa7)
  • install MeshCore onto a radio that answers nothing on USB (3558be1)
  • lifetime: count what the client has seen across every run and radio (fe07e96)
  • map: draw every installed pack as one map (d8f3588)
  • map: draw past a pack's deepest level by enlarging its tiles (f6b8338)
  • maps: download map packs from the catalog, in resumable pieces (7e9a9a5)
  • maps: download, update and delete map packs from Settings > Maps (99624a7)
  • maps: hold a catalog of every country (c53bd5e)
  • meshcore: plan a restore of a radio's settings from a backup (1d36cfe)
  • meshcore: send a repeater commands and ask it for its neighbours (0326066)
  • messages: name a sender in the tint their avatar wears (4fe66a3)
  • move a MeshCore radio on its cable to the Bluetooth build (0666796)
  • nodes: badge the Nodes tab and announce newly discovered nodes (e3fcc15)
  • nodes: stand a node's facts in two columns where there is room (6fc3154)
  • pair a radio moved to Bluetooth with the PIN it kept (1ee9829)
  • profiles: make a profile from a backup, apply it, and carry it as a .cfg (acad52b)
  • profiles: make, list, compare, apply and share profiles on screen (2d2dc79)
  • send a crash report to Sentry when the user asks (eae7e59)
  • session: announce messages and nodes as they are recorded (356d855)
  • set a MeshCore radio's Bluetooth PIN from Settings (709cbac)
  • split: preview the row under the list's cursor beside it (0e3a213), closes mcereal/inkcell#84
  • stats: count delivered and undelivered messages (78813eb)
  • stats: count MQTT and private messages, and record the farthest node heard and weakest signal (1a3caf3)
  • stats: name who set each record, and when (95e52ed)
  • status: show how many nodes this client has ever heard (cb577e5)
  • ui: a MeshCore repeater's thread is its console, and its sheet asks for neighbours (75a1c0c)
  • ui: a side rail the reader folds to icons or unfolds into labelled tabs (fb17e67)
  • ui: a Stats page for the lifetime counts (f33d4b1)
  • ui: a window's cursor, hover, sidebar clicks and a message field (ee44047)
  • ui: carry the whole node roster in the Nodes list (a5bb507)
  • ui: centre a split frame's empty detail, and ring one place while typing (37d78b9)
  • ui: dock the keyboard under the thread on a wide frame (ac7cd54)
  • ui: give the map and the waypoints a tab of their own (948ec81)
  • ui: head a direct conversation with the peer's long name (01b9419)
  • ui: lay the tapback sheet out as a row of faces over a delete button (bfc1ade)
  • ui: list, open, compare and delete the radios' backups on the card (92851bd)
  • ui: open a node's detail on its signal and battery (3cdad96)
  • ui: put the Nodes list's search, filter and sort on one chip bar (ed3bc2c)
  • ui: say a radio-reported switch as a state, not a control (8603df6)
  • ui: stop heading our own channel bubbles with "You" (2168e19)
  • ui: take inkcell's vector emoji (8dab891)
  • ui: use a wide window's room on the Status and Map tabs (1076ce3)

Bug Fixes

  • a PIN typed over a pending Random makes MeshCore pairing Fixed (ac22b08)
  • actions: name A on a Radio page only when the row is a verb (74833cb)
  • admin: stop an edit transaction whose begin fails, and count a refused commit (d26d82b)
  • an erased MeshCore PIN takes its Fixed edit with it (40129d1)
  • app: count the attached radio again after a stats reset (e024fc1)
  • app: size the BLE handoff addresses by INKWELL_BLE_ADDRESS_MAX (da3a791)
  • backup: compare what a MeshCore radio advertises itself as (cf490e6)
  • backup: keep every contact a MeshCore radio can report (741640c)
  • backups: a restart is not a refused transaction (60574c1)
  • backups: fit the restore sheet and its firmware note in every language (a48e16e)
  • backups: keep a late key off the queue, never wait for ever, wipe keyed backups on free (88ba369)
  • backups: list the first-connect backup when the list is full (7a1a7bd)
  • backups: make restores finish, and keep what a restore needs (1c1ce9a)
  • backups: name a choice in a comparison as its settings row does (cf4d3ee)
  • backups: name every field the Settings tab has in a comparison (73861e9)
  • backups: name Radio UI's theme, GPS format and clock face in a comparison (824a32e)
  • backups: never call an identity restore good without a public key to judge it by (d8fec25)
  • backups: put a key only on the radio its sheet was about, and resync after an export timeout (0ac0671)
  • backups: refuse a restore without its safety copy, and keep the backup it needs (fe04be5)
  • backups: resync after an unanswered key import, and wipe the admin queue as it empties (22c8a27)
  • backups: stop only a restore's contacts, and count a refused send once (7e5ffa6)
  • backups: tell two backups taken in the same minute apart (cd6a1ef)
  • backups: wait for a restarted radio even when its link dropped first (4779d07)
  • backups: wipe the file codec's scratch buffers after a key goes through them (7e4a28c)
  • clear the gcc warnings a release and a sanitizer build print (a5844ac)
  • clear the remaining gcc and clang build warnings (9370873)
  • compose: head the compose sheet and keyboard with the thread's name (a8df7d0)
  • devtools: map_pack.py info takes coverage from the deepest zoom too (061964e)
  • do not step the report parser one past the end of its buffer (cbabe0c)
  • end a MeshCore link whose handshake loses a step (5c581fe)
  • find a long-named radio by its truncated advert, and drop impostor bonds (45088c7)
  • follow a rename into the Bluetooth handoff's name (a250c5c)
  • hold a typed MeshCore PIN and Pairing as one edit (f380897)
  • hold the Bluetooth handoff while its write can still be resumed (b50979b)
  • hold the next handoff candidate until an impostor's bond is gone (56216e9)
  • keep retrying removal of an impostor's handoff bond (30fde1e)
  • keep the Bluetooth handoff until the radio is reached (43d97f1)
  • keep the MeshCore PIN note inside the help panel's cap (78bcf34)
  • know the moved radio by its key, and pair it afresh (5b500f8)
  • let the Bluetooth handoff outrank a cable and the network (f5119ce)
  • lifetime: measure a hearing after its payload, retry failed appends, count CLI radios (d895552)
  • lifetime: remember across a restart that the node set is a floor (ff11fb7)
  • lifetime: say whether a record was measured, not just its value (dc0fb35)
  • list a silent radio's boards beside a cached radio (1028e54)
  • macos: resolve without forking, and upload a dSYM (b7b7c61)
  • main: keep the app off main()'s stack (dbf4158)
  • map: open on our own radio, and draw a position's footprint see-through (dce7983)
  • map: open the installed map packs again (982e33b)
  • map: order a maps directory ignoring case, over every name in it (b480f65)
  • maps: count the legacy pack, skip styles the map does not draw, keep an aimed map aimed (eeae42d)
  • maps: download only what the map will draw, into the directory it reads (4beb262)
  • maps: show the catalog a group at a time, count every pack, report a refused delete (3242c53)
  • map: take a pack's coverage from its deepest level (6ddcb43)
  • meshcore: a late reply answers the command it was for, not the next one (e837f91)
  • meshcore: a repeater's reply settles the command sent first, not the lowest id (4cb7015)
  • meshcore: a reply settles only a command the radio has sent (5a8ea51)
  • meshcore: finish the sync when a slow first boot answers twice (75845ed)
  • meshcore: refuse a command rather than evict one still in line (f1df30d)
  • meshcore: refuse a restore that cannot name its radio, and count names it cannot send (ec233cc)
  • meshcore: restart before anything queued behind a key import goes out (63a6d45)
  • meshcore: unanswered commands free their slots, and each timeout is said (d0872f6)
  • name the confirm sheet's choose keys from the way its answers were drawn (60422d0)
  • nodes: a completed sync is a baseline, so a first neighbour is news (2b19208)
  • nodes: a discovery seen on the list mid-sync is not announced after it (51f226c)
  • nodes: a MeshCore contact import is not a discovery, and one list predicate (db509d4)
  • nodes: a node opened from the map is not a visit to the list (230dfd4)
  • nodes: a replayed node is news only when heard since the roster's newest (719cc25)
  • nodes: an open node covers the list, and does not end the visit (806a836)
  • nodes: draw a node's verbs measured over a detail in two columns (ff3d0dc)
  • nodes: hold a discovery notice for a completed sync, and queue it (292f043)
  • nodes: keep a first sync first across a retry, and know ourselves from the cache (06065c2)
  • offer the Bluetooth move only once the radio has named itself (a084767)
  • parse a crash report from terminated line copies (9973a81)
  • profiles: apply a profile to the radio it was compared with, not the one on the link (f7a5dc5)
  • profiles: carry an empty channel slot with empty settings, as the firmware does (3dc9a07)
  • profiles: claim an export's file name as it is created, and build on Windows (bb8a645)
  • profiles: end an apply's screen when another radio connects before it is judged (163c5bb)
  • profiles: export beside an existing .cfg, and keep the newest profiles in a full list (8d3f1bb)
  • profiles: leave the Position section out of a .cfg export (8d1cae2)
  • profiles: read the folder again when Profiles opens, and keep a profile being applied (ee2474b)
  • profiles: refuse an empty .cfg, and judge an apply beside another open comparison (5964594)
  • reach a silent USB radio on a Brick that remembers a Bluetooth node (86c53f6), closes #396
  • retry a failed Bluetooth check, and pass over every impostor (ac17802)
  • say a failed firmware list failed once in the log (6cf52cd)
  • settings: say "from preset" only while a preset is on (def4f22)
  • settings: show a preset's LoRa trio as the preset's, not 4/0 (3a7f662)
  • show a typed MeshCore PIN as Fixed before it is saved (087f5a6)
  • silence the two warnings the device build prints (44c23a2)
  • split: clamp the preview's nav so a thread previews where it opens (e849151)
  • stats: count direct deliveries by where each message is now (606447f)
  • stats: drop an SNR no radio could report before it becomes a record (bb5db2a)
  • stats: keep record holders through an older build (9ce2210)
  • stats: move only the deliveries this run counted (bc9b0b3)
  • stats: reuse a delivery slot only once its message leaves the log (5c58d28)
  • the confirm sheet chooses with Left and Right, and says so (7c4e20b)
  • tie a tried bond to the address it was tried at (24b0515)
  • ui-drive: show the cursor after a key the control socket pressed (e62562b)
  • ui: a click on a heading beside a detail leaves nothing (d8e96fd)
  • ui: a click on the sidebar's selected row is no change (089d4a4)
  • ui: a repeater's failed command is not offered to resend (13436a6)
  • ui: address review on the inactive rows, ham power and map counts (afd6c16)
  • ui: clearer hint labels and radio terminology (825a6b8)
  • ui: count only the reader's own narrowing in the Nodes heading (2f7dc58)
  • ui: decide the keyboard's dock from the current geometry (58648ed)
  • ui: draw a traced route's hops behind a real arrow (5a1b25b)
  • ui: find the sidebar's open row by identity; no sidebar click under a layer (703ca39)
  • ui: handle wheel scrolling across list routes (1aa5467)
  • ui: keep message text inside its bubble (d62c4e4)
  • ui: keep node detail chips inside their rows, space bubbles apart (b2b5436)
  • ui: keep the reaction tray and delete inside a narrow sheet (4276556)
  • ui: line help's paragraphs up under its heading on a window (7bbbe27)
  • ui: name L2 from the cursor, and say quit on overlays too (81e7af9)
  • ui: open a map marker's node without the last node's chart or verbs (3a22ae5)
  • ui: polish the Radio tab, Settings, the map and help (00109e9)
  • ui: record the new click cases' success; the sidebar's selection is inkcell's (5ad4b49), closes mcereal/inkcell#75
  • ui: retain wheel key fallback without row targets (913d92f)
  • ui: ring the bubble a reply answers, not the cursor's (14e6a20)
  • ui: scroll visible lists with the Windows mouse wheel (2a16214)
  • ui: stop a sidebar click at the discard question; a blank click puts the field down (35ee895), closes mcereal/inkcell#75
  • ui: turn the measure back on before the dialogs, not after the action bar (68529c7)
  • wait for the moved radio, and drop its bond only after it fails (b342e89)
  • waypoints: make the new-place row the bright line on an empty list (569741e)

Documentation

  • add status badges to the README (4c6a684)
  • describe the Map tab and the Nodes chip bar (381653b)
  • say a fixed MeshCore PIN is used by Move to Bluetooth (660e5a2)

Code Refactoring

  • ui: ask the compose sheet's question of a snapshot's own records (7393832)