#include "lvgl.h"
#if LV_USE_GIF
#include "extra/libs/gif/lv_gif.h"
#include "extra/libs/gif/gifdec.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#endif
#include "esp_heap_caps.h"
#include "fatfs.h"
#include "driver/ledc.h"
#include "gpio.h"
#include "wifi.h"
#include "jpeg_decoder.h"
#include "../ui/screens/ui_ScreenImg.h"
#include <inttypes.h>

// 前向声明界面切换函数
extern void _ui_screen_change(lv_obj_t **target, lv_scr_load_anim_t fademode, int spd, int delay, void (*target_init)(void));
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
char img_path[40];
char *img_filename;
lv_obj_t *app_img;
lv_obj_t *act_mainscreen;
uint8_t *app_img_data = 0;
esp_jpeg_image_output_t outdata;
lv_img_dsc_t image;

#define MAX_IMAGE_FILES     10
#define MAX_FILENAME_LEN    32
static char spiffs_image_files[MAX_IMAGE_FILES][MAX_FILENAME_LEN];
static int spiffs_image_count = 0;
static int current_image_index = 0;
static bool image_list_initialized = false;

#if LV_USE_GIF
// === 自定义 GIF 播放器（替代 lv_gif，性能优化） ===
// 优化: 1.Palette LUT查表 2.TRUE_COLOR无Alpha 3.后台线程解码流水线
static gd_GIF *gif_decoder = NULL;             // gifdec 解码句柄
static lv_obj_t *gif_img_obj = NULL;           // 普通 lv_img 控件（替代 lv_gif）
static uint16_t *gif_rgb565_buf[2] = {NULL, NULL}; // 双缓冲 RGB565 帧 (PSRAM)
static lv_img_dsc_t gif_frame_dsc;             // LVGL 图片描述符（TRUE_COLOR，无Alpha）
static uint16_t gif_palette_lut[256];          // 调色板 RGB565 查找表
static volatile uint8_t gif_front_idx = 0;     // 当前显示的缓冲区索引
static lv_timer_t *gif_play_timer = NULL;      // LVGL 播放定时器
static TaskHandle_t gif_decode_task_handle = NULL; // 后台解码任务句柄
static volatile bool gif_playing = false;      // 播放状态标志
static volatile bool gif_new_frame_ready = false;  // 新帧就绪标志
static uint32_t gif_last_frame_ms = 0;         // 上一帧显示时间戳
static uint8_t *gif_psram_buf = NULL;          // GIF 文件数据（PSRAM）
static bool current_is_gif = false;            // 当前是否为 GIF 模式

// 前向声明
static bool is_gif_file(const char *filename);
static void gif_player_start(void);
static void gif_player_stop(void);
#endif // LV_USE_GIF

// 当前亮度值（用于休眠恢复）
static uint8_t current_brightness = 50;

// 获取当前亮度值
uint8_t pwm_get_brightness(void) {
    return current_brightness;
}

// 设置屏幕亮度，percent范围0-100
// 0=完全关闭背光，10~100为正常亮度范围
// 显示10%~100%映射到实际亮度20%~100%，背光低电平有效需反转占空比
void pwm_set_brightness(uint8_t percent) {
    if (percent == 0) {
        // 完全关闭背光（低电平有效，占空比100%=全高=关闭）
        ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191);
        ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
        return;
    }
    if (percent < 10) percent = 10;
    if (percent > 100) percent = 100;
    current_brightness = percent;
    uint32_t actual = 20 + (uint32_t)(percent - 10) * 80 / 90;
    uint32_t duty = 8191 - (8191 * actual) / 100;
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
}

// 初始化PWM
void pwm_init(){
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_LOW_SPEED_MODE,
        .timer_num        = LEDC_TIMER_0,
        .duty_resolution  = LEDC_TIMER_13_BIT,
        .freq_hz          = 5000,
        .clk_cfg          = LEDC_AUTO_CLK
    };
    ledc_timer_config(&ledc_timer);// 配置PWM定时器
    ledc_channel_config_t ledc_channel = {
        .speed_mode     = LEDC_LOW_SPEED_MODE,
        .channel        = LEDC_CHANNEL_0,
        .timer_sel      = LEDC_TIMER_0,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = PIN_LCD_EN,
        .duty           = 0,
        .hpoint         = 0
    };
    ledc_channel_config(&ledc_channel);// 配置PWM通道
    pwm_set_brightness(50);// 初始亮度50%
    // ledc_timer_config_t motor_timer = {
    //     .speed_mode       = LEDC_LOW_SPEED_MODE,
    //     .timer_num        = LEDC_TIMER_1,
    //     .duty_resolution  = LEDC_TIMER_13_BIT,
    //     .freq_hz          = 5000,
    //     .clk_cfg          = LEDC_AUTO_CLK
    // };
    // ledc_timer_config(&motor_timer);
    // ledc_channel_config_t motor_channel = {
    //     .speed_mode     = LEDC_LOW_SPEED_MODE,
    //     .channel        = LEDC_CHANNEL_1,
    //     .timer_sel      = LEDC_TIMER_0,
    //     .intr_type      = LEDC_INTR_DISABLE,
    //     .gpio_num       = PIN_MOTOR_EN,
    //     .duty           = 4095,
    //     .hpoint         = 0
    // };
    // ledc_channel_config(&motor_channel);
    // ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 0);
    // ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1);
}

// 测试扫描WiFi列表
void wifi_scan_list_test(){
    wifi_ap_record_t* wifi_list = NULL;// 定义WiFi列表指针
    uint16_t num = 0;// 定义WiFi数量变量
    esp_err_t err = wifi_scan_list(&num,&wifi_list);// 扫描WiFi列表
    if(err == ESP_OK){
        ESP_LOGI("WIFI","列表获取成功,数量:%d",num);// 打印WiFi数量
        for (int i = 0; i < num; i++) {
            ESP_LOGI("WIFI", "AP %d - SSID: %s, RSSI: %d", i + 1, wifi_list[i].ssid, wifi_list[i].rssi);// 打印每个WiFi的SSID和RSSI
        }
    }
}
// 测试连接WiFi
void wifi_connect_test(){
    wifi_config_t wifi_config = {
        .sta = {
            .password = "12345678",
            .ssid = "LDL的iPhone"
        }
    };
    esp_wifi_set_config(ESP_IF_WIFI_STA,&wifi_config);// 设置WiFi配置
    esp_err_t err = esp_wifi_connect();// 连接WiFi
    if(err == ESP_OK){
        ESP_LOGI("WIFI","WIFI连接成功");
    }
}
// 测试断开WiFi连接
void wifi_disconnect_test(){
    esp_err_t err = esp_wifi_disconnect();// 断开WiFi连接
    if(err == ESP_OK){
        ESP_LOGI("WIFI","已断开WiFi连接");
    }
}

