Skip to content

Commit

Permalink
Update bloc and use new state pattern (#45)
Browse files Browse the repository at this point in the history
* Update bloc and use new state pattern

* Fixing most prop equatable uses
  • Loading branch information
clone1018 authored Feb 22, 2022
1 parent 3d9a887 commit 83b7724
Show file tree
Hide file tree
Showing 14 changed files with 411 additions and 653 deletions.
123 changes: 14 additions & 109 deletions lib/blocs/repos/channel_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ import 'package:glimesh_app/models.dart';

/* Events */
@immutable
abstract class ChannelEvent extends Equatable {
ChannelEvent([List props = const []]) : super();
}
abstract class ChannelEvent extends Equatable {}

class LoadChannel extends ChannelEvent {
final int channelId;

LoadChannel({required this.channelId}) : super([channelId]);
LoadChannel({required this.channelId});

@override
List<Object> get props => [this.channelId];
Expand All @@ -26,28 +24,15 @@ class LoadChannel extends ChannelEvent {
class WatchChannel extends ChannelEvent {
final int channelId;

WatchChannel({required this.channelId}) : super([channelId]);
WatchChannel({required this.channelId});

@override
List<Object> get props => [this.channelId];
}

class SendChatMessage extends ChannelEvent {
final int channelId;
final String message;

SendChatMessage({required this.channelId, required this.message})
: super([channelId, message]);

@override
List<Object> get props => [this.channelId, message];
}

/* State */
@immutable
abstract class ChannelState extends Equatable {
ChannelState([List props = const []]) : super();
}
abstract class ChannelState extends Equatable {}

class ChannelLoading extends ChannelState {
@override
Expand All @@ -58,7 +43,7 @@ class ChannelLoading extends ChannelState {
class ChannelLoaded extends ChannelState {
final User channel;

ChannelLoaded({required this.channel}) : super([channel]);
ChannelLoaded({required this.channel});

@override
List<Object> get props => [channel];
Expand All @@ -67,10 +52,8 @@ class ChannelLoaded extends ChannelState {
// ChannelReady is for when we're ready to play the video
class ChannelReady extends ChannelState {
final JanusEdgeRoute edgeRoute;
final Stream<List<ChatMessage>> chatMessagesStream;

ChannelReady({required this.edgeRoute, required this.chatMessagesStream})
: super([edgeRoute, chatMessagesStream]);
ChannelReady({required this.edgeRoute});

@override
List<Object> get props => [edgeRoute];
Expand All @@ -79,7 +62,7 @@ class ChannelReady extends ChannelState {
class ChannelNotLoaded extends ChannelState {
final List<GraphQLError>? errors;

ChannelNotLoaded([this.errors]) : super([errors]);
ChannelNotLoaded([this.errors]);

@override
List<Object?> get props => [this.errors];
Expand All @@ -89,79 +72,13 @@ class ChannelNotLoaded extends ChannelState {
class ChannelBloc extends Bloc<ChannelEvent, ChannelState> {
final GlimeshRepository glimeshRepository;

ChannelBloc({required this.glimeshRepository}) : super(ChannelLoading());

List<ChatMessage> chatMessages = [];

final _controller = StreamController<List<ChatMessage>>();
Stream<List<ChatMessage>> get chatMessagesStream =>
_controller.stream.asBroadcastStream();

@override
Stream<ChannelState> mapEventToState(ChannelEvent event) async* {
try {
print("ChannelBloc.mapEventToState($event)");
if (event is WatchChannel) {
print("Event is WatchChannel");

JanusEdgeRoute edgeRoute = await watchChannel(event.channelId);
Stream<QueryResult> subscription =
this.glimeshRepository.subscribeToChatMessages(event.channelId);

final queryResults =
await this.glimeshRepository.getSomeChatMessages(event.channelId);

if (!queryResults.hasException) {
final List<dynamic> messages = queryResults.data!['channel']
['chatMessages']['edges'] as List<dynamic>;

final List<ChatMessage> existingChatMessages = messages
.map((dynamic e) => ChatMessage(
username: e['node']['user']['username'] as String,
avatarUrl: e['node']['user']['avatarUrl'] as String,
tokens: _buildMessageTokensFromJson(e['node']['tokens']),
))
.toList();

chatMessages = existingChatMessages.reversed.toList();
_controller.add(chatMessages);
}

subscription.listen((event) {
dynamic data = event.data!['chatMessage'] as dynamic;

ChatMessage chatMessage = ChatMessage(
username: data['user']['username'] as String,
avatarUrl: data['user']['avatarUrl'] as String,
tokens: _buildMessageTokensFromJson(data['tokens']),
);

chatMessages.insert(0, chatMessage);

// Introducing the slowest thing on the planet!
// chatMessagesStream.
_controller.add(chatMessages);
// _controller.add(chatMessages.reversed.toList());
});

yield ChannelReady(
edgeRoute: edgeRoute,
chatMessagesStream: chatMessagesStream,
);
} else if (event is SendChatMessage) {
// Currently this doesn't yield anything back since the subscription handler will automatically get it back from the server
// TODO: What we should add is yielding an error when it fails to send.
this.glimeshRepository.sendChatMessage(event.channelId, event.message);
} else {
// else if (event is LoadChannel) {
// yield* _mapUserToState(event.username);
// }
// New event, who dis?
}
} catch (_, stackTrace) {
print('$_ $stackTrace');
yield state;
}
ChannelBloc({required this.glimeshRepository}) : super(ChannelLoading()) {
on<WatchChannel>((event, emit) async {
JanusEdgeRoute edgeRoute = await watchChannel(event.channelId);
emit(ChannelReady(
edgeRoute: edgeRoute,
));
});
}

Future<JanusEdgeRoute> watchChannel(int channelId) async {
Expand All @@ -171,18 +88,6 @@ class ChannelBloc extends Bloc<ChannelEvent, ChannelState> {
return _buildJanusEdgeRouteFromJson(res.data!['watchChannel']);
}

List<MessageToken> _buildMessageTokensFromJson(List<dynamic> json) {
final List<MessageToken> tokens = json
.map((dynamic token) => MessageToken(
tokenType: token['type'] as String,
text: token['text'] as String,
src: token['src'] as String?,
))
.toList();

return tokens;
}

JanusEdgeRoute _buildJanusEdgeRouteFromJson(dynamic json) {
return JanusEdgeRoute(
id: int.parse(json['id']),
Expand Down
146 changes: 54 additions & 92 deletions lib/blocs/repos/channel_list_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,13 @@ import 'package:glimesh_app/models.dart';
import 'package:glimesh_app/lang_displaynames.dart';

@immutable
abstract class ChannelListEvent extends Equatable {
ChannelListEvent([List props = const []]) : super();
}
abstract class ChannelListEvent extends Equatable {}

class LoadChannels extends ChannelListEvent {
final String categorySlug;
final int channelLimit;

LoadChannels({required this.categorySlug, this.channelLimit: 15})
: super([categorySlug, channelLimit]);
LoadChannels({required this.categorySlug, this.channelLimit: 15});

@override
String toString() => 'LoadChannels';
Expand All @@ -42,9 +39,7 @@ class LoadHomepageChannels extends ChannelListEvent {
}

@immutable
abstract class ChannelListState extends Equatable {
ChannelListState([List props = const []]) : super();
}
abstract class ChannelListState extends Equatable {}

class ChannelListLoading extends ChannelListState {
@override
Expand All @@ -57,7 +52,7 @@ class ChannelListLoading extends ChannelListState {
class ChannelListLoaded extends ChannelListState {
final List<Channel> results;

ChannelListLoaded({required this.results}) : super([results]);
ChannelListLoaded({required this.results});

@override
List<Object> get props => [results];
Expand All @@ -66,7 +61,7 @@ class ChannelListLoaded extends ChannelListState {
class ChannelListNotLoaded extends ChannelListState {
final List<GraphQLError>? errors;

ChannelListNotLoaded([this.errors]) : super([errors]);
ChannelListNotLoaded([this.errors]);

@override
String toString() => 'ReposNotLoaded';
Expand All @@ -81,111 +76,78 @@ class ChannelListBloc extends Bloc<ChannelListEvent, ChannelListState> {
List<Channel> channels = [];

ChannelListBloc({required this.glimeshRepository})
: super(ChannelListLoading());

@override
Stream<ChannelListState> mapEventToState(ChannelListEvent event) async* {
try {
print("ChannelListBloc.mapEventToState($event)");
if (event is LoadChannels) {
yield* _loadChannels(event.categorySlug, event.channelLimit);
} else if (event is LoadMyLiveFollowedChannels) {
yield* _loadMyLiveFollowedChannels();
} else if (event is LoadHomepageChannels) {
yield* _loadHomepageChannels();
} else {
// New event, who dis?
}
} catch (_, stackTrace) {
print('$_ $stackTrace');
yield state;
}
: super(ChannelListLoading()) {
on<LoadChannels>(_loadChannels);
on<LoadMyLiveFollowedChannels>(_loadMyLiveFollowedChannels);
on<LoadHomepageChannels>(_loadHomepageChannels);
}

Stream<ChannelListState> _loadChannels(
String categorySlug, int channelLimit) async* {
try {
yield ChannelListLoading();

final queryResults =
await this.glimeshRepository.getLiveChannels(categorySlug);
_loadChannels(LoadChannels event, Emitter emit) async {
emit(ChannelListLoading());

if (queryResults.hasException) {
yield ChannelListNotLoaded(queryResults.exception!.graphqlErrors);
return;
}
final queryResults =
await this.glimeshRepository.getLiveChannels(event.categorySlug);

final List<dynamic> channels =
queryResults.data!['channels']['edges'] as List<dynamic>;
if (queryResults.hasException) {
emit(ChannelListNotLoaded(queryResults.exception!.graphqlErrors));
return;
}

final List<Channel> listOfChannels =
channels.map(buildChannelFromJson).toList();
final List<dynamic> channels =
queryResults.data!['channels']['edges'] as List<dynamic>;

listOfChannels.shuffle();
final List<Channel> listOfChannels =
channels.map(buildChannelFromJson).toList();

print("ChannelListLoaded");
listOfChannels.shuffle();

yield ChannelListLoaded(results: listOfChannels);
} catch (error) {
print(error);
yield ChannelListNotLoaded();
}
emit(ChannelListLoaded(results: listOfChannels));
}

Stream<ChannelListState> _loadMyLiveFollowedChannels() async* {
try {
yield ChannelListLoading();
_loadMyLiveFollowedChannels(
LoadMyLiveFollowedChannels event, Emitter emit) async {
emit(ChannelListLoading());

final queryResults =
await this.glimeshRepository.getMyLiveFollowedChannels();
final queryResults =
await this.glimeshRepository.getMyLiveFollowedChannels();

if (queryResults.hasException) {
yield ChannelListNotLoaded(queryResults.exception!.graphqlErrors);
return;
}
if (queryResults.hasException) {
emit(ChannelListNotLoaded(queryResults.exception!.graphqlErrors));
return;
}

final List<dynamic> channels = queryResults.data!['myself']
['followingLiveChannels']['edges'] as List<dynamic>;
final List<dynamic> channels = queryResults.data!['myself']
['followingLiveChannels']['edges'] as List<dynamic>;

final List<Channel> listOfChannels =
channels.map(buildChannelFromJson).toList();
final List<Channel> listOfChannels =
channels.map(buildChannelFromJson).toList();

yield ChannelListLoaded(results: listOfChannels);
} catch (error) {
print(error);
yield ChannelListNotLoaded();
}
emit(ChannelListLoaded(results: listOfChannels));
}

Stream<ChannelListState> _loadHomepageChannels() async* {
try {
yield ChannelListLoading();
_loadHomepageChannels(LoadHomepageChannels event, Emitter emit) async {
emit(ChannelListLoading());

final queryResults = await this.glimeshRepository.getHomepageChannels();
final queryResults = await this.glimeshRepository.getHomepageChannels();

if (queryResults.hasException) {
yield ChannelListNotLoaded(queryResults.exception!.graphqlErrors);
return;
}
if (queryResults.hasException) {
emit(ChannelListNotLoaded(queryResults.exception!.graphqlErrors));
return;
}

final List<dynamic> channels =
queryResults.data!['homepageChannels']['edges'] as List<dynamic>;
final List<dynamic> channels =
queryResults.data!['homepageChannels']['edges'] as List<dynamic>;

// filter and then map here because channels can stop streaming and still be on the homepage,
// and this seemed like the best way instead of introducing nulls elsewhere.
final List<Channel> listOfChannels = channels
.where((c) => c['node']['stream'] != null)
.map(buildChannelFromJson)
.toList();
// filter and then map here because channels can stop streaming and still be on the homepage,
// and this seemed like the best way instead of introducing nulls elsewhere.
final List<Channel> listOfChannels = channels
.where((c) => c['node']['stream'] != null)
.map(buildChannelFromJson)
.toList();

listOfChannels.shuffle();
listOfChannels.shuffle();

yield ChannelListLoaded(results: listOfChannels);
} catch (error, s) {
print(error);
print(s);
yield ChannelListNotLoaded();
}
emit(ChannelListLoaded(results: listOfChannels));
}

Channel buildChannelFromJson(dynamic json) {
Expand Down
Loading

0 comments on commit 83b7724

Please sign in to comment.