Skip to content

Commit 1d51fe0

Browse files
Added: Local Storage
1 parent 87f2baf commit 1d51fe0

File tree

11 files changed

+660
-29
lines changed

11 files changed

+660
-29
lines changed

lib/vaahextendflutter/base/base_controller.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import '../env/env.dart';
1111
import '../services/api.dart';
1212
import '../services/notification/internal/notification.dart';
1313
import '../services/notification/push/notification.dart';
14+
import '../services/storage/local/storage.dart';
1415
import 'root_assets_controller.dart';
1516

1617
class BaseController extends GetxController {
@@ -47,6 +48,8 @@ class BaseController extends GetxController {
4748
await InternalNotifications.init();
4849
PushNotifications.askPermission();
4950

51+
await LocalDatabaseStorage.init();
52+
5053
// Sentry Initialization (And/ Or) Running main app
5154
if (null != config.sentryConfig && config.sentryConfig!.dsn.isNotEmpty) {
5255
await SentryFlutter.init(

lib/vaahextendflutter/env/env.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:json_annotation/json_annotation.dart';
99
import '../services/logging_library/logging_library.dart';
1010
import 'logging.dart';
1111
import 'notification.dart';
12+
import 'storage.dart';
1213

1314
part 'env.g.dart';
1415

@@ -62,6 +63,7 @@ class EnvironmentConfig {
6263
this.oneSignalConfig,
6364
this.pusherConfig,
6465
required this.showDebugPanel,
66+
required this.localDatabaseStorageType,
6567
required this.debugPanelColor,
6668
});
6769

@@ -82,6 +84,7 @@ class EnvironmentConfig {
8284
final OneSignalConfig? oneSignalConfig;
8385
final PusherConfig? pusherConfig;
8486
final bool showDebugPanel;
87+
final LocalDatabaseStorageType localDatabaseStorageType;
8588
@JsonKey(fromJson: _colorFromJson, toJson: _colorToJson)
8689
final Color debugPanelColor;
8790

@@ -123,6 +126,7 @@ class EnvironmentConfig {
123126
pushNotificationsServiceType: PushNotificationsServiceType.none,
124127
internalNotificationsServiceType: InternalNotificationsServiceType.none,
125128
showDebugPanel: true,
129+
localDatabaseStorageType: LocalDatabaseStorageType.none,
126130
debugPanelColor: Colors.black.withOpacity(0.8),
127131
);
128132
}

lib/vaahextendflutter/env/env.g.dart

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
enum LocalDatabaseStorageType { hive, none }
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
abstract class LocalStorageService {
2+
static Future<LocalStorageService> init() async {
3+
throw UnimplementedError();
4+
}
5+
6+
Future<void> addCollection({
7+
required String collectionName,
8+
});
9+
10+
Future<void> create({
11+
required String collectionName,
12+
required String key,
13+
required String value,
14+
});
15+
16+
Future<void> createMany({
17+
required String collectionName,
18+
required Map<String, String> values,
19+
});
20+
21+
Future<String?> read({
22+
required String collectionName,
23+
required String key,
24+
});
25+
26+
Future<Map<String, String>> readMany({
27+
required String collectionName,
28+
required List<String> keys,
29+
});
30+
31+
Future<Map<String, String>> readAll({
32+
required String collectionName,
33+
});
34+
35+
Future<void> update({
36+
required String collectionName,
37+
required String key,
38+
required String value,
39+
});
40+
41+
Future<void> updateMany({
42+
required String collectionName,
43+
required Map<String, String> values,
44+
});
45+
46+
Future<void> createOrUpdate({
47+
required String collectionName,
48+
required String key,
49+
required String value,
50+
});
51+
52+
Future<void> createOrUpdateMany({
53+
required String collectionName,
54+
required Map<String, String> values,
55+
});
56+
57+
Future<void> delete({required String collectionName, required String key});
58+
59+
Future<void> deleteMany({
60+
required String collectionName,
61+
List<String> keys = const [],
62+
});
63+
64+
Future<void> deleteAll({required String collectionName});
65+
}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
import 'dart:io';
2+
3+
import 'package:hive/hive.dart';
4+
import 'package:path_provider/path_provider.dart';
5+
6+
import 'base_storage.dart';
7+
8+
/// A class implementing LocalStorageService interface using Hive as storage backend.
9+
class LocalHiveStorage implements LocalStorageService {
10+
static Future<LocalHiveStorage> init() async {
11+
final Directory docsDirectory = await getApplicationDocumentsDirectory();
12+
final String storagePath = '${docsDirectory.path}/vaahflutter';
13+
final Directory storageDirectory = await Directory(storagePath).create(
14+
recursive: true,
15+
);
16+
17+
Hive.init(storageDirectory.path);
18+
return LocalHiveStorage();
19+
}
20+
21+
final Map<String, Future<Box>> _collections = {
22+
'vaah-flutter-box': Hive.openBox('vaah-flutter-box'),
23+
};
24+
25+
@override
26+
Future<void> addCollection({
27+
required String collectionName,
28+
}) async {
29+
if (!_collections.containsKey(collectionName)) {
30+
_collections[collectionName] = Hive.openBox(collectionName);
31+
}
32+
}
33+
34+
@override
35+
Future<void> create({
36+
required String collectionName,
37+
required String key,
38+
required String value,
39+
}) async {
40+
if (!_collections.containsKey(collectionName)) {
41+
return;
42+
}
43+
final Box box = await _collections[collectionName]!;
44+
if (box.containsKey(key)) {}
45+
46+
await box.put(key, value);
47+
}
48+
49+
@override
50+
Future<void> createMany({
51+
required String collectionName,
52+
required Map<String, String> values,
53+
}) async {
54+
final List<String> errors = [];
55+
final List<String> success = [];
56+
for (final String key in values.keys) {
57+
try {
58+
await create(
59+
collectionName: collectionName,
60+
key: key,
61+
value: values[key]!,
62+
);
63+
success.add(key);
64+
} catch (e, st) {
65+
errors.add(key);
66+
}
67+
}
68+
return;
69+
}
70+
71+
@override
72+
Future<String?> read({
73+
required String collectionName,
74+
required String key,
75+
}) async {
76+
if (!_collections.containsKey(collectionName)) {
77+
throw 'no collection data found';
78+
}
79+
final Box box = await _collections[collectionName]!;
80+
if (!box.containsKey(key)) {
81+
throw 'no data found';
82+
}
83+
84+
return box.get(key);
85+
}
86+
87+
@override
88+
Future<Map<String, String>> readMany({
89+
required String collectionName,
90+
required List<String> keys,
91+
}) async {
92+
final Map<String, String?> success = {};
93+
final List<String> errors = [];
94+
for (final String key in keys) {
95+
try {
96+
final String? result = await read(collectionName: collectionName, key: key);
97+
if (result != null) {
98+
success[key] = result;
99+
} else {
100+
errors.add(key);
101+
}
102+
} catch (e, st) {
103+
errors.add(key);
104+
}
105+
}
106+
return {};
107+
}
108+
109+
@override
110+
Future<Map<String, String>> readAll({required String collectionName}) async {
111+
if (!_collections.containsKey(collectionName)) {
112+
throw 'no collection found';
113+
}
114+
final Box box = await _collections[collectionName]!;
115+
return box.toMap().map(
116+
(key, value) {
117+
return MapEntry(
118+
key.toString(),
119+
value.toString(),
120+
);
121+
},
122+
);
123+
}
124+
125+
@override
126+
Future<void> update({
127+
required String collectionName,
128+
required String key,
129+
required String value,
130+
}) async {
131+
if (!_collections.containsKey(collectionName)) {
132+
throw 'no collection found';
133+
}
134+
final Box box = await _collections[collectionName]!;
135+
if (!box.containsKey(key)) {
136+
throw 'no key found';
137+
}
138+
return await box.put(key, value);
139+
}
140+
141+
@override
142+
Future<void> updateMany({
143+
required String collectionName,
144+
required Map<String, String> values,
145+
}) async {
146+
final List<String> errors = [];
147+
final List<String> success = [];
148+
for (final String key in values.keys) {
149+
try {
150+
await update(
151+
collectionName: collectionName,
152+
key: key,
153+
value: values[key]!,
154+
);
155+
success.add(key);
156+
} catch (e, st) {
157+
errors.add(key);
158+
}
159+
}
160+
}
161+
162+
@override
163+
Future<void> createOrUpdate({
164+
required String collectionName,
165+
required String key,
166+
required String value,
167+
}) async {
168+
if (!_collections.containsKey(collectionName)) {
169+
throw 'no collection found';
170+
}
171+
final Box box = await _collections[collectionName]!;
172+
if (!box.containsKey(key)) {
173+
return create(collectionName: collectionName, key: key, value: value);
174+
}
175+
return update(collectionName: collectionName, key: key, value: value);
176+
}
177+
178+
@override
179+
Future<void> createOrUpdateMany({
180+
required String collectionName,
181+
required Map<String, String> values,
182+
}) async {
183+
final List<String> errors = [];
184+
final List<String> success = [];
185+
for (final String key in values.keys) {
186+
try {
187+
await createOrUpdate(
188+
collectionName: collectionName,
189+
key: key,
190+
value: values[key]!,
191+
);
192+
success.add(key);
193+
} catch (e, st) {
194+
errors.add(key);
195+
}
196+
}
197+
}
198+
199+
@override
200+
Future<void> delete({required String collectionName, dynamic key}) async {
201+
if (!_collections.containsKey(collectionName)) {
202+
throw 'no collection found';
203+
}
204+
final Box box = await _collections[collectionName]!;
205+
if (!box.containsKey(key)) {
206+
throw 'no key found';
207+
}
208+
await box.delete(key);
209+
}
210+
211+
@override
212+
Future<void> deleteMany({
213+
required String collectionName,
214+
List<String> keys = const [],
215+
}) async {
216+
final List<String> errors = [];
217+
if (!_collections.containsKey(collectionName)) {
218+
throw 'no collection found';
219+
}
220+
final List<String> nonExistingKeys = [];
221+
final List<String> existingKeys = [];
222+
final Box box = await _collections[collectionName]!;
223+
for (int i = 0; i < keys.length; i++) {
224+
if (!box.containsKey(keys[i])) {
225+
errors.add(keys[i]);
226+
nonExistingKeys.add(keys[i]);
227+
} else {
228+
existingKeys.add(keys[i]);
229+
}
230+
}
231+
if (nonExistingKeys.isEmpty) {
232+
await box.deleteAll(keys);
233+
} else {
234+
await box.deleteAll(existingKeys);
235+
// Notify about errors
236+
}
237+
}
238+
239+
@override
240+
Future<void> deleteAll({required String collectionName}) async {
241+
if (!_collections.containsKey(collectionName)) {
242+
throw 'no collection found';
243+
}
244+
final Box box = await _collections[collectionName]!;
245+
await box.clear();
246+
}
247+
}

0 commit comments

Comments
 (0)