Line data Source code
1 : import 'dart:convert'; 2 : import 'package:flutter/widgets.dart'; 3 : import 'storage/html.dart' if (dart.library.io) 'storage/io.dart'; 4 : import 'value.dart'; 5 : 6 : /// Instantiate GetStorage to access storage driver apis 7 : class GetStorage { 8 1 : factory GetStorage( 9 : [String container = 'GetStorage', 10 : String path, 11 : Map<String, dynamic> initialData]) { 12 2 : if (_sync.containsKey(container)) { 13 2 : return _sync[container]; 14 : } else { 15 1 : final instance = GetStorage._internal(container, path, initialData); 16 2 : _sync[container] = instance; 17 : return instance; 18 : } 19 : } 20 : 21 1 : GetStorage._internal(String key, 22 : [String path, Map<String, dynamic> initialData]) { 23 2 : _concrete = StorageImpl(key, path); 24 1 : _initialData = initialData; 25 : 26 3 : initStorage = Future<bool>(() async { 27 2 : await _init(); 28 : return true; 29 : }); 30 : } 31 : 32 3 : static final Map<String, GetStorage> _sync = {}; 33 : 34 : /// Start the storage drive. Importate: use await before calling this api, or side effects will happen. 35 1 : static Future<bool> init([String container = 'GetStorage']) { 36 1 : WidgetsFlutterBinding.ensureInitialized(); 37 : if (container == null) { 38 : throw 'key can not be null'; 39 : } 40 2 : return GetStorage(container).initStorage; 41 : } 42 : 43 1 : Future<void> _init() async { 44 : try { 45 4 : await _concrete.init(_initialData); 46 : } catch (err) { 47 : throw err; 48 : } 49 : } 50 : 51 : /// Reads a value in your container with the given key. 52 1 : T read<T>(String key) { 53 2 : return _concrete.read(key); 54 : } 55 : 56 : /// return data true if value is different of null; 57 1 : bool hasData(String key) { 58 1 : return (read(key) == null ? false : true); 59 : } 60 : 61 4 : Map<String, dynamic> get changes => _concrete.subject.changes; 62 : 63 : /// Listen changes in your container 64 1 : void listen(void Function() value) { 65 3 : _concrete.subject.addListener(value); 66 : } 67 : 68 : Map<Function, Function> _keyListeners = <Function, Function>{}; 69 : 70 1 : void listenKey(String key, Function(dynamic) callback) { 71 1 : final listen = () { 72 4 : if (changes.keys.first == key) { 73 3 : callback(changes[key]); 74 : } 75 : }; 76 3 : _concrete.subject.addListener(listen); 77 2 : _keyListeners[callback] = listen; 78 : } 79 : 80 : /// Remove listen of your container 81 1 : void removeKeyListen(Function(Map<String, dynamic>) callback) { 82 5 : _concrete.subject.removeListener(_keyListeners[callback]); 83 : } 84 : 85 : /// Remove listen of your container 86 1 : void removeListen(void Function() listener) { 87 3 : _concrete.subject.removeListener(listener); 88 : } 89 : 90 : /// Write data on your container 91 1 : Future<void> write(String key, dynamic value, 92 : [EncodeObject objectToEncode]) async { 93 : final _encoded = 94 1 : json.encode(objectToEncode != null ? objectToEncode(value) : value); 95 4 : await _concrete.write(key, json.decode(_encoded)); 96 : 97 1 : return _tryFlush(); 98 : } 99 : 100 : /// Write data on your only if data is null 101 1 : Future<void> writeIfNull(String key, dynamic value, 102 : [EncodeObject objectToEncode]) async { 103 1 : if (read(key) != null) return; 104 : final _encoded = 105 1 : json.encode(objectToEncode != null ? objectToEncode(value) : value); 106 4 : await _concrete.write(key, json.decode(_encoded)); 107 1 : return _tryFlush(); 108 : } 109 : 110 : /// remove data from container by key 111 1 : Future<void> remove(String key) async { 112 3 : await _concrete.remove(key); 113 1 : return _tryFlush(); 114 : } 115 : 116 : /// clear all data on your container 117 1 : Future<void> erase() async { 118 3 : await _concrete.clear(); 119 1 : return _tryFlush(); 120 : } 121 : 122 1 : Future<void> _tryFlush() async { 123 1 : if (_lockDatabase != null) { 124 2 : await _lockDatabase; 125 : } 126 2 : _lockDatabase = _flush(); 127 1 : return _lockDatabase; 128 : } 129 : 130 1 : Future<void> _flush() async { 131 : try { 132 3 : await _concrete.flush(); 133 : } catch (e) { 134 : rethrow; 135 : } 136 : return; 137 : } 138 : 139 : StorageImpl _concrete; 140 : 141 : /// listenable of container 142 3 : Value<Map<String, dynamic>> get listenable => _concrete.subject; 143 : 144 : /// Start the storage drive. Importate: use await before calling this api, or side effects will happen. 145 : Future<bool> initStorage; 146 : 147 : Future<void> _lockDatabase; 148 : 149 : Map<String, dynamic> _initialData; 150 : } 151 : 152 : typedef EncodeObject = Object Function(Object); 153 : 154 : typedef KeyCallback = Function(String);