Merge pull request #1030 from GetStream/live-event-improvements
feat(flutter): Live event integration improvements
This commit is contained in:
@@ -172,6 +172,7 @@ class StreamMessageListView extends StatefulWidget {
|
|||||||
const StreamMessageListView({
|
const StreamMessageListView({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.showScrollToBottom = true,
|
this.showScrollToBottom = true,
|
||||||
|
this.scrollToBottomBuilder,
|
||||||
this.messageBuilder,
|
this.messageBuilder,
|
||||||
this.parentMessageBuilder,
|
this.parentMessageBuilder,
|
||||||
this.parentMessage,
|
this.parentMessage,
|
||||||
@@ -243,6 +244,25 @@ class StreamMessageListView extends StatefulWidget {
|
|||||||
/// messages and the scroll offset is not zero
|
/// messages and the scroll offset is not zero
|
||||||
final bool showScrollToBottom;
|
final bool showScrollToBottom;
|
||||||
|
|
||||||
|
/// Function used to build a custom scroll to bottom widget
|
||||||
|
///
|
||||||
|
/// Provides the current unread messages count and a reference
|
||||||
|
/// to the function that is executed on tap of this widget by default
|
||||||
|
///
|
||||||
|
/// As an example:
|
||||||
|
/// MessageListView(
|
||||||
|
/// scrollToBottomBuilder: (unreadCount, defaultTapAction) {
|
||||||
|
/// return InkWell(
|
||||||
|
/// onTap: () => defaultTapAction(unreadCount),
|
||||||
|
/// child: Text('Scroll To Bottom'),
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// ),
|
||||||
|
final Widget Function(
|
||||||
|
int unreadCount,
|
||||||
|
Future<void> Function(int) scrollToBottomDefaultTapAction,
|
||||||
|
)? scrollToBottomBuilder;
|
||||||
|
|
||||||
/// Parent message in case of a thread
|
/// Parent message in case of a thread
|
||||||
final Message? parentMessage;
|
final Message? parentMessage;
|
||||||
|
|
||||||
@@ -848,30 +868,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
|
|||||||
.index;
|
.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildScrollToBottom() => StreamBuilder<int>(
|
Future<void> scrollToBottomDefaultTapAction(int unreadCount) async {
|
||||||
stream: streamChannel!.channel.state!.unreadCountStream,
|
|
||||||
builder: (_, snapshot) {
|
|
||||||
if (snapshot.hasError) {
|
|
||||||
return const Offstage();
|
|
||||||
} else if (!snapshot.hasData) {
|
|
||||||
return const Offstage();
|
|
||||||
}
|
|
||||||
final unreadCount = snapshot.data!;
|
|
||||||
final showUnreadCount = unreadCount > 0 &&
|
|
||||||
streamChannel!.channel.state!.members.any((e) =>
|
|
||||||
e.userId ==
|
|
||||||
streamChannel!.channel.client.state.currentUser!.id);
|
|
||||||
return Positioned(
|
|
||||||
bottom: 8,
|
|
||||||
right: 8,
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
child: Stack(
|
|
||||||
clipBehavior: Clip.none,
|
|
||||||
children: [
|
|
||||||
FloatingActionButton(
|
|
||||||
backgroundColor: _streamTheme.colorTheme.barsBg,
|
|
||||||
onPressed: () async {
|
|
||||||
if (unreadCount > 0) {
|
if (unreadCount > 0) {
|
||||||
streamChannel!.channel.markRead();
|
streamChannel!.channel.markRead();
|
||||||
}
|
}
|
||||||
@@ -892,7 +889,38 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
|
|||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
|
Widget _buildScrollToBottom() => StreamBuilder<int>(
|
||||||
|
stream: streamChannel!.channel.state!.unreadCountStream,
|
||||||
|
builder: (_, snapshot) {
|
||||||
|
if (snapshot.hasError) {
|
||||||
|
return const Offstage();
|
||||||
|
} else if (!snapshot.hasData) {
|
||||||
|
return const Offstage();
|
||||||
|
}
|
||||||
|
final unreadCount = snapshot.data!;
|
||||||
|
if (widget.scrollToBottomBuilder != null) {
|
||||||
|
return widget.scrollToBottomBuilder!(
|
||||||
|
unreadCount,
|
||||||
|
scrollToBottomDefaultTapAction,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final showUnreadCount = unreadCount > 0 &&
|
||||||
|
streamChannel!.channel.state!.members.any((e) =>
|
||||||
|
e.userId ==
|
||||||
|
streamChannel!.channel.client.state.currentUser!.id);
|
||||||
|
return Positioned(
|
||||||
|
bottom: 8,
|
||||||
|
right: 8,
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
clipBehavior: Clip.none,
|
||||||
|
children: [
|
||||||
|
FloatingActionButton(
|
||||||
|
backgroundColor: _streamTheme.colorTheme.barsBg,
|
||||||
|
onPressed: () => scrollToBottomDefaultTapAction(unreadCount),
|
||||||
child: widget.reverse
|
child: widget.reverse
|
||||||
? StreamSvgIcon.down(
|
? StreamSvgIcon.down(
|
||||||
color: _streamTheme.colorTheme.textHighEmphasis,
|
color: _streamTheme.colorTheme.textHighEmphasis,
|
||||||
|
|||||||
@@ -210,6 +210,8 @@ class StreamMessageInput extends StatefulWidget {
|
|||||||
this.enableSafeArea,
|
this.enableSafeArea,
|
||||||
this.elevation,
|
this.elevation,
|
||||||
this.shadow,
|
this.shadow,
|
||||||
|
this.autoCorrect,
|
||||||
|
this.disableEmojiSuggestionsOverlay,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// List of options for showing overlays.
|
/// List of options for showing overlays.
|
||||||
@@ -329,6 +331,14 @@ class StreamMessageInput extends StatefulWidget {
|
|||||||
/// Shadow for the [StreamMessageInput] widget
|
/// Shadow for the [StreamMessageInput] widget
|
||||||
final BoxShadow? shadow;
|
final BoxShadow? shadow;
|
||||||
|
|
||||||
|
/// Disable autoCorrect by passing false
|
||||||
|
/// autoCorrect is enabled by default
|
||||||
|
final bool? autoCorrect;
|
||||||
|
|
||||||
|
/// Disable the default emoji suggestions
|
||||||
|
/// Enabled by default
|
||||||
|
final bool? disableEmojiSuggestionsOverlay;
|
||||||
|
|
||||||
static bool _defaultValidator(Message message) =>
|
static bool _defaultValidator(Message message) =>
|
||||||
message.text?.isNotEmpty == true || message.attachments.isNotEmpty;
|
message.text?.isNotEmpty == true || message.attachments.isNotEmpty;
|
||||||
|
|
||||||
@@ -360,6 +370,11 @@ class StreamMessageInputState extends State<StreamMessageInput>
|
|||||||
bool get _isEditing =>
|
bool get _isEditing =>
|
||||||
_effectiveController.value.status != MessageSendingStatus.sending;
|
_effectiveController.value.status != MessageSendingStatus.sending;
|
||||||
|
|
||||||
|
bool get _autoCorrect => widget.autoCorrect ?? true;
|
||||||
|
|
||||||
|
bool get _disableEmojiSuggestionsOverlay =>
|
||||||
|
widget.disableEmojiSuggestionsOverlay ?? false;
|
||||||
|
|
||||||
RestorableMessageInputController? _controller;
|
RestorableMessageInputController? _controller;
|
||||||
|
|
||||||
MessageInputController get _effectiveController =>
|
MessageInputController get _effectiveController =>
|
||||||
@@ -589,6 +604,7 @@ class StreamMessageInputState extends State<StreamMessageInput>
|
|||||||
visible: _showCommandsOverlay,
|
visible: _showCommandsOverlay,
|
||||||
widget: _buildCommandsOverlayEntry(),
|
widget: _buildCommandsOverlayEntry(),
|
||||||
),
|
),
|
||||||
|
if (!_disableEmojiSuggestionsOverlay)
|
||||||
OverlayOptions(
|
OverlayOptions(
|
||||||
visible: _focusNode.hasFocus &&
|
visible: _focusNode.hasFocus &&
|
||||||
_effectiveController.text.isNotEmpty &&
|
_effectiveController.text.isNotEmpty &&
|
||||||
@@ -802,6 +818,7 @@ class StreamMessageInputState extends State<StreamMessageInput>
|
|||||||
textAlignVertical: TextAlignVertical.center,
|
textAlignVertical: TextAlignVertical.center,
|
||||||
decoration: _getInputDecoration(context),
|
decoration: _getInputDecoration(context),
|
||||||
textCapitalization: TextCapitalization.sentences,
|
textCapitalization: TextCapitalization.sentences,
|
||||||
|
autocorrect: _autoCorrect,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user