🎨 Optimized code structure, rename a lot of widgets
💄 Better large screen support in chat
			
			
This commit is contained in:
		| @@ -34,7 +34,7 @@ class SolianApp extends StatelessWidget { | |||||||
|       themeMode: ThemeMode.system, |       themeMode: ThemeMode.system, | ||||||
|       localizationsDelegates: AppLocalizations.localizationsDelegates, |       localizationsDelegates: AppLocalizations.localizationsDelegates, | ||||||
|       supportedLocales: AppLocalizations.supportedLocales, |       supportedLocales: AppLocalizations.supportedLocales, | ||||||
|       routerConfig: router, |       routerConfig: SolianRouter.router, | ||||||
|       builder: (context, child) { |       builder: (context, child) { | ||||||
|         return MultiProvider( |         return MultiProvider( | ||||||
|           providers: [ |           providers: [ | ||||||
|   | |||||||
							
								
								
									
										224
									
								
								lib/router.dart
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								lib/router.dart
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
| import 'package:solian/models/call.dart'; | import 'package:solian/models/call.dart'; | ||||||
| import 'package:solian/models/channel.dart'; | import 'package:solian/models/channel.dart'; | ||||||
| @@ -8,110 +9,135 @@ import 'package:solian/screens/account/personalize.dart'; | |||||||
| import 'package:solian/screens/auth/signup.dart'; | import 'package:solian/screens/auth/signup.dart'; | ||||||
| import 'package:solian/screens/chat/call.dart'; | import 'package:solian/screens/chat/call.dart'; | ||||||
| import 'package:solian/screens/chat/chat.dart'; | import 'package:solian/screens/chat/chat.dart'; | ||||||
| import 'package:solian/screens/chat/index.dart'; | import 'package:solian/screens/chat/chat_list.dart'; | ||||||
| import 'package:solian/screens/chat/manage.dart'; | import 'package:solian/screens/chat/chat_detail.dart'; | ||||||
| import 'package:solian/screens/chat/channel/editor.dart'; | import 'package:solian/screens/chat/channel/channel_editor.dart'; | ||||||
| import 'package:solian/screens/chat/channel/member.dart'; | import 'package:solian/screens/chat/channel/channel_member.dart'; | ||||||
| import 'package:solian/screens/explore.dart'; | import 'package:solian/screens/explore.dart'; | ||||||
| import 'package:solian/screens/notification.dart'; | import 'package:solian/screens/notification.dart'; | ||||||
| import 'package:solian/screens/posts/comment_editor.dart'; | import 'package:solian/screens/posts/comment_editor.dart'; | ||||||
| import 'package:solian/screens/posts/moment_editor.dart'; | import 'package:solian/screens/posts/moment_editor.dart'; | ||||||
| import 'package:solian/screens/posts/screen.dart'; | import 'package:solian/screens/posts/screen.dart'; | ||||||
| import 'package:solian/screens/auth/signin.dart'; | import 'package:solian/screens/auth/signin.dart'; | ||||||
|  | import 'package:solian/utils/theme.dart'; | ||||||
|  | import 'package:solian/widgets/empty.dart'; | ||||||
|  | import 'package:solian/widgets/layouts/two_column.dart'; | ||||||
|  |  | ||||||
| final router = GoRouter( | abstract class SolianRouter { | ||||||
|   routes: [ |   static final router = GoRouter( | ||||||
|     GoRoute( |     routes: [ | ||||||
|       path: '/', |       GoRoute( | ||||||
|       name: 'explore', |         path: '/', | ||||||
|       builder: (context, state) => const ExploreScreen(), |         name: 'explore', | ||||||
|     ), |         builder: (context, state) => const ExploreScreen(), | ||||||
|     GoRoute( |  | ||||||
|       path: '/notification', |  | ||||||
|       name: 'notification', |  | ||||||
|       builder: (context, state) => const NotificationScreen(), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/chat', |  | ||||||
|       name: 'chat', |  | ||||||
|       builder: (context, state) => const ChatIndexScreen(), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/chat/create', |  | ||||||
|       name: 'chat.channel.editor', |  | ||||||
|       builder: (context, state) => |  | ||||||
|           ChannelEditorScreen(editing: state.extra as Channel?), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/chat/c/:channel', |  | ||||||
|       name: 'chat.channel', |  | ||||||
|       builder: (context, state) => |  | ||||||
|           ChatScreen(alias: state.pathParameters['channel'] as String), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/chat/c/:channel/call', |  | ||||||
|       name: 'chat.channel.call', |  | ||||||
|       builder: (context, state) => ChatCall(call: state.extra as Call), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/chat/c/:channel/manage', |  | ||||||
|       name: 'chat.channel.manage', |  | ||||||
|       builder: (context, state) => |  | ||||||
|           ChatManageScreen(channel: state.extra as Channel), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/chat/c/:channel/member', |  | ||||||
|       name: 'chat.channel.member', |  | ||||||
|       builder: (context, state) => |  | ||||||
|           ChatMemberScreen(channel: state.extra as Channel), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/account', |  | ||||||
|       name: 'account', |  | ||||||
|       builder: (context, state) => const AccountScreen(), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/posts/publish/moments', |  | ||||||
|       name: 'posts.moments.editor', |  | ||||||
|       builder: (context, state) => |  | ||||||
|           MomentEditorScreen(editing: state.extra as Post?), |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/posts/publish/comments', |  | ||||||
|       name: 'posts.comments.editor', |  | ||||||
|       builder: (context, state) { |  | ||||||
|         final args = state.extra as CommentPostArguments; |  | ||||||
|         return CommentEditorScreen( |  | ||||||
|             editing: args.editing, related: args.related); |  | ||||||
|       }, |  | ||||||
|     ), |  | ||||||
|     GoRoute( |  | ||||||
|       path: '/posts/:dataset/:alias', |  | ||||||
|       name: 'posts.screen', |  | ||||||
|       builder: (context, state) => PostScreen( |  | ||||||
|         alias: state.pathParameters['alias'] as String, |  | ||||||
|         dataset: state.pathParameters['dataset'] as String, |  | ||||||
|       ), |       ), | ||||||
|     ), |       GoRoute( | ||||||
|     GoRoute( |         path: '/notification', | ||||||
|       path: '/auth/sign-in', |         name: 'notification', | ||||||
|       name: 'auth.sign-in', |         builder: (context, state) => const NotificationScreen(), | ||||||
|       builder: (context, state) => SignInScreen(), |       ), | ||||||
|     ), |       ShellRoute( | ||||||
|     GoRoute( |         pageBuilder: (context, state, child) => defaultPageBuilder( | ||||||
|       path: '/auth/sign-up', |           context, | ||||||
|       name: 'auth.sign-up', |           state, | ||||||
|       builder: (context, state) => SignUpScreen(), |           SolianTheme.isLargeScreen(context) | ||||||
|     ), |               ? TwoColumnLayout( | ||||||
|     GoRoute( |                   sideChild: const ChatListScreen(), | ||||||
|       path: '/account/friend', |                   mainChild: child, | ||||||
|       name: 'account.friend', |                 ) | ||||||
|       builder: (context, state) => const FriendScreen(), |               : child, | ||||||
|     ), |         ), | ||||||
|     GoRoute( |         routes: [ | ||||||
|       path: '/account/personalize', |           GoRoute( | ||||||
|       name: 'account.personalize', |             path: '/chat', | ||||||
|       builder: (context, state) => const PersonalizeScreen(), |             name: 'chat', | ||||||
|     ), |             builder: (context, state) => | ||||||
|   ], |                 !SolianTheme.isLargeScreen(context) ? const ChatListScreen() : const PageEmptyWidget(), | ||||||
| ); |           ), | ||||||
|  |           GoRoute( | ||||||
|  |             path: '/chat/create', | ||||||
|  |             name: 'chat.channel.editor', | ||||||
|  |             builder: (context, state) => ChannelEditorScreen(editing: state.extra as Channel?), | ||||||
|  |           ), | ||||||
|  |           GoRoute( | ||||||
|  |             path: '/chat/c/:channel', | ||||||
|  |             name: 'chat.channel', | ||||||
|  |             builder: (context, state) => ChatScreen(alias: state.pathParameters['channel'] as String), | ||||||
|  |           ), | ||||||
|  |           GoRoute( | ||||||
|  |             path: '/chat/c/:channel/call', | ||||||
|  |             name: 'chat.channel.call', | ||||||
|  |             builder: (context, state) => ChatCall(call: state.extra as Call), | ||||||
|  |           ), | ||||||
|  |           GoRoute( | ||||||
|  |             path: '/chat/c/:channel/manage', | ||||||
|  |             name: 'chat.channel.manage', | ||||||
|  |             builder: (context, state) => ChatDetailScreen(channel: state.extra as Channel), | ||||||
|  |           ), | ||||||
|  |           GoRoute( | ||||||
|  |             path: '/chat/c/:channel/member', | ||||||
|  |             name: 'chat.channel.member', | ||||||
|  |             builder: (context, state) => ChatMemberScreen(channel: state.extra as Channel), | ||||||
|  |           ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/account', | ||||||
|  |         name: 'account', | ||||||
|  |         builder: (context, state) => const AccountScreen(), | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/posts/publish/moments', | ||||||
|  |         name: 'posts.moments.editor', | ||||||
|  |         builder: (context, state) => MomentEditorScreen(editing: state.extra as Post?), | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/posts/publish/comments', | ||||||
|  |         name: 'posts.comments.editor', | ||||||
|  |         builder: (context, state) { | ||||||
|  |           final args = state.extra as CommentPostArguments; | ||||||
|  |           return CommentEditorScreen(editing: args.editing, related: args.related); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/posts/:dataset/:alias', | ||||||
|  |         name: 'posts.screen', | ||||||
|  |         builder: (context, state) => PostScreen( | ||||||
|  |           alias: state.pathParameters['alias'] as String, | ||||||
|  |           dataset: state.pathParameters['dataset'] as String, | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/auth/sign-in', | ||||||
|  |         name: 'auth.sign-in', | ||||||
|  |         builder: (context, state) => SignInScreen(), | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/auth/sign-up', | ||||||
|  |         name: 'auth.sign-up', | ||||||
|  |         builder: (context, state) => SignUpScreen(), | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/account/friend', | ||||||
|  |         name: 'account.friend', | ||||||
|  |         builder: (context, state) => const FriendScreen(), | ||||||
|  |       ), | ||||||
|  |       GoRoute( | ||||||
|  |         path: '/account/personalize', | ||||||
|  |         name: 'account.personalize', | ||||||
|  |         builder: (context, state) => const PersonalizeScreen(), | ||||||
|  |       ), | ||||||
|  |     ], | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   static Page defaultPageBuilder( | ||||||
|  |     BuildContext context, | ||||||
|  |     GoRouterState state, | ||||||
|  |     Widget child, | ||||||
|  |   ) => | ||||||
|  |       MaterialPage( | ||||||
|  |         key: state.pageKey, | ||||||
|  |         restorationId: state.pageKey.value, | ||||||
|  |         child: child, | ||||||
|  |       ); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -4,10 +4,10 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/screens/account/friend.dart'; | import 'package:solian/screens/account/friend.dart'; | ||||||
| import 'package:solian/screens/account/personalize.dart'; | import 'package:solian/screens/account/personalize.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:solian/widgets/empty.dart'; | import 'package:solian/widgets/empty.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
|  |  | ||||||
| class AccountScreen extends StatefulWidget { | class AccountScreen extends StatefulWidget { | ||||||
|   const AccountScreen({super.key}); |   const AccountScreen({super.key}); | ||||||
| @@ -32,11 +32,11 @@ class _AccountScreenState extends State<AccountScreen> { | |||||||
|         case 'account.personalize': |         case 'account.personalize': | ||||||
|           return const PersonalizeScreenWidget(); |           return const PersonalizeScreenWidget(); | ||||||
|         default: |         default: | ||||||
|           return const SelectionEmptyWidget(); |           return const PageEmptyWidget(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: _title ?? AppLocalizations.of(context)!.account, |       title: _title ?? AppLocalizations.of(context)!.account, | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
|       fixedAppBarColor: true, |       fixedAppBarColor: true, | ||||||
| @@ -60,7 +60,7 @@ class _AccountScreenState extends State<AccountScreen> { | |||||||
|             ) |             ) | ||||||
|           : AccountScreenWidget( |           : AccountScreenWidget( | ||||||
|               onSelect: (item, _) { |               onSelect: (item, _) { | ||||||
|                 router.pushNamed(item); |                 SolianRouter.router.pushNamed(item); | ||||||
|               }, |               }, | ||||||
|             ), |             ), | ||||||
|     ); |     ); | ||||||
| @@ -139,7 +139,7 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> { | |||||||
|               title: AppLocalizations.of(context)!.signIn, |               title: AppLocalizations.of(context)!.signIn, | ||||||
|               caption: AppLocalizations.of(context)!.signInCaption, |               caption: AppLocalizations.of(context)!.signInCaption, | ||||||
|               onTap: () { |               onTap: () { | ||||||
|                 router.pushNamed('auth.sign-in').then((did) { |                 SolianRouter.router.pushNamed('auth.sign-in').then((did) { | ||||||
|                   auth.isAuthorized().then((value) { |                   auth.isAuthorized().then((value) { | ||||||
|                     setState(() => _isAuthorized = value); |                     setState(() => _isAuthorized = value); | ||||||
|                   }); |                   }); | ||||||
| @@ -151,7 +151,7 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> { | |||||||
|               title: AppLocalizations.of(context)!.signUp, |               title: AppLocalizations.of(context)!.signUp, | ||||||
|               caption: AppLocalizations.of(context)!.signUpCaption, |               caption: AppLocalizations.of(context)!.signUpCaption, | ||||||
|               onTap: () { |               onTap: () { | ||||||
|                 router.pushNamed('auth.sign-up'); |                 SolianRouter.router.pushNamed('auth.sign-up'); | ||||||
|               }, |               }, | ||||||
|             ), |             ), | ||||||
|           ], |           ], | ||||||
|   | |||||||
| @@ -6,9 +6,9 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:solian/models/friendship.dart'; | import 'package:solian/models/friendship.dart'; | ||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class FriendScreen extends StatelessWidget { | class FriendScreen extends StatelessWidget { | ||||||
| @@ -16,7 +16,7 @@ class FriendScreen extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.friend, |       title: AppLocalizations.of(context)!.friend, | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class PersonalizeScreen extends StatelessWidget { | class PersonalizeScreen extends StatelessWidget { | ||||||
| @@ -15,7 +15,7 @@ class PersonalizeScreen extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.personalize, |       title: AppLocalizations.of(context)!.personalize, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       child: const PersonalizeScreenWidget(), |       child: const PersonalizeScreenWidget(), | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:url_launcher/url_launcher_string.dart'; | import 'package:url_launcher/url_launcher_string.dart'; | ||||||
|  |  | ||||||
| class SignInScreen extends StatelessWidget { | class SignInScreen extends StatelessWidget { | ||||||
| @@ -21,7 +21,7 @@ class SignInScreen extends StatelessWidget { | |||||||
|     final password = _passwordController.value.text; |     final password = _passwordController.value.text; | ||||||
|     if (username.isEmpty || password.isEmpty) return; |     if (username.isEmpty || password.isEmpty) return; | ||||||
|     auth.signin(context, username, password).then((_) { |     auth.signin(context, username, password).then((_) { | ||||||
|       router.pop(true); |       SolianRouter.router.pop(true); | ||||||
|     }).catchError((e) { |     }).catchError((e) { | ||||||
|       List<String> messages = e.toString().split('\n'); |       List<String> messages = e.toString().split('\n'); | ||||||
|       if (messages.last.contains('risk')) { |       if (messages.last.contains('risk')) { | ||||||
| @@ -61,7 +61,7 @@ class SignInScreen extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.signIn, |       title: AppLocalizations.of(context)!.signIn, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       child: Center( |       child: Center( | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:http/http.dart' as http; | import 'package:http/http.dart' as http; | ||||||
|  |  | ||||||
| class SignUpScreen extends StatelessWidget { | class SignUpScreen extends StatelessWidget { | ||||||
| @@ -58,7 +58,7 @@ class SignUpScreen extends StatelessWidget { | |||||||
|           ); |           ); | ||||||
|         }, |         }, | ||||||
|       ).then((_) { |       ).then((_) { | ||||||
|         router.replaceNamed('auth.sign-in'); |         SolianRouter.router.replaceNamed('auth.sign-in'); | ||||||
|       }); |       }); | ||||||
|     } else { |     } else { | ||||||
|       var message = utf8.decode(res.bodyBytes); |       var message = utf8.decode(res.bodyBytes); | ||||||
| @@ -68,7 +68,7 @@ class SignUpScreen extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.signUp, |       title: AppLocalizations.of(context)!.signUp, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       child: Center( |       child: Center( | ||||||
|   | |||||||
| @@ -3,10 +3,11 @@ import 'package:livekit_client/livekit_client.dart'; | |||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| import 'package:solian/models/call.dart'; | import 'package:solian/models/call.dart'; | ||||||
| import 'package:solian/providers/chat.dart'; | import 'package:solian/providers/chat.dart'; | ||||||
| import 'package:solian/widgets/chat/call/controls.dart'; | import 'package:solian/utils/theme.dart'; | ||||||
|  | import 'package:solian/widgets/chat/call/call_controls.dart'; | ||||||
| import 'package:solian/widgets/chat/call/participant.dart'; | import 'package:solian/widgets/chat/call/participant.dart'; | ||||||
| import 'package:solian/widgets/chat/call/participant_menu.dart'; | import 'package:solian/widgets/chat/call/participant_menu.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'dart:math' as math; | import 'dart:math' as math; | ||||||
|  |  | ||||||
| @@ -127,8 +128,9 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.chatCall, |       title: AppLocalizations.of(context)!.chatCall, | ||||||
|  |       fixedAppBarColor: SolianTheme.isLargeScreen(context), | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       child: content, |       child: content, | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:uuid/uuid.dart'; | import 'package:uuid/uuid.dart'; | ||||||
| 
 | 
 | ||||||
| @@ -55,8 +55,8 @@ class _ChannelEditorScreenState extends State<ChannelEditorScreen> { | |||||||
|       var message = utf8.decode(res.bodyBytes); |       var message = utf8.decode(res.bodyBytes); | ||||||
|       context.showErrorDialog(message); |       context.showErrorDialog(message); | ||||||
|     } else { |     } else { | ||||||
|       if (router.canPop()) { |       if (SolianRouter.router.canPop()) { | ||||||
|         router.pop(true); |         SolianRouter.router.pop(true); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     setState(() => _isSubmitting = false); |     setState(() => _isSubmitting = false); | ||||||
| @@ -67,8 +67,8 @@ class _ChannelEditorScreenState extends State<ChannelEditorScreen> { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void cancelEditing() { |   void cancelEditing() { | ||||||
|     if (router.canPop()) { |     if (SolianRouter.router.canPop()) { | ||||||
|       router.pop(false); |       SolianRouter.router.pop(false); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @@ -99,7 +99,7 @@ class _ChannelEditorScreenState extends State<ChannelEditorScreen> { | |||||||
|       ], |       ], | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       title: AppLocalizations.of(context)!.chatChannelOrganize, |       title: AppLocalizations.of(context)!.chatChannelOrganize, | ||||||
|       appBarActions: <Widget>[ |       appBarActions: <Widget>[ | ||||||
| @@ -7,10 +7,10 @@ import 'package:solian/models/account.dart'; | |||||||
| import 'package:solian/models/channel.dart'; | import 'package:solian/models/channel.dart'; | ||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:solian/widgets/account/friend_picker.dart'; | import 'package:solian/widgets/account/friend_picker.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| 
 | 
 | ||||||
| class ChatMemberScreen extends StatefulWidget { | class ChatMemberScreen extends StatefulWidget { | ||||||
| @@ -141,7 +141,7 @@ class _ChatMemberScreenState extends State<ChatMemberScreen> { | |||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.chatMember, |       title: AppLocalizations.of(context)!.chatMember, | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
| @@ -10,12 +10,13 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/providers/chat.dart'; | import 'package:solian/providers/chat.dart'; | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
|  | import 'package:solian/utils/theme.dart'; | ||||||
| import 'package:solian/widgets/chat/channel_action.dart'; | import 'package:solian/widgets/chat/channel_action.dart'; | ||||||
| import 'package:solian/widgets/chat/maintainer.dart'; | import 'package:solian/widgets/chat/chat_maintainer.dart'; | ||||||
| import 'package:solian/widgets/chat/message.dart'; | import 'package:solian/widgets/chat/message.dart'; | ||||||
| import 'package:solian/widgets/chat/message_action.dart'; | import 'package:solian/widgets/chat/message_action.dart'; | ||||||
| import 'package:solian/widgets/chat/message_editor.dart'; | import 'package:solian/widgets/chat/message_editor.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class ChatScreen extends StatelessWidget { | class ChatScreen extends StatelessWidget { | ||||||
| @@ -27,9 +28,11 @@ class ChatScreen extends StatelessWidget { | |||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     final chat = context.watch<ChatProvider>(); |     final chat = context.watch<ChatProvider>(); | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: chat.focusChannel?.name ?? 'Loading...', |       title: chat.focusChannel?.name ?? 'Loading...', | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|  |       fixedAppBarColor: SolianTheme.isLargeScreen(context), | ||||||
|  |       appBarLeading: IconButton(icon: const Icon(Icons.tag), onPressed: () {}), | ||||||
|       appBarActions: chat.focusChannel != null |       appBarActions: chat.focusChannel != null | ||||||
|           ? [ |           ? [ | ||||||
|               ChannelCallAction( |               ChannelCallAction( | ||||||
| @@ -197,7 +200,7 @@ class _ChatScreenWidgetState extends State<ChatScreenWidget> { | |||||||
|         TextButton( |         TextButton( | ||||||
|           child: Text(AppLocalizations.of(context)!.chatCallJoin), |           child: Text(AppLocalizations.of(context)!.chatCallJoin), | ||||||
|           onPressed: () { |           onPressed: () { | ||||||
|             router.pushNamed( |             SolianRouter.router.pushNamed( | ||||||
|               'chat.channel.call', |               'chat.channel.call', | ||||||
|               extra: _chat.ongoingCall, |               extra: _chat.ongoingCall, | ||||||
|               pathParameters: {'channel': widget.alias}, |               pathParameters: {'channel': widget.alias}, | ||||||
|   | |||||||
| @@ -4,19 +4,19 @@ import 'package:solian/models/channel.dart'; | |||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/widgets/chat/channel_deletion.dart'; | import 'package:solian/widgets/chat/channel_deletion.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| 
 | 
 | ||||||
| class ChatManageScreen extends StatefulWidget { | class ChatDetailScreen extends StatefulWidget { | ||||||
|   final Channel channel; |   final Channel channel; | ||||||
| 
 | 
 | ||||||
|   const ChatManageScreen({super.key, required this.channel}); |   const ChatDetailScreen({super.key, required this.channel}); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   State<ChatManageScreen> createState() => _ChatManageScreenState(); |   State<ChatDetailScreen> createState() => _ChatDetailScreenState(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class _ChatManageScreenState extends State<ChatManageScreen> { | class _ChatDetailScreenState extends State<ChatDetailScreen> { | ||||||
|   bool _isOwned = false; |   bool _isOwned = false; | ||||||
| 
 | 
 | ||||||
|   void promptLeaveChannel() async { |   void promptLeaveChannel() async { | ||||||
| @@ -27,8 +27,8 @@ class _ChatManageScreenState extends State<ChatManageScreen> { | |||||||
|         isOwned: _isOwned, |         isOwned: _isOwned, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|     if (did == true && router.canPop()) { |     if (did == true && SolianRouter.router.canPop()) { | ||||||
|       router.pop('disposed'); |       SolianRouter.router.pop('disposed'); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @@ -53,16 +53,16 @@ class _ChatManageScreenState extends State<ChatManageScreen> { | |||||||
|         leading: const Icon(Icons.settings), |         leading: const Icon(Icons.settings), | ||||||
|         title: Text(AppLocalizations.of(context)!.settings), |         title: Text(AppLocalizations.of(context)!.settings), | ||||||
|         onTap: () async { |         onTap: () async { | ||||||
|           router.pushNamed('chat.channel.editor', extra: widget.channel).then((did) { |           SolianRouter.router.pushNamed('chat.channel.editor', extra: widget.channel).then((did) { | ||||||
|             if (did == true) { |             if (did == true) { | ||||||
|               if (router.canPop()) router.pop('refresh'); |               if (SolianRouter.router.canPop()) SolianRouter.router.pop('refresh'); | ||||||
|             } |             } | ||||||
|           }); |           }); | ||||||
|         }, |         }, | ||||||
|       ), |       ), | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.chatManage, |       title: AppLocalizations.of(context)!.chatManage, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
| @@ -100,7 +100,7 @@ class _ChatManageScreenState extends State<ChatManageScreen> { | |||||||
|                   leading: const Icon(Icons.supervisor_account), |                   leading: const Icon(Icons.supervisor_account), | ||||||
|                   title: Text(AppLocalizations.of(context)!.chatMember), |                   title: Text(AppLocalizations.of(context)!.chatMember), | ||||||
|                   onTap: () { |                   onTap: () { | ||||||
|                     router.pushNamed( |                     SolianRouter.router.pushNamed( | ||||||
|                       'chat.channel.member', |                       'chat.channel.member', | ||||||
|                       extra: widget.channel, |                       extra: widget.channel, | ||||||
|                       pathParameters: {'channel': widget.channel.alias}, |                       pathParameters: {'channel': widget.channel.alias}, | ||||||
| @@ -4,90 +4,47 @@ import 'package:flutter/material.dart'; | |||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| import 'package:solian/models/channel.dart'; | import 'package:solian/models/channel.dart'; | ||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/providers/chat.dart'; |  | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/screens/chat/chat.dart'; |  | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/chat/channel_action.dart'; | import 'package:solian/utils/theme.dart'; | ||||||
| import 'package:solian/widgets/chat/chat_new.dart'; | import 'package:solian/widgets/chat/chat_new.dart'; | ||||||
| import 'package:solian/widgets/empty.dart'; |  | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:solian/widgets/notification_notifier.dart'; | import 'package:solian/widgets/notification_notifier.dart'; | ||||||
| import 'package:solian/widgets/signin_required.dart'; | import 'package:solian/widgets/signin_required.dart'; | ||||||
| 
 | 
 | ||||||
| class ChatIndexScreen extends StatefulWidget { | class ChatListScreen extends StatelessWidget { | ||||||
|   const ChatIndexScreen({super.key}); |   const ChatListScreen({super.key}); | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   State<ChatIndexScreen> createState() => _ChatIndexScreenState(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class _ChatIndexScreenState extends State<ChatIndexScreen> { |  | ||||||
|   Channel? _selectedChannel; |  | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     final chat = context.watch<ChatProvider>(); |     return IndentScaffold( | ||||||
| 
 |  | ||||||
|     final screenWidth = MediaQuery.of(context).size.width; |  | ||||||
|     final isLargeScreen = screenWidth >= 600; |  | ||||||
| 
 |  | ||||||
|     return IndentWrapper( |  | ||||||
|       title: AppLocalizations.of(context)!.chat, |       title: AppLocalizations.of(context)!.chat, | ||||||
|       appBarActions: isLargeScreen && chat.focusChannel != null |       appBarActions: const [NotificationButton()], | ||||||
|           ? [ |       fixedAppBarColor: SolianTheme.isLargeScreen(context), | ||||||
|               ChannelCallAction( |       child: ChatListWidget( | ||||||
|                 call: chat.ongoingCall, |         onSelect: (item) { | ||||||
|                 channel: chat.focusChannel!, |           SolianRouter.router.pushReplacementNamed( | ||||||
|                 onUpdate: () => chat.fetchChannel(chat.focusChannel!.alias), |             'chat.channel', | ||||||
|               ), |             pathParameters: {'channel': item.alias}, | ||||||
|               ChannelManageAction( |           ); | ||||||
|                 channel: chat.focusChannel!, |         }, | ||||||
|                 onUpdate: () => chat.fetchChannel(chat.focusChannel!.alias), |       ), | ||||||
|               ), |  | ||||||
|             ] |  | ||||||
|           : [const NotificationButton()], |  | ||||||
|       fixedAppBarColor: isLargeScreen, |  | ||||||
|       child: isLargeScreen |  | ||||||
|           ? Row( |  | ||||||
|               children: [ |  | ||||||
|                 Flexible( |  | ||||||
|                   flex: 2, |  | ||||||
|                   child: ChatIndexScreenWidget( |  | ||||||
|                     onSelect: (item) { |  | ||||||
|                       setState(() => _selectedChannel = item); |  | ||||||
|                     }, |  | ||||||
|                   ), |  | ||||||
|                 ), |  | ||||||
|                 const VerticalDivider(thickness: 0.3, width: 0.3), |  | ||||||
|                 Flexible( |  | ||||||
|                   flex: 4, |  | ||||||
|                   child: _selectedChannel == null |  | ||||||
|                       ? const SelectionEmptyWidget() |  | ||||||
|                       : ChatScreenWidget( |  | ||||||
|                           key: Key('c${_selectedChannel!.id}'), |  | ||||||
|                           alias: _selectedChannel!.alias, |  | ||||||
|                         ), |  | ||||||
|                 ), |  | ||||||
|               ], |  | ||||||
|             ) |  | ||||||
|           : const ChatIndexScreenWidget(), |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class ChatIndexScreenWidget extends StatefulWidget { | class ChatListWidget extends StatefulWidget { | ||||||
|   final Function(Channel item)? onSelect; |   final Function(Channel item)? onSelect; | ||||||
| 
 | 
 | ||||||
|   const ChatIndexScreenWidget({super.key, this.onSelect}); |   const ChatListWidget({super.key, this.onSelect}); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   State<ChatIndexScreenWidget> createState() => _ChatIndexScreenWidgetState(); |   State<ChatListWidget> createState() => _ChatListWidgetState(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class _ChatIndexScreenWidgetState extends State<ChatIndexScreenWidget> { | class _ChatListWidgetState extends State<ChatListWidget> { | ||||||
|   List<Channel> _channels = List.empty(); |   List<Channel> _channels = List.empty(); | ||||||
| 
 | 
 | ||||||
|   Future<void> fetchChannels() async { |   Future<void> fetchChannels() async { | ||||||
| @@ -169,7 +126,7 @@ class _ChatIndexScreenWidgetState extends State<ChatIndexScreenWidget> { | |||||||
|                       return; |                       return; | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     final result = await router.pushNamed( |                     final result = await SolianRouter.router.pushNamed( | ||||||
|                       'chat.channel', |                       'chat.channel', | ||||||
|                       pathParameters: { |                       pathParameters: { | ||||||
|                         'channel': element.alias, |                         'channel': element.alias, | ||||||
| @@ -12,9 +12,9 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | |||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:http/http.dart' as http; | import 'package:http/http.dart' as http; | ||||||
| import 'package:solian/widgets/empty.dart'; | import 'package:solian/widgets/empty.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:solian/widgets/notification_notifier.dart'; | import 'package:solian/widgets/notification_notifier.dart'; | ||||||
| import 'package:solian/widgets/posts/item.dart'; | import 'package:solian/widgets/posts/post.dart'; | ||||||
|  |  | ||||||
| class ExploreScreen extends StatefulWidget { | class ExploreScreen extends StatefulWidget { | ||||||
|   const ExploreScreen({super.key}); |   const ExploreScreen({super.key}); | ||||||
| @@ -31,7 +31,7 @@ class _ExploreScreenState extends State<ExploreScreen> { | |||||||
|     final screenWidth = MediaQuery.of(context).size.width; |     final screenWidth = MediaQuery.of(context).size.width; | ||||||
|     final isLargeScreen = screenWidth >= 600; |     final isLargeScreen = screenWidth >= 600; | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
|       fixedAppBarColor: isLargeScreen, |       fixedAppBarColor: isLargeScreen, | ||||||
|       appBarActions: const [NotificationButton()], |       appBarActions: const [NotificationButton()], | ||||||
| @@ -51,7 +51,7 @@ class _ExploreScreenState extends State<ExploreScreen> { | |||||||
|                 Flexible( |                 Flexible( | ||||||
|                   flex: 4, |                   flex: 4, | ||||||
|                   child: _selectedPost == null |                   child: _selectedPost == null | ||||||
|                       ? const SelectionEmptyWidget() |                       ? const PageEmptyWidget() | ||||||
|                       : PostScreenWidget( |                       : PostScreenWidget( | ||||||
|                           key: Key('p${_selectedPost!.id}'), |                           key: Key('p${_selectedPost!.id}'), | ||||||
|                           dataset: _selectedPost!.dataset, |                           dataset: _selectedPost!.dataset, | ||||||
| @@ -62,7 +62,7 @@ class _ExploreScreenState extends State<ExploreScreen> { | |||||||
|             ) |             ) | ||||||
|           : ExploreScreenWidget( |           : ExploreScreenWidget( | ||||||
|               onSelect: (item) { |               onSelect: (item) { | ||||||
|                 router.pushNamed( |                 SolianRouter.router.pushNamed( | ||||||
|                   'posts.screen', |                   'posts.screen', | ||||||
|                   pathParameters: { |                   pathParameters: { | ||||||
|                     'alias': item.alias, |                     'alias': item.alias, | ||||||
| @@ -130,7 +130,7 @@ class _ExploreScreenWidgetState extends State<ExploreScreenWidget> { | |||||||
|             return FloatingActionButton( |             return FloatingActionButton( | ||||||
|               child: const Icon(Icons.edit), |               child: const Icon(Icons.edit), | ||||||
|               onPressed: () async { |               onPressed: () async { | ||||||
|                 final did = await router.pushNamed('posts.moments.editor'); |                 final did = await SolianRouter.router.pushNamed('posts.moments.editor'); | ||||||
|                 if (did == true) _pagingController.refresh(); |                 if (did == true) _pagingController.refresh(); | ||||||
|               }, |               }, | ||||||
|             ); |             ); | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/providers/notify.dart'; | import 'package:solian/providers/notify.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:url_launcher/url_launcher_string.dart'; | import 'package:url_launcher/url_launcher_string.dart'; | ||||||
| import 'package:solian/models/notification.dart' as model; | import 'package:solian/models/notification.dart' as model; | ||||||
| @@ -25,7 +25,7 @@ class _NotificationScreenState extends State<NotificationScreen> { | |||||||
|       nty.allRead(); |       nty.allRead(); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       title: AppLocalizations.of(context)!.notification, |       title: AppLocalizations.of(context)!.notification, | ||||||
| @@ -82,10 +82,10 @@ class NotificationItem extends StatelessWidget { | |||||||
|   const NotificationItem( |   const NotificationItem( | ||||||
|       {super.key, required this.index, required this.item, this.onDismiss}); |       {super.key, required this.index, required this.item, this.onDismiss}); | ||||||
|  |  | ||||||
|   bool hasLinks() => item.links != null && item.links!.isNotEmpty; |   bool get hasLinks => item.links != null && item.links!.isNotEmpty; | ||||||
|  |  | ||||||
|   void showLinks(BuildContext context) { |   void showLinks(BuildContext context) { | ||||||
|     if (!hasLinks()) return; |     if (!hasLinks) return; | ||||||
|  |  | ||||||
|     showModalBottomSheet<void>( |     showModalBottomSheet<void>( | ||||||
|       context: context, |       context: context, | ||||||
| @@ -170,7 +170,7 @@ class NotificationItem extends StatelessWidget { | |||||||
|         child: ListTile( |         child: ListTile( | ||||||
|           title: Text(item.subject), |           title: Text(item.subject), | ||||||
|           subtitle: Text(item.content), |           subtitle: Text(item.content), | ||||||
|           trailing: hasLinks() |           trailing: hasLinks | ||||||
|               ? TextButton( |               ? TextButton( | ||||||
|                   onPressed: () => showLinks(context), |                   onPressed: () => showLinks(context), | ||||||
|                   style: TextButton.styleFrom(shape: const CircleBorder()), |                   style: TextButton.styleFrom(shape: const CircleBorder()), | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:solian/widgets/posts/attachment_editor.dart'; | import 'package:solian/widgets/posts/attachment_editor.dart'; | ||||||
|  |  | ||||||
| class CommentPostArguments { | class CommentPostArguments { | ||||||
| @@ -78,16 +78,16 @@ class _CommentEditorScreenState extends State<CommentEditorScreen> { | |||||||
|       var message = utf8.decode(res.bodyBytes); |       var message = utf8.decode(res.bodyBytes); | ||||||
|       context.showErrorDialog(message); |       context.showErrorDialog(message); | ||||||
|     } else { |     } else { | ||||||
|       if (router.canPop()) { |       if (SolianRouter.router.canPop()) { | ||||||
|         router.pop(true); |         SolianRouter.router.pop(true); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     setState(() => _isSubmitting = false); |     setState(() => _isSubmitting = false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void cancelEditing() { |   void cancelEditing() { | ||||||
|     if (router.canPop()) { |     if (SolianRouter.router.canPop()) { | ||||||
|       router.pop(false); |       SolianRouter.router.pop(false); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -120,7 +120,7 @@ class _CommentEditorScreenState extends State<CommentEditorScreen> { | |||||||
|       ], |       ], | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       title: AppLocalizations.of(context)!.newComment, |       title: AppLocalizations.of(context)!.newComment, | ||||||
|       appBarActions: <Widget>[ |       appBarActions: <Widget>[ | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:solian/widgets/posts/attachment_editor.dart'; | import 'package:solian/widgets/posts/attachment_editor.dart'; | ||||||
|  |  | ||||||
| class MomentEditorScreen extends StatefulWidget { | class MomentEditorScreen extends StatefulWidget { | ||||||
| @@ -68,16 +68,16 @@ class _MomentEditorScreenState extends State<MomentEditorScreen> { | |||||||
|       var message = utf8.decode(res.bodyBytes); |       var message = utf8.decode(res.bodyBytes); | ||||||
|       context.showErrorDialog(message); |       context.showErrorDialog(message); | ||||||
|     } else { |     } else { | ||||||
|       if (router.canPop()) { |       if (SolianRouter.router.canPop()) { | ||||||
|         router.pop(true); |         SolianRouter.router.pop(true); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     setState(() => _isSubmitting = false); |     setState(() => _isSubmitting = false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void cancelEditing() { |   void cancelEditing() { | ||||||
|     if (router.canPop()) { |     if (SolianRouter.router.canPop()) { | ||||||
|       router.pop(false); |       SolianRouter.router.pop(false); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -110,7 +110,7 @@ class _MomentEditorScreenState extends State<MomentEditorScreen> { | |||||||
|       ], |       ], | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|       title: AppLocalizations.of(context)!.newMoment, |       title: AppLocalizations.of(context)!.newMoment, | ||||||
|       appBarActions: <Widget>[ |       appBarActions: <Widget>[ | ||||||
|   | |||||||
| @@ -6,9 +6,9 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | |||||||
| import 'package:solian/models/post.dart'; | import 'package:solian/models/post.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/exts.dart'; | import 'package:solian/widgets/exts.dart'; | ||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/scaffold.dart'; | ||||||
| import 'package:solian/widgets/posts/comment_list.dart'; | import 'package:solian/widgets/posts/comment_list.dart'; | ||||||
| import 'package:solian/widgets/posts/item.dart'; | import 'package:solian/widgets/posts/post.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class PostScreen extends StatelessWidget { | class PostScreen extends StatelessWidget { | ||||||
| @@ -19,7 +19,7 @@ class PostScreen extends StatelessWidget { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IndentWrapper( |     return IndentScaffold( | ||||||
|       title: AppLocalizations.of(context)!.post, |       title: AppLocalizations.of(context)!.post, | ||||||
|       noSafeArea: true, |       noSafeArea: true, | ||||||
|       hideDrawer: true, |       hideDrawer: true, | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| abstract class SolianTheme { | abstract class SolianTheme { | ||||||
|   static bool isColumnMode(BuildContext context) => |   static bool isLargeScreen(BuildContext context) => | ||||||
|       MediaQuery.of(context).size.width > 640; |       MediaQuery.of(context).size.width > 640; | ||||||
|  |  | ||||||
|   static ThemeData build(Brightness brightness) { |   static ThemeData build(Brightness brightness) { | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/providers/friend.dart'; | import 'package:solian/providers/friend.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
|  |  | ||||||
| class FriendPicker extends StatefulWidget { | class FriendPicker extends StatefulWidget { | ||||||
|   const FriendPicker({super.key}); |   const FriendPicker({super.key}); | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|     if (chat.currentCall != null) { |     if (chat.currentCall != null) { | ||||||
|       chat.currentCall!.deactivate(); |       chat.currentCall!.deactivate(); | ||||||
|       chat.currentCall!.dispose(); |       chat.currentCall!.dispose(); | ||||||
|       router.pop(); |       SolianRouter.router.pop(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @@ -52,7 +52,7 @@ class CallOverlay extends StatelessWidget { | |||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|       onTap: () { |       onTap: () { | ||||||
|         router.pushNamed( |         SolianRouter.router.pushNamed( | ||||||
|           'chat.channel.call', |           'chat.channel.call', | ||||||
|           extra: chat.currentCall!.info, |           extra: chat.currentCall!.info, | ||||||
|           pathParameters: {'channel': chat.currentCall!.channel.alias}, |           pathParameters: {'channel': chat.currentCall!.channel.alias}, | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; | |||||||
| import 'package:livekit_client/livekit_client.dart'; | import 'package:livekit_client/livekit_client.dart'; | ||||||
| import 'package:solian/models/account.dart'; | import 'package:solian/models/account.dart'; | ||||||
| import 'package:solian/models/call.dart'; | import 'package:solian/models/call.dart'; | ||||||
| import 'package:solian/widgets/chat/call/no_content.dart'; | import 'package:solian/widgets/chat/call/participant_no_content.dart'; | ||||||
| import 'package:solian/widgets/chat/call/participant_info.dart'; | import 'package:solian/widgets/chat/call/participant_info.dart'; | ||||||
| import 'package:solian/widgets/chat/call/participant_stats.dart'; | import 'package:solian/widgets/chat/call/participant_stats.dart'; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:flutter_animate/flutter_animate.dart'; | import 'package:flutter_animate/flutter_animate.dart'; | ||||||
| import 'package:solian/models/account.dart'; | import 'package:solian/models/account.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'dart:math' as math; | import 'dart:math' as math; | ||||||
| 
 | 
 | ||||||
| class NoContentWidget extends StatefulWidget { | class NoContentWidget extends StatefulWidget { | ||||||
| @@ -97,14 +97,14 @@ class ChannelManageAction extends StatelessWidget { | |||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return IconButton( |     return IconButton( | ||||||
|       onPressed: () async { |       onPressed: () async { | ||||||
|         final result = await router.pushNamed( |         final result = await SolianRouter.router.pushNamed( | ||||||
|           'chat.channel.manage', |           'chat.channel.manage', | ||||||
|           extra: channel, |           extra: channel, | ||||||
|           pathParameters: {'channel': channel.alias}, |           pathParameters: {'channel': channel.alias}, | ||||||
|         ); |         ); | ||||||
|         switch (result) { |         switch (result) { | ||||||
|           case 'disposed': |           case 'disposed': | ||||||
|             if (router.canPop()) router.pop('refresh'); |             if (SolianRouter.router.canPop()) SolianRouter.router.pop('refresh'); | ||||||
|           case 'refresh': |           case 'refresh': | ||||||
|             onUpdate(); |             onUpdate(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ class ChatNewAction extends StatelessWidget { | |||||||
|                   leading: const Icon(Icons.add), |                   leading: const Icon(Icons.add), | ||||||
|                   title: Text(AppLocalizations.of(context)!.chatNewCreate), |                   title: Text(AppLocalizations.of(context)!.chatNewCreate), | ||||||
|                   onTap: () { |                   onTap: () { | ||||||
|                     router.pushNamed('chat.channel.editor').then((did) { |                     SolianRouter.router.pushNamed('chat.channel.editor').then((did) { | ||||||
|                       if (did == true) { |                       if (did == true) { | ||||||
|                         onUpdate(); |                         onUpdate(); | ||||||
|                         if (Navigator.canPop(context)) { |                         if (Navigator.canPop(context)) { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:solian/models/message.dart'; | import 'package:solian/models/message.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:solian/widgets/chat/content.dart'; | import 'package:solian/widgets/chat/message_content.dart'; | ||||||
| import 'package:solian/widgets/posts/content/attachment.dart'; | import 'package:solian/widgets/posts/content/attachment.dart'; | ||||||
| import 'package:timeago/timeago.dart' as timeago; | import 'package:timeago/timeago.dart' as timeago; | ||||||
| import 'dart:math' as math; | import 'dart:math' as math; | ||||||
|   | |||||||
| @@ -1,22 +1,24 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class SelectionEmptyWidget extends StatelessWidget { | class PageEmptyWidget extends StatelessWidget { | ||||||
|   const SelectionEmptyWidget({super.key}); |   const PageEmptyWidget({super.key}); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Center( |     return Material( | ||||||
|       child: Column( |       child: Center( | ||||||
|         mainAxisSize: MainAxisSize.min, |         child: Column( | ||||||
|         children: [ |           mainAxisSize: MainAxisSize.min, | ||||||
|           Image.asset('assets/logo.png', width: 64, height: 64), |           children: [ | ||||||
|           const SizedBox(height: 2), |             Image.asset('assets/logo.png', width: 64, height: 64), | ||||||
|           Text( |             const SizedBox(height: 2), | ||||||
|             AppLocalizations.of(context)!.appName, |             Text( | ||||||
|             style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900), |               AppLocalizations.of(context)!.appName, | ||||||
|           ), |               style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900), | ||||||
|         ], |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,43 +0,0 @@ | |||||||
| import 'package:flutter/material.dart'; |  | ||||||
| import 'package:solian/router.dart'; |  | ||||||
| import 'package:solian/widgets/common_wrapper.dart'; |  | ||||||
| import 'package:solian/widgets/navigation_drawer.dart'; |  | ||||||
|  |  | ||||||
| class IndentWrapper extends LayoutWrapper { |  | ||||||
|   final bool hideDrawer; |  | ||||||
|   final bool fixedAppBarColor; |  | ||||||
|  |  | ||||||
|   const IndentWrapper({ |  | ||||||
|     super.key, |  | ||||||
|     super.child, |  | ||||||
|     required super.title, |  | ||||||
|     super.floatingActionButton, |  | ||||||
|     super.appBarActions, |  | ||||||
|     this.hideDrawer = false, |  | ||||||
|     this.fixedAppBarColor = false, |  | ||||||
|     super.noSafeArea = false, |  | ||||||
|   }) : super(); |  | ||||||
|  |  | ||||||
|   @override |  | ||||||
|   Widget build(BuildContext context) { |  | ||||||
|     final content = child ?? Container(); |  | ||||||
|  |  | ||||||
|     return Scaffold( |  | ||||||
|       appBar: AppBar( |  | ||||||
|         leading: hideDrawer |  | ||||||
|             ? IconButton( |  | ||||||
|                 icon: const Icon(Icons.arrow_back), |  | ||||||
|                 onPressed: () => router.pop(), |  | ||||||
|               ) |  | ||||||
|             : null, |  | ||||||
|         title: Text(title), |  | ||||||
|         actions: appBarActions, |  | ||||||
|         centerTitle: false, |  | ||||||
|         elevation: fixedAppBarColor ? 4 : null, |  | ||||||
|       ), |  | ||||||
|       floatingActionButton: floatingActionButton, |  | ||||||
|       drawer: const SolianNavigationDrawer(), |  | ||||||
|       body: noSafeArea ? content : SafeArea(child: content), |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										31
									
								
								lib/widgets/layouts/two_column.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/widgets/layouts/two_column.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:solian/widgets/empty.dart'; | ||||||
|  |  | ||||||
|  | class TwoColumnLayout extends StatelessWidget { | ||||||
|  |   final Widget sideChild; | ||||||
|  |   final Widget? mainChild; | ||||||
|  |  | ||||||
|  |   const TwoColumnLayout({ | ||||||
|  |     super.key, | ||||||
|  |     required this.sideChild, | ||||||
|  |     required this.mainChild, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return ScaffoldMessenger( | ||||||
|  |       child: Scaffold( | ||||||
|  |         body: Row( | ||||||
|  |           children: [ | ||||||
|  |             SizedBox( | ||||||
|  |               width: 400, | ||||||
|  |               child: sideChild, | ||||||
|  |             ), | ||||||
|  |             const VerticalDivider(width: 0.3, thickness: 0.3), | ||||||
|  |             Expanded(child: mainChild ?? const PageEmptyWidget()), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; | |||||||
| import 'package:solian/providers/navigation.dart'; | import 'package:solian/providers/navigation.dart'; | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  | import 'package:solian/utils/theme.dart'; | ||||||
|  |  | ||||||
| class SolianNavigationDrawer extends StatefulWidget { | class SolianNavigationDrawer extends StatefulWidget { | ||||||
|   const SolianNavigationDrawer({super.key}); |   const SolianNavigationDrawer({super.key}); | ||||||
| @@ -17,7 +18,7 @@ class _SolianNavigationDrawerState extends State<SolianNavigationDrawer> { | |||||||
|   void _onSelect(String name, int idx) { |   void _onSelect(String name, int idx) { | ||||||
|     setState(() => _selectedIndex = idx); |     setState(() => _selectedIndex = idx); | ||||||
|     context.read<NavigationProvider>().selectedIndex = idx; |     context.read<NavigationProvider>().selectedIndex = idx; | ||||||
|     router.goNamed(name); |     SolianRouter.router.goNamed(name); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -59,6 +60,9 @@ class _SolianNavigationDrawerState extends State<SolianNavigationDrawer> { | |||||||
|  |  | ||||||
|     return NavigationDrawer( |     return NavigationDrawer( | ||||||
|       selectedIndex: _selectedIndex, |       selectedIndex: _selectedIndex, | ||||||
|  |       elevation: SolianTheme.isLargeScreen(context) ? 20 : 0, | ||||||
|  |       shadowColor: SolianTheme.isLargeScreen(context) ? Theme.of(context).shadowColor : null, | ||||||
|  |       surfaceTintColor: Theme.of(context).colorScheme.background, | ||||||
|       onDestinationSelected: (int idx) { |       onDestinationSelected: (int idx) { | ||||||
|         final element = navigationItems[idx]; |         final element = navigationItems[idx]; | ||||||
|         _onSelect(element.$2, idx); |         _onSelect(element.$2, idx); | ||||||
|   | |||||||
| @@ -85,7 +85,7 @@ class _NotificationButtonState extends State<NotificationButton> { | |||||||
|       child: IconButton( |       child: IconButton( | ||||||
|         icon: const Icon(Icons.notifications), |         icon: const Icon(Icons.notifications), | ||||||
|         onPressed: () { |         onPressed: () { | ||||||
|           router.pushNamed('notification'); |           SolianRouter.router.pushNamed('notification'); | ||||||
|         }, |         }, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/screens/posts/comment_editor.dart'; | import 'package:solian/screens/posts/comment_editor.dart'; | ||||||
| import 'package:solian/utils/service_url.dart'; | import 'package:solian/utils/service_url.dart'; | ||||||
| import 'package:solian/widgets/posts/item.dart'; | import 'package:solian/widgets/posts/post.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class CommentList extends StatefulWidget { | class CommentList extends StatefulWidget { | ||||||
| @@ -120,7 +120,7 @@ class CommentListHeader extends StatelessWidget { | |||||||
|               if (snapshot.hasData && snapshot.data == true) { |               if (snapshot.hasData && snapshot.data == true) { | ||||||
|                 return TextButton( |                 return TextButton( | ||||||
|                   onPressed: () async { |                   onPressed: () async { | ||||||
|                     final did = await router.pushNamed( |                     final did = await SolianRouter.router.pushNamed( | ||||||
|                       'posts.comments.editor', |                       'posts.comments.editor', | ||||||
|                       extra: CommentPostArguments(related: related), |                       extra: CommentPostArguments(related: related), | ||||||
|                     ); |                     ); | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||||
| import 'package:solian/models/post.dart'; | import 'package:solian/models/post.dart'; | ||||||
| import 'package:solian/widgets/account/avatar.dart'; | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
| import 'package:solian/widgets/posts/comment_list.dart'; | import 'package:solian/widgets/posts/comment_list.dart'; | ||||||
| import 'package:solian/widgets/posts/content/article.dart'; | import 'package:solian/widgets/posts/content/article.dart'; | ||||||
| import 'package:solian/widgets/posts/content/attachment.dart'; | import 'package:solian/widgets/posts/content/attachment.dart'; | ||||||
| import 'package:solian/widgets/posts/content/moment.dart'; | import 'package:solian/widgets/posts/content/moment.dart'; | ||||||
| import 'package:solian/widgets/posts/item_action.dart'; | import 'package:solian/widgets/posts/post_action.dart'; | ||||||
| import 'package:solian/widgets/posts/reaction_list.dart'; | import 'package:solian/widgets/posts/reaction_list.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:timeago/timeago.dart' as timeago; | import 'package:timeago/timeago.dart' as timeago; | ||||||
| @@ -5,7 +5,7 @@ import 'package:solian/providers/auth.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
| import 'package:solian/screens/posts/comment_editor.dart'; | import 'package:solian/screens/posts/comment_editor.dart'; | ||||||
| import 'package:solian/widgets/posts/item_deletion.dart'; | import 'package:solian/widgets/posts/post_deletion.dart'; | ||||||
| 
 | 
 | ||||||
| class PostItemAction extends StatelessWidget { | class PostItemAction extends StatelessWidget { | ||||||
|   final Post item; |   final Post item; | ||||||
| @@ -23,17 +23,17 @@ class PostItemAction extends StatelessWidget { | |||||||
|     bool ok = false; |     bool ok = false; | ||||||
|     switch (item.modelType) { |     switch (item.modelType) { | ||||||
|       case 'article': |       case 'article': | ||||||
|         ok = await router.pushNamed( |         ok = await SolianRouter.router.pushNamed( | ||||||
|           'posts.articles.editor', |           'posts.articles.editor', | ||||||
|           extra: item, |           extra: item, | ||||||
|         ) as bool; |         ) as bool; | ||||||
|       case 'moment': |       case 'moment': | ||||||
|         ok = await router.pushNamed( |         ok = await SolianRouter.router.pushNamed( | ||||||
|           'posts.moments.editor', |           'posts.moments.editor', | ||||||
|           extra: item, |           extra: item, | ||||||
|         ) as bool; |         ) as bool; | ||||||
|       case 'comment': |       case 'comment': | ||||||
|         ok = await router.pushNamed( |         ok = await SolianRouter.router.pushNamed( | ||||||
|           'posts.comments.editor', |           'posts.comments.editor', | ||||||
|           extra: CommentPostArguments(editing: item), |           extra: CommentPostArguments(editing: item), | ||||||
|         ) as bool; |         ) as bool; | ||||||
| @@ -1,19 +1,26 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:solian/utils/theme.dart'; | ||||||
| import 'package:solian/widgets/navigation_drawer.dart'; | import 'package:solian/widgets/navigation_drawer.dart'; | ||||||
| 
 | 
 | ||||||
| class LayoutWrapper extends StatelessWidget { | class IndentScaffold extends StatelessWidget { | ||||||
|   final Widget? child; |   final Widget? child; | ||||||
|   final Widget? floatingActionButton; |   final Widget? floatingActionButton; | ||||||
|  |   final Widget? appBarLeading; | ||||||
|   final List<Widget>? appBarActions; |   final List<Widget>? appBarActions; | ||||||
|   final bool noSafeArea; |   final bool noSafeArea; | ||||||
|  |   final bool hideDrawer; | ||||||
|  |   final bool fixedAppBarColor; | ||||||
|   final String title; |   final String title; | ||||||
| 
 | 
 | ||||||
|   const LayoutWrapper({ |   const IndentScaffold({ | ||||||
|     super.key, |     super.key, | ||||||
|     this.child, |     this.child, | ||||||
|     required this.title, |     required this.title, | ||||||
|     this.floatingActionButton, |     this.floatingActionButton, | ||||||
|  |     this.appBarLeading, | ||||||
|     this.appBarActions, |     this.appBarActions, | ||||||
|  |     this.hideDrawer = false, | ||||||
|  |     this.fixedAppBarColor = false, | ||||||
|     this.noSafeArea = false, |     this.noSafeArea = false, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @@ -24,11 +31,14 @@ class LayoutWrapper extends StatelessWidget { | |||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       appBar: AppBar( |       appBar: AppBar( | ||||||
|         title: Text(title), |         title: Text(title), | ||||||
|  |         leading: appBarLeading, | ||||||
|         actions: appBarActions, |         actions: appBarActions, | ||||||
|         centerTitle: false, |         centerTitle: false, | ||||||
|  |         elevation: fixedAppBarColor ? 4 : null, | ||||||
|       ), |       ), | ||||||
|       floatingActionButton: floatingActionButton, |       floatingActionButton: floatingActionButton, | ||||||
|       drawer: const SolianNavigationDrawer(), |       drawer: !hideDrawer ? const SolianNavigationDrawer() : null, | ||||||
|  |       drawerScrimColor: SolianTheme.isLargeScreen(context) ? Colors.transparent : null, | ||||||
|       body: noSafeArea ? content : SafeArea(child: content), |       body: noSafeArea ? content : SafeArea(child: content), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -32,7 +32,7 @@ class SignInRequiredScreen extends StatelessWidget { | |||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|       onTap: () { |       onTap: () { | ||||||
|         router.goNamed('account'); |         SolianRouter.router.goNamed('account'); | ||||||
|       }, |       }, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
|  |  | ||||||
| #include "generated_plugin_registrant.h" | #include "generated_plugin_registrant.h" | ||||||
|  |  | ||||||
|  | #include <desktop_drop/desktop_drop_plugin.h> | ||||||
| #include <file_selector_linux/file_selector_plugin.h> | #include <file_selector_linux/file_selector_plugin.h> | ||||||
| #include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h> | #include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h> | ||||||
| #include <flutter_webrtc/flutter_web_r_t_c_plugin.h> | #include <flutter_webrtc/flutter_web_r_t_c_plugin.h> | ||||||
| @@ -14,6 +15,9 @@ | |||||||
| #include <url_launcher_linux/url_launcher_plugin.h> | #include <url_launcher_linux/url_launcher_plugin.h> | ||||||
|  |  | ||||||
| void fl_register_plugins(FlPluginRegistry* registry) { | void fl_register_plugins(FlPluginRegistry* registry) { | ||||||
|  |   g_autoptr(FlPluginRegistrar) desktop_drop_registrar = | ||||||
|  |       fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin"); | ||||||
|  |   desktop_drop_plugin_register_with_registrar(desktop_drop_registrar); | ||||||
|   g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = |   g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = | ||||||
|       fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); |       fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); | ||||||
|   file_selector_plugin_register_with_registrar(file_selector_linux_registrar); |   file_selector_plugin_register_with_registrar(file_selector_linux_registrar); | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| # | # | ||||||
|  |  | ||||||
| list(APPEND FLUTTER_PLUGIN_LIST | list(APPEND FLUTTER_PLUGIN_LIST | ||||||
|  |   desktop_drop | ||||||
|   file_selector_linux |   file_selector_linux | ||||||
|   flutter_secure_storage_linux |   flutter_secure_storage_linux | ||||||
|   flutter_webrtc |   flutter_webrtc | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import FlutterMacOS | |||||||
| import Foundation | import Foundation | ||||||
|  |  | ||||||
| import connectivity_plus | import connectivity_plus | ||||||
|  | import desktop_drop | ||||||
| import device_info_plus | import device_info_plus | ||||||
| import file_selector_macos | import file_selector_macos | ||||||
| import flutter_local_notifications | import flutter_local_notifications | ||||||
| @@ -23,6 +24,7 @@ import wakelock_plus | |||||||
|  |  | ||||||
| func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | ||||||
|   ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) |   ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) | ||||||
|  |   DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) | ||||||
|   DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) |   DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) | ||||||
|   FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) |   FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) | ||||||
|   FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) |   FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) | ||||||
|   | |||||||
| @@ -177,6 +177,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.7.10" |     version: "0.7.10" | ||||||
|  |   desktop_drop: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: desktop_drop | ||||||
|  |       sha256: d55a010fe46c8e8fcff4ea4b451a9ff84a162217bdb3b2a0aa1479776205e15d | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "0.4.4" | ||||||
|   device_info_plus: |   device_info_plus: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
|   | |||||||
| @@ -70,6 +70,7 @@ dependencies: | |||||||
|   file_picker: ^8.0.3 |   file_picker: ^8.0.3 | ||||||
|   package_info_plus: ^7.0.0 |   package_info_plus: ^7.0.0 | ||||||
|   cached_network_image: ^3.3.1 |   cached_network_image: ^3.3.1 | ||||||
|  |   desktop_drop: ^0.4.4 | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| #include "generated_plugin_registrant.h" | #include "generated_plugin_registrant.h" | ||||||
|  |  | ||||||
| #include <connectivity_plus/connectivity_plus_windows_plugin.h> | #include <connectivity_plus/connectivity_plus_windows_plugin.h> | ||||||
|  | #include <desktop_drop/desktop_drop_plugin.h> | ||||||
| #include <file_selector_windows/file_selector_windows.h> | #include <file_selector_windows/file_selector_windows.h> | ||||||
| #include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h> | #include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h> | ||||||
| #include <flutter_webrtc/flutter_web_r_t_c_plugin.h> | #include <flutter_webrtc/flutter_web_r_t_c_plugin.h> | ||||||
| @@ -20,6 +21,8 @@ | |||||||
| void RegisterPlugins(flutter::PluginRegistry* registry) { | void RegisterPlugins(flutter::PluginRegistry* registry) { | ||||||
|   ConnectivityPlusWindowsPluginRegisterWithRegistrar( |   ConnectivityPlusWindowsPluginRegisterWithRegistrar( | ||||||
|       registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); |       registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); | ||||||
|  |   DesktopDropPluginRegisterWithRegistrar( | ||||||
|  |       registry->GetRegistrarForPlugin("DesktopDropPlugin")); | ||||||
|   FileSelectorWindowsRegisterWithRegistrar( |   FileSelectorWindowsRegisterWithRegistrar( | ||||||
|       registry->GetRegistrarForPlugin("FileSelectorWindows")); |       registry->GetRegistrarForPlugin("FileSelectorWindows")); | ||||||
|   FlutterSecureStorageWindowsPluginRegisterWithRegistrar( |   FlutterSecureStorageWindowsPluginRegisterWithRegistrar( | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|  |  | ||||||
| list(APPEND FLUTTER_PLUGIN_LIST | list(APPEND FLUTTER_PLUGIN_LIST | ||||||
|   connectivity_plus |   connectivity_plus | ||||||
|  |   desktop_drop | ||||||
|   file_selector_windows |   file_selector_windows | ||||||
|   flutter_secure_storage_windows |   flutter_secure_storage_windows | ||||||
|   flutter_webrtc |   flutter_webrtc | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user