replaced account data singleton with a session model

This commit is contained in:
2026-09-27 14:49:38 +02:00
parent 79b33ab248
commit 5e65c4671a
60 changed files with 1019 additions and 679 deletions
+14 -12
View File
@@ -26,7 +26,6 @@ import 'api/marianumconnect/queries/telemetry_heartbeat/telemetry_heartbeat.dart
import 'app.dart';
import 'background/widget_background_task.dart';
import 'firebase_options.dart';
import 'model/account_data.dart';
import 'model/session_wipe.dart';
import 'notification/notification_service.dart';
import 'push/push_message_handler.dart';
@@ -34,6 +33,7 @@ import 'push/push_registration.dart';
import 'push/push_registration_store.dart';
import 'push/push_renderer.dart';
import 'routing/app_routes.dart';
import 'session/session_manager.dart';
import 'share_intent/share_intent_listener.dart';
import 'state/app/modules/account/bloc/account_bloc.dart';
import 'state/app/modules/account/bloc/account_state.dart';
@@ -119,7 +119,7 @@ void _installErrorHandlers() {
Future<void> main() async {
log('MarianumMobile started');
WidgetsFlutterBinding.ensureInitialized();
AccountData().markUiEngine();
SessionManager().markUiEngine();
// Before any initialisation so startup failures reach the backend too.
_installErrorHandlers();
@@ -152,12 +152,12 @@ Future<void> main() async {
_startupStep('documents dir', () async {
AppPaths.documentsDir = (await getApplicationDocumentsDirectory()).path;
}),
// The keychain may still be locked right after device unlock; AccountData
// The keychain may still be locked right after device unlock; the session
// keeps retrying, so on timeout the app starts on the loading screen and
// flips to the real state once the session is readable (see _MainState).
_startupStep(
'account data',
AccountData().waitForPopulation,
SessionManager().waitForLoad,
timeout: const Duration(seconds: 5),
// Expected on every background wake of a locked device; not an error.
report: false,
@@ -224,7 +224,7 @@ Future<void> main() async {
// has data ready by the time the user navigates to it. No-op when a
// cached payload is already present, so this does not undo the day-long
// root cache TTL.
if (AccountData().isPopulated()) {
if (SessionManager().hasNextcloud) {
unawaited(
ListFilesCache.prefetchRootListing().onError(
(e, _) => log('Files root prefetch failed: $e'),
@@ -262,9 +262,9 @@ Future<void> main() async {
}
AccountStatus _initialAccountStatus() {
final account = AccountData();
if (account.isPopulated()) return AccountStatus.loggedIn;
return account.isLoaded ? AccountStatus.loggedOut : AccountStatus.undefined;
final session = SessionManager();
if (session.isSignedIn) return AccountStatus.loggedIn;
return session.isLoaded ? AccountStatus.loggedOut : AccountStatus.undefined;
}
class Main extends StatefulWidget {
@@ -293,13 +293,13 @@ class _MainState extends State<Main> {
Jiffy.setLocale('de');
_lastStatus = context.read<AccountBloc>().state.status;
AccountData().waitForPopulation().then((value) {
SessionManager().waitForLoad().then((session) {
if (!mounted) return;
final accountBloc = context.read<AccountBloc>();
accountBloc.setStatus(
value ? AccountStatus.loggedIn : AccountStatus.loggedOut,
session != null ? AccountStatus.loggedIn : AccountStatus.loggedOut,
);
if (value) {
if (session != null) {
_scheduleSessionValidation(accountBloc);
// Cold start while already logged in: the account status doesn't
// change, so the loggedIn listener below never fires — refresh
@@ -323,7 +323,9 @@ class _MainState extends State<Main> {
void _prefetchBaseData(BuildContext context) {
context.read<TimetableBloc>().refresh();
unawaited(context.read<ChatListBloc>().refresh(silent: true));
unawaited(ListFilesCache.prefetchRootListing());
if (SessionManager().hasNextcloud) {
unawaited(ListFilesCache.prefetchRootListing());
}
}
/// Registers/self-heals the push subscription whenever the backend advertises