taafee-mobile/lib/core/network/socket/socket.dart
2023-10-17 17:22:55 +03:00

162 lines
3.6 KiB
Dart

import 'dart:async';
import 'dart:developer';
import 'package:taafee_mobile/core/errors/custom_exception.dart';
import 'package:socket_io_client/socket_io_client.dart';
import './event.dart';
import './extension.dart';
class SocketIO {
// @attributes
final String uri;
Function()? onConnect;
Function()? onDisconnect;
Function()? onConnecting;
Function()? onError;
Map<String, dynamic> extraHeaders = {};
// @constructors
SocketIO({
required this.uri,
this.onConnect,
this.onConnecting,
this.onError,
this.onDisconnect,
});
// @privates
Socket? _socket; // suggest late instead of nullable
bool _initialized = false;
Status _status = Status.notConnected;
final Map<String, dynamic> _socketOptions = {
'transports': ['websocket'],
'autoConnect': true,
};
// @getters
bool get initialized => _initialized;
Status get status => _status;
// @methods
Future<void> boot() async {
init();
await connect();
}
Future<void> restart() async {
_assertInitialized();
await disconnect();
await boot();
}
void init() {
_socketOptions["extraHeaders"] = extraHeaders;
_socket = io(uri, _socketOptions);
_initialized = true;
}
Future<void> connect() async {
_assertInitialized();
_status = Status.connecting;
onConnecting?.call();
await _socket!.connectAsync().timeout(const Duration(seconds: 10),
onTimeout: () {
onError?.call();
throw GenericException(
type: ExceptionType.ConnectionError,
errorMessage: "You Have no Internet Connection",
);
});
onConnect?.call();
_status = Status.connected;
}
void setOnDisconnect(Function() trigger) {
onDisconnect = trigger;
_socket?.onDisconnect((_) => trigger());
}
void setOnConnect(Function() trigger) {
onConnect = trigger;
_socket?.onConnect((data) => trigger());
}
void setOnConnectionError(Function() trigger) {
onError = trigger;
_socket?.onerror((_) => trigger());
}
void setOnConnecting(Function() trigger) {
onConnecting = trigger;
_socket?.onerror((_) => trigger());
}
Future<void> disconnect() async {
_assertInitialized();
await _socket!.disconnectAsync();
// suggest onDisconnect?.call();
_status = Status.notConnected;
}
Future<dynamic> emit(Event event, {bool reciveDataOnError = false}) async {
_assertInitialized();
dynamic ack = {};
try {
ack = await _socket!.emitAsync(event.name, event.body);
if (ack["status"] == "failed") {
if (reciveDataOnError) {
return ack;
}
throw badRequestException[
ack["error"]["name"] ?? "INTERNAL_SERVER_ERROR"] ??
GenericException(
type: ExceptionType.InternalServerException,
);
}
} catch (e) {
if (e is GenericException) {
rethrow;
}
throw GenericException(
type: ExceptionType.InternalServerException,
);
}
return ack["data"];
}
void listen(String eventName, Function(dynamic) handler) {
// there is no need to check if initialized here, it is just registering a handler.
_socket!.on(eventName, (data) {
log('event:$eventName');
handler(data);
});
}
void setAuthentication(String token) {
extraHeaders["authorization"] = token;
}
void _assertInitialized() {
if (!initialized) {
throw Exception("Object is not initialized, do call .init() method");
}
}
void clearListeners() {
_socket?.clearListeners();
}
}
enum Status { connected, connecting, notConnected }