✨ Better post list
This commit is contained in:
		| @@ -40,20 +40,12 @@ abstract class AppRouter { | ||||
|   ); | ||||
|  | ||||
|   static final ShellRoute _feedRoute = ShellRoute( | ||||
|     builder: (context, state, child) => BasicShell( | ||||
|       state: state, | ||||
|       sidebarFirst: true, | ||||
|       showAppBar: false, | ||||
|       sidebar: const FeedScreen(), | ||||
|       child: child, | ||||
|     ), | ||||
|     builder: (context, state, child) => child, | ||||
|     routes: [ | ||||
|       GoRoute( | ||||
|         path: '/', | ||||
|         name: 'feed', | ||||
|         builder: (context, state) => SolianTheme.isExtraLargeScreen(context) | ||||
|             ? const EmptyPagePlaceholder() | ||||
|             : const FeedScreen(), | ||||
|         builder: (context, state) => const FeedScreen(), | ||||
|       ), | ||||
|       GoRoute( | ||||
|         path: '/posts/view/:alias', | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import 'package:get/get.dart'; | ||||
| import 'package:solian/exts.dart'; | ||||
| import 'package:solian/models/post.dart'; | ||||
| import 'package:solian/providers/content/post.dart'; | ||||
| import 'package:solian/widgets/centered_container.dart'; | ||||
| import 'package:solian/widgets/posts/post_item.dart'; | ||||
| import 'package:solian/widgets/posts/post_replies.dart'; | ||||
|  | ||||
| @@ -47,21 +48,29 @@ class _PostDetailScreenState extends State<PostDetailScreen> { | ||||
|           return CustomScrollView( | ||||
|             slivers: [ | ||||
|               SliverToBoxAdapter( | ||||
|                 child: PostItem( | ||||
|                   item: item!, | ||||
|                   isClickable: true, | ||||
|                   isFullDate: true, | ||||
|                   isShowReply: false, | ||||
|                 child: CenteredContainer( | ||||
|                   child: PostItem( | ||||
|                     item: item!, | ||||
|                     isClickable: true, | ||||
|                     isFullDate: true, | ||||
|                     isShowReply: false, | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|               const SliverToBoxAdapter( | ||||
|                 child: Divider(thickness: 0.3, height: 0.3), | ||||
|               SliverToBoxAdapter( | ||||
|                 child: const Divider(thickness: 0.3, height: 1) | ||||
|                     .paddingOnly(top: 4), | ||||
|               ), | ||||
|               SliverToBoxAdapter( | ||||
|                 child: Text( | ||||
|                   'postReplies'.tr, | ||||
|                   style: Theme.of(context).textTheme.headlineSmall, | ||||
|                 ).paddingOnly(left: 24, right: 24, top: 16), | ||||
|                 child: CenteredContainer( | ||||
|                   child: Align( | ||||
|                     alignment: Alignment.centerLeft, | ||||
|                     child: Text( | ||||
|                       'postReplies'.tr, | ||||
|                       style: Theme.of(context).textTheme.headlineSmall, | ||||
|                     ).paddingOnly(left: 24, right: 24, top: 16), | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|               PostReplyList(item: item!), | ||||
|               SliverToBoxAdapter( | ||||
|   | ||||
							
								
								
									
										43
									
								
								lib/shells/centered_shell.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								lib/shells/centered_shell.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:get/get.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| import 'package:solian/router.dart'; | ||||
| import 'package:solian/theme.dart'; | ||||
| import 'package:solian/widgets/app_bar_title.dart'; | ||||
| import 'package:solian/widgets/prev_page.dart'; | ||||
|  | ||||
| class CenteredShell extends StatelessWidget { | ||||
|   final bool showAppBar; | ||||
|   final GoRouterState state; | ||||
|   final Widget child; | ||||
|  | ||||
|   const CenteredShell({ | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     required this.state, | ||||
|     this.showAppBar = true, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final canPop = AppRouter.instance.canPop(); | ||||
|  | ||||
|     return Scaffold( | ||||
|       appBar: showAppBar | ||||
|           ? AppBar( | ||||
|               title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr), | ||||
|               centerTitle: false, | ||||
|               toolbarHeight: SolianTheme.toolbarHeight(context), | ||||
|               leading: canPop ? const PrevPageButton() : null, | ||||
|               automaticallyImplyLeading: false, | ||||
|             ) | ||||
|           : null, | ||||
|       body: Center( | ||||
|         child: Container( | ||||
|           constraints: const BoxConstraints(maxWidth: 640), | ||||
|           child: child, | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -1,89 +0,0 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:get/get.dart'; | ||||
| import 'package:solian/router.dart'; | ||||
| import 'package:solian/theme.dart'; | ||||
| import 'package:solian/widgets/navigation/app_navigation.dart'; | ||||
| import 'package:solian/widgets/prev_page.dart'; | ||||
| import 'package:solian/widgets/navigation/app_navigation_bottom_bar.dart'; | ||||
| import 'package:solian/widgets/navigation/app_navigation_rail.dart'; | ||||
| import 'package:solian/widgets/sidebar/sidebar_placeholder.dart'; | ||||
|  | ||||
| class NavShell extends StatelessWidget { | ||||
|   final bool showAppBar; | ||||
|   final bool showSidebar; | ||||
|   final bool showNavigation; | ||||
|   final bool? showBottomNavigation; | ||||
|   final Widget child; | ||||
|  | ||||
|   final bool sidebarFirst; | ||||
|   final Widget? sidebar; | ||||
|  | ||||
|   const NavShell({ | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     this.showAppBar = true, | ||||
|     this.showSidebar = true, | ||||
|     this.showNavigation = true, | ||||
|     this.showBottomNavigation, | ||||
|     this.sidebarFirst = false, | ||||
|     this.sidebar, | ||||
|   }); | ||||
|  | ||||
|   List<Widget> buildContent(BuildContext context) { | ||||
|     return [ | ||||
|       Flexible( | ||||
|         flex: 2, | ||||
|         child: child, | ||||
|       ), | ||||
|       if (SolianTheme.isExtraLargeScreen(context)) | ||||
|         const VerticalDivider(thickness: 0.3, width: 1), | ||||
|       if (SolianTheme.isExtraLargeScreen(context)) | ||||
|         Flexible( | ||||
|           flex: 1, | ||||
|           child: sidebar ?? const SidebarPlaceholder(), | ||||
|         ), | ||||
|     ]; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final canPop = AppRouter.instance.canPop(); | ||||
|  | ||||
|     final routeName = | ||||
|         AppRouter.instance.routerDelegate.currentConfiguration.last.route.name; | ||||
|     final showBottom = showBottomNavigation ?? | ||||
|         AppNavigation.destinationPages.contains(routeName); | ||||
|  | ||||
|     return Scaffold( | ||||
|       appBar: showAppBar | ||||
|           ? AppBar( | ||||
|               title: Text(routeName ?? 'page'.tr), | ||||
|               centerTitle: false, | ||||
|               titleSpacing: canPop ? null : 24, | ||||
|               elevation: SolianTheme.isLargeScreen(context) ? 1 : 0, | ||||
|               leading: canPop ? const PrevPageButton() : null, | ||||
|               automaticallyImplyLeading: false, | ||||
|             ) | ||||
|           : null, | ||||
|       bottomNavigationBar: (SolianTheme.isLargeScreen(context) || | ||||
|               !(showNavigation && showBottom)) | ||||
|           ? null | ||||
|           : const AppNavigationBottomBar(), | ||||
|       body: SolianTheme.isLargeScreen(context) | ||||
|           ? Row( | ||||
|               children: [ | ||||
|                 if (showNavigation) const AppNavigationRail(), | ||||
|                 if (showNavigation) | ||||
|                   const VerticalDivider(thickness: 0.3, width: 1), | ||||
|                 if (showSidebar && sidebarFirst) | ||||
|                   ...buildContent(context).reversed | ||||
|                 else if (showSidebar) | ||||
|                   ...buildContent(context) | ||||
|                 else | ||||
|                   Expanded(child: child), | ||||
|               ], | ||||
|             ) | ||||
|           : child, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										22
									
								
								lib/widgets/centered_container.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/widgets/centered_container.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class CenteredContainer extends StatelessWidget { | ||||
|   final Widget child; | ||||
|   final double maxWidth; | ||||
|  | ||||
|   const CenteredContainer({ | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     this.maxWidth = 720, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Center( | ||||
|       child: Container( | ||||
|         constraints: BoxConstraints(maxWidth: maxWidth), | ||||
|         child: child, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -3,6 +3,7 @@ import 'package:get/get.dart'; | ||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||
| import 'package:solian/models/post.dart'; | ||||
| import 'package:solian/router.dart'; | ||||
| import 'package:solian/widgets/centered_container.dart'; | ||||
| import 'package:solian/widgets/posts/post_action.dart'; | ||||
| import 'package:solian/widgets/posts/post_item.dart'; | ||||
|  | ||||
| @@ -27,29 +28,31 @@ class PostListWidget extends StatelessWidget { | ||||
|       builderDelegate: PagedChildBuilderDelegate<Post>( | ||||
|         itemBuilder: (context, item, index) { | ||||
|           return RepaintBoundary( | ||||
|             child: GestureDetector( | ||||
|               child: PostItem( | ||||
|                 key: Key('p${item.alias}'), | ||||
|                 item: item, | ||||
|                 isShowEmbed: isShowEmbed, | ||||
|                 isClickable: isNestedClickable, | ||||
|               ).paddingSymmetric(vertical: 8), | ||||
|               onTap: () { | ||||
|                 if (!isClickable) return; | ||||
|                 AppRouter.instance.pushNamed( | ||||
|                   'postDetail', | ||||
|                   pathParameters: {'alias': item.alias}, | ||||
|                 ); | ||||
|               }, | ||||
|               onLongPress: () { | ||||
|                 showModalBottomSheet( | ||||
|                   useRootNavigator: true, | ||||
|                   context: context, | ||||
|                   builder: (context) => PostAction(item: item), | ||||
|                 ).then((value) { | ||||
|                   if (value != null) controller.refresh(); | ||||
|                 }); | ||||
|               }, | ||||
|             child: CenteredContainer( | ||||
|               child: GestureDetector( | ||||
|                 child: PostItem( | ||||
|                   key: Key('p${item.alias}'), | ||||
|                   item: item, | ||||
|                   isShowEmbed: isShowEmbed, | ||||
|                   isClickable: isNestedClickable, | ||||
|                 ).paddingSymmetric(vertical: 8), | ||||
|                 onTap: () { | ||||
|                   if (!isClickable) return; | ||||
|                   AppRouter.instance.pushNamed( | ||||
|                     'postDetail', | ||||
|                     pathParameters: {'alias': item.alias}, | ||||
|                   ); | ||||
|                 }, | ||||
|                 onLongPress: () { | ||||
|                   showModalBottomSheet( | ||||
|                     useRootNavigator: true, | ||||
|                     context: context, | ||||
|                     builder: (context) => PostAction(item: item), | ||||
|                   ).then((value) { | ||||
|                     if (value != null) controller.refresh(); | ||||
|                   }); | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
|         }, | ||||
|   | ||||
| @@ -83,6 +83,12 @@ PODS: | ||||
|     - WebRTC-SDK (= 114.5735.10) | ||||
|   - macos_window_utils (1.0.0): | ||||
|     - FlutterMacOS | ||||
|   - media_kit_libs_macos_video (1.0.4): | ||||
|     - FlutterMacOS | ||||
|   - media_kit_native_event_loop (1.0.0): | ||||
|     - FlutterMacOS | ||||
|   - media_kit_video (0.0.1): | ||||
|     - FlutterMacOS | ||||
|   - nanopb (2.30910.0): | ||||
|     - nanopb/decode (= 2.30910.0) | ||||
|     - nanopb/encode (= 2.30910.0) | ||||
| @@ -96,14 +102,13 @@ PODS: | ||||
|   - PromisesObjC (2.4.0) | ||||
|   - protocol_handler_macos (0.0.1): | ||||
|     - FlutterMacOS | ||||
|   - screen_brightness_macos (0.1.0): | ||||
|     - FlutterMacOS | ||||
|   - Sentry/HybridSDK (8.29.0) | ||||
|   - sentry_flutter (8.3.0): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|     - Sentry/HybridSDK (= 8.29.0) | ||||
|   - shared_preferences_foundation (0.0.1): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - sqflite (0.0.3): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
| @@ -111,9 +116,6 @@ PODS: | ||||
|     - FlutterMacOS | ||||
|   - url_launcher_macos (0.0.1): | ||||
|     - FlutterMacOS | ||||
|   - video_player_avfoundation (0.0.1): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - wakelock_plus (0.0.1): | ||||
|     - FlutterMacOS | ||||
|   - WebRTC-SDK (114.5735.10) | ||||
| @@ -131,15 +133,17 @@ DEPENDENCIES: | ||||
|   - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`) | ||||
|   - livekit_client (from `Flutter/ephemeral/.symlinks/plugins/livekit_client/macos`) | ||||
|   - macos_window_utils (from `Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos`) | ||||
|   - media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`) | ||||
|   - media_kit_native_event_loop (from `Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos`) | ||||
|   - media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`) | ||||
|   - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) | ||||
|   - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) | ||||
|   - protocol_handler_macos (from `Flutter/ephemeral/.symlinks/plugins/protocol_handler_macos/macos`) | ||||
|   - screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`) | ||||
|   - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) | ||||
|   - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) | ||||
|   - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) | ||||
|   - super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`) | ||||
|   - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) | ||||
|   - video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`) | ||||
|   - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) | ||||
|  | ||||
| SPEC REPOS: | ||||
| @@ -181,24 +185,28 @@ EXTERNAL SOURCES: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/livekit_client/macos | ||||
|   macos_window_utils: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos | ||||
|   media_kit_libs_macos_video: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos | ||||
|   media_kit_native_event_loop: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos | ||||
|   media_kit_video: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos | ||||
|   package_info_plus: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos | ||||
|   path_provider_foundation: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin | ||||
|   protocol_handler_macos: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/protocol_handler_macos/macos | ||||
|   screen_brightness_macos: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos | ||||
|   sentry_flutter: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos | ||||
|   shared_preferences_foundation: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin | ||||
|   sqflite: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin | ||||
|   super_native_extensions: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos | ||||
|   url_launcher_macos: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos | ||||
|   video_player_avfoundation: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin | ||||
|   wakelock_plus: | ||||
|     :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos | ||||
|  | ||||
| @@ -222,18 +230,20 @@ SPEC CHECKSUMS: | ||||
|   irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 | ||||
|   livekit_client: 9b39e0f1b8e1a8ec794bb72a4f9bbfc28c959ece | ||||
|   macos_window_utils: 933f91f64805e2eb91a5bd057cf97cd097276663 | ||||
|   media_kit_libs_macos_video: b3e2bbec2eef97c285f2b1baa7963c67c753fb82 | ||||
|   media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5 | ||||
|   media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5 | ||||
|   nanopb: 438bc412db1928dac798aa6fd75726007be04262 | ||||
|   package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c | ||||
|   path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 | ||||
|   PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 | ||||
|   protocol_handler_macos: d10a6c01d6373389ffd2278013ab4c47ed6d6daa | ||||
|   screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda | ||||
|   Sentry: 016de45ee5ce5fca2a829996f1bfafeb5e62e8b4 | ||||
|   sentry_flutter: 5fb57c5b7e6427a9dc1fedde4269eb65823982d4 | ||||
|   shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 | ||||
|   sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec | ||||
|   super_native_extensions: 85efee3a7495b46b04befcfc86ed12069264ebf3 | ||||
|   url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 | ||||
|   video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 | ||||
|   wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 | ||||
|   WebRTC-SDK: 8c0edd05b880a39648118192c252667ea06dea51 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user