Commit Graph

13 Commits

Author SHA1 Message Date
Jakub
74764aed2b perf(ui): O(n) FullscreenMsgView wrap via getCodepointWidth virtual
The wrap loop used to memcpy a growing substring and call getTextWidth
on it for every appended codepoint — O(n²) UTF-8 decoding with Lemon
font, ~5-20 ms on a full e-ink redraw of a long message.

Add DisplayDriver::getCodepointWidth(cp) (default: build a UTF-8 buffer
and forward to getTextWidth) plus DisplayDriver::decodeCodepoint() as
the shared UTF-8 walker. Override getCodepointWidth in GxEPDDisplay
(direct lemonXAdvance for Lemon size 1) and SH1106Display (lemonXAdvance
for Lemon, fixed 6*sz for built-in font). FullscreenMsgView now walks
codepoints once and sums widths incrementally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:22:16 +02:00
Jakub
744f263932 refactor: replace all hardcoded pixel positions with layout helpers
Add lineStep(), headerH(), listStart(), listVisible(), valCol() to
DisplayDriver so layout derives from getLineHeight() instead of fixed
OLED constants. Refactor all screens (SettingsScreen, NearbyScreen,
FullscreenMsgView, QuickMsgScreen, BotScreen, DashboardConfigScreen,
AutoAdvertScreen, RingtoneEditorScreen) and all HomeScreen pages plus
the lock screen and splash screen in UITask.cpp.

On OLED (lh=8) positions are unchanged; on landscape e-ink (lh=16) all
text and widgets now scale correctly to the 250×122 display.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 18:05:09 +02:00
Jakub
319428c7c6 chore: remove unused FS_START_Y constant from FullscreenMsgView
startY is computed dynamically from header_h, making the constant redundant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 09:34:24 +02:00
Jakub
a115916d8f feat: runtime font switcher — Default vs Lemon in Settings > Display
- Add Lemon font (LemonFont.h, LemonIcons.h) to the standard build
  alongside the Adafruit built-in font; ~101 KB added to flash
- SH1106Display: add _use_lemon flag + setLemonFont(bool) to switch
  at runtime; print() and getTextWidth() use Lemon path when active;
  translateUTF8ToBlocks() passes UTF-8 through unchanged (Lemon supports
  full Unicode U+0020-U+04FF) vs transliterating for the default font
- DisplayDriver: add getCharWidth()/getLineHeight() virtuals (defaults 6/8);
  SH1106Display returns 5/9 for Lemon, 6/8 for default; add setLemonFont()
  no-op virtual; fix orphaned UTF-8 leading byte in drawTextEllipsized
- FullscreenMsgView: replace fixed-char-count word-wrap with pixel-accurate
  wrap using display.getTextWidth(); use getLineHeight() for spacing so
  Lemon (9 px) and default (8 px) both render correctly
- NodePrefs: add use_lemon_font field (0=default, 1=Lemon)
- SettingsScreen: add "Font" item in Display section (Default / Lemon),
  calls UITask::applyFont() on change
- UITask: add applyFont() that calls display->setLemonFont(use_lemon_font);
  called at startup (begin()) and when the setting changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 09:33:35 +02:00
Jakub
34cfd27b8a fix: use @[nick] format for replies and fix fullscreen message display
- Reply prefix changed to "@[nick] " format — bracket delimiter handles
  nicks with spaces unambiguously
- FullscreenMsgView: parse "@[nick] body" to show "To: nick" header;
  fall back gracefully if format not matched
- Reduce FS_CHARS 21→20 to prevent scroll arrows overlapping last char
- Transliterate nick before displaying in "To:" header and "RE:" title
  so non-ASCII characters render correctly on the OLED font

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:18:45 +02:00
Jakub
6f7de3ed20 feat: add reply action to channel and DM message history
Long-press Enter (KEY_CONTEXT_MENU) on a selected message shows an
'Options / Reply' popup in both list and fullscreen views. Confirming
opens MSG_PICK with 'RE: nick' title — the reply can be sent via
keyboard or quick message templates, both automatically prefixed with
'@nick '.

- Channel: reply prefix extracted from 'sender: message' format
- DM: reply available only on incoming messages, uses contact name
- FullscreenMsgView: REPLY added to Result enum, KEY_CONTEXT_MENU handled
- MSG_PICK: _reply_mode flag routes prefix through keyboard and templates
- Guard: prevent sending empty reply (prefix-only keyboard input ignored)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 15:12:11 +02:00
Jakub
8f566732ed feat: show @recipient as 'To: nick' bar in fullscreen message view
When a message starts with @nick, the fullscreen view expands the header
to show a second row 'To: nick' below the sender name, and displays the
message body without the @nick prefix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 15:00:01 +02:00
Jakub
a60ec376d7 perf: increase render interval on static screens from 300ms to 2000ms
Static screens (SettingsScreen, BotScreen, FullscreenMsgView, message
list, contact picker) were re-rendering every 300ms with no visible
benefit. New messages still trigger immediate refresh via newMsg() →
_next_refresh=100, so responsiveness is unchanged. Reduces unnecessary
SPI transfers and CPU wakeups ~6x on idle static screens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 23:42:52 +02:00
Jakub
c4b152fd6a fix: clear arrow background in FullscreenMsgView to prevent text overlap
Text lines fill the full display width, causing the last chars to bleed
into the scroll arrow area. Draw a DARK fillRect behind each arrow before
rendering it, so the arrow appears on a clean black background without
truncating the text width.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 23:28:18 +02:00
Jakub
44b2519df4 fix: with_sender buffer too small and FS_LINE_H mismatch
- with_sender[160] could hold only ~160 chars but node_name(32) +
  expanded(200) needs up to 234; snprintf would silently truncate
  the UI display entry. Increased to 240.
- FS_LINE_H was 9 but Adafruit 5x7 font line height is 8, wasting
  1px per line and showing 5 lines instead of 6.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 23:23:20 +02:00
Jakub
6a7f8b7ca7 fix: transliterate message text in FullscreenMsgView before wrapping
Raw UTF-8 message body was passed directly to display.print(), rendering
Polish and other accented chars as garbage on the Adafruit font.
Transliterating before wrapLines also fixes byte-count wrapping for
multi-byte UTF-8 characters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:24:36 +02:00
Jakub
c86e6c803e fix: reverse fullscreen message nav order and remove channel # prefix
- Swap left/right navigation in fullscreen view: left=newer, right=older
- Update arrow indicators to match new direction
- Remove # prefix from channel name in message and compose view titles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 20:21:13 +02:00
Jakub
26d3d7ab00 refactor: extract fullscreen message view into reusable FullscreenMsgView module
Shared struct handles rendering and input for both DM and channel fullscreen
views, replacing ~80 lines of duplicated inline code. Fixes navigation arrow
indicators being swapped in channel fullscreen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 23:54:26 +02:00