收口本地工作区清理与资源投影
清理历史 Electron、Graphify、沙箱和截图等仓库跟踪残留,补充 CodeGraph 与 Convex active deploy source 协作说明。 新增 tree-first 下一阶段设计稿和 2026-05-20 清理总结,记录本地工作区、路径身份和 Zed/Lapce/VSCode 参考收口方向。 扩展 Rust Web 本地文件夹、DocumentBuffer、mindmap 资源、tree runtime 和页面聚合链路,并补充 task455 local-folder mindmap clean smoke。 验证:git diff --check 通过;pnpm store status --store-dir .pnpm-store 通过;npm ls --depth=0 --json 通过;find -L node_modules 未发现断链。cargo test -p mnote-web 当前 418 passed / 35 failed。
This commit is contained in:
@@ -3,27 +3,46 @@ use crate::context::RequestContext;
|
||||
use crate::error::WebError;
|
||||
use crate::routes::web_shell::{
|
||||
build_page_aggregate_snapshot, load_file_tree_html, load_sidebar_tree_html,
|
||||
load_workspace_shell_projection,
|
||||
load_workspace_shell_projection, render_local_file_tree_html, render_local_sidebar_tree_html,
|
||||
};
|
||||
use crate::ssr::pages::mindmap::MindmapPage;
|
||||
use crate::workspace_shell::render_workspace_shell_sidebar_html;
|
||||
use axum::extract::{Extension, Path, State};
|
||||
use axum::extract::{Extension, Path, Query, State};
|
||||
use axum::http::{HeaderMap, HeaderName, HeaderValue};
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
|
||||
const HEADER_MNOTE_WEB_OWNER: &str = "x-mnote-web-owner";
|
||||
const HEADER_MNOTE_WEB_SHELL: &str = "x-mnote-web-shell";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MindmapShellQuery {
|
||||
pub source_kind: Option<String>,
|
||||
pub root_uri: Option<String>,
|
||||
pub workspace_id: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn mindmap_object_shell(
|
||||
State(state): State<AppState>,
|
||||
Extension(context): Extension<RequestContext>,
|
||||
Path((doc_id, mindmap_id)): Path<(String, String)>,
|
||||
Query(query): Query<MindmapShellQuery>,
|
||||
) -> Result<Response, WebError> {
|
||||
let default_workspace_name = format!("{} 的空间", state.config().dev_user_name);
|
||||
let aggregate = build_page_aggregate_snapshot(&state, &context, &doc_id, None, None, None)
|
||||
.await
|
||||
.ok();
|
||||
let source_kind = query.source_kind.as_deref();
|
||||
let root_uri = query.root_uri.as_deref();
|
||||
let aggregate = build_page_aggregate_snapshot(
|
||||
&state,
|
||||
&context,
|
||||
&doc_id,
|
||||
query.workspace_id.as_deref(),
|
||||
source_kind,
|
||||
root_uri,
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
let workspace_id = aggregate
|
||||
.as_ref()
|
||||
.map(|value| value.identity.workspace_id.clone())
|
||||
@@ -33,44 +52,69 @@ pub async fn mindmap_object_shell(
|
||||
.map(|value| value.head.title.trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or_else(|| "思维导图".to_string());
|
||||
let (workspace_name, sidebar_tree_html, workspace_sidebar_html) =
|
||||
if let Some(workspace_id) = workspace_id.as_deref() {
|
||||
let workspace_projection = load_workspace_shell_projection(
|
||||
state.config(),
|
||||
&context,
|
||||
workspace_id,
|
||||
Some(&doc_id),
|
||||
&default_workspace_name,
|
||||
)
|
||||
.await;
|
||||
let sidebar_tree_html =
|
||||
load_sidebar_tree_html(state.config(), &context, workspace_id, Some(&doc_id))
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let active_filetree_row_id = format!("asset:{mindmap_id}");
|
||||
let file_tree_html = load_file_tree_html(
|
||||
state.config(),
|
||||
&context,
|
||||
workspace_id,
|
||||
Some(&doc_id),
|
||||
Some(active_filetree_row_id.as_str()),
|
||||
)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let workspace_name = workspace_projection.workspace_name.clone();
|
||||
let workspace_sidebar_html = render_workspace_shell_sidebar_html(
|
||||
&workspace_projection,
|
||||
Some(sidebar_tree_html.as_str()),
|
||||
Some(file_tree_html.as_str()),
|
||||
);
|
||||
(
|
||||
Some(workspace_name),
|
||||
Some(sidebar_tree_html),
|
||||
Some(workspace_sidebar_html),
|
||||
)
|
||||
} else {
|
||||
(None, None, None)
|
||||
};
|
||||
let is_local_folder = source_kind.map(str::trim) == Some("local_folder");
|
||||
let (workspace_name, sidebar_tree_html, workspace_sidebar_html) = if is_local_folder {
|
||||
let root_uri = root_uri.unwrap_or_default();
|
||||
let sidebar_tree_html =
|
||||
render_local_sidebar_tree_html(root_uri, Some(&doc_id)).unwrap_or_default();
|
||||
let file_tree_html =
|
||||
render_local_file_tree_html(root_uri, Some(&doc_id)).unwrap_or_default();
|
||||
let workspace_projection = load_workspace_shell_projection(
|
||||
state.config(),
|
||||
&context,
|
||||
workspace_id.as_deref().unwrap_or("local-folder"),
|
||||
Some(&doc_id),
|
||||
&default_workspace_name,
|
||||
)
|
||||
.await;
|
||||
let workspace_name = workspace_projection.workspace_name.clone();
|
||||
let workspace_sidebar_html = render_workspace_shell_sidebar_html(
|
||||
&workspace_projection,
|
||||
Some(sidebar_tree_html.as_str()),
|
||||
Some(file_tree_html.as_str()),
|
||||
);
|
||||
(
|
||||
Some(workspace_name),
|
||||
Some(sidebar_tree_html),
|
||||
Some(workspace_sidebar_html),
|
||||
)
|
||||
} else if let Some(workspace_id) = workspace_id.as_deref() {
|
||||
let workspace_projection = load_workspace_shell_projection(
|
||||
state.config(),
|
||||
&context,
|
||||
workspace_id,
|
||||
Some(&doc_id),
|
||||
&default_workspace_name,
|
||||
)
|
||||
.await;
|
||||
let sidebar_tree_html =
|
||||
load_sidebar_tree_html(state.config(), &context, workspace_id, Some(&doc_id))
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let active_filetree_row_id = format!("asset:{mindmap_id}");
|
||||
let file_tree_html = load_file_tree_html(
|
||||
state.config(),
|
||||
&context,
|
||||
workspace_id,
|
||||
Some(&doc_id),
|
||||
Some(active_filetree_row_id.as_str()),
|
||||
)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let workspace_name = workspace_projection.workspace_name.clone();
|
||||
let workspace_sidebar_html = render_workspace_shell_sidebar_html(
|
||||
&workspace_projection,
|
||||
Some(sidebar_tree_html.as_str()),
|
||||
Some(file_tree_html.as_str()),
|
||||
);
|
||||
(
|
||||
Some(workspace_name),
|
||||
Some(sidebar_tree_html),
|
||||
Some(workspace_sidebar_html),
|
||||
)
|
||||
} else {
|
||||
(None, None, None)
|
||||
};
|
||||
let editor_bootstrap = json!({
|
||||
"documentId": format!("__mindmap_object__:{doc_id}:{mindmap_id}"),
|
||||
"workspaceId": workspace_id
|
||||
@@ -99,6 +143,8 @@ pub async fn mindmap_object_shell(
|
||||
"documentId": doc_id,
|
||||
"mindmapId": mindmap_id
|
||||
},
|
||||
"sourceKind": source_kind.unwrap_or("convex_workspace"),
|
||||
"rootUri": root_uri.unwrap_or(""),
|
||||
"revision": serde_json::Value::Null,
|
||||
"conflictDetectionKey": serde_json::Value::Null,
|
||||
"pageOptions": {
|
||||
@@ -114,6 +160,8 @@ pub async fn mindmap_object_shell(
|
||||
"shell": "mindmap",
|
||||
"documentId": doc_id,
|
||||
"mindmapId": mindmap_id,
|
||||
"sourceKind": source_kind.unwrap_or("convex_workspace"),
|
||||
"rootUri": root_uri.unwrap_or(""),
|
||||
"projection": {
|
||||
"schema": "mnote.mindmap.simple_mind_map_scene.v1",
|
||||
"runtime": "simple-mind-map",
|
||||
@@ -151,7 +199,7 @@ pub async fn mindmap_object_shell(
|
||||
<title>{}</title>
|
||||
<style>{}</style>
|
||||
</head>
|
||||
<body data-mnote-web-owner="mnote-web" data-mnote-shell="mindmap" data-document-id="{}" data-mindmap-id="{}">
|
||||
<body data-mnote-web-owner="mnote-web" data-mnote-shell="mindmap" data-document-id="{}" data-mindmap-id="{}" data-mnote-source-kind="{}" data-mnote-root-uri="{}">
|
||||
{}
|
||||
<script id="__MNOTE_MINDMAP_EDITOR_BOOTSTRAP__" type="application/json">{}</script>
|
||||
<script id="__MNOTE_MINDMAP_SHELL__" type="application/json">{}</script>
|
||||
@@ -162,6 +210,8 @@ pub async fn mindmap_object_shell(
|
||||
crate::ssr::MNOTE_CSS,
|
||||
escape_html(&doc_id),
|
||||
escape_html(&mindmap_id),
|
||||
escape_html(source_kind.unwrap_or("convex_workspace")),
|
||||
escape_html(root_uri.unwrap_or("")),
|
||||
body_content,
|
||||
escape_script_json(&editor_bootstrap_json),
|
||||
escape_script_json(&contract_json),
|
||||
|
||||
Reference in New Issue
Block a user