Initial project import
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:miaoji_zhang/shared/api/api_client.dart';
|
||||
import 'package:miaoji_zhang/shared/services/local_database.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
|
||||
class LedgerInfo {
|
||||
final int id;
|
||||
final String name;
|
||||
final String iconKey;
|
||||
final bool isDefault;
|
||||
final int transactionCount;
|
||||
|
||||
const LedgerInfo({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.iconKey,
|
||||
required this.isDefault,
|
||||
required this.transactionCount,
|
||||
});
|
||||
|
||||
factory LedgerInfo.fromJson(Map<String, dynamic> json) => LedgerInfo(
|
||||
id: (json['id'] as num).toInt(),
|
||||
name: json['name'] as String,
|
||||
iconKey: json['iconKey'] as String? ?? 'wallet',
|
||||
isDefault: json['isDefault'] as bool? ?? false,
|
||||
transactionCount: (json['txCount'] as num?)?.toInt() ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
class CurrentLedgerStore extends ChangeNotifier {
|
||||
CurrentLedgerStore._();
|
||||
|
||||
static final instance = CurrentLedgerStore._();
|
||||
final _dio = ApiClient.instance.dio;
|
||||
|
||||
List<LedgerInfo> _ledgers = const [];
|
||||
LedgerInfo? _current;
|
||||
Future<void>? _loading;
|
||||
|
||||
List<LedgerInfo> get ledgers => List.unmodifiable(_ledgers);
|
||||
LedgerInfo? get current => _current;
|
||||
int? get currentId => _current?.id;
|
||||
String get currentName => _current?.name ?? '账本';
|
||||
|
||||
Future<void> ensureLoaded({bool force = false}) {
|
||||
if (!force && _current != null) return Future.value();
|
||||
return _loading ??= _load().whenComplete(() => _loading = null);
|
||||
}
|
||||
|
||||
Future<void> loadCached({bool force = false}) {
|
||||
if (!force && _current != null) return Future.value();
|
||||
return _loading ??= _loadCached().whenComplete(() => _loading = null);
|
||||
}
|
||||
|
||||
Future<void> _loadCached() async {
|
||||
_apply(LocalDatabase.instance.ledgers());
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
final session = SessionStore.instance;
|
||||
List<dynamic> values;
|
||||
if (session.shouldUseLocalOnly) {
|
||||
values = LocalDatabase.instance.ledgers();
|
||||
} else {
|
||||
try {
|
||||
final response = await _dio.get('/api/ledgers');
|
||||
values = response.data as List;
|
||||
LocalDatabase.instance.cacheLedgers(values);
|
||||
} catch (error) {
|
||||
if (!isConnectivityError(error) || !session.isAccount) rethrow;
|
||||
values = LocalDatabase.instance.ledgers();
|
||||
}
|
||||
}
|
||||
_apply(values);
|
||||
}
|
||||
|
||||
void _apply(List<dynamic> values) {
|
||||
final items = values
|
||||
.map((item) => LedgerInfo.fromJson(item as Map<String, dynamic>))
|
||||
.toList();
|
||||
_ledgers = items;
|
||||
_current =
|
||||
items.where((item) => item.isDefault).firstOrNull ??
|
||||
(items.isEmpty ? null : items.first);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> select(int id) async {
|
||||
if (_current?.id == id) return;
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly || id < 0) {
|
||||
LocalDatabase.instance.selectLedger(id);
|
||||
if (session.isAccount && session.cloudSyncEnabled) {
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'select', {'id': id});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await _dio.put('/api/ledgers/$id/default');
|
||||
} catch (error) {
|
||||
if (!isConnectivityError(error)) rethrow;
|
||||
LocalDatabase.instance.selectLedger(id);
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'select', {'id': id});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
}
|
||||
|
||||
Future<void> create(String name) async {
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly) {
|
||||
final id = LocalDatabase.instance.createLedger(name.trim());
|
||||
if (session.isAccount && session.cloudSyncEnabled) {
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'create', {
|
||||
'name': name.trim(),
|
||||
'iconKey': 'wallet',
|
||||
});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await _dio.post(
|
||||
'/api/ledgers',
|
||||
data: {'name': name.trim(), 'iconKey': 'wallet'},
|
||||
);
|
||||
} catch (error) {
|
||||
if (!isConnectivityError(error)) rethrow;
|
||||
final id = LocalDatabase.instance.createLedger(name.trim());
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'create', {
|
||||
'name': name.trim(),
|
||||
'iconKey': 'wallet',
|
||||
});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
}
|
||||
|
||||
Future<void> rename(int id, String name, String iconKey) async {
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly || id < 0) {
|
||||
LocalDatabase.instance.renameLedger(id, name.trim(), iconKey);
|
||||
if (session.isAccount && session.cloudSyncEnabled) {
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'update', {
|
||||
'name': name.trim(),
|
||||
'iconKey': iconKey,
|
||||
});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await _dio.put(
|
||||
'/api/ledgers/$id',
|
||||
data: {'name': name.trim(), 'iconKey': iconKey},
|
||||
);
|
||||
} catch (error) {
|
||||
if (!isConnectivityError(error)) rethrow;
|
||||
LocalDatabase.instance.renameLedger(id, name.trim(), iconKey);
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'update', {
|
||||
'name': name.trim(),
|
||||
'iconKey': iconKey,
|
||||
});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
}
|
||||
|
||||
Future<void> delete(int id) async {
|
||||
final session = SessionStore.instance;
|
||||
if (session.shouldUseLocalOnly || id < 0) {
|
||||
LocalDatabase.instance.deleteLedger(id);
|
||||
if (session.isAccount && session.cloudSyncEnabled) {
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'delete', {'id': id});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await _dio.delete('/api/ledgers/$id');
|
||||
} catch (error) {
|
||||
if (!isConnectivityError(error)) rethrow;
|
||||
LocalDatabase.instance.deleteLedger(id);
|
||||
LocalDatabase.instance.enqueueSync('ledger', id, 'delete', {'id': id});
|
||||
}
|
||||
await ensureLoaded(force: true);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_ledgers = const [];
|
||||
_current = null;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user