// 测试开始扫描WiFi
void wifi_scan_start_test(){
    wifi_scan_start();// 开始扫描WiFi
}

// 测试获取可用堆内存
void free_heap_test(){
    ESP_LOGI("HEAP","可用堆内存:%d",(int)heap_caps_get_total_size(MALLOC_CAP_SPIRAM));
}

lv_obj_t *act_wifiscreen;// 当前WiFi屏幕对象
lv_obj_t *act_testscreen;// 当前测试屏幕对象
lv_obj_t *act_mainscreen;// 当前主屏幕对象

void app_wifi_display(){

}

// 从NVS中读取图片路径
esp_err_t nvs_read_img(void) {
    nvs_handle_t nvs_handle;    // NVS 句柄
    esp_err_t err;  // NVS 错误码
    err = nvs_open("config", NVS_READONLY, &nvs_handle);// 打开 NVS 句柄
    if (err != ESP_OK) return err;    // 如果打开失败，返回错误码
    size_t imgname_len;
    err = nvs_get_str(nvs_handle, "img_filename", NULL, &imgname_len);// 获取图片路径长度
    if (err == ESP_OK) {
        img_filename = malloc(imgname_len);// 分配内存
        err = nvs_get_str(nvs_handle, "img_filename", img_filename, &imgname_len);// 获取图片路径
        if (err != ESP_OK) {
            nvs_close(nvs_handle);// 关闭 NVS 句柄
            return err;    // 如果获取失败，返回错误码
        }
        ESP_LOGI("NVS", "img_filename: %s", img_filename);// 打印图片路径
    }
    nvs_close(nvs_handle);// 关闭 NVS 句柄
    return err;
}

// 测试改变NVS中的图片路径
esp_err_t nvs_change_img(char *imgname) {
    nvs_handle_t nvs_handle;// NVS 句柄
    esp_err_t err;
    err = nvs_open("config", NVS_READWRITE, &nvs_handle);// 打开 NVS 句柄
    if (err != ESP_OK) goto close_handle; 
    err = nvs_set_str(nvs_handle, "img_filename", imgname);// 设置图片路径
    if (err != ESP_OK) goto close_handle;
    err = nvs_commit(nvs_handle);// 提交更改
    if (err != ESP_OK) goto close_handle;// 如果提交失败，关闭句柄并返回错误码
    close_handle:
        nvs_close(nvs_handle);  // 关闭 NVS 句柄
        return err;
}

// 仅更新现有图片，显示其他图片
// img_name: 图片文件名，为NULL时从NVS读取
void app_img_change(const char *img_name){
    // 释放之前的图片数据
    if(app_img_data){
        free(app_img_data);
        app_img_data = NULL;
        ESP_LOGI("IMG", "释放之前显示的图片数据缓存");
    }

    const char *current_img_name = img_name;
    
    // 如果没有指定图片名，从NVS读取
    if(!current_img_name) {
        esp_err_t ret_nvs =  nvs_read_img();// 从NVS中读取图片路径
        if(ret_nvs != ESP_OK){
            ESP_LOGE("NVS","图片路径获取失败2");
            return;
        }
        current_img_name = img_filename;
    }
    
    // 构建图片路径
    snprintf(img_path, sizeof(img_path), "/spiflash/%s", current_img_name);// 格式化图片路径
    ESP_LOGI("IMG", "准备显示图片: %s, 路径: %s", current_img_name, img_path);
    
    // 检查文件是否存在
    struct stat file_stat;
    if(stat(img_path, &file_stat) != 0) {
        ESP_LOGE("IMG", "文件不存在: %s", img_path);
        return;
    }
    ESP_LOGI("IMG", "文件大小: %ld 字节", file_stat.st_size);
    
    // 解码图片
    esp_err_t ret =  DecodeImg(img_path,&app_img_data,&outdata);// 解码图片
    if(ret == ESP_OK){
        ESP_LOGI("IMG", "图片解码成功，数据地址: %p, 宽度: %d, 高度: %d", 
                 app_img_data, outdata.width, outdata.height);
        
        // 检查解码后的数据
        if(app_img_data == NULL) {
            ESP_LOGE("IMG", "解码数据为空");
            return;
        }
        
        // 配置图片数据
        image.header.cf = LV_IMG_CF_TRUE_COLOR;
        image.header.always_zero = 0;
        image.header.reserved = 0;
        image.header.w = outdata.width;
        image.header.h = outdata.height;
        image.data_size = outdata.output_len;
        image.data = app_img_data;
        
        // 获取屏幕对象
        act_mainscreen = lv_scr_act();
        if(act_mainscreen == NULL) {
            ESP_LOGE("IMG", "获取屏幕对象失败");
            return;
        }
        
        // 如果图片对象不存在，创建它
        if(app_img == NULL) {
            app_img = lv_img_create(act_mainscreen);
            if(app_img == NULL) {
                ESP_LOGE("IMG", "创建图片对象失败");
                return;
            }
            lv_obj_center(app_img);
            ESP_LOGI("IMG", "创建图片对象成功");
        }
        
        // 更新图片显示
        lvgl_port_lock(0);// 锁定LVGL端口
        lv_img_set_src(app_img, &image);// 设置图片源
        lv_scr_load(act_mainscreen);// 加载主屏幕
        lvgl_port_unlock();// 解锁LVGL端口
        
        ESP_LOGI("IMG", "图片显示成功: %s", current_img_name);
    } else {
        ESP_LOGE("IMG", "图片解码失败，错误码: %d", ret);
    }
}

// 完整的图片显示初始化
void app_img_display(){
    ESP_LOGI("IMG", "开始显示图片");
    esp_err_t ret_nvs =  nvs_read_img();// 从NVS中读取图片路径
    if(ret_nvs != ESP_OK){
        ESP_LOGE("NVS","图片路径获取失败1");
        return;
    }
    ESP_LOGI("IMG", "图片路径: %s", img_filename);
    snprintf(img_path, sizeof(img_path), "/spiflash/%s",img_filename);// 格式化图片路径
    ESP_LOGI("IMG", "完整路径: %s", img_path);
    
    // 检查文件是否存在
    struct stat file_stat;
    if(stat(img_path, &file_stat) != 0){
        ESP_LOGE("IMG", "文件不存在");
        return;
    }
    ESP_LOGI("IMG", "文件大小: %ld 字节", file_stat.st_size);
    
    esp_err_t ret =  DecodeImg(img_path,&app_img_data,&outdata);// 解码图片
    if(ret == ESP_OK){
        ESP_LOGI("IMG", "图片解码成功，数据地址: %p", app_img_data);
        
        // 检查解码后的数据
        if(app_img_data == NULL){
            ESP_LOGE("IMG", "解码数据为空");
            return;
        }
        
        image.header.cf = LV_IMG_CF_TRUE_COLOR;
        image.header.always_zero = 0;
        image.header.reserved = 0;
        image.header.w = outdata.width;
        image.header.h = outdata.height;
        image.data_size = outdata.output_len;
        image.data = app_img_data;
        
        ESP_LOGI("IMG", "LV_IMG_CF_RGB565 值: %d", LV_IMG_CF_RGB565);
        ESP_LOGI("IMG", "设置图片数据: 宽度=%lu, 高度=%lu, 数据大小=%lu", (unsigned long)image.header.w, (unsigned long)image.header.h, (unsigned long)image.data_size);
        
        act_mainscreen = lv_scr_act();// 获取当前主屏幕对象
        if(act_mainscreen == NULL){
            ESP_LOGE("IMG", "获取屏幕对象失败");
            return;
        }
        ESP_LOGI("IMG", "获取屏幕对象成功");
        
        app_img = lv_img_create(act_mainscreen);// 创建图片对象
        if(app_img == NULL){
            ESP_LOGE("IMG", "创建图片对象失败");
            return;
        }
        ESP_LOGI("IMG", "创建图片对象成功");
        
        lvgl_port_lock(0);// 锁定LVGL端口
        ESP_LOGI("IMG", "设置图片源前");
        lv_img_set_src(app_img, &image);// 设置图片源
        ESP_LOGI("IMG", "设置图片源后");
        lv_obj_center(app_img);// 居中显示图片
        ESP_LOGI("IMG", "居中显示图片后");
        lv_scr_load(act_mainscreen);// 加载主屏幕
        ESP_LOGI("IMG", "加载主屏幕后");
        lvgl_port_unlock();// 解锁LVGL端口
        vTaskDelay(50);// 延时50ms
        pwm_init();// 初始化PWM
        ESP_LOGI("IMG", "图片显示完成");
    } else {
        ESP_LOGE("IMG", "图片解码失败，错误码: %d", ret);
    }
}

// // 图片切换任务
// void img_switch_task(void *pvParameters) {
//     char *image_files[] = {"default.jpg", "02.jpg"};
//     int file_count = 2;
//     int current_index = 0;
    
//     while(1) {
//         // 释放之前的图片数据
//         if(app_img_data) {
//             free(app_img_data);
//             app_img_data = NULL;
//         }
        
//         // 获取当前要显示的图片文件名
//         const char *current_image = image_files[current_index];
//         ESP_LOGI("IMG_SWITCH", "切换到图片: %s", current_image);
        
//         // 构建图片路径
//         snprintf(img_path, sizeof(img_path), "/spiflash/%s", current_image);
//         ESP_LOGI("IMG_SWITCH", "图片路径: %s", img_path);
        
//         // 检查文件是否存在
//         struct stat file_stat;
//         if(stat(img_path, &file_stat) != 0) {
//             ESP_LOGE("IMG_SWITCH", "文件不存在");
//             vTaskDelay(pdMS_TO_TICKS(2000));
//             continue;
//         }
//         ESP_LOGI("IMG_SWITCH", "文件大小: %ld 字节", file_stat.st_size);
        
//         // 解码图片
//         esp_err_t ret = DecodeImg(img_path, &app_img_data, &outdata);
//         if(ret == ESP_OK) {
//             ESP_LOGI("IMG_SWITCH", "图片解码成功，数据地址: %p", app_img_data);
            
//             // 检查解码后的数据
//             if(app_img_data == NULL) {
//                 ESP_LOGE("IMG_SWITCH", "解码数据为空");
//                 vTaskDelay(pdMS_TO_TICKS(2000));
//                 continue;
//             }
            
//             // 配置图片数据
//             image.header.cf = LV_IMG_CF_TRUE_COLOR;
//             image.header.always_zero = 0;
//             image.header.reserved = 0;
//             image.header.w = outdata.width;
//             image.header.h = outdata.height;
//             image.data_size = outdata.output_len;
//             image.data = app_img_data;
            
//             // 获取屏幕对象
//             act_mainscreen = lv_scr_act();
//             if(act_mainscreen == NULL) {
//                 ESP_LOGE("IMG_SWITCH", "获取屏幕对象失败");
//                 vTaskDelay(pdMS_TO_TICKS(2000));
//                 continue;
//             }
            
//             // 如果图片对象不存在，创建它
//             if(app_img == NULL) {
//                 app_img = lv_img_create(act_mainscreen);
//                 if(app_img == NULL) {
//                     ESP_LOGE("IMG_SWITCH", "创建图片对象失败");
//                     vTaskDelay(pdMS_TO_TICKS(2000));
//                     continue;
//                 }
//                 lv_obj_center(app_img);
//             }
            
//             // 更新图片显示
//             lvgl_port_lock(0);
//             lv_img_set_src(app_img, &image);
//             lv_scr_load(act_mainscreen);
//             lvgl_port_unlock();
            
//             ESP_LOGI("IMG_SWITCH", "图片显示成功");
//         } else {
//             ESP_LOGE("IMG_SWITCH", "图片解码失败，错误码: %d", ret);
//         }
        
//         // 切换到下一张图片
//         current_index = (current_index + 1) % file_count;
        
//         // 等待2秒
//         vTaskDelay(pdMS_TO_TICKS(2000));
//     }
// }

