better loading indicators for timetables, talk and files

This commit is contained in:
2026-05-05 21:07:48 +02:00
parent bee5c02a4f
commit db9c3386f1
25 changed files with 439 additions and 203 deletions
@@ -1,5 +1,6 @@
import 'package:flutter_app_badge/flutter_app_badge.dart';
import '../../../infrastructure/loadableState/loading_error.dart';
import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc.dart';
import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc_event.dart';
import '../repository/chat_list_repository.dart';
@@ -7,6 +8,14 @@ import 'chat_list_event.dart';
import 'chat_list_state.dart';
class ChatListBloc extends LoadableHydratedBloc<ChatListEvent, ChatListState, ChatListRepository> {
bool _forceRenew = false;
@override
void retry() {
_forceRenew = true;
super.retry();
}
@override
ChatListRepository repository() => ChatListRepository();
@@ -21,15 +30,39 @@ class ChatListBloc extends LoadableHydratedBloc<ChatListEvent, ChatListState, Ch
@override
Future<void> gatherData() async {
final rooms = await repo.data.getRooms();
final renew = _forceRenew;
_forceRenew = false;
Object? capturedError;
final rooms = await repo.data.getRooms(
renew: renew,
onError: (e) => capturedError = e,
);
add(DataGathered((s) => s.copyWith(rooms: rooms)));
_updateAppBadge(rooms);
if (capturedError != null) throw capturedError!;
}
Future<void> refresh({bool renew = true}) async {
final rooms = await repo.data.getRooms(renew: renew);
add(DataGathered((s) => s.copyWith(rooms: rooms)));
_updateAppBadge(rooms);
add(RefetchStarted<ChatListState>());
Object? capturedError;
try {
final rooms = await repo.data.getRooms(
renew: renew,
onError: (e) => capturedError = e,
);
add(DataGathered((s) => s.copyWith(rooms: rooms)));
_updateAppBadge(rooms);
} catch (e) {
capturedError = e;
}
if (capturedError != null) {
add(Error(LoadingError(
message: capturedError.toString(),
allowRetry: true,
)));
}
}
Future<void> createDirectChat(String invite) async {
@@ -1,20 +1,26 @@
import 'dart:async';
import '../../../../../api/marianumcloud/talk/room/getRoomCache.dart';
import '../../../../../api/marianumcloud/talk/room/getRoomResponse.dart';
import '../../../../../api/marianumcloud/talk/createRoom/createRoom.dart';
import '../../../../../api/marianumcloud/talk/createRoom/createRoomParams.dart';
class ChatListDataProvider {
Future<GetRoomResponse> getRooms({bool renew = false}) {
final completer = Completer<GetRoomResponse>();
GetRoomCache(
Future<GetRoomResponse> getRooms({
void Function(Object)? onError,
bool renew = false,
}) async {
GetRoomResponse? latest;
Object? capturedError;
final cache = GetRoomCache(
renew: renew,
onUpdate: (data) {
if (!completer.isCompleted) completer.complete(data);
onUpdate: (data) => latest = data,
onError: (e) {
capturedError = e;
onError?.call(e);
},
);
return completer.future;
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getRooms');
}
Future<void> createDirectRoom(String invite) =>