From 6faca0354996d73e4f45c63accececce9067ecc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Sun, 21 Jun 2026 11:44:05 +0200 Subject: [PATCH] feat(ui): infinite wrap carousels Arrow prev/next in home and games carousels now use modular arithmetic ((cur + dir + n) % n) instead of clamping, so pressing left on the first slide jumps to the last and vice versa. Swipe still clamps at the edges (LVGL snap resists a clean programmatic jump mid-gesture); arrow-wrap is seamless. --- main/modes/games.c | 9 +++++---- main/modes/home.c | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/main/modes/games.c b/main/modes/games.c index a2e5bca..411792e 100644 --- a/main/modes/games.c +++ b/main/modes/games.c @@ -344,7 +344,9 @@ static void gdots_update(int idx) static void games_scroll_cb(lv_event_t *e) { lv_obj_t *t = lv_event_get_target(e); - int idx = (lv_obj_get_scroll_x(t) + GAMES_SLIDE_W / 2) / GAMES_SLIDE_W; + int32_t sx = lv_obj_get_scroll_x(t); + int idx = (int)((sx + GAMES_SLIDE_W / 2) / GAMES_SLIDE_W); + // Clamp for dot update; swipe past first/last will snap back naturally. if (idx < 0) idx = 0; if (idx >= GAMES_N_TILES) idx = GAMES_N_TILES - 1; s_gcur = idx; @@ -353,9 +355,8 @@ static void games_scroll_cb(lv_event_t *e) static void games_arrow_cb(lv_event_t *e) { - int idx = s_gcur + (int)(intptr_t)lv_event_get_user_data(e); - if (idx < 0) idx = 0; - if (idx >= GAMES_N_TILES) idx = GAMES_N_TILES - 1; + // Wrap-around: (cur + dir + n) % n handles both +1 and -1 cleanly. + int idx = (s_gcur + (int)(intptr_t)lv_event_get_user_data(e) + GAMES_N_TILES) % GAMES_N_TILES; s_gcur = idx; lv_obj_scroll_to_x(s_gtrack, idx * GAMES_SLIDE_W, LV_ANIM_ON); gdots_update(idx); diff --git a/main/modes/home.c b/main/modes/home.c index f77d790..d28a3a0 100644 --- a/main/modes/home.c +++ b/main/modes/home.c @@ -72,7 +72,9 @@ static void adots_update(int idx) static void home_scroll_cb(lv_event_t *e) { lv_obj_t *t = lv_event_get_target(e); - int idx = (lv_obj_get_scroll_x(t) + HOME_SLIDE_W / 2) / HOME_SLIDE_W; + int32_t sx = lv_obj_get_scroll_x(t); + int idx = (int)((sx + HOME_SLIDE_W / 2) / HOME_SLIDE_W); + // Clamp for dot update; swipe past first/last will snap back naturally. if (idx < 0) idx = 0; if (idx >= s_n_acts) idx = s_n_acts - 1; s_acur = idx; @@ -81,9 +83,8 @@ static void home_scroll_cb(lv_event_t *e) static void home_arrow_cb(lv_event_t *e) { - int idx = s_acur + (int)(intptr_t)lv_event_get_user_data(e); - if (idx < 0) idx = 0; - if (idx >= s_n_acts) idx = s_n_acts - 1; + // Wrap-around: (cur + dir + n) % n handles both +1 and -1 cleanly. + int idx = (s_acur + (int)(intptr_t)lv_event_get_user_data(e) + s_n_acts) % s_n_acts; s_acur = idx; lv_obj_scroll_to_x(s_track, idx * HOME_SLIDE_W, LV_ANIM_ON); adots_update(idx);