// 新的显示测试屏幕函数
void app_test_display(){     
    lvgl_port_lock(0);// 锁定LVGL端口
    
    // 获取或创建屏幕对象
    lv_obj_t *screen = lv_scr_act();
    if(screen == NULL) {
        screen = lv_obj_create(NULL);// 创建屏幕对象
        if(screen == NULL) {
            ESP_LOGE("TEST", "Failed to create screen object");// 创建屏幕对象失败
            lvgl_port_unlock();// 解锁LVGL端口
            return;
        }
    }
    
    // 清空屏幕
    lv_obj_clean(screen);
    
    // 创建标签
    lv_obj_t *label = lv_label_create(screen);
    if(label) {
        lv_label_set_text(label, "Test Screen\nLCD is working!");// 设置标签文本
        lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
        
        // 创建基本样式
        static lv_style_t style;// 基本样式
        lv_style_init(&style);// 初始化基本样式
        lv_style_set_text_font(&style, &lv_font_montserrat_14);// 设置字体
        lv_style_set_text_color(&style, lv_color_hex(0xf9076a));// 设置文本颜色
        lv_style_set_bg_color(&style, lv_color_hex(0x000000));// 设置背景颜色
        
        lv_obj_add_style(label, &style, 0);// 添加样式到标签
    }
    lv_scr_load(screen);// 加载屏幕
    lvgl_port_unlock();// 解锁LVGL端口
}


