f1e0f6b5ef
- Add complete server infrastructure with Gitea, API, PostgreSQL - Implement Obsidian-compatible markdown mindmap converter - Add Flutter service for server synchronization - Configure GitHub Actions for automated build and deploy - Add production docker-compose with health checks - Include VPS setup and deployment scripts - Add comprehensive deployment documentation
101 lines
2.8 KiB
Dart
101 lines
2.8 KiB
Dart
import 'package:reactive_mind_map/reactive_mind_map.dart' as rm;
|
|
import '../models/mind_map_model.dart';
|
|
|
|
/// Адаптер для конвертации MindMapNode в формат reactive_mind_map
|
|
class MindMapAdapter {
|
|
/// Конвертирует список MindMapNode в rm.MindMapData для reactive_mind_map
|
|
static rm.MindMapData nodesToMindMapData(List<MindMapNode> nodes) {
|
|
if (nodes.isEmpty) {
|
|
return rm.MindMapData(
|
|
id: 'empty',
|
|
title: 'Пустая карта',
|
|
children: [],
|
|
);
|
|
}
|
|
|
|
// Находим корневой узел (level 0)
|
|
final rootNodes = nodes.where((n) => n.level == 0).toList();
|
|
|
|
if (rootNodes.isEmpty) {
|
|
// Если нет корневого узла, создаём его
|
|
return rm.MindMapData(
|
|
id: 'auto_root',
|
|
title: 'Автоматический корень',
|
|
children: _buildChildren(nodes, null, nodes),
|
|
);
|
|
}
|
|
|
|
final root = rootNodes.first;
|
|
return rm.MindMapData(
|
|
id: root.id,
|
|
title: root.title,
|
|
children: _buildChildren(nodes, root.id, nodes),
|
|
);
|
|
}
|
|
|
|
/// Рекурсивно строит дочерние узлы
|
|
static List<rm.MindMapData> _buildChildren(
|
|
List<MindMapNode> allNodes,
|
|
String? parentId,
|
|
List<MindMapNode> nodes,
|
|
) {
|
|
final children = allNodes.where((n) => n.parentId == parentId).toList();
|
|
|
|
return children.map((node) {
|
|
return rm.MindMapData(
|
|
id: node.id,
|
|
title: node.title,
|
|
children: _buildChildren(allNodes, node.id, nodes),
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
/// Конвертирует rm.MindMapData обратно в список MindMapNode
|
|
static List<MindMapNode> mindMapDataToNodes(
|
|
rm.MindMapData data,
|
|
String projectId, {
|
|
String? parentId,
|
|
int level = 0,
|
|
}) {
|
|
final nodes = <MindMapNode>[];
|
|
final now = DateTime.now();
|
|
|
|
nodes.add(MindMapNode(
|
|
id: data.id,
|
|
projectId: projectId,
|
|
parentId: parentId,
|
|
level: level,
|
|
title: data.title,
|
|
color: '#2196F3', // Default color, можно улучшить хранить цвет в metadata
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
));
|
|
|
|
// Рекурсивно добавляем детей
|
|
for (final child in data.children!) {
|
|
nodes.addAll(mindMapDataToNodes(
|
|
child,
|
|
projectId,
|
|
parentId: data.id,
|
|
level: level + 1,
|
|
));
|
|
}
|
|
|
|
return nodes;
|
|
}
|
|
|
|
/// HEX → int (для reactive_mind_map)
|
|
static int _hexToColorInt(String hex) {
|
|
hex = hex.replaceAll('#', '');
|
|
if (hex.length == 6) {
|
|
return int.parse('FF$hex', radix: 16);
|
|
}
|
|
return 0xFF2196F3; // Default blue
|
|
}
|
|
|
|
/// int → HEX (для MindMapNode)
|
|
static String _colorIntToHex(int color) {
|
|
return '#${(color & 0xFFFFFF).toRadixString(16).padLeft(6, '0').toUpperCase()}';
|
|
}
|
|
}
|