|
|
|
|
@ -8,8 +8,13 @@ import 'package:signalr_netcore/http_connection_options.dart';
|
|
|
|
|
import 'package:signalr_netcore/hub_connection.dart';
|
|
|
|
|
import 'package:signalr_netcore/hub_connection_builder.dart';
|
|
|
|
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
|
|
|
|
import 'package:test_sa/modules/cx_module/chat/api_client.dart';
|
|
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
|
|
|
|
|
|
import '../chat_provider.dart';
|
|
|
|
|
import '../model/chat_login_response_model.dart';
|
|
|
|
|
|
|
|
|
|
HubConnection? callHubConnection;
|
|
|
|
|
|
|
|
|
|
class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
///////////////////// Web RTC Video Calling //////////////////////
|
|
|
|
|
@ -27,112 +32,93 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
bool isPeerMuted = false;
|
|
|
|
|
bool isPeerCameraOn = true;
|
|
|
|
|
|
|
|
|
|
bool isLoading = false;
|
|
|
|
|
|
|
|
|
|
Future<void> _disposeConnection() async {
|
|
|
|
|
try {
|
|
|
|
|
if (chatHubConnection != null) {
|
|
|
|
|
await chatHubConnection!.stop();
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('🔌 SignalR connection closed successfully');
|
|
|
|
|
}
|
|
|
|
|
if (callHubConnection != null) {
|
|
|
|
|
await callHubConnection!.stop();
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('⚠️ Error closing SignalR connection: $e');
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
chatHubConnection = null;
|
|
|
|
|
callHubConnection = null;
|
|
|
|
|
}
|
|
|
|
|
// isLoading = false;
|
|
|
|
|
// notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void dispose() {
|
|
|
|
|
_disposeConnection().then((_) {
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('✅ ChatProvider disposed');
|
|
|
|
|
}
|
|
|
|
|
}).catchError((error) {
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('⚠️ Error during ChatProvider disposal: $error');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
_disposeConnection().then((_) {}).catchError((error) {});
|
|
|
|
|
super.dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<HubConnection> getHubConnection() async {
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('🔧 Creating new SignalR hub connection...');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<HubConnection> getHubConnection(String token) async {
|
|
|
|
|
HubConnection hub;
|
|
|
|
|
HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
|
|
|
|
|
hub = HubConnectionBuilder().withUrl("${URLs.chatHubUrlChat}?accessTokenFactory=${URLs.chatApiKey}", options: httpOp).withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
|
|
|
|
|
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('✅ SignalR hub connection created');
|
|
|
|
|
}
|
|
|
|
|
hub = HubConnectionBuilder().withUrl("${URLs.chatHubUrlChat}?accessTokenFactory=$token}", options: httpOp).withAutomaticReconnect(retryDelays: <int>[2000, 5000, 10000, 20000]).build();
|
|
|
|
|
|
|
|
|
|
return hub;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<bool> buildHubConnection() async {
|
|
|
|
|
Future<bool> buildHubConnection(String employeeNumber) async {
|
|
|
|
|
try {
|
|
|
|
|
// Dispose existing connection if any
|
|
|
|
|
await _disposeConnection();
|
|
|
|
|
|
|
|
|
|
chatHubConnection = await getHubConnection();
|
|
|
|
|
await chatHubConnection!.start();
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print("🔌 SignalR Hub Connection: Started");
|
|
|
|
|
// isLoading = true;
|
|
|
|
|
// notifyListeners();
|
|
|
|
|
http.Response response = await ApiClient().postJsonForResponse(URLs.chatSdkToken, {"apiKey": URLs.chatApiKey, "employeeNumber": employeeNumber, "voIPToken": null});
|
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
|
ChatLoginResponse chatResponse = ChatLoginResponse.fromJson(jsonDecode(response.body));
|
|
|
|
|
print("chatResponse:${chatResponse.token}");
|
|
|
|
|
callHubConnection = await getHubConnection(chatResponse.token!);
|
|
|
|
|
await callHubConnection!.start();
|
|
|
|
|
// isLoading = false;
|
|
|
|
|
// notifyListeners();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
//group On message
|
|
|
|
|
|
|
|
|
|
// chatHubConnection.on("OnDeliveredGroupChatHistoryAsync", onGroupMsgReceived);
|
|
|
|
|
// isLoading = false;
|
|
|
|
|
// notifyListeners();
|
|
|
|
|
return false;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (kDebugMode) {
|
|
|
|
|
print('⚠️ Error building SignalR connection: $e');
|
|
|
|
|
}
|
|
|
|
|
// Clean up on error
|
|
|
|
|
print("buildHubConnectionE:$e");
|
|
|
|
|
await _disposeConnection();
|
|
|
|
|
return false;
|
|
|
|
|
rethrow; // Rethrow so caller knows about the error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initAudioCallListeners() {
|
|
|
|
|
chatHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync);
|
|
|
|
|
chatHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync);
|
|
|
|
|
chatHubConnection!.on("OnOfferAsync", onOfferAsync);
|
|
|
|
|
chatHubConnection!.on("OnAnswerOffer", onAnswerOffer);
|
|
|
|
|
chatHubConnection!.on("OnHangUpAsync", onHangUpAsync);
|
|
|
|
|
chatHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
|
|
|
|
|
chatHubConnection!.on('OnAudioToggle', onAudioToggle);
|
|
|
|
|
callHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync);
|
|
|
|
|
callHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync);
|
|
|
|
|
callHubConnection!.on("OnOfferAsync", onOfferAsync);
|
|
|
|
|
callHubConnection!.on("OnAnswerOffer", onAnswerOffer);
|
|
|
|
|
callHubConnection!.on("OnHangUpAsync", onHangUpAsync);
|
|
|
|
|
callHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
|
|
|
|
|
callHubConnection!.on('OnAudioToggle', onAudioToggle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initCallListeners() {
|
|
|
|
|
chatHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync);
|
|
|
|
|
chatHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync);
|
|
|
|
|
chatHubConnection!.on("OnOfferAsync", onOfferAsync);
|
|
|
|
|
chatHubConnection!.on("OnAnswerOffer", onAnswerOffer);
|
|
|
|
|
chatHubConnection!.on("OnHangUpAsync", onHangUpAsync);
|
|
|
|
|
chatHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
|
|
|
|
|
chatHubConnection!.on('OnAudioToggle', onAudioToggle);
|
|
|
|
|
chatHubConnection!.on('OnCameraToggle', onCameraToggle);
|
|
|
|
|
|
|
|
|
|
// chatHubConnection!.on('OnIncomingCallAsync', onHandleIncomingCall);
|
|
|
|
|
// chatHubConnection!.on('OnCallAcceptedAsync', _handleCallAccepted);
|
|
|
|
|
// chatHubConnection!.on('OnCallDeclinedAsync', _handleCallDeclined);
|
|
|
|
|
// chatHubConnection!.on('OnHangUpAsync', onHangUpAsync);
|
|
|
|
|
// chatHubConnection!.on('OnOfferAsync', _handleOffer);
|
|
|
|
|
// chatHubConnection!.on('OnAnswerOfferAsync', onAnswerOffer);
|
|
|
|
|
// chatHubConnection!.on('OnIceCandidateAsync', _handleIceCandidate);
|
|
|
|
|
// chatHubConnection!.on('OnAudioToggle', _handleAudioToggle);
|
|
|
|
|
// chatHubConnection!.on('OnCameraToggle', _handleCameraToggle);
|
|
|
|
|
// chatHubConnection!.on('OnUserOnlineAsync', _handleUserOnline);
|
|
|
|
|
// chatHubConnection!.on('OnUserOfflineAsync', _handleUserOffline);
|
|
|
|
|
// chatHubConnection!.on('OnCallHistoryUpdated', _handleCallHistoryUpdated);
|
|
|
|
|
// chatHubConnection!.on('OnError', _handleError);
|
|
|
|
|
callHubConnection!.on("OnCallAcceptedAsync", onCallAcceptedAsync);
|
|
|
|
|
callHubConnection!.on("OnIceCandidateAsync", onIceCandidateAsync);
|
|
|
|
|
callHubConnection!.on("OnOfferAsync", onOfferAsync);
|
|
|
|
|
callHubConnection!.on("OnAnswerOffer", onAnswerOffer);
|
|
|
|
|
callHubConnection!.on("OnHangUpAsync", onHangUpAsync);
|
|
|
|
|
callHubConnection!.on("OnCallDeclinedAsync", onCallDeclinedAsync);
|
|
|
|
|
callHubConnection!.on('OnAudioToggle', onAudioToggle);
|
|
|
|
|
callHubConnection!.on('OnCameraToggle', onCameraToggle);
|
|
|
|
|
|
|
|
|
|
// callHubConnection!.on('OnIncomingCallAsync', onHandleIncomingCall);
|
|
|
|
|
// callHubConnection!.on('OnCallAcceptedAsync', _handleCallAccepted);
|
|
|
|
|
// callHubConnection!.on('OnCallDeclinedAsync', _handleCallDeclined);
|
|
|
|
|
// callHubConnection!.on('OnHangUpAsync', onHangUpAsync);
|
|
|
|
|
// callHubConnection!.on('OnOfferAsync', _handleOffer);
|
|
|
|
|
// callHubConnection!.on('OnAnswerOfferAsync', onAnswerOffer);
|
|
|
|
|
// callHubConnection!.on('OnIceCandidateAsync', _handleIceCandidate);
|
|
|
|
|
// callHubConnection!.on('OnAudioToggle', _handleAudioToggle);
|
|
|
|
|
// callHubConnection!.on('OnCameraToggle', _handleCameraToggle);
|
|
|
|
|
// callHubConnection!.on('OnUserOnlineAsync', _handleUserOnline);
|
|
|
|
|
// callHubConnection!.on('OnUserOfflineAsync', _handleUserOffline);
|
|
|
|
|
// callHubConnection!.on('OnCallHistoryUpdated', _handleCallHistoryUpdated);
|
|
|
|
|
// callHubConnection!.on('OnError', _handleError);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Video Constraints
|
|
|
|
|
@ -337,16 +323,16 @@ class CallProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
} else if (invokeMethod == "AnswerOfferAsync") {
|
|
|
|
|
args = [targetUserID, data];
|
|
|
|
|
}
|
|
|
|
|
await chatHubConnection!.invoke(invokeMethod, args: args);
|
|
|
|
|
await callHubConnection?.invoke(invokeMethod, args: args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stopListeners() async {
|
|
|
|
|
chatHubConnection!.off('OnCallDeclinedAsync');
|
|
|
|
|
chatHubConnection!.off('OnCallAcceptedAsync');
|
|
|
|
|
chatHubConnection!.off('OnIceCandidateAsync');
|
|
|
|
|
chatHubConnection!.off('OnAnswerOffer');
|
|
|
|
|
chatHubConnection!.off('OnOfferAsync');
|
|
|
|
|
chatHubConnection!.off('OnHangUpAsync');
|
|
|
|
|
chatHubConnection!.off('OnAudioToggle');
|
|
|
|
|
callHubConnection?.off('OnCallDeclinedAsync');
|
|
|
|
|
callHubConnection?.off('OnCallAcceptedAsync');
|
|
|
|
|
callHubConnection?.off('OnIceCandidateAsync');
|
|
|
|
|
callHubConnection?.off('OnAnswerOffer');
|
|
|
|
|
callHubConnection?.off('OnOfferAsync');
|
|
|
|
|
callHubConnection?.off('OnHangUpAsync');
|
|
|
|
|
callHubConnection?.off('OnAudioToggle');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|