refactored chat data fetching to support separate cache and network callbacks

This commit is contained in:
2026-05-07 09:46:30 +02:00
parent 517e515ac1
commit 710e88d744
3 changed files with 27 additions and 24 deletions
@@ -5,7 +5,8 @@ import 'get_chat_response.dart';
class GetChatCache extends SimpleCache<GetChatResponse> {
GetChatCache({
required void Function(GetChatResponse) onUpdate,
super.onCacheData,
super.onNetworkData,
super.onError,
required String chatToken,
}) : super(
@@ -19,7 +20,6 @@ class GetChatCache extends SimpleCache<GetChatResponse> {
),
).run(),
fromJson: GetChatResponse.fromJson,
onUpdate: onUpdate,
) {
start('nc-chat-$chatToken');
}
+19 -8
View File
@@ -1,5 +1,4 @@
import '../../../../../api/errors/error_mapper.dart';
import '../../../../../api/marianumcloud/talk/chat/get_chat_response.dart';
import '../../../infrastructure/loadable_state/loading_error.dart';
import '../../../infrastructure/utility_widgets/loadable_hydrated_bloc/loadable_hydrated_bloc.dart';
import '../../../infrastructure/utility_widgets/loadable_hydrated_bloc/loadable_hydrated_bloc_event.dart';
@@ -57,23 +56,35 @@ class ChatBloc extends LoadableHydratedBloc<ChatEvent, ChatState, ChatRepository
final requestStart = DateTime.now();
_lastTokenSet = requestStart;
bool stillCurrent() {
if (_lastTokenSet.isAfter(requestStart)) return false;
if ((innerState?.currentToken ?? '') != token) return false;
return true;
}
Object? capturedError;
GetChatResponse? response;
try {
response = await repo.data.getChat(
await repo.data.getChat(
token: token,
onCacheData: (data) {
if (!stillCurrent()) return;
// Cache hit: show data immediately but preserve lastFetch — the
// cached payload may be stale and we don't want the UI to claim a
// fresh fetch just happened.
add(Emit((s) => s.copyWith(chatResponse: data)));
},
onNetworkData: (data) {
if (!stillCurrent()) return;
add(DataGathered((s) => s.copyWith(chatResponse: data)));
},
onError: (e) => capturedError = e,
);
} catch (e) {
capturedError = e;
}
if (_lastTokenSet.isAfter(requestStart)) return;
if ((innerState?.currentToken ?? '') != token) return;
if (!stillCurrent()) return;
if (response != null) {
add(DataGathered((s) => s.copyWith(chatResponse: response)));
}
if (capturedError != null) {
add(Error(LoadingError(
message: errorToUserMessage(capturedError),
@@ -2,26 +2,18 @@ import '../../../../../api/marianumcloud/talk/chat/get_chat_cache.dart';
import '../../../../../api/marianumcloud/talk/chat/get_chat_response.dart';
class ChatDataProvider {
Future<GetChatResponse> getChat({
Future<void> getChat({
required String token,
void Function(GetChatResponse data)? onUpdate,
void Function(GetChatResponse data)? onCacheData,
void Function(GetChatResponse data)? onNetworkData,
void Function(Object)? onError,
}) async {
GetChatResponse? latest;
Object? capturedError;
final cache = GetChatCache(
chatToken: token,
onUpdate: (data) {
latest = data;
onUpdate?.call(data);
},
onError: (e) {
capturedError = e;
onError?.call(e);
},
onCacheData: onCacheData,
onNetworkData: onNetworkData,
onError: (e) => onError?.call(e),
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getChat');
}
}