replaced account data singleton with a session model
This commit is contained in:
@@ -2,7 +2,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../model/account_data.dart';
|
||||
import '../../session/session_manager.dart';
|
||||
import '../../theming/light_app_theme.dart';
|
||||
import '../../widget/app_progress_indicator.dart';
|
||||
|
||||
@@ -61,7 +61,7 @@ class _AccountLoadingScreenState extends State<AccountLoadingScreen> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextButton(
|
||||
onPressed: AccountData().abandonLoad,
|
||||
onPressed: SessionManager().abandonLoad,
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.white),
|
||||
child: const Text('Zur Anmeldung'),
|
||||
),
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../background/widget_background_task.dart';
|
||||
import '../../session/session_lifecycle.dart';
|
||||
import '../../state/app/modules/account/bloc/account_bloc.dart';
|
||||
import '../../state/app/modules/account/bloc/account_state.dart';
|
||||
import '../../state/app/modules/settings/bloc/settings_cubit.dart';
|
||||
@@ -11,6 +12,7 @@ import '../../storage/dev_tools_settings.dart';
|
||||
import '../../storage/settings.dart' as model;
|
||||
import '../../theming/light_app_theme.dart';
|
||||
import '../../utils/haptics.dart';
|
||||
import '../../widget/info_dialog.dart';
|
||||
import '../pages/settings/widgets/endpoint_picker.dart';
|
||||
import 'login_controller.dart';
|
||||
import 'post_login_splash.dart';
|
||||
@@ -34,6 +36,21 @@ class _LoginState extends State<Login> with SingleTickerProviderStateMixin {
|
||||
value: 1,
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _showSignOutNotice());
|
||||
}
|
||||
|
||||
/// An involuntary sign-out (expired token, rotated password) otherwise just
|
||||
/// drops the user here without a word.
|
||||
void _showSignOutNotice() {
|
||||
final notice = SessionLifecycle.signOutNotice.value;
|
||||
if (notice == null || !mounted) return;
|
||||
SessionLifecycle.signOutNotice.value = null;
|
||||
InfoDialog.show(context, notice, title: 'Erneut anmelden');
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
@@ -10,8 +10,9 @@ import '../../api/marianumconnect/auth/device_token_name.dart';
|
||||
import '../../api/marianumconnect/auth/token_storage.dart';
|
||||
import '../../api/marianumconnect/queries/auth_login/auth_login.dart';
|
||||
import '../../api/marianumconnect/queries/auth_logout/auth_logout.dart';
|
||||
import '../../model/account_data.dart';
|
||||
import '../../model/session_wipe.dart';
|
||||
import '../../session/session.dart';
|
||||
import '../../session/session_manager.dart';
|
||||
import '../../widget_data/widget_sync.dart';
|
||||
|
||||
/// Outcome of a login attempt.
|
||||
@@ -56,25 +57,18 @@ class LoginController extends ChangeNotifier {
|
||||
// Demo login: the prefix enters local demo mode, password ignored, no
|
||||
// network (see DemoMode).
|
||||
if (DemoMode.matches(user)) {
|
||||
await AccountData().removeData();
|
||||
await const MarianumConnectTokenStorage().clear();
|
||||
await WidgetSync.clear();
|
||||
await WidgetSync.triggerUpdate();
|
||||
await AccountData().setDemo(user);
|
||||
await _discardPreviousAccount();
|
||||
await SessionManager().signIn(
|
||||
CredentialSession(username: user, password: 'demo', isDemo: true),
|
||||
);
|
||||
_loading = false;
|
||||
notifyListeners();
|
||||
return LoginResult.success;
|
||||
}
|
||||
|
||||
var signedIn = false;
|
||||
try {
|
||||
await AccountData().removeData();
|
||||
// Vorherigen Token revoken bevor wir einen neuen anfordern — ein altes
|
||||
// Account hätte sonst noch einen aktiven Token in api_tokens.
|
||||
await const MarianumConnectTokenStorage().clear();
|
||||
// Widget-Snapshot löschen, sonst blitzt nach Account-Wechsel kurz der
|
||||
// Stundenplan des vorigen Users auf dem Home-Bildschirm.
|
||||
await WidgetSync.clear();
|
||||
await WidgetSync.triggerUpdate();
|
||||
await _discardPreviousAccount();
|
||||
// AuthLogin = Credential-Probe + Token-Create in einem Call.
|
||||
// 401 hier heißt: falsches Passwort.
|
||||
await AuthLogin().run(
|
||||
@@ -82,7 +76,10 @@ class LoginController extends ChangeNotifier {
|
||||
password: password,
|
||||
tokenName: await DeviceTokenName.resolve(),
|
||||
);
|
||||
await AccountData().setData(user, password);
|
||||
await SessionManager().signIn(
|
||||
CredentialSession(username: user, password: password),
|
||||
);
|
||||
signedIn = true;
|
||||
// Mint the Nextcloud app password now — it doubles as the Nextcloud
|
||||
// credential probe: a rejection means 2FA is active (or the NC password
|
||||
// diverges) and the login must finish interactively in the browser.
|
||||
@@ -92,7 +89,9 @@ class LoginController extends ChangeNotifier {
|
||||
return ncReady ? LoginResult.success : LoginResult.nextcloudLoginRequired;
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
await AccountData().removeData();
|
||||
// Only the account signed in by this attempt; while adding an account
|
||||
// the active one is parked and restored on cancel.
|
||||
if (signedIn) await SessionManager().signOut();
|
||||
await const MarianumConnectTokenStorage().clear();
|
||||
final isWrongCredentials = e is AuthException && e.statusCode == 401;
|
||||
_errorMessage = isWrongCredentials
|
||||
@@ -105,6 +104,17 @@ class LoginController extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Vorherigen Token verwerfen, bevor ein neuer angefordert wird, und den
|
||||
/// Widget-Snapshot löschen — sonst blitzt nach einem Account-Wechsel kurz
|
||||
/// der Stundenplan des vorigen Users auf dem Home-Bildschirm. Die Session
|
||||
/// selbst überschreibt signIn vollständig; beim Hinzufügen eines Kontos
|
||||
/// liegt der Token des aktiven Kontos schon in dessen Tresor.
|
||||
Future<void> _discardPreviousAccount() async {
|
||||
await const MarianumConnectTokenStorage().clear();
|
||||
await WidgetSync.clear();
|
||||
await WidgetSync.triggerUpdate();
|
||||
}
|
||||
|
||||
/// Tries to mint the Nextcloud app password with the just-verified password.
|
||||
/// `false` = Nextcloud rejected the credentials → Login Flow v2 required.
|
||||
/// Transport/server problems stay non-blocking (like the previous
|
||||
@@ -112,7 +122,7 @@ class LoginController extends ChangeNotifier {
|
||||
Future<bool> _prepareNextcloudAppPassword() async {
|
||||
try {
|
||||
final appPassword = await GetAppPassword().run();
|
||||
await AccountData().setAppPassword(appPassword);
|
||||
await SessionManager().setAppPassword(appPassword);
|
||||
return true;
|
||||
} on AuthException {
|
||||
return false;
|
||||
@@ -131,7 +141,7 @@ class LoginController extends ChangeNotifier {
|
||||
} on Object catch (e) {
|
||||
log('Login rollback: MC logout failed: $e');
|
||||
}
|
||||
await AccountData().removeData();
|
||||
await SessionManager().signOut();
|
||||
await const MarianumConnectTokenStorage().clear();
|
||||
_errorMessage =
|
||||
'Die Anmeldung wurde abgebrochen — dein Konto erfordert die Bestätigung im Browser.';
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
|
||||
import '../../api/errors/error_mapper.dart';
|
||||
import '../../api/marianumcloud/app_password/delete_app_password.dart';
|
||||
import '../../api/marianumcloud/login_flow/login_flow_api.dart';
|
||||
import '../../model/account_data.dart';
|
||||
import '../../session/session_manager.dart';
|
||||
import '../../utils/url_opener.dart';
|
||||
import '../../widget/app_progress_indicator.dart';
|
||||
|
||||
@@ -19,7 +19,7 @@ enum _FlowStep { primary, talk }
|
||||
|
||||
/// Runs the Nextcloud Login Flow v2: opens the browser login, polls until the
|
||||
/// user confirmed it there (2FA happens inside the browser) and adopts the
|
||||
/// returned app password via [AccountData.setLoginFlow]. A second, skippable
|
||||
/// returned app password via [SessionManager.setLoginFlow]. A second, skippable
|
||||
/// pass mints the Talk app password so flow accounts keep BOTH push
|
||||
/// subscriptions (see PushRegistrationType). Pops `true` once the primary
|
||||
/// credential was adopted, `false`/`null` when the user backs out before that.
|
||||
@@ -104,7 +104,7 @@ class _NextcloudLoginFlowPageState extends State<NextcloudLoginFlowPage>
|
||||
final credentials = await _api.poll(flow);
|
||||
if (credentials == null || _finished || !mounted) return;
|
||||
if (!LoginFlowApi.loginNameMatches(
|
||||
expected: AccountData().getUsername(),
|
||||
expected: SessionManager().requireNextcloud().username,
|
||||
actual: credentials.loginName,
|
||||
)) {
|
||||
_timer?.cancel();
|
||||
@@ -120,7 +120,7 @@ class _NextcloudLoginFlowPageState extends State<NextcloudLoginFlowPage>
|
||||
}
|
||||
switch (_step) {
|
||||
case _FlowStep.primary:
|
||||
await AccountData().setLoginFlow(credentials.appPassword);
|
||||
await SessionManager().setLoginFlow(credentials.appPassword);
|
||||
if (!mounted) return;
|
||||
// Zweite Freigabe direkt anstoßen: die Browser-Session besteht
|
||||
// bereits, es fehlt nur noch der Grant-Tipp.
|
||||
@@ -129,7 +129,7 @@ class _NextcloudLoginFlowPageState extends State<NextcloudLoginFlowPage>
|
||||
case _FlowStep.talk:
|
||||
_finished = true;
|
||||
_timer?.cancel();
|
||||
await AccountData().setAppPasswordTalk(credentials.appPassword);
|
||||
await SessionManager().setAppPasswordTalk(credentials.appPassword);
|
||||
if (!mounted) return;
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../api/marianumcloud/webdav/queries/list_files/cacheable_file.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../model/endpoint_data.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../data/file_type_icon.dart';
|
||||
|
||||
/// Leading slot for a file row: shows the Nextcloud thumbnail when the
|
||||
@@ -35,7 +35,7 @@ class FileLeading extends StatelessWidget {
|
||||
'https://${EndpointData().nextcloud().full()}'
|
||||
'/index.php/core/preview'
|
||||
'?fileId=$fileId&x=128&y=128&a=0',
|
||||
httpHeaders: AccountData().authHeaders(),
|
||||
httpHeaders: SessionManager().requireNextcloud().authHeaders,
|
||||
fit: BoxFit.cover,
|
||||
fadeInDuration: Duration.zero,
|
||||
fadeOutDuration: Duration.zero,
|
||||
|
||||
@@ -7,7 +7,7 @@ import '../../../api/marianumconnect/queries/timetable_get_element_week/timetabl
|
||||
import '../../../api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart';
|
||||
import '../../../api/marianumconnect/queries/timetable_get_students/timetable_get_students.dart';
|
||||
import '../../../api/marianumconnect/queries/timetable_get_teachers/timetable_get_teachers.dart';
|
||||
import '../../../model/account_data.dart';
|
||||
import '../../../session/session_manager.dart';
|
||||
import '../../../state/app/modules/settings/bloc/settings_cubit.dart';
|
||||
import '../../../storage/timetable_favorites_settings.dart';
|
||||
import '../../../utils/haptics.dart';
|
||||
@@ -56,7 +56,7 @@ class _ElementPickerPageState extends State<ElementPickerPage> {
|
||||
}
|
||||
|
||||
Future<List<_PickerItem>> _loadFor(TimetableElementType type) {
|
||||
final epoch = AccountData().sessionEpoch;
|
||||
final epoch = SessionManager().sessionEpoch;
|
||||
final cached = _futures[type];
|
||||
if (cached != null &&
|
||||
cached.epoch == epoch &&
|
||||
|
||||
@@ -13,10 +13,11 @@ import '../../../api/marianumconnect/marianumconnect_endpoint.dart';
|
||||
import '../../../api/marianumconnect/queries/telemetry_heartbeat/telemetry_device_id.dart';
|
||||
import '../../../background/widget_background_task.dart';
|
||||
import '../../../extensions/date_time.dart';
|
||||
import '../../../model/account_data.dart';
|
||||
import '../../../model/endpoint_data.dart';
|
||||
import '../../../push/push_registration_store.dart';
|
||||
import '../../../push/push_registration_type.dart';
|
||||
import '../../../session/session.dart';
|
||||
import '../../../session/session_manager.dart';
|
||||
import '../../../state/app/modules/account/bloc/account_bloc.dart';
|
||||
import '../../../state/app/modules/settings/bloc/settings_cubit.dart';
|
||||
import '../../../utils/clipboard_helper.dart';
|
||||
@@ -44,7 +45,8 @@ class _DiagnosticsPageState extends State<DiagnosticsPage> {
|
||||
Future<List<_Section>> _collect() async {
|
||||
final settings = context.read<SettingsCubit>().val();
|
||||
final accountStatus = context.read<AccountBloc>().state.status;
|
||||
final account = AccountData();
|
||||
final session = SessionManager().current;
|
||||
final nextcloud = session?.nextcloud;
|
||||
const tokens = MarianumConnectTokenStorage();
|
||||
final push = PushRegistrationStore();
|
||||
|
||||
@@ -101,13 +103,17 @@ class _DiagnosticsPageState extends State<DiagnosticsPage> {
|
||||
title: 'Sitzung',
|
||||
rows: await rows({
|
||||
'Status': () async => accountStatus.name,
|
||||
'Benutzer': () async =>
|
||||
account.isPopulated() ? account.getUsername() : null,
|
||||
'Demo-Modus': () async => account.isDemo,
|
||||
'Login Flow v2': () async => account.usesLoginFlow,
|
||||
'App-Passwort (Dateien)': () async => account.hasAppPassword(),
|
||||
'App-Passwort (Talk)': () async => account.hasAppPasswordTalk(),
|
||||
'Session-Epoche': () async => account.sessionEpoch,
|
||||
'Benutzer': () async => switch (session) {
|
||||
CredentialSession(:final username) => username,
|
||||
null => null,
|
||||
},
|
||||
'Demo-Modus': () async => session?.isDemo ?? false,
|
||||
'Login Flow v2': () async => nextcloud?.usesLoginFlow ?? false,
|
||||
'App-Passwort (Dateien)': () async =>
|
||||
nextcloud?.hasAppPassword ?? false,
|
||||
'App-Passwort (Talk)': () async =>
|
||||
nextcloud?.hasAppPasswordTalk ?? false,
|
||||
'Session-Epoche': () async => SessionManager().sessionEpoch,
|
||||
'MC-Token-ID': tokens.readTokenId,
|
||||
'MC-Token läuft ab': tokens.readExpiresAt,
|
||||
}),
|
||||
|
||||
@@ -4,10 +4,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../../api/marianumcloud/cloud_users/cloud_users_actions.dart';
|
||||
import '../../../../api/marianumconnect/queries/auth_logout/auth_logout.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../push/push_registration.dart';
|
||||
import '../../../../routing/app_routes.dart';
|
||||
import '../../../../session/session_lifecycle.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../state/app/modules/account/bloc/account_bloc.dart';
|
||||
import '../../../../state/app/modules/account/bloc/account_state.dart';
|
||||
import '../../../../widget/app_progress_indicator.dart';
|
||||
@@ -84,13 +84,17 @@ class _AccountSectionState extends State<AccountSection> {
|
||||
setState(() => _avatarBusy = false);
|
||||
if (!ok) return;
|
||||
|
||||
invalidateAvatarCache(id: AccountData().getUsername(), isGroup: false);
|
||||
invalidateAvatarCache(
|
||||
id: SessionManager().requireNextcloud().username,
|
||||
isGroup: false,
|
||||
);
|
||||
setState(() => _avatarVersion++);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final username = AccountData().getUsername();
|
||||
final nextcloud = SessionManager().requireNextcloud();
|
||||
final username = nextcloud.username;
|
||||
final displayName = _displayName;
|
||||
final theme = Theme.of(context);
|
||||
|
||||
@@ -175,7 +179,7 @@ class _AccountSectionState extends State<AccountSection> {
|
||||
// Nur für Login-Flow-Konten (2FA) sichtbar — Passwort-Konten heilen
|
||||
// sich still über das App-Passwort-Minting und sollen von dem ganzen
|
||||
// Flow-Mechanismus nichts mitbekommen.
|
||||
if (!AccountData().isDemo && AccountData().usesLoginFlow)
|
||||
if (!SessionManager().isDemo && nextcloud.usesLoginFlow)
|
||||
AsyncListTile(
|
||||
leading: const Icon(Icons.cloud_sync_outlined),
|
||||
title: const Text('Nextcloud neu verbinden'),
|
||||
@@ -203,7 +207,7 @@ class _AccountSectionState extends State<AccountSection> {
|
||||
|
||||
Future<void> _showLogoutDialog(BuildContext context) async {
|
||||
// Flip AccountBloc state only after the dialog fully closes: doing it from
|
||||
// inside removeData (the previous approach) raced AsyncDialogAction's
|
||||
// inside the sign-out (the previous approach) raced AsyncDialogAction's
|
||||
// pop(true) against the listener's popUntil(isFirst) and could leave the
|
||||
// navigator in an inconsistent state.
|
||||
final confirmed = await showDialog<bool>(
|
||||
@@ -219,14 +223,8 @@ class _AccountSectionState extends State<AccountSection> {
|
||||
context.read<AccountBloc>().setStatus(AccountStatus.loggedOut);
|
||||
}
|
||||
|
||||
// Ordered teardown: unregister push at Nextcloud + proxy and revoke the app
|
||||
// password (while Nextcloud credentials are still available), THEN revoke the
|
||||
// MC bearer token, and finally wipe local credentials. Each step is
|
||||
// best-effort so an offline logout still reaches a clean local state.
|
||||
Future<void> _performLogout() async {
|
||||
await PushRegistration().logoutCleanup();
|
||||
await AuthLogout().run();
|
||||
await AccountData().removeData();
|
||||
await SessionLifecycle.signOut();
|
||||
_cachedDisplayName = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../api/marianumcloud/talk/chat/get_chat_response.dart';
|
||||
import '../../../../api/marianumcloud/talk/chat/rich_object_string_processor.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../model/endpoint_data.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../utils/emoji_detection.dart';
|
||||
import '../../../../utils/url_opener.dart';
|
||||
import '../widgets/highlighted_linkify.dart';
|
||||
@@ -105,7 +105,7 @@ class ChatMessage {
|
||||
fadeInDuration: Duration.zero,
|
||||
fadeOutDuration: Duration.zero,
|
||||
errorListener: (value) {},
|
||||
httpHeaders: AccountData().authHeaders(),
|
||||
httpHeaders: SessionManager().requireNextcloud().authHeaders,
|
||||
imageUrl:
|
||||
'https://${EndpointData().nextcloud().full()}/index.php/core/preview?fileId=${file!.id}&x=130&y=-1&a=1',
|
||||
),
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../api/marianumcloud/talk/get_reactions/get_reactions.dart';
|
||||
import '../../../../api/marianumcloud/talk/get_reactions/get_reactions_response.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../widget/centered_leading.dart';
|
||||
import '../../../../widget/emoji_text.dart';
|
||||
import '../../../../widget/loading_spinner.dart';
|
||||
@@ -63,10 +63,10 @@ class _MessageReactionsState extends State<MessageReactions> {
|
||||
leading: CenteredLeading(EmojiText(entry.key)),
|
||||
title: Text('${entry.value.length} mal reagiert'),
|
||||
children: entry.value.map((e) {
|
||||
final isSelf = AccountData().getUsername() == e.actorId;
|
||||
final isSelf =
|
||||
SessionManager().requireNextcloud().username == e.actorId;
|
||||
final isGuest =
|
||||
e.actorType ==
|
||||
GetReactionsResponseObjectActorType.guests;
|
||||
e.actorType == GetReactionsResponseObjectActorType.guests;
|
||||
return ListTile(
|
||||
leading: UserAvatar(id: e.actorId, isGroup: false),
|
||||
title: Text(e.actorDisplayName),
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../api/marianumcloud/talk/get_participants/get_participants_response.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../widget/user_avatar.dart';
|
||||
import '../data/open_direct_chat.dart';
|
||||
|
||||
@@ -36,7 +36,7 @@ class ParticipantsListView extends StatelessWidget {
|
||||
(participant) => participant.participantType,
|
||||
);
|
||||
|
||||
final selfId = AccountData().getUsername();
|
||||
final selfId = SessionManager().requireNextcloud().username;
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Mitglieder')),
|
||||
body: ListView(
|
||||
|
||||
@@ -9,8 +9,8 @@ import '../../../../api/marianumcloud/talk/get_shared_items/get_shared_items_ove
|
||||
import '../../../../api/marianumcloud/talk/get_shared_items/get_shared_items_response.dart';
|
||||
import '../../../../api/marianumcloud/talk/room/get_room_response.dart';
|
||||
import '../../../../extensions/date_time.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../model/endpoint_data.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../share_intent/remote_file_ref.dart';
|
||||
import '../../../../utils/downloads/download_job.dart';
|
||||
import '../../../../widget/app_progress_indicator.dart';
|
||||
@@ -54,9 +54,10 @@ class SharedItemsPage {
|
||||
const SharedItemsPage(this.items, this.lastKnownMessageId, this.hasMore);
|
||||
}
|
||||
|
||||
List<GetChatResponseObject> _fileItems(List<GetChatResponseObject> items) => items
|
||||
.where((item) => item.messageParameters?['file']?.path != null)
|
||||
.toList();
|
||||
List<GetChatResponseObject> _fileItems(List<GetChatResponseObject> items) =>
|
||||
items
|
||||
.where((item) => item.messageParameters?['file']?.path != null)
|
||||
.toList();
|
||||
|
||||
SharedItemsPage buildSharedItemsPage(
|
||||
GetSharedItemsResponse response,
|
||||
@@ -140,7 +141,9 @@ class _SharedItemsViewState extends State<SharedItemsView>
|
||||
Future<void> _load() async {
|
||||
setState(() => _error = null);
|
||||
try {
|
||||
final overview = await SharedItemsView.prefetchOverview(widget.room.token);
|
||||
final overview = await SharedItemsView.prefetchOverview(
|
||||
widget.room.token,
|
||||
);
|
||||
if (!mounted) return;
|
||||
_overview = overview;
|
||||
_prepareTabs();
|
||||
@@ -501,7 +504,10 @@ class _SharedItemTileState extends State<_SharedItemTile>
|
||||
if (isDownloading) {
|
||||
confirmCancelDownload();
|
||||
} else {
|
||||
startDownload(name: _file.name, remoteFile: RemoteFileRef.fromTalk(_file));
|
||||
startDownload(
|
||||
name: _file.name,
|
||||
remoteFile: RemoteFileRef.fromTalk(_file),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +539,7 @@ class _SharedItemTileState extends State<_SharedItemTile>
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
imageUrl: _previewUrl,
|
||||
httpHeaders: AccountData().authHeaders(),
|
||||
httpHeaders: SessionManager().requireNextcloud().authHeaders,
|
||||
fit: BoxFit.cover,
|
||||
fadeInDuration: Duration.zero,
|
||||
fadeOutDuration: Duration.zero,
|
||||
|
||||
@@ -9,9 +9,9 @@ import '../../../../api/marianumcloud/talk/room/get_room_response.dart';
|
||||
import '../../../../api/marianumcloud/talk/room/notification_level.dart';
|
||||
import '../../../../api/marianumcloud/talk/set_read_marker/set_read_marker.dart';
|
||||
import '../../../../extensions/date_time.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../notification/notification_tasks.dart';
|
||||
import '../../../../routing/app_routes.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../state/app/modules/chat/bloc/chat_bloc.dart';
|
||||
import '../../../../state/app/modules/chat_list/bloc/chat_list_bloc.dart';
|
||||
import '../../../../utils/haptics.dart';
|
||||
@@ -53,13 +53,9 @@ class _ChatTileState extends State<ChatTile> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
AccountData().waitForPopulation().then((_) {
|
||||
SessionManager().waitForLoad().then((session) {
|
||||
if (!mounted) return;
|
||||
setState(
|
||||
() => selfUsername = AccountData().isPopulated()
|
||||
? AccountData().getUsername()
|
||||
: null,
|
||||
);
|
||||
setState(() => selfUsername = session?.nextcloud?.username);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import '../../../../api/marianumcloud/talk/get_poll/get_poll_state_response.dart
|
||||
import '../../../../api/marianumcloud/talk/room/get_room_response.dart';
|
||||
import '../../../../api/marianumcloud/talk/vote_poll/vote_poll.dart';
|
||||
import '../../../../api/marianumcloud/talk/vote_poll/vote_poll_params.dart';
|
||||
import '../../../../model/account_data.dart';
|
||||
import '../../../../session/session_manager.dart';
|
||||
import '../../../../widget/async_action_button.dart';
|
||||
import '../../../../widget/confirm_dialog.dart';
|
||||
import '../../../../widget/demo_restricted.dart';
|
||||
@@ -186,7 +186,7 @@ class _PollOptionsListState extends State<PollOptionsList> {
|
||||
|
||||
Widget _actionBar(GetPollStateResponseObject poll, ThemeData theme) {
|
||||
final canClose = poll.canClose(
|
||||
selfId: AccountData().getUsername(),
|
||||
selfId: SessionManager().requireNextcloud().username,
|
||||
participantType: widget.room.participantType,
|
||||
);
|
||||
if (!_isInteractive && !canClose) return const SizedBox.shrink();
|
||||
|
||||
Reference in New Issue
Block a user