Improve local filetree view state and sidebar performance

This commit is contained in:
lix-2026
2026-05-27 11:31:12 +08:00
parent 58e2fdb5d8
commit 3ae33cc21d
56 changed files with 8614 additions and 461 deletions
+112 -1
View File
@@ -86,6 +86,7 @@ pub struct TreeCommandEnvelope {
pub target_resource_meta: Option<Value>,
pub selection: Option<Value>,
pub operation: Option<String>,
pub batch_id: Option<String>,
pub document_id: Option<String>,
pub parent_id: Option<String>,
pub target_parent_id: Option<String>,
@@ -114,6 +115,7 @@ pub struct TreeCommandEnvelopeContext {
pub target_resource_meta: Option<Value>,
pub selection: Option<Value>,
pub operation: Option<String>,
pub batch_id: Option<String>,
}
impl TreeCommandEnvelopeContext {
@@ -130,6 +132,7 @@ impl TreeCommandEnvelopeContext {
target_resource_meta: envelope.target_resource_meta.clone(),
selection: envelope.selection.clone(),
operation: read_optional_non_empty(envelope.operation.clone()),
batch_id: read_optional_non_empty(envelope.batch_id.clone()),
}
}
}
@@ -525,6 +528,25 @@ pub(crate) fn collect_filetree_render_rows(
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToOwned::to_owned);
let relative_path = item
.get("relativePath")
.and_then(Value::as_str)
.or_else(|| {
resource_meta
.and_then(|meta| meta.get("workspacePath"))
.and_then(|workspace_path| workspace_path.get("relativePath"))
.and_then(Value::as_str)
})
.or_else(|| {
resource_meta
.and_then(|meta| meta.get("extra"))
.and_then(|extra| extra.get("source"))
.and_then(|source| source.get("relativePath"))
.and_then(Value::as_str)
})
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToOwned::to_owned);
let icon_kind = item
.get("iconHint")
.and_then(Value::as_str)
@@ -571,6 +593,7 @@ pub(crate) fn collect_filetree_render_rows(
icon_kind,
document_id,
asset_id,
relative_path,
object_identity: resource_meta
.and_then(|meta| meta.get("objectIdentity"))
.and_then(|value| serde_json::to_string(value).ok()),
@@ -2092,6 +2115,79 @@ async fn resolve_tree_create_workspace_id(
})
}
fn operation_resource_relative_path(value: &Value, key: &str) -> Option<String> {
value
.get(key)
.and_then(Value::as_object)
.and_then(|object| object.get("relativePath"))
.and_then(Value::as_str)
.map(str::trim)
.filter(|path| !path.is_empty())
.map(ToOwned::to_owned)
}
fn operation_resource_document_id(value: &Value, key: &str) -> Option<String> {
value
.get(key)
.and_then(Value::as_object)
.and_then(|object| object.get("documentId"))
.and_then(Value::as_str)
.map(str::trim)
.filter(|path| path.starts_with("local-md:"))
.map(ToOwned::to_owned)
}
fn apply_local_file_operation_participants(
buffer_store: &crate::document_buffer_store::BufferStore,
workspace_id: &str,
root_uri: &str,
action: &str,
execution: &Value,
) {
let previous_relative_path = operation_resource_relative_path(execution, "previousResource");
let previous_document_id = operation_resource_document_id(execution, "previousResource");
let next_relative_path = operation_resource_relative_path(execution, "resource");
let next_document_id = operation_resource_document_id(execution, "resource");
match action {
"rename" | "move" => {
if let (
Some(previous_relative_path),
Some(previous_document_id),
Some(next_relative_path),
Some(next_document_id),
) = (
previous_relative_path.as_deref(),
previous_document_id.as_deref(),
next_relative_path.as_deref(),
next_document_id.as_deref(),
) {
let _ = buffer_store.rekey_local_folder_markdown(
workspace_id,
root_uri,
previous_relative_path,
previous_document_id,
next_relative_path,
next_document_id,
);
}
}
"delete" | "archive" | "trash" | "purge" => {
if let (Some(previous_relative_path), Some(previous_document_id)) = (
previous_relative_path.as_deref(),
previous_document_id.as_deref(),
) {
let _ = buffer_store.mark_local_folder_markdown_deleted(
workspace_id,
root_uri,
previous_relative_path,
previous_document_id,
);
}
}
_ => {}
}
}
pub async fn tree_command(
State(state): State<AppState>,
Extension(context): Extension<RequestContext>,
@@ -2292,10 +2388,18 @@ pub async fn tree_command(
.with_context(&context)
.with_header("x-error-phase", "tree_local_executor")
})?;
let local_workspace_id = local_workspace_id_from_root_uri(root_uri)?;
apply_local_file_operation_participants(
&state.buffer_store,
&local_workspace_id,
root_uri,
action,
&execution,
);
return Ok(json_response(
&context,
json!({
"workspaceId": local_workspace_id_from_root_uri(root_uri)?,
"workspaceId": local_workspace_id,
"action": action,
"documentId": execution
.get("documentId")
@@ -2304,6 +2408,12 @@ pub async fn tree_command(
"parentId": requested_parent_id,
"title": requested_title,
"sortOrder": requested_sort_order,
"affectedParents": execution.get("affectedParents").cloned().unwrap_or(Value::Null),
"revealTarget": execution.get("revealTarget").cloned().unwrap_or(Value::Null),
"selectTarget": execution.get("selectTarget").cloned().unwrap_or(Value::Null),
"operationId": execution.get("operationId").cloned().unwrap_or(Value::Null),
"batchId": envelope_context.batch_id.clone(),
"schema": execution.get("schema").cloned().unwrap_or(Value::Null),
"updatedAt": Value::Null,
"execution": execution,
"artifacts": Value::Null,
@@ -3999,6 +4109,7 @@ mod tests {
"rowIds": ["doc:page_child"]
})),
operation: Some("tree.node.rename".into()),
batch_id: None,
};
let rename_wire = create_command_wire(