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'; class WebsocketClient { WebSocketChannel? _channel; FlutterSecureStorage? _secureStorage; final BehaviorSubject _baseController = BehaviorSubject(); final BehaviorSubject _ownersController = BehaviorSubject( sync: true, ); late final StreamSubscription sub; Logger log = Logger( printer: PrettyPrinter( colors: true, lineLength: 100, methodCount: 0, dateTimeFormat: DateTimeFormat.dateAndTime, ), ); Stream get owners => _ownersController.stream; Future _initStore() async { _secureStorage ??= const FlutterSecureStorage(); } Future 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 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(); }, ); } } void _handleDisconnect() { sub.cancel(); _channel = null; } void dispose() { sub.cancel(); _channel?.sink.close(); _ownersController.close(); } }