From ecef8dab0ca512c62ccea1475af53f8f31d45988 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 1 Aug 2024 01:21:27 +0800 Subject: [PATCH] :zap: Fix post list ui jank --- devtools_options.yaml | 1 + lib/bootstrapper.dart | 8 ++ lib/main.dart | 2 +- lib/screens/account/profile_page.dart | 4 +- lib/screens/feed/search.dart | 4 +- lib/screens/home.dart | 4 +- lib/theme.dart | 4 +- lib/widgets/markdown_text_content.dart | 4 +- lib/widgets/posts/post_item.dart | 2 +- lib/widgets/posts/post_list.dart | 2 + lib/widgets/posts/post_quick_action.dart | 106 +++++++++--------- .../post_warped_list.dart} | 5 +- pubspec.yaml | 2 +- 13 files changed, 81 insertions(+), 67 deletions(-) rename lib/widgets/{feed/feed_list.dart => posts/post_warped_list.dart} (91%) diff --git a/devtools_options.yaml b/devtools_options.yaml index fa0b357..2bc8e05 100644 --- a/devtools_options.yaml +++ b/devtools_options.yaml @@ -1,3 +1,4 @@ description: This file stores settings for Dart & Flutter DevTools. documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states extensions: + - provider: true \ No newline at end of file diff --git a/lib/bootstrapper.dart b/lib/bootstrapper.dart index e1dac38..038bb57 100644 --- a/lib/bootstrapper.dart +++ b/lib/bootstrapper.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:get/get.dart'; +import 'package:provider/provider.dart'; import 'package:solian/exts.dart'; import 'package:solian/providers/auth.dart'; import 'package:solian/providers/content/channel.dart'; import 'package:solian/providers/relation.dart'; +import 'package:solian/providers/theme_switcher.dart'; import 'package:solian/providers/websocket.dart'; import 'package:solian/services.dart'; import 'package:solian/widgets/sized_container.dart'; @@ -29,6 +31,12 @@ class _BootstrapperShellState extends State { int _periodCursor = 0; late final List<({String label, Future Function() action})> _periods = [ + ( + label: 'bsLoadingTheme', + action: () async { + await context.read().restoreTheme(); + }, + ), ( label: 'bsCheckingServer', action: () async { diff --git a/lib/main.dart b/lib/main.dart index 546bfff..749f018 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -76,7 +76,7 @@ Future _initializePlatformComponents() async { final themeSwitcher = ThemeSwitcher( lightThemeData: SolianTheme.build(Brightness.light), darkThemeData: SolianTheme.build(Brightness.dark), -)..restoreTheme(); +); class SolianApp extends StatelessWidget { const SolianApp({super.key}); diff --git a/lib/screens/account/profile_page.dart b/lib/screens/account/profile_page.dart index 4beef5a..4b6f639 100644 --- a/lib/screens/account/profile_page.dart +++ b/lib/screens/account/profile_page.dart @@ -13,8 +13,8 @@ import 'package:solian/theme.dart'; import 'package:solian/widgets/account/account_avatar.dart'; import 'package:solian/widgets/app_bar_leading.dart'; import 'package:solian/widgets/attachments/attachment_list.dart'; -import 'package:solian/widgets/feed/feed_list.dart'; import 'package:solian/widgets/posts/post_list.dart'; +import 'package:solian/widgets/posts/post_warped_list.dart'; import 'package:solian/widgets/sized_container.dart'; class AccountProfilePage extends StatefulWidget { @@ -292,7 +292,7 @@ class _AccountProfilePageState extends State { child: Center(child: CircularProgressIndicator()), ), if (_userinfo != null) - FeedListWidget( + PostWarpedListWidget( isPinned: false, controller: _postController.pagingController, ), diff --git a/lib/screens/feed/search.dart b/lib/screens/feed/search.dart index 5ec96cc..729f94a 100644 --- a/lib/screens/feed/search.dart +++ b/lib/screens/feed/search.dart @@ -3,7 +3,7 @@ import 'package:get/get.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:solian/models/pagination.dart'; import 'package:solian/providers/content/posts.dart'; -import 'package:solian/widgets/feed/feed_list.dart'; +import 'package:solian/widgets/posts/post_warped_list.dart'; import '../../models/post.dart'; @@ -77,7 +77,7 @@ class _FeedSearchScreenState extends State { onRefresh: () => Future.sync(() => _pagingController.refresh()), child: CustomScrollView( slivers: [ - FeedListWidget(controller: _pagingController), + PostWarpedListWidget(controller: _pagingController), ], ), ), diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 493e236..e07445b 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -8,8 +8,8 @@ import 'package:solian/theme.dart'; import 'package:solian/widgets/app_bar_title.dart'; import 'package:solian/widgets/current_state_action.dart'; import 'package:solian/widgets/app_bar_leading.dart'; -import 'package:solian/widgets/feed/feed_list.dart'; import 'package:solian/widgets/posts/post_shuffle_swiper.dart'; +import 'package:solian/widgets/posts/post_warped_list.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @@ -95,7 +95,7 @@ class _HomeScreenState extends State RefreshIndicator( onRefresh: () => _postController.reloadAllOver(), child: CustomScrollView(slivers: [ - FeedListWidget( + PostWarpedListWidget( controller: _postController.pagingController, ), ]), diff --git a/lib/theme.dart b/lib/theme.dart index 359519f..3a70764 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -36,11 +36,11 @@ abstract class SolianTheme { seedColor: seedColor ?? const Color.fromRGBO(154, 98, 91, 1), ), fontFamily: 'Comfortaa', - fontFamilyFallback: const [ + fontFamilyFallback: [ 'NotoSansSC', 'NotoSansHK', 'NotoSansJP', - 'NotoSansEmoji' + if (PlatformInfo.isWeb) 'NotoSansEmoji', ], typography: Typography.material2021( colorScheme: brightness == Brightness.light diff --git a/lib/widgets/markdown_text_content.dart b/lib/widgets/markdown_text_content.dart index 198a9eb..3fe9635 100644 --- a/lib/widgets/markdown_text_content.dart +++ b/lib/widgets/markdown_text_content.dart @@ -19,7 +19,9 @@ class MarkdownTextContent extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), data: content, padding: EdgeInsets.zero, - styleSheet: MarkdownStyleSheet.fromTheme(Theme.of(context)).copyWith( + styleSheet: MarkdownStyleSheet.fromTheme( + Theme.of(context), + ).copyWith( horizontalRuleDecoration: BoxDecoration( border: Border( top: BorderSide( diff --git a/lib/widgets/posts/post_item.dart b/lib/widgets/posts/post_item.dart index 466988e..7837a67 100644 --- a/lib/widgets/posts/post_item.dart +++ b/lib/widgets/posts/post_item.dart @@ -325,7 +325,7 @@ class _PostItemState extends State { _buildFooter().paddingOnly(left: 12), ], ), - ) + ), ], ).paddingOnly( top: 10, diff --git a/lib/widgets/posts/post_list.dart b/lib/widgets/posts/post_list.dart index 90f5a1e..9c4d929 100644 --- a/lib/widgets/posts/post_list.dart +++ b/lib/widgets/posts/post_list.dart @@ -48,6 +48,7 @@ class PostListWidget extends StatelessWidget { } class PostListEntryWidget extends StatelessWidget { + final int renderOrder; final bool isShowEmbed; final bool isNestedClickable; final bool isClickable; @@ -56,6 +57,7 @@ class PostListEntryWidget extends StatelessWidget { const PostListEntryWidget({ super.key, + this.renderOrder = 0, required this.isShowEmbed, required this.isNestedClickable, required this.isClickable, diff --git a/lib/widgets/posts/post_quick_action.dart b/lib/widgets/posts/post_quick_action.dart index 91c7747..ff9d7c0 100644 --- a/lib/widgets/posts/post_quick_action.dart +++ b/lib/widgets/posts/post_quick_action.dart @@ -85,65 +85,65 @@ class _PostQuickActionState extends State { Widget build(BuildContext context) { const density = VisualDensity(horizontal: -4, vertical: -3); + final reactionEntries = widget.item.metric!.reactionList.entries.toList(); + return SizedBox( height: 32, width: double.infinity, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + child: CustomScrollView( + scrollDirection: Axis.horizontal, + slivers: [ if (widget.isReactable && widget.isShowReply) - ActionChip( - avatar: const Icon(Icons.comment), - label: Text(widget.item.metric!.replyCount.toString()), - visualDensity: density, - onPressed: () { - showModalBottomSheet( - useRootNavigator: true, - context: context, - builder: (context) { - return PostReplyListPopup(item: widget.item); - }, - ); - }, - ), - if (widget.isReactable && widget.isShowReply) - const VerticalDivider( - thickness: 0.3, - width: 0.3, - indent: 8, - endIndent: 8, - ).paddingSymmetric(horizontal: 8), - Expanded( - child: ListView( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - children: [ - ...widget.item.metric!.reactionList.entries.map((x) { - final info = reactions[x.key]; - return Padding( - padding: const EdgeInsets.only(right: 8), - child: ActionChip( - avatar: Text(info!.icon), - label: Text(x.value.toString()), - tooltip: ':${x.key}:', - visualDensity: density, - onPressed: _isSubmitting - ? null - : () => doWidgetReact(x.key, info.attitude), - ), + SliverToBoxAdapter( + child: ActionChip( + avatar: const Icon(Icons.comment), + label: Text(widget.item.metric!.replyCount.toString()), + visualDensity: density, + onPressed: () { + showModalBottomSheet( + useRootNavigator: true, + context: context, + builder: (context) { + return PostReplyListPopup(item: widget.item); + }, ); - }), - if (widget.isReactable) - ActionChip( - avatar: const Icon(Icons.add_reaction, color: Colors.teal), - label: Text('reactAdd'.tr), - visualDensity: density, - onPressed: () => showReactMenu(), - ), - ], + }, + ), + ), + if (widget.isReactable && widget.isShowReply) + SliverToBoxAdapter( + child: const VerticalDivider( + thickness: 0.3, + width: 0.3, + indent: 8, + endIndent: 8, + ).paddingSymmetric(horizontal: 8), + ), + SliverList.builder( + itemCount: reactionEntries.length, + itemBuilder: (context, index) { + final x = reactionEntries[index]; + final info = reactions[x.key]; + return ActionChip( + avatar: Text(info!.icon), + label: Text(x.value.toString()), + tooltip: ':${x.key}:', + visualDensity: density, + onPressed: _isSubmitting + ? null + : () => doWidgetReact(x.key, info.attitude), + ).paddingOnly(right: 8); + }, + ), + if (widget.isReactable) + SliverToBoxAdapter( + child: ActionChip( + avatar: const Icon(Icons.add_reaction, color: Colors.teal), + label: Text('reactAdd'.tr), + visualDensity: density, + onPressed: () => showReactMenu(), + ), ), - ) ], ), ); diff --git a/lib/widgets/feed/feed_list.dart b/lib/widgets/posts/post_warped_list.dart similarity index 91% rename from lib/widgets/feed/feed_list.dart rename to lib/widgets/posts/post_warped_list.dart index 0af8357..a4609cd 100644 --- a/lib/widgets/feed/feed_list.dart +++ b/lib/widgets/posts/post_warped_list.dart @@ -3,14 +3,14 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:solian/models/post.dart'; import 'package:solian/widgets/posts/post_list.dart'; -class FeedListWidget extends StatelessWidget { +class PostWarpedListWidget extends StatelessWidget { final bool isShowEmbed; final bool isClickable; final bool isNestedClickable; final bool isPinned; final PagingController controller; - const FeedListWidget({ + const PostWarpedListWidget({ super.key, required this.controller, this.isShowEmbed = true, @@ -30,6 +30,7 @@ class FeedListWidget extends StatelessWidget { return const SizedBox(); } return PostListEntryWidget( + renderOrder: index, isShowEmbed: isShowEmbed, isNestedClickable: isNestedClickable, isClickable: isClickable, diff --git a/pubspec.yaml b/pubspec.yaml index 4cd9e52..f04607b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: solian description: "The Solar Network App" publish_to: "none" -version: 1.2.0+4 +version: 1.2.0+6 environment: sdk: ">=3.3.4 <4.0.0"