From a5b6ace79b1e07c250c27482cdaca6749fb3bcba Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Fri, 26 Jul 2024 01:16:32 +0800 Subject: [PATCH] :lipstick: Better attachments list styles --- ios/Podfile.lock | 14 +- lib/models/attachment.dart | 12 +- lib/screens/home.dart | 118 +++++++-------- lib/widgets/attachments/attachment_list.dart | 149 ++++++++++++------- lib/widgets/chat/chat_event.dart | 48 ++++-- lib/widgets/chat/chat_event_message.dart | 93 +++++------- lib/widgets/posts/post_item.dart | 36 +++-- lib/widgets/posts/post_list.dart | 4 + lib/widgets/posts/post_shuffle_swiper.dart | 3 + lib/widgets/posts/post_single_display.dart | 18 ++- 10 files changed, 278 insertions(+), 217 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 011079b..7eee836 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -107,7 +107,7 @@ PODS: - GoogleUtilities/Privacy - image_picker_ios (0.0.1): - Flutter - - livekit_client (2.2.1): + - livekit_client (2.2.2): - Flutter - WebRTC-SDK (= 125.6422.04) - media_kit_libs_ios_video (1.0.4): @@ -138,11 +138,11 @@ PODS: - SDWebImage (5.19.4): - SDWebImage/Core (= 5.19.4) - SDWebImage/Core (5.19.4) - - Sentry/HybridSDK (8.30.1) - - sentry_flutter (8.4.0): + - Sentry/HybridSDK (8.32.0) + - sentry_flutter (8.5.0): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.30.1) + - Sentry/HybridSDK (= 8.32.0) - sqflite (0.0.3): - Flutter - FlutterMacOS @@ -268,7 +268,7 @@ SPEC CHECKSUMS: GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 - livekit_client: 411d387fd6f993851081069afbe7f04a8e974f1b + livekit_client: c767049a635d5b6d43de3273dca3c439b8a6e970 media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e @@ -281,8 +281,8 @@ SPEC CHECKSUMS: protocol_handler_ios: a5db8abc38526ee326988b808be621e5fd568990 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d - Sentry: 514a3ea653886e9a48c6287d8b7bf05ec24bf3be - sentry_flutter: edc037f7af0dc1512d6c33a5c2c7c838bd0d6806 + Sentry: 96ae1dcdf01a644bc3a3b1dc279cecaf48a833fb + sentry_flutter: f1d86adcb93a959bc47a40d8d55059bdf7569bc5 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe diff --git a/lib/models/attachment.dart b/lib/models/attachment.dart index be9807d..87b374c 100644 --- a/lib/models/attachment.dart +++ b/lib/models/attachment.dart @@ -1,10 +1,8 @@ -import 'package:solian/models/account.dart'; - class Attachment { int id; DateTime createdAt; DateTime updatedAt; - dynamic deletedAt; + DateTime? deletedAt; String uuid; int size; String name; @@ -15,7 +13,6 @@ class Attachment { String destination; Map? metadata; bool isMature; - Account account; int accountId; Attachment({ @@ -33,7 +30,6 @@ class Attachment { required this.destination, required this.metadata, required this.isMature, - required this.account, required this.accountId, }); @@ -41,7 +37,7 @@ class Attachment { id: json['id'], createdAt: DateTime.parse(json['created_at']), updatedAt: DateTime.parse(json['updated_at']), - deletedAt: json['deleted_at'], + deletedAt: json['deleted_at'] != null ? DateTime.parse(json['deleted_at']) : null, uuid: json['uuid'], size: json['size'], name: json['name'], @@ -52,7 +48,6 @@ class Attachment { destination: json['destination'], metadata: json['metadata'], isMature: json['is_mature'], - account: Account.fromJson(json['account']), accountId: json['account_id'], ); @@ -60,7 +55,7 @@ class Attachment { 'id': id, 'created_at': createdAt.toIso8601String(), 'updated_at': updatedAt.toIso8601String(), - 'deleted_at': deletedAt, + 'deleted_at': deletedAt?.toIso8601String(), 'uuid': uuid, 'size': size, 'name': name, @@ -71,7 +66,6 @@ class Attachment { 'destination': destination, 'metadata': metadata, 'is_mature': isMature, - 'account': account.toJson(), 'account_id': accountId, }; } \ No newline at end of file diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 7e8c169..37df5dd 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -44,70 +44,66 @@ class _HomeScreenState extends State Widget build(BuildContext context) { return Material( color: Theme.of(context).colorScheme.surface, - child: SafeArea( - bottom: false, - child: Scaffold( - floatingActionButton: FloatingActionButton( - child: const Icon(Icons.add), - onPressed: () { - showModalBottomSheet( - useRootNavigator: true, - isScrollControlled: true, - context: context, - builder: (context) => const PostCreatePopup(), - ); - }, - ), - body: NestedScrollView( - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverAppBar( - title: AppBarTitle('home'.tr), - centerTitle: false, - floating: true, - toolbarHeight: SolianTheme.toolbarHeight(context), - leading: AppBarLeadingButton.adaptive(context), - actions: [ - const BackgroundStateWidget(), - const NotificationButton(), - SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, - ), - ], - bottom: TabBar( - controller: _tabController, - tabs: [ - Tab(text: 'postListNews'.tr), - Tab(text: 'postListShuffle'.tr), - ], + child: Scaffold( + floatingActionButton: FloatingActionButton( + child: const Icon(Icons.add), + onPressed: () { + showModalBottomSheet( + useRootNavigator: true, + isScrollControlled: true, + context: context, + builder: (context) => const PostCreatePopup(), + ); + }, + ), + body: NestedScrollView( + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverAppBar( + title: AppBarTitle('home'.tr), + centerTitle: false, + floating: true, + toolbarHeight: SolianTheme.toolbarHeight(context), + leading: AppBarLeadingButton.adaptive(context), + actions: [ + const BackgroundStateWidget(), + const NotificationButton(), + SizedBox( + width: SolianTheme.isLargeScreen(context) ? 8 : 16, ), - ) - ]; - }, - body: Obx(() { - if (_postController.isPreparing.isTrue) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - return TabBarView( - physics: const NeverScrollableScrollPhysics(), - controller: _tabController, - children: [ - RefreshIndicator( - onRefresh: () => _postController.reloadAllOver(), - child: CustomScrollView(slivers: [ - FeedListWidget( - controller: _postController.pagingController), - ]), - ), - PostShuffleSwiper(controller: _postController), ], + bottom: TabBar( + controller: _tabController, + tabs: [ + Tab(text: 'postListNews'.tr), + Tab(text: 'postListShuffle'.tr), + ], + ), + ) + ]; + }, + body: Obx(() { + if (_postController.isPreparing.isTrue) { + return const Center( + child: CircularProgressIndicator(), ); - }), - ), + } + + return TabBarView( + physics: const NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + RefreshIndicator( + onRefresh: () => _postController.reloadAllOver(), + child: CustomScrollView(slivers: [ + FeedListWidget( + controller: _postController.pagingController), + ]), + ), + PostShuffleSwiper(controller: _postController), + ], + ); + }), ), ), ); diff --git a/lib/widgets/attachments/attachment_list.dart b/lib/widgets/attachments/attachment_list.dart index fb8b543..2d5a186 100644 --- a/lib/widgets/attachments/attachment_list.dart +++ b/lib/widgets/attachments/attachment_list.dart @@ -1,3 +1,4 @@ +import 'dart:math' show min; import 'dart:ui'; import 'package:carousel_slider/carousel_slider.dart'; @@ -11,7 +12,7 @@ import 'package:solian/widgets/attachments/attachment_list_fullscreen.dart'; class AttachmentList extends StatefulWidget { final String parentId; final List attachmentsId; - final bool divided; + final bool isGrid; final double? width; final double? viewport; @@ -20,7 +21,7 @@ class AttachmentList extends StatefulWidget { super.key, required this.parentId, required this.attachmentsId, - this.divided = false, + this.isGrid = false, this.width, this.viewport, }); @@ -101,12 +102,43 @@ class _AttachmentListState extends State { } } - Widget buildEntry(Attachment element, int idx) { + Widget _buildEntry(Attachment? element, int idx) { + if (element == null) { + return Center( + child: Container( + constraints: const BoxConstraints(maxWidth: 280), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.close, size: 32), + const SizedBox(height: 8), + Text( + 'attachmentLoadFailed'.tr, + style: + const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), + ), + Text( + 'attachmentLoadFailedCaption'.tr, + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + } + return GestureDetector( child: Container( width: widget.width ?? MediaQuery.of(context).size.width, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHigh, + border: widget.attachmentsId.length > 1 + ? Border.symmetric( + vertical: BorderSide( + width: 0.3, + color: Theme.of(context).dividerColor, + ), + ) + : null, ), child: Stack( fit: StackFit.expand, @@ -115,7 +147,7 @@ class _AttachmentListState extends State { parentId: widget.parentId, key: Key('a${element.uuid}'), item: element, - badge: _attachmentsMeta.length > 1 + badge: _attachmentsMeta.length > 1 && !widget.isGrid ? '${idx + 1}/${_attachmentsMeta.length}' : null, showHideButton: !element.isMature || _showMature, @@ -139,15 +171,19 @@ class _AttachmentListState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.visibility_off, - color: Colors.white, size: 32), + const Icon( + Icons.visibility_off, + color: Colors.white, + size: 32, + ), const SizedBox(height: 8), Text( 'matureContent'.tr, style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16, + ), ), Text( 'matureContentCaption'.tr, @@ -193,62 +229,65 @@ class _AttachmentListState extends State { if (_isLoading) { return Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHigh), + color: Theme.of(context).colorScheme.surfaceContainerHigh, + ), child: const LinearProgressIndicator(), ); } - return CarouselSlider.builder( - options: CarouselOptions( - aspectRatio: _aspectRatio, - viewportFraction: widget.viewport ?? (widget.divided ? 0.9 : 1), - enableInfiniteScroll: false, - ), - itemCount: _attachmentsMeta.length, - itemBuilder: (context, idx, _) { - final element = _attachmentsMeta[idx]; - - if (element == null) { - return Center( - child: Container( - constraints: const BoxConstraints(maxWidth: 280), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.close, size: 32), - const SizedBox(height: 8), - Text( - 'attachmentLoadFailed'.tr, - style: const TextStyle( - fontWeight: FontWeight.bold, fontSize: 16), - ), - Text( - 'attachmentLoadFailedCaption'.tr, - textAlign: TextAlign.center, - ), - ], - ), - ), - ); - } - - if (widget.divided) { - const radius = BorderRadius.all(Radius.circular(16)); + if (widget.isGrid) { + const radius = BorderRadius.all(Radius.circular(8)); + return GridView.builder( + padding: EdgeInsets.zero, + primary: false, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: min(3, widget.attachmentsId.length), + mainAxisSpacing: 8.0, + crossAxisSpacing: 8.0, + ), + itemCount: widget.attachmentsId.length, + itemBuilder: (context, idx) { + final element = _attachmentsMeta[idx]; return Container( decoration: BoxDecoration( border: - Border.all(color: Theme.of(context).dividerColor, width: 1), + Border.all(color: Theme.of(context).dividerColor, width: 1), borderRadius: radius, ), child: ClipRRect( borderRadius: radius, - child: buildEntry(element, idx), - ), - ).paddingSymmetric(horizontal: widget.divided ? 4 : 0); - } else { - return buildEntry(element, idx); - } - }, + child: _buildEntry(element, idx), + ) + ); + }, + ).paddingSymmetric(horizontal: 24); + } + + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + border: Border.symmetric( + horizontal: BorderSide( + width: 0.3, + color: Theme.of(context).dividerColor, + ), + ), + ), + child: CarouselSlider.builder( + options: CarouselOptions( + aspectRatio: _aspectRatio, + viewportFraction: + widget.viewport ?? (widget.attachmentsId.length > 1 ? 0.95 : 1), + enableInfiniteScroll: false, + ), + itemCount: _attachmentsMeta.length, + itemBuilder: (context, idx, _) { + final element = _attachmentsMeta[idx]; + return _buildEntry(element, idx); + }, + ), ); } } diff --git a/lib/widgets/chat/chat_event.dart b/lib/widgets/chat/chat_event.dart index 18602ab..7c7049b 100644 --- a/lib/widgets/chat/chat_event.dart +++ b/lib/widgets/chat/chat_event.dart @@ -5,6 +5,7 @@ import 'package:solian/controllers/chat_events_controller.dart'; import 'package:solian/models/event.dart'; import 'package:solian/widgets/account/account_avatar.dart'; import 'package:solian/widgets/account/account_profile_popup.dart'; +import 'package:solian/widgets/attachments/attachment_list.dart'; import 'package:solian/widgets/chat/chat_event_action_log.dart'; import 'package:solian/widgets/chat/chat_event_message.dart'; import 'package:timeago/timeago.dart' show format; @@ -36,7 +37,30 @@ class ChatEvent extends StatelessWidget { return '$negativeSign${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds'; } - Widget buildQuote() { + Widget _buildAttachment(BuildContext context) { + final attachments = item.body['attachments'] != null + ? List.from(item.body['attachments'].map((x) => x)) + : List.empty(); + + if (attachments.isEmpty) return const SizedBox(); + + return Container( + key: Key('m${item.uuid}attachments-box'), + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.only(top: isMerged ? 0 : 4), + constraints: const BoxConstraints( + maxHeight: 720, + ), + child: AttachmentList( + key: Key('m${item.uuid}attachments'), + parentId: item.uuid, + attachmentsId: attachments, + viewport: 1, + ), + ); + } + + Widget _buildQuote() { return FutureBuilder( future: chatController!.getEvent( item.body['quote_event'], @@ -55,7 +79,7 @@ class ChatEvent extends StatelessWidget { ); } - Widget buildContent() { + Widget _buildContent() { switch (item.type) { case 'messages.new': return ChatEventMessage( @@ -121,17 +145,17 @@ class ChatEvent extends StatelessWidget { } } - Widget buildBody(BuildContext context) { + Widget _buildBody(BuildContext context) { if (isContentPreviewing || (isMerged && !isQuote)) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (item.body['quote_event'] != null && chatController != null) - buildQuote(), + _buildQuote(), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Expanded(child: buildContent()), + Expanded(child: _buildContent()), if (item.isPending) const SizedBox( width: 12, @@ -139,9 +163,10 @@ class ChatEvent extends StatelessWidget { child: CircularProgressIndicator(strokeWidth: 2), ), ], - ), + ).paddingOnly(right: 12), + _buildAttachment(context), ], - ).paddingOnly(right: 12); + ); } else if (isQuote) { return Card( child: Row( @@ -170,7 +195,7 @@ class ChatEvent extends StatelessWidget { Text(format(item.createdAt, locale: 'en_short')), ], ), - buildContent().paddingOnly(left: 0.5), + _buildContent().paddingOnly(left: 0.5), ], ), ), @@ -214,11 +239,11 @@ class ChatEvent extends StatelessWidget { ).paddingSymmetric(horizontal: 12), if (item.body['quote_event'] != null && chatController != null) - buildQuote(), + _buildQuote(), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Expanded(child: buildContent()), + Expanded(child: _buildContent()), if (item.isPending) const SizedBox( width: 12, @@ -232,6 +257,7 @@ class ChatEvent extends StatelessWidget { ), ], ).paddingSymmetric(horizontal: 12), + _buildAttachment(context), ], ); } @@ -239,6 +265,6 @@ class ChatEvent extends StatelessWidget { @override Widget build(BuildContext context) { - return buildBody(context); + return _buildBody(context); } } diff --git a/lib/widgets/chat/chat_event_message.dart b/lib/widgets/chat/chat_event_message.dart index 7530ea8..2fdbdaa 100644 --- a/lib/widgets/chat/chat_event_message.dart +++ b/lib/widgets/chat/chat_event_message.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:solian/models/event.dart'; -import 'package:solian/widgets/attachments/attachment_list.dart'; import 'package:solian/widgets/markdown_text_content.dart'; class ChatEventMessage extends StatelessWidget { @@ -20,66 +19,52 @@ class ChatEventMessage extends StatelessWidget { this.isQuote = false, }); - Widget buildAttachment(BuildContext context) { - final body = EventMessageBody.fromJson(item.body); - - return Container( - key: Key('m${item.uuid}attachments-box'), - width: MediaQuery.of(context).size.width, - constraints: const BoxConstraints( - maxHeight: 720, - maxWidth: 640, - ), - child: AttachmentList( - key: Key('m${item.uuid}attachments'), - parentId: item.uuid, - attachmentsId: body.attachments ?? List.empty(), - divided: true, - viewport: 1, - ), - ); - } - - Widget buildContent() { + Widget _buildContent(BuildContext context) { final body = EventMessageBody.fromJson(item.body); final hasAttachment = body.attachments?.isNotEmpty ?? false; - return MarkdownTextContent(content: body.text).paddingOnly( + if (body.text.isEmpty && hasAttachment) { + final unFocusColor = Theme.of(context).colorScheme.onSurface.withOpacity(0.75); + return Row( + children: [ + Icon( + Icons.attachment, + size: 18, + color: unFocusColor, + ).paddingOnly(right: 6), + Text( + 'postAttachmentTip'.trParams( + {'count': body.attachments?.length.toString() ?? 0.toString()}, + ), + style: TextStyle(color: unFocusColor), + ) + ], + ); + } + + return MarkdownTextContent(content: body.text); + } + + Widget _buildBody(BuildContext context) { + if (isContentPreviewing) { + return _buildContent(context); + } else if (isMerged) { + return _buildContent(context).paddingOnly(left: 52); + } else { + return _buildContent(context); + } + } + + @override + Widget build(BuildContext context) { + final body = EventMessageBody.fromJson(item.body); + final hasAttachment = body.attachments?.isNotEmpty ?? false; + + return _buildBody(context).paddingOnly( left: isQuote ? 0 : 12, right: isQuote ? 0 : 12, top: body.quoteEvent == null ? 2 : 0, bottom: hasAttachment ? 4 : (isHasMerged ? 2 : 0), ); } - - Widget buildBody(BuildContext context) { - final body = EventMessageBody.fromJson(item.body); - - if (isContentPreviewing) { - return buildContent(); - } else if (isMerged) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildContent().paddingOnly(left: 52), - if (body.attachments?.isNotEmpty ?? false) - buildAttachment(context).paddingOnly(left: 52, bottom: 4), - ], - ); - } else { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildContent(), - if (body.attachments?.isNotEmpty ?? false) - buildAttachment(context).paddingOnly(bottom: 4), - ], - ); - } - } - - @override - Widget build(BuildContext context) { - return buildBody(context); - } } diff --git a/lib/widgets/posts/post_item.dart b/lib/widgets/posts/post_item.dart index f41fffa..5c4bae6 100644 --- a/lib/widgets/posts/post_item.dart +++ b/lib/widgets/posts/post_item.dart @@ -52,15 +52,21 @@ class _PostItemState extends State { super.initState(); } - Widget buildDate() { + Widget _buildDate() { if (widget.isFullDate) { - return Text(DateFormat('y/M/d H:m').format(item.createdAt.toLocal())); + return Text(DateFormat('y/M/d H:m') + .format(item.publishedAt?.toLocal() ?? DateTime.now())); } else { - return Text(format(item.createdAt.toLocal(), locale: 'en_short')); + return Text( + format( + item.publishedAt?.toLocal() ?? DateTime.now(), + locale: 'en_short', + ), + ); } } - Widget buildHeader() { + Widget _buildHeader() { return Row( children: [ if (widget.isCompact) @@ -72,12 +78,12 @@ class _PostItemState extends State { item.author.nick, style: const TextStyle(fontWeight: FontWeight.bold), ).paddingOnly(left: widget.isCompact ? 6 : 12), - buildDate().paddingOnly(left: 4), + _buildDate().paddingOnly(left: 4), ], ); } - Widget buildFooter() { + Widget _buildFooter() { List labels = List.empty(growable: true); if (widget.item.createdAt != widget.item.updatedAt) { labels.add('postEdited'.trParams({ @@ -116,7 +122,7 @@ class _PostItemState extends State { } } - Widget buildReply(BuildContext context) { + Widget _buildReply(BuildContext context) { return Column( children: [ Row( @@ -148,7 +154,7 @@ class _PostItemState extends State { ); } - Widget buildRepost(BuildContext context) { + Widget _buildRepost(BuildContext context) { return Column( children: [ Row( @@ -191,7 +197,7 @@ class _PostItemState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildHeader().paddingSymmetric(horizontal: 12), + _buildHeader().paddingSymmetric(horizontal: 12), MarkdownTextContent( content: item.body['content'], isSelectable: widget.isContentSelectable, @@ -201,7 +207,7 @@ class _PostItemState extends State { top: 2, bottom: hasAttachment ? 4 : 0, ), - buildFooter().paddingOnly(left: 16), + _buildFooter().paddingOnly(left: 16), if (attachments.isNotEmpty) Row( children: [ @@ -246,14 +252,14 @@ class _PostItemState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildHeader(), + _buildHeader(), MarkdownTextContent( content: item.body['content'], isSelectable: widget.isContentSelectable, ).paddingOnly(left: 12, right: 8), if (widget.item.replyTo != null && widget.isShowEmbed) GestureDetector( - child: buildReply(context).paddingOnly(top: 4), + child: _buildReply(context).paddingOnly(top: 4), onTap: () { if (!widget.isClickable) return; AppRouter.instance.pushNamed( @@ -266,7 +272,7 @@ class _PostItemState extends State { ), if (widget.item.repostTo != null && widget.isShowEmbed) GestureDetector( - child: buildRepost(context).paddingOnly(top: 4), + child: _buildRepost(context).paddingOnly(top: 4), onTap: () { if (!widget.isClickable) return; AppRouter.instance.pushNamed( @@ -277,7 +283,7 @@ class _PostItemState extends State { ); }, ), - buildFooter().paddingOnly(left: 12), + _buildFooter().paddingOnly(left: 12), ], ), ) @@ -297,7 +303,7 @@ class _PostItemState extends State { child: AttachmentList( parentId: widget.item.id.toString(), attachmentsId: attachments, - divided: true, + isGrid: attachments.length > 1, ), ), if (widget.isShowReply && widget.isReactable) diff --git a/lib/widgets/posts/post_list.dart b/lib/widgets/posts/post_list.dart index 63e8279..90f5a1e 100644 --- a/lib/widgets/posts/post_list.dart +++ b/lib/widgets/posts/post_list.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:solian/models/post.dart'; +import 'package:solian/providers/auth.dart'; import 'package:solian/router.dart'; import 'package:solian/widgets/sized_container.dart'; import 'package:solian/widgets/posts/post_action.dart'; @@ -79,6 +80,9 @@ class PostListEntryWidget extends StatelessWidget { ); }, onLongPress: () { + final AuthProvider auth = Get.find(); + if (auth.isAuthorized.isFalse) return; + showModalBottomSheet( useRootNavigator: true, context: context, diff --git a/lib/widgets/posts/post_shuffle_swiper.dart b/lib/widgets/posts/post_shuffle_swiper.dart index 3f62f37..f50605a 100644 --- a/lib/widgets/posts/post_shuffle_swiper.dart +++ b/lib/widgets/posts/post_shuffle_swiper.dart @@ -40,6 +40,9 @@ class _PostShuffleSwiperState extends State { return PostSingleDisplay( key: Key('p${element.id}'), item: element, + onUpdate: () { + widget.controller.reloadAllOver(); + }, ); }, padding: const EdgeInsets.all(24), diff --git a/lib/widgets/posts/post_single_display.dart b/lib/widgets/posts/post_single_display.dart index 2300a78..db6055f 100644 --- a/lib/widgets/posts/post_single_display.dart +++ b/lib/widgets/posts/post_single_display.dart @@ -1,12 +1,16 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; import 'package:solian/models/post.dart'; -import 'package:solian/widgets/posts/post_item.dart'; +import 'package:solian/widgets/posts/post_list.dart'; class PostSingleDisplay extends StatelessWidget { final Post item; + final Function onUpdate; - const PostSingleDisplay({super.key, required this.item}); + const PostSingleDisplay({ + super.key, + required this.item, + required this.onUpdate, + }); @override Widget build(BuildContext context) { @@ -14,9 +18,13 @@ class PostSingleDisplay extends StatelessWidget { alignment: Alignment.center, child: Card( child: SingleChildScrollView( - child: PostItem( + child: PostListEntryWidget( item: item, - ).paddingSymmetric(horizontal: 10, vertical: 16), + isClickable: true, + isShowEmbed: true, + isNestedClickable: true, + onUpdate: onUpdate, + ), ), ), );