Commit Graph
1188 Commits
Author SHA1 Message Date
Claude d2ee8cea5f fix(ui): Mentions breadcrumb on the left like every other screen
The Mentions screen drew its own header with the back chevron at the top
right, the only screen whose back breadcrumb was on the right. Use the
shared app-page chrome instead (appPageBegin/appPageEnd, as Send advert,
Spectrum and the settings pages do): "‹ @ Mentions" on the left of the
status bar, tap to go back. The list starts below the tall bar on square
panels. Keeps the existing translated "@  Mentions" key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBQtHzNKA9Q55ogrULN6JJ
2026-09-24 15:28:04 -04:00
Claude fc631be52c fix(tdisplay-p4): GPS baud, nav bar, map chrome, presets, export
- GPS: the P4 listened at 9600 (the L76K power-on default), but LilyGo's
  factory firmware leaves the receiver at 115200, so the UART opened and
  never parsed a sentence. Set GPS_BAUD_RATE=115200 for the P4. A GPS baud
  saved in Settings still overrides it.
- Nav bar: the active-tab bar assumed a full-width tab row. The P4's round
  corners inset the row by SB_INSET_X on each side, leaving the bar ~13 px
  off under the outer tabs. Measure the real button row instead; move the
  unread and update badges in by the same inset.
- Map: with no tiles rendered the canvas shows the COLOR_FIELD
  placeholder, but the chrome followed only the night setting (except on
  the Wio Tracker L2). Pick the chrome colour from the placeholder's
  brightness on every board, and refresh it when tiles appear or vanish.
- Radio & mesh: picking a community preset only filled the fields and a
  dropdown never blurs a field, so nothing was saved; leaving the screen
  lost it. Apply on pick. Also remember the picked preset by label, since
  several presets share identical parameters and the first match
  (e.g. EU/UK instead of Switzerland) was shown on return.
- Export: add a wadamesh_settings block with airtime factor, region
  scope, auto-add rules, advert/telemetry policy, multi-ACKs, GPS and
  RX boosted gain, and restore it on import. The stock-app fields keep
  their exact shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 15:28:04 -04:00
Michael A. Cojocari 2fde038f08 fix(m9): streamline mark-all-read action
Closes #569\n\nCo-Authored-By: GitHub Copilot <noreply@github.com>
2026-09-24 15:16:09 -04:00
Michael A. Cojocari a3090aebbe fix(tdeck-pro): split v1.0 and v1.1 targets 2026-09-23 16:43:29 -04:00
Michael A. Cojocari 98dd4dadea fix(m9): preserve locked drawer through shortcuts
Keep the app-drawer Home root open beneath Messages, Map, Mentions, and Advert function-key navigation while still dismissing overlays and respecting blocker dialogs.

Fixes #564
2026-09-23 10:34:28 -04:00
Michael A. Cojocari a8067c921b fix(tdeck-pro): separate compact chat messages
Measure the same vertical padding that compact rows render and increase the blank gap between separate messages without changing wrapped-line spacing.

Fixes #563
2026-09-23 10:23:59 -04:00
Michael A. Cojocari 31a6a9798e fix(tdeck-pro): make console readable on e-paper
Use white paper and black ink from the first boot frame, commit sprite-backed input updates, and keep the e-paper cursor solid.

Fixes #562
2026-09-23 10:23:45 -04:00
Kaj SchittecatandClaude Opus 5 c9ecaf383f reports: say how long they ran it, not just a span
The first real report read "works, about a day, 57 min ago" and the two halves
looked like they disagreed. They answer different questions: "about a day" is
how long the tester ran the build, "57 min ago" is when they sent the report.
Now it says "ran it for about a day, reported 57 min ago".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 15:58:23 +02:00
Kaj SchittecatandClaude Opus 5 df99548a10 touch: text sizes on the M9, landscape on the T-Display P4
The M9 gets the V4-R8's text-size presets verbatim, because it is the same
240x320 panel and two tables for one screen size is two things to keep in step.
Fonts grow, geometry does not: rows, cards and controls keep their dimensions
and stay reachable, which is why the labels say "Large text" rather than a
percentage.

