210 lines
6.1 KiB
Dart
210 lines
6.1 KiB
Dart
import 'package:get/get.dart';
|
|
import 'package:agora_chat_sdk/agora_chat_sdk.dart';
|
|
import 'package:onufitness/constants/data_constant.dart';
|
|
import 'dart:async';
|
|
import 'package:onufitness/controller/get_agora_token_controller.dart';
|
|
import 'package:onufitness/services/local_storage_services/shared_services.dart';
|
|
import 'package:onufitness/services/logger_service.dart';
|
|
|
|
class AgoraChatService extends GetxService {
|
|
static AgoraChatService get instance => Get.find();
|
|
final logger = LoggerService();
|
|
final String appKey = agoraChatAppKey;
|
|
Timer? _tokenRefreshTimer;
|
|
Future<AgoraChatService> init() async {
|
|
await initChatSdk();
|
|
return this;
|
|
}
|
|
|
|
Future<void> initChatSdk() async {
|
|
final options = ChatOptions(
|
|
appKey: appKey,
|
|
autoLogin: false,
|
|
isAutoDownloadThumbnail: false,
|
|
requireAck: true,
|
|
requireDeliveryAck: true,
|
|
);
|
|
|
|
try {
|
|
await ChatClient.getInstance.init(options);
|
|
|
|
// Critical: Wait for native SDK to fully initialize
|
|
await Future.delayed(Duration(milliseconds: 1500));
|
|
|
|
await ChatClient.getInstance.startCallback();
|
|
await addListener();
|
|
|
|
logger.log("Agora Chat SDK initialized successfully");
|
|
} catch (e, stackTrace) {
|
|
logger.error(
|
|
"Failed to initialize Agora Chat SDK",
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
addListener() async {
|
|
_startTokenRefreshTimer();
|
|
ChatClient.getInstance.addConnectionEventHandler(
|
|
"TOKEN_REFRESH_HANDLER",
|
|
ConnectionEventHandler(
|
|
onTokenWillExpire: () async {
|
|
await agoraChatTokenAPIcall();
|
|
var tokenSuccess = SharedServices.getAgoraUserAndRtmTokens();
|
|
var userToken = tokenSuccess!.data!.agoraUserToken.toString();
|
|
await ChatClient.getInstance.renewAgoraToken(userToken);
|
|
},
|
|
onTokenDidExpire: () async {
|
|
await agoraChatTokenAPIcall();
|
|
},
|
|
onDisconnected: () {},
|
|
onConnected: () {
|
|
_startTokenRefreshTimer();
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
void _startTokenRefreshTimer() {
|
|
_tokenRefreshTimer?.cancel();
|
|
_tokenRefreshTimer = Timer.periodic(Duration(minutes: 5), (timer) async {
|
|
await agoraChatTokenAPIcall();
|
|
});
|
|
}
|
|
|
|
Future<void> agoraChatTokenAPIcall() async {
|
|
try {
|
|
if (!Get.isRegistered<AgoraTokenController>()) {
|
|
Get.put(AgoraTokenController());
|
|
}
|
|
final agoraTokenController = Get.find<AgoraTokenController>();
|
|
|
|
final success = await agoraTokenController.getAgoraUserAndRrmToken();
|
|
if (success) {
|
|
await loginToAgora();
|
|
}
|
|
} catch (e, stackTrace) {
|
|
logger.error(
|
|
"Failed to get Agora chat token",
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
}
|
|
}
|
|
|
|
String globalUserToken = "";
|
|
|
|
Future<bool> loginToAgora() async {
|
|
globalUserToken = "";
|
|
try {
|
|
final loginDetails = SharedServices.getLoginDetails();
|
|
if (loginDetails?.data?.userId == null) {
|
|
logger.error("No login details found");
|
|
return false;
|
|
}
|
|
|
|
final tokenSuccess = SharedServices.getAgoraUserAndRtmTokens();
|
|
if (tokenSuccess?.data == null ||
|
|
tokenSuccess?.data?.agoraUserToken == null) {
|
|
logger.error("No Agora token found");
|
|
return false;
|
|
}
|
|
|
|
final userToken = tokenSuccess!.data!.agoraUserToken.toString();
|
|
globalUserToken = userToken;
|
|
final userId = loginDetails!.data!.userId.toString();
|
|
final agoraUserId = userId.replaceAll("-", "");
|
|
|
|
// Check connection state first
|
|
final isConnected = await ChatClient.getInstance.isConnected();
|
|
final currentUser = ChatClient.getInstance.currentUserId;
|
|
|
|
if (isConnected && currentUser == agoraUserId) {
|
|
logger.log("User already logged in and connected: $agoraUserId");
|
|
return true;
|
|
}
|
|
|
|
// If currentUser exists but not connected, logout first
|
|
if (currentUser != null && currentUser != agoraUserId) {
|
|
logger.log("Different user logged in, logging out first");
|
|
await ChatClient.getInstance.logout(false);
|
|
}
|
|
|
|
logger.log("Attempting login to Agora chat: $agoraUserId");
|
|
await ChatClient.getInstance.loginWithToken(agoraUserId, userToken);
|
|
|
|
// Verify login succeeded
|
|
await Future.delayed(Duration(milliseconds: 500));
|
|
final loginVerified = await ChatClient.getInstance.isConnected();
|
|
|
|
if (loginVerified) {
|
|
logger.log("Successfully logged in to Agora chat: $agoraUserId");
|
|
return true;
|
|
} else {
|
|
logger.error("Login completed but not connected");
|
|
return false;
|
|
}
|
|
} on ChatError catch (e, stackTrace) {
|
|
// Handle "already logged in" error gracefully
|
|
if (e.code == 200) {
|
|
logger.log("User already logged in to Agora chat (code 200)");
|
|
return true;
|
|
}
|
|
|
|
logger.error(
|
|
"Failed to login to Agora chat",
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
|
|
// Try to renew token
|
|
if (globalUserToken.isNotEmpty) {
|
|
try {
|
|
await ChatClient.getInstance.renewAgoraToken(globalUserToken);
|
|
} catch (renewError) {
|
|
logger.error("Failed to renew token", error: renewError);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} catch (e, stackTrace) {
|
|
logger.error(
|
|
"Unexpected error during Agora login",
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> isUserLoggedIn() async {
|
|
try {
|
|
final isConnected = await ChatClient.getInstance.isConnected();
|
|
final currentUser = ChatClient.getInstance.currentUserId;
|
|
|
|
if (!isConnected || currentUser == null) {
|
|
logger.log(
|
|
"User not logged in. Connected: $isConnected, User: $currentUser",
|
|
);
|
|
return false;
|
|
}
|
|
|
|
logger.log("User logged in and connected: $currentUser");
|
|
return true;
|
|
} catch (e) {
|
|
logger.error("Error checking login state", error: e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
String? get currentUserId => ChatClient.getInstance.currentUserId;
|
|
|
|
@override
|
|
void onClose() {
|
|
_tokenRefreshTimer?.cancel();
|
|
super.onClose();
|
|
}
|
|
}
|