From e76fa437a32ce7c01fcc3edc97c857b837d30156 Mon Sep 17 00:00:00 2001 From: lix-2026 Date: Tue, 26 May 2026 02:46:02 +0800 Subject: [PATCH] refactor: split tree shell icon runtime --- ...ime-module-maintainability-checklist-v1.md | 2 +- .../browser/tree-shell-icons-runtime.js | 133 +++++++++++++++++ .../mnote-web/browser/tree-shell-runtime.js | 138 +----------------- rust/crates/mnote-web/src/routes/mod.rs | 5 + rust/crates/mnote-web/src/routes/web_shell.rs | 14 ++ 5 files changed, 160 insertions(+), 132 deletions(-) create mode 100644 rust/crates/mnote-web/browser/tree-shell-icons-runtime.js diff --git a/design/10-review/process/16-mnote-web-runtime-module-maintainability-checklist-v1.md b/design/10-review/process/16-mnote-web-runtime-module-maintainability-checklist-v1.md index 879c90d7..3899d4e5 100644 --- a/design/10-review/process/16-mnote-web-runtime-module-maintainability-checklist-v1.md +++ b/design/10-review/process/16-mnote-web-runtime-module-maintainability-checklist-v1.md @@ -209,7 +209,7 @@ cargo test --manifest-path rust/Cargo.toml -p mnote-web --lib ssr::pages::layout - [ ] D3. `tree-shell-filetree-runtime.js`:filetree row normalization、resource meta、open target。 - [ ] D4. `tree-shell-picker-runtime.js`:picker search/focus/pick root。 - [ ] D5. `tree-shell-dom-runtime.js`:DOM patch/render helpers。 -- [ ] D6. `tree-shell-icons-runtime.js`:icon templates 和 resource kind badge。 +- [x] D6. `tree-shell-icons-runtime.js`:icon templates 和 resource kind badge。 - [ ] D7. entrypoint 少于 2,500 行。 验收命令: diff --git a/rust/crates/mnote-web/browser/tree-shell-icons-runtime.js b/rust/crates/mnote-web/browser/tree-shell-icons-runtime.js new file mode 100644 index 00000000..d205db5d --- /dev/null +++ b/rust/crates/mnote-web/browser/tree-shell-icons-runtime.js @@ -0,0 +1,133 @@ +// MNote debug /tree shell icon templates and small DOM factories. + +export const TREE_SHELL_ICONS = { + add: ` + + `, + more: ` + + `, + edit: ` + + `, + up: ` + + `, + page: ` + + `, + index: ` + + `, + mindmap: ` + + `, + table: ` + + `, + pdf: ` + + `, + book: ` + + `, + image: ` + + `, + video: ` + + `, + audio: ` + + `, + file: ` + + `, +}; + +export function createTreeShellKindBadge(kind) { + const badge = document.createElement("span"); + badge.className = "tree-kind-badge"; + badge.dataset.kind = kind; + badge.innerHTML = + kind === "mindmap" + ? TREE_SHELL_ICONS.mindmap + : kind === "table" + ? TREE_SHELL_ICONS.table + : kind === "pdf" + ? TREE_SHELL_ICONS.pdf + : kind === "book" + ? TREE_SHELL_ICONS.book + : kind === "image" + ? TREE_SHELL_ICONS.image + : kind === "video" + ? TREE_SHELL_ICONS.video + : kind === "audio" + ? TREE_SHELL_ICONS.audio + : kind === "index" + ? TREE_SHELL_ICONS.index + : kind === "page" + ? TREE_SHELL_ICONS.page + : TREE_SHELL_ICONS.file; + return badge; +} + +export function createTreeShellActionButton(icon, testId, title, onClick, disabled, busy) { + const button = document.createElement("button"); + button.type = "button"; + button.className = "tree-action"; + button.dataset.testid = testId; + button.title = title; + button.setAttribute("aria-label", title); + button.innerHTML = icon; + button.disabled = disabled || busy; + button.addEventListener("click", (event) => { + event.stopPropagation(); + onClick(button); + }); + return button; +} diff --git a/rust/crates/mnote-web/browser/tree-shell-runtime.js b/rust/crates/mnote-web/browser/tree-shell-runtime.js index a753b27e..a969c40b 100644 --- a/rust/crates/mnote-web/browser/tree-shell-runtime.js +++ b/rust/crates/mnote-web/browser/tree-shell-runtime.js @@ -5,6 +5,11 @@ import { reconcilePageRuntimeResult, reducePageActionWithRuntime, } from "./tree-shell-page-runtime.js"; +import { + TREE_SHELL_ICONS as ICONS, + createTreeShellActionButton, + createTreeShellKindBadge as createKindBadge, +} from "./tree-shell-icons-runtime.js"; function buildFileTreeRuntimeEnvironment(runtimeContext) { const fileTreeRowById = runtimeContext.fileTreeRowById || new Map(); @@ -1759,95 +1764,6 @@ function startTreeShellRuntime() { return text ? text.slice(0, 180) : "树命令执行失败"; }; - const ICONS = { - add: ` - - `, - more: ` - - `, - edit: ` - - `, - up: ` - - `, - page: ` - - `, - index: ` - - `, - mindmap: ` - - `, - table: ` - - `, - pdf: ` - - `, - book: ` - - `, - image: ` - - `, - video: ` - - `, - audio: ` - - `, - file: ` - - `, - }; - const sendCommand = async (payload) => { setBusy(true); setStatus("正在提交树命令…"); @@ -3768,48 +3684,8 @@ function startTreeShellRuntime() { return false; }; - const createKindBadge = (kind) => { - const badge = document.createElement("span"); - badge.className = "tree-kind-badge"; - badge.dataset.kind = kind; - badge.innerHTML = - kind === "mindmap" - ? ICONS.mindmap - : kind === "table" - ? ICONS.table - : kind === "pdf" - ? ICONS.pdf - : kind === "book" - ? ICONS.book - : kind === "image" - ? ICONS.image - : kind === "video" - ? ICONS.video - : kind === "audio" - ? ICONS.audio - : kind === "index" - ? ICONS.index - : kind === "page" - ? ICONS.page - : ICONS.file; - return badge; - }; - - const createActionButton = (icon, testId, title, onClick, disabled) => { - const button = document.createElement("button"); - button.type = "button"; - button.className = "tree-action"; - button.dataset.testid = testId; - button.title = title; - button.setAttribute("aria-label", title); - button.innerHTML = icon; - button.disabled = disabled || busy; - button.addEventListener("click", (event) => { - event.stopPropagation(); - onClick(button); - }); - return button; - }; + const createActionButton = (icon, testId, title, onClick, disabled) => + createTreeShellActionButton(icon, testId, title, onClick, disabled, busy); const renderNode = (item) => { const hasChildren = item.childCount > 0; diff --git a/rust/crates/mnote-web/src/routes/mod.rs b/rust/crates/mnote-web/src/routes/mod.rs index 9d18d845..129868b6 100644 --- a/rust/crates/mnote-web/src/routes/mod.rs +++ b/rust/crates/mnote-web/src/routes/mod.rs @@ -170,6 +170,10 @@ pub fn build_router(state: AppState) -> Router { "/api/mnote-browser-runtime/tree-shell-page-runtime.js", get(web_shell::tree_shell_page_runtime_asset), ) + .route( + "/api/mnote-browser-runtime/tree-shell-icons-runtime.js", + get(web_shell::tree_shell_icons_runtime_asset), + ) .route( "/api/mnote-browser-runtime/document-conflict-panel-runtime.js", get(web_shell::document_conflict_panel_runtime_asset), @@ -622,6 +626,7 @@ mod tests { "/api/mnote-browser-runtime/tree-live-controller.js", "/api/mnote-browser-runtime/tree-shell-runtime.js", "/api/mnote-browser-runtime/tree-shell-page-runtime.js", + "/api/mnote-browser-runtime/tree-shell-icons-runtime.js", "/api/mnote-browser-runtime/document-conflict-panel-runtime.js", "/api/mnote-browser-runtime/document-pane-runtime.js", "/api/mnote-browser-runtime/document-mindmap-host-runtime.js", diff --git a/rust/crates/mnote-web/src/routes/web_shell.rs b/rust/crates/mnote-web/src/routes/web_shell.rs index fbfc751c..3abb1e28 100644 --- a/rust/crates/mnote-web/src/routes/web_shell.rs +++ b/rust/crates/mnote-web/src/routes/web_shell.rs @@ -952,6 +952,20 @@ pub async fn tree_shell_page_runtime_asset() -> Response { .unwrap_or_else(|_| Response::new(Body::empty())) } +pub async fn tree_shell_icons_runtime_asset() -> Response { + const JS: &str = include_str!("../../browser/tree-shell-icons-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 document_conflict_panel_runtime_asset() -> Response { // include_str! 路径相对于当前源文件 (src/routes/web_shell.rs -> ../../browser/) const JS: &str = include_str!("../../browser/document-conflict-panel-runtime.js");