2026-03-20 15:37:59 +08:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
|
|
import '../../../core/cache/cache_entry.dart';
|
|
|
|
|
import '../../../core/cache/cache_invalidator.dart';
|
|
|
|
|
import '../../../core/cache/hybrid_cache_store.dart';
|
|
|
|
|
import 'todo_api.dart';
|
|
|
|
|
|
|
|
|
|
class TodoRepository {
|
|
|
|
|
static const String pendingListKey = 'todo:list:pending';
|
|
|
|
|
|
|
|
|
|
final TodoApi api;
|
|
|
|
|
final HybridCacheStore store;
|
|
|
|
|
final CacheInvalidator invalidator;
|
|
|
|
|
final DateTime Function() now;
|
|
|
|
|
|
|
|
|
|
TodoRepository({
|
|
|
|
|
required this.api,
|
|
|
|
|
required this.store,
|
|
|
|
|
required this.invalidator,
|
|
|
|
|
DateTime Function()? now,
|
|
|
|
|
}) : now = now ?? DateTime.now;
|
|
|
|
|
|
|
|
|
|
Future<List<TodoResponse>> getPendingTodos({
|
|
|
|
|
bool forceRefresh = false,
|
|
|
|
|
}) async {
|
|
|
|
|
if (!forceRefresh) {
|
|
|
|
|
final cached = await store.read<CacheEntry<List<TodoResponse>>>(
|
|
|
|
|
pendingListKey,
|
|
|
|
|
);
|
|
|
|
|
if (cached != null) {
|
|
|
|
|
return cached.value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final remote = await api.getPendingTodos();
|
|
|
|
|
await store.write<CacheEntry<List<TodoResponse>>>(
|
|
|
|
|
pendingListKey,
|
|
|
|
|
CacheEntry(value: remote, fetchedAt: now()),
|
|
|
|
|
);
|
|
|
|
|
return remote;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> completeTodo(String id) async {
|
|
|
|
|
final cached = await store.read<CacheEntry<List<TodoResponse>>>(
|
|
|
|
|
pendingListKey,
|
|
|
|
|
);
|
|
|
|
|
if (cached != null) {
|
|
|
|
|
final next = cached.value
|
2026-03-20 16:45:08 +08:00
|
|
|
.where((todo) => todo.id != id)
|
2026-03-20 15:37:59 +08:00
|
|
|
.toList(growable: false);
|
|
|
|
|
await store.write<CacheEntry<List<TodoResponse>>>(
|
|
|
|
|
pendingListKey,
|
|
|
|
|
CacheEntry(value: next, fetchedAt: now()),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await api.completeTodo(id);
|
2026-03-20 16:45:08 +08:00
|
|
|
invalidator.invalidate(pendingListKey);
|
2026-03-20 15:37:59 +08:00
|
|
|
} catch (error) {
|
|
|
|
|
if (cached != null) {
|
|
|
|
|
await store.write<CacheEntry<List<TodoResponse>>>(
|
|
|
|
|
pendingListKey,
|
|
|
|
|
cached,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
rethrow;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> invalidatePending() {
|
|
|
|
|
invalidator.invalidate(pendingListKey);
|
|
|
|
|
return Future<void>.value();
|
|
|
|
|
}
|
|
|
|
|
}
|