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
+156 -10
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( child: Container(
onTap: () { width: size?.width ?? 100,
launchURL(context, attachment.assetUrl); height: 56.0,
}, margin: trailing != null ? EdgeInsets.only(top: 4.0) : null,
child: Container( decoration: BoxDecoration(
width: size?.width ?? 100, color: Colors.white,
height: size?.height ?? 100, borderRadius: trailing != null ? BorderRadius.circular(16.0) : null,
child: Center( border: trailing != null
child: Icon(Icons.attach_file), ? 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;
}
}
} }
+180 -80
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,49 +699,49 @@ 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
setState(() { ? null
_filePickerIndex = 0; : () {
}); setState(() {
}, _filePickerIndex = 0;
});
},
), ),
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
pickFile(DefaultAttachmentTypes.file, false); ? null
}, : () {
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
pickFile(DefaultAttachmentTypes.image, true); ? null
}, : () {
pickFile(DefaultAttachmentTypes.image, true);
},
), ),
IconButton( IconButton(
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
pickFile(DefaultAttachmentTypes.video, true); ? null
}, : () {
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,19 +813,22 @@ class MessageInputState extends State<MessageInput> {
} }
if (snapshot.data) { if (snapshot.data) {
return MediaListView( return IgnorePointer(
selectedIds: _attachments.map((e) => e.id).toList(), ignoring: _attachmentContainsFile,
onSelect: (media) async { child: MediaListView(
if (!_attachments selectedIds: _attachments.map((e) => e.id).toList(),
.any((element) => element.id == media.id)) { onSelect: (media) async {
_addAttachment(media); if (!_attachments
} else { .any((element) => element.id == media.id)) {
setState(() { _addAttachment(media);
_attachments } else {
.removeWhere((element) => element.id == media.id); setState(() {
}); _attachments
} .removeWhere((element) => element.id == media.id);
}, });
}
},
),
); );
} }
@@ -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,44 +1235,98 @@ class MessageInputState extends State<MessageInput> {
Widget _buildAttachments() { Widget _buildAttachments() {
return _attachments.isEmpty return _attachments.isEmpty
? Container() ? Container()
: LimitedBox( : Column(
maxHeight: 104.0, children: [
child: ListView( if (_attachments.any((e) => e.attachment?.type == 'file'))
scrollDirection: Axis.horizontal, LimitedBox(
children: _attachments maxHeight: 73.0,
.map( child: ListView(
(attachment) => Padding( scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(8.0), children: _attachments
child: ClipRRect( .where((e) => e.attachment?.type == 'file')
borderRadius: BorderRadius.circular(10), .map(
child: Stack( (e) => Padding(
children: <Widget>[ padding:
AspectRatio( const EdgeInsets.symmetric(horizontal: 8.0),
aspectRatio: 1.0, child: ClipRRect(
child: Container( borderRadius: BorderRadius.circular(10),
height: 104, clipBehavior: Clip.antiAlias,
width: 104, child: FileAttachment(
child: _buildAttachment(attachment), attachment: e.attachment,
), size: Size(
), MediaQuery.of(context).size.width * 0.55,
_buildRemoveButton(attachment), MediaQuery.of(context).size.height * 0.3,
attachment.uploaded ),
? SizedBox() trailing: Padding(
: Positioned.fill( padding: const EdgeInsets.all(8.0),
child: Center( child: InkWell(
child: Padding( child: CircleAvatar(
padding: const EdgeInsets.all(16.0), backgroundColor:
child: CircularProgressIndicator(), 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) { 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),
+81 -73
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,18 +302,46 @@ class _MessageWidgetState extends State<MessageWidget> {
messageTheme: widget.messageTheme, messageTheme: widget.messageTheme,
), ),
) )
: Column( : Material(
crossAxisAlignment: clipBehavior: Clip.antiAlias,
CrossAxisAlignment.start, shape: widget.shape ??
mainAxisSize: MainAxisSize.min, RoundedRectangleBorder(
children: <Widget>[ side: isOnlyEmoji
..._parseAttachments(context), ? BorderSide.none
if (widget.message.text : widget.borderSide ??
.trim() BorderSide(
.isNotEmpty && color: Theme.of(context)
!isGiphy) .brightness ==
_buildTextBubble(context), 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) if (widget.showReactionPickerIndicator)
@@ -629,46 +664,40 @@ 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( onTap: () => retryMessage(context),
bottom: 4, onLongPress: () => onLongPress(context),
), child: Material(
child: GestureDetector( color:
onTap: () => retryMessage(context), attachment?.type == 'giphy' ? Colors.white : _getBackgroundColor(),
onLongPress: () => onLongPress(context), clipBehavior: Clip.hardEdge,
child: Material( shape: attachmentShape,
color: attachment?.type == 'giphy' child: Padding(
? Colors.white padding: widget.attachmentPadding,
: _getBackgroundColor(), child: Material(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
shape: attachmentShape, shape: attachmentShape,
child: Padding( type: MaterialType.transparency,
padding: widget.attachmentPadding, child: Transform(
child: Material( transform: Matrix4.rotationY(widget.reverse ? pi : 0),
clipBehavior: Clip.hardEdge, alignment: Alignment.center,
shape: attachmentShape, child: Column(
type: MaterialType.transparency, mainAxisSize: MainAxisSize.min,
child: Transform( crossAxisAlignment: CrossAxisAlignment.end,
transform: Matrix4.rotationY(widget.reverse ? pi : 0), children: <Widget>[
alignment: Alignment.center, getFailedMessageWidget(
child: Column( context,
mainAxisSize: MainAxisSize.min, padding: const EdgeInsets.all(8.0),
crossAxisAlignment: CrossAxisAlignment.end, ),
children: <Widget>[ attachmentWidget,
getFailedMessageWidget( ],
context,
padding: const EdgeInsets.all(8.0),
),
attachmentWidget,
],
),
), ),
), ),
), ),
@@ -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,
);
}
} }