Solian/lib/providers/chat.dart
2024-07-06 17:39:19 +08:00

77 lines
1.8 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:get/get.dart';
import 'package:solian/models/packet.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
class ChatProvider extends GetxController {
RxBool isConnected = false.obs;
RxBool isConnecting = false.obs;
WebSocketChannel? websocket;
StreamController<NetworkPackage> stream = StreamController.broadcast();
void connect({noRetry = false}) async {
if (isConnected.value) {
return;
} else {
disconnect();
}
final AuthProvider auth = Get.find();
await auth.ensureCredentials();
if (globalCredentials == null) await auth.loadCredentials();
final uri = Uri.parse(
'${ServiceFinder.services['messaging']}/api/ws?tk=${globalCredentials!.accessToken}'
.replaceFirst('http', 'ws'),
);
isConnecting.value = true;
try {
websocket = WebSocketChannel.connect(uri);
await websocket?.ready;
} catch (e) {
if (!noRetry) {
await auth.refreshCredentials();
return connect(noRetry: true);
}
}
listen();
isConnected.value = true;
isConnecting.value = false;
}
void disconnect() {
websocket?.sink.close(WebSocketStatus.normalClosure);
websocket = null;
isConnected.value = false;
}
void listen() {
websocket?.stream.listen(
(event) {
final packet = NetworkPackage.fromJson(jsonDecode(event));
stream.sink.add(packet);
},
onDone: () {
isConnected.value = false;
Future.delayed(const Duration(seconds: 1), () => connect());
},
onError: (err) {
isConnected.value = false;
Future.delayed(const Duration(seconds: 3), () => connect());
},
);
}
}