184 lines
5.7 KiB
Dart
184 lines
5.7 KiB
Dart
import 'dart:convert' show jsonDecode, jsonEncode;
|
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../model/bookmark.dart';
|
|
import '../model/collection.dart';
|
|
import 'json_file_service.dart';
|
|
|
|
class Storage {
|
|
static const String _bookmarksKey = 'bookmarks';
|
|
static const String _collectionsKey = 'collections';
|
|
static SharedPreferencesWithCache? _prefsWithCache;
|
|
static const String _statsKey = 'stats';
|
|
|
|
static Future<void> initialize() async {
|
|
_prefsWithCache = await SharedPreferencesWithCache.create(
|
|
cacheOptions: const SharedPreferencesWithCacheOptions(
|
|
allowList: <String>{_collectionsKey, _bookmarksKey, _statsKey},
|
|
),
|
|
);
|
|
}
|
|
|
|
static List<Collection> loadCollections() {
|
|
final jsonString = _prefs.getString(_collectionsKey) ?? '[]';
|
|
final jsonList = jsonDecode(jsonString) as List;
|
|
return jsonList
|
|
.map((json) => Collection.fromJson(json as Map<String, dynamic>))
|
|
.toList();
|
|
}
|
|
|
|
static List<Bookmark> loadBookmarks() {
|
|
final jsonString = _prefs.getString(_bookmarksKey) ?? '[]';
|
|
final jsonList = jsonDecode(jsonString) as List;
|
|
return jsonList
|
|
.map((json) => Bookmark.fromJson(json as Map<String, dynamic>))
|
|
.toList();
|
|
}
|
|
|
|
static Future<void> saveCollections(List<Collection> collections) async {
|
|
final jsonList = collections.map((c) => c.toJson()).toList();
|
|
await _prefs.setString(_collectionsKey, jsonEncode(jsonList));
|
|
}
|
|
|
|
static Future<void> saveBookmarks(List<Bookmark> bookmarks) async {
|
|
final jsonList = bookmarks.map((b) => b.toJson()).toList();
|
|
await _prefs.setString(_bookmarksKey, jsonEncode(jsonList));
|
|
}
|
|
|
|
static List<Bookmark> loadBookmarksForCollection(int collectionId) {
|
|
final allBookmarks = loadBookmarks();
|
|
return allBookmarks.where((b) => b.collectionId == collectionId).toList();
|
|
}
|
|
|
|
static Map<int, int> loadPerCollectionBookmarkCount() {
|
|
return loadBookmarks().fold(<int, int>{}, (map, bookmark) {
|
|
map[bookmark.collectionId] ??= 0;
|
|
map[bookmark.collectionId] = map[bookmark.collectionId]! + 1;
|
|
return map;
|
|
});
|
|
}
|
|
|
|
static Future<void> addBookmark(Bookmark bookmark) async {
|
|
final bookmarks = loadBookmarks();
|
|
bookmarks.add(bookmark);
|
|
await saveBookmarks(bookmarks);
|
|
}
|
|
|
|
static Future<void> addOrUpdateBookmark(Bookmark bookmark) async {
|
|
final bookmarks = loadBookmarks();
|
|
final index = bookmarks.indexWhere((b) => b.id == bookmark.id);
|
|
|
|
if (index == -1) {
|
|
bookmarks.add(bookmark);
|
|
} else if (index >= 0) {
|
|
bookmarks[index] = bookmark;
|
|
}
|
|
await saveBookmarks(bookmarks);
|
|
}
|
|
|
|
static Future<void> addOrUpdateCollection(Collection collection) async {
|
|
final collections = loadCollections();
|
|
final index = collections.indexWhere((b) => b.id == collection.id);
|
|
|
|
if (index == -1) {
|
|
collections.add(collection);
|
|
} else if (index >= 0) {
|
|
collections[index] = collection;
|
|
}
|
|
await saveCollections(collections);
|
|
}
|
|
|
|
static Future<void> updateBookmarkById(
|
|
int bookmarkId, {
|
|
String? name,
|
|
String? description,
|
|
String? link,
|
|
}) async {
|
|
final bookmarks = loadBookmarks();
|
|
final index = bookmarks.indexWhere((b) => b.id == bookmarkId);
|
|
|
|
if (index == -1) return;
|
|
|
|
if (name != null) bookmarks[index].name = name;
|
|
if (description != null) bookmarks[index].description = description;
|
|
if (link != null) bookmarks[index].link = link;
|
|
|
|
await saveBookmarks(bookmarks);
|
|
}
|
|
|
|
static Future<void> deleteBookmark(Bookmark bookmark) async {
|
|
final bookmarks = loadBookmarks();
|
|
bookmarks.remove(bookmark);
|
|
await saveBookmarks(bookmarks);
|
|
}
|
|
|
|
static Future<void> deleteBookmarkById(int bookmarkId) async {
|
|
final bookmarks = loadBookmarks();
|
|
bookmarks.removeWhere((b) => b.id == bookmarkId);
|
|
await saveBookmarks(bookmarks);
|
|
}
|
|
|
|
static Future<void> deleteBookmarksForCollection(int collectionId) async {
|
|
final bookmarks = loadBookmarks();
|
|
bookmarks.removeWhere((b) => b.collectionId == collectionId);
|
|
await saveBookmarks(bookmarks);
|
|
}
|
|
|
|
static Future<void> deleteCollection(Collection collection) async {
|
|
final collections = loadCollections();
|
|
final bookmarks = loadBookmarks();
|
|
bookmarks.removeWhere((bookmark) => bookmark.collectionId == collection.id);
|
|
collections.remove(collection);
|
|
await saveBookmarks(bookmarks);
|
|
await saveCollections(collections);
|
|
}
|
|
|
|
static Map<String, int> getStats() {
|
|
final statsJson = _prefs.getString(_statsKey) ?? '{}';
|
|
final stats = jsonDecode(statsJson) as Map<String, dynamic>;
|
|
return {
|
|
'totalCollections': stats['totalCollections'] ?? 0,
|
|
'totalBookmarks': stats['totalBookmarks'] ?? 0,
|
|
};
|
|
}
|
|
|
|
static Future<void> updateStats() async {
|
|
final collections = loadCollections();
|
|
final bookmarks = loadBookmarks();
|
|
|
|
final stats = {
|
|
'totalCollections': collections.length,
|
|
'totalBookmarks': bookmarks.length,
|
|
'lastUpdated': DateTime.now().millisecondsSinceEpoch,
|
|
};
|
|
|
|
await _prefs.setString(_statsKey, jsonEncode(stats));
|
|
}
|
|
|
|
static SharedPreferencesWithCache get _prefs {
|
|
if (_prefsWithCache == null) {
|
|
throw StateError(
|
|
'BookmarkStorage not initialized. Call initialize() first.',
|
|
);
|
|
}
|
|
return _prefsWithCache!;
|
|
}
|
|
|
|
static Future<bool> exportToJsonFile() => JsonFileService.exportToJson(
|
|
collections: loadCollections(),
|
|
bookmarks: loadBookmarks(),
|
|
);
|
|
|
|
static Future<bool> importFromJsonFile() async {
|
|
final import = await JsonFileService.importFromJson();
|
|
|
|
if (import.bookmarks.isNotEmpty || import.collections.isNotEmpty) {
|
|
saveBookmarks(import.bookmarks);
|
|
saveCollections(import.collections);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|