Skip to content

Instantly share code, notes, and snippets.

@namdiemefo
Created March 18, 2022 11:54
Show Gist options
  • Save namdiemefo/3d1d420ee46b8749dae42fbaa88a0170 to your computer and use it in GitHub Desktop.
Save namdiemefo/3d1d420ee46b8749dae42fbaa88a0170 to your computer and use it in GitHub Desktop.
import 'package:bloomm_assistant/app/db/app/app_storage.dart';
import 'package:bloomm_assistant/app/helpers/di/service_locator.dart';
import 'package:bloomm_assistant/app/models/chat/assistant_message_model.dart';
import 'package:bloomm_assistant/app/models/chat/chat_message_model.dart';
import 'package:bloomm_assistant/app/models/chat/chat_model.dart';
import 'package:logging/logging.dart';
import 'package:rxdart/rxdart.dart';
import 'package:signalr_netcore/hub_connection.dart';
import 'package:signalr_netcore/signalr_client.dart';
import 'package:uuid/uuid.dart';
extension on Chat {
List<Chat> appendDeliveredStatus(List<Chat> chats) {
for (var element in chats) {
element.time = DateTime.parse(element.time!).toString();
element.messageId = const Uuid().v4();
element.status = STATUS.DELIVERED;
}
return chats;
}
}
class AppSocket {
// static final AppSocket _instance = AppSocket._internal();
//
// AppSocket._internal() {}
// static AppSocket instance = _instance;
final serverUrl = "https://bloomm-assistant-prod-blm.bloommbank.com/BloommAssistantChatHub";
HubConnection? _hubConnection;
late bool _connectionIsOpen;
static List<Chat> conversationList = [];
final chatSubject = BehaviorSubject<List<Chat>>();
final outgoingAssistantMessageMethodName = "SendBloommCustomerMessage";
final outgoingAssistantMessageStatusMethodName = "OutgoingBloommAssistantMessageStatus";
final incomingBloommCustomerMessageMethodName = "IncomingBloommCustomerMessage";
final incomingBloommCustomerOnlineStatusMethodName = "IncomingBloommCustomerOnlineStatus";
final AppStorage _appStorage = locator<AppStorage>();
bool get connectionIsOpen => _connectionIsOpen;
// If you want only to log out the message for the higher level hub protocol:
final hubPortLogger = Logger("SignalR - hub");
// If you want to also to log out transport messages:
final transportPortLogger = Logger("SignalR - transport");
void openConnection() {
const transportType = HttpTransportType.WebSockets;
final httpOptions = HttpConnectionOptions(
logger: transportPortLogger,
transport: transportType,
logMessageContent: true,
accessTokenFactory: () => _getToken());
if (_hubConnection == null) {
_hubConnection = HubConnectionBuilder()
.withUrl(serverUrl, options: httpOptions)
.configureLogging(hubPortLogger)
.build();
_hubConnection?.start()!.then((value) {
print("socket connection is open");
_connectionIsOpen = true;
}).catchError((error) {
_connectionIsOpen = false;
print("socket error : $error");
startReconnection();
});
_hubConnection?.onclose(({Exception? error}) {
_connectionIsOpen = false;
print("close");
startReconnection();
});
registerOutgoingBloommAssistantMessageStatusListener(outgoingAssistantMessageStatusMethodName);
registerIncomingBloommCustomerMessageListener(incomingBloommCustomerMessageMethodName);
}
print("state is ${_hubConnection?.state}");
if (_hubConnection?.state == HubConnectionState.Connected) {
print("im sure connection is open");
} else {
_hubConnection?.start()?.then((value) {
print("socket connection is open again");
_connectionIsOpen = true;
}).onError((error, stackTrace) {
print('error connecting to socket : $error');
_connectionIsOpen = false;
});
}
}
void sendMessage(ChatModel userChatModel) {
print("state is ${_hubConnection?.state}");
print("BA message: ${userChatModel.toJson().toString()}");
Chat chat = Chat(
messageId: userChatModel.messageId,
messageType: userChatModel.messageType,
message: userChatModel.message,
time: DateTime.now().toString(),
isBloommAssistant: true,
attachments: userChatModel.attachments,
status: STATUS.PENDING,
);
conversationList.add(chat);
chatSubject.add(conversationList);
print(_hubConnection);
_hubConnection?.invoke(outgoingAssistantMessageMethodName, args: [userChatModel]).then((value) {
print("value : $value");
}).catchError((error) {
print("error: $error ");
});
}
Future<String> _getToken() async {
String? token = await _appStorage.getAccessToken();
print("token boy is $token");
return await token!;
}
void resendMessage(ChatModel userChatModel) {
conversationList.forEach((chatElement) {
if (userChatModel.messageId == chatElement.messageId) {
conversationList.remove(chatElement);
}
});
chatSubject.value.forEach((chatElement) {
if (userChatModel.messageId == chatElement.messageId) {
chatSubject.value.remove(chatElement);
}
});
sendMessage(userChatModel);
}
void setConversation(List<Chat> chats) {
Chat chat = Chat();
if (chats.isNotEmpty) {
chats = chat.appendDeliveredStatus(chats);
}
conversationList = chats;
chatSubject.add(conversationList);
}
void startReconnection() {
openConnection();
}
void registerOutgoingBloommAssistantMessageStatusListener(String outgoingAssistantMessageStatusMethodName) {
_hubConnection?.on(outgoingAssistantMessageStatusMethodName, (arguments) {
print("outgoingAssistantMessageStatusMethodName: $arguments");
var msg = arguments;
List<AssistantMessageModel> list = List<AssistantMessageModel>.unmodifiable(msg!.map((e) => AssistantMessageModel.fromJson(msg[0])));
AssistantMessageModel messageModel = list[0];
String messageId = messageModel.messageId!;
String message = messageModel.message!;
String messageStatus = messageModel.status!;
String messageType = messageModel.messageType!;
List<dynamic> attachments = messageModel.attachments!;
// String messageId = arguments![0]["messageId"];
// String message = arguments[0]["message"];
// String messageType = arguments[0]["messageType"];
// String messageStatus = arguments[0]["status"];
// List<dynamic> attachments = arguments[0]["attachments"];
Chat newChat = Chat(
message: message,
messageId: messageId,
messageType: messageType,
isBloommAssistant: true,
attachments: attachments,
time: DateTime.now().toString());
switch (messageStatus) {
case "Delivered":
{
conversationList
.removeWhere((element) => element.messageId == messageId);
newChat.status = STATUS.DELIVERED;
conversationList.add(newChat);
chatSubject.add(conversationList);
break;
}
case "Received":
print("here now");
{
conversationList
.removeWhere((element) => element.messageId == messageId);
newChat.status = STATUS.RECEIVED;
conversationList.add(newChat);
chatSubject.add(conversationList);
break;
}
case "Failed":
{
conversationList
.removeWhere((element) => element.messageId == messageId);
newChat.status = STATUS.FAILED;
conversationList.add(newChat);
chatSubject.add(conversationList);
}
}
});
}
void registerIncomingBloommCustomerMessageListener(String incomingBloommCustomerMessageMethodName) {
_hubConnection?.on(incomingBloommCustomerMessageMethodName, (arguments) {
print("incomingBloommCustomerMessageMethodName: $arguments");
var msg = arguments;
List<AssistantMessageModel> list = List<AssistantMessageModel>.unmodifiable(msg!.map((e) => AssistantMessageModel.fromJson(msg[0])));
AssistantMessageModel messageModel = list[0];
String message = messageModel.message!;
String messageType = messageModel.messageType!;
List<dynamic> attachments = messageModel.attachments!;
Chat chat = Chat(isBloommAssistant: false, attachments: attachments, message: message, messageType: messageType,
status: STATUS.RECEIVED,
time: DateTime.now().toString());
print(chat.message);
conversationList.add(chat);
chatSubject.add(conversationList);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment