feat: 收口本地文件夹入口并推进 page aggregate rust-first

- 为 Rust Web 主入口补齐本地文件夹/云空间切换、最近目录与路径回填体验\n- 对齐 local markdown media 与 inline marks 的 Rust shell / TipTap converter 语义\n- 让 documents/page 优先消费 Rust page aggregate snapshot,并保留 TS fallback\n- 补强 tree live、local markdown 与主入口 smoke,并同步设计稿状态
This commit is contained in:
lix-2026
2026-05-09 19:05:06 +08:00
parent 71146de5f0
commit d148e1ccc2
20 changed files with 1635 additions and 374 deletions
@@ -17,10 +17,12 @@ function fileUrl(filePath) {
async function main() {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "mnote-main-local-folder-"));
const otherRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mnote-main 本地 #other-"));
fs.mkdirSync(path.join(root, "docs"), { recursive: true });
fs.writeFileSync(path.join(root, "README.md"), "# Root Page\n", "utf8");
fs.writeFileSync(path.join(root, "docs", "child.md"), "# Child Page\n", "utf8");
fs.writeFileSync(path.join(root, "plain.txt"), "plain asset\n", "utf8");
fs.writeFileSync(path.join(otherRoot, "OTHER.md"), "# Other Root\n", "utf8");
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
@@ -54,6 +56,11 @@ async function main() {
url.searchParams.get("rootUri") === fileUrl(root) &&
url.searchParams.get("treeView") === "filetree";
}, { timeout: UI_TIMEOUT_MS });
const recentLocalRoots = await page.evaluate(() => {
const raw = window.localStorage.getItem("mnote.localFolder.recentRoots") || "[]";
return JSON.parse(raw);
});
assert.equal(recentLocalRoots[0], fileUrl(root), "打开本地文件夹后应记录最近 rootUri");
const bodyText = await page.locator("body").innerText({ timeout: UI_TIMEOUT_MS });
assert(!bodyText.includes("legacy_next_compat_disabled"), "本地文件夹主入口不能落入 legacy Next fallback");
@@ -83,10 +90,57 @@ async function main() {
`Shift+Click 应形成文件树范围多选,实际选中: ${selectedRowIds.join(", ")}`,
);
await page.locator('[data-testid="mnote-workspace-source-trigger"]').click({ timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-workspace-source-menu"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
await page.locator(`[data-testid="mnote-recent-local-root"][data-root-uri="${fileUrl(root)}"]`).waitFor({
state: "visible",
timeout: UI_TIMEOUT_MS,
});
await page.locator('[data-testid="mnote-open-other-local-folder"]').click({ timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-local-folder-dialog"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-local-folder-path-input"]').fill(otherRoot);
await page.locator('[data-testid="mnote-local-folder-open-confirm"]').click({ timeout: UI_TIMEOUT_MS });
await page.waitForURL((url) => {
return url.pathname === "/" &&
url.searchParams.get("sourceKind") === "local_folder" &&
url.searchParams.get("rootUri") === fileUrl(otherRoot) &&
url.searchParams.get("treeView") === "filetree";
}, { timeout: UI_TIMEOUT_MS });
const updatedRecentLocalRoots = await page.evaluate(() => {
const raw = window.localStorage.getItem("mnote.localFolder.recentRoots") || "[]";
return JSON.parse(raw);
});
assert.equal(updatedRecentLocalRoots[0], fileUrl(otherRoot), "切到其他本地文件夹后应把它放到最近目录首位");
assert.equal(updatedRecentLocalRoots[1], fileUrl(root), "之前打开过的本地目录应保留在最近目录列表中");
await page.locator('.tree-row[data-row-id="local:markdown:OTHER.md"]').waitFor({
state: "visible",
timeout: UI_TIMEOUT_MS,
});
await page.locator('[data-testid="mnote-workspace-source-trigger"]').click({ timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-workspace-source-menu"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-open-other-local-folder"]').click({ timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-local-folder-dialog"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
const recentPathInputValue = await page.locator('[data-testid="mnote-local-folder-path-input"]').inputValue({
timeout: UI_TIMEOUT_MS,
});
assert.equal(recentPathInputValue, otherRoot, "最近目录回填输入框时应解码 file:// rootUri,避免二次编码");
await page.getByRole("button", { name: "取消" }).click({ timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-workspace-source-trigger"]').click({ timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-workspace-source-menu"]').waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
await page.locator('[data-testid="mnote-switch-cloud-workspace"]').click({ timeout: UI_TIMEOUT_MS });
await page.waitForURL((url) => {
return url.pathname === "/" &&
url.searchParams.get("sourceKind") === "convex_workspace" &&
!url.searchParams.has("rootUri");
}, { timeout: UI_TIMEOUT_MS });
console.log("task164 desktop hot local folder main entry smoke passed");
} finally {
await browser.close();
fs.rmSync(root, { recursive: true, force: true });
fs.rmSync(otherRoot, { recursive: true, force: true });
}
}