feat: continue tree rust family cutover

- add rust renderer/state-family scaffolds and inline compat host thinning for page tree, file tree, and picker
- route tree/filetree preflight, file projection, resource artifact, and stream delta contracts through rust plans
- preserve canonical move-order validation, file-tree search projection, and related frontend/runtime regression coverage
This commit is contained in:
lix-2026
2026-04-26 19:35:52 +08:00
parent 338bb2e20f
commit e564dfde02
93 changed files with 17492 additions and 1856 deletions
@@ -0,0 +1,63 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TreeShellDragEffect {
Copy,
Move,
None,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TreeShellDragPayload {
pub row_ids: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TreeShellDropTarget {
pub row_id: Option<String>,
pub document_id: Option<String>,
pub asset_id: Option<String>,
}
pub fn resolve_drag_effect(has_external_files: bool, alt_key: bool) -> TreeShellDragEffect {
if has_external_files || alt_key {
TreeShellDragEffect::Copy
} else {
TreeShellDragEffect::Move
}
}
pub fn normalize_drag_payload(row_ids: &[String]) -> Option<TreeShellDragPayload> {
let mut normalized = Vec::new();
for row_id in row_ids {
let row_id = row_id.trim();
if row_id.is_empty() || normalized.iter().any(|existing| existing == row_id) {
continue;
}
normalized.push(row_id.to_string());
}
if normalized.is_empty() {
None
} else {
Some(TreeShellDragPayload {
row_ids: normalized,
})
}
}
#[cfg(test)]
mod tests {
use super::{normalize_drag_payload, resolve_drag_effect, TreeShellDragEffect};
fn ids(values: &[&str]) -> Vec<String> {
values.iter().map(|value| (*value).to_string()).collect()
}
#[test]
fn tree_shell_drag_drop_state_normalizes_payload_and_effect() {
let payload = normalize_drag_payload(&ids(&[" doc:a ", "asset:b", "doc:a", ""])).unwrap();
assert_eq!(payload.row_ids, ids(&["doc:a", "asset:b"]));
assert_eq!(resolve_drag_effect(true, false), TreeShellDragEffect::Copy);
assert_eq!(resolve_drag_effect(false, true), TreeShellDragEffect::Copy);
assert_eq!(resolve_drag_effect(false, false), TreeShellDragEffect::Move);
assert!(normalize_drag_payload(&ids(&["", " "])).is_none());
}
}