fartstack/frontend/lib/providers/web_socket.dart

67 lines
2.1 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:frontend/providers/auth.dart';
import 'package:logging/logging.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:shared_models/room.dart';
part 'web_socket.g.dart';
final _logger = Logger('WebSocketNotifier');
@riverpod
class WebSocketNotifier extends _$WebSocketNotifier {
@override
Future<WebSocket?> build() async {
return null;
}
Future<void> connect() async {
state = AsyncValue.loading();
final jwt = ref.read(jwtNotifierProvider).valueOrNull;
final jwtBody = ref.read(jwtBodyProvider);
if (jwt == null || jwtBody == null) {
_logger.warning('Tried to connect to ws without jwt token');
return;
}
final wsUrl = Uri.parse('ws://localhost:8080/room/${jwtBody.roomCode}/ws');
_logger.finest('Attempting to connect to $wsUrl');
try {
final connection = await WebSocket.connect(wsUrl.toString(), headers: {'Authorization': 'Bearer: $jwt'});
_logger.fine('Client ws connection established to room ${jwtBody.roomUuid}');
state = AsyncValue.data(connection);
} catch (e) {
if (e is WebSocketException) {
if (e.httpStatusCode == 401) {
ref.read(jwtNotifierProvider.notifier).eraseJwt();
}
}
_logger.warning('Error occurred creating web socket: $e');
}
}
void sendMessage(GameRoomMessage message) {
final msgStr = jsonEncode(message.toJson());
final socket = state.valueOrNull;
if (socket == null) {
// TODO add queue
_logger.info('Socket unavailable... adding to queue');
throw UnimplementedError('No queue available');
}
_logger.finest('Sending message $message on websocket');
socket.add(msgStr);
}
}
@riverpod
Raw<Stream<dynamic>> webSocketStream(Ref ref) {
final connection = ref.watch(webSocketNotifierProvider).valueOrNull;
if (connection == null) return Stream.empty();
_logger.finest('Created broadcast stream from ws connection');
return connection.asBroadcastStream();
}