Files

176 lines
4.4 KiB
C

/**
****************************************************************************************************
* @file ui.c
* @author HiFi Player Project
* @version V1.2
* @date 2026-01-01
* @brief 界面路由器:模式切换 + 按键事件分发
*
* ---------------------------------------------------------------------------------------------------
* 全局按键约定(K0 为“返回/切换”键,任何 App 都遵循同一套语义)
* ---------------------------------------------------------------------------------------------------
* K0 短按 在任意 App 内 -> 返回主界面
* 在主界面 -> 切换到下一个应用
* K0 长按 任意界面 -> 直接切换到下一个应用
* K1/K2/K3 由当前 App 自己定义(见各 App 界面底部的按键提示)
*
* 因此新增 App 时,只需实现自己的 K1/K2/K3,返回与切换是完全自动的。
****************************************************************************************************
*/
#include "ui.h"
#include "ui_common.h"
#include "app.h"
#include "ui_home.h"
#include "ui_player.h"
#include "ui_files.h"
static app_mode_t s_last_mode = APP_MODE_NUM;
/**
* @brief 切换到某个 App 的界面
*/
static void ui_load_mode(app_mode_t mode)
{
switch (mode)
{
case APP_MODE_PLAYER:
ui_player_show();
break;
case APP_MODE_FILES:
ui_files_show();
break;
case APP_MODE_HOME:
default:
ui_home_show();
break;
}
}
/**
* @brief 把按键事件分发给当前界面
*/
static void ui_dispatch(const app_event_t *ev)
{
app_mode_t mode = app_get_mode();
/* ---------------- 1. K0:返回 / 切换应用(全局语义) ---------------- */
if (ev->key == APP_KEY_0)
{
/* 高亮交给当前界面,纯视觉效果 */
switch (mode)
{
case APP_MODE_PLAYER:
ui_player_flash(ev->key);
break;
case APP_MODE_FILES:
ui_files_flash(ev->key);
break;
case APP_MODE_HOME:
default:
ui_home_flash(ev->key);
break;
}
if (ev->type == APP_KEY_LONG)
{
app_switch_next(); /* 长按:直接跳到下一个应用 */
}
else if (mode == APP_MODE_HOME)
{
app_switch_next(); /* 主界面短按:切换应用 */
}
else if ((mode == APP_MODE_FILES) && ui_files_back())
{
/* 文件管理器:先返回上一级目录,停留在本应用内 */
}
else
{
app_set_mode(APP_MODE_HOME); /* App 内短按:返回主界面 */
}
return;
}
/* ---------------- 2. 其它按键的长按暂时没有功能 ---------------- */
if (ev->type == APP_KEY_LONG)
{
return;
}
/* ---------------- 3. 交给当前 App ---------------- */
switch (mode)
{
case APP_MODE_PLAYER:
ui_player_handle_key(ev->key);
break;
case APP_MODE_FILES:
ui_files_handle_key(ev->key);
break;
case APP_MODE_HOME:
default:
ui_home_handle_key(ev->key);
break;
}
}
/**
* @brief 界面周期任务(在 LVGL 任务中执行)
*/
static void ui_tick_cb(lv_timer_t *timer)
{
(void)timer;
app_mode_t mode = app_get_mode();
/* ---------------- 1. 应用切换:换屏 ---------------- */
if (mode != s_last_mode)
{
s_last_mode = mode;
ui_load_mode(mode);
}
/* ---------------- 2. 消费按键事件(唯一消费者) ---------------- */
app_event_t ev;
while (app_event_poll(&ev))
{
ui_dispatch(&ev);
}
/* ---------------- 3. 当前界面刷新 ---------------- */
switch (app_get_mode())
{
case APP_MODE_PLAYER:
ui_player_tick();
break;
case APP_MODE_FILES:
ui_files_tick();
break;
case APP_MODE_HOME:
default:
ui_home_tick();
break;
}
}
void ui_create(void)
{
ui_home_create();
ui_player_create();
ui_files_create();
s_last_mode = app_get_mode();
ui_load_mode(s_last_mode);
lv_timer_create(ui_tick_cb, UI_TICK_MS, NULL);
}