Compare commits
	
		
			2 Commits
		
	
	
		
			8236d31ecc
			...
			cf355a95fd
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cf355a95fd | |||
| 2f43073172 | 
| @@ -793,5 +793,10 @@ | ||||
|   "joinedAt": "Joined at {}", | ||||
|   "searchAccounts": "Search accounts...", | ||||
|   "webFeeds": "Web Feeds", | ||||
|   "polls": "Polls" | ||||
|   "polls": "Polls", | ||||
|   "sharePostSlogan": "Explore more on the Solar Network", | ||||
|   "filesListAdditional": { | ||||
|     "one": "+{} file remaining", | ||||
|     "other": "+{} files remaining" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -791,5 +791,10 @@ | ||||
|   "joinedAt": "加入于 {}", | ||||
|   "searchAccounts": "搜索帐号……", | ||||
|   "webFeeds": "订阅源", | ||||
|   "polls": "投票" | ||||
|   "polls": "投票", | ||||
|   "sharePostSlogan": "加入 Solar Network 以便探索更多", | ||||
|   "filesListAdditional": { | ||||
|     "one": "+{} 个文件被折叠", | ||||
|     "other": "+{} 个文件被折叠" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import 'package:dio/dio.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| @@ -262,6 +263,10 @@ class AccountProfileScreen extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     final user = ref.watch(userInfoProvider); | ||||
|     final isCurrentUser = useMemoized( | ||||
|       () => user.value?.id == account.value?.id, | ||||
|       [user, account], | ||||
|     ); | ||||
|  | ||||
|     Widget accountBasicInfo(SnAccount data) => Padding( | ||||
|       padding: const EdgeInsets.fromLTRB(24, 24, 24, 8), | ||||
| @@ -589,7 +594,7 @@ class AccountProfileScreen extends HookConsumerWidget { | ||||
|                           child: CustomScrollView( | ||||
|                             slivers: [ | ||||
|                               SliverGap(24), | ||||
|                               if (user.value != null) | ||||
|                               if (user.value != null && !isCurrentUser) | ||||
|                                 SliverToBoxAdapter(child: accountAction(data)), | ||||
|                               SliverToBoxAdapter( | ||||
|                                 child: Card( | ||||
| @@ -686,7 +691,7 @@ class AccountProfileScreen extends HookConsumerWidget { | ||||
|                             data, | ||||
|                           ).padding(horizontal: 4), | ||||
|                         ), | ||||
|                         if (user.value != null) | ||||
|                         if (user.value != null && !isCurrentUser) | ||||
|                           SliverToBoxAdapter( | ||||
|                             child: accountAction(data).padding(horizontal: 4), | ||||
|                           ), | ||||
|   | ||||
| @@ -31,6 +31,7 @@ class CloudFileList extends HookConsumerWidget { | ||||
|   final bool disableZoomIn; | ||||
|   final bool disableConstraint; | ||||
|   final EdgeInsets? padding; | ||||
|   final bool isColumn; | ||||
|   const CloudFileList({ | ||||
|     super.key, | ||||
|     required this.files, | ||||
| @@ -40,6 +41,7 @@ class CloudFileList extends HookConsumerWidget { | ||||
|     this.disableZoomIn = false, | ||||
|     this.disableConstraint = false, | ||||
|     this.padding, | ||||
|     this.isColumn = false, | ||||
|   }); | ||||
|  | ||||
|   double calculateAspectRatio() { | ||||
| @@ -63,6 +65,74 @@ class CloudFileList extends HookConsumerWidget { | ||||
|     ); | ||||
|  | ||||
|     if (files.isEmpty) return const SizedBox.shrink(); | ||||
|  | ||||
|     if (isColumn) { | ||||
|       final children = <Widget>[]; | ||||
|       const maxFiles = 2; | ||||
|       final filesToShow = files.take(maxFiles).toList(); | ||||
|  | ||||
|       for (var i = 0; i < filesToShow.length; i++) { | ||||
|         final file = filesToShow[i]; | ||||
|         final isImage = file.mimeType?.startsWith('image') ?? false; | ||||
|         final isAudio = file.mimeType?.startsWith('audio') ?? false; | ||||
|         final widgetItem = ClipRRect( | ||||
|           borderRadius: const BorderRadius.all(Radius.circular(8)), | ||||
|           child: _CloudFileListEntry( | ||||
|             file: file, | ||||
|             heroTag: heroTags[i], | ||||
|             isImage: isImage, | ||||
|             disableZoomIn: disableZoomIn, | ||||
|             onTap: () { | ||||
|               if (!isImage) { | ||||
|                 return; | ||||
|               } | ||||
|               if (!disableZoomIn) { | ||||
|                 context.pushTransparentRoute( | ||||
|                   CloudFileZoomIn(item: file, heroTag: heroTags[i]), | ||||
|                   rootNavigator: true, | ||||
|                 ); | ||||
|               } | ||||
|             }, | ||||
|           ), | ||||
|         ); | ||||
|  | ||||
|         Widget item; | ||||
|         if (isAudio) { | ||||
|           item = SizedBox(height: 120, child: widgetItem); | ||||
|         } else { | ||||
|           item = AspectRatio( | ||||
|             aspectRatio: file.fileMeta?['ratio'] as double? ?? 1.0, | ||||
|             child: widgetItem, | ||||
|           ); | ||||
|         } | ||||
|         children.add(item); | ||||
|         if (i < filesToShow.length - 1) { | ||||
|           children.add(const Gap(8)); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (files.length > maxFiles) { | ||||
|         children.add(const Gap(8)); | ||||
|         children.add( | ||||
|           Text( | ||||
|             'filesListAdditional'.plural(files.length - filesToShow.length), | ||||
|             textAlign: TextAlign.center, | ||||
|             style: Theme.of(context).textTheme.bodyMedium?.copyWith( | ||||
|               color: Theme.of(context).colorScheme.onSurface.withOpacity(0.7), | ||||
|             ), | ||||
|           ), | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|       return Padding( | ||||
|         padding: padding ?? EdgeInsets.zero, | ||||
|         child: Column( | ||||
|           mainAxisSize: MainAxisSize.min, | ||||
|           crossAxisAlignment: CrossAxisAlignment.stretch, | ||||
|           children: children, | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|     if (files.length == 1) { | ||||
|       final isImage = files.first.mimeType?.startsWith('image') ?? false; | ||||
|       final isAudio = files.first.mimeType?.startsWith('audio') ?? false; | ||||
|   | ||||
| @@ -23,7 +23,6 @@ import 'package:island/widgets/safety/abuse_report_helper.dart'; | ||||
| import 'package:island/widgets/share/share_sheet.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:path_provider/path_provider.dart' show getTemporaryDirectory; | ||||
| import 'package:relative_time/relative_time.dart'; | ||||
| import 'package:screenshot/screenshot.dart'; | ||||
| import 'package:share_plus/share_plus.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| @@ -103,13 +102,13 @@ class PostActionableItem extends HookConsumerWidget { | ||||
|                 textDirection: TextDirection.ltr, | ||||
|                 child: SizedBox( | ||||
|                   width: 520, | ||||
|                   height: 640, | ||||
|                   child: PostItemScreenshot(item: item, isFullPost: isFullPost), | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|             context: context, | ||||
|             pixelRatio: MediaQuery.of(context).devicePixelRatio, | ||||
|             delay: const Duration(seconds: 1), | ||||
|           ) | ||||
|           .then((Uint8List? image) async { | ||||
|             if (image == null) return; | ||||
| @@ -468,7 +467,8 @@ class PostItem extends HookConsumerWidget { | ||||
|           translationSection: translationSection, | ||||
|           renderingPadding: renderingPadding, | ||||
|         ), | ||||
|         if (isShowReference) ReferencedPostWidget(item: item), | ||||
|         if (isShowReference) | ||||
|           ReferencedPostWidget(item: item, renderingPadding: renderingPadding), | ||||
|         if (item.repliesCount > 0 && isEmbedReply) | ||||
|           PostReplyPreview( | ||||
|             parent: item, | ||||
|   | ||||
| @@ -1,9 +1,12 @@ | ||||
| import 'package:collection/collection.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/post.dart'; | ||||
| import 'package:island/widgets/post/post_shared.dart'; | ||||
| import 'package:qr_flutter/qr_flutter.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| class PostItemScreenshot extends ConsumerWidget { | ||||
|   final SnPost item; | ||||
| @@ -31,15 +34,22 @@ class PostItemScreenshot extends ConsumerWidget { | ||||
|                 .map((e) => e.key) | ||||
|                 .last; | ||||
|  | ||||
|     return Column( | ||||
|     final isDark = MediaQuery.of(context).platformBrightness == Brightness.dark; | ||||
|  | ||||
|     return Material( | ||||
|       elevation: 0, | ||||
|       color: Theme.of(context).colorScheme.surface, | ||||
|       child: Column( | ||||
|         mainAxisSize: MainAxisSize.min, | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           Gap(renderingPadding.vertical), | ||||
|           PostHeader( | ||||
|             item: item, | ||||
|             isFullPost: isFullPost, | ||||
|             isInteractive: false, | ||||
|             renderingPadding: renderingPadding, | ||||
|             isRelativeTime: false, | ||||
|             trailing: | ||||
|                 mostReaction != null | ||||
|                     ? Row( | ||||
| @@ -65,8 +75,61 @@ class PostItemScreenshot extends ConsumerWidget { | ||||
|             isInteractive: false, | ||||
|           ), | ||||
|           if (isShowReference) | ||||
|           ReferencedPostWidget(item: item, isInteractive: false), | ||||
|             ReferencedPostWidget( | ||||
|               item: item, | ||||
|               isInteractive: false, | ||||
|               renderingPadding: renderingPadding, | ||||
|             ), | ||||
|           Container( | ||||
|             color: Theme.of(context).colorScheme.surfaceContainerLow, | ||||
|             margin: const EdgeInsets.only(top: 8), | ||||
|             padding: EdgeInsets.symmetric( | ||||
|               horizontal: renderingPadding.horizontal, | ||||
|               vertical: 4, | ||||
|             ), | ||||
|             child: Row( | ||||
|               children: [ | ||||
|                 SizedBox( | ||||
|                   width: 44, | ||||
|                   height: 44, | ||||
|                   child: Image.asset( | ||||
|                     'assets/icons/icon${isDark ? '-dark' : ''}.png', | ||||
|                     width: 40, | ||||
|                     height: 40, | ||||
|                   ), | ||||
|                 ).padding(vertical: 8, right: 12), | ||||
|                 Expanded( | ||||
|                   child: Column( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     children: [ | ||||
|                       const Text( | ||||
|                         'Solar Network', | ||||
|                         style: TextStyle( | ||||
|                           fontSize: 14, | ||||
|                           fontWeight: FontWeight.bold, | ||||
|                         ), | ||||
|                       ), | ||||
|                       const Text( | ||||
|                         'sharePostSlogan', | ||||
|                         style: TextStyle(fontSize: 12), | ||||
|                       ).tr().opacity(0.9), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|                 QrImageView( | ||||
|                   data: 'https://solian.app/posts/${item.id}', | ||||
|                   version: QrVersions.auto, | ||||
|                   size: 60, | ||||
|                   errorCorrectionLevel: QrErrorCorrectLevel.M, | ||||
|                   backgroundColor: Colors.transparent, | ||||
|                   foregroundColor: Theme.of(context).colorScheme.onSurface, | ||||
|                   padding: const EdgeInsets.all(8), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -348,11 +348,13 @@ class PostTruncateHint extends StatelessWidget { | ||||
| class ReferencedPostWidget extends StatelessWidget { | ||||
|   final SnPost item; | ||||
|   final bool isInteractive; | ||||
|   final EdgeInsets renderingPadding; | ||||
|  | ||||
|   const ReferencedPostWidget({ | ||||
|     super.key, | ||||
|     required this.item, | ||||
|     this.isInteractive = true, | ||||
|     this.renderingPadding = EdgeInsets.zero, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
| @@ -363,8 +365,15 @@ class ReferencedPostWidget extends StatelessWidget { | ||||
|     final isReply = item.repliedPost != null; | ||||
|  | ||||
|     final content = Container( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), | ||||
|       margin: const EdgeInsets.only(top: 8), | ||||
|       padding: EdgeInsets.symmetric( | ||||
|         horizontal: renderingPadding.horizontal, | ||||
|         vertical: 8, | ||||
|       ), | ||||
|       margin: EdgeInsets.only( | ||||
|         top: 8, | ||||
|         left: renderingPadding.vertical, | ||||
|         right: renderingPadding.vertical, | ||||
|       ), | ||||
|       decoration: BoxDecoration( | ||||
|         color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.5), | ||||
|         borderRadius: BorderRadius.circular(12), | ||||
| @@ -522,6 +531,7 @@ class PostHeader extends StatelessWidget { | ||||
|   final Widget? trailing; | ||||
|   final bool isInteractive; | ||||
|   final EdgeInsets renderingPadding; | ||||
|   final bool isRelativeTime; | ||||
|  | ||||
|   const PostHeader({ | ||||
|     super.key, | ||||
| @@ -530,6 +540,7 @@ class PostHeader extends StatelessWidget { | ||||
|     this.trailing, | ||||
|     this.isInteractive = true, | ||||
|     this.renderingPadding = EdgeInsets.zero, | ||||
|     this.isRelativeTime = true, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
| @@ -569,15 +580,21 @@ class PostHeader extends StatelessWidget { | ||||
|                 crossAxisAlignment: CrossAxisAlignment.end, | ||||
|                 children: [ | ||||
|                   Text( | ||||
|                     isFullPost | ||||
|                         ? (item.publishedAt ?? item.createdAt)!.formatSystem() | ||||
|                         : (item.publishedAt ?? item.createdAt)!.formatRelative( | ||||
|                     !isFullPost && isRelativeTime | ||||
|                         ? (item.publishedAt ?? item.createdAt)!.formatRelative( | ||||
|                           context, | ||||
|                         ), | ||||
|                         ) | ||||
|                         : (item.publishedAt ?? item.createdAt)!.formatSystem(), | ||||
|                   ).fontSize(10), | ||||
|                   if (item.editedAt != null) | ||||
|                     Text( | ||||
|                       'editedAt'.tr(args: [item.editedAt!.formatSystem()]), | ||||
|                       'editedAt'.tr( | ||||
|                         args: [ | ||||
|                           !isFullPost && isRelativeTime | ||||
|                               ? item.editedAt!.formatRelative(context) | ||||
|                               : item.editedAt!.formatSystem(), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ).fontSize(10), | ||||
|                   if (item.visibility != 0) | ||||
|                     Text( | ||||
| @@ -711,6 +728,7 @@ class PostBody extends ConsumerWidget { | ||||
|         if (item.attachments.isNotEmpty && item.type != 1) | ||||
|           CloudFileList( | ||||
|             files: item.attachments, | ||||
|             isColumn: !isInteractive, | ||||
|             padding: EdgeInsets.symmetric( | ||||
|               horizontal: renderingPadding.horizontal, | ||||
|               vertical: 4, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user