import 'dart:developer'; import 'package:dart_pusher_channels/dart_pusher_channels.dart'; import 'package:eatvio_app/core/const.dart'; import 'package:eatvio_app/core/websockets/ws_service.dart'; import 'package:eatvio_app/core/token_storage.dart'; class WsManager { final WsService wsService; WsManager({required this.wsService}); PusherChannelsClient? client; int? userId; PrivateChannel? _privateNotificationChannel; PrivateChannel? _privateMessagesChannel; PrivateChannel? _privateDirectChatChannel; Stream? get newMessagesStream => _privateMessagesChannel?.bind('App\\Events\\ChatMessageUpdated'); Stream? get newNotificationsStream => _privateNotificationChannel?.bind('Illuminate\\Notifications\\Events\\BroadcastNotificationCreated'); Stream? get directChatStream => _privateDirectChatChannel?.bind('App\\Events\\ChatMessageUpdated'); Stream? get clientTypingStream => _privateDirectChatChannel?.bind('client-typing'); Future initialize() async { if (client == null) { try { await TokenStorage.haveTokenInStorage(); final wsUrl = await wsService.getWebsocket(); final options = PusherChannelsOptions.fromHost( scheme: 'wss', key: wsUrl.key, host: wsUrl.host, shouldSupplyMetadataQueries: true, metadata: const PusherChannelsOptionsMetadata.byDefault(), port: 443, ); client = PusherChannelsClient.websocket( options: options, connectionErrorHandler: (exception, trace, refresh) { refresh(); }, minimumReconnectDelayDuration: const Duration( seconds: 1, ), defaultActivityDuration: const Duration( seconds: 30, ), waitForPongDuration: const Duration( seconds: 30, ), ); await client?.connect(); client = client; userId = wsUrl.userId; await _initPrivateNotificationsChannel(); await _initPrivateMessagesChannel(); client?.lifecycleStream.listen((data) { if (data == PusherChannelsClientLifeCycleState.establishedConnection) { _unsubscribe(); _subscribe(); } }); client?.eventStream.listen((event) { log(event.rootObject.toString()); }); _subscribe(); } catch (e, st) { log(e.toString(), stackTrace: st); } } } Future _initPrivateNotificationsChannel() async { final token = await TokenStorage.getTokenFromStorage(); _privateNotificationChannel = client?.privateChannel( '$newNotificationsChannelName.$userId', authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate.forPrivateChannel( authorizationEndpoint: Uri.parse('$baseUrl/broadcasting/auth'), headers: { 'Authorization': 'Bearer $token', }, ), ); } Future _initPrivateMessagesChannel() async { final token = await TokenStorage.getTokenFromStorage(); _privateMessagesChannel = client?.privateChannel( '$newMessagesChannelName.$userId', authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate.forPrivateChannel( authorizationEndpoint: Uri.parse('$baseUrl/broadcasting/auth'), headers: { 'Authorization': 'Bearer $token', }, ), ); } Future initPrivateDirectChatChannel(String chatId) async { final token = await TokenStorage.getTokenFromStorage(); _privateDirectChatChannel = client?.privateChannel( '$directChatChannelName.$chatId', authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate.forPrivateChannel( authorizationEndpoint: Uri.parse('$baseUrl/broadcasting/auth'), headers: { 'Authorization': 'Bearer $token', }, ), ); } void _subscribe() { _privateMessagesChannel?.subscribe(); _privateNotificationChannel?.subscribe(); } void _unsubscribe() { _privateMessagesChannel?.unsubscribe(); _privateNotificationChannel?.unsubscribe(); } void subscribeDirectChatChannel() { _privateDirectChatChannel?.subscribe(); } void unsubscribeDirectChatChannel() { _privateDirectChatChannel?.unsubscribe(); } Future clear() async { await client?.disconnect(); client = null; userId = null; _privateDirectChatChannel?.unsubscribe(); _privateMessagesChannel?.unsubscribe(); _privateNotificationChannel?.unsubscribe(); _privateDirectChatChannel = null; _privateMessagesChannel = null; _privateNotificationChannel = null; } }