added guardian letters with chat and multiple answer functionalities

This commit is contained in:
2026-09-20 16:12:45 +02:00
parent 67c935c05b
commit 2423c1a75e
68 changed files with 8348 additions and 226 deletions
+22 -3
View File
@@ -28,6 +28,7 @@ import 'auth_link/guardian_link_listener.dart';
import 'background/widget_background_task.dart';
import 'firebase_options.dart';
import 'notification/notification_service.dart';
import 'push/notification_permission_prompt.dart';
import 'push/push_message_handler.dart';
import 'push/push_registration.dart';
import 'push/push_registration_store.dart';
@@ -43,6 +44,7 @@ import 'state/app/modules/chat/bloc/chat_bloc.dart';
import 'state/app/modules/chat_list/bloc/chat_list_bloc.dart';
import 'state/app/modules/children/child_selection_cubit.dart';
import 'state/app/modules/nextcloud_capabilities/bloc/nextcloud_capabilities_cubit.dart';
import 'state/app/modules/parent_letters/bloc/parent_letters_bloc.dart';
import 'state/app/modules/settings/bloc/settings_cubit.dart';
import 'state/app/modules/timetable/primary/primary_timetable_scope.dart';
import 'storage/hydrated_storage_bootstrap.dart';
@@ -256,6 +258,7 @@ Future<void> main() async {
create: (ctx) => ChatBloc(chatListBloc: ctx.read<ChatListBloc>()),
),
BlocProvider<ChildSelectionCubit>(create: (_) => ChildSelectionCubit()),
BlocProvider<ParentLettersBloc>(create: (_) => ParentLettersBloc()),
],
child: const PrimaryTimetableScope(child: Main()),
),
@@ -327,16 +330,27 @@ class _MainState extends State<Main> {
capabilitiesCubit.load().then((_) {
if (!mounted) return;
_syncPush(settingsCubit, capabilitiesCubit);
_promptGuardianNotifications();
}),
);
unawaited(context.read<NextcloudCapabilitiesCubit>().load());
}
/// Waits for the post-login splash so the dialog never covers it; the
/// splash's completion calls this again.
void _promptGuardianNotifications() {
if (_showPostLoginSplash) return;
final overlayContext = AppRoutes.overlayContext;
if (overlayContext == null) return;
unawaited(maybePromptGuardianLoginNotifications(overlayContext));
}
/// Warms the chat list and files root in the background so the first screen
/// render hits populated data. The timetable needs no warm-up:
/// PrimaryTimetableScope creates a freshly loading bloc per account.
void _prefetchBaseData(BuildContext context) {
unawaited(context.read<ChatListBloc>().refresh(silent: true));
unawaited(context.read<ParentLettersBloc>().refresh(silent: true));
if (SessionManager().hasNextcloud) {
unawaited(ListFilesCache.prefetchRootListing());
}
@@ -482,6 +496,7 @@ class _MainState extends State<Main> {
final childSelectionCubit = context
.read<ChildSelectionCubit>();
final chatListBloc = context.read<ChatListBloc>();
final parentLettersBloc = context.read<ParentLettersBloc>();
final chatBloc = context.read<ChatBloc>();
final nextcloudCapabilitiesCubit = context
.read<NextcloudCapabilitiesCubit>();
@@ -495,6 +510,7 @@ class _MainState extends State<Main> {
settingsCubit: settingsCubit,
childSelectionCubit: childSelectionCubit,
chatListBloc: chatListBloc,
parentLettersBloc: parentLettersBloc,
chatBloc: chatBloc,
breakerBloc: breakerBloc,
capabilitiesCubit: capabilitiesCubit,
@@ -515,9 +531,10 @@ class _MainState extends State<Main> {
if (_showPostLoginSplash)
PostLoginSplash(
key: const ValueKey('post-login-splash'),
onComplete: () => setState(
() => _showPostLoginSplash = false,
),
onComplete: () {
setState(() => _showPostLoginSplash = false);
_promptGuardianNotifications();
},
),
],
);
@@ -541,6 +558,7 @@ Future<void> _wipeUserState({
required SettingsCubit settingsCubit,
required ChildSelectionCubit childSelectionCubit,
required ChatListBloc chatListBloc,
required ParentLettersBloc parentLettersBloc,
required ChatBloc chatBloc,
required BreakerBloc breakerBloc,
required CapabilitiesCubit capabilitiesCubit,
@@ -558,6 +576,7 @@ Future<void> _wipeUserState({
await Future.wait([
childSelectionCubit.reset(),
chatListBloc.reset(),
parentLettersBloc.reset(),
chatBloc.reset(),
breakerBloc.reset(),
capabilitiesCubit.reset(),