Files
Avtex/lib/core/local_storage_service.dart
T
Alexyz f1e0f6b5ef feat: Add Nanaxe server with Docker, GitHub Actions CI/CD, and auto-deployment
- 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
2026-04-19 22:18:25 +05:00

178 lines
5.7 KiB
Dart

import 'package:hive_flutter/hive_flutter.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../models/task_model.dart';
import '../models/alarm_model.dart';
import '../models/mind_map_model.dart';
import '../models/calendar_event_model.dart';
class LocalStorageService {
static const String _tasksBoxName = 'tasks';
static const String _alarmsBoxName = 'alarms';
static const String _mindMapsBoxName = 'mindMaps';
static const String _eventsBoxName = 'events';
static const String _settingsBoxName = 'settings';
late Box<Map> _tasksBox;
late Box<Map> _alarmsBox;
late Box<Map> _mindMapsBox;
late Box<Map> _eventsBox;
late Box<Object?> _settingsBox;
Future<void> initialize() async {
await Hive.initFlutter();
_tasksBox = await Hive.openBox<Map>(_tasksBoxName);
_alarmsBox = await Hive.openBox<Map>(_alarmsBoxName);
_mindMapsBox = await Hive.openBox<Map>(_mindMapsBoxName);
_eventsBox = await Hive.openBox<Map>(_eventsBoxName);
_settingsBox = await Hive.openBox<Object?>(_settingsBoxName);
}
// Tasks
Future<void> saveTask(TaskModel task) async {
final data = _convertTimestamps(task.toFirestore());
data['id'] = task.id; // Добавляем id для fromMap
await _tasksBox.put(task.id, data);
}
Future<void> saveTasks(List<TaskModel> tasks) async {
for (final task in tasks) {
final data = _convertTimestamps(task.toFirestore());
data['id'] = task.id;
await _tasksBox.put(task.id, data);
}
}
List<TaskModel> getTasks() {
return _tasksBox.values.map((data) {
final restoredData = _restoreTimestamps(data);
return TaskModel.fromMap(restoredData);
}).toList();
}
Future<void> deleteTask(String taskId) async {
await _tasksBox.delete(taskId);
}
// Alarms
Future<void> saveAlarm(AlarmModel alarm) async {
await _alarmsBox.put(alarm.id, _convertTimestamps(alarm.toFirestore()));
}
List<AlarmModel> getAlarms() {
return _alarmsBox.keys.map((id) {
final data = _alarmsBox.get(id) as Map<dynamic, dynamic>;
final restoredData = _restoreTimestamps(data);
return AlarmModel.fromMap(id.toString(), restoredData);
}).toList();
}
Future<void> deleteAlarm(String alarmId) async {
await _alarmsBox.delete(alarmId);
}
// Mind Maps
Future<void> saveMindMapNodes(List<MindMapNode> nodes) async {
for (final node in nodes) {
await _mindMapsBox.put(node.id, _convertTimestamps(node.toFirestore()));
}
}
List<MindMapNode> getMindMapNodes() {
return _mindMapsBox.keys.map((id) {
final data = _mindMapsBox.get(id) as Map<dynamic, dynamic>;
final restoredData = _restoreTimestamps(data);
return MindMapNode.fromMap(id.toString(), restoredData);
}).toList();
}
// Events
Future<void> saveEvent(CalendarEventModel event) async {
await _eventsBox.put(event.id, _convertTimestamps(event.toFirestore()));
}
List<CalendarEventModel> getEvents() {
return _eventsBox.keys.map((id) {
final data = _eventsBox.get(id) as Map<dynamic, dynamic>;
final restoredData = _restoreTimestamps(data);
return CalendarEventModel.fromMap(id.toString(), restoredData);
}).toList();
}
// Settings
Future<void> saveSetting(String key, Object? value) async {
await _settingsBox.put(key, value);
}
T? getSetting<T>(String key, {T? defaultValue}) {
return _settingsBox.get(key, defaultValue: defaultValue) as T?;
}
// Clear all local data
Future<void> clearAll() async {
await _tasksBox.clear();
await _alarmsBox.clear();
await _mindMapsBox.clear();
await _eventsBox.clear();
await _settingsBox.clear();
}
// Sync with Firebase (merge remote and local)
Future<void> syncWithRemote(List<TaskModel> remoteTasks) async {
final localTasks = getTasks();
final localMap = {for (var t in localTasks) t.id: t};
final remoteMap = {for (var t in remoteTasks) t.id: t};
// Merge: remote takes precedence
final merged = {...localMap, ...remoteMap};
await _tasksBox.clear();
for (final task in merged.values) {
await _tasksBox.put(task.id, _convertTimestamps(task.toFirestore()));
}
}
// Конвертирует Firestore Timestamp в ISO строки для Hive
Map<String, dynamic> _convertTimestamps(Map<String, dynamic> data) {
final converted = <String, dynamic>{};
for (final entry in data.entries) {
if (entry.value is Timestamp) {
// Конвертируем Timestamp → ISO строка
converted[entry.key] = {
'__type__': 'timestamp',
'value': (entry.value as Timestamp).toDate().toIso8601String(),
};
} else if (entry.value is Map<String, dynamic>) {
converted[entry.key] =
_convertTimestamps(entry.value as Map<String, dynamic>);
} else {
converted[entry.key] = entry.value;
}
}
return converted;
}
// Восстанавливает ISO строки обратно в Timestamp из Hive
Map<String, dynamic> _restoreTimestamps(Map<dynamic, dynamic> data) {
final converted = <String, dynamic>{};
for (final entry in data.entries) {
final key = entry.key.toString();
if (entry.value is Map &&
(entry.value as Map).containsKey('__type__') &&
(entry.value as Map)['__type__'] == 'timestamp') {
// Конвертируем ISO строку → Timestamp
final dateStr = (entry.value as Map)['value'] as String;
converted[key] = Timestamp.fromDate(DateTime.parse(dateStr));
} else if (entry.value is Map) {
converted[key] =
_restoreTimestamps(entry.value as Map<dynamic, dynamic>);
} else {
converted[key] = entry.value;
}
}
return converted;
}
}
final localStorageService = LocalStorageService();