diff --git a/main/ui_task.c b/main/ui_task.c index 0f72a79..5b1402e 100644 --- a/main/ui_task.c +++ b/main/ui_task.c @@ -119,6 +119,9 @@ static lv_obj_t *s_ota_bar = NULL; static lv_obj_t *s_ota_pct_lbl = NULL; static lv_obj_t *s_ota_bytes_lbl = NULL; +/* Card view scrollable container */ +static lv_obj_t *s_card_scroll_cont = NULL; + /* Forward declarations */ static void view_menu(void); static void view_scanner(void); @@ -248,6 +251,7 @@ static const char *get_json_str(cJSON *root, const char *key, const char *fallba static void ui_clean_screen(void) { free_art_buffer(); + s_card_scroll_cont = NULL; s_ota_bar = NULL; s_ota_pct_lbl = NULL; s_ota_bytes_lbl = NULL; @@ -1425,9 +1429,10 @@ static void view_card(void) lv_obj_set_style_border_width(card_box, 2, 0); lv_obj_set_style_radius(card_box, 6, 0); lv_obj_set_style_pad_all(card_box, 6, 0); + lv_obj_clear_flag(card_box, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_scrollbar_mode(card_box, LV_SCROLLBAR_MODE_OFF); - /* Name */ + /* Pinned Header: Name */ lv_obj_t *name_lbl = lv_label_create(card_box); lv_label_set_text(name_lbl, name); lv_obj_set_style_text_font(name_lbl, &lv_font_montserrat_14, 0); @@ -1437,7 +1442,7 @@ static void view_card(void) lv_label_set_long_mode(name_lbl, LV_LABEL_LONG_DOT); lv_obj_align(name_lbl, LV_ALIGN_TOP_LEFT, 0, 0); - /* Mana */ + /* Pinned Header: Mana */ if (mana[0]) { lv_obj_t *mana_lbl = lv_label_create(card_box); lv_label_set_text(mana_lbl, mana); @@ -1446,41 +1451,7 @@ static void view_card(void) lv_obj_align(mana_lbl, LV_ALIGN_TOP_RIGHT, 0, 0); } - int cur_y = 20; - - /* Art Crop Image */ - if (has_art) { - lv_obj_t *img = lv_img_create(card_box); - lv_img_set_src(img, &s_art_img_dsc); - lv_obj_align(img, LV_ALIGN_TOP_MID, 0, cur_y); - lv_obj_set_style_border_color(img, lv_color_hex(0x8B6508), 0); - lv_obj_set_style_border_width(img, 1, 0); - lv_obj_set_style_radius(img, 3, 0); - cur_y += s_art_img_dsc.header.h + 4; - } - - /* Type */ - lv_obj_t *type_lbl = lv_label_create(card_box); - lv_label_set_text(type_lbl, type); - lv_obj_set_style_text_font(type_lbl, &lv_font_montserrat_14, 0); - lv_obj_set_style_text_color(type_lbl, lv_color_white(), 0); - lv_obj_set_width(type_lbl, DISP_W - 28); - lv_label_set_long_mode(type_lbl, LV_LABEL_LONG_DOT); - lv_obj_align(type_lbl, LV_ALIGN_TOP_LEFT, 0, cur_y); - cur_y += 18; - - /* Oracle text */ - if (oracle[0]) { - lv_obj_t *oracle_lbl = lv_label_create(card_box); - lv_label_set_text(oracle_lbl, oracle); - lv_label_set_long_mode(oracle_lbl, LV_LABEL_LONG_WRAP); - lv_obj_set_width(oracle_lbl, DISP_W - 32); - lv_obj_set_style_text_font(oracle_lbl, &lv_font_montserrat_14, 0); - lv_obj_set_style_text_color(oracle_lbl, lv_color_hex(COLOR_AMBER), 0); - lv_obj_align(oracle_lbl, LV_ALIGN_TOP_LEFT, 0, cur_y); - } - - /* Bottom: P/T, Loyalty, and Price */ + /* Pinned Footer: P/T or Loyalty */ if (power[0] || tough[0]) { lv_obj_t *pt_lbl = lv_label_create(card_box); lv_label_set_text_fmt(pt_lbl, "%s / %s", power, tough); @@ -1495,6 +1466,7 @@ static void view_card(void) lv_obj_align(loy_lbl, LV_ALIGN_BOTTOM_RIGHT, 0, 0); } + /* Pinned Footer: Price */ if (price[0]) { lv_obj_t *pr_lbl = lv_label_create(card_box); lv_label_set_text_fmt(pr_lbl, "$%s", price); @@ -1503,6 +1475,56 @@ static void view_card(void) lv_obj_align(pr_lbl, LV_ALIGN_BOTTOM_LEFT, 0, 0); } + /* Middle Scrollable Container (Art + Type + Oracle Text) */ + s_card_scroll_cont = lv_obj_create(card_box); + lv_obj_set_size(s_card_scroll_cont, lv_pct(100), 250); + lv_obj_set_pos(s_card_scroll_cont, 0, 22); + lv_obj_set_style_bg_opa(s_card_scroll_cont, LV_OPA_TRANSP, 0); + lv_obj_set_style_border_width(s_card_scroll_cont, 0, 0); + lv_obj_set_style_pad_all(s_card_scroll_cont, 0, 0); + lv_obj_set_style_pad_right(s_card_scroll_cont, 6, 0); + lv_obj_set_style_pad_bottom(s_card_scroll_cont, 24, 0); + lv_obj_set_scrollbar_mode(s_card_scroll_cont, LV_SCROLLBAR_MODE_AUTO); + lv_obj_set_scroll_dir(s_card_scroll_cont, LV_DIR_VER); + lv_obj_set_style_bg_color(s_card_scroll_cont, lv_color_hex(COLOR_GOLD), LV_PART_SCROLLBAR); + lv_obj_set_style_bg_opa(s_card_scroll_cont, LV_OPA_70, LV_PART_SCROLLBAR); + lv_obj_set_style_width(s_card_scroll_cont, 4, LV_PART_SCROLLBAR); + + int cur_y = 0; + + /* Art Crop Image */ + if (has_art) { + lv_obj_t *img = lv_img_create(s_card_scroll_cont); + lv_img_set_src(img, &s_art_img_dsc); + lv_obj_align(img, LV_ALIGN_TOP_MID, 0, cur_y); + lv_obj_set_style_border_color(img, lv_color_hex(0x8B6508), 0); + lv_obj_set_style_border_width(img, 1, 0); + lv_obj_set_style_radius(img, 3, 0); + cur_y += s_art_img_dsc.header.h + 4; + } + + /* Type */ + lv_obj_t *type_lbl = lv_label_create(s_card_scroll_cont); + lv_label_set_text(type_lbl, type); + lv_obj_set_style_text_font(type_lbl, &lv_font_montserrat_14, 0); + lv_obj_set_style_text_color(type_lbl, lv_color_white(), 0); + lv_obj_set_width(type_lbl, DISP_W - 32); + lv_label_set_long_mode(type_lbl, LV_LABEL_LONG_WRAP); + lv_obj_align(type_lbl, LV_ALIGN_TOP_LEFT, 0, cur_y); + lv_obj_update_layout(type_lbl); + cur_y += lv_obj_get_height(type_lbl) + 4; + + /* Oracle text */ + if (oracle[0]) { + lv_obj_t *oracle_lbl = lv_label_create(s_card_scroll_cont); + lv_label_set_text(oracle_lbl, oracle); + lv_label_set_long_mode(oracle_lbl, LV_LABEL_LONG_WRAP); + lv_obj_set_width(oracle_lbl, DISP_W - 36); + lv_obj_set_style_text_font(oracle_lbl, &lv_font_montserrat_14, 0); + lv_obj_set_style_text_color(oracle_lbl, lv_color_hex(COLOR_AMBER), 0); + lv_obj_align(oracle_lbl, LV_ALIGN_TOP_LEFT, 0, cur_y); + } + lvgl_port_unlock(); cJSON_Delete(root); } @@ -1855,6 +1877,16 @@ static void handle_encoder_rotation(int32_t delta) if (delta == 0) return; app_state_t cur = app_get_view(); + if (cur == APP_STATE_CARD_VIEW) { + if (s_card_scroll_cont != NULL) { + lvgl_port_lock(0); + lv_obj_scroll_by_bounded(s_card_scroll_cont, 0, -delta * 35, LV_ANIM_ON); + lvgl_port_unlock(); + } + buzzer_chirp(600, 10); + return; + } + int32_t dir = (delta > 0) ? 1 : -1; int32_t count = (delta > 0) ? delta : -delta;