This repository has been archived on 2025-08-25. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
Seshat/lib/data/services/websocket_client.dart

97 lines
2.6 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:logger/logger.dart';
import 'package:rxdart/rxdart.dart';
import 'package:seshat/config/constants.dart';
import 'package:seshat/domain/models/owner.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
/// API Client to manages connections to WebSockets
class WebsocketClient {
/// Storage to access JWT
FlutterSecureStorage? _secureStorage;
/// Raw channel of data from WebSocket
WebSocketChannel? _channel;
/// Global WebSocket Stream
final BehaviorSubject<dynamic> _baseController = BehaviorSubject();
/// WebSocket Stream dedicated to [Owner] entries
final BehaviorSubject<Owner> _ownersController = BehaviorSubject<Owner>(
sync: true,
);
/// Subscription to [_baseController]
late final StreamSubscription sub;
Logger log = Logger(
printer: PrettyPrinter(
colors: true,
lineLength: 100,
methodCount: 0,
dateTimeFormat: DateTimeFormat.dateAndTime,
),
);
/// Gets a stream of [Owner]
Stream<Owner> get owners => _ownersController.stream;
/// Initializes connection to the [_secureStorage]
Future<void> _initStore() async {
_secureStorage ??= const FlutterSecureStorage();
}
/// Connects to the websocket
Future<void> connect() async {
final url = "wss://$apiBasePath/ws";
log.i("Webocket: $url");
await _initStore();
if (_channel != null) return;
_channel = WebSocketChannel.connect(Uri.parse(url));
await _channel!.ready;
var token = await _secureStorage!.read(key: "token");
_channel!.sink.add(jsonEncode({"token": "$token"}));
_channel!.stream.listen((message) {
_baseController.add(message);
});
var data = await _baseController.stream.first;
var result = jsonDecode(data);
if (result["type"] == "auth_success") {
sub = _baseController.stream.listen(
(message) {
final Map<String, dynamic> data = jsonDecode(message);
switch (data["type"]) {
case "new_owner":
final owner = Owner.fromJSON(data["data"]);
_ownersController.add(owner);
break;
default:
}
},
onDone: _handleDisconnect,
onError: (error) {
_handleDisconnect();
},
);
}
}
/// Disconnects from the websocket
void _handleDisconnect() {
sub.cancel();
_channel = null;
}
/// Closes all connections
void dispose() {
sub.cancel();
_channel?.sink.close();
_ownersController.close();
}
}