BotScreen and DashboardConfigScreen were calling savePrefs() on every
exit regardless of whether any setting changed. Add _dirty flag set only
on actual value changes (toggle, channel select, keyboard confirm,
field cycle), reset on enter().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- KeyboardWidget: replace inline placeholder overlay with PopupMenu
- UITask QuickMsgScreen: replace inline CONTACT_PICK/CHANNEL_PICK context
menus with PopupMenu; notif label stored in _ctx_notif_item at open time
- BotScreen: clear placeholder list for trigger field (expansion tokens
would never match incoming literal text)
- MsgExpand: fix APPEND macro off-by-one (oi+_l < out_len-1 → < out_len)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
expandMsg now expands {temp}, {hum}, {pres}, {batt}, {alt}, {lux}, {dist},
{co2} from live sensor readings. The [{}] picker in the on-screen keyboard
shows only sensors currently detected by SensorManager and scrolls when
more than 3 items fit the overlay.
New SensorPlaceholders.h helper keeps sensor-to-keyboard wiring out of
UITask.cpp. MsgExpand.h handles all expansion logic centrally; MyMeshBot
and QuickMsgScreen pass &sensors and batt_volts to each call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All three keyboard instances (Settings, QuickMsg, Bot) now show plain
text + cursor without any field-name prefix. Removes the label field
from KeyboardWidget entirely — the screen title already indicates context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All three keyboard implementations (SettingsScreen, QuickMsgScreen, BotScreen)
now share a single KeyboardWidget struct defined in KeyboardWidget.h, eliminating
~480 lines of duplicated render/input logic. Also fixes the SettingsScreen bug
where navigation keys were checked before the placeholder overlay, causing cursor
movement when the overlay was open.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Bot redesign: DM bot active for all private messages (no pubkey filter),
channel bot optional with separate enable flag; both can run simultaneously
- Bot: one shared trigger, separate reply texts for DM and channel
- Buzzer: add Auto mode (mutes when BT connected, unmutes on disconnect);
per-channel force-on overrides still work as intended
- Settings: defer flash writes to menu exit (only when dirty)
- Settings: add Seconds toggle (hide clock seconds, refresh drops 1s→60s)
- Fullscreen msg preview: fix truncation (fmsg buf 79→140 chars)
- RingtoneEditor: fix melody playback cut after first note (RTTTL lib holds
pointer — moved play buffer to member variable)
- BotScreen: remove key hint footer
- .gitattributes: protect README.md from upstream merge conflicts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move three custom screens out of UITask.cpp into their own .h files
(RingtoneEditorScreen.h, BotScreen.h, ToolsScreen.h) and replace them
with three #include lines. UITask.cpp now only contains screens that
overlap with upstream (SplashScreen, SettingsScreen, QuickMsgScreen,
HomeScreen), making future upstream merges easier — custom screens live
in files that upstream will never touch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>