refactor: split sidebar workspace runtime

This commit is contained in:
lix-2026
2026-05-26 01:31:28 +08:00
parent ff9a779a6c
commit 5a18631af8
6 changed files with 1093 additions and 1005 deletions
+5
View File
@@ -126,6 +126,10 @@ pub fn build_router(state: AppState) -> Router {
"/api/mnote-browser-runtime/sidebar-shell-runtime.js",
get(web_shell::sidebar_shell_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/sidebar-workspace-runtime.js",
get(web_shell::sidebar_workspace_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/sidebar-tree-runtime.js",
get(web_shell::sidebar_tree_runtime_asset),
@@ -579,6 +583,7 @@ mod tests {
"/api/mnote-browser-runtime/filetree-dnd-runtime.js",
"/api/mnote-browser-runtime/filetree-keyboard-runtime.js",
"/api/mnote-browser-runtime/sidebar-shell-runtime.js",
"/api/mnote-browser-runtime/sidebar-workspace-runtime.js",
"/api/mnote-browser-runtime/sidebar-tree-runtime.js",
"/api/mnote-browser-runtime/tree-live-controller.js",
"/api/mnote-browser-runtime/tree-shell-runtime.js",
@@ -742,6 +742,20 @@ pub async fn sidebar_shell_runtime_asset() -> Response {
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_workspace_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-workspace-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, "no-store")
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(Body::from(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn filetree_keyboard_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/filetree-keyboard-runtime.js");
Response::builder()
+34 -31
View File
@@ -201,6 +201,8 @@ mod tests {
const SIDEBAR_TREE_RUNTIME_JS: &str = include_str!("../../../browser/sidebar-tree-runtime.js");
const SIDEBAR_SHELL_RUNTIME_JS: &str =
include_str!("../../../browser/sidebar-shell-runtime.js");
const SIDEBAR_WORKSPACE_RUNTIME_JS: &str =
include_str!("../../../browser/sidebar-workspace-runtime.js");
const FILETREE_CONTEXT_MENU_RUNTIME_JS: &str =
include_str!("../../../browser/filetree-context-menu-runtime.js");
const FILETREE_DND_RUNTIME_JS: &str = include_str!("../../../browser/filetree-dnd-runtime.js");
@@ -301,18 +303,18 @@ mod tests {
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("sidebarFileTreeClipboard"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("pasteSidebarFileTreeClipboard"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("MNOTE_RECENT_LOCAL_ROOTS_KEY_PREFIX"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("function recentLocalRootsStorageKey"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("data-mnote-actor-id"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("requestOpenLocalFolder"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("autoOpenRecentLocalRootOnHome"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("sourceKind', 'local_folder"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("switchToCloudWorkspace"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote-switch-cloud-workspace"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote-recent-local-root"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote-local-folder-authorized-roots"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote-local-folder-authorized-root"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("已授权文件夹"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("fetch('/api/user/access-policy'"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("function recentLocalRootsStorageKey"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("data-mnote-actor-id"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("requestOpenLocalFolder"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("autoOpenRecentLocalRootOnHome"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("sourceKind', 'local_folder"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("switchToCloudWorkspace"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("mnote-switch-cloud-workspace"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("mnote-recent-local-root"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("mnote-local-folder-authorized-roots"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("mnote-local-folder-authorized-root"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("已授权文件夹"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("fetch('/api/user/access-policy'"));
}
#[test]
@@ -338,12 +340,12 @@ mod tests {
#[test]
fn page_ai_local_source_passes_file_reference_fields_to_agent_run() {
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("function currentRootUri()"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("function currentRootUri()"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("sourceKind: currentSourceKind()"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("rootUri: currentRootUri()"));
assert!(SIDEBAR_TREE_RUNTIME_JS
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("if (sourceKind && !payload.sourceKind) payload.sourceKind = sourceKind"));
assert!(SIDEBAR_TREE_RUNTIME_JS
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("if (rootUri && !payload.rootUri) payload.rootUri = rootUri"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("pageContext: scopedContext.pageContext"));
assert!(
@@ -449,15 +451,15 @@ mod tests {
"进入本地文件夹前不能用 document.body 推导 workspaceId;它会在无 workspaceId URL 时回退成 default"
);
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains("rememberCurrentCloudWorkspaceId()"),
SIDEBAR_WORKSPACE_RUNTIME_JS.contains("rememberCurrentCloudWorkspaceId()"),
"进入本地文件夹前应从 URL 或 DOM 子树读取真实 workspaceId"
);
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains("normalized.indexOf('local-ws:') === 0"),
SIDEBAR_WORKSPACE_RUNTIME_JS.contains("normalized.indexOf('local-ws:') === 0"),
"本地文件夹 workspaceId 不能写入 lastCloudWorkspaceId"
);
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains("stored.trim().indexOf('local-ws:') !== 0"),
SIDEBAR_WORKSPACE_RUNTIME_JS.contains("stored.trim().indexOf('local-ws:') !== 0"),
"切回工作区时不能复用 local-ws:* 作为旧云 workspace"
);
assert!(
@@ -471,7 +473,7 @@ mod tests {
fn sidebar_tree_runtime_polls_local_folder_without_browser_reload() {
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("startLocalFolderSidebarWatch"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("refreshLocalFolderSidebarSnapshot"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("function currentWorkspaceId()"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("function currentWorkspaceId()"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("var rootUri = currentRootUri();"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("/api/tree/local-folder-watch"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("/api/tree/projections/sidebar"));
@@ -791,21 +793,22 @@ mod tests {
#[test]
fn sidebar_local_folder_authorized_root_normalizes_plain_path_root_uri() {
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains("function normalizeGrantedLocalFolderRootUri(grant)")
);
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains("if (rootPath) return pathToFileRootUri(rootPath);")
);
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("if (rootUri) return pathToFileRootUri(rootUri);"));
assert!(SIDEBAR_TREE_RUNTIME_JS
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("function normalizeGrantedLocalFolderRootUri(grant)"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("if (rootPath) return pathToFileRootUri(rootPath);"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("if (rootUri) return pathToFileRootUri(rootUri);"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("var rootUri = normalizeGrantedLocalFolderRootUri(grant);"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("function isDefaultWorkspaceAutoGrant(grant)"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("if (isDefaultWorkspaceAutoGrant(grant)) return;"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("function recentLocalRootLabel(rootUri)"));
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains("button.textContent = recentLocalRootLabel(rootUri);")
SIDEBAR_WORKSPACE_RUNTIME_JS.contains("function isDefaultWorkspaceAutoGrant(grant)")
);
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("if (isDefaultWorkspaceAutoGrant(grant)) return;"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS.contains("function recentLocalRootLabel(rootUri)"));
assert!(SIDEBAR_WORKSPACE_RUNTIME_JS
.contains("button.textContent = recentLocalRootLabel(rootUri);"));
assert!(!SIDEBAR_TREE_RUNTIME_JS
.contains("button.textContent = rootUri.replace(/^file:\\/\\//, '')"));
}