theme: Mute colours and animations (#798)

A new switch at the top of Settings > Theme > Colour for a calm, old-desktop
look, saved as ui_mute (default off) and applied at the next boot like the
rest of the theme:

- No animations: no boot splash, lock screen motion, Home radar sweep,
  live-dot breathing, advert ring, PIN shake or glance fades; scrolls, tab
  changes, Lua app scrolls and switch knobs jump instead of sliding.
- Constellation screensaver goes calm: no pulse, sweep, pings or packets; the
  burn-in steps (turn, drift, corner moves) stay, without the fade.
- Muted colours: a grey-blue accent, Regular look, and the link, mention,
  status and bubble colours pulled towards grey, in Day and Night.
- Solid panels: no background, no glass tiles, and popup backdrops are the
  theme background instead of see-through black.

While it is on, the accent, looks, rainbow, background and glass controls are
locked with a note; their saved values come back when it is turned off. High
contrast keeps its own colours but still loses the animations. T-Deck Pro is
unchanged (no Colour section).

Placeholder rows for the 3 new strings in the 15 language files; the
Constellation render harness takes CST_CALM=1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
This commit is contained in:
Michael A. CojocariandCopilot committed 2026-11-03 15:52:41 -05:00
1 parent 53d17d0b0f
commit 4644affad9
22 files changed
+274 -104

No files matched your search

+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2369,3 +2369,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ Do Not Disturb until you switch it off. Holding Shift does the same from anywher
Backspace Backspace
M C H A S M C H A S
N N
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2352,3 +2352,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2363,3 +2363,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2352,3 +2352,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2351,3 +2351,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2366,3 +2366,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2354,3 +2354,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+3
View File
@@ -2353,3 +2353,6 @@ This help This help
Turn the knob • click to insert Turn the knob • click to insert
Turn to scroll, click or any key to close. Turn to scroll, click or any key to close.
W A S D, Q / E W A S D, Q / E
Mute colours and animations Mute colours and animations
Mute colours and animations sets these for now. Mute colours and animations sets these for now.
Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off. Nothing moves, no boot animation, quiet colours and solid panels. Your other colour choices come back when it is off.
+2
View File
@@ -2595,6 +2595,8 @@ uint8_t touchPrefsGetColorStyle() {
void touchPrefsSetColorStyle(uint8_t style) { if (!s_begun) touchPrefsBegin(); prefsPutUChar("col_style", style > TOUCH_LOOK_PASTEL ? TOUCH_LOOK_REGULAR : style); }
bool touchPrefsGetRainbow() { if (!s_begun) touchPrefsBegin(); return s_prefs.getUChar("col_rb", 0) != 0; }
void touchPrefsSetRainbow(bool on) { if (!s_begun) touchPrefsBegin(); prefsPutUChar("col_rb", on ? 1 : 0); }
bool touchPrefsGetMuted() { if (!s_begun) touchPrefsBegin(); return s_prefs.getUChar("ui_mute", 0) != 0; }
void touchPrefsSetMuted(bool on) { if (!s_begun) touchPrefsBegin(); prefsPutUChar("ui_mute", on ? 1 : 0); }
bool touchPrefsGetGlassTiles() { if (!s_begun) touchPrefsBegin(); return s_prefs.getUChar("glass", 1) != 0; }
void touchPrefsSetGlassTiles(bool on) { if (!s_begun) touchPrefsBegin(); prefsPutUChar("glass", on ? 1 : 0); }
bool touchPrefsGetAntExtAlways() { if (!s_begun) touchPrefsBegin(); return s_prefs.getUChar("ant_ext", 0) == 1; }
+5
View File
@@ -769,6 +769,11 @@ uint8_t touchPrefsGetColorStyle();
void touchPrefsSetColorStyle(uint8_t style);
bool touchPrefsGetRainbow();
void touchPrefsSetRainbow(bool on);
// Settings > Theme > Colour > Mute colours and animations (default OFF, at next boot):
// no animations or boot splash, a muted palette, no background, glass or see-through
// layers. The looks above keep their saved values and return when it is turned off.
bool touchPrefsGetMuted();
void touchPrefsSetMuted(bool on);
// Settings > Theme > Glass tiles: Home widgets, cards and control panel tiles are frosted
// glass over the background (default ON, today's look); off = opaque panel-colour fills.
bool touchPrefsGetGlassTiles();
+18 -7
View File
@@ -369,7 +369,8 @@ void flowDrawCb(lv_event_t* e) {
ld.width = K1(1);
ld.round_start = ld.round_end = 1;
const float period = (float)K(9), dash = (float)LV_MAX(2, K(2));
const float shift = fmodf((float)((uint64_t)lv_tick_get() * (uint64_t)K(12) % 1000000000ull) / 1000.0f, period);
const float shift = s_th.calm ? 0.0f
: fmodf((float)((uint64_t)lv_tick_get() * (uint64_t)K(12) % 1000000000ull) / 1000.0f, period);
for (int f = 0; f < s_nflow; ++f) {
const Flow& fl = s_flow[f];
ld.color = C(s_flow_col[f]);
@@ -838,7 +839,7 @@ void pingExec(void* var, int32_t v) {
void hideReady(lv_anim_t* a) { lv_obj_add_flag(static_cast<lv_obj_t*>(a->var), LV_OBJ_FLAG_HIDDEN); }
void pingAt(lv_coord_t x, lv_coord_t y, uint32_t col) {
if (!s_root) return;
if (!s_root || s_th.calm) return;
lv_obj_t* o = s_ping[s_next_ping];
s_next_ping = (s_next_ping + 1) % kPings;
lv_anim_del(o, pingExec);
@@ -872,7 +873,7 @@ void dotStart(lv_anim_t* a) { lv_obj_clear_flag(static_cast<lv_obj_t*>(a->var),
// A packet travelling one leg of its path. Delayed legs stay hidden until they
// start, so a two-hop arrival reads as one dot handed on by the repeater.
void launchDot(Pt from, Pt to, uint32_t delay_ms, uint32_t col) {
if (!s_root) return;
if (!s_root || s_th.calm) return;
const int i = s_next_dot;
s_next_dot = (s_next_dot + 1) % kDots;
lv_obj_t* o = s_dot[i];
@@ -1191,6 +1192,12 @@ void hudHiddenReady(lv_anim_t*) {
}
void hudMove() {
if (!s_root || s_hud_moving || !s_clock) return;
if (s_th.calm) { // straight to the next corner, no fade
s_hud = (s_hud + 1) % (s_portrait ? 2 : 4);
placeHud();
s_sig = 0;
return;
}
s_hud_moving = true;
lv_anim_t a;
lv_anim_init(&a);
@@ -1269,7 +1276,7 @@ void cstShow(lv_obj_t* parent, const CstTheme& theme) {
s_core = disc(s_scene, s_cx, s_cy, K(8));
lv_obj_set_style_bg_color(s_core, C(s_th.glow), 0);
lv_obj_set_style_bg_opa(s_core, LV_OPA_COVER, 0);
{
if (!s_th.calm) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, s_core);
@@ -1281,7 +1288,7 @@ void cstShow(lv_obj_t* parent, const CstTheme& theme) {
lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);
lv_anim_start(&a);
}
{
if (!s_th.calm) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, s_halo);
@@ -1292,6 +1299,9 @@ void cstShow(lv_obj_t* parent, const CstTheme& theme) {
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);
lv_anim_start(&a);
} else { // you, held still part way through the pulse; no breath going out
corePulseExec(s_core, 700);
lv_obj_add_flag(s_halo, LV_OBJ_FLAG_HIDDEN);
}
for (int i = 0; i < kPings; ++i) {
@@ -1310,8 +1320,8 @@ void cstShow(lv_obj_t* parent, const CstTheme& theme) {
lv_obj_add_flag(s_dot[i], LV_OBJ_FLAG_HIDDEN);
}
// The radar sweep, over the mesh and under the status.
{
// The radar sweep, over the mesh and under the status (none when calm).
if (!s_th.calm) {
uint32_t seed = 0x9E3779B9u;
for (int i = 0; i < kClutter; ++i) {
seed ^= seed << 13; seed ^= seed >> 17; seed ^= seed << 5;
@@ -1623,6 +1633,7 @@ void cstTick(uint32_t now_ms) {
applyTurn(now_ms);
ringsBuild();
if (s_self_ring) lv_obj_set_pos(s_self_ring, s_cx - K(15) / 2, s_cy - K(15) / 2);
if (s_th.calm && s_core) corePulseExec(s_core, 700); // no pulse to follow the drift
rebuildScene();
}
if (!s_hud_ms) { s_hud_ms = now_ms ? now_ms : 1; return; }
+4
View File
@@ -70,6 +70,10 @@ struct CstTheme {
// Keep north up (#706): no slow turn, so north stays at the top. The drift, the
// pulse and the status changing corners still keep pixels moving.
bool north_lock = false;
// Mute colours and animations: nothing moves but the slow burn-in steps (the turn,
// the drift and the status changing corners, without its fade). No pulse, sweep,
// pings or packets, and the light on the routes stands still.
bool calm = false;
};
void cstShow(lv_obj_t* parent, const CstTheme& theme); // build; no-op when shown
+2 -1
View File
@@ -38,6 +38,7 @@ extern bool luaHostBeep();
extern void luaHostSetSelectionGlow(lv_obj_t* obj, bool selected);
extern uint32_t luaHostPanelColor(); // wada.ui.panel defaults (live theme)
extern uint32_t luaHostBorderColor();
extern bool luaHostAnimOn(); // false: Mute colours and animations
extern void luaHostMarkInert(lv_obj_t* obj); // never a keyboard focus stop
extern bool luaHostScreenOn(); // false = display asleep; app ticks pause
extern void luaHostKeepAwake(bool on); // hold the screen + ticks for a measuring app // notification chime; false = no sounder / muted
@@ -3279,7 +3280,7 @@ bool luaAppScroll(bool up) {
lv_coord_t step = (lv_coord_t)((s_h->body_h * 3) / 5);
if (step > room) step = room;
const lv_coord_t cur = lv_obj_get_scroll_y(s_h->body);
lv_obj_scroll_to_y(s_h->body, up ? cur - step : cur + step, LV_ANIM_ON);
lv_obj_scroll_to_y(s_h->body, up ? cur - step : cur + step, luaHostAnimOn() ? LV_ANIM_ON : LV_ANIM_OFF);
return true;
}
+196 -96
View File
@@ -897,6 +897,27 @@ static uint32_t rgbMix(uint32_t a, uint32_t b, uint8_t t) {
};
return ch(16) | ch(8) | ch(0);
}
// ---- Mute colours and animations (Settings > Theme > Colour) -----------------------
// A calm, old-desktop look: no motion, no splash, muted colours, no see-through
// layers. Read once at boot (applyBootTheme), like the rest of the theme.
static bool s_ui_muted = false;
// How long a one-shot animation runs: none at all when muted. An LVGL anim of 0 ms
// still lands on its end value and calls its ready callback on the next tick.
static inline uint32_t uiAnimMs(uint32_t ms) { return s_ui_muted ? 0u : ms; }
// LV_ANIM_ON for scrolls and tab changes, unless muted.
static inline lv_anim_enable_t uiAnimOn() { return s_ui_muted ? LV_ANIM_OFF : LV_ANIM_ON; }
// A popup's dimming backdrop: see-through black, or when muted a solid page in the
// theme's background, so nothing half shows through. Call after setting its colour.
static inline void styleScrim(lv_obj_t* o, lv_opa_t opa) {
if (s_ui_muted) lv_obj_set_style_bg_color(o, lv_color_hex(COLOR_BG), LV_PART_MAIN);
lv_obj_set_style_bg_opa(o, s_ui_muted ? LV_OPA_COVER : opa, LV_PART_MAIN);
}
// Pull a colour towards its own grey by t/255.
static inline uint32_t rgbDesat(uint32_t c, uint8_t t) {
const uint32_t l = (299u*((c>>16)&0xFF) + 587u*((c>>8)&0xFF) + 114u*(c&0xFF)) / 1000u;
return rgbMix(c, (l << 16) | (l << 8) | l, t);
}
// HSV (0..359, 0..100, 0..100) to 0xRRGGBB, the same mapping as lv_color_hsv_to_rgb
// without its RGB565 rounding.
static uint32_t hsvRgb(int h, int s, int v) {
@@ -3091,6 +3112,7 @@ static void setNavSelectionGlow(lv_obj_t* obj, bool selected) {
// wada.ui.panel's defaults, from the live theme, and its nav exclusion.
uint32_t luaHostPanelColor() { return COLOR_PANEL; }
uint32_t luaHostBorderColor() { return COLOR_BORDER; }
bool luaHostAnimOn() { return !s_ui_muted; } // Mute colours and animations is off
void luaHostMarkInert(lv_obj_t* obj) { lv_obj_add_flag(obj, NAV_SKIP_FLAG); }
void luaHostSetSelectionGlow(lv_obj_t* obj, bool selected) {
setSelectionGlow(obj, selected, LV_PART_MAIN);
@@ -7008,7 +7030,7 @@ static void navScrollBy(lv_obj_t* p, bool up) {
const lv_coord_t room = up ? lv_obj_get_scroll_top(p) : lv_obj_get_scroll_bottom(p);
lv_coord_t step = lv_obj_get_height(p) * 2 / 3;
if (step > room) step = room;
lv_obj_scroll_by(p, 0, up ? step : -step, LV_ANIM_ON);
lv_obj_scroll_by(p, 0, up ? step : -step, uiAnimOn());
}
// Find the largest scrollable container under `o` that still has room to scroll the
// requested way (the main page scroller usually wins on area).
@@ -7617,7 +7639,7 @@ static void navPump() {
case BSP_INPUT_NAVIGATION_KEY_F5: if (down) navGoToMainTab(MAP_TAB_INDEX); break; // blue ♣ = Map
case BSP_INPUT_NAVIGATION_KEY_F6: // purple ◇ — chat: jump to latest; else Settings
if (down) { LvChatPanel* cp = navOpenChatPanel();
if (cp) { if (cp->msgs) lv_obj_scroll_to_y(cp->msgs, LV_COORD_MAX, LV_ANIM_ON); }
if (cp) { if (cp->msgs) lv_obj_scroll_to_y(cp->msgs, LV_COORD_MAX, uiAnimOn()); }
else navGoToMainTab(SETTINGS_TAB_INDEX); }
break;
default: break;
@@ -9670,7 +9692,7 @@ static void openActionList(const char* title, const ActItem* items, int n) {
lv_obj_remove_style_all(s_actlist_root);
lv_obj_set_size(s_actlist_root, sw, sh);
lv_obj_set_style_bg_color(s_actlist_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_actlist_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_actlist_root, LV_OPA_60);
lv_obj_add_flag(s_actlist_root, LV_OBJ_FLAG_CLICKABLE);
lv_obj_clear_flag(s_actlist_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_actlist_root, actListBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -10003,7 +10025,7 @@ static void scrollClampOnEndCb(lv_event_t* e) {
// Chat virt: only spacer sets scroll extent; use instant snap (no ANIM_ON) so
// clamp doesn't fire a second SCROLL_END that races virt re-render.
const bool is_chat_msgs = (s_chat_msgs_scroll_obj == obj);
const lv_anim_enable_t anim = is_chat_msgs ? LV_ANIM_OFF : LV_ANIM_ON;
const lv_anim_enable_t anim = is_chat_msgs ? LV_ANIM_OFF : uiAnimOn();
if (sy < 0) lv_obj_scroll_to_y(obj, 0, anim);
else if (sy > sm) lv_obj_scroll_to_y(obj, sm, anim);
}
@@ -11921,7 +11943,7 @@ static void openThreadActionSheet(int thread_idx, const char* name, bool is_chan
lv_disp_get_ver_res(nullptr) - STATUSBAR_H);
lv_obj_set_pos(s_channel_long_sheet, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_channel_long_sheet, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_channel_long_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_channel_long_sheet, LV_OPA_60);
lv_obj_clear_flag(s_channel_long_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_channel_long_sheet);
lv_obj_add_event_cb(s_channel_long_sheet, channelLongSheetDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -12446,7 +12468,7 @@ static void emojiPaintSelection() {
}
if (s_emoji_sel >= 0 && s_emoji_sel < (int)n) {
lv_obj_t* b = lv_obj_get_child(s_emoji_grid, (uint32_t)s_emoji_sel);
if (b) lv_obj_scroll_to_view(b, LV_ANIM_ON);
if (b) lv_obj_scroll_to_view(b, uiAnimOn());
}
}
@@ -12514,7 +12536,7 @@ static void openEmojiPicker(lv_obj_t* ta, const char* const* items = k_emoji_ite
lv_obj_set_size(s_emoji_sheet, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_emoji_sheet, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_emoji_sheet, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_emoji_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_emoji_sheet, LV_OPA_60);
lv_obj_clear_flag(s_emoji_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_emoji_sheet, emojiSheetCloseCb, LV_EVENT_CLICKED, nullptr);
@@ -12824,7 +12846,7 @@ static void openQuickReplyPicker(LvChatPanel* p) {
lv_obj_set_size(s_qr_sheet, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_qr_sheet, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_qr_sheet, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_qr_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_qr_sheet, LV_OPA_60);
lv_obj_clear_flag(s_qr_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_qr_sheet, qrSheetCloseCb, LV_EVENT_CLICKED, nullptr);
@@ -13208,7 +13230,7 @@ static lv_anim_enable_t tabSwitchAnim(int idx) {
(void)idx;
return LV_ANIM_OFF;
#else
return idx == MAP_TAB_INDEX ? LV_ANIM_OFF : LV_ANIM_ON;
return idx == MAP_TAB_INDEX ? LV_ANIM_OFF : uiAnimOn();
#endif
}
@@ -15061,7 +15083,7 @@ static void openDiscoveredSettingsSheetCb(lv_event_t* e) {
lv_obj_set_size(s_disc_settings_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_disc_settings_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_disc_settings_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_disc_settings_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_disc_settings_root, LV_OPA_60);
lv_obj_clear_flag(s_disc_settings_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_disc_settings_root);
lv_obj_add_event_cb(s_disc_settings_root, discSettingsDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -18321,7 +18343,7 @@ static void openExpansionCard() {
lv_obj_set_size(s_expansion_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_expansion_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_expansion_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_expansion_root, LV_OPA_50, LV_PART_MAIN);
styleScrim(s_expansion_root, LV_OPA_50);
lv_obj_clear_flag(s_expansion_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_expansion_root, expansionBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -19883,8 +19905,8 @@ static void showConfirm(const char* msg, const char* ok_label, SimpleCb on_confi
lv_obj_set_size(s_confirm_modal, lv_disp_get_hor_res(nullptr),
lv_disp_get_ver_res(nullptr) - STATUSBAR_H);
lv_obj_set_pos(s_confirm_modal, 0, STATUSBAR_H);
lv_obj_set_style_bg_opa(s_confirm_modal, LV_OPA_60, LV_PART_MAIN);
lv_obj_set_style_bg_color(s_confirm_modal, lv_color_black(), LV_PART_MAIN);
styleScrim(s_confirm_modal, LV_OPA_60);
lv_obj_clear_flag(s_confirm_modal, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_flag(s_confirm_modal, LV_OBJ_FLAG_FLOATING);
lv_obj_move_foreground(s_confirm_modal);
@@ -22013,7 +22035,7 @@ static void openContactsSearchSheetCb(lv_event_t* e) {
lv_obj_set_size(s_contacts_search_sheet, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_contacts_search_sheet, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_contacts_search_sheet, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_contacts_search_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_contacts_search_sheet, LV_OPA_60);
lv_obj_clear_flag(s_contacts_search_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_contacts_search_sheet, contactsSearchSheetCloseCb, LV_EVENT_CLICKED, nullptr);
@@ -22491,7 +22513,7 @@ static void openAdminCmdPicker() {
lv_obj_set_size(s_admin_picker_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_admin_picker_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_admin_picker_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_admin_picker_root, LV_OPA_70, LV_PART_MAIN);
styleScrim(s_admin_picker_root, LV_OPA_70);
lv_obj_clear_flag(s_admin_picker_root, LV_OBJ_FLAG_SCROLLABLE);
// Tap on the dim backdrop dismisses the picker (matches the action
// sheet / search overlay convention).
@@ -22836,7 +22858,7 @@ static void openAdminLoginPrompt(const ContactInfo& c) {
lv_obj_set_size(s_admin_pw_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_admin_pw_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_admin_pw_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_admin_pw_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_admin_pw_root, LV_OPA_60);
lv_obj_clear_flag(s_admin_pw_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_admin_pw_root, [](lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED) return;
@@ -23666,7 +23688,7 @@ static void openLosModal(uint32_t mesh_idx) {
lv_obj_set_size(s_los_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_los_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_los_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_los_root, LV_OPA_70, LV_PART_MAIN);
styleScrim(s_los_root, LV_OPA_70);
lv_obj_clear_flag(s_los_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_los_root);
lv_obj_add_event_cb(s_los_root, losModalCloseCb, LV_EVENT_CLICKED, nullptr);
@@ -23787,7 +23809,7 @@ static void openContactActionSheet(uint32_t mesh_idx, bool is_repeater, const ch
lv_obj_set_size(s_action_sheet_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_action_sheet_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_action_sheet_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_action_sheet_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_action_sheet_root, LV_OPA_60);
lv_obj_set_style_pad_all(s_action_sheet_root, 0, LV_PART_MAIN);
lv_obj_clear_flag(s_action_sheet_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_action_sheet_root);
@@ -24715,7 +24737,7 @@ static void openAddChannelSheet() {
lv_disp_get_ver_res(nullptr) - STATUSBAR_H);
lv_obj_set_pos(s_addch_sheet, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_addch_sheet, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_addch_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_addch_sheet, LV_OPA_60);
lv_obj_clear_flag(s_addch_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_addch_sheet);
lv_obj_add_event_cb(s_addch_sheet, addChannelSheetDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -24868,7 +24890,7 @@ static void openShareMyContactPopup() {
lv_obj_set_size(s_share_my_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_share_my_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_share_my_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_share_my_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_share_my_root, LV_OPA_60);
lv_obj_clear_flag(s_share_my_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_share_my_root, shareMyContactBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -25659,7 +25681,7 @@ static void openBatteryChartWindow() {
lv_obj_set_size(s_batt_chart_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_batt_chart_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_batt_chart_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_batt_chart_root, LV_OPA_50, LV_PART_MAIN);
styleScrim(s_batt_chart_root, LV_OPA_50);
lv_obj_clear_flag(s_batt_chart_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_batt_chart_root, batteryChartDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -27268,7 +27290,7 @@ static void openTermCmdPicker() {
lv_obj_set_style_bg_opa(s_term_picker_root, LV_OPA_COVER, LV_PART_MAIN);
#else
lv_obj_set_style_bg_color(s_term_picker_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_term_picker_root, LV_OPA_70, LV_PART_MAIN);
styleScrim(s_term_picker_root, LV_OPA_70);
#endif
lv_obj_clear_flag(s_term_picker_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_term_picker_root, [](lv_event_t* e) {
@@ -28151,7 +28173,7 @@ static void fmTextPrompt(const char* title, const char* initial, void (*cb)(cons
lv_obj_set_size(s_fm_prompt, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_fm_prompt, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_fm_prompt, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_fm_prompt, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_fm_prompt, LV_OPA_60);
lv_obj_clear_flag(s_fm_prompt, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_t* card = lv_obj_create(s_fm_prompt);
@@ -28459,7 +28481,7 @@ static void fmOpenActions(const char* name, bool isdir) {
lv_obj_set_size(s_fm_actions, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_fm_actions, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_fm_actions, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_fm_actions, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_fm_actions, LV_OPA_60);
lv_obj_clear_flag(s_fm_actions, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_fm_actions, [](lv_event_t* ev) {
if (lv_event_get_code(ev) != LV_EVENT_CLICKED) return;
@@ -29757,7 +29779,7 @@ static void openSignalInfoPopup() {
lv_obj_set_size(s_siginfo_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_siginfo_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_siginfo_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_siginfo_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_siginfo_root, LV_OPA_60);
lv_obj_clear_flag(s_siginfo_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_siginfo_root, sigInfoDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -34347,7 +34369,7 @@ static void openContactsOverflowSheetCb(lv_event_t* e) {
lv_obj_set_size(s_contacts_overflow_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_contacts_overflow_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_contacts_overflow_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_contacts_overflow_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_contacts_overflow_root, LV_OPA_60);
lv_obj_clear_flag(s_contacts_overflow_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_contacts_overflow_root);
lv_obj_add_event_cb(s_contacts_overflow_root, contactsOverflowDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -34624,7 +34646,7 @@ static void ctDeleteProgressOpen(){
lv_obj_set_size(s_ctd_overlay, sw, sh);
lv_obj_set_pos(s_ctd_overlay, 0, 0);
lv_obj_set_style_bg_color(s_ctd_overlay, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_ctd_overlay, LV_OPA_70, LV_PART_MAIN);
styleScrim(s_ctd_overlay, LV_OPA_70);
lv_obj_clear_flag(s_ctd_overlay, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_flag(s_ctd_overlay, LV_OBJ_FLAG_CLICKABLE); // swallow taps during the delete
@@ -34895,7 +34917,7 @@ static lv_obj_t* ctOpenOptionSheet(const char* title){
lv_obj_set_size(s_ct_sort_sheet, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_ct_sort_sheet, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_ct_sort_sheet, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_ct_sort_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_ct_sort_sheet, LV_OPA_60);
lv_obj_clear_flag(s_ct_sort_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_ct_sort_sheet, ctSortSheetBackdropCb, LV_EVENT_CLICKED, nullptr);
lv_obj_add_event_cb(s_ct_sort_sheet, ctSortSheetGestureCb, LV_EVENT_GESTURE, nullptr); // swipe-to-close
@@ -40292,7 +40314,7 @@ static void mapOptPmTilesCb(lv_event_t* e) {
lv_obj_set_size(s_map_opts_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_map_opts_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_map_opts_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_map_opts_root, LV_OPA_50, LV_PART_MAIN);
styleScrim(s_map_opts_root, LV_OPA_50);
lv_obj_clear_flag(s_map_opts_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_map_opts_root, mapOptionsDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -40479,7 +40501,7 @@ static void mapOptInfoCb(lv_event_t* e) {
lv_obj_set_size(s_map_opts_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_map_opts_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_map_opts_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_map_opts_root, LV_OPA_70, LV_PART_MAIN);
styleScrim(s_map_opts_root, LV_OPA_70);
lv_obj_clear_flag(s_map_opts_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_map_opts_root, mapOptionsDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -40550,7 +40572,7 @@ static void openMapOptions() {
lv_obj_set_size(s_map_opts_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_map_opts_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_map_opts_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_map_opts_root, LV_OPA_50, LV_PART_MAIN);
styleScrim(s_map_opts_root, LV_OPA_50);
lv_obj_clear_flag(s_map_opts_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_map_opts_root, mapOptionsDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -40846,7 +40868,7 @@ static void openMapPicker(const int* idxs, int n) {
lv_obj_set_size(s_map_picker_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_map_picker_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_map_picker_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_map_picker_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_map_picker_root, LV_OPA_60);
lv_obj_clear_flag(s_map_picker_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_map_picker_root, mapPickerBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -40946,7 +40968,7 @@ static void openMapLocationMenu() {
lv_obj_set_size(s_map_location_menu_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_map_location_menu_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_map_location_menu_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_map_location_menu_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_map_location_menu_root, LV_OPA_60);
lv_obj_clear_flag(s_map_location_menu_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_map_location_menu_root, mapLocationMenuBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -41215,7 +41237,7 @@ static void openMapContactsList() {
lv_obj_set_size(s_map_contacts_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_map_contacts_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_map_contacts_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_map_contacts_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_map_contacts_root, LV_OPA_60);
lv_obj_clear_flag(s_map_contacts_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_map_contacts_root, mapContactsBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -43395,7 +43417,7 @@ static void reportOpenForm() {
lv_obj_set_size(s_report_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_report_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_report_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_report_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_report_root, LV_OPA_60);
lv_obj_clear_flag(s_report_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_flag(s_report_root, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(s_report_root, reportBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -44552,7 +44574,7 @@ static void openTraceResultPopup(const char* title, const char* body) {
lv_obj_set_size(s_trace_result_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_trace_result_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_trace_result_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_trace_result_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_trace_result_root, LV_OPA_60);
lv_obj_clear_flag(s_trace_result_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_trace_result_root, traceResultBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -44826,7 +44848,7 @@ static void openMessageActionMenu(int msg_idx) {
lv_obj_set_size(s_msg_menu_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_msg_menu_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_msg_menu_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_msg_menu_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_msg_menu_root, LV_OPA_60);
lv_obj_clear_flag(s_msg_menu_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_msg_menu_root, msgMenuBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -45015,7 +45037,7 @@ static void openMessageInfoPopup(int msg_idx) {
lv_obj_set_size(s_msg_info_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_msg_info_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_msg_info_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_msg_info_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_msg_info_root, LV_OPA_60);
lv_obj_clear_flag(s_msg_info_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_msg_info_root, msgInfoBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -46738,7 +46760,7 @@ static void openUrlQrPopup(const char* url) {
lv_obj_set_size(s_urlqr_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_urlqr_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_urlqr_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_urlqr_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_urlqr_root, LV_OPA_60);
lv_obj_clear_flag(s_urlqr_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_urlqr_root, urlQrBackdropCb, LV_EVENT_CLICKED, nullptr);
int card_w = PCW(230); if (card_w > modalAvailW()) card_w = modalAvailW();
@@ -46825,7 +46847,7 @@ static void openUrlMenu(const char* url) {
lv_obj_set_size(s_urlmenu_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_urlmenu_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_urlmenu_root, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_urlmenu_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_urlmenu_root, LV_OPA_60);
lv_obj_clear_flag(s_urlmenu_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_urlmenu_root, urlMenuBackdropCb, LV_EVENT_CLICKED, nullptr);
const int card_w = PCW(230), btn_h = PSC(34), pad = PSC(12), gap = PSC(8), url_h = PSC(18);
@@ -47188,7 +47210,7 @@ static void openChatLinkPicker(const char* text, ChatLinkKind kind) {
lv_obj_remove_style_all(s_chat_link_picker);
lv_obj_set_size(s_chat_link_picker, sw, sh);
lv_obj_set_style_bg_color(s_chat_link_picker, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_chat_link_picker, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_chat_link_picker, LV_OPA_60);
lv_obj_add_flag(s_chat_link_picker, LV_OBJ_FLAG_CLICKABLE);
lv_obj_clear_flag(s_chat_link_picker, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_chat_link_picker, chatLinkPickerBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -49986,7 +50008,7 @@ static bool pagerEncoderEdgeScroll(bool up) {
lv_coord_t step = lv_obj_get_content_height(sc) * 2 / 3;
if (step < 24) step = 24;
if (step > room) step = room;
lv_obj_scroll_by(sc, 0, up ? step : -step, LV_ANIM_ON);
lv_obj_scroll_by(sc, 0, up ? step : -step, uiAnimOn());
return true;
}
return false;
@@ -50017,7 +50039,7 @@ static bool pagerEncoderScrollOversizedFocused(bool up) {
lv_coord_t step = view_h * 2 / 3;
if (step < 24) step = 24;
if (step > room) step = room;
lv_obj_scroll_by(scroller, 0, up ? step : -step, LV_ANIM_ON);
lv_obj_scroll_by(scroller, 0, up ? step : -step, uiAnimOn());
return true;
}
return false;
@@ -50630,11 +50652,11 @@ static bool pagerModifierKnob(int delta, bool held) {
s_click_was = held;
if (s_owned) { // a click that began here: keep it until it is let go
if (!held) s_owned = false;
if (s_keyhelp && delta) lv_obj_scroll_by_bounded(s_keyhelp, 0, -delta * 40, LV_ANIM_ON);
if (s_keyhelp && delta) lv_obj_scroll_by_bounded(s_keyhelp, 0, -delta * 40, uiAnimOn());
return true;
}
if (s_keyhelp) {
if (delta) lv_obj_scroll_by_bounded(s_keyhelp, 0, -delta * 40, LV_ANIM_ON);
if (delta) lv_obj_scroll_by_bounded(s_keyhelp, 0, -delta * 40, uiAnimOn());
if (press) { pagerKeyHelpClose(); s_owned = true; }
return true;
}
@@ -52110,7 +52132,7 @@ static void lockscreenShow() {
lockscreenUpdateActivity();
lockscreenUpdateUnread();
lockscreenUpdateBattery();
if (!paper) s_lock_anim = lv_timer_create(lockAnimCb, 40, nullptr);
if (!paper && !s_ui_muted) s_lock_anim = lv_timer_create(lockAnimCb, 40, nullptr);
}
static void lockscreenHide() {
@@ -52577,10 +52599,10 @@ static void bgTheme() {
s_aur_on = s_glass_on = false;
// Glass tiles off: the background stays, but every card, Home widget and control panel
// tile is the solid panel colour, as before the aurora (ljh08ralith liked that look).
s_glass_tiles = touchPrefsGetGlassTiles();
s_glass_tiles = touchPrefsGetGlassTiles() && !s_ui_muted;
#if !defined(HAS_TDECK_PRO)
if (s_theme_high_contrast) return;
s_bg_kind = touchPrefsGetBackground();
s_bg_kind = s_ui_muted ? TOUCH_BG_NONE : touchPrefsGetBackground();
#if defined(DOC_CAPTURE) && defined(DOC_BG)
s_bg_kind = DOC_BG; // capture builds: a background without touching the setting
#endif
@@ -57308,7 +57330,7 @@ static void openControlCenter() {
// ESP32 (no GPU; a per-frame gaussian would wreck the framerate), so instead heavily mute
// the screen behind the translucent card — that keeps the panel's own content crisp/readable
// while the card fill stays see-through enough to still read as glass.
lv_obj_set_style_bg_opa(s_cc_root, LV_OPA_70, LV_PART_MAIN);
styleScrim(s_cc_root, LV_OPA_70);
lv_obj_clear_flag(s_cc_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_move_foreground(s_cc_root);
lv_obj_add_event_cb(s_cc_root, ccBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -60055,6 +60077,7 @@ static void addAppTile(lv_obj_t* parent, int x, int y, int w, int h,
lv_obj_set_style_bg_color(dot, lv_color_hex(COLOR_STATUS_WARN), LV_PART_MAIN);
lv_obj_set_style_bg_opa(dot, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_align(dot, LV_ALIGN_TOP_RIGHT, -SC(4), SC(4));
if (s_ui_muted) return; // a steady dot, no breathing
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, dot);
@@ -60215,7 +60238,7 @@ static void openAppGridSheet() {
lv_obj_remove_style_all(s_appgrid_sheet);
lv_obj_set_size(s_appgrid_sheet, sw, sh);
lv_obj_set_style_bg_color(s_appgrid_sheet, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_appgrid_sheet, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_appgrid_sheet, LV_OPA_60);
lv_obj_add_flag(s_appgrid_sheet, LV_OBJ_FLAG_CLICKABLE);
lv_obj_clear_flag(s_appgrid_sheet, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_appgrid_sheet, appGridBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -61397,7 +61420,7 @@ static void buildGlobalStatusBar() {
lv_obj_set_size(g_statusbar.dim, lv_disp_get_hor_res(nullptr), STATUSBAR_H * 2);
lv_obj_set_pos(g_statusbar.dim, 0, 0);
lv_obj_set_style_bg_color(g_statusbar.dim, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(g_statusbar.dim, LV_OPA_50, LV_PART_MAIN);
lv_obj_set_style_bg_opa(g_statusbar.dim, s_ui_muted ? LV_OPA_TRANSP : LV_OPA_50, LV_PART_MAIN); // muted: the bar stays readable
lv_obj_clear_flag(g_statusbar.dim, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_flag(g_statusbar.dim, LV_OBJ_FLAG_CLICKABLE); // swallow bar taps behind a modal
lv_obj_add_flag(g_statusbar.dim, LV_OBJ_FLAG_HIDDEN);
@@ -65154,7 +65177,7 @@ static void hwAdvertTap(int i, lv_event_t*) {
const bool flood = hwR(i).opt == 1;
const bool ok = flood ? g_lv.task->sendAdvertFlood() : g_lv.task->sendAdvertNow();
g_lv.task->showAlert(ok ? (flood ? TR("Advert sent across the mesh") : TR("Advert sent")) : TR("Advert failed"), 1200);
if (!ok || kHwEpaper) return;
if (!ok || kHwEpaper || s_ui_muted) return;
lv_obj_t* b = hwI(i).box;
lv_obj_set_style_outline_color(b, lv_color_hex(COLOR_GLOW), LV_PART_MAIN);
lv_obj_set_style_outline_pad(b, 0, LV_PART_MAIN);
@@ -66134,10 +66157,12 @@ static void hwRadarDrawCb(lv_event_t* e) {
const uint32_t ms = millis();
// A couple of pixels of drift on slow cycles, so the rings never sit still either.
const double kT = 2.0 * 3.14159265358979;
const int dx = (int)lround(2.0 * sin((ms % 1380000u) / 1380000.0 * kT));
const int dy = (int)lround(2.0 * cos((ms % 1020000u) / 1020000.0 * kT));
// Muted: a still plot, no drift, turn or beam.
const bool still = s_ui_muted;
const int dx = still ? 0 : (int)lround(2.0 * sin((ms % 1380000u) / 1380000.0 * kT));
const int dy = still ? 0 : (int)lround(2.0 * cos((ms % 1020000u) / 1020000.0 * kT));
const lv_point_t c = { (lv_coord_t)(a.x1 + w / 2 + dx), (lv_coord_t)(a.y1 + h / 2 + dy) };
const int turn = (int)((ms / 5000u) % 720u) / 2; // half a degree every 5 s
const int turn = still ? 0 : (int)((ms / 5000u) % 720u) / 2; // half a degree every 5 s
const int beam = (int)((ms % 6000u) * 360u / 6000u); // one sweep in 6 s
lv_draw_arc_dsc_t ad;
lv_draw_arc_dsc_init(&ad);
@@ -66151,7 +66176,7 @@ static void hwRadarDrawCb(lv_event_t* e) {
lv_draw_line_dsc_init(&ld);
ld.color = lv_color_hex(COLOR_GLOW);
ld.width = 2;
for (int t = 0; t < 8; ++t) {
for (int t = 0; t < (still ? 0 : 8); ++t) {
const int ang = beam - t * 5;
ld.opa = (lv_opa_t)(220 - t * 26);
const lv_point_t p = { (lv_coord_t)(c.x + R * sin(ang * k)), (lv_coord_t)(c.y - R * cos(ang * k)) };
@@ -66168,7 +66193,7 @@ static void hwRadarDrawCb(lv_event_t* e) {
const int x = c.x + (int)(rr * sin(ang * k)), y = c.y - (int)(rr * cos(ang * k));
int diff = (beam - ang) % 360;
if (diff < 0) diff += 360;
const bool lit = diff < 40; // the beam just passed it
const bool lit = !still && diff < 40; // the beam just passed it
const int dot = (nd.level >= 2 ? 3 : 2) + (lit ? 1 : 0);
lv_area_t d = { (lv_coord_t)(x - dot), (lv_coord_t)(y - dot), (lv_coord_t)(x + dot), (lv_coord_t)(y + dot) };
rd.bg_color = lv_color_hex(nd.kind == ADV_TYPE_REPEATER ? COLOR_HUE[HUE_RADIO]
@@ -66199,7 +66224,7 @@ static void hwRadarBuild(int i) {
w.l[2] = hwLabel(w.box, &g_font_12, COLOR_SUB); // how many
lv_obj_align(w.l[2], LV_ALIGN_BOTTOM_RIGHT, 0, 0);
hwRadarNodes();
if (!s_hw_radar_timer) s_hw_radar_timer = lv_timer_create(hwRadarTimerCb, 100, nullptr);
if (!s_hw_radar_timer && !s_ui_muted) s_hw_radar_timer = lv_timer_create(hwRadarTimerCb, 100, nullptr);
}
static void hwRadarUpdate(int i) {
HwInst& w = hwI(i);
@@ -66481,7 +66506,7 @@ static void hwPickBuild() {
lv_obj_remove_style_all(s_hw_pick_root);
lv_obj_set_size(s_hw_pick_root, sw, sh);
lv_obj_set_style_bg_color(s_hw_pick_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_hw_pick_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_hw_pick_root, LV_OPA_60);
lv_obj_add_flag(s_hw_pick_root, LV_OBJ_FLAG_CLICKABLE);
lv_obj_clear_flag(s_hw_pick_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_hw_pick_root, hwPickBackdropCb, LV_EVENT_CLICKED, nullptr);
@@ -68435,6 +68460,37 @@ static void themeTokensFor(uint8_t mode, uint32_t accent, bool more, uint8_t sty
lookAdjust(t, day, more && !hc, style);
}
// Mute colours: a slate accent in place of the picked one, and every hue pulled most
// of the way to grey. Status colours keep enough of theirs to still read as state.
static constexpr uint32_t kMutedAccent = 0x5F6B73;
static constexpr uint8_t kMuteHue = 190, kMuteInfo = 150, kMuteWarn = 110, kMuteDanger = 90,
kMuteSent = 200, kMuteMention = 170;
static uint32_t mutedHue(uint32_t c) { return rgbDesat(c, kMuteHue); }
static void applyMutedLook() {
for (uint32_t& h : COLOR_HUE) h = mutedHue(h);
COLOR_LINK = mutedHue(COLOR_LINK);
COLOR_MENTION = rgbDesat(COLOR_MENTION, kMuteInfo);
COLOR_CHAT_LINK = rgbDesat(COLOR_CHAT_LINK, kMuteWarn);
COLOR_STATUS_INFO = rgbDesat(COLOR_STATUS_INFO, kMuteInfo);
COLOR_STATUS_WARN = rgbDesat(COLOR_STATUS_WARN, kMuteWarn);
COLOR_STATUS_WARN_TEXT = rgbDesat(COLOR_STATUS_WARN_TEXT, kMuteWarn);
COLOR_STATUS_DANGER = rgbDesat(COLOR_STATUS_DANGER, kMuteDanger);
COLOR_STATUS_DANGER_PRESSED = rgbDesat(COLOR_STATUS_DANGER_PRESSED, kMuteDanger);
COLOR_STATUS_DANGER_TEXT = rgbDesat(COLOR_STATUS_DANGER_TEXT, kMuteDanger);
COLOR_SENT_BG = COLOR_CHAT_SENT_BG = rgbDesat(COLOR_CHAT_SENT_BG, kMuteSent);
COLOR_MENTION_BG = COLOR_CHAT_MENTION_BG = rgbDesat(COLOR_CHAT_MENTION_BG, kMuteMention);
themeStylesInvalidate();
}
// The same on the Theme page's palette copy, for its preview.
static void themeTokensMute(ThemeTokens& t) {
for (uint32_t& h : t.hue) h = mutedHue(h);
t.link = mutedHue(t.link);
t.info = rgbDesat(t.info, kMuteInfo);
t.warn = rgbDesat(t.warn, kMuteWarn);
t.sent_bg = rgbDesat(t.sent_bg, kMuteSent);
t.mention_bg = rgbDesat(t.mention_bg, kMuteMention);
}
// Everything colour, in boot order: the mode, the accent, then the look.
static void applyBootTheme() {
#if defined(HAS_TDECK_PRO)
@@ -68464,9 +68520,16 @@ static void applyBootTheme() {
bgTheme();
return;
#else
s_ui_muted = touchPrefsGetMuted();
applyThemeMode(touchPrefsGetThemeMode());
applyAccent(touchPrefsGetAccentColor());
applyColorLook(touchPrefsGetMoreColors(), touchPrefsGetColorStyle(), touchPrefsGetRainbow());
if (s_ui_muted && !s_theme_high_contrast) { // high contrast keeps its own colours
applyAccent(kMutedAccent);
applyColorLook(false, TOUCH_LOOK_REGULAR, false);
applyMutedLook();
} else {
applyAccent(touchPrefsGetAccentColor());
applyColorLook(touchPrefsGetMoreColors(), touchPrefsGetColorStyle(), touchPrefsGetRainbow());
}
#endif
s_chat_icons_initials = touchPrefsGetChatIcons() != 0;
bgTheme(); // last: it may change the background colour
@@ -68543,6 +68606,7 @@ static void touchThemeApplyCb(lv_theme_t* /*th*/, lv_obj_t* obj) {
lv_obj_add_style(obj, &s_ts.sw_on, LV_PART_INDICATOR | LV_STATE_CHECKED);
lv_obj_add_style(obj, &s_ts.sw_knob, LV_PART_KNOB);
lv_obj_add_style(obj, &s_ts.sw_knob_on, LV_PART_KNOB | LV_STATE_CHECKED);
if (s_ui_muted) lv_obj_set_style_anim_time(obj, 0, LV_PART_MAIN); // the knob jumps
} else if (lv_obj_check_type(obj, &lv_textarea_class)) {
lv_obj_add_style(obj, &s_ts.field, LV_PART_MAIN);
lv_obj_add_style(obj, &s_ts.field_focus, LV_PART_MAIN | LV_STATE_FOCUSED);
@@ -68614,6 +68678,7 @@ struct ThemeChoice {
uint8_t bg_kind; uint32_t bg_col; char bg_img[TOUCH_LOCK_WALLPAPER_MAXLEN]; // Background
bool glass; // Glass tiles
uint8_t bg_dim; // Picture dimming (TOUCH_DIM_*)
bool mute; // Mute colours and animations
};
static ThemeChoice s_theme_saved = {}, s_theme_pend = {};
static constexpr int kThemeColorN = (int)(sizeof(kThemeColors) / sizeof(kThemeColors[0]));
@@ -68632,7 +68697,7 @@ struct ThemePageUi {
lv_obj_t* mode_dot[2]; lv_obj_t* mode_ic[2]; lv_obj_t* mode_lbl[2];
lv_obj_t* hc_sw;
lv_obj_t* swatch[kThemeColorN]; lv_obj_t* custom; lv_obj_t* custom_dot; lv_obj_t* accent_note;
lv_obj_t* more_sw; lv_obj_t* style[3]; lv_obj_t* style_dot[3][3]; lv_obj_t* rainbow_sw; lv_obj_t* colour_note;
lv_obj_t* mute_sw; lv_obj_t* more_sw; lv_obj_t* style[3]; lv_obj_t* style_dot[3][3]; lv_obj_t* rainbow_sw; lv_obj_t* colour_note;
lv_obj_t* bg[5]; lv_obj_t* bg_sw[5]; lv_obj_t* bg_col_btn; lv_obj_t* bg_col_dot;
lv_obj_t* bg_img_btn; lv_obj_t* bg_img_lbl; lv_obj_t* bg_note; lv_obj_t* glass_sw;
lv_obj_t* bg_dim_box; lv_obj_t* bg_dim_row; // Picture dimming, under the picture's button
@@ -68872,12 +68937,23 @@ static bool themePendingDiffers() {
return a.mode != b.mode || a.accent != b.accent || a.more != b.more ||
a.style != b.style || a.rainbow != b.rainbow || a.bg_kind != b.bg_kind ||
a.bg_col != b.bg_col || strcmp(a.bg_img, b.bg_img) != 0 || a.glass != b.glass ||
a.bg_dim != b.bg_dim;
a.bg_dim != b.bg_dim || a.mute != b.mute;
}
// Mute colours and animations fixes the accent, the look and the background (high
// contrast fixes them too); the page keeps the other choices for when it is off.
static bool themeLooksLocked() { return s_theme_pend.mute || themeModeIsHc(s_theme_pend.mode); }
static uint32_t themePendAccent() {
return s_theme_pend.mute && !themeModeIsHc(s_theme_pend.mode) ? kMutedAccent : s_theme_pend.accent;
}
// The palette copy for the preview in the pending look, muted when that is picked.
static void themeTokensPend(uint8_t mode, bool more, uint8_t style, ThemeTokens& t) {
themeTokensFor(mode, themePendAccent(), more, style, t);
if (s_theme_pend.mute && !themeModeIsHc(mode)) themeTokensMute(t);
}
// MORE COLORS! as the pending choice has it: Taste the rainbow brings it along, and
// high contrast keeps its own fixed colours.
static bool themePendMore() {
return (s_theme_pend.more || s_theme_pend.rainbow) && !themeModeIsHc(s_theme_pend.mode);
return (s_theme_pend.more || s_theme_pend.rainbow) && !themeLooksLocked();
}
// A choice tile (mode, style, chat icons): the picked one ringed in the glow on a faint
@@ -68908,9 +68984,9 @@ static void themePreviewPaint() {
const bool day = themeModeIsDay(mode), hc = themeModeIsHc(mode);
const bool more = themePendMore();
const bool neon = more && style == TOUCH_LOOK_NEON;
const bool rainbow = s_theme_pend.rainbow && !hc;
const bool rainbow = s_theme_pend.rainbow && !themeLooksLocked();
ThemeTokens t;
themeTokensFor(mode, s_theme_pend.accent, more, style, t);
themeTokensPend(mode, more, style, t);
lv_obj_set_style_bg_color(s_tp.frame, lv_color_hex(t.bg), LV_PART_MAIN);
lv_obj_set_style_border_color(s_tp.frame, lv_color_hex(hc ? t.text : t.border), LV_PART_MAIN);
@@ -69201,7 +69277,7 @@ static void themePageRepaint() {
for (int d = 0; d < 2; ++d) {
if (!s_tp.mode[d]) continue;
ThemeTokens mt;
themeTokensFor(themeModeOf(d == 1, hc), s_theme_pend.accent, more, s_theme_pend.style, mt);
themeTokensPend(themeModeOf(d == 1, hc), more, s_theme_pend.style, mt);
lv_obj_set_style_bg_color(s_tp.mode_sky[d], lv_color_hex(mt.bg), LV_PART_MAIN);
lv_obj_set_style_border_color(s_tp.mode_sky[d], lv_color_hex(hc ? mt.text : mt.border), LV_PART_MAIN);
lv_obj_set_style_bg_color(s_tp.mode_card[d], lv_color_hex(mt.panel), LV_PART_MAIN);
@@ -69214,6 +69290,9 @@ static void themePageRepaint() {
lv_obj_set_style_text_font(s_tp.mode_lbl[d], on ? &g_font_semi_14 : &g_font_14, LV_PART_MAIN);
}
themeSwitchSet(s_tp.hc_sw, hc, true);
const bool mute = s_theme_pend.mute, locked = themeLooksLocked();
const char* lock_note = hc ? TR("High contrast keeps its own fixed colours.")
: TR("Mute colours and animations sets these for now.");
bool listed = false;
for (int i = 0; i < kThemeColorN; ++i) {
@@ -69222,18 +69301,20 @@ static void themePageRepaint() {
const bool on = kThemeColors[i] == s_theme_pend.accent;
listed |= on;
lv_obj_set_style_outline_width(sw, on ? 2 : 0, LV_PART_MAIN);
lv_obj_set_style_opa(sw, hc ? LV_OPA_40 : LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_opa(sw, locked ? LV_OPA_40 : LV_OPA_COVER, LV_PART_MAIN);
}
if (s_tp.custom) {
themeChoiceStyle(s_tp.custom, !listed, !hc);
themeChoiceStyle(s_tp.custom, !listed, !locked);
lv_obj_set_style_bg_color(s_tp.custom_dot, lv_color_hex(listed ? COLOR_SUB : s_theme_pend.accent), LV_PART_MAIN);
}
if (s_tp.accent_note) {
if (hc) lv_obj_clear_flag(s_tp.accent_note, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.accent_note, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(s_tp.accent_note, lock_note);
if (locked) lv_obj_clear_flag(s_tp.accent_note, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.accent_note, LV_OBJ_FLAG_HIDDEN);
}
themeSwitchSet(s_tp.more_sw, more, !hc);
themeSwitchSet(s_tp.mute_sw, mute, true);
themeSwitchSet(s_tp.more_sw, more, !locked);
for (int i = 0; i < 3; ++i) {
if (!s_tp.style[i]) continue;
themeChoiceStyle(s_tp.style[i], more && s_theme_pend.style == i, more);
@@ -69246,16 +69327,17 @@ static void themePageRepaint() {
lv_obj_set_style_shadow_color(s_tp.style_dot[i][k], lv_color_hex(dots[k]), LV_PART_MAIN);
}
}
themeSwitchSet(s_tp.rainbow_sw, s_theme_pend.rainbow && !hc, !hc);
themeSwitchSet(s_tp.rainbow_sw, s_theme_pend.rainbow && !locked, !locked);
// Background: the picked tile, its little pictures in the pending look, and the
// colour's or the picture's own button under the tiles.
{
ThemeTokens bt;
themeTokensFor(mode, s_theme_pend.accent, more, s_theme_pend.style, bt);
themeTokensPend(mode, more, s_theme_pend.style, bt);
const uint32_t col = s_theme_pend.bg_col == 0xFFFFFFFFu ? bt.glow : s_theme_pend.bg_col;
for (int i = 0; i < 5; ++i) {
if (!s_tp.bg[i]) continue;
themeChoiceStyle(s_tp.bg[i], !hc && s_theme_pend.bg_kind == i, !hc);
const uint8_t kind = mute ? TOUCH_BG_NONE : s_theme_pend.bg_kind; // muted: the plain theme
themeChoiceStyle(s_tp.bg[i], !hc && kind == i, !locked);
lv_obj_t* sw = s_tp.bg_sw[i];
if (i == TOUCH_BG_COLOR || i == TOUCH_BG_NONE) {
lv_obj_set_style_bg_color(sw, lv_color_hex(i == TOUCH_BG_NONE ? bt.bg : bgSafeColor(col, day)), LV_PART_MAIN);
@@ -69271,32 +69353,34 @@ static void themePageRepaint() {
}
}
if (s_tp.bg_col_btn) {
if (!hc && s_theme_pend.bg_kind == TOUCH_BG_COLOR) lv_obj_clear_flag(s_tp.bg_col_btn, LV_OBJ_FLAG_HIDDEN);
if (!locked && s_theme_pend.bg_kind == TOUCH_BG_COLOR) lv_obj_clear_flag(s_tp.bg_col_btn, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.bg_col_btn, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_style_bg_color(s_tp.bg_col_dot, lv_color_hex(bgSafeColor(col, day)), LV_PART_MAIN);
}
if (s_tp.bg_img_btn) {
if (!hc && s_theme_pend.bg_kind == TOUCH_BG_IMAGE) lv_obj_clear_flag(s_tp.bg_img_btn, LV_OBJ_FLAG_HIDDEN);
if (!locked && s_theme_pend.bg_kind == TOUCH_BG_IMAGE) lv_obj_clear_flag(s_tp.bg_img_btn, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.bg_img_btn, LV_OBJ_FLAG_HIDDEN);
const char* base = strrchr(s_theme_pend.bg_img, '/');
base = base ? base + 1 : (strncmp(s_theme_pend.bg_img, "sd:", 3) ? s_theme_pend.bg_img : s_theme_pend.bg_img + 3);
lv_label_set_text(s_tp.bg_img_lbl, base && base[0] ? base : TR("Choose an image"));
}
if (s_tp.bg_dim_box) { // only with a picture to dim
if (!hc && s_theme_pend.bg_kind == TOUCH_BG_IMAGE) lv_obj_clear_flag(s_tp.bg_dim_box, LV_OBJ_FLAG_HIDDEN);
if (!locked && s_theme_pend.bg_kind == TOUCH_BG_IMAGE) lv_obj_clear_flag(s_tp.bg_dim_box, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.bg_dim_box, LV_OBJ_FLAG_HIDDEN);
setChoicePick(s_tp.bg_dim_row, s_theme_pend.bg_dim);
}
// Glass tiles: nothing to see through in high contrast or on the plain theme.
themeSwitchSet(s_tp.glass_sw, s_theme_pend.glass, !hc && s_theme_pend.bg_kind != TOUCH_BG_NONE);
themeSwitchSet(s_tp.glass_sw, s_theme_pend.glass && !mute, !locked && s_theme_pend.bg_kind != TOUCH_BG_NONE);
if (s_tp.bg_note) {
if (hc) lv_obj_clear_flag(s_tp.bg_note, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.bg_note, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(s_tp.bg_note, lock_note);
if (locked) lv_obj_clear_flag(s_tp.bg_note, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.bg_note, LV_OBJ_FLAG_HIDDEN);
}
}
if (s_tp.colour_note) {
if (hc) lv_obj_clear_flag(s_tp.colour_note, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.colour_note, LV_OBJ_FLAG_HIDDEN);
lv_label_set_text(s_tp.colour_note, lock_note);
if (locked) lv_obj_clear_flag(s_tp.colour_note, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(s_tp.colour_note, LV_OBJ_FLAG_HIDDEN);
}
#endif
for (int i = 0; i < 2; ++i) themeChoiceStyle(s_tp.icons[i], (i == 1) == s_chat_icons_initials, true);
@@ -69328,14 +69412,19 @@ static void themeHcCb(lv_event_t* e) {
themePageRepaint();
}
static void themeSwatchCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeModeIsHc(s_theme_pend.mode)) return;
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeLooksLocked()) return;
s_theme_pend.accent = (uint32_t)(uintptr_t)lv_event_get_user_data(e);
themePageRepaint();
}
static void themeCustomCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeModeIsHc(s_theme_pend.mode)) return;
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeLooksLocked()) return;
openAccentPicker();
}
static void themeMuteCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_VALUE_CHANGED) return;
s_theme_pend.mute = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
themePageRepaint();
}
static void themeMoreCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_VALUE_CHANGED) return;
const bool on = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
@@ -69382,14 +69471,14 @@ static void themeBgImagePicked(const char* path) {
themePageRepaint();
}
static void themeBgKindCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeModeIsHc(s_theme_pend.mode)) return;
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeLooksLocked()) return;
const uint8_t k = (uint8_t)(uintptr_t)lv_event_get_user_data(e);
if (k == TOUCH_BG_IMAGE && !s_theme_pend.bg_img[0]) { themeBgPickImage(); return; } // no picture yet: choose one
s_theme_pend.bg_kind = k;
themePageRepaint();
}
static void themeBgColorCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeModeIsHc(s_theme_pend.mode)) return;
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeLooksLocked()) return;
s_picker_for_bg = true;
openAccentPicker();
}
@@ -69399,10 +69488,10 @@ static void themeGlassCb(lv_event_t* e) {
themePageRepaint();
}
static void themeBgImageCb(lv_event_t* e) {
if (lv_event_get_code(e) == LV_EVENT_CLICKED && !themeModeIsHc(s_theme_pend.mode)) themeBgPickImage();
if (lv_event_get_code(e) == LV_EVENT_CLICKED && !themeLooksLocked()) themeBgPickImage();
}
static void themeBgDimCb(lv_event_t* e) {
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeModeIsHc(s_theme_pend.mode)) return;
if (lv_event_get_code(e) != LV_EVENT_CLICKED || themeLooksLocked()) return;
s_theme_pend.bg_dim = (uint8_t)setChoiceIndex(e);
themePageRepaint();
}
@@ -69443,6 +69532,7 @@ static void themeApplyCb(lv_event_t* e) {
touchPrefsSetBackgroundImage(s_theme_pend.bg_img);
touchPrefsSetGlassTiles(s_theme_pend.glass);
touchPrefsSetBackgroundDim(s_theme_pend.bg_dim);
touchPrefsSetMuted(s_theme_pend.mute);
#endif
s_theme_saved = s_theme_pend;
lv_obj_add_flag(lv_event_get_target(e), LV_OBJ_FLAG_HIDDEN); // one tap; the restart follows
@@ -69455,7 +69545,7 @@ static void themePageDeleteCb(lv_event_t* e) {
#if !defined(HAS_TDECK_PRO)
// Up to the preview box again (the bar's dots).
static void themeMiniDotsCb(lv_event_t* e) {
if (lv_event_get_code(e) == LV_EVENT_CLICKED && s_tp.page) lv_obj_scroll_to_y(s_tp.page, 0, LV_ANIM_ON);
if (lv_event_get_code(e) == LV_EVENT_CLICKED && s_tp.page) lv_obj_scroll_to_y(s_tp.page, 0, uiAnimOn());
}
// The bar under the title: Apply and restart, beside six dots in the picked look. It
// sits over the top of the page, opaque, so the rows scroll under it.
@@ -69643,6 +69733,7 @@ static void buildThemeSettings() {
touchPrefsGetBackgroundImage(s_theme_saved.bg_img, sizeof s_theme_saved.bg_img);
s_theme_saved.glass = touchPrefsGetGlassTiles();
s_theme_saved.bg_dim = touchPrefsGetBackgroundDim();
s_theme_saved.mute = touchPrefsGetMuted();
s_theme_pend = s_theme_saved;
const lv_coord_t sw = lv_disp_get_hor_res(nullptr);
const lv_coord_t card_w = sw - 22; // as createSettingsModal's cards
@@ -69784,10 +69875,15 @@ static void buildThemeSettings() {
s_tp.accent_note = themeNote(c, cw, "High contrast keeps its own fixed colours.");
}
// Colour: MORE COLORS! with its style right under it, then Taste the rainbow.
// Colour: Mute colours and animations first, then MORE COLORS! with its style right
// under it, then Taste the rainbow.
{
lv_obj_t* c = themeSection("Colour");
const lv_coord_t cw = s_settings_content_w;
s_tp.mute_sw = themeSwitchRow(c, cw, "Mute colours and animations",
"Nothing moves, no boot animation, quiet colours and solid panels. "
"Your other colour choices come back when it is off.",
s_theme_pend.mute, themeMuteCb);
s_tp.more_sw = themeSwitchRow(c, cw, "MORE COLORS!",
"A colour for every section, coloured status icons, names and glyphs in their own hue.",
themePendMore(), themeMoreCb);
@@ -71680,7 +71776,7 @@ static void buildUiTree() {
if (g_lv.tabview) lv_tabview_set_act(g_lv.tabview, saved_tab, LV_ANIM_OFF);
s_lv_tab_prev = static_cast<int>(saved_tab);
if (g_lv.task) g_lv.task->onLvTabChanged(static_cast<int>(saved_tab));
buildBootSplash();
if (!s_ui_muted) buildBootSplash(); // muted: straight to the UI, no animated logo
pushDiagLine("UI ready");
}
#endif // HAS_TOUCH_UI
@@ -72109,7 +72205,7 @@ static void openTelemetryWindow(const uint8_t* key6, const char* name, int state
lv_obj_set_size(s_telemetry_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_telemetry_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_telemetry_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_telemetry_root, LV_OPA_50, LV_PART_MAIN);
styleScrim(s_telemetry_root, LV_OPA_50);
lv_obj_clear_flag(s_telemetry_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_telemetry_root, telemetryWindowDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -72362,7 +72458,7 @@ static void openTelemetryConfigWindow() {
lv_obj_set_size(s_telem_config_root, sw, sh - STATUSBAR_H);
lv_obj_set_pos(s_telem_config_root, 0, STATUSBAR_H);
lv_obj_set_style_bg_color(s_telem_config_root, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(s_telem_config_root, LV_OPA_60, LV_PART_MAIN);
styleScrim(s_telem_config_root, LV_OPA_60);
lv_obj_clear_flag(s_telem_config_root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_event_cb(s_telem_config_root, telemCfgDismissCb, LV_EVENT_CLICKED, nullptr);
@@ -79739,6 +79835,7 @@ static void ssaverStart(uint32_t now, bool preview) {
#if CAP_SSAVER_NORTH_LOCK
th.north_lock = s_ssaver_north_lock;
#endif
th.calm = s_ui_muted;
if (s_look_rainbow) { // every node in its own hue, in the look's strength (as lookRainbow)
th.node_sat = lookNeon() ? 100 : lookPastel() ? 36 : s_theme_day ? 80 : 72;
th.node_val = lookNeon() || lookPastel() ? 100 : s_theme_day ? 72 : 96;
@@ -80042,7 +80139,7 @@ static void pinShakeExec(void* var, int32_t v) {
lv_obj_set_style_translate_x(static_cast<lv_obj_t*>(var), (lv_coord_t)v, LV_PART_MAIN);
}
static void pinShake() {
if (!s_pin_row) return;
if (!s_pin_row || s_ui_muted) return;
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, s_pin_row);
@@ -80316,7 +80413,7 @@ static void pinWarnSelect(int i, bool show) {
else lv_obj_clear_state(s_pin_warn_btn[k], LV_STATE_CHECKED);
}
// Big text on a short panel can put the answers below the edge: bring the lit one in.
if (show && s_pin_warn_btn[s_pin_warn_sel]) lv_obj_scroll_to_view_recursive(s_pin_warn_btn[s_pin_warn_sel], LV_ANIM_ON);
if (show && s_pin_warn_btn[s_pin_warn_sel]) lv_obj_scroll_to_view_recursive(s_pin_warn_btn[s_pin_warn_sel], uiAnimOn());
#else
(void)show;
#endif
@@ -80854,7 +80951,7 @@ static void atGlanceAnim(lv_obj_t* o, lv_anim_exec_xcb_t cb, int32_t from, int32
lv_anim_set_var(&a, o);
lv_anim_set_exec_cb(&a, cb);
lv_anim_set_values(&a, from, to);
lv_anim_set_time(&a, ms);
lv_anim_set_time(&a, uiAnimMs(ms));
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
lv_anim_start(&a);
}
@@ -84820,6 +84917,9 @@ static void docLookAudit() {
lv_obj_scroll_by(s_tp.page, 0, -SC(170), LV_ANIM_OFF); auditShot("look_theme_pending_rb_scrolled");
lv_obj_scroll_to_y(s_tp.page, 0, LV_ANIM_OFF);
s_theme_pend = s_theme_saved;
s_theme_pend.mute = true;
themePageRepaint(); auditShot("look_theme_pending_mute");
s_theme_pend = s_theme_saved;
themePageRepaint();
}
closeSettingsCategory(); docSettle(6);
+2
View File
@@ -85,8 +85,10 @@ int main(int argc, char** argv) {
&lv_font_montserrat_12, &ui_semibold_12};
// CST_UPTIME_MS: how long the device has been up, which sets how far the slow turn
// has gone (it follows the time since boot). CST_NORTH_LOCK=1: Keep north up (#706).
// CST_CALM=1: nothing moves.
if (const char* up = getenv("CST_UPTIME_MS")) lv_tick_inc((uint32_t)strtoul(up, nullptr, 10));
th.north_lock = getenv("CST_NORTH_LOCK") && getenv("CST_NORTH_LOCK")[0] == '1';
th.calm = getenv("CST_CALM") && getenv("CST_CALM")[0] == '1'; // Mute colours and animations (#798)
cstShow(lv_layer_top(), th);
// Index: 0 repeater (direct) 1 repeater (via 0)