您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
272 行
11 KiB
272 行
11 KiB
using System.Collections.Generic;
|
|
using ChatComponents;
|
|
using uiwidgets;
|
|
using Unity.UIWidgets.animation;
|
|
using Unity.UIWidgets.foundation;
|
|
using Unity.UIWidgets.material;
|
|
using Unity.UIWidgets.painting;
|
|
using Unity.UIWidgets.rendering;
|
|
using Unity.UIWidgets.ui;
|
|
using Unity.UIWidgets.widgets;
|
|
using Image = Unity.UIWidgets.widgets.Image;
|
|
|
|
namespace UIWidgetsSample
|
|
{
|
|
internal class Message : StatelessWidget
|
|
{
|
|
/// Build a custom message inside predefined bubble
|
|
public readonly BuildCustomMessage buildCustomMessage;
|
|
|
|
|
|
/// Any message type
|
|
public readonly ChatComponents.Message message;
|
|
|
|
/// Maximum message width
|
|
public readonly int messageWidth;
|
|
|
|
/// Called when user makes a long press on any message
|
|
public readonly OnMessageLongPress onMessageLongPress;
|
|
|
|
/// Called when user taps on any message
|
|
public readonly OnMessageTap onMessageTap;
|
|
|
|
/// See [TextMessage.onPreviewDataFetched]
|
|
public readonly OnPreviewDataFetched onPreviewDataFetched;
|
|
|
|
/// Rounds border of the message to visually group messages together.
|
|
public readonly bool roundBorder;
|
|
|
|
/// Show user avatar for the received message. Useful for a group chat.
|
|
public readonly bool showAvatar;
|
|
|
|
/// See [TextMessage.showName]
|
|
public readonly bool showName;
|
|
|
|
/// Show message's status
|
|
public readonly bool showStatus;
|
|
|
|
/// Show user avatars for received messages. Useful for a group chat.
|
|
public readonly bool showUserAvatars;
|
|
|
|
/// See [TextMessage.usePreviewData]
|
|
public readonly bool usePreviewData;
|
|
|
|
/// Creates a particular message from any message type
|
|
public Message(
|
|
ChatComponents.Message message,
|
|
int messageWidth,
|
|
bool roundBorder,
|
|
bool showAvatar,
|
|
bool showName,
|
|
bool showStatus,
|
|
bool showUserAvatars,
|
|
bool usePreviewData,
|
|
Key key = null,
|
|
OnMessageLongPress onMessageLongPress = null,
|
|
OnMessageTap onMessageTap = null,
|
|
OnPreviewDataFetched onPreviewDataFetched = null,
|
|
BuildCustomMessage buildCustomMessage = null
|
|
) : base(key)
|
|
{
|
|
this.message = message;
|
|
this.messageWidth = messageWidth;
|
|
this.buildCustomMessage = buildCustomMessage;
|
|
this.onMessageTap = onMessageTap;
|
|
this.onMessageLongPress = onMessageLongPress;
|
|
this.onPreviewDataFetched = onPreviewDataFetched;
|
|
this.roundBorder = roundBorder;
|
|
this.showAvatar = showAvatar;
|
|
this.showName = showName;
|
|
this.showStatus = showStatus;
|
|
this.showUserAvatars = showUserAvatars;
|
|
this.usePreviewData = usePreviewData;
|
|
}
|
|
|
|
private Widget _buildAvatar(BuildContext context)
|
|
{
|
|
var color = ChatUtils.getUserAvatarNameColor(message.author,
|
|
InheritedChatTheme.of(context).theme.userAvatarNameColors);
|
|
var hasImage = message.author.imageUrl != null;
|
|
string name = ChatUtils.getUserName(message.author);
|
|
|
|
return showAvatar
|
|
? new Container(
|
|
margin: EdgeInsets.only(right: 8),
|
|
child: new CircleAvatar(
|
|
backgroundImage:
|
|
hasImage ? new NetworkImage(message.author.imageUrl == null ? "" : (string)message.author.imageUrl) : null,
|
|
backgroundColor: color,
|
|
radius: 16,
|
|
child: !hasImage
|
|
? new Text(
|
|
name.isEmpty() ? "" : name[0].ToString().ToUpper(),
|
|
style: InheritedChatTheme.of(context).theme.userAvatarTextStyle
|
|
)
|
|
: null
|
|
)
|
|
)
|
|
: new Container(
|
|
margin: EdgeInsets.only(right: 40)
|
|
);
|
|
}
|
|
|
|
private Widget _buildMessage()
|
|
{
|
|
switch (message.type)
|
|
{
|
|
case MessageType.custom:
|
|
var customMessage = message as CustomMessage;
|
|
return buildCustomMessage != null
|
|
? buildCustomMessage(customMessage)
|
|
: new SizedBox();
|
|
/*case MessageType.file:
|
|
var fileMessage = message as ChatComponents.FileMessage;
|
|
return new FileMessage(
|
|
message: fileMessage
|
|
);
|
|
case MessageType.image:
|
|
var imageMessage = message as ChatComponents.ImageMessage;
|
|
return new ImageMessage(
|
|
message: imageMessage,
|
|
messageWidth: messageWidth
|
|
);*/
|
|
case MessageType.text:
|
|
var textMessage = message as ChatComponents.TextMessage;
|
|
return new TextMessage(
|
|
message: textMessage,
|
|
onPreviewDataFetched: onPreviewDataFetched,
|
|
showName: showName,
|
|
usePreviewData: usePreviewData
|
|
);
|
|
default:
|
|
return new SizedBox();
|
|
}
|
|
}
|
|
|
|
private Widget _buildStatus(BuildContext context)
|
|
{
|
|
switch (message.status)
|
|
{
|
|
case Status.error:
|
|
return InheritedChatTheme.of(context).theme.errorIcon != null
|
|
? InheritedChatTheme.of(context).theme.errorIcon
|
|
: Image.asset(
|
|
"assets/icon-error.png",
|
|
color: InheritedChatTheme.of(context).theme.errorColor,
|
|
package: "flutter_chat_ui"
|
|
);
|
|
case Status.sent:
|
|
case Status.delivered:
|
|
return InheritedChatTheme.of(context).theme.deliveredIcon != null
|
|
? InheritedChatTheme.of(context).theme.deliveredIcon
|
|
: Image.asset(
|
|
"assets/icon-delivered.png",
|
|
color: InheritedChatTheme.of(context).theme.primaryColor,
|
|
package: "flutter_chat_ui"
|
|
);
|
|
case Status.seen:
|
|
return InheritedChatTheme.of(context).theme.seenIcon != null
|
|
? InheritedChatTheme.of(context).theme.seenIcon
|
|
: Image.file(
|
|
"assets/icon-seen.png",
|
|
color: InheritedChatTheme.of(context).theme.primaryColor,
|
|
scale:1
|
|
//package: "flutter_chat_ui"
|
|
);
|
|
|
|
case Status.sending:
|
|
return new Center(
|
|
child: new SizedBox(
|
|
height: 10,
|
|
width: 10,
|
|
child: new CircularProgressIndicator(
|
|
backgroundColor: Colors.transparent,
|
|
strokeWidth: 1.5f,
|
|
valueColor: new AlwaysStoppedAnimation<Color>(
|
|
InheritedChatTheme.of(context).theme.primaryColor
|
|
)
|
|
)
|
|
)
|
|
);
|
|
default:
|
|
return new SizedBox();
|
|
}
|
|
}
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
var _user = InheritedUser.of(context).user;
|
|
var _messageBorderRadius =
|
|
InheritedChatTheme.of(context).theme.messageBorderRadius;
|
|
var _borderRadius = BorderRadius.only(
|
|
bottomLeft: Radius.circular(_user.id == message.author.id || roundBorder
|
|
? _messageBorderRadius
|
|
: 0),
|
|
bottomRight: Radius.circular(_user.id == message.author.id
|
|
? roundBorder
|
|
? _messageBorderRadius
|
|
: 0
|
|
: _messageBorderRadius),
|
|
topLeft: Radius.circular(_messageBorderRadius),
|
|
topRight: Radius.circular(_messageBorderRadius)
|
|
);
|
|
var _currentUserIsAuthor = _user.id == message.author.id;
|
|
var results = new List<Widget>();
|
|
if (!_currentUserIsAuthor && showUserAvatars)
|
|
results.Add(_buildAvatar(context));
|
|
results.Add(new ConstrainedBox(
|
|
constraints: new BoxConstraints(
|
|
maxWidth: messageWidth * 1f
|
|
),
|
|
child: new Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: new List<Widget>
|
|
{
|
|
new GestureDetector(
|
|
onLongPress: () => onMessageLongPress?.Invoke(message),
|
|
onTap: () => onMessageTap?.Invoke(message),
|
|
child: new Container(
|
|
decoration: new BoxDecoration(
|
|
borderRadius: _borderRadius,
|
|
color: !_currentUserIsAuthor ||
|
|
message.type == MessageType.image
|
|
? InheritedChatTheme.of(context).theme.secondaryColor
|
|
: InheritedChatTheme.of(context).theme.primaryColor
|
|
),
|
|
child: new ClipRRect(
|
|
borderRadius: _borderRadius,
|
|
child: _buildMessage()
|
|
)
|
|
)
|
|
)
|
|
}
|
|
)
|
|
));
|
|
if (_currentUserIsAuthor)
|
|
results.Add(new Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 4),
|
|
child: new Center(
|
|
child: new SizedBox(
|
|
height: 16,
|
|
width: 16,
|
|
child: showStatus ? _buildStatus(context) : null
|
|
)
|
|
)
|
|
));
|
|
return new Container(
|
|
alignment: _user.id == message.author.id
|
|
? Alignment.centerRight
|
|
: Alignment.centerLeft,
|
|
margin: EdgeInsets.only(
|
|
bottom: 4,
|
|
left: 20
|
|
),
|
|
|
|
child: new Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: results)
|
|
);
|
|
}
|
|
}
|
|
}
|