diff --git a/melos.yaml b/melos.yaml index 4172629cd9..a5bb91076f 100644 --- a/melos.yaml +++ b/melos.yaml @@ -52,7 +52,7 @@ command: # upper bounds once FlutterFire ships a fixed release. firebase_crashlytics: '>=5.2.0 <5.2.5' firebase_messaging: '>=16.0.0 <16.4.2' - file_picker: ^11.0.0 + file_picker: ^12.1.0 file_selector: ^1.1.0 app_badge_plus: ^1.3.2 flutter_local_notifications: ^21.0.0 diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 7a1c74ed54..a557abab19 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -8,13 +8,17 @@ - Long-pressing a reaction chip no longer opens the message actions modal; the chips always claim the long press. Left unset, `onReactionLongPress` defaults to opening the `ReactionDetailSheet`. - Tapping or long-pressing a reaction chip now opens the `ReactionDetailSheet` pre-filtered to that reaction; it previously opened unfiltered. Clustered and overflow chips map to no single reaction, so they still open unfiltered. +- **BREAKING**: `PlatformFileX.toAttachmentFile` and `PlatformFileX.toAttachment` are now asynchronous, returning `Future` and `Future`. `file_picker` 12 removed `PlatformFile`'s eagerly-loaded `bytes` and `size` getters, so the content is read on demand. Both are exported, so callers must `await` them; this matches the existing `XFileX` extensions. 🔄 Changed - Raised minimum Flutter to `>=3.44.0` and Dart SDK to `^3.12.0`. +- Bumped `file_picker` to `^12.1.0`. +- `StreamAttachmentHandler.pickFile` no longer forwards `withData` and `withReadStream`; `file_picker` deprecated them in favour of reading the content on demand. The method's own signature is unchanged. 🐞 Fixed +- Fixed `StreamAttachmentHandler.pickFile` throwing when the picker returned an empty selection: it took `.files.first` unconditionally. It now returns `null`. - Fixed a crash on web when the message list rebuilt while messages were selectable, for example after opening the attachment picker. - Fixed the browser's native context menu reappearing over the message context menu on web after scrolling messages out of view or deleting one. - Fixed the SDK re-enabling the browser's native context menu on web in apps that had disabled it themselves. diff --git a/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_html.dart b/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_html.dart index 92314a8cd1..1712497431 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_html.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_html.dart @@ -25,19 +25,18 @@ class StreamAttachmentHandler extends StreamAttachmentHandlerBase { bool withReadStream = false, bool lockParentWindow = true, }) async { - final result = await FilePicker.pickFiles( + final result = await FilePicker.pickFile( dialogTitle: dialogTitle, initialDirectory: initialDirectory, type: type, allowedExtensions: allowedExtensions, onFileLoading: onFileLoading, compressionQuality: compressionQuality, - withData: withData, - withReadStream: withReadStream, - lockParentWindow: lockParentWindow, + windowsOptions: WindowsOptions(lockParentWindow: lockParentWindow), + linuxOptions: LinuxOptions(lockParentWindow: lockParentWindow), ); - return result?.files.first.toAttachment(type: type.toAttachmentType()); + return await result?.toAttachment(type: type.toAttachmentType()); } @override diff --git a/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart b/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart index a3d1bc7ca8..b666d4ff44 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/handler/stream_attachment_handler_io.dart @@ -134,19 +134,18 @@ class StreamAttachmentHandler extends StreamAttachmentHandlerBase { bool withReadStream = false, bool lockParentWindow = true, }) async { - final result = await FilePicker.pickFiles( + final result = await FilePicker.pickFile( dialogTitle: dialogTitle, initialDirectory: initialDirectory, type: type, allowedExtensions: allowedExtensions, onFileLoading: onFileLoading, compressionQuality: compressionQuality, - withData: withData, - withReadStream: withReadStream, - lockParentWindow: lockParentWindow, + windowsOptions: WindowsOptions(lockParentWindow: lockParentWindow), + linuxOptions: LinuxOptions(lockParentWindow: lockParentWindow), ); - return result?.files.first.toAttachment(type: type.toAttachmentType()); + return await result?.toAttachment(type: type.toAttachmentType()); } @override diff --git a/packages/stream_chat_flutter/lib/src/utils/extensions.dart b/packages/stream_chat_flutter/lib/src/utils/extensions.dart index 88b771b630..ebf006fc52 100644 --- a/packages/stream_chat_flutter/lib/src/utils/extensions.dart +++ b/packages/stream_chat_flutter/lib/src/utils/extensions.dart @@ -115,19 +115,22 @@ extension IterableExtension on Iterable { /// Useful extension for [PlatformFile] extension PlatformFileX on PlatformFile { /// Converts the [PlatformFile] into [AttachmentFile] - AttachmentFile get toAttachmentFile { + /// + /// Reads the file content on demand, so the result is asynchronous. + Future get toAttachmentFile async { + final bytes = await readAsBytes(); return AttachmentFile( // Path is not supported on web. path: CurrentPlatform.isWeb ? null : path, name: name, + size: bytes.length, bytes: bytes, - size: size, ); } /// Converts the [PlatformFile] to a [Attachment]. - Attachment toAttachment({required String type}) { - final file = toAttachmentFile; + Future toAttachment({required String type}) async { + final file = await toAttachmentFile; final extraDataMap = {}; final mimeType = file.mediaType?.mimeType; diff --git a/packages/stream_chat_flutter/pubspec.yaml b/packages/stream_chat_flutter/pubspec.yaml index bba0f2a0f3..a83d9dd771 100644 --- a/packages/stream_chat_flutter/pubspec.yaml +++ b/packages/stream_chat_flutter/pubspec.yaml @@ -30,7 +30,7 @@ dependencies: diacritic: ^0.1.6 dio: ^5.11.0 ezanimation: ^0.6.0 - file_picker: ^11.0.0 + file_picker: ^12.1.0 file_selector: ^1.1.0 flutter: sdk: flutter diff --git a/sample_app/android/build.gradle b/sample_app/android/build.gradle index 22f412dfaa..79709112b1 100644 --- a/sample_app/android/build.gradle +++ b/sample_app/android/build.gradle @@ -25,6 +25,17 @@ subprojects { } +// Plugin projects evaluate before `:app` by default, but the Flutter Gradle +// plugin only registers the `flutter` extension on them while `:app` is being +// configured. A plugin whose build script reads that extension at configuration +// time — android_file_picker, pulled in by file_picker 12 — fails without this. +// Present in the current Flutter app template; this module predates it. Kept in +// its own block, after the one above: forcing evaluation from inside that block +// would run `:app` before its `afterEvaluate` is registered. +subprojects { + project.evaluationDependsOn(":app") +} + tasks.register("clean", Delete) { delete rootProject.layout.buildDirectory } \ No newline at end of file