🐛 Bug fixes and optimization
This commit is contained in:
		| @@ -13,6 +13,7 @@ import 'package:solian/utils/timeago.dart'; | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||
| import 'package:solian/utils/video_player.dart'; | ||||
| import 'package:solian/widgets/chat/call/call_overlay.dart'; | ||||
| import 'package:solian/widgets/provider_init.dart'; | ||||
|  | ||||
| void main() { | ||||
|   WidgetsFlutterBinding.ensureInitialized(); | ||||
| @@ -52,7 +53,9 @@ class SolianApp extends StatelessWidget { | ||||
|               OverlayEntry(builder: (context) { | ||||
|                 return ScaffoldMessenger( | ||||
|                   child: Scaffold( | ||||
|                     body: child ?? Container(), | ||||
|                     body: ProviderInitializer( | ||||
|                       child: child ?? Container(), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ); | ||||
|               }), | ||||
|   | ||||
| @@ -31,6 +31,8 @@ class ChatProvider extends ChangeNotifier { | ||||
|  | ||||
|   PagingController<int, Message>? historyPagingController; | ||||
|  | ||||
|   WebSocketChannel? _channel; | ||||
|  | ||||
|   Future<WebSocketChannel?> connect(AuthProvider auth) async { | ||||
|     if (auth.client == null) await auth.loadClient(); | ||||
|     if (!await auth.isAuthorized()) return null; | ||||
| @@ -46,11 +48,12 @@ class ChatProvider extends ChangeNotifier { | ||||
|       queryParameters: {'tk': Uri.encodeComponent(auth.client!.currentToken!)}, | ||||
|     ); | ||||
|  | ||||
|     final channel = WebSocketChannel.connect(uri); | ||||
|  | ||||
|     isOpened = true; | ||||
|  | ||||
|     channel.stream.listen( | ||||
|     _channel = WebSocketChannel.connect(uri); | ||||
|     await _channel!.ready; | ||||
|  | ||||
|     _channel!.stream.listen( | ||||
|       (event) { | ||||
|         final result = NetworkPackage.fromJson(jsonDecode(event)); | ||||
|         if (focusChannel == null || historyPagingController == null) return; | ||||
| @@ -90,11 +93,16 @@ class ChatProvider extends ChangeNotifier { | ||||
|         } | ||||
|         notifyListeners(); | ||||
|       }, | ||||
|       onError: (_, __) => connect(auth), | ||||
|       onDone: () => connect(auth), | ||||
|       onError: (_, __) => Future.delayed(const Duration(seconds: 3), () => connect(auth)), | ||||
|       onDone: () => Future.delayed(const Duration(seconds: 1), () => connect(auth)), | ||||
|     ); | ||||
|  | ||||
|     return channel; | ||||
|     return _channel!; | ||||
|   } | ||||
|  | ||||
|   void disconnect() { | ||||
|     _channel = null; | ||||
|     isOpened = false; | ||||
|   } | ||||
|  | ||||
|   Future<void> fetchMessages(int pageKey, BuildContext context) async { | ||||
|   | ||||
| @@ -64,6 +64,8 @@ class NotifyProvider extends ChangeNotifier { | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   WebSocketChannel? _channel; | ||||
|  | ||||
|   Future<WebSocketChannel?> connect( | ||||
|     AuthProvider auth, { | ||||
|     Keypair? Function(String id)? onKexRequest, | ||||
| @@ -83,10 +85,12 @@ class NotifyProvider extends ChangeNotifier { | ||||
|       queryParameters: {'tk': Uri.encodeComponent(auth.client!.currentToken!)}, | ||||
|     ); | ||||
|  | ||||
|     final channel = WebSocketChannel.connect(uri); | ||||
|     await channel.ready; | ||||
|     isOpened = true; | ||||
|  | ||||
|     channel.stream.listen( | ||||
|     _channel = WebSocketChannel.connect(uri); | ||||
|     await _channel!.ready; | ||||
|  | ||||
|     _channel!.stream.listen( | ||||
|       (event) { | ||||
|         final result = NetworkPackage.fromJson(jsonDecode(event)); | ||||
|         switch (result.method) { | ||||
| @@ -101,7 +105,7 @@ class NotifyProvider extends ChangeNotifier { | ||||
|             if (onKexRequest == null || result.payload == null) break; | ||||
|             final resp = onKexRequest(result.payload!['keypair_id']); | ||||
|             if (resp == null) break; | ||||
|             channel.sink.add(jsonEncode( | ||||
|             _channel!.sink.add(jsonEncode( | ||||
|               NetworkPackage(method: 'kex.provide', payload: { | ||||
|                 'request_id': result.payload!['request_id'], | ||||
|                 'keypair_id': resp.id, | ||||
| @@ -121,11 +125,16 @@ class NotifyProvider extends ChangeNotifier { | ||||
|             break; | ||||
|         } | ||||
|       }, | ||||
|       onError: (_, __) => connect(auth), | ||||
|       onDone: () => connect(auth), | ||||
|       onError: (_, __) => Future.delayed(const Duration(seconds: 3), () => connect(auth)), | ||||
|       onDone: () => Future.delayed(const Duration(seconds: 1), () => connect(auth)), | ||||
|     ); | ||||
|  | ||||
|     return channel; | ||||
|     return _channel!; | ||||
|   } | ||||
|  | ||||
|   void disconnect() { | ||||
|     _channel = null; | ||||
|     isOpened = false; | ||||
|   } | ||||
|  | ||||
|   void notifyMessage(String title, String body) { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:solian/providers/auth.dart'; | ||||
| import 'package:solian/providers/chat.dart'; | ||||
| import 'package:solian/providers/keypair.dart'; | ||||
| import 'package:solian/providers/notify.dart'; | ||||
| import 'package:solian/router.dart'; | ||||
| import 'package:solian/utils/theme.dart'; | ||||
| import 'package:solian/widgets/account/account_avatar.dart'; | ||||
| @@ -82,6 +84,8 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> { | ||||
|             onTap: () { | ||||
|               auth.signoff(); | ||||
|               keypair.clearKeys(); | ||||
|               context.read<NotifyProvider>().disconnect(); | ||||
|               context.read<ChatProvider>().disconnect(); | ||||
|               setState(() { | ||||
|                 _isAuthorized = false; | ||||
|               }); | ||||
|   | ||||
| @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:solian/providers/auth.dart'; | ||||
| import 'package:solian/providers/chat.dart'; | ||||
| import 'package:solian/providers/notify.dart'; | ||||
| import 'package:solian/router.dart'; | ||||
| import 'package:solian/utils/services_url.dart'; | ||||
| import 'package:solian/widgets/exts.dart'; | ||||
| @@ -21,6 +23,8 @@ class SignInScreen extends StatelessWidget { | ||||
|     final password = _passwordController.value.text; | ||||
|     if (username.isEmpty || password.isEmpty) return; | ||||
|     auth.signin(context, username, password).then((_) { | ||||
|       context.read<ChatProvider>().connect(auth); | ||||
|       context.read<NotifyProvider>().connect(auth); | ||||
|       SolianRouter.router.pop(true); | ||||
|     }).catchError((e) { | ||||
|       List<String> messages = e.toString().split('\n'); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import 'dart:convert'; | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_animate/flutter_animate.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:solian/models/pagination.dart'; | ||||
| import 'package:solian/models/post.dart'; | ||||
| @@ -133,14 +134,12 @@ class _ExplorePostWidgetState extends State<ExplorePostWidget> { | ||||
|                           return Container(); | ||||
|                         } | ||||
|  | ||||
|                         return Container( | ||||
|                           height: 120, | ||||
|                           decoration: BoxDecoration( | ||||
|                             border: Border( | ||||
|                               bottom: BorderSide(width: 0.3, color: Theme.of(context).dividerColor), | ||||
|                             ), | ||||
|                           ), | ||||
|                           child: const RealmShortcuts(), | ||||
|                         return Padding( | ||||
|                           padding: const EdgeInsets.only(bottom: 8), | ||||
|                           child: const Material( | ||||
|                             elevation: 8, | ||||
|                             child: SizedBox(height: 120, child: RealmShortcuts()), | ||||
|                           ).animate().fade().slideY(begin: -1, end: 0, curve: Curves.fastEaseInToSlowEaseOut), | ||||
|                         ); | ||||
|                       }, | ||||
|                     ), | ||||
|   | ||||
| @@ -1,57 +1,12 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:solian/providers/auth.dart'; | ||||
| import 'package:solian/providers/keypair.dart'; | ||||
| import 'package:solian/providers/notify.dart'; | ||||
| import 'package:solian/router.dart'; | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||
| import 'package:badges/badges.dart' as badge; | ||||
|  | ||||
| class NotificationButton extends StatefulWidget { | ||||
| class NotificationButton extends StatelessWidget { | ||||
|   const NotificationButton({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<NotificationButton> createState() => _NotificationButtonState(); | ||||
| } | ||||
|  | ||||
| class _NotificationButtonState extends State<NotificationButton> { | ||||
|   void connect() async { | ||||
|     final auth = context.read<AuthProvider>(); | ||||
|     final nty = context.read<NotifyProvider>(); | ||||
|     final keypair = context.read<KeypairProvider>(); | ||||
|  | ||||
|     if (nty.isOpened) return; | ||||
|  | ||||
|     final notify = ScaffoldMessenger.of(context).showSnackBar( | ||||
|       SnackBar( | ||||
|         content: Text(AppLocalizations.of(context)!.connectingServer), | ||||
|         duration: const Duration(minutes: 1), | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
|     if (await auth.isAuthorized()) { | ||||
|       if (auth.client == null) { | ||||
|         await auth.loadClient(); | ||||
|       } | ||||
|  | ||||
|       nty.fetch(auth); | ||||
|       keypair.channel = await nty.connect( | ||||
|         auth, | ||||
|         onKexRequest: keypair.provideKeypair, | ||||
|         onKexProvide: keypair.receiveKeypair, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     notify.close(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|  | ||||
|     Future.delayed(Duration.zero, () => connect()); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final nty = context.watch<NotifyProvider>(); | ||||
|   | ||||
							
								
								
									
										59
									
								
								lib/widgets/provider_init.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								lib/widgets/provider_init.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:solian/providers/auth.dart'; | ||||
| import 'package:solian/providers/chat.dart'; | ||||
| import 'package:solian/providers/keypair.dart'; | ||||
| import 'package:solian/providers/notify.dart'; | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||
|  | ||||
| class ProviderInitializer extends StatefulWidget { | ||||
|   final Widget child; | ||||
|  | ||||
|   const ProviderInitializer({super.key, required this.child}); | ||||
|  | ||||
|   @override | ||||
|   State<ProviderInitializer> createState() => _ProviderInitializerState(); | ||||
| } | ||||
|  | ||||
| class _ProviderInitializerState extends State<ProviderInitializer> { | ||||
|   void connect() async { | ||||
|     final auth = context.read<AuthProvider>(); | ||||
|     final nty = context.read<NotifyProvider>(); | ||||
|     final chat = context.read<ChatProvider>(); | ||||
|     final keypair = context.read<KeypairProvider>(); | ||||
|  | ||||
|     final notify = ScaffoldMessenger.of(context).showSnackBar( | ||||
|       SnackBar( | ||||
|         content: Text(AppLocalizations.of(context)!.connectingServer), | ||||
|         duration: const Duration(minutes: 1), | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
|     if (await auth.isAuthorized()) { | ||||
|       if (auth.client == null) { | ||||
|         await auth.loadClient(); | ||||
|       } | ||||
|  | ||||
|       nty.fetch(auth); | ||||
|       chat.connect(auth); | ||||
|       keypair.channel = await nty.connect( | ||||
|         auth, | ||||
|         onKexRequest: keypair.provideKeypair, | ||||
|         onKexProvide: keypair.receiveKeypair, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     notify.close(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     Future.delayed(Duration.zero, () => connect()); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return widget.child; | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user