图库: 书库点图改按文件名定位(修 P1 截断错位)+ 册间衔接根锁定(M18 评审 r1)

P1-1(会静默开错图):取消「书库从列表推导图片下标」。
- 新增 mr_reader_open_dir_at_name(dir, name):阅读器打开目录册后,在**自己刚枚举出的
  全量目录册**(mr_dir_book,与翻页同一份枚举)里按 basename 定位起始页(先精确,
  再大小写不敏感兜底;找不到退回续读/首页)。书库点击只传文件名。
- 删除 mr_library_image_index(不再有跨枚举的隐式契约)。
- 截断提示文案改为「仅显示前 2000 项(图片可在阅读器中翻到)」。
- 修复前(cb02722 探针,2100 张 4 位名夹具):rows=2000/truncated=1/
  library_images=2000/reader_pages=2100/**mismatched=590**(首行 p1412 → 打开 p1411);
  评审夹具为 1995/2000。修复后:2000 个可见图片行按名定位 **0 mismatch**,
  2100 页全量可翻;26 次真实 UI 点开(首尾各 3 + 20 个确定性伪随机)逐张命中。

连带处理(评审 r1):
1. 删掉 reader_page_enter 的 c->view 死写(reopen 判定用 activity active/depth);
   顺手删掉 library_page_create 里同款死写。
2. 阅读器册间衔接根锁定:新增 mr_path_within_root + mr_book_adjacent_rooted,
   book_switch 用浏览根(默认 MR_ROOT_DIR,测试可注入)钳制相邻册;
   根外的兄弟册按「没有相邻册」处理。test_cont_adjacent A7 验证「明文 _ex 会越根、
   rooted 拒绝、根内翻册不受影响」;test_mode_switch_host H6 验证条漫末页不越根。
3. test_reader_perf 不再依赖顶栏 tap 命中时序:模式切换改走测试钩子
   mr_reader_test_toggle_mode()(与顶栏动作同一个 mode_set),负载下稳定。
4. page_cache 注释去掉「缩略图缓存/缩略图线程」过时描述(只改文字)。

回归:run_tests.sh(library 81 / nav 74 / lazy 57 / perf 25 / … / open_book 含 2100 用例)
与 run_webtoon_tests.sh(含 A7/H6)全 PASS;交叉构建零警告。
This commit is contained in:
AskaEth committed 2026-11-05 20:26:40 +08:00
1 parent 64336f95d9
commit 4befbfe14c
17 files changed
+523 -112

No files matched your search

+17 -11
View File
@@ -5,7 +5,8 @@
* 类型·大小(不再有占位/后台补位),图标/右侧箭头按类型区分;
* U2 行合成零 IO:反复取可见行不触发 opendir/readdir/lstat(渲染期无文件访问);
* U3 点击语义:点目录=进入(空目录也进);点图片=从该图开始读
* (mr_reader_open_dir_at(当前目录, 图片下标));点档案册=打开档案册;
* (mr_reader_open_dir_at_name(当前目录, 文件名);阅读器自己定位下标);
* 点档案册=打开档案册;
* U4 根目录锁定:根不显示顶栏返回、library_go_up 在根返回 0(app.c 退出);
* 子目录返回=回根;不存在越过浏览根的导航;
* U5 无 SD 卡容错:浏览根不可访问(不存在/不是目录)→ 友好空态「未检测到 SD 卡」,
@@ -47,18 +48,28 @@ int library_test_go_up(void);
int library_test_drag_active(void);
int library_test_has_list(void);
/* 阅读器入口打桩:只记录被打开的册路径与起始页(本测试不建 reader 页)。 */
/* 阅读器入口打桩:记录被打开的册路径 / 起始页 / 按名定位的文件名(本测试不建 reader 页)。 */
#define MR_READER_START_RESUME (-1)
void mr_reader_open_dir_at(const char *dir, int start_index);
void mr_reader_open_dir_at_name(const char *dir, const char *name);
static char g_opened[MR_PATH_MAX];
static char g_opened_name[MR_NAME_MAX];
static int g_opened_start;
static int g_opened_n;
void mr_reader_open_dir_at(const char *dir, int start_index)
{
snprintf(g_opened, sizeof g_opened, "%s", dir ? dir : "");
g_opened_name[0] = '\0';
g_opened_start = start_index;
g_opened_n++;
}
void mr_reader_open_dir_at_name(const char *dir, const char *name)
{
snprintf(g_opened, sizeof g_opened, "%s", dir ? dir : "");
snprintf(g_opened_name, sizeof g_opened_name, "%s", name ? name : "");
g_opened_start = MR_READER_START_RESUME;
g_opened_n++;
}
static int g_fail;
#define CHECK(cond, ...) do { \
@@ -279,22 +290,17 @@ int main(void)
CHECK(library_test_load(pics_dir) == 1, "entered Pictures");
CHECK(strcmp(library_test_dir(), pics_dir) == 0, "current dir=%s", library_test_dir());
/* 图片下标 = 该目录里排在该图之前的图片行数(阅读器目录册同序)。 */
/* 点图片:把**文件名**交给阅读器(阅读器用自己的全量目录册定位起始页;
* 书库列表可能被 MR_LIB_SCAN_MAX 截断,所以不再传下标)。 */
const char *target = "img10.png";
int ti = row_index_for(target);
CHECK(ti >= 0, "target image row present");
int expect_idx = 0;
for (int i = 0; i < ti; i++) {
meow_list_item tmp;
if (!library_test_src(i, &tmp)) continue;
if (tmp.subtitle && strncmp(tmp.subtitle, "图片 · ", strlen("图片 · ")) == 0)
expect_idx++;
}
g_opened_n = 0;
tap_row(target);
CHECK(g_opened_n == 1 && strcmp(g_opened, pics_dir) == 0,
"tap image opens reader for current dir (%s)", g_opened);
CHECK(g_opened_start == expect_idx, "start index=%d (want %d)", g_opened_start, expect_idx);
CHECK(strcmp(g_opened_name, target) == 0, "reader gets file name (%s)", g_opened_name);
CHECK(g_opened_start == MR_READER_START_RESUME, "name-based open does not pass an index");
CHECK(strcmp(library_test_dir(), pics_dir) == 0, "tap image does not navigate");
g_opened_n = 0;