fix: add more actions locations, merge actions and add showCommandsButton option (#333)

* add more actions locations and merge actions

* remove print

* fix command chip

* fix ui

* rotate icon
This commit is contained in:
Salvatore Giordano
2021-03-15 14:40:36 +01:00
committed by GitHub
parent 9f002f32b3
commit f60f43af49
@@ -12,12 +12,12 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:image_picker/image_picker.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:shimmer/shimmer.dart';
import 'package:stream_chat_flutter/src/video_service.dart';
import 'package:stream_chat_flutter/src/media_list_view.dart';
import 'package:stream_chat_flutter/src/message_list_view.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
import 'package:stream_chat_flutter/src/user_avatar.dart';
import 'package:stream_chat_flutter/src/video_service.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'package:substring_highlight/substring_highlight.dart';
@@ -35,6 +35,8 @@ typedef AttachmentThumbnailBuilder = Widget Function(
enum ActionsLocation {
left,
right,
leftInside,
rightInside,
}
enum DefaultAttachmentTypes {
@@ -122,6 +124,7 @@ class MessageInput extends StatefulWidget {
this.hideSendAsDm = false,
this.idleSendButton,
this.activeSendButton,
this.showCommandsButton = true,
}) : super(key: key);
/// Message to edit
@@ -149,6 +152,9 @@ class MessageInput extends StatefulWidget {
/// If true the attachments button will not be displayed
final bool disableAttachments;
/// Use this property to hide/show the commands button
final bool showCommandsButton;
/// Hide send as dm checkbox
final bool hideSendAsDm;
@@ -336,12 +342,11 @@ class MessageInputState extends State<MessageInput> {
direction: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
if (!_commandEnabled) _buildExpandActionsButton(),
if (widget.actionsLocation == ActionsLocation.left)
...widget.actions ?? [],
if (!_commandEnabled && widget.actionsLocation == ActionsLocation.left)
_buildExpandActionsButton(),
_buildTextInput(context),
if (widget.actionsLocation == ActionsLocation.right)
...widget.actions ?? [],
if (!_commandEnabled && widget.actionsLocation == ActionsLocation.right)
_buildExpandActionsButton(),
if (widget.sendButtonLocation == SendButtonLocation.outside)
_animateSendButton(context),
],
@@ -421,18 +426,15 @@ class MessageInputState extends State<MessageInput> {
child: widget.activeSendButton,
)
: _buildSendButton(context);
return Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedCrossFade(
crossFadeState: (_messageIsPresent || _attachments.isNotEmpty)
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstChild: sendButton,
secondChild: widget.idleSendButton ?? _buildIdleSendButton(context),
duration:
StreamChatTheme.of(context).messageInputTheme.sendAnimationDuration,
alignment: Alignment.center,
),
return AnimatedCrossFade(
crossFadeState: (_messageIsPresent || _attachments.isNotEmpty)
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstChild: sendButton,
secondChild: widget.idleSendButton ?? _buildIdleSendButton(context),
duration:
StreamChatTheme.of(context).messageInputTheme.sendAnimationDuration,
alignment: Alignment.center,
);
}
@@ -445,8 +447,15 @@ class MessageInputState extends State<MessageInput> {
: CrossFadeState.showSecond,
firstChild: IconButton(
onPressed: () => setState(() => _actionsShrunk = false),
icon: StreamSvgIcon.emptyCircleLeft(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
icon: Transform.rotate(
alignment: Alignment.center,
angle: (widget.actionsLocation == ActionsLocation.right ||
widget.actionsLocation == ActionsLocation.rightInside)
? pi
: 0,
child: StreamSvgIcon.emptyCircleLeft(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
),
),
padding: const EdgeInsets.all(0),
constraints: BoxConstraints.tightFor(
@@ -457,10 +466,12 @@ class MessageInputState extends State<MessageInput> {
),
secondChild: FittedBox(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
children: <Widget>[
if (!widget.disableAttachments) _buildAttachmentButton(),
if (widget.editMessage == null &&
if (widget.showCommandsButton &&
widget.editMessage == null &&
StreamChannel.of(context)
.channel
?.config
@@ -468,6 +479,7 @@ class MessageInputState extends State<MessageInput> {
?.isNotEmpty ==
true)
_buildCommandButton(),
...widget.actions ?? [],
].insertBetween(const SizedBox(width: 8)),
),
),
@@ -565,51 +577,75 @@ class MessageInputState extends State<MessageInput> {
),
),
contentPadding: const EdgeInsets.fromLTRB(16, 12, 13, 11),
prefixIconConstraints: BoxConstraints.tight(Size(78, 24)),
suffixIconConstraints: BoxConstraints.tight(Size(40, 40)),
prefixIcon: _commandEnabled
? Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: theme.colorTheme.accentBlue,
),
margin: const EdgeInsets.only(right: 4, left: 8),
alignment: Alignment.center,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
StreamSvgIcon.lightning(
color: Colors.white,
size: 16.0,
),
Text(
_chosenCommand?.name?.toUpperCase() ?? '',
style: StreamChatTheme.of(context)
.textTheme
.footnoteBold
.copyWith(
? Row(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
constraints: BoxConstraints.tight(Size(64, 24)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: theme.colorTheme.accentBlue,
),
alignment: Alignment.center,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
StreamSvgIcon.lightning(
color: Colors.white,
size: 16.0,
),
Text(
_chosenCommand?.name?.toUpperCase() ?? '',
style: StreamChatTheme.of(context)
.textTheme
.footnoteBold
.copyWith(
color: Colors.white,
),
),
],
),
),
],
),
),
],
)
: null,
: (widget.actionsLocation == ActionsLocation.leftInside
? Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_buildExpandActionsButton(),
],
)
: null),
suffixIconConstraints: BoxConstraints.tightFor(height: 40),
prefixIconConstraints: BoxConstraints.tightFor(height: 40),
suffixIcon: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (_commandEnabled)
IconButton(
icon: StreamSvgIcon.closeSmall(),
splashRadius: 24,
padding: const EdgeInsets.all(0),
constraints: BoxConstraints.tightFor(
height: 24,
width: 24,
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: IconButton(
icon: StreamSvgIcon.closeSmall(),
splashRadius: 24,
padding: const EdgeInsets.all(0),
constraints: BoxConstraints.tightFor(
height: 24,
width: 24,
),
onPressed: () {
setState(() => _commandEnabled = false);
},
),
onPressed: () {
setState(() => _commandEnabled = false);
},
),
if (!_commandEnabled &&
widget.actionsLocation == ActionsLocation.rightInside)
_buildExpandActionsButton(),
if (widget.sendButtonLocation == SendButtonLocation.inside)
_animateSendButton(context),
],
@@ -619,7 +655,13 @@ class MessageInputState extends State<MessageInput> {
Timer _debounce;
String _previousValue;
void _onChanged(BuildContext context, String s) {
if (s == _previousValue) {
return;
}
_previousValue = s;
if (_debounce?.isActive == true) _debounce.cancel();
_debounce = Timer(
const Duration(milliseconds: 350),
@@ -631,7 +673,11 @@ class MessageInputState extends State<MessageInput> {
setState(() {
_messageIsPresent = s.trim().isNotEmpty;
_actionsShrunk = s.trim().isNotEmpty;
_actionsShrunk = s.trim().isNotEmpty &&
((widget.actions?.length ?? 0) +
(widget.showCommandsButton ? 1 : 0) +
(widget.disableAttachments ? 0 : 1) >
1);
});
_commandsOverlay?.remove();
@@ -1684,13 +1730,19 @@ class MessageInputState extends State<MessageInput> {
}
Widget _buildCommandButton() {
final s = textEditingController.text.trim();
return IconButton(
icon: StreamSvgIcon.lightning(
color: _commandsOverlay != null
? StreamChatTheme.of(context).messageInputTheme.actionButtonColor
: StreamChatTheme.of(context)
.messageInputTheme
.actionButtonIdleColor,
color: s.isNotEmpty
? StreamChatTheme.of(context).colorTheme.greyGainsboro
: (_commandsOverlay != null
? StreamChatTheme.of(context)
.messageInputTheme
.actionButtonColor
: StreamChatTheme.of(context)
.messageInputTheme
.actionButtonIdleColor),
),
padding: const EdgeInsets.all(0),
constraints: BoxConstraints.tightFor(
@@ -1711,7 +1763,9 @@ class MessageInputState extends State<MessageInput> {
if (_commandsOverlay == null) {
setState(() {
_commandsOverlay = _buildCommandsOverlayEntry();
Overlay.of(context).insert(_commandsOverlay);
if (_commandsOverlay != null) {
Overlay.of(context).insert(_commandsOverlay);
}
});
} else {
setState(() {
@@ -1965,24 +2019,31 @@ class MessageInputState extends State<MessageInput> {
}
Widget _buildIdleSendButton(BuildContext context) {
return StreamSvgIcon(
assetName: _getIdleSendIcon(),
color: StreamChatTheme.of(context).messageInputTheme.sendButtonIdleColor,
return Padding(
padding: const EdgeInsets.all(8.0),
child: StreamSvgIcon(
assetName: _getIdleSendIcon(),
color:
StreamChatTheme.of(context).messageInputTheme.sendButtonIdleColor,
),
);
}
Widget _buildSendButton(BuildContext context) {
return IconButton(
onPressed: sendMessage,
padding: const EdgeInsets.all(0),
splashRadius: 24,
constraints: BoxConstraints.tightFor(
height: 24,
width: 24,
),
icon: StreamSvgIcon(
assetName: _getSendIcon(),
color: StreamChatTheme.of(context).messageInputTheme.sendButtonColor,
return Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: sendMessage,
padding: const EdgeInsets.all(0),
splashRadius: 24,
constraints: BoxConstraints.tightFor(
height: 24,
width: 24,
),
icon: StreamSvgIcon(
assetName: _getSendIcon(),
color: StreamChatTheme.of(context).messageInputTheme.sendButtonColor,
),
),
);
}