diff --git a/bugs/04-tree-domain/process/4-49-filetree-drag-upload-target-parent-folder-v1.md b/bugs/04-tree-domain/process/4-49-filetree-drag-upload-target-parent-folder-v1.md index b8aa1883..c94e162d 100644 --- a/bugs/04-tree-domain/process/4-49-filetree-drag-upload-target-parent-folder-v1.md +++ b/bugs/04-tree-domain/process/4-49-filetree-drag-upload-target-parent-folder-v1.md @@ -321,4 +321,5 @@ PLAYWRIGHT_CHROME_EXECUTABLE=/snap/bin/chromium node scripts/task479-local-folde - 2.1 上传 intent 已显式化:前端主编辑区上传发送 `editor.markdown.attach`,File Tree folder drop 发送 `filetree.folder.drop`;后端 `/api/local-folder/assets/upload` 解析并校验 intent,不再靠 `documentId` / `targetRelativePath` 隐式分流;`task479` 已断言两个入口的响应字段。 - 2.3 Backspace / Delete 删除相邻附件已补浏览器级 smoke:`task479` Check 7 通过。Backspace 与手柄删除都只删除 Markdown 链接,不删除真实附件文件,相邻附件刷新后仍保持可点击附件块。 - 2.4 切回“我的空间”已按当前 local-first MVP 语义修复并复测:旧“云空间”入口不再进入 `convex_workspace`,改为“我的空间”,通过 `mnoteHome=1` 回默认 `my-space`,避免最近普通本地目录和旧 Convex compat 接管;`task441-local-folder-cloud-switch-smoke.js` 通过。 +- 2.5 / 2.7 resource tab 打开目标已补 active/selected row 验证:`task479` Check 4 断言刚进入 asset-only local folder 点击 `report-a.pdf` 后,主编辑区 resource tab 打开且 File Tree 唯一 selected/active row 保持在该附件 row。 - 页面设置中“隐藏本地 Markdown 文件标题”的可切换 UI / 持久化尚未实现;当前只落地默认隐藏。 diff --git a/design/04-tree-domain/process/4-48-local-folder-markdown-resource-lifecycle-contract-v1.md b/design/04-tree-domain/process/4-48-local-folder-markdown-resource-lifecycle-contract-v1.md index b45c690e..0d592836 100644 --- a/design/04-tree-domain/process/4-48-local-folder-markdown-resource-lifecycle-contract-v1.md +++ b/design/04-tree-domain/process/4-48-local-folder-markdown-resource-lifecycle-contract-v1.md @@ -129,7 +129,7 @@ Markdown 正文链接只是引用,不是所有权声明。 - [x] filetree resource open 默认 active tab。 - [x] PDF 使用与 cloud asset 一致的 preview chrome。 - [x] 本地 Markdown 附件作为 resource tab 打开,不抢占当前页面正文。 -- [ ] active row / selected row 保持在被打开资源。 +- [x] active row / selected row 保持在被打开资源。 ### 5.5 标题和页面设置 @@ -187,3 +187,4 @@ codegraph sync . - 2026-05-24 追加:`task479` 新增 Check 7,覆盖 Backspace 与手柄删除单个附件引用;删除后只改 Markdown 链接,不删除真实附件文件,相邻附件刷新后仍保持可点击附件块。 - 2026-05-24 追加:来源菜单的旧“云空间”入口按当前 local-first MVP 语义改为“我的空间”,默认回到受管 `my-space` 本地根;新增 `mnoteHome=1` 防止被最近普通本地目录自动重定向接管。`task441-local-folder-cloud-switch-smoke.js` 已按当前语义通过。 - 2026-05-24 追加:上传链路已改为显式 `uploadIntent` 合同。主编辑区上传发送并返回 `editor.markdown.attach`,写入 page resource directory;File Tree folder drop 发送并返回 `filetree.folder.drop`,写入 `targetRelativePath` 指向目录。`task479` 已断言响应中的 `uploadIntent`、`rootRelativePath`、`markdownRelativePath`、`ownerDocumentId`。 +- 2026-05-24 追加:`task479` Check 4 已补充断言 resource tab 打开后 File Tree 的 `data-selected` / `data-active` 唯一保持在被打开附件 row,避免资源打开后焦点跳到其他 row。 diff --git a/scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js b/scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js index 9f9de14c..22c927bf 100644 --- a/scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js +++ b/scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js @@ -562,6 +562,24 @@ async function main() { .first() .textContent({ timeout: UI_TIMEOUT_MS }) .catch(() => ""); + const rowState = await pdfAssetRow.evaluate((row) => ({ + rowId: row.getAttribute("data-row-id") || "", + selected: row.getAttribute("data-selected") || "", + active: row.getAttribute("data-active") || "", + focused: row.getAttribute("data-focused") || "", + })); + const selectedRows = await page.locator('#sidebar-file-tree-root .tree-row[data-selected="true"]').evaluateAll((rows) => ( + rows.map((row) => ({ + rowId: row.getAttribute("data-row-id") || "", + text: row.textContent || "", + })) + )); + const activeRows = await page.locator('#sidebar-file-tree-root .tree-row[data-active="true"]').evaluateAll((rows) => ( + rows.map((row) => ({ + rowId: row.getAttribute("data-row-id") || "", + text: row.textContent || "", + })) + )); assert( popupCountAfter === popupCountBefore, @@ -569,13 +587,20 @@ async function main() { ); assert(resourceTabVisible, "点击附件 row 后应显示主编辑区 resource tab host"); assert((resourceTabTitle || "").includes("report-a.pdf"), `资源 tab 标题应包含 report-a.pdf,实际: ${resourceTabTitle}`); + assert.equal(rowState.selected, "true", `点击附件 row 后应保持选中该 row,实际: ${JSON.stringify({ rowState, selectedRows })}`); + assert.equal(rowState.active, "true", `点击附件 row 后应保持 active 在该 row,实际: ${JSON.stringify({ rowState, activeRows })}`); + assert.deepEqual(selectedRows.map((row) => row.rowId), [rowState.rowId], `打开资源后不应跳选其他 row: ${JSON.stringify(selectedRows)}`); + assert.deepEqual(activeRows.map((row) => row.rowId), [rowState.rowId], `打开资源后 active row 不应跳到其他 row: ${JSON.stringify(activeRows)}`); checks[checkId] = { ok: true, - message: "无 active Markdown document 时,点击附件 row 后主编辑区 resource tab 打开且不产生 popup", + message: "无 active Markdown document 时,点击附件 row 后主编辑区 resource tab 打开,且 File Tree active/selected 保持在该附件 row", popupCount: popupCountAfter - popupCountBefore, resourceTabVisible, resourceTabTitle, + rowState, + selectedRows, + activeRows, }; } catch (err) { overallOk = false;