refactor: Enable lint use_build_context_synchronously

This commit is contained in:
Christian Kußowski 2026-03-25 10:42:17 +01:00
commit 3296c0d92d
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
50 changed files with 490 additions and 293 deletions

View file

@ -211,6 +211,7 @@ class ChatController extends State<ChatPageWithRoom>
context: context,
future: room.leave,
);
if (!mounted) return;
if (success.error != null) return;
context.go('/rooms');
}
@ -475,8 +476,9 @@ class ChatController extends State<ChatPageWithRoom>
Future<void>? loadTimelineFuture;
Future<void> _getTimeline({String? eventContextId}) async {
await Matrix.of(context).client.roomsLoading;
await Matrix.of(context).client.accountDataLoading;
final matrix = Matrix.of(context);
await matrix.client.roomsLoading;
await matrix.client.accountDataLoading;
if (eventContextId != null &&
(!eventContextId.isValidMatrixId || eventContextId.sigil != '\$')) {
eventContextId = null;
@ -632,6 +634,7 @@ class ChatController extends State<ChatPageWithRoom>
Future<void> sendFileAction({FileType type = FileType.any}) async {
final files = await selectFiles(context, allowMultiple: true, type: type);
if (files.isEmpty) return;
if (!mounted) return;
await showAdaptiveDialog(
context: context,
builder: (c) => SendFileDialog(
@ -663,6 +666,7 @@ class ChatController extends State<ChatPageWithRoom>
FocusScope.of(context).requestFocus(FocusNode());
final file = await ImagePicker().pickImage(source: ImageSource.camera);
if (file == null) return;
if (!mounted) return;
await showAdaptiveDialog(
context: context,
@ -684,6 +688,7 @@ class ChatController extends State<ChatPageWithRoom>
maxDuration: const Duration(minutes: 1),
);
if (file == null) return;
if (!mounted) return;
await showAdaptiveDialog(
context: context,
@ -726,26 +731,27 @@ class ChatController extends State<ChatPageWithRoom>
mimeType: mimeType,
);
room
.sendFileEvent(
file,
inReplyTo: replyEvent,
threadRootEventId: activeThreadId,
extraContent: {
'info': {...file.info, 'duration': duration},
'org.matrix.msc3245.voice': {},
'org.matrix.msc1767.audio': {
'duration': duration,
'waveform': waveform,
},
try {
await room.sendFileEvent(
file,
inReplyTo: replyEvent,
threadRootEventId: activeThreadId,
extraContent: {
'info': {...file.info, 'duration': duration},
'org.matrix.msc3245.voice': {},
'org.matrix.msc1767.audio': {
'duration': duration,
'waveform': waveform,
},
)
.catchError((e) {
scaffoldMessenger.showSnackBar(
SnackBar(content: Text((e as Object).toLocalizedString(context))),
);
return null;
});
},
);
} catch (e) {
if (!mounted) return;
scaffoldMessenger.showSnackBar(
SnackBar(content: Text(e.toLocalizedString(context))),
);
return;
}
setState(() {
replyEvent = null;
});
@ -807,29 +813,30 @@ class ChatController extends State<ChatPageWithRoom>
Future<void> reportEventAction() async {
final event = selectedEvents.single;
final l10n = L10n.of(context);
final scaffoldMessenger = ScaffoldMessenger.of(context);
final score = await showModalActionPopup<int>(
context: context,
title: L10n.of(context).reportMessage,
message: L10n.of(context).howOffensiveIsThisContent,
cancelLabel: L10n.of(context).cancel,
title: l10n.reportMessage,
message: l10n.howOffensiveIsThisContent,
cancelLabel: l10n.cancel,
actions: [
AdaptiveModalAction(
value: -100,
label: L10n.of(context).extremeOffensive,
),
AdaptiveModalAction(value: -50, label: L10n.of(context).offensive),
AdaptiveModalAction(value: 0, label: L10n.of(context).inoffensive),
AdaptiveModalAction(value: -100, label: l10n.extremeOffensive),
AdaptiveModalAction(value: -50, label: l10n.offensive),
AdaptiveModalAction(value: 0, label: l10n.inoffensive),
],
);
if (score == null) return;
if (!mounted) return;
final reason = await showTextInputDialog(
context: context,
title: L10n.of(context).whyDoYouWantToReportThis,
okLabel: L10n.of(context).ok,
cancelLabel: L10n.of(context).cancel,
hintText: L10n.of(context).reason,
title: l10n.whyDoYouWantToReportThis,
okLabel: l10n.ok,
cancelLabel: l10n.cancel,
hintText: l10n.reason,
);
if (reason == null || reason.isEmpty) return;
if (!mounted) return;
final result = await showFutureLoadingDialog(
context: context,
future: () => Matrix.of(context).client.reportEvent(
@ -840,12 +847,13 @@ class ChatController extends State<ChatPageWithRoom>
),
);
if (result.error != null) return;
if (!mounted) return;
setState(() {
showEmojiPicker = false;
selectedEvents.clear();
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(L10n.of(context).contentHasBeenReported)),
scaffoldMessenger.showSnackBar(
SnackBar(content: Text(l10n.contentHasBeenReported)),
);
}
@ -861,6 +869,7 @@ class ChatController extends State<ChatPageWithRoom>
}
setState(selectedEvents.clear);
} catch (e, s) {
if (!mounted) return;
ErrorReporter(
context,
'Error while delete error events action',
@ -885,6 +894,7 @@ class ChatController extends State<ChatPageWithRoom>
: null;
if (reasonInput == null) return;
final reason = reasonInput.isEmpty ? null : reasonInput;
if (!mounted) return;
await showFutureLoadingDialog(
context: context,
futureWithProgress: (onProgress) async {
@ -1239,6 +1249,7 @@ class ChatController extends State<ChatPageWithRoom>
okLabel: L10n.of(context).unpin,
cancelLabel: L10n.of(context).cancel,
);
if (!mounted) return;
if (response == OkCancelResult.ok) {
final events = room.pinnedEventIds
..removeWhere((oldEvent) => oldEvent == eventId);
@ -1328,17 +1339,18 @@ class ChatController extends State<ChatPageWithRoom>
Future<void> onPhoneButtonTap() async {
// VoIP required Android SDK 21
if (PlatformInfos.isAndroid) {
DeviceInfoPlugin().androidInfo.then((value) {
if (value.version.sdkInt < 21) {
Navigator.pop(context);
showOkAlertDialog(
context: context,
title: L10n.of(context).unsupportedAndroidVersion,
message: L10n.of(context).unsupportedAndroidVersionLong,
okLabel: L10n.of(context).close,
);
}
});
final androidInfo = await DeviceInfoPlugin().androidInfo;
if (!mounted) return;
if (androidInfo.version.sdkInt < 21) {
Navigator.pop(context);
await showOkAlertDialog(
context: context,
title: L10n.of(context).unsupportedAndroidVersion,
message: L10n.of(context).unsupportedAndroidVersionLong,
okLabel: L10n.of(context).close,
);
return;
}
}
final callType = await showModalActionPopup<CallType>(
context: context,
@ -1359,11 +1371,13 @@ class ChatController extends State<ChatPageWithRoom>
],
);
if (callType == null) return;
if (!mounted) return;
final voipPlugin = Matrix.of(context).voipPlugin;
try {
await voipPlugin!.voip.inviteToCall(room, callType);
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));

View file

@ -189,6 +189,7 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
});
} catch (e, s) {
Logs().v('Could not download audio file', e, s);
if (!mounted) rethrow;
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
@ -208,6 +209,7 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
),
);
}
if (!mounted) return;
audioPlayer.play().onError(
ErrorReporter(context, 'Unable to play audio message').onErrorCallback,

View file

@ -50,6 +50,7 @@ class _CuteContentState extends State<CuteContent> {
Future<void> addOverlay() async {
_isOverlayShown = true;
await Future.delayed(const Duration(milliseconds: 50));
if (!mounted) return;
OverlayEntry? overlay;
overlay = OverlayEntry(

View file

@ -61,9 +61,11 @@ class MessageContent extends StatelessWidget {
final client = Matrix.of(context).client;
final state = await client.getCryptoIdentityState();
if (!state.connected) {
if (!context.mounted) return;
final success = await context.push('/backup');
if (success != true) return;
}
if (!context.mounted) return;
event.requestKey();
final sender = event.senderFromMemoryOrFallback;
await showAdaptiveBottomSheet(

View file

@ -15,6 +15,7 @@ class PinnedEvents extends StatelessWidget {
const PinnedEvents(this.controller, {super.key});
Future<void> _displayPinnedEventsDialog(BuildContext context) async {
final l10n = L10n.of(context);
final eventsResult = await showFutureLoadingDialog(
context: context,
future: () => Future.wait(
@ -25,13 +26,14 @@ class PinnedEvents extends StatelessWidget {
);
final events = eventsResult.result;
if (events == null) return;
if (!context.mounted) return;
final eventId = events.length == 1
? events.single?.eventId
: await showModalActionPopup<String>(
context: context,
title: L10n.of(context).pin,
cancelLabel: L10n.of(context).cancel,
title: l10n.pin,
cancelLabel: l10n.cancel,
actions: events
.map(
(event) => AdaptiveModalAction(
@ -39,7 +41,7 @@ class PinnedEvents extends StatelessWidget {
icon: const Icon(Icons.push_pin_outlined),
label:
event?.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)),
MatrixLocals(l10n),
withSenderNamePrefix: true,
hideReply: true,
) ??

View file

@ -44,6 +44,7 @@ class RecordingViewModelState extends State<RecordingViewModel> {
room.client.getConfig(); // Preload server file configuration.
if (PlatformInfos.isAndroid) {
final info = await DeviceInfoPlugin().androidInfo;
if (!mounted) return;
if (info.version.sdkInt < 19) {
showOkAlertDialog(
context: context,
@ -76,6 +77,7 @@ class RecordingViewModelState extends State<RecordingViewModel> {
final result = await audioRecorder.hasPermission();
if (result != true) {
if (!mounted) return;
showOkAlertDialog(
context: context,
title: L10n.of(context).oopsSomethingWentWrong,
@ -97,10 +99,12 @@ class RecordingViewModelState extends State<RecordingViewModel> {
),
path: path ?? '',
);
if (!mounted) return;
setState(() => duration = Duration.zero);
_subscribe();
} catch (e, s) {
Logs().w('Unable to start voice message recording', e, s);
if (!mounted) return;
showOkAlertDialog(
context: context,
title: L10n.of(context).oopsSomethingWentWrong,

View file

@ -146,6 +146,7 @@ class SendFileDialogState extends State<SendFileDialog> {
scaffoldMessenger.clearSnackBars();
} catch (e) {
scaffoldMessenger.clearSnackBars();
if (!mounted || !widget.outerContext.mounted) rethrow;
final theme = Theme.of(context);
scaffoldMessenger.showSnackBar(
SnackBar(

View file

@ -81,6 +81,7 @@ class SendLocationDialogState extends State<SendLocationDialog> {
context: context,
future: () => widget.room.sendLocation(body, uri),
);
if (!mounted) return;
Navigator.of(context, rootNavigator: false).pop();
}

View file

@ -44,6 +44,7 @@ class _StartPollBottomSheetState extends State<StartPollBottomSheet> {
maxSelections: _allowMultipleAnswers ? _answers.length : 1,
txid: _txid,
);
if (!mounted) return;
Navigator.of(context).pop();
} catch (e, s) {
Logs().w('Unable to create poll', e, s);