- 页源契约(logic/reader):count/meta/open/close + 目录册(文件夹即书)为第一个实现; meta 由纯 C 图片头探测(PNG IHDR/JPEG SOF/BMP)提供原始尺寸,条漫可先排版再取图, zip 册(M9/M11)只需另写 mr_book_ops,两种消费方式零改动复用 - 翻页引擎:pthread 后台解码窗口=当前±1 页(目录册 downscale 到屏幕长边),翻页只 blit 缓存页图 + meow_anim 150ms 滑动吸附;未命中立即切页显示加载态、不在翻页路径解码; 只 flush 内容区;decode/flip 首帧/翻页完成/进出内存全部 meow_log 打点 - 阅读页 UI:fit 三档(适宽/适高/原始,TopAppBar 动作循环,标题显示页码 x/y)+ 双击以点击点为锚放大(临时缓冲超上限自动降倍率)+ 单指拖拽/滑动步进平移; tap 三分区方向感知(RTL 默认:左=下一页,LTR 反之),中区切 chrome; 左缘返回交给 app.c、屏底热区交给 SDK 回桌面,两者都不拦截 - 跟手:app.c 仅补 2 处极小路由(ACT_READER 的 down/move),reader 自行算位移; 屏底 28px/左缘 24px 不进拖动,竖向主导放弃横滑 - 内存纪律:驻留 ≤3 张 downscale 页图;放大时窗口收缩到当前页;on_leave 停解码线程、 释放全部页图/册索引/TopAppBar,并记录 VmRSS/MemAvailable 前后对比 - 测试/构建:新增 test_reader_core(契约边界/空册/越界/重复 open-close/首末页/头探测/ 方向语义/fit/平移夹取,108 项);run_tests.sh 与 build_tuku.sh 源列表接线; 宿主 46+108 全 PASS,交叉构建静态 MIPS32r2 ELF、-Wall -Wextra 零警告
143 lines
4.5 KiB
C
143 lines
4.5 KiB
C
/* app.c — 图库装配层:main + 建页 + meow_ui_run 回调路由 + 主题监听。
|
||
*
|
||
* 契约(docs/APP_DEV_GUIDE.md §2-§3):
|
||
* - main 只做 meow_ui_init → 建 view → meow_ui_run → 清理;退出走 meow_ui_request_exit;
|
||
* - 页面切换统一走 meow_view_page_push/pop(activity 栈 + on_enter/on_leave 唯一入口);
|
||
* - 物理键不映射返回/确认(on_key 仅日志);屏底上滑由 SDK 系统手势接管,App 不拦截;
|
||
* - 左缘返回:书库内逐级上移,根目录才退出。
|
||
*
|
||
* 主题同步:注册 meow_theme_add_listener;明暗/风格族切换时更新页面底色并整帧 invalidate,
|
||
* 各页 on_draw / SDK 控件下一帧即用新语义色重绘(不缓存颜色)。
|
||
*/
|
||
#include "tuku_internal.h"
|
||
#include "ui/reader/reader.h"
|
||
#include "meow_ui_nav.h"
|
||
|
||
#include <signal.h>
|
||
|
||
static void on_sigterm(int s)
|
||
{
|
||
(void)s;
|
||
meow_ui_request_exit();
|
||
}
|
||
|
||
/* 向 launcher 上报当前页栈深/顶层,供系统导航栈跟随。各页 on_enter 调用。 */
|
||
void mr_nav_report(void)
|
||
{
|
||
int depth = meow_ui_activity_depth();
|
||
if (depth <= 0) depth = 1;
|
||
int id = meow_ui_activity_active();
|
||
const char *top = (id == ACT_READER) ? "reader"
|
||
: (id == ACT_SETTINGS) ? "settings"
|
||
: (id == ACT_LOCK) ? "lock"
|
||
: "library";
|
||
meow_ui_nav_report((uint32_t)depth, top);
|
||
}
|
||
|
||
/* 主题切换:页面底色 + 整帧重绘(控件与 on_draw 全部从 meow_theme_get() 取色)。 */
|
||
static void app_theme_changed(meow_theme_mode m)
|
||
{
|
||
(void)m;
|
||
meow_ui_set_page_bg(meow_theme_get()->bg);
|
||
meow_ui_invalidate(0, 0, meow_ui_width(), meow_ui_height());
|
||
}
|
||
|
||
static int app_active(void)
|
||
{
|
||
return meow_ui_activity_active();
|
||
}
|
||
|
||
static void app_on_key(int keycode, int is_down)
|
||
{
|
||
(void)keycode; (void)is_down; /* 物理键是系统语义,不做返回/确认映射 */
|
||
meow_log(MEOW_LOG_DEBUG, "key");
|
||
}
|
||
|
||
static void app_on_tap(int x, int y)
|
||
{
|
||
switch (app_active()) {
|
||
case ACT_LIBRARY: library_on_tap(x, y); break;
|
||
case ACT_READER: reader_on_tap(x, y); break;
|
||
default: break;
|
||
}
|
||
}
|
||
|
||
static void app_on_swipe(int dir, int dx, int dy)
|
||
{
|
||
(void)dy;
|
||
if (dir == MEOW_SWIPE_LEFT) {
|
||
if (app_active() == ACT_LIBRARY) {
|
||
if (!library_go_up()) {
|
||
meow_log(MEOW_LOG_INFO, "exit:swipe");
|
||
meow_ui_request_exit();
|
||
}
|
||
} else {
|
||
meow_view_page_pop();
|
||
}
|
||
return;
|
||
}
|
||
/* SDK 的 on_swipe 把位移量放在第二参(第三参为 0):UP/DOWN 时 dx=纵向位移。 */
|
||
if (app_active() == ACT_LIBRARY) library_on_swipe(dir, dx);
|
||
}
|
||
|
||
static void app_on_tick(void)
|
||
{
|
||
library_on_tick();
|
||
}
|
||
|
||
static void app_on_swipe_progress(int x_start, int dx)
|
||
{
|
||
meow_ui_swipe_hint(x_start + dx);
|
||
}
|
||
|
||
/* 跟手拖动路由(M6):ACT_READER 需要原始 down/move 算位移;其余页保持原语义。
|
||
* 屏底热区/左缘的避让由 reader 侧按同一口径判断(reader_on_touch_down)。 */
|
||
static void app_on_touch_down(int x, int y)
|
||
{
|
||
if (app_active() == ACT_LIBRARY) library_on_touch_down(x, y);
|
||
else if (app_active() == ACT_READER) reader_on_touch_down(x, y);
|
||
}
|
||
|
||
static void app_on_touch_move(int x, int y)
|
||
{
|
||
if (app_active() == ACT_LIBRARY) library_on_touch_move(x, y);
|
||
else if (app_active() == ACT_READER) reader_on_touch_move(x, y);
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
meow_log(MEOW_LOG_INFO, "start");
|
||
meow_ui_opts o = { 480, 720 };
|
||
if (meow_ui_init(&o) != 0) {
|
||
meow_log(MEOW_LOG_ERROR, "init failed");
|
||
return 1;
|
||
}
|
||
|
||
meow_theme_add_listener(app_theme_changed);
|
||
meow_ui_set_page_bg(meow_theme_get()->bg);
|
||
meow_ui_nav_init();
|
||
signal(SIGTERM, on_sigterm);
|
||
|
||
/* 先建全部页面(on_create 建各自控件/扫描书库),再按启动锁状态进根页。 */
|
||
meow_view *library = library_view_create();
|
||
meow_view *reader = reader_view_create();
|
||
meow_view *settings = settings_view_create();
|
||
meow_view *lock = lock_view_create();
|
||
|
||
meow_view_page_push(lock_view_should_show() ? ACT_LOCK : ACT_LIBRARY);
|
||
|
||
meow_ui_events ev = {
|
||
app_on_key, app_on_tap, app_on_swipe, app_on_tick,
|
||
app_on_swipe_progress, app_on_touch_down, app_on_touch_move,
|
||
};
|
||
meow_ui_run(&ev);
|
||
|
||
meow_view_free(lock);
|
||
meow_view_free(settings);
|
||
meow_view_free(reader);
|
||
meow_view_free(library);
|
||
meow_ui_shutdown();
|
||
meow_log(MEOW_LOG_INFO, "exit");
|
||
return 0;
|
||
}
|