Skip to content

Commit e93a276

Browse files
committed
feat(ui)!: Enhance onAttachmentTap with fallback to default behavior
This commit introduces a significant enhancement to the `onAttachmentTap` callback, allowing for more flexible and powerful customization of attachment interactions. Key changes: - The `onAttachmentTap` callback signature is updated to `FutureOr<bool> Function(BuildContext, Message, Attachment)`. - The callback now returns a `FutureOr<bool>`. Returning `true` signifies that the tap has been handled by custom logic, preventing the default behavior. Returning `false` allows the default SDK behavior (e.g., opening image/video viewer, launching URLs) to execute. - The `BuildContext` is now passed as the first parameter to the callback. - The `onLinkTap` callback is now respected for URL attachments, providing more granular control over link handling. This change enables developers to implement custom logic for specific attachment types while seamlessly falling back to the default SDK handling for all other types, reducing boilerplate and improving user experience.
1 parent 3f89e28 commit e93a276

File tree

7 files changed

+239
-63
lines changed

7 files changed

+239
-63
lines changed

migrations/v10-migration.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
This guide includes breaking changes grouped by release phase:
1010

11+
### 🚧 Upcoming Beta
12+
13+
- [onAttachmentTap](#-onattachmenttap)
14+
1115
### 🚧 v10.0.0-beta.8
1216

1317
- [customAttachmentPickerOptions](#-customattachmentpickeroptions)
@@ -38,6 +42,79 @@ This guide includes breaking changes grouped by release phase:
3842

3943
---
4044

45+
## 🧪 Migration for Upcoming Beta
46+
47+
### 🛠 onAttachmentTap
48+
49+
#### Key Changes:
50+
51+
- `onAttachmentTap` callback signature has changed to support custom attachment handling with automatic fallback to default behavior.
52+
- Callback now receives `BuildContext` as the first parameter.
53+
- Returns `FutureOr<bool>` to indicate whether the attachment was handled.
54+
- Returning `true` skips default behavior, `false` uses default handling (URLs, images, videos, giphys).
55+
56+
#### Migration Steps:
57+
58+
**Before:**
59+
```dart
60+
StreamMessageWidget(
61+
message: message,
62+
onAttachmentTap: (message, attachment) {
63+
// Could only override - no way to fallback to default behavior
64+
if (attachment.type == 'location') {
65+
showLocationDialog(context, attachment);
66+
}
67+
// Other attachment types (images, videos, URLs) lost default behavior
68+
},
69+
)
70+
```
71+
72+
**After:**
73+
```dart
74+
StreamMessageWidget(
75+
message: message,
76+
onAttachmentTap: (context, message, attachment) async {
77+
if (attachment.type == 'location') {
78+
await showLocationDialog(context, attachment);
79+
return true; // Handled by custom logic
80+
}
81+
return false; // Use default behavior for images, videos, URLs, etc.
82+
},
83+
)
84+
```
85+
86+
**Example: Handling multiple custom types**
87+
```dart
88+
StreamMessageWidget(
89+
message: message,
90+
onAttachmentTap: (context, message, attachment) async {
91+
switch (attachment.type) {
92+
case 'location':
93+
await Navigator.push(
94+
context,
95+
MaterialPageRoute(builder: (_) => MapView(attachment)),
96+
);
97+
return true;
98+
99+
case 'product':
100+
await showProductDialog(context, attachment);
101+
return true;
102+
103+
default:
104+
return false; // Images, videos, URLs use default viewer
105+
}
106+
},
107+
)
108+
```
109+
110+
> ⚠️ **Important:**
111+
> - The callback now requires `BuildContext` as the first parameter
112+
> - Must return `FutureOr<bool>` - `true` if handled, `false` for default behavior
113+
> - Default behavior automatically handles URL previews, images, videos, and giphys
114+
> - Supports both synchronous and asynchronous operations
115+
116+
---
117+
41118
## 🧪 Migration for v10.0.0-beta.8
42119

43120
### 🛠 customAttachmentPickerOptions
@@ -750,6 +827,11 @@ StreamMessageWidget(
750827

751828
## 🎉 You're Ready to Migrate!
752829

830+
### For Upcoming Beta:
831+
- ✅ Update `onAttachmentTap` callback signature to include `BuildContext` as first parameter
832+
- ✅ Return `FutureOr<bool>` from `onAttachmentTap` - `true` if handled, `false` for default behavior
833+
- ✅ Leverage automatic fallback to default handling for standard attachment types (images, videos, URLs)
834+
753835
### For v10.0.0-beta.8:
754836
- ✅ Replace `customAttachmentPickerOptions` with `attachmentPickerOptionsBuilder` to access and modify default options
755837
- ✅ Replace `onCustomAttachmentPickerResult` with `onAttachmentPickerResult` that returns `FutureOr<bool>`

packages/stream_chat_flutter/CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1+
## Upcoming Beta
2+
3+
🛑️ Breaking
4+
5+
- `onAttachmentTap` callback signature has changed to support custom attachment handling with automatic fallback to default behavior. The callback now receives `BuildContext` as the first parameter and returns `FutureOr<bool>` to indicate if the attachment was handled.
6+
```dart
7+
// Before
8+
StreamMessageWidget(
9+
message: message,
10+
onAttachmentTap: (message, attachment) {
11+
// Could only override - no way to fallback to default behavior
12+
if (attachment.type == 'location') {
13+
showLocationDialog(context, attachment);
14+
}
15+
// Other attachment types lost default behavior
16+
},
17+
)
18+
19+
// After
20+
StreamMessageWidget(
21+
message: message,
22+
onAttachmentTap: (context, message, attachment) async {
23+
if (attachment.type == 'location') {
24+
await showLocationDialog(context, attachment);
25+
return true; // Handled by custom logic
26+
}
27+
return false; // Use default behavior for images, videos, URLs, etc.
28+
},
29+
)
30+
```
31+
32+
For more details, please refer to the [migration guide](../../migrations/v10-migration.md).
33+
134
## 10.0.0-beta.8
235

336
🛑️ Breaking
@@ -54,6 +87,8 @@
5487
},
5588
)
5689
```
90+
91+
For more details, please refer to the [migration guide](../../migrations/v10-migration.md).
5792

5893
- Included the changes from version [`9.19.0`](https://pub.dev/packages/stream_chat_flutter/changelog).
5994

packages/stream_chat_flutter/lib/src/message_widget/message_card.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ class MessageCard extends StatefulWidget {
8383
/// {@macro attachmentShape}
8484
final ShapeBorder? attachmentShape;
8585

86-
/// {@macro onAttachmentTap}
87-
final StreamAttachmentWidgetTapCallback? onAttachmentTap;
86+
/// {@macro onAttachmentWidgetTap}
87+
final OnAttachmentWidgetTap? onAttachmentTap;
8888

8989
/// {@macro onShowMessage}
9090
final ShowMessageCallback? onShowMessage;
@@ -188,6 +188,7 @@ class _MessageCardState extends State<MessageCard> {
188188
attachmentShape: widget.attachmentShape,
189189
onAttachmentTap: widget.onAttachmentTap,
190190
onShowMessage: widget.onShowMessage,
191+
onLinkTap: widget.onLinkTap,
191192
onReplyTap: widget.onReplyTap,
192193
attachmentActionsModalBuilder: widget.attachmentActionsModalBuilder,
193194
),

packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ class StreamMessageWidget extends StatefulWidget {
377377
/// {@macro onMessageActionTap}
378378
final OnMessageActionTap<CustomMessageAction>? onCustomActionTap;
379379

380-
/// {@macro onMessageWidgetAttachmentTap}
381-
final StreamAttachmentWidgetTapCallback? onAttachmentTap;
380+
/// {@macro onAttachmentWidgetTap}
381+
final OnAttachmentWidgetTap? onAttachmentTap;
382382

383383
/// {@macro attachmentActionsBuilder}
384384
final AttachmentActionsBuilder? attachmentActionsModalBuilder;
@@ -462,7 +462,7 @@ class StreamMessageWidget extends StatefulWidget {
462462
OnReactionsHover? onReactionsHover,
463463
List<StreamMessageAction>? customActions,
464464
OnMessageActionTap<CustomMessageAction>? onCustomActionTap,
465-
void Function(Message message, Attachment attachment)? onAttachmentTap,
465+
OnAttachmentWidgetTap? onAttachmentTap,
466466
Widget Function(BuildContext, User)? userAvatarBuilder,
467467
Size? imageAttachmentThumbnailSize,
468468
String? imageAttachmentThumbnailResizeType,

packages/stream_chat_flutter/lib/src/message_widget/message_widget_content.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ class MessageWidgetContent extends StatelessWidget {
152152
/// {@macro attachmentShape}
153153
final ShapeBorder? attachmentShape;
154154

155-
/// {@macro onAttachmentTap}
156-
final StreamAttachmentWidgetTapCallback? onAttachmentTap;
155+
/// {@macro onAttachmentWidgetTap}
156+
final OnAttachmentWidgetTap? onAttachmentTap;
157157

158158
/// {@macro onShowMessage}
159159
final ShowMessageCallback? onShowMessage;

0 commit comments

Comments
 (0)