fixed stale state after logout and replayed or lost share intents

This commit is contained in:
2026-09-24 21:43:21 +02:00
parent e4e2b1a4fb
commit 498d195138
32 changed files with 743 additions and 188 deletions
@@ -5,6 +5,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import '../../../../../api/demo/data/demo_capabilities.dart';
import '../../../../../api/demo/demo_mode.dart';
import '../../../../../api/marianumconnect/queries/get_capabilities/get_capabilities.dart';
import '../../../../../model/account_data.dart';
import 'capabilities_state.dart';
/// Holds the current user's mobile capability flags. Hydrated so the last
@@ -34,8 +35,12 @@ class CapabilitiesCubit extends HydratedCubit<CapabilitiesState> {
emit(DemoCapabilities.state());
return;
}
final epoch = AccountData().sessionEpoch;
try {
final response = await GetCapabilities().run();
// A slow answer for the previous account must not decide the modules
// of the next one.
if (!AccountData().isCurrentSession(epoch)) return;
emit(
CapabilitiesState(
viewForeignTimetables: response.viewForeignTimetables,
@@ -123,6 +123,15 @@ class ChatBloc
/// No-op when the bloc has already moved on to a different token: when
/// popping a stacked chat (B over A), A's didPopNext runs setToken(A)
/// before B's dispose fires.
/// The chat view may still be popping when the sign-out resets this bloc,
/// so leaveChat would find no token and the long-poll would keep running.
@override
Future<void> reset() {
_chatViewActive = false;
_stopLongPoll();
return super.reset();
}
void leaveChat(String fromToken) {
if ((innerState?.currentToken ?? '') != fromToken) return;
_chatViewActive = false;
@@ -30,6 +30,13 @@ class ChatListBloc
return super.close();
}
// The timer outlives the app shell; the next shell re-arms it after login.
@override
Future<void> reset() {
setAutoRefreshInterval(null);
return super.reset();
}
/// Silent refresh — explicit pull-to-refresh and tab-activation are non-silent.
void setAutoRefreshInterval(Duration? interval) {
if (interval == _autoRefreshInterval) return;
@@ -5,6 +5,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import '../../../../../api/demo/data/demo_capabilities.dart';
import '../../../../../api/demo/demo_mode.dart';
import '../../../../../api/marianumcloud/capabilities/get_nextcloud_capabilities.dart';
import '../../../../../model/account_data.dart';
import 'nextcloud_capabilities_state.dart';
/// Holds the current user's Nextcloud `files_sharing` capabilities. Hydrated so
@@ -63,8 +64,12 @@ class NextcloudCapabilitiesCubit
emit(DemoNextcloudCapabilities.state());
return;
}
final epoch = AccountData().sessionEpoch;
try {
final caps = await GetNextcloudCapabilities().run();
// A slow answer for the previous account must not decide the modules
// of the next one.
if (!AccountData().isCurrentSession(epoch)) return;
emit(
NextcloudCapabilitiesState(
apiEnabled: caps.apiEnabled,
@@ -91,8 +91,10 @@ class TimetableBloc
final current = innerState ?? fromNothing();
if (current.startDate == startDate && current.endDate == endDate) return;
add(Emit((s) => s.copyWith(startDate: startDate, endDate: endDate)));
_loadCurrentWeek(startDate, endDate);
_prefetchAdjacentWeeks(startDate, endDate);
runInSession(() {
_loadCurrentWeek(startDate, endDate);
_prefetchAdjacentWeeks(startDate, endDate);
});
}
void resetWeek() {