Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 190 additions & 0 deletions migrations/v10-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

This guide includes breaking changes grouped by release phase:

### 🚧 v10.0.0-beta.3

- [AttachmentPickerType](#-attachmentpickertype)
- [StreamAttachmentPickerOption](#-streamattachmentpickeroption)
- [showStreamAttachmentPickerModalBottomSheet](#-showstreamattachmentpickermodalbottomsheet)
- [AttachmentPickerBottomSheet](#-attachmentpickerbottomsheet)

### 🚧 v10.0.0-beta.1

- [StreamReactionPicker](#-streamreactionpicker)
Expand All @@ -17,6 +24,183 @@ This guide includes breaking changes grouped by release phase:

---

## 🧪 Migration for v10.0.0-beta.3

### 🛠 AttachmentPickerType

#### Key Changes:

- `AttachmentPickerType` enum replaced with sealed class hierarchy
- Now supports extensible custom types like contact and location pickers
- Use built-in types like `AttachmentPickerType.images` or define your own via `CustomAttachmentPickerType`

#### Migration Steps:

**Before:**
```dart
// Using enum-based attachment types
final attachmentType = AttachmentPickerType.images;
```

**After:**
```dart
// Using sealed class attachment types
final attachmentType = AttachmentPickerType.images;

// For custom types
class LocationAttachmentPickerType extends CustomAttachmentPickerType {
const LocationAttachmentPickerType();
}
```

> ⚠️ **Important:**
> The enum is now a sealed class, but the basic usage remains the same for built-in types.

---

### 🛠 StreamAttachmentPickerOption

#### Key Changes:

- `StreamAttachmentPickerOption` replaced with two sealed classes:
- `SystemAttachmentPickerOption` for system pickers (camera, files)
- `TabbedAttachmentPickerOption` for tabbed pickers (gallery, polls, location)

#### Migration Steps:

**Before:**
```dart
final option = AttachmentPickerOption(
title: 'Gallery',
icon: Icon(Icons.photo_library),
supportedTypes: [AttachmentPickerType.images, AttachmentPickerType.videos],
optionViewBuilder: (context, controller) {
return GalleryPickerView(controller: controller);
},
);

final webOrDesktopOption = WebOrDesktopAttachmentPickerOption(
title: 'File Upload',
icon: Icon(Icons.upload_file),
type: AttachmentPickerType.files,
);
```

**After:**
```dart
// For custom UI pickers (gallery, polls)
final tabbedOption = TabbedAttachmentPickerOption(
title: 'Gallery',
icon: Icon(Icons.photo_library),
supportedTypes: [AttachmentPickerType.images, AttachmentPickerType.videos],
optionViewBuilder: (context, controller) {
return GalleryPickerView(controller: controller);
},
);

// For system pickers (camera, file dialogs)
final systemOption = SystemAttachmentPickerOption(
title: 'Camera',
icon: Icon(Icons.camera_alt),
supportedTypes: [AttachmentPickerType.images],
onTap: (context, controller) => pickFromCamera(),
);
```

> ⚠️ **Important:**
> - Use `SystemAttachmentPickerOption` for system pickers (camera, file dialogs)
> - Use `TabbedAttachmentPickerOption` for custom UI pickers (gallery, polls)

---

### 🛠 showStreamAttachmentPickerModalBottomSheet

#### Key Changes:

- Now returns `StreamAttachmentPickerResult` instead of `AttachmentPickerValue`
- Improved type safety and clearer intent handling

#### Migration Steps:

**Before:**
```dart
final result = await showStreamAttachmentPickerModalBottomSheet(
context: context,
controller: controller,
);

// result is AttachmentPickerValue
```

**After:**
```dart
final result = await showStreamAttachmentPickerModalBottomSheet(
context: context,
controller: controller,
);

// result is StreamAttachmentPickerResult
switch (result) {
case AttachmentsPicked():
// Handle picked attachments
case PollCreated():
// Handle created poll
case AttachmentPickerError():
// Handle error
case CustomAttachmentPickerResult():
// Handle custom result
}
```

> ⚠️ **Important:**
> Always handle the new `StreamAttachmentPickerResult` return type with proper switch cases.

---

### 🛠 AttachmentPickerBottomSheet

#### Key Changes:

- `StreamMobileAttachmentPickerBottomSheet` → `StreamTabbedAttachmentPickerBottomSheet`
- `StreamWebOrDesktopAttachmentPickerBottomSheet` → `StreamSystemAttachmentPickerBottomSheet`

#### Migration Steps:

**Before:**
```dart
StreamMobileAttachmentPickerBottomSheet(
context: context,
controller: controller,
customOptions: [option],
);

StreamWebOrDesktopAttachmentPickerBottomSheet(
context: context,
controller: controller,
customOptions: [option],
);
```

**After:**
```dart
StreamTabbedAttachmentPickerBottomSheet(
context: context,
controller: controller,
customOptions: [tabbedOption],
);

StreamSystemAttachmentPickerBottomSheet(
context: context,
controller: controller,
customOptions: [systemOption],
);
```

> ⚠️ **Important:**
> The new names better reflect their respective layouts and functionality.

---

## 🧪 Migration for v10.0.0-beta.1

### 🛠 StreamReactionPicker
Expand Down Expand Up @@ -182,6 +366,12 @@ StreamMessageWidget(

## 🎉 You're Ready to Migrate!

### For v10.0.0-beta.3:
- ✅ Update attachment picker options to use `SystemAttachmentPickerOption` or `TabbedAttachmentPickerOption`
- ✅ Handle new `StreamAttachmentPickerResult` return type from attachment picker
- ✅ Use renamed bottom sheet classes (`StreamTabbedAttachmentPickerBottomSheet`, `StreamSystemAttachmentPickerBottomSheet`)

### For v10.0.0-beta.1:
- ✅ Use `StreamReactionPicker.builder` or supply `onReactionPicked`
- ✅ Convert all `StreamMessageAction` instances to type-safe generic usage
- ✅ Centralize handling with `onCustomActionTap`
Expand Down
16 changes: 13 additions & 3 deletions packages/stream_chat_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@

🛑️ Breaking

- `PollMessage` widget has been removed and replaced with `PollAttachment` for better integration
with the attachment system. Polls can now be customized through `PollAttachmentBuilder` or by
creating custom poll attachment widgets via the attachment builder system.
- `PollMessage` widget has been removed and replaced with `PollAttachment` for better integration with the attachment system. Polls can now be customized through `PollAttachmentBuilder` or by creating custom poll attachment widgets via the attachment builder system.
- `AttachmentPickerType` enum has been replaced with a sealed class to support extensible custom types like contact and location pickers. Use built-in types like `AttachmentPickerType.images` or define your own via `CustomAttachmentPickerType`.
- `StreamAttachmentPickerOption` has been replaced with two sealed classes to support layout-specific picker options: `SystemAttachmentPickerOption` for system pickers (e.g. camera, files) and `TabbedAttachmentPickerOption` for tabbed pickers (e.g. gallery, polls, location).
- `showStreamAttachmentPickerModalBottomSheet` now returns a `StreamAttachmentPickerResult` instead of `AttachmentPickerValue` for improved type safety and clearer intent handling.
- `StreamMobileAttachmentPickerBottomSheet` has been renamed to `StreamTabbedAttachmentPickerBottomSheet`, and `StreamWebOrDesktopAttachmentPickerBottomSheet` has been renamed to `StreamSystemAttachmentPickerBottomSheet` to better reflect their respective layouts.

For more details, please refer to the [migration guide](../../migrations/v10-migration.md).

✅ Added

- Added `extraData` field to `AttachmentPickerValue` to support storing and retrieving custom picker state (e.g. tab-specific config).
- Added `customAttachmentPickerOptions` to `StreamMessageInput` to allow injecting custom picker tabs like contact and location pickers.
- Added `onCustomAttachmentPickerResult` callback to `StreamMessageInput` to handle results returned by custom picker tabs.

## 10.0.0-beta.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ class _EditMessageSheetState extends State<EditMessageSheet> {
StreamMessageInput(
elevation: 0,
messageInputController: controller,
// Disallow editing poll for now as it's not supported.
allowedAttachmentPickerTypes: [
...AttachmentPickerType.values,
]..remove(AttachmentPickerType.poll),
preMessageSending: (m) {
FocusScope.of(context).unfocus();
Navigator.of(context).pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import 'package:photo_manager/photo_manager.dart';
import 'package:stream_chat_flutter/src/icons/stream_svg_icon.dart';
import 'package:stream_chat_flutter/src/message_input/attachment_picker/stream_attachment_picker.dart';
import 'package:stream_chat_flutter/src/message_input/attachment_picker/stream_attachment_picker_controller.dart';
import 'package:stream_chat_flutter/src/misc/empty_widget.dart';
import 'package:stream_chat_flutter/src/scroll_view/photo_gallery/stream_photo_gallery.dart';
import 'package:stream_chat_flutter/src/scroll_view/photo_gallery/stream_photo_gallery_controller.dart';
Expand All @@ -14,7 +15,7 @@
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';

/// Max image resolution which can be resized by the CDN.
// Taken from https://getstream.io/chat/docs/flutter-dart/file_uploads/?language=dart#image-resizing
/// Taken from https://getstream.io/chat/docs/flutter-dart/file_uploads/?language=dart#image-resizing
const maxCDNImageResolution = 16800000;

/// Widget used to pick media from the device gallery.
Expand All @@ -23,42 +24,23 @@
const StreamGalleryPicker({
super.key,
this.limit = 50,
GalleryPickerConfig? config,
required this.selectedMediaItems,
required this.onMediaItemSelected,
this.mediaThumbnailSize = const ThumbnailSize(400, 400),
this.mediaThumbnailFormat = ThumbnailFormat.jpeg,
this.mediaThumbnailQuality = 100,
this.mediaThumbnailScale = 1,
});
}) : config = config ?? const GalleryPickerConfig();

/// Maximum number of media items that can be selected.
final int limit;

/// Configuration for the gallery picker.
final GalleryPickerConfig config;

/// List of selected media items.
final Iterable<String> selectedMediaItems;

/// Callback called when an media item is selected.
final ValueSetter<AssetEntity> onMediaItemSelected;

/// Size of the attachment thumbnails.
///
/// Defaults to (400, 400).
final ThumbnailSize mediaThumbnailSize;

/// Format of the attachment thumbnails.
///
/// Defaults to [ThumbnailFormat.jpeg].
final ThumbnailFormat mediaThumbnailFormat;

/// The quality value for the attachment thumbnails.
///
/// Valid from 1 to 100.
/// Defaults to 100.
final int mediaThumbnailQuality;

/// The scale to apply on the [attachmentThumbnailSize].
final double mediaThumbnailScale;

@override
State<StreamGalleryPicker> createState() => _StreamGalleryPickerState();
}
Expand Down Expand Up @@ -159,10 +141,10 @@
onMediaTap: widget.onMediaItemSelected,
loadMoreTriggerIndex: 10,
padding: const EdgeInsets.all(2),
thumbnailSize: widget.mediaThumbnailSize,
thumbnailFormat: widget.mediaThumbnailFormat,
thumbnailQuality: widget.mediaThumbnailQuality,
thumbnailScale: widget.mediaThumbnailScale,
thumbnailSize: widget.config.mediaThumbnailSize,
thumbnailFormat: widget.config.mediaThumbnailFormat,
thumbnailQuality: widget.config.mediaThumbnailQuality,
thumbnailScale: widget.config.mediaThumbnailScale,

Check warning on line 147 in packages/stream_chat_flutter/lib/src/message_input/attachment_picker/options/stream_gallery_picker.dart

View check run for this annotation

Codecov / codecov/patch

packages/stream_chat_flutter/lib/src/message_input/attachment_picker/options/stream_gallery_picker.dart#L144-L147

Added lines #L144 - L147 were not covered by tests
itemBuilder: (context, mediaItems, index, defaultWidget) {
final media = mediaItems[index];
return defaultWidget.copyWith(
Expand All @@ -178,6 +160,29 @@
}
}

/// Configuration for the [StreamGalleryPicker].
class GalleryPickerConfig {
/// Creates a [GalleryPickerConfig] instance.
const GalleryPickerConfig({
this.mediaThumbnailSize = const ThumbnailSize(400, 400),
this.mediaThumbnailFormat = ThumbnailFormat.jpeg,
this.mediaThumbnailQuality = 100,
this.mediaThumbnailScale = 1,
});

/// Size of the attachment thumbnails.
final ThumbnailSize mediaThumbnailSize;

/// Format of the attachment thumbnails.
final ThumbnailFormat mediaThumbnailFormat;

/// The quality value for the attachment thumbnails.
final int mediaThumbnailQuality;

/// The scale to apply on the [mediaThumbnailSize].
final double mediaThumbnailScale;
}

///
extension StreamImagePickerX on StreamAttachmentPickerController {
///
Expand Down
Loading