Improve chat error handling
This commit is contained in:
parent
268f8427d6
commit
679a7f45f0
9 changed files with 181 additions and 101 deletions
|
|
@ -20,7 +20,7 @@ class BTTVApi {
|
|||
|
||||
return emotes.map((emote) => Emote.fromBTTV(emote, EmoteType.bttvGlobal)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get global BTTV emotes.');
|
||||
return Future.error('Failed to get BTTV global emotes.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ class BTTVApi {
|
|||
|
||||
return emoteToUrl;
|
||||
} else {
|
||||
throw Exception('Failed to get channel BTTV emotes.');
|
||||
return Future.error('Failed to get BTTV channel emotes.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class BTTVApi {
|
|||
|
||||
return {for (final badge in badgeObjects) badge.providerId: Badge.fromBTTV(badge)};
|
||||
} else {
|
||||
throw Exception('Failed to get BTTV badges');
|
||||
return Future.error('Failed to get BTTV badges');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class FFZApi {
|
|||
|
||||
return emotes.map((emote) => Emote.fromFFZ(emote, EmoteType.ffzGlobal)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get global FFZ emotes.');
|
||||
return Future.error('Failed to get FFZ global emotes.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ class FFZApi {
|
|||
|
||||
return Tuple2(roomInfo, emotes.map((emote) => Emote.fromFFZ(emote, EmoteType.ffzChannel)).toList());
|
||||
} else {
|
||||
throw Exception('Failed to get FFZ room info.}');
|
||||
return Future.error('Failed to get FFZ room info.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ class FFZApi {
|
|||
|
||||
return result;
|
||||
} else {
|
||||
throw Exception('Failed to get FFZ badges.');
|
||||
return Future.error('Failed to get FFZ badges.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class SevenTVAPI {
|
|||
|
||||
return emotes.map((emote) => Emote.from7TV(emote, EmoteType.sevenTvGlobal)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get global 7TV emotes.');
|
||||
return Future.error('Failed to get 7TV global emotes');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ class SevenTVAPI {
|
|||
|
||||
return emotes.map((emote) => Emote.from7TV(emote, EmoteType.sevenTvChannel)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get channel 7TV emotes.');
|
||||
return Future.error('Failed to get 7TV channel emotes');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ class SevenTVAPI {
|
|||
|
||||
return result;
|
||||
} else {
|
||||
throw Exception('Failed to get 7TV badges.');
|
||||
return Future.error('Failed to get 7TV badges.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class TwitchApi {
|
|||
|
||||
return emotes.map((emote) => Emote.fromTwitch(emote, EmoteType.twitchGlobal)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get global Twitch emotes.');
|
||||
return Future.error('Failed to get Twitch global emotes.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class TwitchApi {
|
|||
|
||||
return emotes.map((emote) => Emote.fromTwitch(emote, EmoteType.twitchChannel)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get channel Twitch emotes.');
|
||||
return Future.error('Failed to get Twitch channel emotes.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ class TwitchApi {
|
|||
}
|
||||
}).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get Twitch emotes set.');
|
||||
return Future.error('Failed to get Twitch emotes set.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ class TwitchApi {
|
|||
|
||||
return result;
|
||||
} else {
|
||||
throw Exception('Failed to get global Twitch badges.');
|
||||
return Future.error('Failed to get Twitch global badges.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ class TwitchApi {
|
|||
|
||||
return result;
|
||||
} else {
|
||||
throw Exception('Failed to get Twitch channel badges.');
|
||||
return Future.error('Failed to get Twitch channel badges.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ class TwitchApi {
|
|||
|
||||
return UserTwitch.fromJson(userData.first);
|
||||
} else {
|
||||
throw Exception('Failed to get user info');
|
||||
return Future.error('Failed to get Twitch user info');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ class TwitchApi {
|
|||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body)['access_token'];
|
||||
} else {
|
||||
throw Exception('Failed to get default token.');
|
||||
return Future.error('Failed to get default token.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -227,10 +227,10 @@ class TwitchApi {
|
|||
if (data.isNotEmpty) {
|
||||
return StreamTwitch.fromJson(data.first);
|
||||
} else {
|
||||
throw Exception('$userLogin is offline');
|
||||
return Future.error('$userLogin is offline');
|
||||
}
|
||||
} else {
|
||||
throw Exception('Failed to get stream info.');
|
||||
return Future.error('Failed to get stream info.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ class TwitchApi {
|
|||
|
||||
return channelData.map((e) => ChannelQuery.fromJson(e)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to get channels.');
|
||||
return Future.error('Failed to get channels.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ class TwitchApi {
|
|||
|
||||
return CategoriesTwitch.fromJson(decoded);
|
||||
} else {
|
||||
throw Exception('Failed to get categories.');
|
||||
return Future.error('Failed to get categories.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ class TwitchApi {
|
|||
|
||||
return decoded['total'] as int;
|
||||
} else {
|
||||
throw Exception('Failed to get sub count.');
|
||||
return Future.error('Failed to get sub count.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -352,7 +352,7 @@ class TwitchApi {
|
|||
|
||||
return ChatUsers.fromJson(decoded);
|
||||
} else {
|
||||
throw Exception('Failed to get chatters.');
|
||||
return Future.error('Failed to get chatters.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -381,10 +381,10 @@ class TwitchApi {
|
|||
|
||||
return result;
|
||||
} else {
|
||||
throw Exception('User does not have anyone blocked');
|
||||
return Future.error('User does not have anyone blocked');
|
||||
}
|
||||
} else {
|
||||
throw Exception('User does not exist');
|
||||
return Future.error('User does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import 'package:frosty/api/seventv_api.dart';
|
|||
import 'package:frosty/api/twitch_api.dart';
|
||||
import 'package:frosty/models/badges.dart';
|
||||
import 'package:frosty/models/emotes.dart';
|
||||
import 'package:frosty/models/user.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'chat_assets_store.g.dart';
|
||||
|
|
@ -81,56 +80,76 @@ abstract class _ChatAssetsStoreBase with Store {
|
|||
|
||||
/// Fetches global and channel assets (badges and emotes) and stores them in [_emoteToUrl]
|
||||
@action
|
||||
Future<void> getAssets({required String channelName, required Map<String, String> headers}) async {
|
||||
// Fetch the desired channel/user's information.
|
||||
final channelInfo = await twitchApi.getUser(userLogin: channelName, headers: headers);
|
||||
|
||||
if (channelInfo != null) {
|
||||
Future<void> assetsFuture({
|
||||
required String channelName,
|
||||
required String channelId,
|
||||
required Map<String, String> headers,
|
||||
required Function onEmoteError,
|
||||
required Function onBadgeError,
|
||||
}) =>
|
||||
// Fetch the global and channel's assets (emotes & badges).
|
||||
// Async awaits are placed in a list so they are performed in parallel.
|
||||
|
||||
await Future.wait([
|
||||
getEmotes(channelInfo: channelInfo, headers: headers),
|
||||
getBadges(channelInfo: channelInfo, headers: headers),
|
||||
Future.wait([
|
||||
emotesFuture(
|
||||
channelName: channelName,
|
||||
channelId: channelId,
|
||||
headers: headers,
|
||||
onError: onEmoteError,
|
||||
),
|
||||
badgesFuture(
|
||||
channelId: channelId,
|
||||
headers: headers,
|
||||
onError: onBadgeError,
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> getEmotes({required UserTwitch channelInfo, required Map<String, String> headers}) async {
|
||||
final assets = await Future.wait([
|
||||
ffzApi.getEmotesGlobal(),
|
||||
bttvApi.getEmotesGlobal(),
|
||||
bttvApi.getEmotesChannel(id: channelInfo.id),
|
||||
twitchApi.getEmotesGlobal(headers: headers),
|
||||
twitchApi.getEmotesChannel(id: channelInfo.id, headers: headers),
|
||||
sevenTvApi.getEmotesGlobal(),
|
||||
sevenTvApi.getEmotesChannel(user: channelInfo.login),
|
||||
ffzApi.getRoomInfo(name: channelInfo.login).then((ffzRoom) {
|
||||
ffzRoomInfo = ffzRoom?.item1;
|
||||
return ffzRoom?.item2 ?? <Emote>[];
|
||||
}),
|
||||
]);
|
||||
|
||||
final emotes = assets.expand((list) => list);
|
||||
|
||||
_emoteToObject = {for (final emote in emotes) emote.name: emote};
|
||||
}
|
||||
Future<void> emotesFuture({
|
||||
required String channelId,
|
||||
required String channelName,
|
||||
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).catchError(onError),
|
||||
sevenTvApi.getEmotesGlobal().catchError(onError),
|
||||
sevenTvApi.getEmotesChannel(user: channelName).catchError(onError),
|
||||
ffzApi.getRoomInfo(name: channelName).then((ffzRoom) {
|
||||
ffzRoomInfo = ffzRoom.item1;
|
||||
return ffzRoom.item2;
|
||||
}).catchError(onError),
|
||||
]).then((assets) => assets.expand((list) => list)).then((emotes) => _emoteToObject = {for (final emote in emotes) emote.name: emote});
|
||||
|
||||
@action
|
||||
Future<void> getBadges({required UserTwitch channelInfo, required Map<String, String> headers}) async => await Future.wait([
|
||||
Future<void> badgesFuture({
|
||||
required String channelId,
|
||||
required Map<String, String> headers,
|
||||
required Function onError,
|
||||
}) =>
|
||||
Future.wait([
|
||||
twitchApi
|
||||
.getBadgesGlobal()
|
||||
.then((badges) => twitchBadgesToObject.addAll(badges))
|
||||
.then((_) => twitchApi.getBadgesChannel(id: channelInfo.id).then((badges) => twitchBadgesToObject.addAll(badges))),
|
||||
ffzApi.getBadges().then((badges) => _userToFFZBadges = badges ?? {}),
|
||||
sevenTvApi.getBadges().then((badges) => _userTo7TVBadges = badges ?? {}),
|
||||
bttvApi.getBadges().then((badges) => _userToBTTVBadges = badges ?? {}),
|
||||
.then((_) => twitchApi.getBadgesChannel(id: channelId).then((badges) => twitchBadgesToObject.addAll(badges)).catchError(onError)),
|
||||
ffzApi.getBadges().then((badges) => _userToFFZBadges = badges).catchError(onError),
|
||||
sevenTvApi.getBadges().then((badges) => _userTo7TVBadges = badges).catchError(onError),
|
||||
bttvApi.getBadges().then((badges) => _userToBTTVBadges = badges).catchError(onError),
|
||||
]);
|
||||
|
||||
@action
|
||||
Future<void> getUserEmotes({required List<String> emoteSets, required Map<String, String> headers}) async =>
|
||||
await Future.wait(emoteSets.map((setId) => twitchApi.getEmotesSets(setId: setId, headers: headers)))
|
||||
Future<void> userEmotesFuture({
|
||||
required List<String> emoteSets,
|
||||
required Map<String, String> headers,
|
||||
required Function onError,
|
||||
}) =>
|
||||
Future.wait(emoteSets.map((setId) => twitchApi.getEmotesSets(setId: setId, headers: headers).catchError(onError)))
|
||||
.then((emotes) => emotes.expand((list) => list).toList())
|
||||
.then((userEmotes) => _userEmoteToObject = {for (final emote in userEmotes) emote.name: emote}.asObservable());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,41 +152,77 @@ mixin _$ChatAssetsStore on _ChatAssetsStoreBase, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$getAssetsAsyncAction = AsyncAction('_ChatAssetsStoreBase.getAssets');
|
||||
final _$_ChatAssetsStoreBaseActionController =
|
||||
ActionController(name: '_ChatAssetsStoreBase');
|
||||
|
||||
@override
|
||||
Future<void> getAssets(
|
||||
{required String channelName, required Map<String, String> headers}) {
|
||||
return _$getAssetsAsyncAction
|
||||
.run(() => super.getAssets(channelName: channelName, headers: headers));
|
||||
Future<void> assetsFuture(
|
||||
{required String channelName,
|
||||
required String channelId,
|
||||
required Map<String, String> headers,
|
||||
required Function onEmoteError,
|
||||
required Function onBadgeError}) {
|
||||
final _$actionInfo = _$_ChatAssetsStoreBaseActionController.startAction(
|
||||
name: '_ChatAssetsStoreBase.assetsFuture');
|
||||
try {
|
||||
return super.assetsFuture(
|
||||
channelName: channelName,
|
||||
channelId: channelId,
|
||||
headers: headers,
|
||||
onEmoteError: onEmoteError,
|
||||
onBadgeError: onBadgeError);
|
||||
} finally {
|
||||
_$_ChatAssetsStoreBaseActionController.endAction(_$actionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
final _$getEmotesAsyncAction = AsyncAction('_ChatAssetsStoreBase.getEmotes');
|
||||
|
||||
@override
|
||||
Future<void> getEmotes(
|
||||
{required UserTwitch channelInfo, required Map<String, String> headers}) {
|
||||
return _$getEmotesAsyncAction
|
||||
.run(() => super.getEmotes(channelInfo: channelInfo, headers: headers));
|
||||
Future<void> emotesFuture(
|
||||
{required String channelId,
|
||||
required String channelName,
|
||||
required Map<String, String> headers,
|
||||
required Function onError}) {
|
||||
final _$actionInfo = _$_ChatAssetsStoreBaseActionController.startAction(
|
||||
name: '_ChatAssetsStoreBase.emotesFuture');
|
||||
try {
|
||||
return super.emotesFuture(
|
||||
channelId: channelId,
|
||||
channelName: channelName,
|
||||
headers: headers,
|
||||
onError: onError);
|
||||
} finally {
|
||||
_$_ChatAssetsStoreBaseActionController.endAction(_$actionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
final _$getBadgesAsyncAction = AsyncAction('_ChatAssetsStoreBase.getBadges');
|
||||
|
||||
@override
|
||||
Future<void> getBadges(
|
||||
{required UserTwitch channelInfo, required Map<String, String> headers}) {
|
||||
return _$getBadgesAsyncAction
|
||||
.run(() => super.getBadges(channelInfo: channelInfo, headers: headers));
|
||||
Future<void> badgesFuture(
|
||||
{required String channelId,
|
||||
required Map<String, String> headers,
|
||||
required Function onError}) {
|
||||
final _$actionInfo = _$_ChatAssetsStoreBaseActionController.startAction(
|
||||
name: '_ChatAssetsStoreBase.badgesFuture');
|
||||
try {
|
||||
return super.badgesFuture(
|
||||
channelId: channelId, headers: headers, onError: onError);
|
||||
} finally {
|
||||
_$_ChatAssetsStoreBaseActionController.endAction(_$actionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
final _$getUserEmotesAsyncAction =
|
||||
AsyncAction('_ChatAssetsStoreBase.getUserEmotes');
|
||||
|
||||
@override
|
||||
Future<void> getUserEmotes(
|
||||
{required List<String> emoteSets, required Map<String, String> headers}) {
|
||||
return _$getUserEmotesAsyncAction
|
||||
.run(() => super.getUserEmotes(emoteSets: emoteSets, headers: headers));
|
||||
Future<void> userEmotesFuture(
|
||||
{required List<String> emoteSets,
|
||||
required Map<String, String> headers,
|
||||
required Function onError}) {
|
||||
final _$actionInfo = _$_ChatAssetsStoreBaseActionController.startAction(
|
||||
name: '_ChatAssetsStoreBase.userEmotesFuture');
|
||||
try {
|
||||
return super.userEmotesFuture(
|
||||
emoteSets: emoteSets, headers: headers, onError: onError);
|
||||
} finally {
|
||||
_$_ChatAssetsStoreBaseActionController.endAction(_$actionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:frosty/core/auth/auth_store.dart';
|
||||
import 'package:frosty/models/badges.dart';
|
||||
import 'package:frosty/models/emotes.dart';
|
||||
import 'package:frosty/models/irc_message.dart';
|
||||
import 'package:frosty/screens/channel/stores/chat_assets_store.dart';
|
||||
import 'package:frosty/screens/channel/stores/chat_details_store.dart';
|
||||
|
|
@ -30,6 +32,12 @@ abstract class _ChatStoreBase with Store {
|
|||
/// The name of the channel to connect to.
|
||||
final String channelName;
|
||||
|
||||
/// The channel's ID for API requests.
|
||||
final String channelId;
|
||||
|
||||
/// The channel's display name to show on widgets.
|
||||
final String displayName;
|
||||
|
||||
/// The Twitch IRC WebSocket channel.
|
||||
WebSocketChannel? _channel;
|
||||
|
||||
|
|
@ -74,6 +82,8 @@ abstract class _ChatStoreBase with Store {
|
|||
required this.assetsStore,
|
||||
required this.settings,
|
||||
required this.channelName,
|
||||
required this.channelId,
|
||||
required this.displayName,
|
||||
}) {
|
||||
// Create a reaction where anytime the emote menu is shown or hidden,
|
||||
// scroll to the bottom of the list. This will prevent the emote menu
|
||||
|
|
@ -145,11 +155,14 @@ abstract class _ChatStoreBase with Store {
|
|||
case Command.globalUserState:
|
||||
final setIds = parsedIRCMessage.tags['emote-sets']?.split(',');
|
||||
if (setIds != null) {
|
||||
_messages.add(IRCMessage.createNotice(message: 'Fetching user emotes...'));
|
||||
assetsStore
|
||||
.getUserEmotes(emoteSets: setIds, headers: auth.headersTwitch)
|
||||
.then((_) => _messages.add(IRCMessage.createNotice(message: 'User emotes fetched!')))
|
||||
.onError((error, stackTrace) => _messages.add(IRCMessage.createNotice(message: 'Failed to fetch user emotes: ${error.toString()}')));
|
||||
assetsStore.userEmotesFuture(
|
||||
emoteSets: setIds,
|
||||
headers: auth.headersTwitch,
|
||||
onError: (error) {
|
||||
debugPrint(error.toString());
|
||||
return <Emote>[];
|
||||
},
|
||||
);
|
||||
}
|
||||
continue;
|
||||
case Command.none:
|
||||
|
|
@ -170,15 +183,22 @@ abstract class _ChatStoreBase with Store {
|
|||
_channel?.sink.add('PONG :tmi.twitch.tv');
|
||||
return;
|
||||
} else if (message.contains('Welcome, GLHF!')) {
|
||||
_messages.add(IRCMessage.createNotice(message: "Connected to $channelName's chat"));
|
||||
_messages.add(IRCMessage.createNotice(message: "Connected to $displayName's chat"));
|
||||
|
||||
// Fetch the assets used in chat including badges and emotes.
|
||||
_messages.add(IRCMessage.createNotice(message: 'Fetching badges and emotes...'));
|
||||
assetsStore
|
||||
.getAssets(channelName: channelName, headers: auth.headersTwitch)
|
||||
.then((_) => _messages.add(IRCMessage.createNotice(message: 'Badges and emotes fetched!')))
|
||||
.onError((error, stackTrace) => _messages.add(IRCMessage.createNotice(message: 'Failed to fetch assets: ${error.toString()}')));
|
||||
|
||||
assetsStore.assetsFuture(
|
||||
channelName: channelName,
|
||||
channelId: channelId,
|
||||
headers: auth.headersTwitch,
|
||||
onEmoteError: (error) {
|
||||
debugPrint(error.toString());
|
||||
return <Emote>[];
|
||||
},
|
||||
onBadgeError: (error) {
|
||||
debugPrint(error.toString());
|
||||
return <Badge>[];
|
||||
},
|
||||
);
|
||||
// Reset exponential backoff if successfully connected.
|
||||
_retries = 0;
|
||||
_backoffTime = 0;
|
||||
|
|
@ -211,7 +231,6 @@ abstract class _ChatStoreBase with Store {
|
|||
(data) => _handleIRCData(data.toString()),
|
||||
onError: (error) {
|
||||
debugPrint('Chat error: ${error.toString()}');
|
||||
_messages.add(IRCMessage.createNotice(message: 'Chat error - ${error.toString()}'));
|
||||
},
|
||||
onDone: () async {
|
||||
if (_channel == null) return;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ class SearchResultsChannels extends StatelessWidget {
|
|||
builder: (context) => VideoChat(
|
||||
displayName: channelInfo.broadcasterName,
|
||||
chatStore: ChatStore(
|
||||
channelName: channelInfo.broadcasterLogin,
|
||||
channelId: channelInfo.broadcasterId,
|
||||
displayName: channelInfo.broadcasterName,
|
||||
chatDetailsStore: ChatDetailsStore(
|
||||
twitchApi: context.read<TwitchApi>(),
|
||||
),
|
||||
|
|
@ -44,7 +47,6 @@ class SearchResultsChannels extends StatelessWidget {
|
|||
bttvApi: context.read<BTTVApi>(),
|
||||
sevenTvApi: context.read<SevenTVAPI>(),
|
||||
),
|
||||
channelName: channelInfo.broadcasterLogin,
|
||||
auth: searchStore.authStore,
|
||||
settings: context.read<SettingsStore>(),
|
||||
),
|
||||
|
|
@ -110,6 +112,9 @@ class SearchResultsChannels extends StatelessWidget {
|
|||
builder: (context) => VideoChat(
|
||||
displayName: channel.displayName,
|
||||
chatStore: ChatStore(
|
||||
channelName: channel.broadcasterLogin,
|
||||
channelId: channel.id,
|
||||
displayName: channel.displayName,
|
||||
chatDetailsStore: ChatDetailsStore(
|
||||
twitchApi: context.read<TwitchApi>(),
|
||||
),
|
||||
|
|
@ -119,7 +124,6 @@ class SearchResultsChannels extends StatelessWidget {
|
|||
bttvApi: context.read<BTTVApi>(),
|
||||
sevenTvApi: context.read<SevenTVAPI>(),
|
||||
),
|
||||
channelName: channel.broadcasterLogin,
|
||||
auth: searchStore.authStore,
|
||||
settings: context.read<SettingsStore>(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ class StreamCard extends StatelessWidget {
|
|||
displayName: streamInfo.userName,
|
||||
chatStore: ChatStore(
|
||||
channelName: streamInfo.userLogin,
|
||||
channelId: streamInfo.userId,
|
||||
displayName: streamInfo.userName,
|
||||
auth: context.read<AuthStore>(),
|
||||
settings: context.read<SettingsStore>(),
|
||||
chatDetailsStore: ChatDetailsStore(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue