import 'dart:developer'; import 'dart:io'; import 'package:hydrated_bloc/hydrated_bloc.dart'; /// Opens the HydratedBloc box; a corrupt box is dropped and rebuilt, and if /// even that fails the app runs on [InMemoryStorage] instead of never /// reaching `runApp`. Future buildHydratedStorageWithFallback(String directoryPath) async { final directory = HydratedStorageDirectory(directoryPath); try { return await HydratedStorage.build(storageDirectory: directory); } catch (e, s) { log('HydratedStorage open failed, rebuilding: $e', stackTrace: s); } try { await _deleteHydratedBox(directoryPath); return await HydratedStorage.build(storageDirectory: directory); } catch (e, s) { log('HydratedStorage rebuild failed, using memory: $e', stackTrace: s); return InMemoryStorage(); } } Future _deleteHydratedBox(String directoryPath) async { final directory = Directory(directoryPath); if (!directory.existsSync()) return; await for (final entity in directory.list()) { final name = entity.uri.pathSegments.lastWhere((s) => s.isNotEmpty); if (entity is File && name.startsWith('hydrated_box')) { await entity.delete(); } } } /// Non-persistent [Storage]; state lives for the session only. class InMemoryStorage implements Storage { final Map _values = {}; @override dynamic read(String key) => _values[key]; @override Future write(String key, dynamic value) async => _values[key] = value; @override Future delete(String key) async => _values.remove(key); @override Future clear() async => _values.clear(); @override Future close() async {} }