Created
April 23, 2021 09:24
-
-
Save Meghatronics/71e1a478ee5f8a977ef409154f0ade15 to your computer and use it in GitHub Desktop.
Chat Manager with socket.io in flutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'dart:async'; | |
| import 'package:meta/meta.dart'; | |
| import 'package:socket_io_client/socket_io_client.dart' as io; | |
| import '../../data/models/chat_message.dart'; | |
| import '../../data/models/room.dart'; | |
| class ChatData { | |
| final bool matchIsTyping; | |
| final ChatMessage chatMessage; | |
| const ChatData({this.matchIsTyping, this.chatMessage}); | |
| } | |
| enum ManagerState { ready, preparing, notReady } | |
| class ChatManager { | |
| final Room room; | |
| final StreamController<ChatData> _controller = StreamController<ChatData>(); | |
| bool _receiverIsTyping = false; | |
| bool _userIsTyping = false; | |
| ManagerState _ready = ManagerState.notReady; | |
| io.Socket chatSocket; | |
| ChatManager({@required this.room}) { | |
| chatSocket = io.io( | |
| "https://link.com", //TODO YOUR OWN URL | |
| <String, dynamic>{ | |
| 'transports': ['websocket'], | |
| //TODO I believe this is where you can add the headers | |
| }, | |
| ); | |
| print('chatSocket is connected ${chatSocket.connected}'); | |
| chatSocket.connect(); | |
| _initializeChatSocket(); | |
| } | |
| Stream get chatStream => _controller.stream; | |
| ///This function starts the chat socket. | |
| /// | |
| ///Calls [_joinRoom()] and waits till room is joined. | |
| ///Then registers call backs for events to listen for: | |
| ///* 'message' | |
| ///* 'typing' | |
| ///* 'stopTyping' | |
| void _initializeChatSocket() async { | |
| _ready = ManagerState.preparing; | |
| final joined = await _joinRoom(); | |
| if (!joined) return; | |
| print('registering callbacks: $_ready'); | |
| chatSocket.on('newMessage', (data) { | |
| final newMessage = ChatMessage.fromJson(data); | |
| _controller.sink.add(ChatData(chatMessage: newMessage)); | |
| room.messages.add(newMessage); | |
| }); | |
| chatSocket.on('isTyping', (space) { | |
| if (space == room.sId) _receiverIsTyping = true; | |
| _controller.sink.add(ChatData(matchIsTyping: _receiverIsTyping)); | |
| }); | |
| chatSocket.on('isNotTyping', (space) { | |
| if (space == room.sId) _receiverIsTyping = false; | |
| _controller.sink.add(ChatData(matchIsTyping: _receiverIsTyping)); | |
| }); | |
| _ready = ManagerState.ready; | |
| print('registering callbacks DONE: $_ready'); | |
| } | |
| bool get ready { | |
| if (_ready == ManagerState.preparing || _ready == ManagerState.notReady) | |
| return false; | |
| else if (chatSocket.connected && _ready == ManagerState.ready) { | |
| return true; | |
| } else { | |
| _ready = ManagerState.notReady; | |
| chatSocket.connect(); | |
| _initializeChatSocket(); | |
| return false; | |
| } | |
| } | |
| int _retryCount = 0; | |
| ///Emits a [joinRoom] event. | |
| ///Identifies socket with a room on the server. | |
| ///Must be called after connect for chat to work | |
| Future<bool> _joinRoom() async { | |
| print('chatSocket is connected ${chatSocket.connected} : $_ready'); | |
| if (_ready == ManagerState.preparing) { | |
| if (chatSocket.connected) { | |
| chatSocket.emit('enterChatRoom', { | |
| "username": room.me.username, | |
| "room": room.me.sId, | |
| }); | |
| print('Joined Room'); | |
| return true; | |
| } else | |
| _retryCount++; | |
| if (_retryCount == 6 || _retryCount == 12) chatSocket.connect(); | |
| if (_retryCount > 18) | |
| return false; | |
| else | |
| return Future.delayed(const Duration(seconds: 1), () { | |
| return _joinRoom(); | |
| }); | |
| } else | |
| return false; | |
| } | |
| ///Close this manager | |
| ///Closes the Stream controller and disposes the sockets | |
| void close() { | |
| _controller.close(); | |
| chatSocket.close(); | |
| chatSocket.dispose(); | |
| _ready = ManagerState.notReady; | |
| print('chatSocket is connected ${chatSocket.connected}'); | |
| } | |
| void sendText(String text) { | |
| print('chatSocket is connected ${chatSocket.connected}'); | |
| final messageToSend = ChatMessage( | |
| text: text, | |
| senderUsername: room.me.username, | |
| senderId: room.me.sId, | |
| to: room.receiver.sId, | |
| chatRoom: room.sId, | |
| ); | |
| chatSocket.emit('chatMessage', messageToSend.toJson()); | |
| room.messages.add(messageToSend); | |
| } | |
| set thisUserTyping(bool isTyping) { | |
| if (isTyping && _userIsTyping) return; | |
| _userIsTyping = isTyping; | |
| print('chatSocket is connected ${chatSocket.connected}'); | |
| chatSocket.emit( | |
| _userIsTyping ? "isTyping" : "isNotTyping", | |
| { | |
| "to": room.receiver.sId, | |
| "space": room.sId, | |
| }, | |
| ); | |
| print('typing : $_userIsTyping'); | |
| if (_userIsTyping) | |
| Future.delayed(const Duration(seconds: 10), () { | |
| thisUserTyping = false; | |
| }); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment