Skip to content
2 changes: 1 addition & 1 deletion docs/docs_screenshots/test/reactions/reactions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void main() {
body: Center(
child: StreamMessageReactionPicker(
message: message,
onReactionPicked: (_) {},
onReactionSelected: (_, _) {},
),
),
),
Expand Down
5 changes: 5 additions & 0 deletions packages/stream_chat_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
✅ Added

- Added `StreamMessageListViewConfiguration.autoScrollPolicy` to control whether and how `StreamMessageListView` scrolls to the newest message when a new message arrives. Use `StreamAutoScrollPolicy.disabled` to fully control scrolling yourself.
- Added `onReactionSelected` to `StreamMessageReactionPicker`, a context-aware callback that provides the `BuildContext` for navigation.

🐞 Fixed

- Fixed `StreamTypingIndicator` briefly showing typing users from a different context (main channel vs. thread) on its first frame.

⚠️ Deprecated

- Deprecated `StreamMessageReactionPicker.onReactionPicked` in favor of `onReactionSelected`.

## 10.2.0

⚠️ Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class StreamMessageActionsModal extends StatelessWidget {
final spacing = context.streamSpacing;
final effectiveAlignment = alignment ?? StreamMessageLayout.alignmentDirectionalOf(context);

void onReactionPicked(Reaction reaction) {
void onReactionSelected(BuildContext context, Reaction reaction) {
final action = SelectReaction(message: message, reaction: reaction);
return Navigator.pop(context, action);
}
Expand All @@ -82,7 +82,7 @@ class StreamMessageActionsModal extends StatelessWidget {
padding: insetPadding,
child: StreamMessageReactionPicker(
message: message,
onReactionPicked: onReactionPicked,
onReactionSelected: onReactionSelected,
),
),
false => null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,13 +678,13 @@ class DefaultStreamMessageItem extends StatelessWidget {
currentUser: currentUser,
);

void onReactionPicked(Reaction reaction) {
void onReactionSelected(BuildContext context, Reaction reaction) {
final action = SelectReaction(message: message, reaction: reaction);
return Navigator.pop(context, action); // Pop the modal with the selected reaction action
}

return [
if (showPicker) StreamMessageReactionPicker(message: message, onReactionPicked: onReactionPicked),
if (showPicker) StreamMessageReactionPicker(message: message, onReactionSelected: onReactionSelected),
...actions,
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,78 @@ import 'package:stream_core_flutter/chat.dart';
/// {@template onReactionPicked}
/// Callback called when a reaction is picked.
/// {@endtemplate}
@Deprecated(
'Use OnReactionSelected instead. '
'OnReactionSelected provides the BuildContext required for nested navigation.',
)
typedef OnReactionPicked = ValueSetter<Reaction>;

/// {@template onReactionSelected}
/// Signature for the callback invoked when a reaction is selected.
/// {@endtemplate}
typedef OnReactionSelected = void Function(BuildContext context, Reaction reaction);

/// {@template streamMessageReactionPicker}
/// A chat-specific reaction picker that bridges [StreamReactionPicker] with
/// chat domain models.
///
/// Resolves reaction icons via [ReactionIconResolver], tracks the current
/// user's own reactions on the [Message], and wires the "add reaction" button
/// to [StreamEmojiPickerSheet].
/// user's own reactions on the [Message], and presents [StreamEmojiPickerSheet]
/// when the add reaction button is tapped.
///
/// Visual customisation is controlled through [StreamReactionPickerTheme] in
/// The [onReactionSelected] callback reports the selected [Reaction] along with
/// the picker's [BuildContext], so navigation targets the correct navigator in
/// nested navigation scenarios.
///
/// Visual customization is controlled through [StreamReactionPickerTheme] in
/// the widget tree.
///
/// See also:
///
/// * [StreamReactionPicker], the domain-agnostic core picker.
/// * [ReactionIconResolver], which maps reaction types to emoji content models.
/// * [StreamReactionPickerTheme], for customising the picker appearance.
/// * [StreamReactionPickerTheme], for customizing the picker appearance.
/// {@endtemplate}
class StreamMessageReactionPicker extends StatelessWidget {
/// {@macro streamMessageReactionPicker}
const StreamMessageReactionPicker({
super.key,
required this.message,
@Deprecated(
'Use onReactionSelected instead. '
'onReactionSelected provides the BuildContext required for nested navigation.',
)
this.onReactionPicked,
});
this.onReactionSelected,
}) : assert(
onReactionPicked == null || onReactionSelected == null,
'Only one of onReactionPicked or onReactionSelected can be provided. '
'Prefer onReactionSelected; onReactionPicked is deprecated.',
);

/// The message to attach the reaction to.
final Message message;

/// {@macro onReactionPicked}
@Deprecated(
'Use onReactionSelected instead. '
'onReactionSelected provides the BuildContext required for nested navigation.',
)
final OnReactionPicked? onReactionPicked;
Comment thread
xsahil03x marked this conversation as resolved.

/// {@macro onReactionSelected}
final OnReactionSelected? onReactionSelected;

// Dispatches a picked reaction to the active callback, preferring the
// context-aware [onReactionSelected] over the deprecated [onReactionPicked].
void _handleReactionSelected(BuildContext context, Reaction reaction) {
if (onReactionSelected case final onReactionSelected?) {
return onReactionSelected(context, reaction);
}

return onReactionPicked?.call(reaction);
}

@override
Widget build(BuildContext context) {
final config = StreamChatConfiguration.of(context);
Expand Down Expand Up @@ -66,7 +105,7 @@ class StreamMessageReactionPicker extends StatelessWidget {
_ => Reaction(type: item.key, emojiCode: reactionEmojiCode),
};

return onReactionPicked?.call(pickedReaction);
return _handleReactionSelected(context, pickedReaction);
}

return StreamReactionPicker(
Expand All @@ -84,7 +123,7 @@ class StreamMessageReactionPicker extends StatelessWidget {
if (!context.mounted || emoji == null) return;

final reaction = Reaction(type: emoji.shortName, emojiCode: emoji.emoji);
return onReactionPicked?.call(reaction);
return _handleReactionSelected(context, reaction);
},
);
}
Expand Down
Loading
Loading