From 9698ca53e4bc83a9ce0f2289df5ab0faae506ed1 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 19 Jan 2025 11:44:14 +0800 Subject: [PATCH] :sparkles: Swipe up to view attachment details --- assets/translations/en-US.json | 1 + assets/translations/zh-CN.json | 1 + lib/widgets/account/account_popover.dart | 1 - lib/widgets/attachment/attachment_zoom.dart | 130 +++++++++++++++++++- 4 files changed, 130 insertions(+), 3 deletions(-) diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index e4b7a73..9c79d0e 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -294,6 +294,7 @@ "addAttachmentFromCameraPhoto": "Take photo", "addAttachmentFromCameraVideo": "Take video", "addAttachmentFromRandomId": "Link via RID", + "attachmentDetailInfo": "Attachment details", "attachmentPastedImage": "Pasted Image", "attachmentInsertLink": "Insert Link", "attachmentSetAsPostThumbnail": "Set as post thumbnail", diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index f109dad..0506b4d 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -292,6 +292,7 @@ "addAttachmentFromCameraPhoto": "拍摄照片", "addAttachmentFromCameraVideo": "拍摄视频", "addAttachmentFromRandomId": "通过访问 ID 链接", + "attachmentDetailInfo": "附件详细信息", "attachmentPastedImage": "粘贴的图片", "attachmentInsertLink": "插入连接", "attachmentSetAsPostThumbnail": "设置为帖子缩略图", diff --git a/lib/widgets/account/account_popover.dart b/lib/widgets/account/account_popover.dart index 9325fad..af6e98c 100644 --- a/lib/widgets/account/account_popover.dart +++ b/lib/widgets/account/account_popover.dart @@ -10,7 +10,6 @@ import 'package:surface/providers/experience.dart'; import 'package:surface/providers/sn_network.dart'; import 'package:surface/screens/account/profile_page.dart'; import 'package:surface/types/account.dart'; -import 'package:surface/types/post.dart'; import 'package:surface/widgets/account/account_image.dart'; import 'package:surface/widgets/universal_image.dart'; diff --git a/lib/widgets/attachment/attachment_zoom.dart b/lib/widgets/attachment/attachment_zoom.dart index 0382e88..0252b98 100644 --- a/lib/widgets/attachment/attachment_zoom.dart +++ b/lib/widgets/attachment/attachment_zoom.dart @@ -129,6 +129,8 @@ class _AttachmentZoomViewState extends State { Color get _unFocusColor => Theme.of(context).colorScheme.onSurface.withOpacity(0.75); + bool _showDetail = false; + @override Widget build(BuildContext context) { final sn = context.read(); @@ -266,7 +268,8 @@ class _AttachmentZoomViewState extends State { borderRadius: const BorderRadius.all(Radius.circular(16)), onTap: _isDownloading ? null - : () => _saveToAlbum(widget.data.length > 1 ? _pageController.page?.round() ?? 0 : 0), + : () => + _saveToAlbum(widget.data.length > 1 ? _pageController.page?.round() ?? 0 : 0), child: Container( padding: const EdgeInsets.all(6), child: !_isDownloading @@ -324,7 +327,8 @@ class _AttachmentZoomViewState extends State { 'f/${item.metadata['exif']?['Aperture']}', style: metaTextStyle, ).padding(right: 2), - if (item.metadata['exif']?['Megapixels'] != null && item.metadata['exif']?['Model'] != null) + if (item.metadata['exif']?['Megapixels'] != null && + item.metadata['exif']?['Model'] != null) Text( '${item.metadata['exif']?['Megapixels']}MP', style: metaTextStyle, @@ -359,6 +363,20 @@ class _AttachmentZoomViewState extends State { ], ), ), + onVerticalDragUpdate: (details) { + if (_showDetail) return; + if (details.delta.dy < 0) { + _showDetail = true; + showModalBottomSheet( + context: context, + builder: (context) => _AttachmentZoomDetailPopup( + data: widget.data.elementAt(widget.data.length > 1 ? _pageController.page?.round() ?? 0 : 0), + ), + ).then((_) { + _showDetail = false; + }); + } + }, onTap: () { Navigator.of(context).pop(); }, @@ -366,3 +384,111 @@ class _AttachmentZoomViewState extends State { ); } } + +class _AttachmentZoomDetailPopup extends StatelessWidget { + final SnAttachment data; + + const _AttachmentZoomDetailPopup({required this.data}); + + @override + Widget build(BuildContext context) { + final ud = context.read(); + final account = ud.getAccountFromCache(data.accountId); + + const tableGap = TableRow( + children: [ + TableCell(child: SizedBox(height: 16)), + TableCell(child: SizedBox(height: 16)), + ], + ); + + return SizedBox( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Symbols.info, size: 24), + const Gap(16), + Text('attachmentDetailInfo').tr().textStyle(Theme.of(context).textTheme.titleLarge!), + ], + ).padding(horizontal: 20, top: 16, bottom: 12), + Expanded( + child: Table( + columnWidths: { + 0: IntrinsicColumnWidth(), + 1: FlexColumnWidth(), + }, + children: [ + TableRow( + children: [ + TableCell( + child: Text('attachmentUploadBy').tr().padding(right: 16), + ), + TableCell( + child: Row( + children: [ + if (data.accountId > 0) + AccountImage( + content: account?.avatar, + radius: 8, + ), + const Gap(8), + Text(data.accountId > 0 ? account?.nick ?? 'unknown'.tr() : 'unknown'.tr()), + const Gap(8), + Text('#${data.accountId}', style: GoogleFonts.robotoMono()).opacity(0.75), + ], + ), + ), + ], + ), + tableGap, + TableRow( + children: [ + TableCell(child: Text('Mimetype').padding(right: 16)), + TableCell(child: Text(data.mimetype)), + ], + ), + TableRow( + children: [ + TableCell(child: Text('Size').padding(right: 16)), + TableCell( + child: Row( + children: [ + Text(data.size.formatBytes()), + const Gap(12), + Text('${data.size} Bytes', style: GoogleFonts.robotoMono()).opacity(0.75), + ], + )), + ], + ), + TableRow( + children: [ + TableCell(child: Text('Name').padding(right: 16)), + TableCell(child: Text(data.name)), + ], + ), + if (data.hash.isNotEmpty) + TableRow( + children: [ + TableCell(child: Text('Hash').padding(right: 16)), + TableCell(child: Text(data.hash, style: GoogleFonts.robotoMono(fontSize: 11)).opacity(0.9)), + ], + ), + tableGap, + ...(data.metadata['exif']?.keys.map((k) => TableRow( + children: [ + TableCell(child: Text(k).padding(right: 16)), + TableCell(child: Text(data.metadata['exif'][k].toString())), + ], + )) ?? + []), + ], + ).padding(horizontal: 20, vertical: 8), + ), + ], + ), + ); + } +}