import 'dart:async'; import 'package:fl_lib/fl_lib.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/store/container.dart'; import 'package:server_box/data/store/setting.dart'; import 'package:server_box/data/store/snippet.dart'; class ServerStore extends HiveStore { ServerStore._() : super('server'); static final instance = ServerStore._(); List? _cache; StreamSubscription? _boxWatchSub; bool _suppressWatch = false; @override Future init() async { await super.init(); _boxWatchSub?.cancel(); _boxWatchSub = box.watch().listen((_) { if (!_suppressWatch) { _cache = null; } }); } @override bool clear({bool? updateLastUpdateTsOnClear}) { _suppressWatch = true; try { _cache = null; return super.clear(updateLastUpdateTsOnClear: updateLastUpdateTsOnClear); } finally { _suppressWatch = false; } } void invalidateCache() { _cache = null; } void put(Spi info) { _suppressWatch = true; try { set(info.id, info); _cache = null; } finally { _suppressWatch = false; } } void _putWithoutInvalidatingCache(Spi info) { _suppressWatch = true; try { box.put(info.id, info); } finally { _suppressWatch = false; } } List fetch() { return List.from(_cache ??= _loadAll()); } List _loadAll() { final List ss = []; for (final id in keys()) { final s = get( id, fromObj: (val) { if (val is Spi) return val; if (val is Map) { final map = val.toStrDynMap; if (map == null) return null; try { final spi = Spi.fromJson(map as Map); _putWithoutInvalidatingCache(spi); return spi; } catch (e) { dprint('Parsing Spi from JSON', e); } } return null; }, ); if (s != null) { ss.add(s); } } return ss; } void delete(String id) { _suppressWatch = true; try { remove(id); _cache = null; } finally { _suppressWatch = false; } } void update(Spi old, Spi newInfo) { if (!have(old)) { throw Exception('Old spi: $old not found'); } _suppressWatch = true; try { remove(old.id); set(newInfo.id, newInfo); _cache = null; } finally { _suppressWatch = false; } } bool have(Spi s) => get(s.id) != null; void migrateIds() { final ss = fetch(); final idMap = {}; for (final s in ss) { final newId = s.migrateId(); if (newId == null) continue; idMap[s.oldId] = newId; } final srvOrder = SettingStore.instance.serverOrder.fetch(); final snippets = SnippetStore.instance.fetch(); final container = ContainerStore.instance; bool srvOrderChanged = false; for (final e in idMap.entries) { final oldId = e.key; final newId = e.value; final srvIdx = srvOrder.indexOf(oldId); if (srvIdx != -1) { srvOrder[srvIdx] = newId; srvOrderChanged = true; } final spi = get(newId); if (spi != null) { final jumpId = spi.jumpId; if (jumpId != null && idMap.containsKey(jumpId)) { final newJumpId = idMap[jumpId]; if (spi.jumpId != newJumpId) { final newSpi = spi.copyWith(jumpId: newJumpId); update(spi, newSpi); } } } for (final snippet in snippets) { final autoRunsOn = snippet.autoRunOn; final idx = autoRunsOn?.indexOf(oldId); if (idx != null && idx != -1) { final newAutoRunsOn = List.from(autoRunsOn ?? []); newAutoRunsOn[idx] = newId; final newSnippet = snippet.copyWith(autoRunOn: newAutoRunsOn); SnippetStore.instance.update(snippet, newSnippet); } } final dockerHost = container.fetch(oldId); if (dockerHost != null) { container.remove(oldId); container.set(newId, dockerHost); } } for (final spi in ss) { if (get(spi.id) == null) continue; if (spi.jumpId != null && idMap.containsKey(spi.jumpId)) { final newJumpId = idMap[spi.jumpId]!; final newSpi = spi.copyWith(jumpId: newJumpId); update(spi, newSpi); } } if (srvOrderChanged) { SettingStore.instance.serverOrder.put(srvOrder); } } }