fixed several runtime errors from client error reports
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user