mf_collab_client/
utils.rs

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