162 lines
3.6 KiB
Dart
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 }
|