Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 8 additions & 0 deletions packages/stream_chat_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 10.0.0-beta.3

🛑️ 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.

## 10.0.0-beta.2

- Included the changes from version [`9.13.0`](https://pub.dev/packages/stream_chat_flutter/changelog).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ export 'file_attachment.dart';
export 'gallery_attachment.dart';
export 'giphy_attachment.dart';
export 'image_attachment.dart';
export 'poll_attachment.dart';
export 'url_attachment.dart';
export 'video_attachment.dart';
export 'voice_recording_attachment.dart';
export 'voice_recording_attachment_playlist.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ class AttachmentWidgetCatalog {
Widget build(BuildContext context, Message message) {
assert(!message.isDeleted, 'Cannot build attachment for deleted message');

assert(
message.attachments.isNotEmpty,
'Cannot build attachment for message without attachments',
);

// The list of attachments to build the widget for.
final attachments = message.attachments.grouped;
for (final builder in builders) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ part 'url_attachment_builder.dart';
part 'video_attachment_builder.dart';
part 'voice_recording_attachment_playlist_builder.dart';
part 'voice_recording_attachment_builder/voice_recording_attachment_builder.dart';
part 'poll_attachment_builder.dart';

/// {@template streamAttachmentWidgetTapCallback}
/// Signature for a function that's called when the user taps on an attachment.
Expand Down Expand Up @@ -43,6 +44,8 @@ abstract class StreamAttachmentWidgetBuilder {
/// * [FileAttachmentBuilder]
/// * [ImageAttachmentBuilder]
/// * [VideoAttachmentBuilder]
/// * [VoiceRecordingAttachmentPlaylistBuilder]
/// * [PollAttachmentBuilder]
/// * [UrlAttachmentBuilder]
/// * [FallbackAttachmentBuilder]
///
Expand Down Expand Up @@ -72,7 +75,14 @@ abstract class StreamAttachmentWidgetBuilder {
return [
...?customAttachmentBuilders,

// Handles a mix of image, gif, video, url and file attachments.
// Handles poll attachments.
PollAttachmentBuilder(
shape: shape,
padding: padding,
),

// Handles a mix of image, gif, video, url, file and voice recording
// attachments.
MixedAttachmentBuilder(
padding: padding,
onAttachmentTap: onAttachmentTap,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
part of 'attachment_widget_builder.dart';

const _kDefaultPollMessageConstraints = BoxConstraints(
maxWidth: 270,
);

/// {@template pollAttachmentBuilder}
/// A widget builder for Poll attachment type.
///
/// This builder is used when a message contains a poll.
/// {@endtemplate}
class PollAttachmentBuilder extends StreamAttachmentWidgetBuilder {
/// {@macro urlAttachmentBuilder}
const PollAttachmentBuilder({
this.shape,
this.padding = const EdgeInsets.all(8),
this.constraints = _kDefaultPollMessageConstraints,
});

/// The shape of the poll attachment.
final ShapeBorder? shape;

/// The constraints to apply to the poll attachment widget.
final BoxConstraints constraints;

/// The padding to apply to the poll attachment widget.
final EdgeInsetsGeometry padding;

@override
bool canHandle(
Message message,
Map<String, List<Attachment>> attachments,
) {
final poll = message.poll;
return poll != null;
}

@override
Widget build(
BuildContext context,
Message message,
Map<String, List<Attachment>> attachments,
) {
assert(debugAssertCanHandle(message, attachments), '');

return Padding(
padding: padding,
child: PollAttachment(
message: message,
shape: shape,
constraints: constraints,
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,43 @@ import 'package:stream_chat_flutter/src/poll/stream_poll_comments_dialog.dart';
import 'package:stream_chat_flutter/src/poll/stream_poll_options_dialog.dart';
import 'package:stream_chat_flutter/src/poll/stream_poll_results_dialog.dart';
import 'package:stream_chat_flutter/src/stream_chat.dart';
import 'package:stream_chat_flutter/src/theme/stream_chat_theme.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';

const _maxVisibleOptionCount = 10;

const _kDefaultPollMessageConstraints = BoxConstraints(
maxWidth: 270,
);

/// {@template pollMessage}
/// A widget that displays a poll message.
///
/// Used in [MessageCard] to display a poll message.
/// {@endtemplate}
class PollMessage extends StatefulWidget {
class PollAttachment extends StatefulWidget {
/// {@macro pollMessage}
const PollMessage({
const PollAttachment({
super.key,
required this.message,
this.shape,
this.constraints = const BoxConstraints(),
});

/// The message with the poll to display.
final Message message;

/// The shape of the poll attachment.
final ShapeBorder? shape;

/// The constraints to apply to the poll attachment widget.
final BoxConstraints constraints;

@override
State<PollMessage> createState() => _PollMessageState();
State<PollAttachment> createState() => _PollAttachmentState();
}

class _PollMessageState extends State<PollMessage> {
class _PollAttachmentState extends State<PollAttachment> {
late final _messageNotifier = ValueNotifier(widget.message);

@override
void didUpdateWidget(covariant PollMessage oldWidget) {
void didUpdateWidget(covariant PollAttachment oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.message != widget.message) {
// If the message changes, schedule an update for the next frame
Expand All @@ -57,6 +62,17 @@ class _PollMessageState extends State<PollMessage> {

@override
Widget build(BuildContext context) {
final theme = StreamChatTheme.of(context);

final shape = widget.shape ??
RoundedRectangleBorder(
side: BorderSide(
color: theme.colorTheme.borders,
strokeAlign: BorderSide.strokeAlignOutside,
),
borderRadius: BorderRadius.circular(14),
);

return ValueListenableBuilder(
valueListenable: _messageNotifier,
builder: (context, message, child) {
Expand Down Expand Up @@ -96,8 +112,9 @@ class _PollMessageState extends State<PollMessage> {
channel.createPollOption(poll, PollOption(text: optionText));
}

return ConstrainedBox(
constraints: _kDefaultPollMessageConstraints,
return Container(
constraints: widget.constraints,
decoration: ShapeDecoration(shape: shape),
child: StreamPollInteractor(
poll: poll,
currentUser: currentUser,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/attachment/voice_recording_attachment.dart';
import 'package:stream_chat_flutter/src/audio/audio_playlist_controller.dart';
import 'package:stream_chat_flutter/src/misc/empty_widget.dart';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class MessageCard extends StatefulWidget {
required this.hasQuotedMessage,
required this.hasUrlAttachments,
required this.hasNonUrlAttachments,
required this.hasPoll,
required this.isOnlyEmoji,
required this.isGiphy,
required this.attachmentBuilders,
Expand Down Expand Up @@ -66,9 +65,6 @@ class MessageCard extends StatefulWidget {
/// {@macro hasNonUrlAttachments}
final bool hasNonUrlAttachments;

/// {@macro hasPoll}
final bool hasPoll;

/// {@macro isOnlyEmoji}
final bool isOnlyEmoji;

Expand Down Expand Up @@ -128,10 +124,6 @@ class _MessageCardState extends State<MessageCard> {
final attachmentsKey = GlobalKey();
double? widthLimit;

bool get hasAttachments {
return widget.hasUrlAttachments || widget.hasNonUrlAttachments;
}

void _updateWidthLimit() {
final attachmentContext = attachmentsKey.currentContext;
final renderBox = attachmentContext?.findRenderObject() as RenderBox?;
Expand All @@ -150,11 +142,9 @@ class _MessageCardState extends State<MessageCard> {
// If there is an attachment, we need to wait for the attachment to be
// rendered to get the width of the attachment and set it as the width
// limit of the message card.
if (hasAttachments) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateWidthLimit();
});
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateWidthLimit();
});
}

@override
Expand Down Expand Up @@ -201,23 +191,17 @@ class _MessageCardState extends State<MessageCard> {
hasNonUrlAttachments: widget.hasNonUrlAttachments,
),
),
if (hasAttachments)
ParseAttachments(
key: attachmentsKey,
message: widget.message,
attachmentBuilders: widget.attachmentBuilders,
attachmentPadding: widget.attachmentPadding,
attachmentShape: widget.attachmentShape,
onAttachmentTap: widget.onAttachmentTap,
onShowMessage: widget.onShowMessage,
onReplyTap: widget.onReplyTap,
attachmentActionsModalBuilder:
widget.attachmentActionsModalBuilder,
),
if (widget.hasPoll)
PollMessage(
message: widget.message,
),
ParseAttachments(
key: attachmentsKey,
message: widget.message,
attachmentBuilders: widget.attachmentBuilders,
attachmentPadding: widget.attachmentPadding,
attachmentShape: widget.attachmentShape,
onAttachmentTap: widget.onAttachmentTap,
onShowMessage: widget.onShowMessage,
onReplyTap: widget.onReplyTap,
attachmentActionsModalBuilder: widget.attachmentActionsModalBuilder,
),
TextBubble(
messageTheme: widget.messageTheme,
message: widget.message,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,11 +600,6 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
bool get hasNonUrlAttachments => widget.message.attachments
.any((it) => it.type != AttachmentType.urlPreview);

/// {@template hasPoll}
/// `true` if the [message] contains a poll.
/// {@endtemplate}
bool get hasPoll => widget.message.poll != null;

/// {@template hasUrlAttachments}
/// `true` if any of the [message]'s attachments are a giphy with a
/// [Attachment.titleLink].
Expand Down Expand Up @@ -719,7 +714,6 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
reverse: widget.reverse,
message: widget.message,
hasNonUrlAttachments: hasNonUrlAttachments,
hasPoll: hasPoll,
hasQuotedMessage: hasQuotedMessage,
textPadding: widget.textPadding,
attachmentBuilders: widget.attachmentBuilders,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class MessageWidgetContent extends StatelessWidget {
required this.hasQuotedMessage,
required this.hasUrlAttachments,
required this.hasNonUrlAttachments,
required this.hasPoll,
required this.isOnlyEmoji,
required this.isGiphy,
required this.attachmentBuilders,
Expand Down Expand Up @@ -137,9 +136,6 @@ class MessageWidgetContent extends StatelessWidget {
/// {@macro hasNonUrlAttachments}
final bool hasNonUrlAttachments;

/// {@macro hasPoll}
final bool hasPoll;

/// {@macro isOnlyEmoji}
final bool isOnlyEmoji;

Expand Down Expand Up @@ -363,7 +359,6 @@ class MessageWidgetContent extends StatelessWidget {
hasQuotedMessage: hasQuotedMessage,
hasUrlAttachments: hasUrlAttachments,
hasNonUrlAttachments: hasNonUrlAttachments,
hasPoll: hasPoll,
isOnlyEmoji: isOnlyEmoji,
isGiphy: isGiphy,
attachmentBuilders: attachmentBuilders,
Expand Down
1 change: 0 additions & 1 deletion packages/stream_chat_flutter/lib/stream_chat_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export 'src/message_widget/message_text.dart';
export 'src/message_widget/message_widget.dart';
export 'src/message_widget/message_widget_content_components.dart';
export 'src/message_widget/moderated_message.dart';
export 'src/message_widget/poll_message.dart';
export 'src/message_widget/system_message.dart';
export 'src/message_widget/text_bubble.dart';
export 'src/misc/adaptive_dialog_action.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:alchemist/alchemist.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:stream_chat_flutter/src/attachment/voice_recording_attachment.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';

import '../mocks.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:alchemist/alchemist.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter/src/attachment/voice_recording_attachment.dart';
import 'package:stream_chat_flutter/src/audio/audio_playlist_state.dart';
import 'package:stream_chat_flutter/src/misc/audio_waveform.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
Expand Down
Loading