// 图片循环显示任务 - 显示spiffs中的所有图片
void img_loop_task(void *pvParameters) {
    // 存储SPIFFS中的图片文件名
    char *image_files[10]; // 最多支持10张图片
    int file_count = 0;
    int current_index = 0;
    static bool backlight_initialized = false;
    
    // 初始化背光（只执行一次）
    if(!backlight_initialized) {
        pwm_init();
        backlight_initialized = true;// 初始化背光
        ESP_LOGI("IMG_LOOP", "背光初始化完成");
    }
    
    while(1) {
        // 重新扫描SPIFFS中的图片文件
        ESP_LOGI("IMG_LOOP", "开始扫描SPIFFS中的图片文件");
        
        // 打开SPIFFS目录
        DIR *dir = opendir("/spiflash");
        if(!dir) {
            ESP_LOGE("IMG_LOOP", "无法打开SPIFFS目录");
            vTaskDelay(pdMS_TO_TICKS(3000));
            continue;
        }
        
        // 重置文件计数
        file_count = 0;
        
        // 遍历目录
        struct dirent *entry;
        while((entry = readdir(dir)) != NULL && file_count < 10) {
            // 检查是否是图片文件（.jpg, .jpeg, .png等）
            const char *name = entry->d_name;
            int len = strlen(name);
            if(len > 4) {
                const char *ext = name + len - 4;
                if(strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 || 
                   strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0) {
                    // 存储图片文件名
                    image_files[file_count] = strdup(name);
                    ESP_LOGI("IMG_LOOP", "发现图片文件: %s", name);
                    file_count++;
                }
            }
        }
        
        closedir(dir);
        
        // 检查是否找到图片
        if(file_count == 0) {
            ESP_LOGE("IMG_LOOP", "未找到图片文件");
            vTaskDelay(pdMS_TO_TICKS(3000));
            continue;
        }
        
        ESP_LOGI("IMG_LOOP", "共发现 %d 张图片，开始循环显示", file_count);
        
        // 循环显示所有图片
        for(current_index = 0; current_index < file_count; current_index++) {
            const char *current_image = image_files[current_index];
            ESP_LOGI("IMG_LOOP", "显示图片 %d/%d: %s", current_index + 1, file_count, current_image);
            
            // 使用修改后的app_img_change函数显示图片
            app_img_change(current_image);
            
            // 等待3秒
            vTaskDelay(pdMS_TO_TICKS(3000));
        }
        
        // 释放文件名内存
        for(int i = 0; i < file_count; i++) {
            free(image_files[i]);
        }
        
        // 再次扫描前短暂延时
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

// 图片切换任务 - 显示指定的两张图片
void img_switch_task(void *pvParameters) {
    char *image_files[] = {"default.jpg", "02.jpg"};
    int file_count = 2;
    int current_index = 0;
    
    while(1) {
        // 使用修改后的app_img_change函数显示图片
        const char *current_image = image_files[current_index];
        ESP_LOGI("IMG_SWITCH", "切换到图片: %s", current_image);
        app_img_change(current_image);
        
        // 切换到下一张图片
        current_index = (current_index + 1) % file_count;
        
        // 等待2秒
        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

// 初始化SPIFFS图片列表
void init_spiffs_image_list(void) {
    if(image_list_initialized) {
        ESP_LOGI("IMG_LIST", "图片列表已初始化，跳过");
        return;
    }
    
    ESP_LOGI("IMG_LIST", "开始扫描SPIFFS中的图片文件");
    
    // 打开SPIFFS目录
    DIR *dir = opendir("/spiflash");
    if(!dir) {
        ESP_LOGE("IMG_LIST", "无法打开SPIFFS目录");
        return;
    }
    
    // 重置文件计数
    spiffs_image_count = 0;
    
    // 遍历目录
    struct dirent *entry;
    while((entry = readdir(dir)) != NULL && spiffs_image_count < MAX_IMAGE_FILES) {
        // 检查是否是图片文件（.jpg, .jpeg, .png等）
        const char *name = entry->d_name;
        int len = strlen(name);
        if(len > 4 && len < MAX_FILENAME_LEN) {
            const char *ext = name + len - 4;
            if(strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 ||
               strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0
#if LV_USE_GIF
               || strcasecmp(ext, ".gif") == 0
#endif
               ) {
                // 存储图片文件名到静态缓冲区
                strncpy(spiffs_image_files[spiffs_image_count], name, MAX_FILENAME_LEN - 1);
                spiffs_image_files[spiffs_image_count][MAX_FILENAME_LEN - 1] = '\0';
                ESP_LOGI("IMG_LIST", "发现图片文件: %s", name);
                spiffs_image_count++;
            }
        }
    }

    closedir(dir);

    // 检查是否找到图片
    if(spiffs_image_count == 0) {
        ESP_LOGE("IMG_LIST", "未找到图片文件");
        return;
    }

    image_list_initialized = true;
    ESP_LOGI("IMG_LIST", "图片列表初始化完成，共发现 %d 张图片", spiffs_image_count);
    
    // 查找default.jpg并设置为当前索引
    for(int i = 0; i < spiffs_image_count; i++) {
        if(strcmp(spiffs_image_files[i], "default.jpg") == 0) {
            current_image_index = i;
            ESP_LOGI("IMG_LIST", "设置默认图片索引: %d", current_image_index);
            break;
        }
    }
}

// 获取下一张图片
const char* get_next_image(void) {
    if(!image_list_initialized || spiffs_image_count == 0) {
        ESP_LOGE("IMG_LIST", "图片列表未初始化或为空");
        return NULL;
    }
    
    current_image_index = (current_image_index + 1) % spiffs_image_count;
    ESP_LOGI("IMG_LIST", "切换到下一张图片，索引: %d/%d", current_image_index + 1, spiffs_image_count);
    return spiffs_image_files[current_image_index];
}

// 获取上一张图片
const char* get_prev_image(void) {
    if(!image_list_initialized || spiffs_image_count == 0) {
        ESP_LOGE("IMG_LIST", "图片列表未初始化或为空");
        return NULL;
    }

    current_image_index = (current_image_index - 1 + spiffs_image_count) % spiffs_image_count;
    ESP_LOGI("IMG_LIST", "切换到上一张图片，索引: %d/%d", current_image_index + 1, spiffs_image_count);
    return spiffs_image_files[current_image_index];
}

// 重置图片列表
void free_spiffs_image_list(void) {
    if(!image_list_initialized) {
        return;
    }

    spiffs_image_count = 0;
    current_image_index = 0;
    image_list_initialized = false;

    ESP_LOGI("IMG_LIST", "图片列表已重置");
}

// 根据文件名设置当前图片索引
bool set_image_index_by_name(const char *name) {
    if(!image_list_initialized || spiffs_image_count == 0 || !name) {
        return false;
    }
    for(int i = 0; i < spiffs_image_count; i++) {
        if(strcmp(spiffs_image_files[i], name) == 0) {
            current_image_index = i;
            ESP_LOGI("IMG_LIST", "设置图片索引为 %d: %s", i, name);
            return true;
        }
    }
    ESP_LOGW("IMG_LIST", "未找到图片: %s", name);
    return false;
}

// BLE接收图片后导航到ScreenImg显示
void ble_image_navigate(const char *filename) {
    // 将新文件直接追加到列表（避免重扫 SPIFFS 目录，节省 ~200ms）
    if (!image_list_initialized) {
        init_spiffs_image_list();
    }
    // 检查文件是否已在列表中（避免重复）
    bool found = false;
    for (int i = 0; i < spiffs_image_count; i++) {
        if (strcmp(spiffs_image_files[i], filename) == 0) {
            current_image_index = i;
            found = true;
            break;
        }
    }
    if (!found && spiffs_image_count < MAX_IMAGE_FILES) {
        strncpy(spiffs_image_files[spiffs_image_count], filename, MAX_FILENAME_LEN - 1);
        spiffs_image_files[spiffs_image_count][MAX_FILENAME_LEN - 1] = '\0';
        current_image_index = spiffs_image_count;
        spiffs_image_count++;
    }

    // 检查是否已在ScreenImg界面
    lvgl_port_lock(0);
    bool already_on_screen = (lv_scr_act() == ui_ScreenImg);
    if (!already_on_screen) {
        // 不在ScreenImg，导航过去（SCREEN_LOADED事件会触发update_ui_ImgBle）
        _ui_screen_change(&ui_ScreenImg, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenImg_screen_init);
    }
    lvgl_port_unlock();

    // 已在ScreenImg时，_ui_screen_change不会触发SCREEN_LOADED，需手动更新图片
    if (already_on_screen) {
        update_ui_ImgBle(filename);
    }

    ESP_LOGI("IMG_LIST", "BLE导航到ScreenImg显示: %s", filename);
}

// BLE接收图片后导航显示（携带预加载数据，跳过 SPIFFS 重读）
void ble_image_navigate_with_data(const char *filename, uint8_t *data, size_t data_size) {
    // 将新文件追加到列表
    if (!image_list_initialized) {
        init_spiffs_image_list();
    }
    bool found = false;
    for (int i = 0; i < spiffs_image_count; i++) {
        if (strcmp(spiffs_image_files[i], filename) == 0) {
            current_image_index = i;
            found = true;
            break;
        }
    }
    if (!found && spiffs_image_count < MAX_IMAGE_FILES) {
        strncpy(spiffs_image_files[spiffs_image_count], filename, MAX_FILENAME_LEN - 1);
        spiffs_image_files[spiffs_image_count][MAX_FILENAME_LEN - 1] = '\0';
        current_image_index = spiffs_image_count;
        spiffs_image_count++;
    }

#if LV_USE_GIF
    // 如果有预加载数据且是 GIF，直接用内存数据显示（跳过 SPIFFS 重读）
    if (data && data_size > 0 && is_gif_file(filename)) {
        // 停止旧 GIF 播放器
        gif_player_stop();
        if (gif_psram_buf) {
            free(gif_psram_buf);
        }
        // BLE 数据直接作为 GIF 源（所有权转移）
        gif_psram_buf = data;

        // 打开 gifdec 解码器（从 PSRAM 内存源）
        gif_decoder = gd_open_gif_data(gif_psram_buf);
        if (!gif_decoder) {
            ESP_LOGE("GIF", "gifdec 打开失败");
            free(gif_psram_buf);
            gif_psram_buf = NULL;
            return;
        }

        // 确保在 ScreenImg 界面
        lvgl_port_lock(0);
        bool already_on_screen = (lv_scr_act() == ui_ScreenImg);
        if (!already_on_screen) {
            _ui_screen_change(&ui_ScreenImg, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenImg_screen_init);
        }
        lvgl_port_unlock();

        // 启动自定义 GIF 播放器
        gif_player_start();

        ESP_LOGI("IMG_LIST", "BLE GIF直通显示(优化): %s", filename);
        return;
    }
#endif // LV_USE_GIF

    // 非 GIF 或无预加载数据，释放 BLE 数据，走常规 SPIFFS 路径
    if (data) {
        free(data);
    }

    lvgl_port_lock(0);
    bool already_on_screen = (lv_scr_act() == ui_ScreenImg);
    if (!already_on_screen) {
        _ui_screen_change(&ui_ScreenImg, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenImg_screen_init);
    }
    lvgl_port_unlock();

    if (already_on_screen) {
        update_ui_ImgBle(filename);
    }

    ESP_LOGI("IMG_LIST", "BLE导航到ScreenImg显示: %s", filename);
}

// 获取当前图片文件名
const char* get_current_image(void) {
    if(!image_list_initialized || spiffs_image_count == 0) {
        ESP_LOGE("IMG_LIST", "图片列表未初始化或为空");
        return NULL;
    }

    return spiffs_image_files[current_image_index];
}

// 删除当前图片并从列表中移除
bool delete_current_image(void) {
    if(!image_list_initialized || spiffs_image_count == 0) {
        ESP_LOGE("IMG_DEL", "图片列表未初始化或为空");
        return false;
    }

    const char *current_img = spiffs_image_files[current_image_index];

    // 构建完整路径
    char full_path[64];
    snprintf(full_path, sizeof(full_path), "/spiflash/%s", current_img);

    ESP_LOGI("IMG_DEL", "准备删除图片: %s", full_path);

    // 从SPIFFS文件系统中删除文件
    if(unlink(full_path) != 0) {
        ESP_LOGE("IMG_DEL", "删除文件失败: %s", full_path);
        return false;
    }

    ESP_LOGI("IMG_DEL", "文件删除成功: %s", current_img);

    // 从列表中移除该图片
    for(int i = current_image_index; i < spiffs_image_count - 1; i++) {
        strncpy(spiffs_image_files[i], spiffs_image_files[i + 1], MAX_FILENAME_LEN);
    }

    // 更新计数
    spiffs_image_count--;

    // 如果列表为空，重置状态
    if(spiffs_image_count == 0) {
        ESP_LOGI("IMG_DEL", "所有图片已删除");
        image_list_initialized = false;
        current_image_index = 0;
        return true;
    }

    // 调整当前索引（如果删除的是最后一张，回到第一张）
    if(current_image_index >= spiffs_image_count) {
        current_image_index = 0;
    }

    ESP_LOGI("IMG_DEL", "图片列表已更新，剩余 %d 张图片，当前索引: %d",
             spiffs_image_count, current_image_index);

    return true;
}

#if LV_USE_GIF
// 判断文件是否为 GIF 格式
static bool is_gif_file(const char *filename) {
    int len = strlen(filename);
    if (len < 4) return false;
    return strcasecmp(filename + len - 4, ".gif") == 0;
}

// === GIF 播放器内部函数 ===

// 构建调色板 RGB565 查找表（每次帧解码前调用，处理局部调色板）
static void gif_build_palette_lut(gd_Palette *palette) {
    for (int i = 0; i < palette->size; i++) {
        uint8_t r = palette->colors[i * 3 + 0];
        uint8_t g = palette->colors[i * 3 + 1];
        uint8_t b = palette->colors[i * 3 + 2];
        lv_color_t c = lv_color_make(r, g, b);  // 自动处理 LV_COLOR_16_SWAP
        gif_palette_lut[i] = c.full;
    }
}

// 快速渲染帧到 canvas（palette LUT 替代逐像素 lv_color_make）
static void gif_render_frame_fast(gd_GIF *gif) {
    int i = gif->fy * gif->width + gif->fx;
    for (int j = 0; j < gif->fh; j++) {
        for (int k = 0; k < gif->fw; k++) {
            uint8_t index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k];
            if (!gif->gce.transparency || index != gif->gce.tindex) {
                uint16_t c = gif_palette_lut[index];
                gif->canvas[(i + k) * 3 + 0] = c & 0xff;
                gif->canvas[(i + k) * 3 + 1] = (c >> 8) & 0xff;
                gif->canvas[(i + k) * 3 + 2] = 0xff;
            }
        }
        i += gif->width;
    }
}

// canvas (RGB565+Alpha 3字节/像素) → RGB565 (2字节/像素) 快速拷贝
static void gif_canvas_to_rgb565(gd_GIF *gif, uint16_t *out) {
    uint8_t *canvas = gif->canvas;
    int total = gif->width * gif->height;
    for (int i = 0; i < total; i++) {
        out[i] = (uint16_t)canvas[i * 3] | ((uint16_t)canvas[i * 3 + 1] << 8);
    }
}

// 后台解码任务（FreeRTOS，与 LVGL 显示并行）
static void gif_decode_task(void *pvParameters) {
    while (1) {
        // 等待解码请求
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        if (!gif_playing || !gif_decoder) break;

        // LZW 解码（含 dispose 处理）
        int ret = gd_get_frame(gif_decoder);
        if (ret == 0) {
            // GIF 循环播放
            gd_rewind(gif_decoder);
            ret = gd_get_frame(gif_decoder);
        }
        if (ret < 0 || !gif_playing) break;

        // 更新调色板 LUT（可能有局部调色板变化）
        gif_build_palette_lut(gif_decoder->palette);

        // 快速渲染到 canvas + 拷贝到后台 RGB565 缓冲
        gif_render_frame_fast(gif_decoder);
        uint8_t back = 1 - gif_front_idx;
        gif_canvas_to_rgb565(gif_decoder, gif_rgb565_buf[back]);

        // 标记新帧就绪
        gif_new_frame_ready = true;
    }

    gif_decode_task_handle = NULL;
    vTaskDelete(NULL);
}

// LVGL 定时器回调（检查新帧并切换显示）
static void gif_play_timer_cb(lv_timer_t *t) {
    if (!gif_playing || !gif_decoder || !gif_img_obj) return;

    // 检查 GIF 帧延时
    uint32_t delay_ms = gif_decoder->gce.delay * 10;
    if (delay_ms < 20) delay_ms = 20;

    uint32_t elapsed = lv_tick_elaps(gif_last_frame_ms);
    if (elapsed < delay_ms) return;

    if (!gif_new_frame_ready) return;

    gif_last_frame_ms = lv_tick_get();
    gif_new_frame_ready = false;

    // 切换前后缓冲
    uint8_t back = 1 - gif_front_idx;
    gif_front_idx = back;

    // 更新 LVGL 图片源（TRUE_COLOR，无 Alpha 混合）
    gif_frame_dsc.data = (uint8_t *)gif_rgb565_buf[gif_front_idx];
    lv_img_cache_invalidate_src(&gif_frame_dsc);
    lv_obj_invalidate(gif_img_obj);

    // 通知后台线程解码下一帧
    if (gif_decode_task_handle) {
        xTaskNotifyGive(gif_decode_task_handle);
    }
}

// 启动自定义 GIF 播放器
static void gif_player_start(void) {
    if (!gif_decoder || !gif_psram_buf) return;

    uint16_t w = gif_decoder->width;
    uint16_t h = gif_decoder->height;
    size_t buf_size = w * h * sizeof(uint16_t);

    // 分配双缓冲 RGB565 帧 (PSRAM)
    for (int i = 0; i < 2; i++) {
        if (!gif_rgb565_buf[i]) {
            gif_rgb565_buf[i] = heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM);
            if (!gif_rgb565_buf[i]) {
                ESP_LOGE("GIF", "RGB565 缓冲分配失败: %d", i);
                return;
            }
        }
        memset(gif_rgb565_buf[i], 0, buf_size);
    }

    // 初始化调色板 LUT
    gif_build_palette_lut(gif_decoder->palette);

    // 同步解码第一帧（确保立即显示）
    int ret = gd_get_frame(gif_decoder);
    if (ret <= 0) {
        ESP_LOGE("GIF", "首帧解码失败");
        return;
    }
    gif_render_frame_fast(gif_decoder);
    gif_canvas_to_rgb565(gif_decoder, gif_rgb565_buf[0]);
    gif_front_idx = 0;
    gif_new_frame_ready = false;
    gif_last_frame_ms = lv_tick_get();

    // 配置 LVGL 图片描述符（TRUE_COLOR，无 Alpha）
    gif_frame_dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
    gif_frame_dsc.header.always_zero = 0;
    gif_frame_dsc.header.reserved = 0;
    gif_frame_dsc.header.w = w;
    gif_frame_dsc.header.h = h;
    gif_frame_dsc.data_size = buf_size;
    gif_frame_dsc.data = (uint8_t *)gif_rgb565_buf[0];

    // 创建 lv_img 控件 + LVGL 播放定时器
    lvgl_port_lock(0);
    lv_obj_add_flag(ui_ImgBle, LV_OBJ_FLAG_HIDDEN);
    gif_img_obj = lv_img_create(ui_ScreenImg);
    lv_obj_set_size(gif_img_obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_align(gif_img_obj, LV_ALIGN_CENTER);
    lv_obj_clear_flag(gif_img_obj, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_move_background(gif_img_obj);
    lv_img_set_src(gif_img_obj, &gif_frame_dsc);
    gif_play_timer = lv_timer_create(gif_play_timer_cb, 10, NULL);
    lvgl_port_unlock();

    // 启动后台解码任务
    gif_playing = true;
    current_is_gif = true;
    xTaskCreatePinnedToCore(gif_decode_task, "gif_dec", 4096, NULL, 5, &gif_decode_task_handle, 1);

    // 触发后台解码第2帧
    xTaskNotifyGive(gif_decode_task_handle);

    ESP_LOGI("GIF", "播放器启动: %dx%d, 双缓冲 %dKB×2", w, h, buf_size / 1024);
}

// 停止自定义 GIF 播放器
static void gif_player_stop(void) {
    // 停止后台解码任务
    gif_playing = false;
    if (gif_decode_task_handle) {
        xTaskNotifyGive(gif_decode_task_handle);
        // 等待任务退出（最多 500ms）
        for (int i = 0; i < 50 && gif_decode_task_handle; i++) {
            vTaskDelay(pdMS_TO_TICKS(10));
        }
    }

    // 删除 LVGL 定时器和控件
    lvgl_port_lock(0);
    if (gif_play_timer) {
        lv_timer_del(gif_play_timer);
        gif_play_timer = NULL;
    }
    if (gif_img_obj) {
        lv_obj_del(gif_img_obj);
        gif_img_obj = NULL;
    }
    lvgl_port_unlock();

    // 关闭 gifdec 解码器
    if (gif_decoder) {
        gd_close_gif(gif_decoder);
        gif_decoder = NULL;
    }

    // 释放 RGB565 双缓冲
    for (int i = 0; i < 2; i++) {
        if (gif_rgb565_buf[i]) {
            free(gif_rgb565_buf[i]);
            gif_rgb565_buf[i] = NULL;
        }
    }

    current_is_gif = false;
    gif_new_frame_ready = false;
}

// 清理 GIF 资源（公开接口，供界面切换时调用）
void pages_cleanup_gif(void) {
    gif_player_stop();
    // 释放 GIF 源文件缓冲区
    if (gif_psram_buf) {
        free(gif_psram_buf);
        gif_psram_buf = NULL;
    }
}
#endif // LV_USE_GIF

// 更新ui_ImgBle控件的图片（支持 JPEG）
bool update_ui_ImgBle(const char *img_name) {
    if(!img_name) {
        ESP_LOGE("IMG_UI", "图片名为空");
        return false;
    }

    if(!ui_ImgBle) {
        ESP_LOGE("IMG_UI", "ui_ImgBle控件不存在");
        return false;
    }

    static uint8_t *ui_img_data = NULL;
    static lv_img_dsc_t ui_image;

    // 构建图片路径
    snprintf(img_path, sizeof(img_path), "/spiflash/%s", img_name);
    ESP_LOGI("IMG_UI", "准备显示图片: %s, 路径: %s", img_name, img_path);

    // 检查文件是否存在
    struct stat file_stat;
    if(stat(img_path, &file_stat) != 0) {
        ESP_LOGE("IMG_UI", "文件不存在: %s", img_path);
        return false;
    }
    ESP_LOGI("IMG_UI", "文件大小: %ld 字节", file_stat.st_size);

#if LV_USE_GIF
    if (is_gif_file(img_name)) {
        // === GIF 显示路径（自定义播放器：Palette LUT + 无Alpha + 后台解码） ===
        // 释放之前的 JPEG 数据
        if(ui_img_data) {
            free(ui_img_data);
            ui_img_data = NULL;
        }

        // 停止旧 GIF 播放器 + 释放旧 GIF 数据
        gif_player_stop();
        if (gif_psram_buf) {
            free(gif_psram_buf);
            gif_psram_buf = NULL;
        }

        // 将 GIF 文件整体读入 PSRAM
        FILE *gif_file = fopen(img_path, "rb");
        if (!gif_file) {
            ESP_LOGE("IMG_UI", "GIF文件打开失败: %s", img_path);
            return false;
        }
        gif_psram_buf = heap_caps_malloc(file_stat.st_size, MALLOC_CAP_SPIRAM);
        if (!gif_psram_buf) {
            ESP_LOGE("IMG_UI", "PSRAM分配失败: %ld 字节", file_stat.st_size);
            fclose(gif_file);
            return false;
        }
        fread(gif_psram_buf, 1, file_stat.st_size, gif_file);
        fclose(gif_file);

        // 打开 gifdec 解码器（从 PSRAM 内存源）
        gif_decoder = gd_open_gif_data(gif_psram_buf);
        if (!gif_decoder) {
            ESP_LOGE("IMG_UI", "gifdec 打开失败: %s", img_name);
            free(gif_psram_buf);
            gif_psram_buf = NULL;
            return false;
        }

        // 启动自定义 GIF 播放器（Palette LUT + 双缓冲流水线）
        gif_player_start();

        ESP_LOGI("IMG_UI", "GIF显示启动(优化): %s", img_name);
        return true;
    } else
#endif // LV_USE_GIF
    {
        // === JPEG 显示路径 ===
#if LV_USE_GIF
        // 停止 GIF 播放器并释放资源
        gif_player_stop();
        if (gif_psram_buf) {
            free(gif_psram_buf);
            gif_psram_buf = NULL;
        }
        // 恢复 JPEG 控件显示
        lvgl_port_lock(0);
        lv_obj_clear_flag(ui_ImgBle, LV_OBJ_FLAG_HIDDEN);
        lvgl_port_unlock();
#endif

        // 释放之前的图片数据
        if(ui_img_data) {
            free(ui_img_data);
            ui_img_data = NULL;
            ESP_LOGI("IMG_UI", "释放之前的图片数据");
        }

        // 解码图片
        esp_jpeg_image_output_t ui_outdata;
        esp_err_t ret = DecodeImg(img_path, &ui_img_data, &ui_outdata);
        if(ret == ESP_OK) {
            ESP_LOGI("IMG_UI", "图片解码成功，宽度: %d, 高度: %d", ui_outdata.width, ui_outdata.height);

            if(ui_img_data == NULL) {
                ESP_LOGE("IMG_UI", "解码数据为空");
                return false;
            }

            // 配置图片数据
            ui_image.header.cf = LV_IMG_CF_TRUE_COLOR;
            ui_image.header.always_zero = 0;
            ui_image.header.reserved = 0;
            ui_image.header.w = ui_outdata.width;
            ui_image.header.h = ui_outdata.height;
            ui_image.data_size = ui_outdata.output_len;
            ui_image.data = ui_img_data;

            lvgl_port_lock(0);
            lv_img_set_src(ui_ImgBle, &ui_image);
            lvgl_port_unlock();

            ESP_LOGI("IMG_UI", "JPEG图片更新成功: %s", img_name);
            return true;
        } else {
            ESP_LOGE("IMG_UI", "图片解码失败，错误码: %d", ret);
            ui_img_data = NULL;
            return false;
        }
    }
    return false;
}


// // 原本显示测试屏幕 代码
// void app_test_display(){     
//     lvgl_port_lock(0);// 锁定LVGL端口
//     act_testscreen = lv_scr_act();// 获取当前测试屏幕对象
//     // 创建列表样式
//     static lv_style_t list_style;
//     lv_style_init(&list_style);
//     lv_style_set_bg_color(&list_style, lv_color_hex(0x1E1E1E));
//     lv_style_set_border_width(&list_style, 0);
//     lv_style_set_radius(&list_style, 0);
//     lv_style_set_text_align(&list_style, LV_TEXT_ALIGN_CENTER);
    
//     // 创建列表项样式
//     static lv_style_t list_item_style;
//     lv_style_init(&list_item_style);
//     lv_style_set_bg_color(&list_item_style, lv_color_hex(0x2E2E2E));
//     lv_style_set_bg_opa(&list_item_style, LV_OPA_100);
//     lv_style_set_text_color(&list_item_style, lv_color_hex(0xFFFFFF));
//     lv_style_set_pad_all(&list_item_style, 10);
//     lv_style_set_min_height(&list_item_style, 80);  // 设置最小高度为60px

//     // 创建选中项样式
//     static lv_style_t list_item_selected_style;
//     lv_style_init(&list_item_selected_style);
//     lv_style_set_bg_color(&list_item_selected_style, lv_color_hex(0x4A90E2));
//     lv_style_set_text_color(&list_item_selected_style, lv_color_hex(0xFFFFFF));
    
    
//     lv_obj_t* list = lv_list_create(act_testscreen);
//     lv_obj_add_style(list, &list_style, 0);
//     lv_obj_set_size(list, lv_pct(100), lv_pct(100));
//     lv_obj_t* list_item1 = lv_list_add_btn(list, LV_SYMBOL_FILE, "FLASH TEST");
//     lv_obj_t* list_item2 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI SCAN START TEST");
//     lv_obj_t* list_item3 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI SCAN LIST TEST");
//     lv_obj_t* list_item5 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI CONNECT TEST");
//     lv_obj_t* list_item6 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI DISCONNECT TEST");
//     lv_obj_t* list_item4 = lv_list_add_btn(list, LV_SYMBOL_FILE, "FREE HEAP");
//     lv_obj_t* list_item7 = lv_list_add_btn(list, LV_SYMBOL_FILE, "TEMP TEST");


//     lv_obj_add_event_cb(list_item1, fs_test, LV_EVENT_CLICKED, NULL);
//     lv_obj_add_event_cb(list_item2, wifi_scan_start_test, LV_EVENT_CLICKED, NULL);
//     lv_obj_add_event_cb(list_item3, wifi_scan_list_test, LV_EVENT_CLICKED, NULL);
//     lv_obj_add_event_cb(list_item4, free_heap_test, LV_EVENT_CLICKED, NULL);
//     lv_obj_add_event_cb(list_item5, wifi_connect_test, LV_EVENT_CLICKED, NULL);
//     lv_obj_add_event_cb(list_item6, wifi_disconnect_test, LV_EVENT_CLICKED, NULL);
//     lv_obj_add_event_cb(list_item7, temp_test, LV_EVENT_CLICKED, NULL);


//     lv_obj_t *parent = lv_obj_create(act_mainscreen);
//     lv_obj_set_size(parent, 150, 150);
//     lv_obj_center(parent);  // 居中显示

//     static lv_style_t style_bg_black;
//     lv_style_init(&style_bg_black);
//     lv_style_set_bg_color(&style_bg_black, lv_color_hex(0x000000));
//     lv_obj_add_style(act_mainscreen, &style_bg_black, 0);

//     static lv_style_t style_img;
//     lv_style_init(&style_img);
//     lv_style_set_radius(&style_img,75);
//     lv_style_set_clip_corner(&style_img, true); 
//     lv_style_set_border_width(&style_img,75);
//     lv_obj_add_style(parent,&style_img,0);

    
//     // lv_obj_t *img = lv_img_create(act_mainscreen);
//     // lv_img_set_src(img,"C:spiflash/face_1759919044875.jpg");

//     lv_scr_load(act_testscreen); 
    
//     lvgl_port_unlock();
//     vTaskDelay(50);
//     pwm_init();

// }
