mf_collab_client/
utils.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2use mf_model::mark::Mark;
3use mf_model::tree::Tree;
4use mf_state::transaction::Transaction;
5// 新版本映射模块已经通过 crate::mapping 提供所有必要的API
6use crate::AwarenessRef;
7use serde_json::Value as JsonValue;
8use yrs::{Map, ReadTxn, Transact};
9use yrs::{
10    types::{array::ArrayRef, map::MapRef, Value},
11    Array, ArrayPrelim, MapPrelim, TransactionMut, WriteTxn,
12};
13
14use crate::ClientResult;
15use mf_model::{node::Node, attrs::Attrs, types::NodeId};
16use std::sync::Arc;
17use std::collections::HashMap;
18
19/// 获取当前时间戳(毫秒)
20pub struct Utils;
21impl Utils {
22    pub fn get_unix_time() -> u64 {
23        SystemTime::now()
24            .duration_since(UNIX_EPOCH)
25            .unwrap_or_default()
26            .as_millis() as u64
27    }
28    /// 将 Yrs 文档转换为 ModuForge Tree
29    /// 这是从协作状态重建文档树的关键方法
30    pub fn apply_yrs_to_tree(doc: &yrs::Doc) -> ClientResult<Tree> {
31        use mf_model::types::NodeId;
32        use std::collections::HashMap;
33
34        let root_id = Utils::get_root_id_from_yrs_doc(doc)?;
35        let txn = doc.transact();
36        let nodes_map = txn
37            .get_map("nodes")
38            .ok_or(anyhow::anyhow!("Yrs 文档中没有找到 nodes 映射"))?;
39        let mut tree_nodes = HashMap::new();
40        let mut parent_map = HashMap::new();
41
42        Utils::build_tree_nodes_from_yrs(
43            &root_id,
44            &nodes_map,
45            &txn,
46            &mut tree_nodes,
47            &mut parent_map,
48            None,
49        )?;
50
51        let root_node = tree_nodes
52            .get(&NodeId::from(root_id))
53            .ok_or(anyhow::anyhow!("根节点不存在"))?
54            .as_ref()
55            .clone();
56        let root_enum =
57            Utils::build_node_enum_from_map(&root_node, &tree_nodes);
58        Ok(Tree::from(root_enum))
59    }
60    /// 初始化树
61    /// 将树同步到 Yrs 文档
62    pub async fn apply_tree_to_yrs(
63        awareness_ref: AwarenessRef,
64        tree: &Tree,
65    ) -> ClientResult<()> {
66        let mut awareness = awareness_ref.write().await;
67        let doc = awareness.doc_mut();
68        let mut txn =
69            doc.transact_mut_with(doc.client_id().clone().to_string());
70
71        // 清空现有数据(如果有的话)
72        let nodes_map = txn.get_or_insert_map("nodes");
73        nodes_map.clear(&mut txn);
74
75        // 同步 Tree 中的所有节点到 Yrs 文档
76        Utils::sync_tree_to_yrs(tree, &mut txn)?;
77
78        // 添加根节点ID到 meta 区域
79        let meta_map = txn.get_or_insert_map("meta");
80        meta_map.insert(
81            &mut txn,
82            "root_id",
83            yrs::Any::String(tree.root_id.to_string().into()),
84        );
85
86        // 提交事务
87        txn.commit();
88
89        tracing::info!(
90            "成功初始化树,包含 {} 个节点,根节点ID: {}",
91            tree.nodes.iter().map(|shard| shard.len()).sum::<usize>(),
92            tree.root_id
93        );
94        Ok(())
95    }
96
97    /// 将树同步到 Yrs 文档
98    pub fn sync_tree_to_yrs(
99        tree: &Tree,
100        txn: &mut yrs::TransactionMut,
101    ) -> ClientResult<()> {
102        use mf_transform::node_step::AddNodeStep;
103
104        // 获取根节点的所有子树
105        if let Some(root_tree) = tree.all_children(&tree.root_id, None) {
106            // 创建一个 AddNodeStep 来添加整个子树
107            // 注意:root_tree 已经包含了根节点,不需要重复添加
108            let add_step = AddNodeStep {
109                parent_id: tree.root_id.clone(),
110                nodes: vec![root_tree],
111            };
112
113            // 使用新版本的转换器API
114            let context = crate::mapping::create_context(
115                "tree_sync_client".to_string(),
116                "tree_sync_user".to_string(),
117            );
118
119            if let Err(e) =
120                crate::mapping::convert_step(&add_step, txn, &context)
121            {
122                tracing::error!("🔄 同步树节点到 Yrs 失败: {}", e);
123                return Err(anyhow::anyhow!(format!(
124                    "Failed to sync tree: {}",
125                    e
126                )));
127            }
128        }
129
130        Ok(())
131    }
132    /// 将事务应用到 Yrs 文档
133    pub async fn apply_transaction_to_yrs(
134        awareness_ref: AwarenessRef,
135        transaction: &Transaction,
136    ) -> ClientResult<()> {
137        // 使用异步锁获取房间信息
138
139        let mut awareness = awareness_ref.write().await;
140        let doc = awareness.doc_mut();
141        let mut txn =
142            doc.transact_mut_with(doc.client_id().clone().to_string());
143        // 使用新版本的转换API应用所有事务中的步骤
144        let context = crate::mapping::create_context(
145            "transaction_client".to_string(),
146            "transaction_user".to_string(),
147        );
148
149        let steps = &transaction.steps;
150        for step in steps {
151            if let Err(e) =
152                crate::mapping::convert_step(step.as_ref(), &mut txn, &context)
153            {
154                tracing::error!("🔄 应用步骤到 Yrs 事务失败: {}", e);
155            }
156        }
157        // 统一提交所有更改
158        txn.commit();
159        tracing::debug!(
160            "🔄 应用 {} 个步骤到文档: {}",
161            transaction.steps.len(),
162            doc.client_id()
163        );
164
165        Ok(())
166    }
167
168    /// 将事务应用到 Yrs 文档
169    pub async fn apply_transactions_to_yrs(
170        awareness_ref: AwarenessRef,
171        transactions: &[Transaction],
172    ) -> ClientResult<()> {
173        // 使用异步锁获取房间信息
174
175        let mut awareness = awareness_ref.write().await;
176        let doc = awareness.doc_mut();
177        let mut txn =
178            doc.transact_mut_with(doc.client_id().clone().to_string());
179
180        // 使用新版本的转换API应用所有事务中的步骤
181        let context = crate::mapping::create_context(
182            "bulk_transaction_client".to_string(),
183            "bulk_transaction_user".to_string(),
184        );
185
186        for tr in transactions {
187            let steps = &tr.steps;
188            for step in steps {
189                if let Err(e) = crate::mapping::convert_step(
190                    step.as_ref(),
191                    &mut txn,
192                    &context,
193                ) {
194                    tracing::error!("🔄 应用步骤到 Yrs 事务失败: {}", e);
195                }
196            }
197        }
198        // 统一提交所有更改
199        txn.commit();
200        tracing::debug!(
201            "🔄 应用 {} 个事务到文档: {}",
202            transactions.len(),
203            doc.client_id()
204        );
205
206        Ok(())
207    }
208
209    // --- 转换器的辅助方法 ---
210    /// 将 JSON 值转换为 Yrs 的 Any 类型
211    pub fn json_value_to_yrs_any(value: &JsonValue) -> yrs::Any {
212        match value {
213            JsonValue::Null => yrs::Any::Null,
214            JsonValue::Bool(b) => yrs::Any::Bool(*b),
215            JsonValue::Number(n) => {
216                if let Some(i) = n.as_i64() {
217                    yrs::Any::BigInt(i)
218                } else if let Some(f) = n.as_f64() {
219                    yrs::Any::Number(f)
220                } else {
221                    yrs::Any::Null
222                }
223            },
224            JsonValue::String(s) => yrs::Any::String(s.clone().into()),
225            JsonValue::Array(arr) => {
226                let yrs_array: Vec<yrs::Any> =
227                    arr.iter().map(Utils::json_value_to_yrs_any).collect();
228                yrs::Any::Array(yrs_array.into())
229            },
230            JsonValue::Object(obj) => {
231                let yrs_map: std::collections::HashMap<String, yrs::Any> = obj
232                    .iter()
233                    .map(|(k, v)| (k.clone(), Utils::json_value_to_yrs_any(v)))
234                    .collect();
235                yrs::Any::Map(yrs_map.into())
236            },
237        }
238    }
239
240    /// 将标记添加到 Yrs 数组中
241    pub fn add_mark_to_array(
242        marks_array: &ArrayRef,
243        txn: &mut TransactionMut,
244        mark: &Mark,
245    ) {
246        let mark_map = MapPrelim::<yrs::Any>::from([
247            ("type".to_string(), yrs::Any::String(mark.r#type.clone().into())),
248            ("attrs".to_string(), {
249                let attrs_map: std::collections::HashMap<String, yrs::Any> =
250                    mark.attrs
251                        .iter()
252                        .map(|(k, v)| {
253                            (k.clone(), Utils::json_value_to_yrs_any(v))
254                        })
255                        .collect();
256                yrs::Any::Map(attrs_map.into())
257            }),
258        ]);
259        marks_array.push_back(txn, mark_map);
260    }
261
262    /// 获取或创建节点数据映射
263    pub fn get_or_create_node_data_map(
264        nodes_map: &MapRef,
265        txn: &mut TransactionMut,
266        node_id: &str,
267    ) -> MapRef {
268        if let Some(Value::YMap(map)) = nodes_map.get(txn, node_id) {
269            map
270        } else {
271            nodes_map.insert(
272                txn,
273                node_id.to_string(),
274                MapPrelim::<yrs::Any>::new(),
275            )
276        }
277    }
278
279    /// 获取或创建节点属性映射
280    pub fn get_or_create_node_attrs_map(
281        node_data_map: &MapRef,
282        txn: &mut TransactionMut,
283    ) -> MapRef {
284        if let Some(Value::YMap(map)) = node_data_map.get(txn, "attrs") {
285            map
286        } else {
287            node_data_map.insert(txn, "attrs", MapPrelim::<yrs::Any>::new())
288        }
289    }
290
291    /// 获取或创建标记数组
292    pub fn get_or_create_content_array(
293        node_data_map: &MapRef,
294        txn: &mut TransactionMut,
295    ) -> ArrayRef {
296        if let Some(Value::YArray(array)) = node_data_map.get(txn, "content") {
297            array
298        } else {
299            node_data_map.insert(
300                txn,
301                "content",
302                ArrayPrelim::from(Vec::<yrs::Any>::new()),
303            )
304        }
305    }
306
307    /// 将 Yrs 的 Any 类型转换为 JSON 值
308    pub fn yrs_any_to_json_value(value: &yrs::Any) -> Option<JsonValue> {
309        match value {
310            yrs::Any::Null => Some(JsonValue::Null),
311            yrs::Any::Bool(b) => Some(JsonValue::Bool(*b)),
312            yrs::Any::Number(n) => {
313                Some(JsonValue::Number(serde_json::Number::from_f64(*n)?))
314            },
315            yrs::Any::BigInt(i) => {
316                Some(JsonValue::Number(serde_json::Number::from(*i)))
317            },
318            yrs::Any::String(s) => Some(JsonValue::String(s.to_string())),
319            yrs::Any::Array(arr) => {
320                let json_array: Vec<JsonValue> = arr
321                    .iter()
322                    .filter_map(Utils::yrs_any_to_json_value)
323                    .collect();
324                Some(JsonValue::Array(json_array))
325            },
326            yrs::Any::Map(map) => {
327                let json_map: std::collections::HashMap<String, JsonValue> =
328                    map.iter()
329                        .filter_map(|(k, v)| {
330                            Utils::yrs_any_to_json_value(v)
331                                .map(|json_v| (k.to_string(), json_v))
332                        })
333                        .collect();
334                Some(JsonValue::Object(serde_json::Map::from_iter(json_map)))
335            },
336            _ => None, // 处理其他类型,如 YText, YMap 等
337        }
338    }
339
340    /// 获取或创建标记数组
341    pub fn get_or_create_marks_array(
342        node_data_map: &MapRef,
343        txn: &mut TransactionMut,
344    ) -> ArrayRef {
345        if let Some(Value::YArray(array)) = node_data_map.get(txn, "marks") {
346            array
347        } else {
348            node_data_map.insert(
349                txn,
350                "marks",
351                ArrayPrelim::from(Vec::<yrs::Any>::new()),
352            )
353        }
354    }
355
356    /// 从 Yrs 文档中获取根节点ID
357    pub fn get_root_id_from_yrs_doc(doc: &yrs::Doc) -> ClientResult<String> {
358        let txn = doc.transact();
359        // 优先从 meta 区域读取
360        if let Some(meta_map) = txn.get_map("meta") {
361            if let Some(yrs::types::Value::Any(any)) =
362                meta_map.get(&txn, "root_id")
363            {
364                return Ok(any.to_string());
365            }
366        }
367        // fallback: 兼容老数据,取 nodes_map 第一个节点
368        let nodes_map = txn
369            .get_map("nodes")
370            .ok_or(anyhow::anyhow!("Yrs 文档中没有找到 nodes 映射"))?;
371        if let Some((key, _)) = nodes_map.iter(&txn).next() {
372            return Ok(key.to_string());
373        }
374        Err(anyhow::anyhow!("Yrs 文档中没有找到根节点"))
375    }
376
377    /// 从 Yrs 文档的 nodes_map 递归构建所有节点和 parent_map
378    pub fn build_tree_nodes_from_yrs(
379        node_id: &str,
380        nodes_map: &yrs::types::map::MapRef,
381        txn: &yrs::Transaction,
382        tree_nodes: &mut HashMap<NodeId, Arc<Node>>,
383        parent_map: &mut HashMap<NodeId, NodeId>,
384        parent_id: Option<&NodeId>,
385    ) -> ClientResult<()> {
386        let node_data = nodes_map.get(txn, node_id);
387        if node_data.is_none() {
388            return Err(anyhow::anyhow!(
389                "节点 {} 在 Yrs 文档中不存在",
390                node_id
391            ));
392        }
393        let node_data = node_data.unwrap();
394        if let yrs::types::Value::YMap(node_map) = node_data {
395            // 提取节点类型
396            let node_type = node_map
397                .get(txn, "type")
398                .and_then(|v| match v {
399                    yrs::types::Value::Any(any) => Some(any.to_string()),
400                    _ => None,
401                })
402                .unwrap_or_else(|| "unknown".to_string());
403
404            // 提取属性
405            let mut attrs = Attrs::default();
406            if let Some(yrs::types::Value::YMap(attrs_yrs_map)) =
407                node_map.get(txn, "attrs")
408            {
409                for (key, value) in attrs_yrs_map.iter(txn) {
410                    if let yrs::types::Value::Any(any_value) = value {
411                        if let Some(json_value) =
412                            Utils::yrs_any_to_json_value(&any_value)
413                        {
414                            attrs.insert(key.to_string(), json_value);
415                        }
416                    }
417                }
418            }
419
420            // 提取内容(子节点ID列表)
421            let mut content = imbl::Vector::new();
422            if let Some(yrs::types::Value::YArray(content_yrs_array)) =
423                node_map.get(txn, "content")
424            {
425                for item in content_yrs_array.iter(txn) {
426                    if let yrs::types::Value::Any(any) = item {
427                        content.push_back(NodeId::from(any.to_string()));
428                    }
429                }
430            }
431
432            // 提取标记
433            let mut marks = imbl::Vector::new();
434            if let Some(yrs::types::Value::YArray(marks_yrs_array)) =
435                node_map.get(txn, "marks")
436            {
437                for item in marks_yrs_array.iter(txn) {
438                    if let yrs::types::Value::YMap(mark_map) = item {
439                        let mark_type = mark_map
440                            .get(txn, "type")
441                            .and_then(|v| match v {
442                                yrs::types::Value::Any(any) => {
443                                    Some(any.to_string())
444                                },
445                                _ => None,
446                            })
447                            .unwrap_or_else(|| "unknown".to_string());
448
449                        let mut mark_attrs = Attrs::default();
450                        if let Some(yrs::types::Value::YMap(attrs_yrs_map)) =
451                            mark_map.get(txn, "attrs")
452                        {
453                            for (key, value) in attrs_yrs_map.iter(txn) {
454                                if let yrs::types::Value::Any(any_value) = value
455                                {
456                                    if let Some(json_value) =
457                                        Utils::yrs_any_to_json_value(&any_value)
458                                    {
459                                        mark_attrs.insert(
460                                            key.to_string(),
461                                            json_value,
462                                        );
463                                    }
464                                }
465                            }
466                        }
467
468                        marks.push_back(Mark {
469                            r#type: mark_type,
470                            attrs: mark_attrs,
471                        });
472                    }
473                }
474            }
475
476            // 创建节点
477            let content_vec: Vec<NodeId> =
478                content.clone().into_iter().collect();
479            let marks_vec: Vec<Mark> = marks.clone().into_iter().collect();
480            let node =
481                Node::new(node_id, node_type, attrs, content_vec, marks_vec);
482
483            let node_id_typed = NodeId::from(node_id);
484            tree_nodes.insert(node_id_typed.clone(), Arc::new(node));
485
486            // 记录父子关系
487            if let Some(parent) = parent_id {
488                parent_map.insert(node_id_typed.clone(), parent.clone());
489            }
490
491            // 递归处理子节点
492            for child_id in content {
493                Utils::build_tree_nodes_from_yrs(
494                    &child_id,
495                    nodes_map,
496                    txn,
497                    tree_nodes,
498                    parent_map,
499                    Some(&node_id_typed),
500                )?;
501            }
502        }
503        Ok(())
504    }
505
506    /// 递归构建 NodeTree
507    pub fn build_node_enum_from_map(
508        node: &Node,
509        tree_nodes: &HashMap<NodeId, Arc<Node>>,
510    ) -> mf_model::node_definition::NodeTree {
511        let mut children = Vec::new();
512        for child_id in &node.content {
513            if let Some(child_node) = tree_nodes.get(child_id) {
514                children.push(Utils::build_node_enum_from_map(
515                    child_node, tree_nodes,
516                ));
517            }
518        }
519        mf_model::node_definition::NodeTree(node.clone(), children)
520    }
521}