Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/tommyxchow/frosty
Browse files Browse the repository at this point in the history
  • Loading branch information
tommyxchow committed Aug 11, 2024
2 parents 8284c51 + 6c49c0b commit 7d49f17
Show file tree
Hide file tree
Showing 8 changed files with 396 additions and 150 deletions.
31 changes: 18 additions & 13 deletions lib/screens/channel/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -128,26 +128,31 @@ class Chat extends StatelessWidget {
const Divider(),
Expanded(
child: FrostyPageView(
headers: const [
headers: [
'Recent',
'Twitch',
'7TV',
'BTTV',
'FFZ',
if (chatStore.settings.showTwitchEmotes)
'Twitch',
if (chatStore.settings.show7TVEmotes) '7TV',
if (chatStore.settings.showBTTVEmotes) 'BTTV',
if (chatStore.settings.showFFZEmotes) 'FFZ',
],
children: [
RecentEmotesPanel(
chatStore: chatStore,
),
EmoteMenuPanel(
chatStore: chatStore,
twitchEmotes: chatStore
.assetsStore.userEmoteSectionToEmotes,
),
if (chatStore.settings.showTwitchEmotes)
EmoteMenuPanel(
chatStore: chatStore,
twitchEmotes: chatStore
.assetsStore.userEmoteSectionToEmotes,
),
...[
chatStore.assetsStore.sevenTVEmotes,
chatStore.assetsStore.bttvEmotes,
chatStore.assetsStore.ffzEmotes,
if (chatStore.settings.show7TVEmotes)
chatStore.assetsStore.sevenTVEmotes,
if (chatStore.settings.showBTTVEmotes)
chatStore.assetsStore.bttvEmotes,
if (chatStore.settings.showFFZEmotes)
chatStore.assetsStore.ffzEmotes,
].map(
(emotes) => EmoteMenuPanel(
chatStore: chatStore,
Expand Down
156 changes: 76 additions & 80 deletions lib/screens/channel/chat/stores/chat_assets_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,91 +125,87 @@ abstract class ChatAssetsStoreBase with Store {
required Map<String, String> headers,
required Function onEmoteError,
required Function onBadgeError,
bool showTwitchEmotes = true,
bool showTwitchBadges = true,
bool show7TVEmotes = true,
bool showBTTVEmotes = true,
bool showBTTVBadges = true,
bool showFFZEmotes = true,
bool showFFZBadges = true,
}) =>
// Fetch the global and channel's assets (emotes & badges).
// Async awaits are placed in a list so they are performed in parallel.
//
// Emotes
Future.wait([
emotesFuture(
channelId: channelId,
headers: headers,
onError: onEmoteError,
),
badgesFuture(
channelId: channelId,
headers: headers,
onError: onBadgeError,
),
]);

@action
Future<void> emotesFuture({
required String channelId,
required Map<String, String> headers,
required Function onError,
}) =>
// Parallel futures look ugly, but are worth the performance improvement.
// Each future has it's own catchError so that the entire future is not ended on an error.
// This will ensure that other futures complete even if one fails.
Future.wait([
ffzApi.getEmotesGlobal().catchError(onError),
bttvApi.getEmotesGlobal().catchError(onError),
bttvApi.getEmotesChannel(id: channelId).catchError(onError),
twitchApi.getEmotesGlobal(headers: headers).catchError(onError),
twitchApi
.getEmotesChannel(id: channelId, headers: headers)
.then((emotes) {
_userEmoteSectionToEmotes.update(
'Channel Emotes',
(existingEmoteSet) => [...existingEmoteSet, ...emotes],
ifAbsent: () => emotes.toList(),
);

return emotes;
}).catchError(onError),
sevenTVApi.getEmotesGlobal().catchError(onError),
sevenTVApi.getEmotesChannel(id: channelId).then((data) {
final (setId, emotes) = data;
sevenTvEmoteSetId = setId;
return emotes;
}).catchError(onError),
ffzApi.getRoomInfo(id: channelId).then((ffzRoom) {
final (roomInfo, emotes) = ffzRoom;

ffzRoomInfo = roomInfo;
return emotes;
}).catchError(onError),
]).then((assets) => assets.expand((list) => list)).then(
(emotes) => _emoteToObject = {
for (final emote in emotes) emote.name: emote,
}.asObservable(),
);

@action
Future<void> badgesFuture({
required String channelId,
required Map<String, String> headers,
required Function onError,
}) =>
Future.wait([
// Get global badges first, then channel badges to avoid badge conflicts.
// We want the channel badges to override the global badges.
twitchApi
.getBadgesGlobal(headers: headers)
.then((badges) => twitchBadgesToObject.addAll(badges))
.then(
(_) => twitchApi
.getBadgesChannel(id: channelId, headers: headers)
.then((badges) => twitchBadgesToObject.addAll(badges))
.catchError(onError),
Future.wait([
if (showTwitchEmotes) ...[
twitchApi
.getEmotesGlobal(headers: headers)
.catchError(onEmoteError),
twitchApi
.getEmotesChannel(id: channelId, headers: headers)
.then((emotes) {
_userEmoteSectionToEmotes.update(
'Channel Emotes',
(existingEmoteSet) => [...existingEmoteSet, ...emotes],
ifAbsent: () => emotes.toList(),
);

return emotes;
}).catchError(onEmoteError),
],
if (show7TVEmotes) ...[
sevenTVApi.getEmotesGlobal().catchError(onEmoteError),
sevenTVApi.getEmotesChannel(id: channelId).then((data) {
final (setId, emotes) = data;
sevenTvEmoteSetId = setId;
return emotes;
}).catchError(onEmoteError),
],
if (showBTTVEmotes) ...[
bttvApi.getEmotesGlobal().catchError(onEmoteError),
bttvApi.getEmotesChannel(id: channelId).catchError(onEmoteError),
],
if (showFFZEmotes) ...[
ffzApi.getEmotesGlobal().catchError(onEmoteError),
ffzApi.getRoomInfo(id: channelId).then((ffzRoom) {
final (roomInfo, emotes) = ffzRoom;

ffzRoomInfo = roomInfo;
return emotes;
}).catchError(onEmoteError),
],
]).then((assets) => assets.expand((list) => list)).then(
(emotes) => _emoteToObject = {
for (final emote in emotes) emote.name: emote,
}.asObservable(),
),
ffzApi
.getBadges()
.then((badges) => _userToFFZBadges = badges)
.catchError(onError),
bttvApi
.getBadges()
.then((badges) => _userToBTTVBadges = badges)
.catchError(onError),
//Emotes
Future.wait([
// Get global badges first, then channel badges to avoid badge conflicts.
// We want the channel badges to override the global badges.
if (showTwitchBadges)
twitchApi
.getBadgesGlobal(headers: headers)
.then((badges) => twitchBadgesToObject.addAll(badges))
.then(
(_) => twitchApi
.getBadgesChannel(id: channelId, headers: headers)
.then((badges) => twitchBadgesToObject.addAll(badges))
.catchError(onBadgeError),
),
if (showFFZBadges)
ffzApi
.getBadges()
.then((badges) => _userToFFZBadges = badges)
.catchError(onBadgeError),
if (showBTTVBadges)
bttvApi
.getBadges()
.then((badges) => _userToBTTVBadges = badges)
.catchError(onBadgeError),
]),
]);

@action
Expand Down
57 changes: 21 additions & 36 deletions lib/screens/channel/chat/stores/chat_assets_store.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 40 additions & 2 deletions lib/screens/channel/chat/stores/chat_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,34 @@ abstract class ChatStoreBase with Store {
),
);

reactions.add(
reaction(
(_) => [
settings.showTwitchEmotes,
settings.showTwitchBadges,
settings.show7TVEmotes,
settings.showBTTVEmotes,
settings.showBTTVBadges,
settings.showFFZEmotes,
settings.showFFZBadges,
],
(_) {
if (!settings.show7TVEmotes) {
_sevenTVChannel?.sink.close(1000);
}

getAssets().then((_) {
if (settings.show7TVEmotes) {
final emoteSetId = assetsStore.sevenTvEmoteSetId;
if (emoteSetId != null) {
listenToSevenTVEmoteSet(emoteSetId: emoteSetId);
}
}
});
},
),
);

// Create a timer that will add messages from the buffer every 200 milliseconds.
_messageBufferTimer = Timer.periodic(
const Duration(milliseconds: 200),
Expand Down Expand Up @@ -353,8 +381,11 @@ abstract class ChatStoreBase with Store {
);

getAssets().then((_) {
if (assetsStore.sevenTvEmoteSetId != null) {
listenToSevenTVEmoteSet(emoteSetId: assetsStore.sevenTvEmoteSetId!);
if (!settings.show7TVEmotes) return;

final emoteSetId = assetsStore.sevenTvEmoteSetId;
if (emoteSetId != null) {
listenToSevenTVEmoteSet(emoteSetId: emoteSetId);
}
});

Expand All @@ -378,6 +409,13 @@ abstract class ChatStoreBase with Store {
debugPrint(error.toString());
return <Badge>[];
},
showTwitchEmotes: settings.showTwitchEmotes,
showTwitchBadges: settings.showTwitchBadges,
show7TVEmotes: settings.show7TVEmotes,
showBTTVEmotes: settings.showBTTVEmotes,
showBTTVBadges: settings.showBTTVBadges,
showFFZEmotes: settings.showFFZEmotes,
showFFZBadges: settings.showFFZBadges,
);

/// Re-enables [_autoScroll] and jumps to the latest message.
Expand Down
45 changes: 26 additions & 19 deletions lib/screens/channel/chat/widgets/chat_bottom_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,32 @@ class ChatBottomBar extends StatelessWidget {

@override
Widget build(BuildContext context) {
final emoteMenuButton = Tooltip(
message: 'Emote menu',
preferBelow: false,
child: IconButton(
color: chatStore.assetsStore.showEmoteMenu
? Theme.of(context).colorScheme.secondary
: null,
icon: Icon(
chatStore.assetsStore.showEmoteMenu
? Icons.emoji_emotions_rounded
: Icons.emoji_emotions_outlined,
),
onPressed: () {
FocusScope.of(context).unfocus();
chatStore.assetsStore.showEmoteMenu =
!chatStore.assetsStore.showEmoteMenu;
},
),
);
final isEmotesEnabled = chatStore.settings.showTwitchEmotes ||
chatStore.settings.show7TVEmotes ||
chatStore.settings.showBTTVEmotes ||
chatStore.settings.showFFZEmotes;

final emoteMenuButton = isEmotesEnabled
? Tooltip(
message: 'Emote menu',
preferBelow: false,
child: IconButton(
color: chatStore.assetsStore.showEmoteMenu
? Theme.of(context).colorScheme.secondary
: null,
icon: Icon(
chatStore.assetsStore.showEmoteMenu
? Icons.emoji_emotions_rounded
: Icons.emoji_emotions_outlined,
),
onPressed: () {
FocusScope.of(context).unfocus();
chatStore.assetsStore.showEmoteMenu =
!chatStore.assetsStore.showEmoteMenu;
},
),
)
: null;

return Observer(
builder: (context) {
Expand Down
Loading

0 comments on commit 7d49f17

Please sign in to comment.