fixed several runtime errors from client error reports

This commit is contained in:
2026-09-26 00:06:18 +02:00
parent 56a497985b
commit d6130584f2
6 changed files with 39 additions and 10 deletions
@@ -25,7 +25,12 @@ class NotificationService {
// iOS Talk category mirrors the Android inline reply + mark-as-read actions // iOS Talk category mirrors the Android inline reply + mark-as-read actions
// so both platforms expose the same quick actions. The actual delivery of // so both platforms expose the same quick actions. The actual delivery of
// these while the app is terminated is handled by the (Phase 3) NSE. // these while the app is terminated is handled by the (Phase 3) NSE.
// The plugin defaults to prompting here, which would block startup on the
// OS dialog; the prompt belongs to maybePromptTalkNotifications instead.
final iosSettings = DarwinInitializationSettings( final iosSettings = DarwinInitializationSettings(
requestAlertPermission: false,
requestSoundPermission: false,
requestBadgePermission: false,
notificationCategories: [ notificationCategories: [
DarwinNotificationCategory( DarwinNotificationCategory(
PushRenderer.iosTalkCategory, PushRenderer.iosTalkCategory,
@@ -129,7 +129,7 @@ class ChatListBloc
/// A background poll that returns the same rooms would otherwise rebuild the /// A background poll that returns the same rooms would otherwise rebuild the
/// list and re-persist the whole state every 15 s. /// list and re-persist the whole state every 15 s.
bool _isUnchanged(GetRoomResponse rooms) { bool _isUnchanged(GetRoomResponse rooms) {
final encoded = jsonEncode(rooms.data); final encoded = jsonEncode(rooms.data.toList());
final unchanged = final unchanged =
encoded == _lastRoomsJson && encoded == _lastRoomsJson &&
innerState?.rooms != null && innerState?.rooms != null &&
@@ -79,6 +79,7 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
}); });
final webdavClient = await WebdavApi.webdav; final webdavClient = await WebdavApi.webdav;
if (!mounted) return;
if (!override) { if (!override) {
List<dynamic> result; List<dynamic> result;
@@ -148,6 +149,7 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
), ),
); );
if (!mounted) return;
if (replaceFiles != true) { if (replaceFiles != true) {
setState(() { setState(() {
_resetProgress(); _resetProgress();
@@ -230,8 +232,8 @@ class _FilesUploadDialogState extends State<FilesUploadDialog> {
uploadetFilePaths.add(fullRemotePath); uploadetFilePaths.add(fullRemotePath);
} }
setState(_resetProgress);
if (!mounted) return; if (!mounted) return;
setState(_resetProgress);
Navigator.of(context).pop(); Navigator.of(context).pop();
widget.onUploadFinished(uploadetFilePaths); widget.onUploadFinished(uploadetFilePaths);
} }
+2 -2
View File
@@ -42,7 +42,7 @@ Future<AvatarSheetResult?> showAvatarActionsSheet(
onTap: () async { onTap: () async {
final bytes = await _pickAndCrop( final bytes = await _pickAndCrop(
sheetContext, sheetContext,
() => FilePick.singleGalleryPick(sheetContext), () => FilePick.singleGalleryPick(sheetContext, forCrop: true),
); );
if (bytes == null || !sheetContext.mounted) return; if (bytes == null || !sheetContext.mounted) return;
result = AvatarUploadResult(bytes); result = AvatarUploadResult(bytes);
@@ -55,7 +55,7 @@ Future<AvatarSheetResult?> showAvatarActionsSheet(
onTap: () async { onTap: () async {
final bytes = await _pickAndCrop( final bytes = await _pickAndCrop(
sheetContext, sheetContext,
() => FilePick.cameraPick(sheetContext), () => FilePick.cameraPick(sheetContext, forCrop: true),
); );
if (bytes == null || !sheetContext.mounted) return; if (bytes == null || !sheetContext.mounted) return;
result = AvatarUploadResult(bytes); result = AvatarUploadResult(bytes);
+4 -2
View File
@@ -22,7 +22,7 @@ Future<Uint8List?> showChatBackgroundPickerSheet(BuildContext context) async {
title: const Text('Aus Galerie wählen'), title: const Text('Aus Galerie wählen'),
onTap: () async { onTap: () async {
final bytes = await _pickRaw( final bytes = await _pickRaw(
() => FilePick.singleGalleryPick(sheetContext), () => FilePick.singleGalleryPick(sheetContext, forCrop: true),
); );
if (bytes == null || !sheetContext.mounted) return; if (bytes == null || !sheetContext.mounted) return;
result = bytes; result = bytes;
@@ -33,7 +33,9 @@ Future<Uint8List?> showChatBackgroundPickerSheet(BuildContext context) async {
leading: const Icon(Icons.photo_camera_outlined), leading: const Icon(Icons.photo_camera_outlined),
title: const Text('Foto aufnehmen'), title: const Text('Foto aufnehmen'),
onTap: () async { onTap: () async {
final bytes = await _pickRaw(() => FilePick.cameraPick(sheetContext)); final bytes = await _pickRaw(
() => FilePick.cameraPick(sheetContext, forCrop: true),
);
if (bytes == null || !sheetContext.mounted) return; if (bytes == null || !sheetContext.mounted) return;
result = bytes; result = bytes;
Navigator.of(sheetContext).pop(); Navigator.of(sheetContext).pop();
+24 -4
View File
@@ -23,11 +23,31 @@ class FilePick {
return pickedImages.isNotEmpty ? pickedImages : null; return pickedImages.isNotEmpty ? pickedImages : null;
}); });
static Future<XFile?> singleGalleryPick(BuildContext context) => static Future<XFile?> singleGalleryPick(
_guarded(context, () => _picker.pickImage(source: ImageSource.gallery)); BuildContext context, {
bool forCrop = false,
}) => _pickImage(context, ImageSource.gallery, forCrop: forCrop);
static Future<XFile?> cameraPick(BuildContext context) => static Future<XFile?> cameraPick(
_guarded(context, () => _picker.pickImage(source: ImageSource.camera)); BuildContext context, {
bool forCrop = false,
}) => _pickImage(context, ImageSource.camera, forCrop: forCrop);
/// [forCrop] makes the picker re-encode to a bounded JPEG: the Dart cropper
/// can't decode HEIC (iOS gallery default) and is slow on full-size photos.
static Future<XFile?> _pickImage(
BuildContext context,
ImageSource source, {
required bool forCrop,
}) => _guarded(
context,
() => _picker.pickImage(
source: source,
maxWidth: forCrop ? 2048 : null,
maxHeight: forCrop ? 2048 : null,
imageQuality: forCrop ? 90 : null,
),
);
static Future<List<String>?> documentPick() async { static Future<List<String>?> documentPick() async {
final result = await FilePicker.pickFiles(allowMultiple: true); final result = await FilePicker.pickFiles(allowMultiple: true);