feat: consolidate local-first mnote web runtime
This commit is contained in:
@@ -94,7 +94,7 @@ pub fn PageLayout(
|
||||
let tree_live_bootstrap = serde_json::json!({
|
||||
"schema": "mnote.tree_live_bootstrap.v1",
|
||||
"disabled": !enable_tree_live,
|
||||
"transport": if enable_tree_live { "convex-command-log-ws" } else { "disabled" },
|
||||
"transport": if enable_tree_live { "tree-live-ws" } else { "disabled" },
|
||||
"workspaceId": null,
|
||||
"rootIds": [],
|
||||
"initialRevision": null,
|
||||
@@ -356,15 +356,18 @@ mod tests {
|
||||
assert!(SIDEBAR_TREE_LIVE_APPLY_RUNTIME_JS
|
||||
.contains("mnote.sidebarTreeViewState.v1:{userId}:{workspaceId}:{sourceKind}:{treeKind}:{rootUriHash}:{scopeHash}"));
|
||||
|
||||
let render_page_rows = js_function_body(SIDEBAR_TREE_LIVE_APPLY_RUNTIME_JS, "renderPageRows");
|
||||
let render_page_rows =
|
||||
js_function_body(SIDEBAR_TREE_LIVE_APPLY_RUNTIME_JS, "renderPageRows");
|
||||
assert!(render_page_rows.contains("sidebarTreeViewStateFor('pagetree'"));
|
||||
assert!(render_page_rows.contains("expandedIds"));
|
||||
assert!(
|
||||
!render_page_rows.contains("var expanded = expandable && item.expandedByDefault !== false"),
|
||||
!render_page_rows
|
||||
.contains("var expanded = expandable && item.expandedByDefault !== false"),
|
||||
"PageTree 不能只依赖 projection expandedByDefault 决定展开"
|
||||
);
|
||||
|
||||
let render_file_rows = js_function_body(SIDEBAR_TREE_LIVE_APPLY_RUNTIME_JS, "renderFileRows");
|
||||
let render_file_rows =
|
||||
js_function_body(SIDEBAR_TREE_LIVE_APPLY_RUNTIME_JS, "renderFileRows");
|
||||
assert!(render_file_rows.contains("sidebarTreeViewStateFor('filetree'"));
|
||||
assert!(render_file_rows.contains("expandedRelativePaths"));
|
||||
}
|
||||
@@ -387,6 +390,11 @@ mod tests {
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("/api/sidebar/shortcuts"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("toggle-sidebar-shortcut"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("openStarredFolderShortcut"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("function openNavigationPageForFolder"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("/api/navigation/recent"));
|
||||
assert!(!SIDEBAR_TREE_RUNTIME_JS.contains("authRedirectUrl"));
|
||||
assert!(!SIDEBAR_TREE_RUNTIME_JS.contains("window.location.assign(authRedirectUrl())"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("window.location.assign(url)"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("rootUri: currentRootUri()"));
|
||||
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("var rootUri = readShortcutRootUri(row);"));
|
||||
assert!(!SIDEBAR_TREE_RUNTIME_JS.contains("inferLocalRootUriFromWorkspaceId"));
|
||||
@@ -414,6 +422,18 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sidebar_filetree_folder_click_toggles_instead_of_navigation_page() {
|
||||
let folder_branch = SIDEBAR_TREE_RUNTIME_JS
|
||||
.split("if (fileAction === 'open' && rowKind === 'folder') {")
|
||||
.nth(1)
|
||||
.and_then(|rest| rest.split("return;").next())
|
||||
.expect("filetree folder open branch exists");
|
||||
assert!(folder_branch.contains("toggleChildren(fileRow"));
|
||||
assert!(!folder_branch.contains("openNavigationPageForFolder"));
|
||||
assert!(!folder_branch.contains("window.location.assign"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn page_ai_context_uses_page_aggregate_subtree_as_single_truth() {
|
||||
assert!(
|
||||
@@ -655,6 +675,10 @@ mod tests {
|
||||
injection.contains("closestAction"),
|
||||
"attachment open runtime 需要显式注入 closestAction,避免首屏点击监听安装时 ReferenceError"
|
||||
);
|
||||
assert!(
|
||||
injection.contains("hydrateEditorAttachmentMeta"),
|
||||
"attachment open runtime 需要显式注入 hydrateEditorAttachmentMeta,避免上传附件增强时 ReferenceError"
|
||||
);
|
||||
assert!(
|
||||
SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS
|
||||
.contains("closestAction = typeof injectedClosestAction === 'function'")
|
||||
@@ -1412,9 +1436,16 @@ mod tests {
|
||||
#[test]
|
||||
fn sidebar_filetree_context_evaluator_uses_readonly_and_selection_count_for_delete_key() {
|
||||
assert!(
|
||||
SIDEBAR_TREE_RUNTIME_JS
|
||||
.contains("evaluateSidebarFileTreeWhen(delCtx, '!workspace.readonly')"),
|
||||
"Delete/Backspace 快捷键应至少评估 workspace.readonly 上下文"
|
||||
SIDEBAR_TREE_RUNTIME_JS.contains(
|
||||
"evaluateSidebarFileTreeWhen(delCtx, '!workspace.readonly && !editor.dirty')"
|
||||
),
|
||||
"Delete/Backspace 快捷键应评估 workspace.readonly 与 editor.dirty 上下文"
|
||||
);
|
||||
assert!(
|
||||
SIDEBAR_TREE_RUNTIME_JS.contains(
|
||||
"evaluateSidebarFileTreeWhen(renameCtx, '!workspace.readonly && !editor.dirty')"
|
||||
),
|
||||
"F2 快捷键应与菜单重命名共用 command context"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1435,6 +1466,12 @@ mod tests {
|
||||
assert!(table_loop.contains("/api/tables/"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sidebar_filetree_runtime_does_not_keep_retired_table_engine_branches() {
|
||||
let retired_table_engine = ["lucky", "sheet"].concat();
|
||||
assert!(!SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains(&retired_table_engine));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sidebar_filetree_asset_open_uses_owner_document_id() {
|
||||
assert!(
|
||||
@@ -1520,6 +1557,18 @@ mod tests {
|
||||
#[test]
|
||||
fn sidebar_tree_runtime_opens_pdf_and_code_assets_with_builtin_tools() {
|
||||
assert!(SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS.contains("function openPdfEditorAttachment"));
|
||||
assert!(SIDEBAR_FILETREE_OPEN_RUNTIME_JS.contains("function buildPdfPreviewOpenUrl"));
|
||||
assert!(SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS.contains("buildPdfPreviewOpenUrl"));
|
||||
assert!(SIDEBAR_FILETREE_OPEN_RUNTIME_JS
|
||||
.contains("var localOpenUrl = isPdfAttachmentFileName(localFileName) ? buildPdfPreviewOpenUrl(localFileUrl, localFileName) : localFileUrl;"));
|
||||
let open_pdf_body = js_function_body(
|
||||
SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS,
|
||||
"openPdfEditorAttachment",
|
||||
);
|
||||
assert!(open_pdf_body.contains("buildPdfPreviewOpenUrl(resolved.url, title)"));
|
||||
assert!(
|
||||
!open_pdf_body.contains("window.open(resolved.url, '_blank', 'noopener,noreferrer');")
|
||||
);
|
||||
assert!(SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS.contains("function openCodeEditorAttachment"));
|
||||
assert!(SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS.contains("function resolveEditorAttachmentUrl"));
|
||||
assert!(SIDEBAR_ATTACHMENT_OPEN_RUNTIME_JS
|
||||
@@ -1553,8 +1602,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn tree_live_controller_marks_transport_and_closes_source_on_pagehide() {
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("convex-command-log-sse"));
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("convex-command-log-ws"));
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("tree-live-sse"));
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("tree-live-ws"));
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("new WebSocket(url.toString())"));
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("startWithSseFallback"));
|
||||
assert!(TREE_LIVE_CONTROLLER_JS.contains("data-mnote-tree-live-transport"));
|
||||
|
||||
Reference in New Issue
Block a user