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