Merge pull request #159 from GetStream/feature/file-attachment-new

Feature/file attachment new
This commit is contained in:
Salvatore Giordano
2020-12-03 12:46:21 +01:00
committed by GitHub
5 changed files with 663 additions and 164 deletions
+153 -7
View File
@@ -1,32 +1,178 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.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'; import 'package:stream_chat_flutter/src/utils.dart';
class FileAttachment extends StatelessWidget { class FileAttachment extends StatelessWidget {
final Attachment attachment; final Attachment attachment;
final Size size; final Size size;
final Widget trailing;
const FileAttachment({ const FileAttachment({
Key key, Key key,
@required this.attachment, @required this.attachment,
this.size, this.size,
this.trailing,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Material( return Material(
child: InkWell(
onTap: () {
launchURL(context, attachment.assetUrl);
},
child: Container( child: Container(
width: size?.width ?? 100, width: size?.width ?? 100,
height: size?.height ?? 100, height: 56.0,
child: Center( margin: trailing != null ? EdgeInsets.only(top: 4.0) : null,
child: Icon(Icons.attach_file), 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;
}
}
} }
+126 -26
View File
@@ -658,6 +658,34 @@ class MessageInputState extends State<MessageInput> {
} }
Widget _buildFilePickerSection() { 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( return AnimatedContainer(
duration: _animateContainer ? Duration(milliseconds: 300) : Duration.zero, duration: _animateContainer ? Duration(milliseconds: 300) : Duration.zero,
height: _openFilePickerSection ? _filePickerSize : 0, height: _openFilePickerSection ? _filePickerSize : 0,
@@ -671,11 +699,11 @@ class MessageInputState extends State<MessageInput> {
IconButton( IconButton(
iconSize: 24, iconSize: 24,
icon: StreamSvgIcon.pictures( icon: StreamSvgIcon.pictures(
color: _filePickerIndex == 0 color: _getIconColor(0),
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
), ),
onPressed: () { onPressed: _attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
setState(() { setState(() {
_filePickerIndex = 0; _filePickerIndex = 0;
}); });
@@ -684,22 +712,22 @@ class MessageInputState extends State<MessageInput> {
IconButton( IconButton(
iconSize: 32, iconSize: 32,
icon: StreamSvgIcon.files( icon: StreamSvgIcon.files(
color: _filePickerIndex == 1 color: _getIconColor(1),
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
), ),
onPressed: () { onPressed: !_attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.file, false); pickFile(DefaultAttachmentTypes.file, false);
}, },
), ),
IconButton( IconButton(
iconSize: 24, iconSize: 24,
icon: StreamSvgIcon.camera( icon: StreamSvgIcon.camera(
color: _filePickerIndex == 2 color: _getIconColor(2),
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
), ),
onPressed: () { onPressed: _attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.image, true); pickFile(DefaultAttachmentTypes.image, true);
}, },
), ),
@@ -707,11 +735,11 @@ class MessageInputState extends State<MessageInput> {
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
iconSize: 24, iconSize: 24,
icon: StreamSvgIcon.record( icon: StreamSvgIcon.record(
color: _filePickerIndex == 3 color: _getIconColor(3),
? StreamChatTheme.of(context).accentColor
: Colors.black.withOpacity(0.5),
), ),
onPressed: () { onPressed: _attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.video, true); pickFile(DefaultAttachmentTypes.video, true);
}, },
), ),
@@ -770,6 +798,9 @@ class MessageInputState extends State<MessageInput> {
} }
Widget _buildPickerSection() { Widget _buildPickerSection() {
var _attachmentContainsFile =
_attachments.any((element) => element.attachment.type == 'file');
switch (_filePickerIndex) { switch (_filePickerIndex) {
case 0: case 0:
return FutureBuilder<bool>( return FutureBuilder<bool>(
@@ -782,7 +813,9 @@ class MessageInputState extends State<MessageInput> {
} }
if (snapshot.data) { if (snapshot.data) {
return MediaListView( return IgnorePointer(
ignoring: _attachmentContainsFile,
child: MediaListView(
selectedIds: _attachments.map((e) => e.id).toList(), selectedIds: _attachments.map((e) => e.id).toList(),
onSelect: (media) async { onSelect: (media) async {
if (!_attachments if (!_attachments
@@ -795,6 +828,7 @@ class MessageInputState extends State<MessageInput> {
}); });
} }
}, },
),
); );
} }
@@ -850,7 +884,7 @@ class MessageInputState extends State<MessageInput> {
); );
if (file.size > _kMaxAttachmentSize) { if (file.size > _kMaxAttachmentSize) {
if (medium.type == AssetType.video) { if (medium?.type == AssetType.video) {
final mediaInfo = await CompressVideoService.compressVideo(file.path); final mediaInfo = await CompressVideoService.compressVideo(file.path);
if (mediaInfo.filesize / (1024 * 1024) > _kMaxAttachmentSize) { if (mediaInfo.filesize / (1024 * 1024) > _kMaxAttachmentSize) {
@@ -890,7 +924,7 @@ class MessageInputState extends State<MessageInput> {
..file = file ..file = file
..attachment = Attachment( ..attachment = Attachment(
localUri: file.path != null ? Uri.parse(file.path) : null, 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, offset: rejoin.length,
), ),
); );
_debounce.cancel();
_mentionsOverlay?.remove(); _mentionsOverlay?.remove();
_mentionsOverlay = null; _mentionsOverlay = null;
}, },
@@ -1201,16 +1235,66 @@ class MessageInputState extends State<MessageInput> {
Widget _buildAttachments() { Widget _buildAttachments() {
return _attachments.isEmpty return _attachments.isEmpty
? Container() ? Container()
: LimitedBox( : 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(),
),
),
if (_attachments.any((e) => e.attachment?.type != 'file'))
LimitedBox(
maxHeight: 104.0, maxHeight: 104.0,
child: ListView( child: ListView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
children: _attachments children: _attachments
.where((e) => e.attachment?.type != 'file')
.map( .map(
(attachment) => Padding( (attachment) => Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAlias,
child: Stack( child: Stack(
children: <Widget>[ children: <Widget>[
AspectRatio( AspectRatio(
@@ -1227,8 +1311,10 @@ class MessageInputState extends State<MessageInput> {
: Positioned.fill( : Positioned.fill(
child: Center( child: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding:
child: CircularProgressIndicator(), const EdgeInsets.all(16.0),
child:
CircularProgressIndicator(),
), ),
), ),
), ),
@@ -1239,6 +1325,8 @@ class MessageInputState extends State<MessageInput> {
) )
.toList(), .toList(),
), ),
),
],
); );
} }
@@ -1275,9 +1363,9 @@ class MessageInputState extends State<MessageInput> {
Widget _buildAttachment(_SendingAttachment attachment) { Widget _buildAttachment(_SendingAttachment attachment) {
if (widget.attachmentThumbnailBuilders if (widget.attachmentThumbnailBuilders
?.containsKey(attachment.attachment.type) == ?.containsKey(attachment.attachment?.type) ==
true) { true) {
return widget.attachmentThumbnailBuilders[attachment.attachment.type]( return widget.attachmentThumbnailBuilders[attachment.attachment?.type](
context, context,
attachment, attachment,
); );
@@ -1287,7 +1375,7 @@ class MessageInputState extends State<MessageInput> {
return SizedBox(); return SizedBox();
} }
switch (attachment.attachment.type) { switch (attachment.attachment?.type) {
case 'image': case 'image':
case 'giphy': case 'giphy':
return attachment.file != null return attachment.file != null
@@ -1562,12 +1650,24 @@ class MessageInputState extends State<MessageInput> {
attachmentType = mimeType.type; 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 channel = StreamChannel.of(context).channel;
final attachment = _SendingAttachment( final attachment = _SendingAttachment(
file: file, file: file,
attachment: Attachment( attachment: Attachment(
localUri: file.path != null ? Uri.parse(file.path) : null, localUri: file.path != null ? Uri.parse(file.path) : null,
type: attachmentType, type: attachmentType,
extraData: extraDataMap.isNotEmpty ? extraDataMap : null,
title: file.name ?? 'File',
), ),
); );
+6 -1
View File
@@ -617,7 +617,12 @@ class _MessageListViewState extends State<MessageListView> {
showDeleteMessage: isMyMessage, showDeleteMessage: isMyMessage,
borderSide: isMyMessage ? BorderSide.none : null, borderSide: isMyMessage ? BorderSide.none : null,
onThreadTap: _onThreadTap, 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), attachmentPadding: const EdgeInsets.all(2),
borderRadiusGeometry: BorderRadius.only( borderRadiusGeometry: BorderRadius.only(
topLeft: Radius.circular(16), topLeft: Radius.circular(16),
+46 -38
View File
@@ -223,6 +223,13 @@ class _MessageWidgetState extends State<MessageWidget> {
widget.message.attachments?.any((element) => element.type == 'giphy') == widget.message.attachments?.any((element) => element.type == 'giphy') ==
true; true;
final isOnlyEmoji =
widget.message.text.characters.every((c) => Emoji.byChar(c) != null);
final hasFiles =
widget.message.attachments?.any((element) => element.type == 'file') ==
true;
return Portal( return Portal(
child: Padding( child: Padding(
padding: widget.padding ?? EdgeInsets.all(8), padding: widget.padding ?? EdgeInsets.all(8),
@@ -295,7 +302,33 @@ class _MessageWidgetState extends State<MessageWidget> {
messageTheme: widget.messageTheme, messageTheme: widget.messageTheme,
), ),
) )
: Column( : 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:
CrossAxisAlignment.start, CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -309,6 +342,8 @@ class _MessageWidgetState extends State<MessageWidget> {
], ],
), ),
), ),
),
),
if (widget.showReactionPickerIndicator) if (widget.showReactionPickerIndicator)
Positioned( Positioned(
right: 0, right: 0,
@@ -629,24 +664,19 @@ class _MessageWidgetState extends State<MessageWidget> {
[]; [];
} }
Padding wrapAttachmentWidget( Widget wrapAttachmentWidget(
BuildContext context, BuildContext context,
Widget attachmentWidget, { Widget attachmentWidget, {
Attachment attachment, Attachment attachment,
}) { }) {
final attachmentShape = final attachmentShape =
widget.attachmentShape ?? widget.shape ?? _getDefaultShape(context); widget.attachmentShape ?? widget.shape ?? _getDefaultShape(context);
return Padding( return GestureDetector(
padding: EdgeInsets.only(
bottom: 4,
),
child: GestureDetector(
onTap: () => retryMessage(context), onTap: () => retryMessage(context),
onLongPress: () => onLongPress(context), onLongPress: () => onLongPress(context),
child: Material( child: Material(
color: attachment?.type == 'giphy' color:
? Colors.white attachment?.type == 'giphy' ? Colors.white : _getBackgroundColor(),
: _getBackgroundColor(),
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
shape: attachmentShape, shape: attachmentShape,
child: Padding( child: Padding(
@@ -673,7 +703,6 @@ class _MessageWidgetState extends State<MessageWidget> {
), ),
), ),
), ),
),
); );
} }
@@ -798,26 +827,6 @@ class _MessageWidgetState extends State<MessageWidget> {
return SizedBox(); 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) { Widget _buildTextBubble(BuildContext context) {
final isOnlyEmoji = final isOnlyEmoji =
widget.message.text.characters.every((c) => Emoji.byChar(c) != null); widget.message.text.characters.every((c) => Emoji.byChar(c) != null);
@@ -858,13 +867,6 @@ class _MessageWidgetState extends State<MessageWidget> {
], ],
), ),
); );
if (!isOnlyEmoji) {
child = _wrapTextInBubble(
context: context,
child: child,
);
}
return GestureDetector( return GestureDetector(
onTap: () => retryMessage(context), onTap: () => retryMessage(context),
onLongPress: () => onLongPress(context), onLongPress: () => onLongPress(context),
@@ -873,6 +875,9 @@ class _MessageWidgetState extends State<MessageWidget> {
} }
Color _getBackgroundColor() { Color _getBackgroundColor() {
final isOnlyEmoji =
widget.message.text.characters.every((c) => Emoji.byChar(c) != null);
if ((widget.message.status == MessageSendingStatus.FAILED || if ((widget.message.status == MessageSendingStatus.FAILED ||
widget.message.status == MessageSendingStatus.FAILED_UPDATE || widget.message.status == MessageSendingStatus.FAILED_UPDATE ||
widget.message.status == MessageSendingStatus.FAILED_DELETE)) { widget.message.status == MessageSendingStatus.FAILED_DELETE)) {
@@ -885,6 +890,9 @@ class _MessageWidgetState extends State<MessageWidget> {
return Color(0xFFE9F2FF); return Color(0xFFE9F2FF);
} }
if (isOnlyEmoji) {
return Colors.transparent;
}
return widget.messageTheme.messageBackgroundColor; 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({ factory StreamSvgIcon.copy({
double size, double size,
Color color, Color color,
@@ -481,4 +505,220 @@ class StreamSvgIcon extends StatelessWidget {
height: size, 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,
);
}
} }