Convert messages to observable, minor refactor
This commit is contained in:
parent
9eca5189db
commit
fec255cceb
2 changed files with 41 additions and 56 deletions
|
|
@ -17,9 +17,11 @@ part 'chat_store.g.dart';
|
|||
class ChatStore = _ChatStoreBase with _$ChatStore;
|
||||
|
||||
abstract class _ChatStoreBase with Store {
|
||||
final messages = <IrcMessage>[];
|
||||
@readonly
|
||||
var _messages = <IRCMessage>[];
|
||||
|
||||
final channel = WebSocketChannel.connect(Uri.parse('wss://irc-ws.chat.twitch.tv:443'));
|
||||
final _channel = WebSocketChannel.connect(Uri.parse('wss://irc-ws.chat.twitch.tv:443'));
|
||||
get channel => _channel;
|
||||
|
||||
final _assetToUrl = <String, String>{};
|
||||
|
||||
|
|
@ -29,7 +31,8 @@ abstract class _ChatStoreBase with Store {
|
|||
|
||||
final AuthStore auth;
|
||||
|
||||
final scrollController = ScrollController();
|
||||
final _scrollController = ScrollController();
|
||||
get scrollController => _scrollController;
|
||||
|
||||
@readonly
|
||||
var _autoScroll = true;
|
||||
|
|
@ -38,9 +41,7 @@ abstract class _ChatStoreBase with Store {
|
|||
final commands = [
|
||||
'PASS oauth:${auth.token}',
|
||||
'NICK ${auth.isLoggedIn ? auth.user!.login : 'justinfan888'}',
|
||||
'CAP REQ :twitch.tv/tags',
|
||||
'CAP REQ :twitch.tv/commands',
|
||||
// 'CAP REQ :twitch.tv/membership',
|
||||
'CAP REQ :twitch.tv/tags twitch.tv/commands twitch.tv/membership',
|
||||
'CAP END',
|
||||
'JOIN #$channelName',
|
||||
];
|
||||
|
|
@ -48,17 +49,15 @@ abstract class _ChatStoreBase with Store {
|
|||
for (final command in commands) {
|
||||
channel.sink.add(command);
|
||||
}
|
||||
|
||||
scrollController.addListener(() {
|
||||
if (!scrollController.position.atEdge && scrollController.position.pixels < scrollController.position.maxScrollExtent) {
|
||||
_scrollController.addListener(() {
|
||||
if (!_scrollController.position.atEdge && _scrollController.position.pixels < _scrollController.position.maxScrollExtent) {
|
||||
_autoScroll = false;
|
||||
} else if (scrollController.position.atEdge && scrollController.position.pixels != scrollController.position.minScrollExtent) {
|
||||
} else if (_scrollController.position.atEdge && _scrollController.position.pixels != _scrollController.position.minScrollExtent) {
|
||||
_autoScroll = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> getAssets() async {
|
||||
final channelInfo = await Twitch.getUser(userLogin: channelName, headers: auth.headersTwitch);
|
||||
|
||||
|
|
@ -84,15 +83,15 @@ abstract class _ChatStoreBase with Store {
|
|||
}
|
||||
}
|
||||
|
||||
void handleWebsocketData(Object? data) {
|
||||
final ircMessages = data.toString();
|
||||
void handleWebsocketData(String ircMessages) {
|
||||
for (final message in ircMessages.substring(0, ircMessages.length - 2).split('\r\n')) {
|
||||
debugPrint(message);
|
||||
if (message.startsWith('@')) {
|
||||
final parsed = Irc.parse(message);
|
||||
final parsedIRCMessage = IRC.parse(message);
|
||||
|
||||
switch (parsed.command) {
|
||||
switch (parsedIRCMessage.command) {
|
||||
case 'CLEARCHAT':
|
||||
clearChat(ircMessage: parsed);
|
||||
_messages = IRC.CLEARCHAT(messages: _messages, ircMessage: parsedIRCMessage);
|
||||
break;
|
||||
case 'CLEARMSG':
|
||||
break;
|
||||
|
|
@ -100,20 +99,20 @@ abstract class _ChatStoreBase with Store {
|
|||
break;
|
||||
case 'PRIVMSG':
|
||||
if (_autoScroll) {
|
||||
if (messages.length > 100) {
|
||||
messages.removeRange(0, messages.length - 100);
|
||||
if (_messages.length > 100) {
|
||||
_messages.removeRange(0, _messages.length - 100);
|
||||
}
|
||||
SchedulerBinding.instance?.addPostFrameCallback((_) {
|
||||
scrollController.jumpTo(scrollController.position.maxScrollExtent);
|
||||
});
|
||||
}
|
||||
messages.add(parsed);
|
||||
_messages = IRC.PRIVMSG(messages: _messages, ircMessage: parsedIRCMessage);
|
||||
break;
|
||||
case 'ROOMSTATE':
|
||||
IRC.USERNOTICE(messages: _messages, ircMessage: parsedIRCMessage);
|
||||
break;
|
||||
case 'USERNOTICE':
|
||||
IRC.USERNOTICE(messages: _messages, ircMessage: parsedIRCMessage);
|
||||
break;
|
||||
case 'USERSTATE':
|
||||
IRC.USERSTATE(messages: _messages, ircMessage: parsedIRCMessage);
|
||||
break;
|
||||
}
|
||||
} else if (message.startsWith('P')) {
|
||||
|
|
@ -122,31 +121,7 @@ abstract class _ChatStoreBase with Store {
|
|||
}
|
||||
}
|
||||
|
||||
void clearChat({required IrcMessage ircMessage}) {
|
||||
// If there is no message, it means that entire chat was cleared.
|
||||
if (ircMessage.message == null) {
|
||||
// messages.clear();
|
||||
messages[0].message = 'User was permabanned!';
|
||||
return;
|
||||
}
|
||||
|
||||
final bannedUser = ircMessage.message;
|
||||
final banDuration = ircMessage.tags['ban-duration'];
|
||||
|
||||
debugPrint('$bannedUser was banned');
|
||||
|
||||
messages.asMap().forEach((i, message) {
|
||||
if (message.user! == bannedUser) {
|
||||
if (banDuration == null) {
|
||||
messages[i].message = 'User was permabanned!';
|
||||
} else {
|
||||
messages[i].message = 'User was timed out for $banDuration seconds!';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ChatMessage renderChatMessage({required IrcMessage ircMessage}) {
|
||||
ChatMessage renderChatMessage(IRCMessage ircMessage) {
|
||||
final result = <InlineSpan>[];
|
||||
|
||||
final emoteTags = ircMessage.tags['emotes'];
|
||||
|
|
@ -245,9 +220,9 @@ abstract class _ChatStoreBase with Store {
|
|||
@action
|
||||
void resumeScroll() {
|
||||
_autoScroll = true;
|
||||
scrollController.jumpTo(scrollController.position.maxScrollExtent);
|
||||
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
|
||||
SchedulerBinding.instance?.addPostFrameCallback((_) {
|
||||
scrollController.jumpTo(scrollController.position.maxScrollExtent);
|
||||
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,23 @@ 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 {
|
||||
|
|
@ -26,13 +43,6 @@ mixin _$ChatStore on _ChatStoreBase, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$getAssetsAsyncAction = AsyncAction('_ChatStoreBase.getAssets');
|
||||
|
||||
@override
|
||||
Future<void> getAssets() {
|
||||
return _$getAssetsAsyncAction.run(() => super.getAssets());
|
||||
}
|
||||
|
||||
final _$_ChatStoreBaseActionController =
|
||||
ActionController(name: '_ChatStoreBase');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue