💄 Better attachment layout
This commit is contained in:
		| @@ -1,4 +1,4 @@ | |||||||
| import 'dart:math' show min; | import 'dart:math' as math; | ||||||
| import 'dart:ui'; | import 'dart:ui'; | ||||||
|  |  | ||||||
| import 'package:carousel_slider/carousel_slider.dart'; | import 'package:carousel_slider/carousel_slider.dart'; | ||||||
| @@ -16,9 +16,11 @@ class AttachmentList extends StatefulWidget { | |||||||
|   final String parentId; |   final String parentId; | ||||||
|   final List<String> attachmentsId; |   final List<String> attachmentsId; | ||||||
|   final bool isGrid; |   final bool isGrid; | ||||||
|  |   final bool isColumn; | ||||||
|   final bool isForceGrid; |   final bool isForceGrid; | ||||||
|   final bool autoload; |   final bool autoload; | ||||||
|   final double flatMaxHeight; |   final double flatMaxHeight; | ||||||
|  |   final double columnMaxWidth; | ||||||
|  |  | ||||||
|   final double? width; |   final double? width; | ||||||
|   final double? viewport; |   final double? viewport; | ||||||
| @@ -28,9 +30,11 @@ class AttachmentList extends StatefulWidget { | |||||||
|     required this.parentId, |     required this.parentId, | ||||||
|     required this.attachmentsId, |     required this.attachmentsId, | ||||||
|     this.isGrid = false, |     this.isGrid = false, | ||||||
|  |     this.isColumn = false, | ||||||
|     this.isForceGrid = false, |     this.isForceGrid = false, | ||||||
|     this.autoload = false, |     this.autoload = false, | ||||||
|     this.flatMaxHeight = 720, |     this.flatMaxHeight = 720, | ||||||
|  |     this.columnMaxWidth = 480, | ||||||
|     this.width, |     this.width, | ||||||
|     this.viewport, |     this.viewport, | ||||||
|   }); |   }); | ||||||
| @@ -105,13 +109,14 @@ class _AttachmentListState extends State<AttachmentList> { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Widget _buildEntry(Attachment? element, int idx) { |   Widget _buildEntry(Attachment? element, int idx, {double? width}) { | ||||||
|     return AttachmentListEntry( |     return AttachmentListEntry( | ||||||
|       item: element, |       item: element, | ||||||
|       parentId: widget.parentId, |       parentId: widget.parentId, | ||||||
|       width: widget.width, |       width: width ?? widget.width, | ||||||
|       badgeContent: '${idx + 1}/${_attachmentsMeta.length}', |       badgeContent: '${idx + 1}/${_attachmentsMeta.length}', | ||||||
|       showBadge: _attachmentsMeta.length > 1 && !widget.isGrid, |       showBadge: | ||||||
|  |           _attachmentsMeta.length > 1 && !widget.isGrid && !widget.isColumn, | ||||||
|       showBorder: widget.attachmentsId.length > 1, |       showBorder: widget.attachmentsId.length > 1, | ||||||
|       showMature: _showMature, |       showMature: _showMature, | ||||||
|       autoload: widget.autoload, |       autoload: widget.autoload, | ||||||
| @@ -142,6 +147,43 @@ class _AttachmentListState extends State<AttachmentList> { | |||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (widget.isColumn) { | ||||||
|  |       var idx = 0; | ||||||
|  |       const radius = BorderRadius.all(Radius.circular(8)); | ||||||
|  |       return Wrap( | ||||||
|  |         spacing: 8, | ||||||
|  |         runSpacing: 8, | ||||||
|  |         children: widget.attachmentsId.map((x) { | ||||||
|  |           final element = _attachmentsMeta[idx]; | ||||||
|  |           idx++; | ||||||
|  |           if (element == null) return const SizedBox(); | ||||||
|  |           double ratio = element.metadata!['ratio']?.toDouble() ?? 16 / 9; | ||||||
|  |           return Container( | ||||||
|  |             constraints: BoxConstraints( | ||||||
|  |               maxWidth: widget.columnMaxWidth, | ||||||
|  |               maxHeight: 640, | ||||||
|  |             ), | ||||||
|  |             child: AspectRatio( | ||||||
|  |               aspectRatio: ratio, | ||||||
|  |               child: Container( | ||||||
|  |                 decoration: BoxDecoration( | ||||||
|  |                   border: Border.all( | ||||||
|  |                     color: Theme.of(context).dividerColor, | ||||||
|  |                     width: 1, | ||||||
|  |                   ), | ||||||
|  |                   borderRadius: radius, | ||||||
|  |                 ), | ||||||
|  |                 child: ClipRRect( | ||||||
|  |                   borderRadius: radius, | ||||||
|  |                   child: _buildEntry(element, idx), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ); | ||||||
|  |         }).toList(), | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     final isNotPureImage = _attachmentsMeta.any( |     final isNotPureImage = _attachmentsMeta.any( | ||||||
|       (x) => x?.mimetype.split('/').firstOrNull != 'image', |       (x) => x?.mimetype.split('/').firstOrNull != 'image', | ||||||
|     ); |     ); | ||||||
| @@ -153,7 +195,7 @@ class _AttachmentListState extends State<AttachmentList> { | |||||||
|         physics: const NeverScrollableScrollPhysics(), |         physics: const NeverScrollableScrollPhysics(), | ||||||
|         shrinkWrap: true, |         shrinkWrap: true, | ||||||
|         gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |         gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||||||
|           crossAxisCount: min(3, widget.attachmentsId.length), |           crossAxisCount: math.min(3, widget.attachmentsId.length), | ||||||
|           mainAxisSpacing: 8.0, |           mainAxisSpacing: 8.0, | ||||||
|           crossAxisSpacing: 8.0, |           crossAxisSpacing: 8.0, | ||||||
|         ), |         ), | ||||||
| @@ -213,6 +255,7 @@ class AttachmentListEntry extends StatelessWidget { | |||||||
|   final Attachment? item; |   final Attachment? item; | ||||||
|   final String? badgeContent; |   final String? badgeContent; | ||||||
|   final double? width; |   final double? width; | ||||||
|  |   final double? height; | ||||||
|   final bool showBorder; |   final bool showBorder; | ||||||
|   final bool showBadge; |   final bool showBadge; | ||||||
|   final bool showMature; |   final bool showMature; | ||||||
| @@ -227,6 +270,7 @@ class AttachmentListEntry extends StatelessWidget { | |||||||
|     this.item, |     this.item, | ||||||
|     this.badgeContent, |     this.badgeContent, | ||||||
|     this.width, |     this.width, | ||||||
|  |     this.height, | ||||||
|     this.showBorder = false, |     this.showBorder = false, | ||||||
|     this.showBadge = false, |     this.showBadge = false, | ||||||
|     this.showMature = false, |     this.showMature = false, | ||||||
| @@ -251,6 +295,7 @@ class AttachmentListEntry extends StatelessWidget { | |||||||
|     return GestureDetector( |     return GestureDetector( | ||||||
|       child: Container( |       child: Container( | ||||||
|         width: width ?? MediaQuery.of(context).size.width, |         width: width ?? MediaQuery.of(context).size.width, | ||||||
|  |         height: height, | ||||||
|         decoration: BoxDecoration( |         decoration: BoxDecoration( | ||||||
|           border: showBorder |           border: showBorder | ||||||
|               ? Border.symmetric( |               ? Border.symmetric( | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ class ChatEvent extends StatelessWidget { | |||||||
|         key: Key('m${item.uuid}attachments'), |         key: Key('m${item.uuid}attachments'), | ||||||
|         parentId: item.uuid, |         parentId: item.uuid, | ||||||
|         attachmentsId: attachments, |         attachmentsId: attachments, | ||||||
|         viewport: 1, |         isColumn: true, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -189,7 +189,7 @@ class ChatEvent extends StatelessWidget { | |||||||
|             ], |             ], | ||||||
|           ).paddingOnly(right: 12), |           ).paddingOnly(right: 12), | ||||||
|           _buildAttachment(context, isMinimal: isContentPreviewing) |           _buildAttachment(context, isMinimal: isContentPreviewing) | ||||||
|               .paddingOnly(left: isContentPreviewing ? 12 : 0), |               .paddingOnly(left: isContentPreviewing ? 12 : 56), | ||||||
|         ], |         ], | ||||||
|       ); |       ); | ||||||
|     } else if (isQuote) { |     } else if (isQuote) { | ||||||
| @@ -221,8 +221,7 @@ class ChatEvent extends StatelessWidget { | |||||||
|                     ], |                     ], | ||||||
|                   ), |                   ), | ||||||
|                   _buildContent().paddingOnly(left: 0.5), |                   _buildContent().paddingOnly(left: 0.5), | ||||||
|                   _buildAttachment(context, isMinimal: true) |                   _buildAttachment(context, isMinimal: true), | ||||||
|                       .paddingOnly(left: 0), |  | ||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
| @@ -284,7 +283,7 @@ class ChatEvent extends StatelessWidget { | |||||||
|               ), |               ), | ||||||
|             ], |             ], | ||||||
|           ).paddingSymmetric(horizontal: 12), |           ).paddingSymmetric(horizontal: 12), | ||||||
|           _buildAttachment(context), |           _buildAttachment(context).paddingOnly(left: 56), | ||||||
|         ], |         ], | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -289,6 +289,35 @@ class _PostItemState extends State<PostItem> { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Widget _buildAttachments() { | ||||||
|  |     final List<String> attachments = item.body['attachments'] is List | ||||||
|  |         ? List.from(item.body['attachments']?.whereType<String>()) | ||||||
|  |         : List.empty(); | ||||||
|  |  | ||||||
|  |     if (attachments.length > 3) { | ||||||
|  |       return AttachmentList( | ||||||
|  |         parentId: widget.item.id.toString(), | ||||||
|  |         attachmentsId: attachments, | ||||||
|  |         autoload: true, | ||||||
|  |         isGrid: true, | ||||||
|  |       ).paddingOnly(left: 36, top: 4, bottom: 4); | ||||||
|  |     } else if (attachments.length > 1) { | ||||||
|  |       return AttachmentList( | ||||||
|  |         parentId: widget.item.id.toString(), | ||||||
|  |         attachmentsId: attachments, | ||||||
|  |         autoload: true, | ||||||
|  |         isColumn: true, | ||||||
|  |       ).paddingOnly(left: 60, right: 24); | ||||||
|  |     } else { | ||||||
|  |       return AttachmentList( | ||||||
|  |         flatMaxHeight: MediaQuery.of(context).size.width, | ||||||
|  |         parentId: widget.item.id.toString(), | ||||||
|  |         attachmentsId: attachments, | ||||||
|  |         autoload: true, | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   double _contentHeight = 0; |   double _contentHeight = 0; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -467,17 +496,11 @@ class _PostItemState extends State<PostItem> { | |||||||
|             ], |             ], | ||||||
|           ).paddingOnly( |           ).paddingOnly( | ||||||
|             top: 10, |             top: 10, | ||||||
|             bottom: hasAttachment ? 10 : 0, |             bottom: attachments.length == 1 ? 10 : 0, | ||||||
|             right: 16, |             right: 16, | ||||||
|             left: 16, |             left: 16, | ||||||
|           ), |           ), | ||||||
|           AttachmentList( |           _buildAttachments(), | ||||||
|             flatMaxHeight: MediaQuery.of(context).size.width, |  | ||||||
|             parentId: widget.item.id.toString(), |  | ||||||
|             attachmentsId: attachments, |  | ||||||
|             autoload: true, |  | ||||||
|             isGrid: attachments.length > 1, |  | ||||||
|           ), |  | ||||||
|           if (widget.isShowReply || widget.isReactable) |           if (widget.isShowReply || widget.isReactable) | ||||||
|             PostQuickAction( |             PostQuickAction( | ||||||
|               isShowReply: widget.isShowReply, |               isShowReply: widget.isShowReply, | ||||||
| @@ -490,8 +513,8 @@ class _PostItemState extends State<PostItem> { | |||||||
|                 }); |                 }); | ||||||
|               }, |               }, | ||||||
|             ).paddingOnly( |             ).paddingOnly( | ||||||
|               top: hasAttachment ? 10 : 6, |               top: attachments.length == 1 ? 10 : 6, | ||||||
|               left: hasAttachment ? 24 : 60, |               left: attachments.length == 1 ? 24 : 60, | ||||||
|               right: 16, |               right: 16, | ||||||
|               bottom: 10, |               bottom: 10, | ||||||
|             ) |             ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user