From f6cf6d044005485290510d131becdedb92873e5d Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 29 Dec 2024 12:02:26 +0800 Subject: [PATCH] :lipstick: Experimental new attachment layout --- assets/translations/en-US.json | 1 + assets/translations/zh-CN.json | 1 + lib/screens/account/pfp.dart | 6 + lib/widgets/attachment/attachment_item.dart | 4 +- lib/widgets/attachment/attachment_list.dart | 143 ++++++++++---------- lib/widgets/chat/chat_message.dart | 1 + lib/widgets/post/post_item.dart | 10 +- 7 files changed, 88 insertions(+), 78 deletions(-) diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index 9d18cce..e79f049 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -458,6 +458,7 @@ "accountJoinedAt": "Joined at {}", "accountBirthday": "Born on {}", "accountBadge": "Badge", + "accountCheckInNoRecords": "No check-in records", "badgeCompanyStaff": "Solsynth Staff", "badgeSiteMigration": "Solar Network Native", "accountStatus": "Status", diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 660c130..6b37e74 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -456,6 +456,7 @@ "accountJoinedAt": "加入于 {}", "accountBirthday": "出生于 {}", "accountBadge": "徽章", + "accountCheckInNoRecords": "暂无运势记录", "badgeCompanyStaff": "索尔辛茨士大夫 · 员工", "badgeSiteMigration": "Solar Network 原住民", "accountStatus": "状态", diff --git a/lib/screens/account/pfp.dart b/lib/screens/account/pfp.dart index 2e9be1d..5ad3cf6 100644 --- a/lib/screens/account/pfp.dart +++ b/lib/screens/account/pfp.dart @@ -517,6 +517,12 @@ class _UserScreenState extends State with SingleTickerProviderStateM future: _getCheckInRecords(), builder: (context, snapshot) { if (!snapshot.hasData) return const SizedBox.shrink(); + if (snapshot.data!.length <= 1) { + return Text( + 'accountCheckInNoRecords', + textAlign: TextAlign.center, + ).tr().fontWeight(FontWeight.bold).center().padding(horizontal: 20, vertical: 8); + } final records = snapshot.data!; return SizedBox( width: double.infinity, diff --git a/lib/widgets/attachment/attachment_item.dart b/lib/widgets/attachment/attachment_item.dart index 6fac8b9..0376024 100644 --- a/lib/widgets/attachment/attachment_item.dart +++ b/lib/widgets/attachment/attachment_item.dart @@ -20,9 +20,11 @@ import 'package:uuid/uuid.dart'; class AttachmentItem extends StatelessWidget { final SnAttachment? data; final String? heroTag; + final BoxFit fit; const AttachmentItem({ super.key, + this.fit = BoxFit.cover, required this.data, required this.heroTag, }); @@ -43,7 +45,7 @@ class AttachmentItem extends StatelessWidget { child: AutoResizeUniversalImage( sn.getAttachmentUrl(data!.rid), key: Key('attachment-${data!.rid}-$tag'), - fit: BoxFit.cover, + fit: fit, ), ); case 'video': diff --git a/lib/widgets/attachment/attachment_list.dart b/lib/widgets/attachment/attachment_list.dart index 445c310..7b87457 100644 --- a/lib/widgets/attachment/attachment_list.dart +++ b/lib/widgets/attachment/attachment_list.dart @@ -4,8 +4,8 @@ import 'package:collection/collection.dart'; import 'package:dismissible_page/dismissible_page.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:gap/gap.dart'; -import 'package:responsive_framework/responsive_framework.dart'; import 'package:surface/types/attachment.dart'; import 'package:surface/widgets/attachment/attachment_zoom.dart'; import 'package:surface/widgets/attachment/attachment_item.dart'; @@ -14,8 +14,9 @@ import 'package:uuid/uuid.dart'; class AttachmentList extends StatefulWidget { final List data; final bool bordered; + final bool gridded; final bool noGrow; - final bool isFlatted; + final BoxFit fit; final double? maxHeight; final EdgeInsets? listPadding; @@ -23,8 +24,9 @@ class AttachmentList extends StatefulWidget { super.key, required this.data, this.bordered = false, + this.gridded = false, this.noGrow = false, - this.isFlatted = false, + this.fit = BoxFit.cover, this.maxHeight, this.listPadding, }); @@ -53,7 +55,6 @@ class _AttachmentListState extends State { final constraints = BoxConstraints( minWidth: 80, maxHeight: widget.maxHeight ?? double.infinity, - maxWidth: layoutConstraints.maxWidth - 20, ); if (widget.data.isEmpty) return const SizedBox.shrink(); @@ -66,52 +67,29 @@ class _AttachmentListState extends State { } .toDouble(); - return Container( - constraints: ResponsiveBreakpoints.of(context).largerThan(MOBILE) - ? constraints.copyWith( - maxWidth: math.min( - constraints.maxWidth, - kAttachmentMaxWidth, - ), - ) - : null, - child: AspectRatio( - aspectRatio: singleAspectRatio, + return Padding( + padding: widget.listPadding ?? EdgeInsets.zero, + child: Container( + constraints: constraints, + width: double.infinity, child: GestureDetector( - child: Builder( - builder: (context) { - if (ResponsiveBreakpoints.of(context).largerThan(MOBILE) || widget.noGrow) { - return Padding( - // Single child list-like displaying - padding: widget.listPadding ?? EdgeInsets.zero, - child: Container( - decoration: BoxDecoration( - color: backgroundColor, - border: Border(top: borderSide, bottom: borderSide), - borderRadius: AttachmentList.kDefaultRadius, - ), - child: ClipRRect( - borderRadius: AttachmentList.kDefaultRadius, - child: AttachmentItem( - data: widget.data[0], - heroTag: heroTags[0], - ), - ), - ), - ); - } - - return Container( - decoration: BoxDecoration( - color: backgroundColor, - border: Border(top: borderSide, bottom: borderSide), - ), + child: AspectRatio( + aspectRatio: singleAspectRatio, + child: Container( + decoration: BoxDecoration( + color: backgroundColor, + border: Border.fromBorderSide(borderSide), + borderRadius: AttachmentList.kDefaultRadius, + ), + child: ClipRRect( + borderRadius: AttachmentList.kDefaultRadius, child: AttachmentItem( data: widget.data[0], - heroTag: heroTags.first, + heroTag: heroTags[0], + fit: widget.fit, ), - ); - }, + ), + ), ), onTap: () { if (widget.data.firstOrNull?.mediaType != SnMediaType.image) return; @@ -130,34 +108,53 @@ class _AttachmentListState extends State { ); } - if (widget.isFlatted) { - return Wrap( - spacing: 4, - runSpacing: 4, - children: widget.data - .mapIndexed( - (idx, ele) => AspectRatio( - aspectRatio: (ele?.data['ratio'] ?? 1).toDouble(), - child: Container( - decoration: BoxDecoration( - color: backgroundColor, - border: Border( - top: borderSide, - bottom: borderSide, + if (widget.gridded) { + return Padding( + padding: widget.listPadding ?? EdgeInsets.zero, + child: Container( + decoration: BoxDecoration( + color: backgroundColor, + border: Border( + top: borderSide, + bottom: borderSide, + ), + borderRadius: AttachmentList.kDefaultRadius, + ), + child: ClipRRect( + borderRadius: AttachmentList.kDefaultRadius, + child: StaggeredGrid.count( + crossAxisCount: math.min(widget.data.length, 2), + crossAxisSpacing: 4, + mainAxisSpacing: 4, + children: widget.data + .mapIndexed( + (idx, ele) => GestureDetector( + child: Container( + constraints: constraints, + child: AttachmentItem( + data: ele, + heroTag: heroTags[idx], + fit: widget.fit, + ), + ), + onTap: () { + if (widget.data[idx]!.mediaType != SnMediaType.image) return; + context.pushTransparentRoute( + AttachmentZoomView( + data: widget.data.where((ele) => ele != null).cast(), + initialIndex: idx, + heroTags: heroTags, + ), + backgroundColor: Colors.black.withOpacity(0.7), + rootNavigator: true, + ); + }, ), - borderRadius: AttachmentList.kDefaultRadius, - ), - child: ClipRRect( - borderRadius: AttachmentList.kDefaultRadius, - child: AttachmentItem( - data: ele, - heroTag: heroTags[idx], - ), - ), - ), - ), - ) - .toList(), + ) + .toList(), + ), + ), + ), ); } diff --git a/lib/widgets/chat/chat_message.dart b/lib/widgets/chat/chat_message.dart index 26080f0..b55f512 100644 --- a/lib/widgets/chat/chat_message.dart +++ b/lib/widgets/chat/chat_message.dart @@ -159,6 +159,7 @@ class ChatMessage extends StatelessWidget { AttachmentList( data: data.preload!.attachments!, bordered: true, + gridded: true, noGrow: true, maxHeight: 520, listPadding: const EdgeInsets.only(top: 8), diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index b83339d..9968e24 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -251,7 +251,9 @@ class PostItem extends StatelessWidget { AttachmentList( data: data.preload!.attachments!, bordered: true, - maxHeight: 560, + gridded: true, + maxHeight: showFullPost ? null : 480, + fit: showFullPost ? BoxFit.cover : BoxFit.contain, listPadding: const EdgeInsets.symmetric(horizontal: 12), ), if (data.body['content'] != null) @@ -337,7 +339,7 @@ class PostShareImageWidget extends StatelessWidget { if (data.type != 'article' && (data.preload?.attachments?.isNotEmpty ?? false)) AttachmentList( data: data.preload!.attachments!, - isFlatted: true, + gridded: true, ).padding(horizontal: 16, bottom: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -930,12 +932,12 @@ class _PostQuoteContent extends StatelessWidget { ), child: AttachmentList( data: child.preload!.attachments!, - isFlatted: isFlatted, + gridded: isFlatted, listPadding: const EdgeInsets.symmetric(horizontal: 12), ), ).padding( top: 8, - bottom: (child.preload?.attachments?.length ?? 0) > 1 ? 12 : 0, + bottom: 12, ) else const Gap(8),