From a93b7fe029462d8a7165a17020c784fdb9460190 Mon Sep 17 00:00:00 2001 From: GW_MC <72297530+GWMCwing@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:45:23 +0800 Subject: [PATCH] feat(travel): Optimize arrival data updates and enhance UI responsiveness --- main/ui/apps/travel/ui/main.cpp | 44 ++++++++++++++++--------- main/ui/apps/travel/ui/main.h | 3 ++ main/ui/apps/travel/ui/main_handler.cpp | 38 +++++++++++++++++++-- main/ui/apps/travel/ui/main_handler.h | 3 ++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/main/ui/apps/travel/ui/main.cpp b/main/ui/apps/travel/ui/main.cpp index 8789e10..3482e47 100644 --- a/main/ui/apps/travel/ui/main.cpp +++ b/main/ui/apps/travel/ui/main.cpp @@ -160,8 +160,10 @@ void MainUI::update_arrivals(const std::vector& arrival_data) return; } - // Hide message label - lv_obj_add_flag(msg_label_, LV_OBJ_FLAG_HIDDEN); + // Hide message label only if it's currently visible + if (!lv_obj_has_flag(msg_label_, LV_OBJ_FLAG_HIDDEN)) { + lv_obj_add_flag(msg_label_, LV_OBJ_FLAG_HIDDEN); + } // Update each route display for (int i = 0; i < MAX_DISPLAY_ROUTES; i++) { @@ -186,16 +188,20 @@ void MainUI::update_route_display_(RouteDisplay& display, const RouteArrivalData display.cached_visible = true; } - // Update header with line color + // Update header text (station -> direction) std::string header_text = data.route.station_name + " -> " + data.route.direction_name; if (header_text != display.cached_header_text) { lv_label_set_text(display.header, header_text.c_str()); display.cached_header_text = header_text; } - if (!data.route.line_color.empty()) { - lv_color_t line_color = hex_to_lv_color_(data.route.line_color); - lv_obj_set_style_text_color(display.header, line_color, 0); + // Update line color only if changed + if (data.route.line_color != display.cached_line_color) { + if (!data.route.line_color.empty()) { + lv_color_t line_color = hex_to_lv_color_(data.route.line_color); + lv_obj_set_style_text_color(display.header, line_color, 0); + } + display.cached_line_color = data.route.line_color; } // Update arrival labels - only if text changed @@ -217,23 +223,28 @@ void MainUI::update_route_display_(RouteDisplay& display, const RouteArrivalData display.cached_arrival_texts[i] = arrival_text; } - // Handle visibility - if (should_show) { - if (lv_obj_has_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN)) { + // Handle visibility only if changed + if (should_show != display.cached_arrival_visible[i]) { + if (should_show) { lv_obj_clear_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN); - } - } else { - if (!lv_obj_has_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN)) { + } else { lv_obj_add_flag(display.arrival_labels[i], LV_OBJ_FLAG_HIDDEN); } + display.cached_arrival_visible[i] = should_show; } } // Show error if any if (!data.is_valid && !data.error_message.empty()) { std::string error_text = " 錯誤: " + data.error_message; - lv_label_set_text(display.arrival_labels[0], error_text.c_str()); - lv_obj_clear_flag(display.arrival_labels[0], LV_OBJ_FLAG_HIDDEN); + if (error_text != display.cached_arrival_texts[0]) { + lv_label_set_text(display.arrival_labels[0], error_text.c_str()); + display.cached_arrival_texts[0] = error_text; + } + if (!display.cached_arrival_visible[0]) { + lv_obj_clear_flag(display.arrival_labels[0], LV_OBJ_FLAG_HIDDEN); + display.cached_arrival_visible[0] = true; + } } } @@ -244,7 +255,10 @@ void MainUI::update_last_refresh_time(const std::string& time_str) { } std::string full_text = "更新: " + time_str; - lv_label_set_text(refresh_time_label_, full_text.c_str()); + if (full_text != cached_refresh_time_text) { + lv_label_set_text(refresh_time_label_, full_text.c_str()); + cached_refresh_time_text = full_text; + } lvgl_port_unlock(); } diff --git a/main/ui/apps/travel/ui/main.h b/main/ui/apps/travel/ui/main.h index d2fa996..d0c63c4 100644 --- a/main/ui/apps/travel/ui/main.h +++ b/main/ui/apps/travel/ui/main.h @@ -37,6 +37,7 @@ private: lv_obj_t* settings_btn_ = nullptr; lv_obj_t* refresh_time_label_ = nullptr; lv_obj_t* msg_label_ = nullptr; + std::string cached_refresh_time_text; // Route display containers (up to MAX_ROUTES) struct RouteDisplay { @@ -46,7 +47,9 @@ private: // Cached values for change detection std::string cached_header_text; + std::string cached_line_color; std::string cached_arrival_texts[3]; + bool cached_arrival_visible[3] = {false, false, false}; bool cached_visible = false; }; RouteDisplay route_displays_[5]; diff --git a/main/ui/apps/travel/ui/main_handler.cpp b/main/ui/apps/travel/ui/main_handler.cpp index 4866cf6..25ed997 100644 --- a/main/ui/apps/travel/ui/main_handler.cpp +++ b/main/ui/apps/travel/ui/main_handler.cpp @@ -238,8 +238,11 @@ void MainUIHandler::fetch_and_update_arrivals_() { arrival_data.push_back(data); } - // Update UI - main_ui_->update_arrivals(arrival_data); + // Update UI only if data changed + if (has_arrival_data_changed_(arrival_data)) { + main_ui_->update_arrivals(arrival_data); + cached_arrival_data_ = arrival_data; + } main_ui_->update_last_refresh_time(get_current_time_string_()); } @@ -296,6 +299,37 @@ std::string MainUIHandler::get_current_time_string_() { return std::string(buffer); } +bool MainUIHandler::has_arrival_data_changed_(const std::vector& new_data) { + if (new_data.size() != cached_arrival_data_.size()) { + return true; + } + + for (size_t i = 0; i < new_data.size(); i++) { + const auto& new_route = new_data[i]; + const auto& cached_route = cached_arrival_data_[i]; + + if (new_route.route.station_code != cached_route.route.station_code || + new_route.route.direction != cached_route.route.direction || + new_route.is_valid != cached_route.is_valid || + new_route.error_message != cached_route.error_message) { + return true; + } + + if (new_route.arrivals.size() != cached_route.arrivals.size()) { + return true; + } + + for (size_t j = 0; j < new_route.arrivals.size(); j++) { + if (new_route.arrivals[j].arrival_time != cached_route.arrivals[j].arrival_time || + new_route.arrivals[j].arrival_time_full != cached_route.arrivals[j].arrival_time_full) { + return true; + } + } + } + + return false; +} + void MainUIHandler::on_settings_button_clicked_static_(lv_event_t* e) { MainUIHandler* handler = static_cast(lv_event_get_user_data(e)); if (handler) { diff --git a/main/ui/apps/travel/ui/main_handler.h b/main/ui/apps/travel/ui/main_handler.h index a5d20d5..b969f26 100644 --- a/main/ui/apps/travel/ui/main_handler.h +++ b/main/ui/apps/travel/ui/main_handler.h @@ -47,6 +47,7 @@ private: void on_settings_button_clicked_(); void fetch_and_update_arrivals_(); + bool has_arrival_data_changed_(const std::vector& new_data); std::string format_arrival_time_(const std::string& api_time); std::string format_arrival_time_full_(const std::string& api_time); std::string get_current_time_string_(); @@ -65,6 +66,8 @@ private: SettingsButtonCallback on_settings_callback_ = nullptr; void* settings_callback_user_data_ = nullptr; + std::vector cached_arrival_data_; + static constexpr uint32_t LVGL_LOCK_TIMEOUT_MS = 4000; };