⚡ Better websocket reconnection and maintainer
This commit is contained in:
parent
b9461e5019
commit
f43f9e91f6
@ -17,11 +17,11 @@ import 'package:solian/utils/services_url.dart';
|
||||
import 'package:solian/widgets/chat/call/exts.dart';
|
||||
import 'package:solian/widgets/exts.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
import 'package:web_socket_channel/status.dart' as status;
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class ChatProvider extends ChangeNotifier {
|
||||
bool isOpened = false;
|
||||
bool isCallShown = false;
|
||||
|
||||
Call? ongoingCall;
|
||||
@ -31,12 +31,16 @@ class ChatProvider extends ChangeNotifier {
|
||||
|
||||
PagingController<int, Message>? historyPagingController;
|
||||
|
||||
WebSocketChannel? _channel;
|
||||
IOWebSocketChannel? _channel;
|
||||
|
||||
Future<WebSocketChannel?> connect(AuthProvider auth, {noRetry = false}) async {
|
||||
Future<IOWebSocketChannel?> connect(AuthProvider auth, {noRetry = false}) async {
|
||||
if (auth.client == null) await auth.loadClient();
|
||||
if (!await auth.isAuthorized()) return null;
|
||||
|
||||
if (_channel != null && (_channel!.innerWebSocket?.readyState ?? 0) < 2) {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
var ori = getRequestUri('messaging', '/api/ws');
|
||||
var uri = Uri(
|
||||
scheme: ori.scheme.replaceFirst('http', 'ws'),
|
||||
@ -46,10 +50,8 @@ class ChatProvider extends ChangeNotifier {
|
||||
queryParameters: {'tk': Uri.encodeComponent(auth.client!.currentToken!)},
|
||||
);
|
||||
|
||||
isOpened = true;
|
||||
|
||||
try {
|
||||
_channel = WebSocketChannel.connect(uri);
|
||||
_channel = IOWebSocketChannel.connect(uri);
|
||||
await _channel!.ready;
|
||||
} catch (e) {
|
||||
if (!noRetry) {
|
||||
@ -108,8 +110,7 @@ class ChatProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
_channel = null;
|
||||
isOpened = false;
|
||||
_channel?.sink.close(status.goingAway);
|
||||
}
|
||||
|
||||
Future<void> fetchMessages(int pageKey, BuildContext context) async {
|
||||
|
@ -45,13 +45,11 @@ class KeypairProvider extends ChangeNotifier {
|
||||
void receiveKeypair(Keypair kp) {
|
||||
keys[kp.id] = kp;
|
||||
requestingKeys.remove(kp.id);
|
||||
saveKeys();
|
||||
notifyListeners();
|
||||
saveKeys();
|
||||
}
|
||||
|
||||
Keypair? provideKeypair(String id) {
|
||||
print(id);
|
||||
print(keys[id]);
|
||||
return keys[id];
|
||||
}
|
||||
|
||||
@ -79,9 +77,11 @@ class KeypairProvider extends ChangeNotifier {
|
||||
saveKeys();
|
||||
}
|
||||
|
||||
bool requestKey(String id, String algorithm, int uid) {
|
||||
if (channel == null) return false;
|
||||
if (requestingKeys.contains(id)) return false;
|
||||
void requestKey(String id, String algorithm, int uid) {
|
||||
if (channel == null) return;
|
||||
if (requestingKeys.contains(id)) return;
|
||||
|
||||
print('requested $id');
|
||||
|
||||
channel!.sink.add(jsonEncode(
|
||||
NetworkPackage(method: 'kex.request', payload: {
|
||||
@ -95,7 +95,6 @@ class KeypairProvider extends ChangeNotifier {
|
||||
|
||||
requestingKeys.add(id);
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
String? encodeViaAESKey(String keypairId, String content) {
|
||||
|
@ -10,11 +10,11 @@ import 'package:solian/models/pagination.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/utils/services_url.dart';
|
||||
import 'package:solian/models/notification.dart' as model;
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
import 'package:web_socket_channel/status.dart' as status;
|
||||
import 'dart:math' as math;
|
||||
|
||||
class NotifyProvider extends ChangeNotifier {
|
||||
bool isOpened = false;
|
||||
int unreadAmount = 0;
|
||||
|
||||
List<model.Notification> notifications = List.empty(growable: true);
|
||||
@ -64,10 +64,9 @@ class NotifyProvider extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
WebSocketChannel? _channel;
|
||||
IOWebSocketChannel? _channel;
|
||||
|
||||
Future<WebSocketChannel?> connect(
|
||||
AuthProvider auth, {
|
||||
Future<IOWebSocketChannel?> connect(AuthProvider auth, {
|
||||
Keypair? Function(String id)? onKexRequest,
|
||||
Function(Keypair kp)? onKexProvide,
|
||||
bool noRetry = false,
|
||||
@ -75,8 +74,9 @@ class NotifyProvider extends ChangeNotifier {
|
||||
if (auth.client == null) await auth.loadClient();
|
||||
if (!await auth.isAuthorized()) return null;
|
||||
|
||||
await auth.client!.refreshToken(auth.client!.currentRefreshToken!);
|
||||
|
||||
if (_channel != null && (_channel!.innerWebSocket?.readyState ?? 0) < 2) {
|
||||
return _channel;
|
||||
}
|
||||
var ori = getRequestUri('passport', '/api/ws');
|
||||
var uri = Uri(
|
||||
scheme: ori.scheme.replaceFirst('http', 'ws'),
|
||||
@ -86,10 +86,8 @@ class NotifyProvider extends ChangeNotifier {
|
||||
queryParameters: {'tk': Uri.encodeComponent(auth.client!.currentToken!)},
|
||||
);
|
||||
|
||||
isOpened = true;
|
||||
|
||||
try {
|
||||
_channel = WebSocketChannel.connect(uri);
|
||||
_channel = IOWebSocketChannel.connect(uri);
|
||||
await _channel!.ready;
|
||||
} catch (e) {
|
||||
if (!noRetry) {
|
||||
@ -101,7 +99,7 @@ class NotifyProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
_channel!.stream.listen(
|
||||
(event) {
|
||||
(event) {
|
||||
final result = NetworkPackage.fromJson(jsonDecode(event));
|
||||
switch (result.method) {
|
||||
case 'notifications.new':
|
||||
@ -143,8 +141,7 @@ class NotifyProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
_channel = null;
|
||||
isOpened = false;
|
||||
_channel?.sink.close(status.goingAway);
|
||||
}
|
||||
|
||||
void notifyMessage(String title, String body) {
|
||||
|
@ -38,7 +38,6 @@ class _ChatMemberScreenState extends State<ChatMemberScreen> {
|
||||
_selfId = prof['id'];
|
||||
|
||||
var uri = getRequestUri('messaging', '/api/channels/${widget.realm}/${widget.channel.alias}/members');
|
||||
print(uri);
|
||||
|
||||
var res = await auth.client!.get(uri);
|
||||
if (res.statusCode == 200) {
|
||||
|
@ -162,7 +162,7 @@ class _ChatWidgetState extends State<ChatWidget> {
|
||||
Future.delayed(Duration.zero, () async {
|
||||
final auth = context.read<AuthProvider>();
|
||||
|
||||
if (!_chat.isOpened) await _chat.connect(auth);
|
||||
await _chat.connect(auth);
|
||||
|
||||
_chat.fetchOngoingCall(widget.alias, widget.realm);
|
||||
_chat.fetchChannel(context, auth, widget.alias, widget.realm).then((result) {
|
||||
|
@ -55,12 +55,11 @@ class _ChatMessageContentState extends State<ChatMessageContent> {
|
||||
final keypair = context.watch<KeypairProvider>();
|
||||
if (keypair.keys[widget.item.decodedContent['keypair_id']] == null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (keypair.requestKey(
|
||||
keypair.requestKey(
|
||||
widget.item.decodedContent['keypair_id'],
|
||||
widget.item.decodedContent['algorithm'],
|
||||
widget.item.sender.account.externalId!,
|
||||
)) {
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
content = keypair.decodeViaAESKey(
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
@ -43,6 +45,11 @@ class _ProviderInitializerState extends State<ProviderInitializer> {
|
||||
onKexRequest: keypair.provideKeypair,
|
||||
onKexProvide: keypair.receiveKeypair,
|
||||
);
|
||||
|
||||
Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
nty.connect(auth);
|
||||
chat.connect(auth);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
context.showErrorDialog(e);
|
||||
|
Loading…
Reference in New Issue
Block a user