diff --git a/deploy/apps/lang/bg.lang b/deploy/apps/lang/bg.lang index 0225a4dc..ac2d9003 100644 --- a/deploy/apps/lang/bg.lang +++ b/deploy/apps/lang/bg.lang @@ -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. diff --git a/deploy/apps/lang/cs.lang b/deploy/apps/lang/cs.lang index d5426140..2063f1e5 100644 --- a/deploy/apps/lang/cs.lang +++ b/deploy/apps/lang/cs.lang @@ -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. diff --git a/deploy/apps/lang/de.lang b/deploy/apps/lang/de.lang index e51fbfb1..44995a20 100644 --- a/deploy/apps/lang/de.lang +++ b/deploy/apps/lang/de.lang @@ -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. diff --git a/deploy/apps/lang/el.lang b/deploy/apps/lang/el.lang index e1a2c323..bc59d555 100644 --- a/deploy/apps/lang/el.lang +++ b/deploy/apps/lang/el.lang @@ -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. diff --git a/deploy/apps/lang/es.lang b/deploy/apps/lang/es.lang index 7e6bf08a..a53b37e0 100644 --- a/deploy/apps/lang/es.lang +++ b/deploy/apps/lang/es.lang @@ -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. diff --git a/deploy/apps/lang/fr.lang b/deploy/apps/lang/fr.lang index 14c6604d..0ecd09bd 100644 --- a/deploy/apps/lang/fr.lang +++ b/deploy/apps/lang/fr.lang @@ -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. diff --git a/deploy/apps/lang/hu.lang b/deploy/apps/lang/hu.lang index 4987f4e1..3f12b0fe 100644 --- a/deploy/apps/lang/hu.lang +++ b/deploy/apps/lang/hu.lang @@ -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. diff --git a/deploy/apps/lang/it.lang b/deploy/apps/lang/it.lang index 130701d3..e84c6f1c 100644 --- a/deploy/apps/lang/it.lang +++ b/deploy/apps/lang/it.lang @@ -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. diff --git a/deploy/apps/lang/nl.lang b/deploy/apps/lang/nl.lang index b2d12ec4..3d822d7b 100644 --- a/deploy/apps/lang/nl.lang +++ b/deploy/apps/lang/nl.lang @@ -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. diff --git a/deploy/apps/lang/pl.lang b/deploy/apps/lang/pl.lang index 107ab1c9..50e35182 100644 --- a/deploy/apps/lang/pl.lang +++ b/deploy/apps/lang/pl.lang @@ -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. diff --git a/deploy/apps/lang/pt-br.lang b/deploy/apps/lang/pt-br.lang index f0a56161..b0760dcd 100644 --- a/deploy/apps/lang/pt-br.lang +++ b/deploy/apps/lang/pt-br.lang @@ -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. diff --git a/deploy/apps/lang/ro.lang b/deploy/apps/lang/ro.lang index 47907c7e..55531402 100644 --- a/deploy/apps/lang/ro.lang +++ b/deploy/apps/lang/ro.lang @@ -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. diff --git a/deploy/apps/lang/ru.lang b/deploy/apps/lang/ru.lang index 1b90d38c..52611ce5 100644 --- a/deploy/apps/lang/ru.lang +++ b/deploy/apps/lang/ru.lang @@ -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. diff --git a/deploy/apps/lang/sr.lang b/deploy/apps/lang/sr.lang index 31295ff5..d8f1d02f 100644 --- a/deploy/apps/lang/sr.lang +++ b/deploy/apps/lang/sr.lang @@ -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. diff --git a/deploy/apps/lang/uk.lang b/deploy/apps/lang/uk.lang index 0987f56f..001a837e 100644 --- a/deploy/apps/lang/uk.lang +++ b/deploy/apps/lang/uk.lang @@ -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. diff --git a/src/helpers/esp32/TouchPrefsStore.cpp b/src/helpers/esp32/TouchPrefsStore.cpp index 9e9574a2..87c9adb2 100644 --- a/src/helpers/esp32/TouchPrefsStore.cpp +++ b/src/helpers/esp32/TouchPrefsStore.cpp @@ -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; } diff --git a/src/helpers/esp32/TouchPrefsStore.h b/src/helpers/esp32/TouchPrefsStore.h index 87b96e09..99bdbb86 100644 --- a/src/helpers/esp32/TouchPrefsStore.h +++ b/src/helpers/esp32/TouchPrefsStore.h @@ -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(); diff --git a/src/ui-touch/Constellation.cpp b/src/ui-touch/Constellation.cpp index 2702990c..3cd9365e 100644 --- a/src/ui-touch/Constellation.cpp +++ b/src/ui-touch/Constellation.cpp @@ -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(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(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; } diff --git a/src/ui-touch/Constellation.h b/src/ui-touch/Constellation.h index 709a3016..d426f616 100644 --- a/src/ui-touch/Constellation.h +++ b/src/ui-touch/Constellation.h @@ -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 diff --git a/src/ui-touch/LuaAppHost.cpp b/src/ui-touch/LuaAppHost.cpp index 88b97db3..fd051a31 100644 --- a/src/ui-touch/LuaAppHost.cpp +++ b/src/ui-touch/LuaAppHost.cpp @@ -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; } diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index 80c8af65..ef88ebb8 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -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(saved_tab); if (g_lv.task) g_lv.task->onLvTabChanged(static_cast(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(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); diff --git a/test/constellation_render/render.cpp b/test/constellation_render/render.cpp index b5b0e762..c8749cb3 100644 --- a/test/constellation_render/render.cpp +++ b/test/constellation_render/render.cpp @@ -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)