⚠️ The migration matters more than the feature. ui_scale has been in the saved
blob since v8 and every M9 carries the large-screen default of 1 that this board
never applied, so exposing the selector without resetting it once would bring
every M9 back from the update rendering Large text nobody chose. Prefs go to v65
with that one-time reset, which is the same correction v63 had to make for the
V4-R8 after it happened to them.

The P4 can run landscape. Its MIPI-DSI panel has no MADCTL to rotate, so LVGL
rotates each flushed area into panel coordinates, exactly as the Tanmatsu
already does on the same silicon; the difference is that the P4 reads the saved
preference instead of pinning one rotation. Portrait stays the default and the
existing Orientation button does the rest.

The rotated branch of the P4 touch mapping had never run: it was carried "for
parity" while the panel was portrait-only, and it clamped rotated coordinates
against the portrait bounds, so every landscape touch past x=284 would have
pinned to the screen edge. It clamps against the swapped space now.

Landscape is UNTESTED on hardware: Kaj did not have his P4 with him, and it
ships that way deliberately, with the release notes saying so and asking P4
owners to report smoothness and touch accuracy near the edges.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
beta_85
2026-09-23 13:58:31 +02:00
Kaj SchittecatandClaude Opus 5 cf0c8da0ff touch: the report form swallowed taps meant for it, and its name was odd
Two things Kaj hit on a T-Deck within a minute of the first flash.

Taps that missed a checkbox went through the card to whatever sat behind the
popup. The card had LV_OBJ_FLAG_CLICKABLE cleared, copied from the version
picker, and a non-clickable object is invisible to hit-testing, so the tap
carried on to the page underneath. The card is clickable again, and tap-outside
now compares the point against the card's own area rather than assuming nothing
inside it can reach the backdrop. Events do not bubble in LVGL 8 unless asked,
so the clear was never needed for its stated purpose.

The card is also explicitly scrollable and capped to the panel height. Eleven
rows do not fit 240 px, and a card taller than its backdrop puts its own
controls outside the area that catches taps.

"Report this build" reads like reporting a fault with it, which is the opposite
of what the button is for. It is "Send a test report" now, "Send another test
report" once you have, and the form is titled "Test report: <tag>". Renamed in
the docs, the site, the issue template and the tracking-issue text too, so the
instruction people are given matches the button they are looking for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 13:39:58 +02:00
Kaj SchittecatandClaude Opus 5 96a7e4a9b4 release: draft notes for beta_85
Not cut. The slice is staged and every target builds; this is the changelog for
whenever it goes out. It leads with reporting from the device, then the T-Deck
Max OTA fix and the instruction that a Max on beta_84 must be flashed over USB
rather than from the device, because publishing a newer build is what exposes
that bug.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 13:22:01 +02:00
Kaj SchittecatandClaude Opus 5 eafcd23f40 touch: review fixes on top of #550 and #549
Four things the merges needed.

The POI menu from #549 was not in the popup registry. Every modal in this file
registers its closer there, and one that does not cannot be dismissed by Back or
by the screen-lock teardown: it stays on screen while the page behind it
changes. That is the same failure #553 describes for Known Regions, which #550
fixes in the same slice.

Czech had no POI string. It was added after #549 was opened, so thirteen
language files got the row and the fourteenth did not.

Auto keyboard backlight never switched off when the screen timeout is Never.
#550 changed Auto to follow the screen timeout instead of a fixed three-second
window, which is right, except that Never then means lit forever. Auto is the
default mode, so a device left on a desk would burn its keyboard backlight until
the battery gave out, where the old window at least ended. The Never case is
bounded to a minute; mode On is still there for a permanently lit keyboard.

