Compare commits
	
		
			3 Commits
		
	
	
		
			3.1.0+114
			...
			8352ce8b5b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8352ce8b5b | |||
| c06abf6e42 | |||
| 37cc0a5291 | 
| @@ -8,6 +8,9 @@ | ||||
|  | ||||
| Hello there! Welcome to the main repository of the DysonNetwork (also known as the Solar Network). The code here is mainly about the front-end app (also known as Solian). But you can still post issues here to get help and request new features! | ||||
|  | ||||
| 如果你看得懂这行字,你可以前往我们的文档来了解更多: | ||||
| [Suki - Solar Network](https://kb.solsynth.dev/zh/solar-network) | ||||
|  | ||||
| ## Server | ||||
|  | ||||
| The backend of the Solar Network project is located at [Solsynth/DysonNetwork](https://github.com/Solsynth/DysonNetwork) | ||||
| @@ -25,8 +28,6 @@ The content below will lead you to the world of Solar Network. | ||||
|  | ||||
| ### For Normal Users | ||||
|  | ||||
| **The v3 Release is not ready, yet.** | ||||
|  | ||||
| 1. Go to the Github Releases page, and download the latest release / pre-release according to your platform. | ||||
|    - **What's the difference between stable and pre-release?** The pre-release is untested by the other users and includes the new cutting-edge features, usually the pre-release is the feature drop. At the same time, due to we're not doing the API versioning, some breaking changes may break the stable release, so use the pre-release one instead. | ||||
| 2. Create an account on the Solar Network | ||||
|   | ||||
| @@ -310,42 +310,36 @@ final routerProvider = Provider<GoRouter>((ref) { | ||||
|             }, | ||||
|             routes: [ | ||||
|               // Explore tab | ||||
|               ShellRoute( | ||||
|                 builder: | ||||
|                     (context, state, child) => ExploreShellScreen(child: child), | ||||
|                 routes: [ | ||||
|                   GoRoute( | ||||
|                     name: 'explore', | ||||
|                     path: '/', | ||||
|                     builder: (context, state) => const ExploreScreen(), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     name: 'postSearch', | ||||
|                     path: '/posts/search', | ||||
|                     builder: (context, state) => const PostSearchScreen(), | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     name: 'postDetail', | ||||
|                     path: '/posts/:id', | ||||
|                     builder: (context, state) { | ||||
|                       final id = state.pathParameters['id']!; | ||||
|                       return PostDetailScreen(id: id); | ||||
|                     }, | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     name: 'publisherProfile', | ||||
|                     path: '/publishers/:name', | ||||
|                     builder: (context, state) { | ||||
|                       final name = state.pathParameters['name']!; | ||||
|                       return PublisherProfileScreen(name: name); | ||||
|                     }, | ||||
|                   ), | ||||
|                   GoRoute( | ||||
|                     name: 'discoveryRealms', | ||||
|                     path: '/discovery/realms', | ||||
|                     builder: (context, state) => const DiscoveryRealmsScreen(), | ||||
|                   ), | ||||
|                 ], | ||||
|               GoRoute( | ||||
|                 name: 'explore', | ||||
|                 path: '/', | ||||
|                 builder: (context, state) => const ExploreScreen(), | ||||
|               ), | ||||
|               GoRoute( | ||||
|                 name: 'postSearch', | ||||
|                 path: '/posts/search', | ||||
|                 builder: (context, state) => const PostSearchScreen(), | ||||
|               ), | ||||
|               GoRoute( | ||||
|                 name: 'postDetail', | ||||
|                 path: '/posts/:id', | ||||
|                 builder: (context, state) { | ||||
|                   final id = state.pathParameters['id']!; | ||||
|                   return PostDetailScreen(id: id); | ||||
|                 }, | ||||
|               ), | ||||
|               GoRoute( | ||||
|                 name: 'publisherProfile', | ||||
|                 path: '/publishers/:name', | ||||
|                 builder: (context, state) { | ||||
|                   final name = state.pathParameters['name']!; | ||||
|                   return PublisherProfileScreen(name: name); | ||||
|                 }, | ||||
|               ), | ||||
|               GoRoute( | ||||
|                 name: 'discoveryRealms', | ||||
|                 path: '/discovery/realms', | ||||
|                 builder: (context, state) => const DiscoveryRealmsScreen(), | ||||
|               ), | ||||
|  | ||||
|               // Chat tab | ||||
|   | ||||
| @@ -17,6 +17,7 @@ class DiscoveryRealmsScreen extends HookConsumerWidget { | ||||
|     final currentQuery = useState<String?>(null); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       noBackground: false, | ||||
|       appBar: AppBar(title: Text('discoverRealms'.tr())), | ||||
|       body: Stack( | ||||
|         children: [ | ||||
|   | ||||
| @@ -9,8 +9,11 @@ import 'package:island/models/activity.dart'; | ||||
| import 'package:island/models/publisher.dart'; | ||||
| import 'package:island/models/realm.dart'; | ||||
| import 'package:island/models/webfeed.dart'; | ||||
| import 'package:island/pods/event_calendar.dart'; | ||||
| import 'package:island/pods/userinfo.dart'; | ||||
| import 'package:island/services/responsive.dart'; | ||||
| import 'package:island/widgets/account/event_calendar.dart'; | ||||
| import 'package:island/widgets/account/fortune_graph.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/models/post.dart'; | ||||
| import 'package:island/widgets/check_in.dart'; | ||||
| @@ -27,42 +30,11 @@ import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| part 'explore.g.dart'; | ||||
|  | ||||
| class ExploreShellScreen extends HookConsumerWidget { | ||||
|   final Widget child; | ||||
|   const ExploreShellScreen({super.key, required this.child}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final isWide = MediaQuery.of(context).size.width > 640; | ||||
|  | ||||
|     if (isWide) { | ||||
|       return AppBackground( | ||||
|         isRoot: true, | ||||
|         child: Row( | ||||
|           children: [ | ||||
|             Flexible(flex: 2, child: ExploreScreen(isAside: true)), | ||||
|             VerticalDivider(width: 1), | ||||
|             Flexible(flex: 3, child: child), | ||||
|           ], | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return AppBackground(isRoot: true, child: child); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class ExploreScreen extends HookConsumerWidget { | ||||
|   final bool isAside; | ||||
|   const ExploreScreen({super.key, this.isAside = false}); | ||||
|   const ExploreScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final isWide = isWideScreen(context); | ||||
|     if (isWide && !isAside) { | ||||
|       return const EmptyPageHolder(); | ||||
|     } | ||||
|  | ||||
|     final tabController = useTabController(initialLength: 3); | ||||
|     final currentFilter = useState<String?>(null); | ||||
|  | ||||
| @@ -89,8 +61,31 @@ class ExploreScreen extends HookConsumerWidget { | ||||
|       activityListNotifierProvider(currentFilter.value).notifier, | ||||
|     ); | ||||
|  | ||||
|     final now = DateTime.now(); | ||||
|  | ||||
|     final query = useState( | ||||
|       EventCalendarQuery(uname: 'me', year: now.year, month: now.month), | ||||
|     ); | ||||
|  | ||||
|     final events = ref.watch(eventCalendarProvider(query.value)); | ||||
|  | ||||
|     final selectedDay = useState(now); | ||||
|  | ||||
|     void onMonthChanged(int year, int month) { | ||||
|       query.value = EventCalendarQuery( | ||||
|         uname: query.value.uname, | ||||
|         year: year, | ||||
|         month: month, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     // Function to handle day selection for synchronizing between widgets | ||||
|     void onDaySelected(DateTime day) { | ||||
|       selectedDay.value = day; | ||||
|     } | ||||
|  | ||||
|     return AppScaffold( | ||||
|       extendBody: false, // Prevent conflicts with tabs navigation | ||||
|       noBackground: false, | ||||
|       appBar: AppBar( | ||||
|         toolbarHeight: 0, | ||||
|         bottom: PreferredSize( | ||||
| @@ -184,23 +179,76 @@ class ExploreScreen extends HookConsumerWidget { | ||||
|         child: const Icon(Symbols.edit), | ||||
|       ), | ||||
|       floatingActionButtonLocation: TabbedFabLocation(context), | ||||
|       body: TabBarView( | ||||
|         controller: tabController, | ||||
|         physics: const NeverScrollableScrollPhysics(), | ||||
|         children: [ | ||||
|           _buildActivityList(ref, null), | ||||
|           _buildActivityList(ref, 'subscriptions'), | ||||
|           _buildActivityList(ref, 'friends'), | ||||
|         ], | ||||
|       body: Builder( | ||||
|         builder: (context) { | ||||
|           final isWider = isWiderScreen(context); | ||||
|  | ||||
|           final bodyView = TabBarView( | ||||
|             controller: tabController, | ||||
|             physics: const NeverScrollableScrollPhysics(), | ||||
|             children: [ | ||||
|               _buildActivityList(context, ref, null), | ||||
|               _buildActivityList(context, ref, 'subscriptions'), | ||||
|               _buildActivityList(context, ref, 'friends'), | ||||
|             ], | ||||
|           ); | ||||
|  | ||||
|           if (isWider) { | ||||
|             return Row( | ||||
|               children: [ | ||||
|                 Flexible(flex: 3, child: bodyView), | ||||
|                 const VerticalDivider(width: 1), | ||||
|                 Flexible( | ||||
|                   flex: 2, | ||||
|                   child: SingleChildScrollView( | ||||
|                     child: Column( | ||||
|                       children: [ | ||||
|                         CheckInWidget(), | ||||
|                         Card( | ||||
|                           margin: EdgeInsets.only(left: 16, right: 16, top: 8), | ||||
|                           child: Column( | ||||
|                             children: [ | ||||
|                               // Use the reusable EventCalendarWidget | ||||
|                               EventCalendarWidget( | ||||
|                                 events: events, | ||||
|                                 initialDate: now, | ||||
|                                 showEventDetails: true, | ||||
|                                 onMonthChanged: onMonthChanged, | ||||
|                                 onDaySelected: onDaySelected, | ||||
|                               ), | ||||
|                             ], | ||||
|                           ), | ||||
|                         ), | ||||
|                         FortuneGraphWidget( | ||||
|                           events: events, | ||||
|                           constrainWidth: true, | ||||
|                           onPointSelected: onDaySelected, | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ); | ||||
|           } | ||||
|  | ||||
|           return bodyView; | ||||
|         }, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildActivityList(WidgetRef ref, String? filter) { | ||||
|   Widget _buildActivityList( | ||||
|     BuildContext context, | ||||
|     WidgetRef ref, | ||||
|     String? filter, | ||||
|   ) { | ||||
|     final activitiesNotifier = ref.watch( | ||||
|       activityListNotifierProvider(filter).notifier, | ||||
|     ); | ||||
|  | ||||
|     final isWider = isWiderScreen(context); | ||||
|  | ||||
|     return RefreshIndicator( | ||||
|       onRefresh: () => Future.sync(activitiesNotifier.forceRefresh), | ||||
|       child: PagingHelperView( | ||||
| @@ -214,7 +262,7 @@ class ExploreScreen extends HookConsumerWidget { | ||||
|                 widgetCount: widgetCount, | ||||
|                 endItemView: endItemView, | ||||
|                 activitiesNotifier: activitiesNotifier, | ||||
|                 contentOnly: filter != null, | ||||
|                 contentOnly: isWider || filter != null, | ||||
|               ), | ||||
|             ), | ||||
|       ), | ||||
|   | ||||
| @@ -57,6 +57,7 @@ class PostDetailScreen extends HookConsumerWidget { | ||||
|     final isWide = isWideScreen(context); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       noBackground: false, | ||||
|       appBar: AppBar(title: const Text('Post')), | ||||
|       body: postState.when( | ||||
|         data: (post) { | ||||
|   | ||||
| @@ -109,6 +109,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return AppScaffold( | ||||
|       noBackground: false, | ||||
|       appBar: AppBar( | ||||
|         title: TextField( | ||||
|           controller: _searchController, | ||||
|   | ||||
| @@ -124,6 +124,7 @@ class PublisherProfileScreen extends HookConsumerWidget { | ||||
|     return publisher.when( | ||||
|       data: | ||||
|           (data) => AppScaffold( | ||||
|             noBackground: false, | ||||
|             body: CustomScrollView( | ||||
|               slivers: [ | ||||
|                 SliverAppBar( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user