fix: support offline manual bookkeeping
This commit is contained in:
@@ -8,6 +8,7 @@ import 'package:miaoji_zhang/shared/services/current_ledger_store.dart';
|
||||
import 'package:miaoji_zhang/shared/services/local_database.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
import 'package:miaoji_zhang/shared/services/shanghai_time.dart';
|
||||
import 'package:miaoji_zhang/shared/services/sync_service.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class TxItem {
|
||||
@@ -370,10 +371,7 @@ class TxApi {
|
||||
static Future<List<CategoryItem>> categories(String type) async {
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly) {
|
||||
return LocalDatabase.instance
|
||||
.categories(type)
|
||||
.map(CategoryItem.fromJson)
|
||||
.toList();
|
||||
return categoriesLocal(type);
|
||||
}
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
@@ -387,18 +385,17 @@ class TxApi {
|
||||
.toList();
|
||||
} catch (error) {
|
||||
if (!isConnectivityError(error) || !session.isAccount) rethrow;
|
||||
return LocalDatabase.instance
|
||||
.categories(type)
|
||||
.map(CategoryItem.fromJson)
|
||||
.toList();
|
||||
return categoriesLocal(type);
|
||||
}
|
||||
}
|
||||
|
||||
static List<CategoryItem> categoriesLocal(String type) => LocalDatabase
|
||||
.instance
|
||||
.categories(type)
|
||||
.map(CategoryItem.fromJson)
|
||||
.toList();
|
||||
static List<CategoryItem> categoriesLocal(String type) {
|
||||
LocalDatabase.instance.ensureDefaultCategories(type: type);
|
||||
return LocalDatabase.instance
|
||||
.categories(type)
|
||||
.map(CategoryItem.fromJson)
|
||||
.toList();
|
||||
}
|
||||
|
||||
static Future<List<CategoryItem>> categoriesRemote(String type) async {
|
||||
final response = await _dio.get(
|
||||
@@ -407,8 +404,10 @@ class TxApi {
|
||||
);
|
||||
final values = response.data as List;
|
||||
LocalDatabase.instance.cacheCategories(values, replaceType: type);
|
||||
return values
|
||||
.map((item) => CategoryItem.fromJson(item as Map<String, dynamic>))
|
||||
LocalDatabase.instance.ensureDefaultCategories(type: type);
|
||||
return LocalDatabase.instance
|
||||
.categories(type)
|
||||
.map(CategoryItem.fromJson)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -429,6 +428,7 @@ class TxApi {
|
||||
String? recognitionOccurrenceId,
|
||||
String? evidenceFingerprint,
|
||||
String? recognitionConfidence,
|
||||
bool localFirst = false,
|
||||
}) async {
|
||||
final payload = <String, dynamic>{
|
||||
'ledgerId': _ledgerId,
|
||||
@@ -456,7 +456,10 @@ class TxApi {
|
||||
'recognitionConfidence': recognitionConfidence,
|
||||
};
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly || categoryId < 0 || _ledgerId < 0) {
|
||||
if (localFirst ||
|
||||
session.shouldUseLocalOnly ||
|
||||
categoryId < 0 ||
|
||||
_ledgerId < 0) {
|
||||
final local = LocalDatabase.instance.createTransaction(payload);
|
||||
if (_queueOfflineChanges) {
|
||||
LocalDatabase.instance.enqueueSync(
|
||||
@@ -465,6 +468,7 @@ class TxApi {
|
||||
'create',
|
||||
payload,
|
||||
);
|
||||
_scheduleBackgroundSync();
|
||||
}
|
||||
return TxItem.fromJson(local);
|
||||
}
|
||||
@@ -1698,8 +1702,9 @@ class CategoryApi {
|
||||
String name,
|
||||
String iconKey,
|
||||
String colorKey,
|
||||
String type,
|
||||
) async {
|
||||
String type, {
|
||||
bool localFirst = false,
|
||||
}) async {
|
||||
final payload = {
|
||||
'name': name,
|
||||
'iconKey': iconKey,
|
||||
@@ -1707,7 +1712,8 @@ class CategoryApi {
|
||||
'type': type,
|
||||
};
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly ||
|
||||
if (localFirst ||
|
||||
session.shouldUseLocalOnly ||
|
||||
ApiClient.availability.value == BackendAvailability.offline) {
|
||||
final local = LocalDatabase.instance.createCategory(
|
||||
name,
|
||||
@@ -1722,6 +1728,7 @@ class CategoryApi {
|
||||
'create',
|
||||
payload,
|
||||
);
|
||||
_scheduleBackgroundSync();
|
||||
}
|
||||
return CategoryItem.fromJson(local);
|
||||
}
|
||||
@@ -1754,6 +1761,7 @@ class CategoryApi {
|
||||
required String iconKey,
|
||||
required String colorKey,
|
||||
required int sortOrder,
|
||||
bool localFirst = false,
|
||||
}) async {
|
||||
final payload = {
|
||||
'name': name,
|
||||
@@ -1762,7 +1770,8 @@ class CategoryApi {
|
||||
'sortOrder': sortOrder,
|
||||
};
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly ||
|
||||
if (localFirst ||
|
||||
session.shouldUseLocalOnly ||
|
||||
ApiClient.availability.value == BackendAvailability.offline ||
|
||||
id < 0) {
|
||||
final local = LocalDatabase.instance.updateCategory(
|
||||
@@ -1774,6 +1783,7 @@ class CategoryApi {
|
||||
);
|
||||
if (session.isAccount && session.cloudSyncEnabled) {
|
||||
LocalDatabase.instance.enqueueSync('category', id, 'update', payload);
|
||||
_scheduleBackgroundSync();
|
||||
}
|
||||
return CategoryItem.fromJson(local);
|
||||
}
|
||||
@@ -1796,10 +1806,15 @@ class CategoryApi {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> reorder(String type, List<int> categoryIds) async {
|
||||
static Future<void> reorder(
|
||||
String type,
|
||||
List<int> categoryIds, {
|
||||
bool localFirst = false,
|
||||
}) async {
|
||||
LocalDatabase.instance.reorderCategories(type, categoryIds);
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly ||
|
||||
if (localFirst ||
|
||||
session.shouldUseLocalOnly ||
|
||||
ApiClient.availability.value == BackendAvailability.offline ||
|
||||
categoryIds.any((id) => id < 0)) {
|
||||
if (session.isAccount && session.cloudSyncEnabled) {
|
||||
@@ -1807,6 +1822,7 @@ class CategoryApi {
|
||||
'type': type,
|
||||
'categoryIds': categoryIds,
|
||||
});
|
||||
_scheduleBackgroundSync();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1824,9 +1840,10 @@ class CategoryApi {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> delete(int id) async {
|
||||
static Future<void> delete(int id, {bool localFirst = false}) async {
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly ||
|
||||
if (localFirst ||
|
||||
session.shouldUseLocalOnly ||
|
||||
ApiClient.availability.value == BackendAvailability.offline ||
|
||||
id < 0) {
|
||||
LocalDatabase.instance.deleteCategory(id);
|
||||
@@ -1834,6 +1851,7 @@ class CategoryApi {
|
||||
LocalDatabase.instance.enqueueSync('category', id, 'delete', {
|
||||
'id': id,
|
||||
});
|
||||
_scheduleBackgroundSync();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1847,3 +1865,8 @@ class CategoryApi {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _scheduleBackgroundSync() {
|
||||
SyncService.instance.refreshLocalStatus();
|
||||
unawaited(SyncService.instance.run());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user