Skip to main content

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