Compact chat rows have vertical padding on the T-Deck Pro and Max (#563).
Compact mode leans on the alternating row tint to show where a message ends and
e-paper has no tint, so messages ran together, worst when one wrapped.

Not fixed here: #562, the Pro terminal drawing black on black. The console
already special-cases e-ink, the Pro's palette is white paper and black ink,
LovyanGFX treats equal fore and back as transparent rather than a filled block,
and consoleBegin gets the display before anything renders. The remaining suspect
is the pre-LVGL boot screen, which fills black on purpose because "our pre-LVGL
screens are always dark" and inks the whole panel on e-paper. That needs the
device to confirm, and guessing at an e-paper fix is how a regression ships.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 13:13:19 +02:00
Kaj Schittecat 5582c37001 Merge PR #549 from TerryTel93: open coordinates from a chat message on the map
Closes #538.
2026-09-23 13:01:23 +02:00
Kaj Schittecat c955c52aa0 Merge PR #550 from oumike: M9 navigation, Advert exit, T-Deck Pro/Max UX, backups and the timeout slider
Closes #548, #537, #553, #555, #556, #559, #560 and addresses #532.
2026-09-23 13:01:18 +02:00
Kaj SchittecatandClaude Opus 5 ee5685a91f reports: every build since stable, and silence that means something
A promote spans every test build published since the last stable, and reports
keep arriving on a build after the next one has been cut, so showing only the
newest beta hid exactly the evidence the decision needs. The page now carries a
chip per build above stable and switches between them.

They never merge. A report vouches for the build it was sent from and for
nothing cut after it; averaging them would let somebody sign off code they
never ran.

The verdict got stricter, because testing it showed it was hollow. "Is anybody
running this board" was answered by the opt-in install count, which most people
will leave off, so a single green board could declare a whole release ready.
A board now also counts as out there once anybody has ever reported on it, on
any build: reports are not opt-in, and somebody who reported on beta_85 still
owns that board when beta_86 lands. So silence on a board we have heard from
before blocks the promote, and silence on a board nobody has ever reported on
does not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 12:02:59 +02:00
Kaj SchittecatandClaude Opus 5 b2030528a0 site: a test-matrix card on the front page, and no GitHub token by choice
The matrix was only reachable from a corner button and a line buried in the
channel explainer. It now has a card in "Docs, tools and help", next to the
others, which is where people actually look.

The tracking issue is dropped: the matrix lives on the site and no write
credential for it exists anywhere. The publishing code stays in place and
dormant, so it is one line in /etc/wadamesh-reports.env if that changes, and
the service and deploy script now say publishes:false is the intended state
rather than a missing piece.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:57:18 +02:00
Kaj SchittecatandClaude Opus 5 baf2e6c0cc reports: one CORS header, not two
nginx and the service were both adding Access-Control-Allow-Origin to the
matrix response. Two of them is not a stronger permission: the CORS check
fails on a duplicate and the browser rejects the response, so
wadamesh.com/beta could not read firmware.wadamesh.com at all. Only the
service sets it now, verified from the live origin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:31:46 +02:00
Kaj SchittecatandClaude Opus 5 a80a48988e touch: report a build from the device, and a QR that files a bug
Settings, About gains "Report this build": works or a problem, five tick
boxes for what you actually exercised, how long you have run it, an optional
line. It posts to the report service and lands on wadamesh.com/beta, which is
what the next promote is decided on. Ticking matters: "it works" from somebody
who watched it boot and "it works" from somebody who messaged on it all week
are not the same claim, and a board only goes green on two of the second kind.

"Report a bug" draws a QR for a prefilled GitHub issue form. The issue is filed
from the reporter's phone under their own account, so no write token has to
exist in a public firmware image and the reporter gets the replies.

"Count this device" is off by default. It lets the update check say which board
and version it is running, so a board with no reports can be told apart from a
board nobody owns. Those need opposite responses and nothing could tell them
apart before.

Mechanics: the POST rides the existing core-0 tile/update worker and its
WiFiClient/HTTPClient, like the version check, because a second pair on that
~8 KB stack overflows it. The device id is a salted SHA-256 of the public key
truncated to 64 bits, so a second report replaces the first without saying who
sent it. Sending is two taps and the second lists every field that leaves.
Prefs v64 appends report_ping + report_done_n at the tail, which the schema's
trailing static_assert now checks.

Also here: scripts/build/matrix-check.sh prints what testers reported for a tag,
and release.sh runs it before a --promote. It never blocks; a board nobody owns
can never go green. With no reports at all it now says so rather than reporting
a clean bill of health, which is the habit this is meant to replace.

Built on all eleven S3 envs and the T-Display P4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:29:20 +02:00
Kaj Schittecat 875162e5df Revert "chore: refresh Mesh America catalog for beta_84"
This reverts commit 577410759d.
2026-09-23 11:27:06 +02:00
Kaj Schittecat 577410759d chore: refresh Mesh America catalog for beta_84 2026-09-23 11:26:42 +02:00
Kaj SchittecatandClaude Opus 5 3729c821b3 reports: a test matrix a beta can be promoted on
A beta goes stable today because it has been out a while and nobody shouted.
With 13 board images, most of them in hands we never hear from, "nobody
shouted" mostly means nobody with that board was listening. This makes the
evidence explicit: testers report per board per tag from the device, and the
promote decision reads off a grid.

The device cannot talk to GitHub itself. TLS does not fit (mbedTLS wants ~30 KB
of heap for a handshake and ~5 KB survives Wi-Fi association on the 2 MB
boards), and a token in a GPL image is a token everybody has. So the split is:

  * Structured test reports go to a small service on the firmware VPS over the
    plain HTTP the device already speaks, and it holds the only write
    credential. SQLite is the database; the per-tag tracking issue is rendered
    from it and rewritten in place, so GitHub can be down or rebuilt at will.
  * Bug reports do not come through here at all. The device draws a QR that
    opens .github/ISSUE_TEMPLATE/bug.yml prefilled with board, version and
    diagnostics, and the reporter files it under their own GitHub account:
    right attribution, GitHub's own spam controls, no token.

Green needs two separate devices whose owners ran the build for a day or more.
A board nobody runs cannot go green and does not block a promote; a board
somebody runs and has not vouched for does. That rule is the whole point: it
distinguishes untested from unowned, which "nobody shouted" cannot.

wadamesh.com/beta.html renders the same JSON for the promote decision.

Two things found while deploying, both repo-vs-box drift that would have bitten
somebody eventually:

  * The repo's copy of the firmware vhost was missing /apps/ and /bringup/,
    which had been added on the box and never committed. Deploying it would
    have 404'd the Lua app and language store for every device. The repo copy
    is now taken from the box, and the deploy script refuses to push a vhost
    that has fewer locations than the live one.
  * The repo's tile-transcode unit named a venv interpreter that does not exist
    on the box (python3.14 there has no ensurepip, so venv cannot bootstrap pip
    at all). The live unit uses the system python; the repo now says so too.

The firmware side (the report page, the QR, the opt-in ping) is not in this
commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:06:07 +02:00
Kaj SchittecatandClaude Opus 5 684f81527a touch: a T-Deck Max self-update installed T-Deck Pro firmware
The Max env defines HAS_TDECK_PRO as well as HAS_TDECK_MAX, because it reuses
the Pro's display and touch drivers, and the OTA name table tested
HAS_TDECK_PRO first. So OTA_BIN_NAME on a Max resolved to wadamesh-tdeck-pro:
the update check found the right release, then downloaded and flashed the Pro
image. Both are ESP32-S3, so the image check passes and the board comes up with
its peripheral power rails, resets and fuel gauge unhandled, which needs a USB
reflash to undo.

This is the failure the comment above that table warns about, and the third
time the table has been wrong (Wio Tracker L2 in beta_80, T-Deck Pro before
it). The Max branch now precedes the Pro branch, the same way the V4-R8 branch
precedes the V4-TFT one.

Shipped in beta_84, so a Max on that build must be updated over USB rather than
from the device.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 10:59:26 +02:00
Michael A. Cojocari 71ae92ff4a feat(ui): add preset screen timeout slider
Replace the freeform seconds field with practical duration stops from 30 seconds through one hour and Never, normalizing legacy values to the nearest stop.

Refs #560
2026-09-22 21:00:12 -04:00
Michael A. Cojocari 4d31c7c35f feat(ui): consolidate backups and refine e-paper UX
Move backup export/import into one workflow, improve narrow settings controls, and make T-Deck Pro/Max dropdowns and lock state e-paper appropriate.

Refs #559
2026-09-22 20:41:58 -04:00
Michael A. Cojocari 6af981fe57 fix(tdeck-pro): restore setup input on 4G model
Keep keyboard navigation available through first-run setup and latch CST3530 touch interrupts on T-Deck Pro as well as Max.
2026-09-22 19:28:47 -04:00
Michael A. Cojocari 9b7d7dc86d feat(tdeck-pro): expand Commander controls 2026-09-22 16:20:48 -04:00
Michael A. Cojocari a3b7fa8444 fix(m9): keep locked app drawer as Back root 2026-09-22 15:57:07 -04:00
Michael A. Cojocari f6ae69b1b6 fix(tdeck-pro): separate chat sender and messages 2026-09-22 15:51:56 -04:00
Michael A. Cojocari 02cce46003 fix(ui): follow screen timeout for keyboard light 2026-09-22 12:19:19 -04:00
Michael A. Cojocari 8759a1f207 fix(m9): hide app title on lock screen 2026-09-21 20:08:37 -04:00
Michael A. Cojocari 6d9c25d064 tools: add build upload monitor helper
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-09-21 14:30:15 -04:00
Michael A. Cojocari f77d37478a fix(ui): add Home exit to Advert screen
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-09-21 14:30:15 -04:00
Michael A. Cojocari 8ed461f9fe fix(m9): reveal the next offscreen chat message
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-09-21 09:31:21 -04:00
Kaj SchittecatandClaude Opus 5 bf9d8f775c site: the language count was three releases out of date
The front page still advertised 11 languages and listed the original
built-in set; the docs said twelve in two places and thirteen in a third.
langs.json carries 14 downloadable languages, so 15 with English.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 15:21:47 +02:00
Kaj SchittecatandClaude Opus 5 e084b1d3bf release: cumulative stable notes for beta_83 (beta_66..83)
The promote reused the single-tag notes, so the stable feed and the GitHub
body only covered beta_83 itself. This is the curated beta_66..83 delta,
136 notes: per-build framing and the still-open lists dropped, supersessions
collapsed to what actually ships.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 15:14:57 +02:00
Kaj SchittecatandClaude Opus 5 5d5f7bc638 release: beta_84 notes, and let a promotion skip boards it predates
A board added mid-cycle (the T-Deck Max) has no images in an older tag, so
promoting that tag copied a file that does not exist and, with set -e, took
the whole promotion down. It is skipped with a note now, and the flasher
manifest generator leaves out any board with no image in the channel it is
writing, rather than handing the flasher a 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
beta_84
2026-09-21 14:39:22 +02:00
Kaj Schittecat 2bf51f1bec chore: refresh Mesh America catalog for beta_83 2026-09-21 14:35:34 +02:00
Terry Carr 0b78e7a142 Add POI translations and implement map location features 2026-09-21 13:23:09 +01:00
Kaj SchittecatandClaude Opus 5 c388a36cb9 touch: restore the trailing newlines the T-Deck Max PRs dropped
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:10:45 +02:00
Kaj SchittecatandClaude Opus 5 9fe008e5ef Merge PR #547 from pelgraine: T-Deck Max boots with Wi-Fi off
Wi-Fi and BLE together at boot leave about 28% of internal RAM free on this
board, so it starts with BLE only; the Settings toggle persists any choice.
HAS_TDECK_MAX gated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:06:41 +02:00
Kaj SchittecatandClaude Opus 5 37e4441cd7 Merge PR #546 from pelgraine: T-Deck Max UI
E-paper adaptations for the Max, all behind HAS_TDECK_MAX: no fades, the
page repainted before power-off so no black frame is left on the glass, a
sleep banner, tap to wake, and the keyboard-backlight chord.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:06:41 +02:00
Kaj SchittecatandClaude Opus 5 9c47a9e50d touch: fixes on the merged PRs, and ship the T-Deck Max
Review of #531 turned up four things that had to be fixed before release:

- An unusable region name no longer discards the radio settings. The save
  returned early, so frequency, bandwidth, SF, CR and TX power were thrown
  away, and the rule rejects names with capitals or a "$private" scope, so
  anyone carrying an older region could not change their radio at all. On the
  pager that path is the silent blur save, so it failed with nothing on screen.
  Now only the region is skipped, and it says so.
- Restored useChainedFont() on the telemetry Show button: without the fallback
  chain that label is boxes in Russian, Ukrainian, Bulgarian, Serbian, Greek.
- Region scanning installs unknown repeaters as transient contacts so their
  encrypted replies can be matched. They were never removed, so each scan left
  up to 16 nameless entries in the contact table (and in Contacts). They are
  dropped when the scan ends or the page closes.
- One radio request per scan tick. The loop ran through all 16 repeaters in a
  single 200 ms tick, which is that many key derivations back to back.

The V4-R8 also did not build (its src/ files see a vendored lv_conf.h, so the
new text-size fonts were missing) and then did not fit at 101.3%. It builds at
85.6% now: the board no longer carries the compiled-in translations it
inherited from the V4, which it never needed, since with 8 MB of PSRAM its
store works like any other 8 MB board.

T-Deck Max (#545) joins the release matrix: build list, flasher manifest,
DEVICES.md and the site's board list. Board names in the flasher lost their
em dashes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:04:24 +02:00
Kaj SchittecatandClaude Opus 5 4df42eedf4 Merge PR #531 from oumike: device usability, input and accessibility
M9 Back and Bluetooth-keyboard Esc stop at the locked app-drawer root, M9
focus fixes, optional M5Stack CardKB on the V4 and V4-R8, V4-R8 touch and
text-size accessibility, Wio L2 SD retry, high-contrast day and night themes
(#544), channel region discovery (#541) and the Czech translation
contributed in #540 by brebtatv.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 13:54:09 +02:00
Kaj SchittecatandClaude Opus 5 6ad23fa236 Merge PR #545 from pelgraine: LilyGo T-Deck Max target
New board: the T-Deck Pro's ESP32-S3 with the peripheral power enables and
resets behind an XL9555 expander and a BQ27220 fuel gauge. Reuses the Pro's
display and touch drivers; the two additions to them are HAS_TDECK_MAX gated,
so the Pro build is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 13:39:50 +02:00
pelgraine a87a44f7cc T-Deck Max: Wi-Fi off by default
Signed-off-by: pelgraine <140762863+pelgraine@users.noreply.github.com>
2026-09-21 21:17:51 +10:00
pelgraine ec5cc09399 T-Deck Max: e-paper UI, front-light and pad shortcuts
Signed-off-by: pelgraine <140762863+pelgraine@users.noreply.github.com>
2026-09-21 21:12:07 +10:00
pelgraine 8dec5cf78d Add LilyGo T-Deck Max target
Signed-off-by: pelgraine <140762863+pelgraine@users.noreply.github.com>
2026-09-21 20:57:46 +10:00
Michael A. Cojocari 36f9628e11 feat: add Czech translation 2026-09-20 20:45:14 -04:00
Michael A. Cojocari a08342a3c0 feat(ui): discover and select channel regions 2026-09-20 19:59:56 -04:00
Michael A. Cojocari 0aa2f28c16 feat(ui): add high-contrast day and night themes 2026-09-20 19:08:45 -04:00