feat(ui-lvgl): SD card as a USB drive, message banner, card format, restart screen

- USB through TinyUSB (ARDUINO_USB_MODE=0) instead of USB-Serial/JTAG: the
  serial port stays, and plugged into a computer (enumerated, the bus not
  suspended -- on battery an unplug only shows as a suspend) the device asks
  "Charge only / USB drive". As a drive the firmware lets go of the card and
  the computer gets its sectors; ejected or unplugged, the device restarts.
- Incoming messages: a banner slides down from under the status bar (icon,
  sender or channel, two lines of the text from history); a tap opens the
  conversation (not while locked), a swipe up dismisses it, not shown for
  the conversation already open. Toasts moved up there too, under the banner
  when both are up; the ones only echoing a switch or a choice are gone.
- Storage > Format card: a popup saying what goes, then Format tapped twice;
  one FAT32 volume over the whole card (readable or not), then a restart.
- A deliberate restart shows a full "Restarting..." screen with the reason
  instead of the screen just freezing.
- The screenshot flash is a thin frame round the edges: a full-screen fade
  redrew all 320x240 each step and tore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-09-28 17:17:38 +02:00
co-authored by Claude Opus 5.5
parent 95c4c093f0
commit 51530ac451
8 changed files with 512 additions and 48 deletions
@@ -135,6 +135,7 @@ public:
void setKeyboardAlphabets(int main_idx, int alt_sel);
void openChannel(uint8_t channel_idx);
void openDM(const uint8_t* pub_key);
void bannerOpen(); // the message banner tapped: its conversation
void back();
void sendFromCompose();
void setKeyboardVisible(bool show);
@@ -256,6 +257,10 @@ public:
void storageClearHistory();
void storageLiveCap(int idx);
void storageClearLive();
void storageFormatAsk(); // Storage > Format card: the popup (first confirmation)
void storageFormatTap(bool go); // its buttons: Format twice (the second confirmation), or Cancel
void usbPoll(); // a computer plugged in: offer the SD card as a USB drive
void usbTap(bool drive); // that popup's buttons
bool locked() const;
void pinKey(const char* key); // the lock screen's keypad
void pinSetupPopup(); // Settings > Display & power > Screen PIN