Add chat send message feature, refactoring

- Added userState and globalUserState fields to keep track of user data while chatting
- Adjusted CAP REQ commands to receive GLOBALUSERSTATE
- Adjusted return and break statements in switch and general cleanup
- Added sendMessage and dispose method
This commit is contained in:
tommyxchow 2021-10-17 17:56:16 -04:00
parent 5ff1744cb9
commit 65611469f3
2 changed files with 75 additions and 47 deletions

View file

@ -18,35 +18,41 @@ class ChatStore = _ChatStoreBase with _$ChatStore;
abstract class _ChatStoreBase with Store {
@readonly
var _messages = <IRCMessage>[];
var _autoScroll = true;
final _channel = WebSocketChannel.connect(Uri.parse('wss://irc-ws.chat.twitch.tv:443'));
get channel => _channel;
@readonly
var _messages = <IRCMessage>[];
final _assetToUrl = <String, String>{};
final _emoteIdToWord = <String, String>{};
final _scrollController = ScrollController();
ScrollController get scrollController => _scrollController;
final _textController = TextEditingController();
TextEditingController get textController => _textController;
final _channel = WebSocketChannel.connect(Uri.parse('wss://irc-ws.chat.twitch.tv:443'));
WebSocketChannel get channel => _channel;
String? userState;
String? globalUserState;
final String channelName;
final AuthStore auth;
final _scrollController = ScrollController();
get scrollController => _scrollController;
@readonly
var _autoScroll = true;
_ChatStoreBase({required this.auth, required this.channelName}) {
channel.stream.listen(
(event) => handleWebsocketData(event.toString()),
onDone: () => debugPrint("DONE"),
);
final commands = [
'CAP REQ :twitch.tv/tags twitch.tv/commands',
'CAP END',
'PASS oauth:${auth.token}',
'NICK ${auth.isLoggedIn ? auth.user!.login : 'justinfan888'}',
'CAP REQ :twitch.tv/tags twitch.tv/commands twitch.tv/membership',
'CAP END',
'JOIN #$channelName',
];
@ -96,37 +102,41 @@ abstract class _ChatStoreBase with Store {
switch (parsedIRCMessage.command) {
case 'CLEARCHAT':
_messages = IRC.CLEARCHAT(messages: _messages, ircMessage: parsedIRCMessage);
break;
return;
case 'CLEARMSG':
break;
_messages = IRC.CLEARMSG(messages: _messages, ircMessage: parsedIRCMessage);
return;
case 'GLOBALUSERSTATE':
break;
// Updates the current global user state data (it includes user-id)
globalUserState = message;
return;
case 'PRIVMSG':
if (_autoScroll) {
if (_messages.length > 100) {
_messages.removeRange(0, _messages.length - 100);
}
if (_scrollController.hasClients) {
SchedulerBinding.instance?.addPostFrameCallback((_) {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
}
}
_messages = IRC.PRIVMSG(messages: _messages, ircMessage: parsedIRCMessage);
break;
case 'ROOMSTATE':
IRC.USERNOTICE(messages: _messages, ircMessage: parsedIRCMessage);
break;
IRC.ROOMSTATE(messages: _messages, ircMessage: parsedIRCMessage);
return;
case 'USERNOTICE':
IRC.USERNOTICE(messages: _messages, ircMessage: parsedIRCMessage);
break;
case 'USERSTATE':
IRC.USERSTATE(messages: _messages, ircMessage: parsedIRCMessage);
break;
// Updates the current user-state data
userState = message;
return;
}
} else if (message.startsWith('P')) {
channel.sink.add('PONG :tmi.twitch.tv');
return;
}
}
if (_autoScroll) {
if (_messages.length > 100) {
_messages.removeRange(0, _messages.length - 80);
}
if (_scrollController.hasClients) {
SchedulerBinding.instance?.addPostFrameCallback((_) {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
}
}
}
@ -222,11 +232,23 @@ abstract class _ChatStoreBase with Store {
}
return ChatMessage(
key: Key(ircMessage.tags['id']!),
// key: Key(ircMessage.tags['id']!),
children: result,
);
}
void sendMessage(String message) {
if (message.isEmpty) {
return;
}
_channel.sink.add('PRIVMSG #$channelName :$message');
_messages = IRC.addMessage(messages: _messages, userState: userState!, sentMessage: message);
_textController.clear();
}
@action
void resumeScroll() {
_autoScroll = true;
@ -235,6 +257,12 @@ abstract class _ChatStoreBase with Store {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
}
void dispose() {
_channel.sink.close();
_textController.dispose();
_scrollController.dispose();
}
}
// https://stackoverflow.com/questions/50081213/how-do-i-use-hexadecimal-color-strings-in-flutter

View file

@ -9,23 +9,6 @@ part of 'chat_store.dart';
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
mixin _$ChatStore on _ChatStoreBase, Store {
final _$_messagesAtom = Atom(name: '_ChatStoreBase._messages');
List<IRCMessage> get messages {
_$_messagesAtom.reportRead();
return super._messages;
}
@override
List<IRCMessage> get _messages => messages;
@override
set _messages(List<IRCMessage> value) {
_$_messagesAtom.reportWrite(value, super._messages, () {
super._messages = value;
});
}
final _$_autoScrollAtom = Atom(name: '_ChatStoreBase._autoScroll');
bool get autoScroll {
@ -43,6 +26,23 @@ mixin _$ChatStore on _ChatStoreBase, Store {
});
}
final _$_messagesAtom = Atom(name: '_ChatStoreBase._messages');
List<IRCMessage> get messages {
_$_messagesAtom.reportRead();
return super._messages;
}
@override
List<IRCMessage> get _messages => messages;
@override
set _messages(List<IRCMessage> value) {
_$_messagesAtom.reportWrite(value, super._messages, () {
super._messages = value;
});
}
final _$_ChatStoreBaseActionController =
ActionController(name: '_ChatStoreBase');