💄 Experimental new attachment layout

This commit is contained in:
LittleSheep 2024-12-29 12:02:26 +08:00
parent e503c3f02f
commit f6cf6d0440
7 changed files with 88 additions and 78 deletions

View File

@ -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",

View File

@ -456,6 +456,7 @@
"accountJoinedAt": "加入于 {}",
"accountBirthday": "出生于 {}",
"accountBadge": "徽章",
"accountCheckInNoRecords": "暂无运势记录",
"badgeCompanyStaff": "索尔辛茨士大夫 · 员工",
"badgeSiteMigration": "Solar Network 原住民",
"accountStatus": "状态",

View File

@ -517,6 +517,12 @@ class _UserScreenState extends State<UserScreen> 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,

View File

@ -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':

View File

@ -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<SnAttachment?> 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<AttachmentList> {
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<AttachmentList> {
}
.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<AttachmentList> {
);
}
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(),
),
),
),
);
}

View File

@ -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),

View File

@ -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),