/* files_internal.h — files 应用内部共享头(UI 各页 + app 装配层 + 宿主测试面)。 * * 层级(对齐 hello_app 的批次②拆分规范): * - ui/browser.c 目录浏览页(ACT_BROWSER,根页):列表虚拟化渲染 + 进/退目录 + 行操作 * - ui/viewer.c 文本预览页(ACT_VIEWER,子页):只读、可滚动、≤256KB 截断 * - ui/common/chrome.c 共享 chrome(TopAppBar 建置 / 内容区几何 / 空态/页脚绘制) * - logic/fsx.* 纯业务(路径安全/格式化/枚举/写操作),不依赖 meow_ui * - app.c main + 装配 + 事件分发(把 meow_ui_run 的平铺回调路由到各页) * * 页面生命周期用 meow_view_page_push/pop 驱动 on_enter/on_leave;目录进退不换页(留在 browser * 页改 cur_dir 重扫)。物理键不映射(§3.4.1):本 App 不做任何 on_key 映射,返回=左缘手势/返回钮/ * request_exit。 */ #ifndef FILES_INTERNAL_H #define FILES_INTERNAL_H #include #include "meow_ui.h" #include "meow_ui_view.h" #include "logic/fsx.h" /* ---- Activity 归属(§6.1 ①)---- */ #define ACT_BROWSER 0 #define ACT_VIEWER 1 /* ---- picker 模式(AMSD_DESIGN §6.2 二期)---- * launcher 注入 MEOW_PICKER_ACTION/REQ_ID/CALLER(amsd `am picker` 路由到本 App)。 * 非空 ACTION → 本 App 进入「选文件」picker 模式:浏览目录、点文件=返回路径(经 * MSG_PICKER_RESULT 发回 launcher→amsd)+ 退出;返回/左滑退出=取消。 */ int picker_active(void); /* 1=进入 picker 模式(MEOW_PICKER_ACTION 非空) */ const char *picker_action(void); uint32_t picker_req_id(void); void picker_return_file(const char *path); /* 选文件:发 MSG_PICKER_RESULT + 请求退出 */ void picker_cancel(void); /* 取消:发 code=MEOW_ERR_NOENT + 请求退出 */ /* ---- 布局 ---- */ #define APP_W 480 #define APP_H 720 #define APP_TOPBAR_H 56 #define APP_ROW_H 56 /* 列表行高下限(旧固定值;实际按字体行高派生,见 files_row_h) */ #define APP_PAD 16 #define APP_ICON_W 26 /* 图标占宽 */ #define APP_OP_W 52 /* 右侧操作钮占宽(触达区) */ #define APP_FOOTER_H 26 /* 底部信息行高(列表/文本内容在其之上滚动) */ #define APP_READ_MAX (256 * 1024) /* 文本预览读取上限 */ /* ---- 列表行高:按字体行高派生(M17,首行标题不显示根因修复)---- * SDK meow_listview 的双行渲染把「标题+副标题」文本块 * block = 2 * meow_ui_text_height(font_body) + MEOW_LISTV_SUB_GAP(2) * 在行内垂直居中(ty = 行顶 + (item - block) / 2),标题只在 ty >= 视口顶时才画。 * item < block 时 ty = 行顶 - Δ:第一行(行顶 == 视口顶)标题被整条跳过、只剩副标题。 * 真机 source_han_serif 20px(ascent 24 + descent 6)行高 30 → block 62,旧的显式 56 → Δ=3。 * 故行高按当前主题正文行高派生:max(APP_ROW_H, 2*line_h + 2)(行高 30 → 62)。 * 本页行恒为双行档位(browser_src2 填 title + subtitle)→ 用 lines=2 公式。 * 行几何(draw / hit / max_scroll)全由 SDK 按传入的这一个值换算,故滚动与命中天然同步; * 页脚几何与行高无关(r_list 单独扣 APP_FOOTER_H)。 */ #define FILES_ROW_SUB_GAP 2 /* 与 SDK MEOW_LISTV_SUB_GAP 同口径(标题/副标题行距) */ static inline int files_row_h_for_line_h(int line_h) { if (line_h < 1) line_h = 1; /* 字体未就绪 → 退回下限 */ int h = 2 * line_h + FILES_ROW_SUB_GAP; return (h > APP_ROW_H) ? h : APP_ROW_H; } /* 当前主题正文行高下的两行列表行高(页面 create 时取一次;字体档位切换走页面重建)。 */ static inline int files_row_h(void) { const meow_theme *th = meow_theme_get(); return files_row_h_for_line_h(th ? meow_ui_text_height(th->font_body) : 0); } /* ---- App 级复用矩形/几何 ---- */ typedef struct { int x, y, w, h; } app_rect_t; #define AR(x,y,w,h) ((app_rect_t){ (x),(y),(w),(h) }) /* ---- chrome(ui/common/chrome.c)---- */ int app_statusbar(void); /* 状态栏高度 inset(0=无) */ app_rect_t app_topbar_rect(void); /* 顶部栏几何(含状态栏偏移) */ app_rect_t app_content_rect(void); /* topbar 之下 → 屏底(列表/文本内容区) */ /* 建 topbar(owner=当前活动:调用方须在正确 activity 下建);返回 widget 供命中/置顶。 */ meow_widget *app_topbar_create(const char *title, int back, const char *action_label); void app_draw_empty(app_rect_t r, const char *kind, const char *what); /* 空态/错误居中 */ void app_draw_footer(app_rect_t r, const char *text); /* 底部信息(项数/路径) */ /* ---- browser 页(ui/browser.c)---- */ meow_view *browser_view_create(void); int browser_is_active(void); int browser_on_tap(int x, int y); /* 1=已消费 */ void browser_swipe(int dir, int dist); void browser_touch_down(int x, int y); void browser_touch_move(int x, int y); void browser_on_long_press(int x, int y); /* SDK 通用长按(§6.3)→ 行 BottomSheet */ int browser_go_up(void); /* 1=回到上级;0=已在根(未动作) */ int browser_at_root(void); void browser_reload(void); const char *browser_current_dir(void); int browser_entry_count(void); /* 宿主测试:当前目录项数 */ /* ---- viewer 页(ui/viewer.c)---- */ meow_view *viewer_view_create(void); int viewer_is_active(void); int viewer_open_file(const char *path); /* 读文件+进预览页;0=成功 */ void viewer_swipe(int dir, int dist); void viewer_touch_down(int x, int y); void viewer_touch_move(int x, int y); int viewer_on_tap(int x, int y); void viewer_load(const char *path); /* 宿主测试:读入 buffer 并解析行 */ #endif /* FILES_INTERNAL_H */