💄 Better attachment layout
This commit is contained in:
parent
32e6658f3d
commit
a5ee5b7f09
@ -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,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user