Merge branch 'feature/new-ui' into feat/two-way-pagination

This commit is contained in:
Salvatore Giordano
2020-12-08 16:21:19 +01:00
9 changed files with 715 additions and 215 deletions
+6 -6
View File
@@ -13,41 +13,41 @@ import 'routes/routes.dart';
const kStreamApiKey = 'STREAM_API_KEY';
const kStreamUserId = 'STREAM_USER_ID';
const kStreamToken = 'STREAM_TOKEN';
const kDefaultStreamApiKey = 's2dxdhpxd94g';
const kDefaultStreamApiKey = 'uj7qrdbfrzvg';
class ChooseUserPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final users = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidmlzaGFsIn0._JHWzo92fpTWZMZriJHXqOng6ShYVmWrdaIaPwEPKBg':
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidmlzaGFsIn0.lCz-idDgaZ-xszjnuB_hTfeIOhTFmJtTB2fEjhwrcCI':
User(
id: 'vishal',
extraData: {
'name': 'Vishal',
},
),
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A':
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.1AvvK2TvEsfcxAlfOK2iUMFACucnk6N-Q8f5bbfnjCM':
User(
id: 'super-band-9',
extraData: {
'name': 'John Doe',
},
),
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.GMEKyEhONmFnqtkf1TR1A3oUOSIWhjfQv5RpI906dAM':
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.uQ-pz8e1_C-Df2rIFpkkvWf7g4M0aW2Zkr7pHVhmU1Y':
User(
id: 'salvatore',
extraData: {
'name': 'Salvatore',
},
),
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GTalMeZHaBdpIM5w-KWrVIDSy-ODkHTRkf1GZbWAveM':
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.feLvMytd5_3-eETKrRdwtO3jcA0HxD8woFUbFU7gQCg':
User(
id: 'tommaso',
extraData: {
'name': 'Tommaso',
},
),
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiamFhcCJ9.xpGE2lu4OoYS7-2yy6PbF0gJnxOaxeGO4EU6xo4EdMU':
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiamFhcCJ9.VLkLs6KH-jRRkPvhYMa4_lqN0R6WiK7JhJVmYvxcKz0':
User(
id: 'jaap',
extraData: {
+1 -1
View File
@@ -1,6 +1,6 @@
name: example
description: A new Flutter project.
version: 1.0.87+89
version: 1.0.88+90
environment:
sdk: ">=2.2.2 <3.0.0"
+156 -10
View File
@@ -1,32 +1,178 @@
import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
import 'package:stream_chat_flutter/src/utils.dart';
class FileAttachment extends StatelessWidget {
final Attachment attachment;
final Size size;
final Widget trailing;
const FileAttachment({
Key key,
@required this.attachment,
this.size,
this.trailing,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
child: InkWell(
onTap: () {
launchURL(context, attachment.assetUrl);
},
child: Container(
width: size?.width ?? 100,
height: size?.height ?? 100,
child: Center(
child: Icon(Icons.attach_file),
),
child: Container(
width: size?.width ?? 100,
height: 56.0,
margin: trailing != null ? EdgeInsets.only(top: 4.0) : null,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: trailing != null ? BorderRadius.circular(16.0) : null,
border: trailing != null
? Border.fromBorderSide(BorderSide(color: Color(0xFFE6E6E6)))
: null,
),
child: Row(
children: [
Container(
child: _getFileTypeImage(attachment.extraData['mime_type']),
height: 40.0,
width: 33.33,
margin: EdgeInsets.all(8.0),
),
SizedBox(
width: 6.0,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
attachment?.title ?? 'File',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(
height: 3.0,
),
Text(
'${attachment.extraData['file_size'] ?? 'N/A'} bytes',
style: TextStyle(
color: Colors.black.withOpacity(0.5),
fontSize: 14.0,
),
),
],
),
),
Column(
children: [
trailing ??
IconButton(
icon: StreamSvgIcon.cloud_download(
color: Colors.black,
),
onPressed: () {
launchURL(context, attachment.assetUrl);
},
),
],
),
],
),
// ListTile(
// dense: true,
// leading: Container(
// child: _getFileTypeImage(attachment.extraData['mime_type']),
// height: 40.0,
// width: 33.33,
// ),
// title: Text(
// attachment?.title ?? 'File',
// style: TextStyle(
// fontWeight: FontWeight.bold,
// ),
// maxLines: 3,
// ),
// subtitle: Text(
// '${attachment.extraData['file_size'] ?? 'N/A'} bytes',
// style: TextStyle(
// color: Colors.black.withOpacity(0.5),
// ),
// ),
// trailing: trailing ??
// IconButton(
// icon: StreamSvgIcon.cloud_download(
// color: Colors.black,
// ),
// onPressed: () {
// launchURL(context, attachment.assetUrl);
// },
// ),
// ),
),
);
}
StreamSvgIcon _getFileTypeImage(String type) {
switch (type) {
case '7z':
return StreamSvgIcon.filetype_7z();
break;
case 'csv':
return StreamSvgIcon.filetype_csv();
break;
case 'doc':
return StreamSvgIcon.filetype_doc();
break;
case 'docx':
return StreamSvgIcon.filetype_docx();
break;
case 'html':
return StreamSvgIcon.filetype_html();
break;
case 'md':
return StreamSvgIcon.filetype_md();
break;
case 'odt':
return StreamSvgIcon.filetype_odt();
break;
case 'pdf':
return StreamSvgIcon.filetype_pdf();
break;
case 'ppt':
return StreamSvgIcon.filetype_ppt();
break;
case 'pptx':
return StreamSvgIcon.filetype_pptx();
break;
case 'rar':
return StreamSvgIcon.filetype_rar();
break;
case 'rtf':
return StreamSvgIcon.filetype_rtf();
break;
case 'tar':
return StreamSvgIcon.filetype_tar();
break;
case 'txt':
return StreamSvgIcon.filetype_txt();
break;
case 'xls':
return StreamSvgIcon.filetype_xls();
break;
case 'xlsx':
return StreamSvgIcon.filetype_xlsx();
break;
case 'zip':
return StreamSvgIcon.filetype_zip();
break;
default:
return StreamSvgIcon.filetype_Generic();
break;
}
}
}
+39 -36
View File
@@ -79,57 +79,60 @@ class GiphyAttachment extends StatelessWidget {
);
}));
},
child: CachedNetworkImage(
height: size?.height,
width: size?.width,
placeholder: (_, __) {
return Container(
width: size?.width,
height: size?.height,
child: Center(
child: CircularProgressIndicator(),
),
);
},
imageUrl: attachment.thumbUrl ??
attachment.imageUrl ??
attachment.assetUrl,
errorWidget: (context, url, error) => AttachmentError(
attachment: attachment,
size: size,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
),
child: CachedNetworkImage(
height: size?.height,
width: size?.width,
placeholder: (_, __) {
return Container(
width: size?.width,
height: size?.height,
child: Center(
child: CircularProgressIndicator(),
),
);
},
imageUrl: attachment.thumbUrl ??
attachment.imageUrl ??
attachment.assetUrl,
errorWidget: (context, url, error) => AttachmentError(
attachment: attachment,
size: size,
),
fit: BoxFit.cover,
),
fit: BoxFit.cover,
),
),
),
Positioned(
left: 0,
top: 0,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(16.0),
)),
bottom: 16,
left: 16,
child: Material(
color: Colors.black.withOpacity(.5),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 8.0,
bottom: 4.0,
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 4.0,
),
child: Row(
children: [
StreamSvgIcon.lightning(
color: StreamChatTheme.of(context).accentColor,
size: 16.0,
color: Colors.white,
size: 16,
),
Text(
'GIPHY',
style: TextStyle(
color: StreamChatTheme.of(context).accentColor,
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 11.0,
fontSize: 11,
),
),
],
+1
View File
@@ -220,6 +220,7 @@ class _ImageFooterState extends State<ImageFooter> {
widget.mediaSelectedCallBack(position);
},
child: FittedBox(
fit: BoxFit.cover,
child: Chewie(
controller: controllerPackage.chewieController,
),
+180 -80
View File
@@ -658,6 +658,34 @@ class MessageInputState extends State<MessageInput> {
}
Widget _buildFilePickerSection() {
var _attachmentContainsFile =
_attachments.any((element) => element?.attachment?.type == 'file');
Color _getIconColor(int index) {
switch (index) {
case 0:
return _attachmentContainsFile && _attachments.isNotEmpty
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.5);
break;
case 1:
return !_attachmentContainsFile && _attachments.isNotEmpty
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.5);
break;
case 2:
return _attachmentContainsFile && _attachments.isNotEmpty
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.5);
break;
case 3:
return _attachmentContainsFile && _attachments.isNotEmpty
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.5);
break;
}
}
return AnimatedContainer(
duration: _animateContainer ? Duration(milliseconds: 300) : Duration.zero,
height: _openFilePickerSection ? _filePickerSize : 0,
@@ -671,49 +699,49 @@ class MessageInputState extends State<MessageInput> {
IconButton(
iconSize: 24,
icon: StreamSvgIcon.pictures(
color: _filePickerIndex == 0
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
color: _getIconColor(0),
),
onPressed: () {
setState(() {
_filePickerIndex = 0;
});
},
onPressed: _attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
setState(() {
_filePickerIndex = 0;
});
},
),
IconButton(
iconSize: 32,
icon: StreamSvgIcon.files(
color: _filePickerIndex == 1
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
color: _getIconColor(1),
),
onPressed: () {
pickFile(DefaultAttachmentTypes.file, false);
},
onPressed: !_attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.file, false);
},
),
IconButton(
iconSize: 24,
icon: StreamSvgIcon.camera(
color: _filePickerIndex == 2
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
color: _getIconColor(2),
),
onPressed: () {
pickFile(DefaultAttachmentTypes.image, true);
},
onPressed: _attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.image, true);
},
),
IconButton(
padding: const EdgeInsets.all(0),
iconSize: 24,
icon: StreamSvgIcon.record(
color: _filePickerIndex == 3
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
color: _getIconColor(3),
),
onPressed: () {
pickFile(DefaultAttachmentTypes.video, true);
},
onPressed: _attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.video, true);
},
),
],
),
@@ -770,6 +798,9 @@ class MessageInputState extends State<MessageInput> {
}
Widget _buildPickerSection() {
var _attachmentContainsFile =
_attachments.any((element) => element.attachment.type == 'file');
switch (_filePickerIndex) {
case 0:
return FutureBuilder<bool>(
@@ -782,19 +813,22 @@ class MessageInputState extends State<MessageInput> {
}
if (snapshot.data) {
return MediaListView(
selectedIds: _attachments.map((e) => e.id).toList(),
onSelect: (media) async {
if (!_attachments
.any((element) => element.id == media.id)) {
_addAttachment(media);
} else {
setState(() {
_attachments
.removeWhere((element) => element.id == media.id);
});
}
},
return IgnorePointer(
ignoring: _attachmentContainsFile,
child: MediaListView(
selectedIds: _attachments.map((e) => e.id).toList(),
onSelect: (media) async {
if (!_attachments
.any((element) => element.id == media.id)) {
_addAttachment(media);
} else {
setState(() {
_attachments
.removeWhere((element) => element.id == media.id);
});
}
},
),
);
}
@@ -850,7 +884,7 @@ class MessageInputState extends State<MessageInput> {
);
if (file.size > _kMaxAttachmentSize) {
if (medium.type == AssetType.video) {
if (medium?.type == AssetType.video) {
final mediaInfo = await CompressVideoService.compressVideo(file.path);
if (mediaInfo.filesize / (1024 * 1024) > _kMaxAttachmentSize) {
@@ -890,7 +924,7 @@ class MessageInputState extends State<MessageInput> {
..file = file
..attachment = Attachment(
localUri: file.path != null ? Uri.parse(file.path) : null,
type: medium.type == AssetType.image ? 'image' : 'video',
type: medium?.type == AssetType.image ? 'image' : 'video',
);
});
@@ -1053,7 +1087,7 @@ class MessageInputState extends State<MessageInput> {
offset: rejoin.length,
),
);
_debounce.cancel();
_mentionsOverlay?.remove();
_mentionsOverlay = null;
},
@@ -1201,44 +1235,98 @@ class MessageInputState extends State<MessageInput> {
Widget _buildAttachments() {
return _attachments.isEmpty
? Container()
: LimitedBox(
maxHeight: 104.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: _attachments
.map(
(attachment) => Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Stack(
children: <Widget>[
AspectRatio(
aspectRatio: 1.0,
child: Container(
height: 104,
width: 104,
child: _buildAttachment(attachment),
),
),
_buildRemoveButton(attachment),
attachment.uploaded
? SizedBox()
: Positioned.fill(
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: CircularProgressIndicator(),
: Column(
children: [
if (_attachments.any((e) => e.attachment?.type == 'file'))
LimitedBox(
maxHeight: 73.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: _attachments
.where((e) => e.attachment?.type == 'file')
.map(
(e) => Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAlias,
child: FileAttachment(
attachment: e.attachment,
size: Size(
MediaQuery.of(context).size.width * 0.55,
MediaQuery.of(context).size.height * 0.3,
),
trailing: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
child: CircleAvatar(
backgroundColor:
Colors.black.withOpacity(0.2),
maxRadius: 12.0,
child: StreamSvgIcon.close(
color: Colors.white,
),
),
onTap: () {
setState(() {
_attachments.remove(e);
});
},
),
],
),
),
),
)
.toList(),
),
),
),
),
),
)
.toList(),
),
),
if (_attachments.any((e) => e.attachment?.type != 'file'))
LimitedBox(
maxHeight: 104.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: _attachments
.where((e) => e.attachment?.type != 'file')
.map(
(attachment) => Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
AspectRatio(
aspectRatio: 1.0,
child: Container(
height: 104,
width: 104,
child: _buildAttachment(attachment),
),
),
_buildRemoveButton(attachment),
attachment.uploaded
? SizedBox()
: Positioned.fill(
child: Center(
child: Padding(
padding:
const EdgeInsets.all(16.0),
child:
CircularProgressIndicator(),
),
),
),
],
),
),
),
)
.toList(),
),
),
],
);
}
@@ -1275,9 +1363,9 @@ class MessageInputState extends State<MessageInput> {
Widget _buildAttachment(_SendingAttachment attachment) {
if (widget.attachmentThumbnailBuilders
?.containsKey(attachment.attachment.type) ==
?.containsKey(attachment.attachment?.type) ==
true) {
return widget.attachmentThumbnailBuilders[attachment.attachment.type](
return widget.attachmentThumbnailBuilders[attachment.attachment?.type](
context,
attachment,
);
@@ -1287,7 +1375,7 @@ class MessageInputState extends State<MessageInput> {
return SizedBox();
}
switch (attachment.attachment.type) {
switch (attachment.attachment?.type) {
case 'image':
case 'giphy':
return attachment.file != null
@@ -1562,12 +1650,24 @@ class MessageInputState extends State<MessageInput> {
attachmentType = mimeType.type;
}
Map<String, dynamic> extraDataMap = {};
if (mimeType?.subtype != null) {
extraDataMap['mime_type'] = mimeType.subtype.toLowerCase();
}
if (file.size != null) {
extraDataMap['file_size'] = file.size;
}
final channel = StreamChannel.of(context).channel;
final attachment = _SendingAttachment(
file: file,
attachment: Attachment(
localUri: file.path != null ? Uri.parse(file.path) : null,
type: attachmentType,
extraData: extraDataMap.isNotEmpty ? extraDataMap : null,
title: file.name ?? 'File',
),
);
+6 -1
View File
@@ -637,7 +637,12 @@ class _MessageListViewState extends State<MessageListView> {
showDeleteMessage: isMyMessage,
borderSide: isMyMessage ? BorderSide.none : null,
onThreadTap: _onThreadTap,
attachmentBorderRadiusGeometry: BorderRadius.circular(16),
attachmentBorderRadiusGeometry: BorderRadius.only(
topLeft: Radius.circular(16),
bottomLeft: Radius.circular(!isNextUser ? 0 : 16),
topRight: Radius.circular(16),
bottomRight: Radius.circular(16),
),
attachmentPadding: const EdgeInsets.all(2),
borderRadiusGeometry: BorderRadius.only(
topLeft: Radius.circular(16),
+86 -81
View File
@@ -186,9 +186,7 @@ class MessageWidget extends StatefulWidget {
'giphy': (context, message, attachment) {
return GiphyAttachment(
attachment: attachment,
messageTheme: messageTheme.copyWith(
messageBackgroundColor: Colors.white,
),
messageTheme: messageTheme,
message: message,
size: Size(
MediaQuery.of(context).size.width * 0.8,
@@ -219,8 +217,8 @@ class _MessageWidgetState extends State<MessageWidget> {
? widget.messageTheme.avatarTheme.constraints.maxWidth + 16.0
: 6.0;
final isGiphy =
widget.message.attachments?.any((element) => element.type == 'giphy') ==
final hasFiles =
widget.message.attachments?.any((element) => element.type == 'file') ==
true;
return Portal(
@@ -295,18 +293,46 @@ class _MessageWidgetState extends State<MessageWidget> {
messageTheme: widget.messageTheme,
),
)
: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
..._parseAttachments(context),
if (widget.message.text
.trim()
.isNotEmpty &&
!isGiphy)
_buildTextBubble(context),
],
: Material(
clipBehavior: Clip.antiAlias,
shape: widget.shape ??
RoundedRectangleBorder(
side: isOnlyEmoji
? BorderSide.none
: widget.borderSide ??
BorderSide(
color: Theme.of(context)
.brightness ==
Brightness
.dark
? Colors.white
.withAlpha(24)
: Colors.black
.withAlpha(
24),
),
borderRadius: widget
.borderRadiusGeometry ??
BorderRadius.zero,
),
color: _getBackgroundColor(),
child: Padding(
padding: EdgeInsets.all(
hasFiles ? 2.0 : 0.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
..._parseAttachments(context),
if (widget.message.text
.trim()
.isNotEmpty &&
!isGiphy)
_buildTextBubble(context),
],
),
),
),
),
if (widget.showReactionPickerIndicator)
@@ -449,6 +475,10 @@ class _MessageWidgetState extends State<MessageWidget> {
);
}
bool get isGiphy =>
widget.message.attachments?.any((element) => element.type == 'giphy') ==
true;
Widget _buildReadIndicator() {
var padding = 0.0;
return Stack(
@@ -629,46 +659,39 @@ class _MessageWidgetState extends State<MessageWidget> {
[];
}
Padding wrapAttachmentWidget(
Widget wrapAttachmentWidget(
BuildContext context,
Widget attachmentWidget, {
Attachment attachment,
}) {
final attachmentShape =
widget.attachmentShape ?? widget.shape ?? _getDefaultShape(context);
return Padding(
padding: EdgeInsets.only(
bottom: 4,
),
child: GestureDetector(
onTap: () => retryMessage(context),
onLongPress: () => onLongPress(context),
child: Material(
color: attachment?.type == 'giphy'
? Colors.white
: _getBackgroundColor(),
clipBehavior: Clip.hardEdge,
shape: attachmentShape,
child: Padding(
padding: widget.attachmentPadding,
child: Material(
clipBehavior: Clip.hardEdge,
shape: attachmentShape,
type: MaterialType.transparency,
child: Transform(
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
getFailedMessageWidget(
context,
padding: const EdgeInsets.all(8.0),
),
attachmentWidget,
],
),
return GestureDetector(
onTap: () => retryMessage(context),
onLongPress: () => onLongPress(context),
child: Material(
color: _getBackgroundColor(),
clipBehavior: Clip.antiAlias,
shape: attachmentShape,
child: Padding(
padding: widget.attachmentPadding,
child: Material(
clipBehavior: Clip.hardEdge,
shape: attachmentShape,
type: MaterialType.transparency,
child: Transform(
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
getFailedMessageWidget(
context,
padding: const EdgeInsets.all(8.0),
),
attachmentWidget,
],
),
),
),
@@ -798,30 +821,7 @@ class _MessageWidgetState extends State<MessageWidget> {
return SizedBox();
}
Widget _wrapTextInBubble({
BuildContext context,
Widget child,
}) {
return Material(
shape: widget.shape ??
RoundedRectangleBorder(
side: widget.borderSide ??
BorderSide(
color: Theme.of(context).brightness == Brightness.dark
? Colors.white.withAlpha(24)
: Colors.black.withAlpha(24),
),
borderRadius: widget.borderRadiusGeometry ?? BorderRadius.zero,
),
color: _getBackgroundColor(),
child: child,
);
}
Widget _buildTextBubble(BuildContext context) {
final isOnlyEmoji =
widget.message.text.characters.every((c) => Emoji.byChar(c) != null);
Widget child = Transform(
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center,
@@ -858,13 +858,6 @@ class _MessageWidgetState extends State<MessageWidget> {
],
),
);
if (!isOnlyEmoji) {
child = _wrapTextInBubble(
context: context,
child: child,
);
}
return GestureDetector(
onTap: () => retryMessage(context),
onLongPress: () => onLongPress(context),
@@ -872,6 +865,10 @@ class _MessageWidgetState extends State<MessageWidget> {
);
}
bool get isOnlyEmoji =>
widget.message.text.characters.isNotEmpty &&
widget.message.text.characters.every((c) => Emoji.byChar(c) != null);
Color _getBackgroundColor() {
if ((widget.message.status == MessageSendingStatus.FAILED ||
widget.message.status == MessageSendingStatus.FAILED_UPDATE ||
@@ -885,6 +882,14 @@ class _MessageWidgetState extends State<MessageWidget> {
return Color(0xFFE9F2FF);
}
if (isOnlyEmoji) {
return Colors.transparent;
}
if (isGiphy) {
return Colors.transparent;
}
return widget.messageTheme.messageBackgroundColor;
}
+240
View File
@@ -338,6 +338,30 @@ class StreamSvgIcon extends StatelessWidget {
);
}
factory StreamSvgIcon.download({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'Icon_download.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.cloud_download({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'Icon_cloud_download.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.copy({
double size,
Color color,
@@ -481,4 +505,220 @@ class StreamSvgIcon extends StatelessWidget {
height: size,
);
}
factory StreamSvgIcon.filetype_7z({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_7z.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_csv({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_CSV.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_doc({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_DOC.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_docx({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_DOCX.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_Generic({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_Generic.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_html({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_html.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_md({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_MD.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_odt({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_ODT.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_pdf({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_PDF.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_ppt({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_PPT.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_pptx({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_PPTX.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_rar({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_RAR.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_rtf({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_RTF.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_tar({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_TAR.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_txt({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_TXT.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_xls({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_XLS.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_xlsx({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_XLSX.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.filetype_zip({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'filetype_ZIP.svg',
color: color,
width: size,
height: size,
);
}
}