mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-02 10:16:11 +00:00
feat(clock,keyboard): alarm repeat + non-Latin keyboard alphabets
Alarm repeat (Clock Tools): - NodePrefs::alarm_repeat_mask (weekday bitmask, struct tm::tm_wday convention) — new Repeat row cycles Off/Daily/Weekdays/Weekends. computeAlarmNextFire() scans the next 7 days for a matching weekday when set; evaluateAlarm() only clears alarm_on (one-shot) when the mask is empty, otherwise re-arms. mask==0 is byte-for-byte the original one-shot behaviour, so existing users see no change. On-screen keyboard alphabets (Settings > Keyboard > Alphabet): - KeyboardWidget reworked from single-byte ASCII cells to UTF-8 codepoints (insertion, backspace and T9 in-place cycling all codepoint-aware now, so a multi-byte character is never split) — see kbApplyCapsUtf8/kbUtf8Len/ kbUtf8CharAt/kbUtf8LastCharBytes. - Cyrillic, Greek and an Extended Latin set (Polish/Czech/Slovak/German/ French/Spanish/Nordic diacritics) join the keyboard's existing #@/abc page cycle (Latin -> alt alphabet -> Symbols -> Latin) — no new key needed. NodePrefs::keyboard_alt_alphabet picks which one, if any, is active. - Lemon font is forced on transiently inside KeyboardWidget::render() (saved and restored every call) whenever the alt-alphabet page is showing or already-typed text has non-ASCII bytes, so composing is visible even if Font is set to Default. - Each script's caps-shift rule is distinct and documented in kbApplyCapsUtf8: flat -0x20 for ASCII/Cyrillic/Greek (with the ё/ς exceptions), flat -0x20 for Latin-1 (à-þ), and an adjacent-pair -1 for Latin Extended-A (verified against every character actually used, not a blanket rule for that whole Unicode block). NodePrefs schema: two tail-appended fields this session (alarm_repeat_mask, keyboard_alt_alphabet), SCHEMA_SENTINEL 0xC0DE001B -> 0xC0DE001D, sizeof(NodePrefs) 2496 -> 2504 (verified via a standalone host compile). Docs: Clock Tools' Repeat row, Settings > Keyboard > Alphabet, and the Rooms keyboard note (no longer ASCII-only once an alphabet is enabled). Not build-verified — no PlatformIO toolchain available this session. Caps mappings cross-checked against Python's Unicode case tables; UTF-8 literal bytes verified at the byte level.
This commit is contained in:
@@ -145,15 +145,16 @@ class ClockToolsScreen : public UIScreen {
|
||||
int renderAlarm(DisplayDriver& d) {
|
||||
d.drawCenteredHeader("ALARM");
|
||||
if (!_prefs) return 60000;
|
||||
const char* rows[3] = { "Hour", "Minute", "Armed" };
|
||||
if (_sel > 2) _sel = 2;
|
||||
const char* rows[4] = { "Hour", "Minute", "Repeat", "Armed" };
|
||||
if (_sel > 3) _sel = 3;
|
||||
const int valx = d.width() / 2 + 6;
|
||||
drawList(d, 3, _sel, _scroll, [&](int i, int y, bool sel, int reserve) {
|
||||
drawList(d, 4, _sel, _scroll, [&](int i, int y, bool sel, int reserve) {
|
||||
drawRowSelection(d, y, sel, reserve);
|
||||
d.setCursor(4, y); d.print(rows[i]);
|
||||
char b[6];
|
||||
char b[10];
|
||||
if (i == 0) snprintf(b, sizeof(b), "%02u", _prefs->alarm_hour);
|
||||
else if (i == 1) snprintf(b, sizeof(b), "%02u", _prefs->alarm_min);
|
||||
else if (i == 2) snprintf(b, sizeof(b), "%s", NodePrefs::alarmRepeatLabel(NodePrefs::alarmRepeatIdxForMask(_prefs->alarm_repeat_mask)));
|
||||
else snprintf(b, sizeof(b), "%s", _prefs->alarm_on ? "ON" : "OFF");
|
||||
EditKind k = (i == 0) ? EK_A_HOUR : (i == 1) ? EK_A_MIN : EK_NONE;
|
||||
drawValue(d, y, valx, reserve, sel, k, b);
|
||||
@@ -226,12 +227,16 @@ class ClockToolsScreen : public UIScreen {
|
||||
_view = V_MENU; _sel = 0; _scroll = 0;
|
||||
return true;
|
||||
}
|
||||
if (c == KEY_UP) { _sel = (_sel > 0) ? _sel - 1 : 2; return true; }
|
||||
if (c == KEY_DOWN) { _sel = (_sel < 2) ? _sel + 1 : 0; return true; }
|
||||
if (c == KEY_UP) { _sel = (_sel > 0) ? _sel - 1 : 3; return true; }
|
||||
if (c == KEY_DOWN) { _sel = (_sel < 3) ? _sel + 1 : 0; return true; }
|
||||
if (c == KEY_ENTER) {
|
||||
if (_sel == 0) editField(EK_A_HOUR, _prefs->alarm_hour, 23);
|
||||
else if (_sel == 1) editField(EK_A_MIN, _prefs->alarm_min, 59);
|
||||
else { _prefs->alarm_on ^= 1; _alarm_dirty = true; _task->onAlarmChanged(); }
|
||||
else if (_sel == 2) { // Repeat: cycle Off -> Daily -> Weekdays -> Weekends -> Off
|
||||
uint8_t idx = (NodePrefs::alarmRepeatIdxForMask(_prefs->alarm_repeat_mask) + 1) % NodePrefs::ALARM_REPEAT_COUNT;
|
||||
_prefs->alarm_repeat_mask = NodePrefs::alarmRepeatMaskForIdx(idx);
|
||||
_alarm_dirty = true; _task->onAlarmChanged();
|
||||
} else { _prefs->alarm_on ^= 1; _alarm_dirty = true; _task->onAlarmChanged(); }
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user