4
2
Fork 0

Merge branch 'feat/adding-modified-eventsource-library' into WIP#feat#heartbeat-manager

pull/37/head
Sudharshan S. 2019-03-23 23:04:35 +08:00
commit 00134c05b8
Signed by: sudharshan
GPG Key ID: C861C97AAF3D9559
15 changed files with 197 additions and 156 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "utility_packages/dart-eventsource"]
path = utility_packages/dart-eventsource
url = git@makerforce.io:beep/dart-eventsource.git

View File

@ -17,7 +17,7 @@ class Routes {
title: "Beep",
theme: theme,
routes: routes,
home: Welcome(),
home: Home(),
));
}
}

View File

@ -0,0 +1,26 @@
import "package:rxdart/rxdart.dart";
class BottomBusBloc {
final _bottomBarBus = PublishSubject<Map<String, String>>();
Map<String, String> _lastMessage = {"state": "no_connection"};
BottomBusBloc() {
_bottomBarBus.listen((data) => print(data));
}
Observable<Map<String, String>> get bus => _bottomBarBus.stream;
Map<String, String> get lastMessage => _lastMessage;
publish(Map<String, String> message) async {
print(message);
_lastMessage = message;
_bottomBarBus.sink.add(message);
}
dispose() {
_bottomBarBus.close();
}
}
// global instance for access throughout the app
final bottomBusBloc = BottomBusBloc();

View File

@ -1,17 +1,17 @@
import "package:rxdart/rxdart.dart";
import "../resources/repository.dart";
import "../resources/contact_api_provider.dart";
import "../models/user_model.dart";
// TODO: SHOULD BE A INHERITED SCOPED BLOC Widget
class ContactBloc {
final _repository = Repository();
final _provider = ContactApiProvider();
final _contactsFetcher = PublishSubject<List<User>>();
Observable<List<User>> get contacts => _contactsFetcher.stream;
fetchContacts() async {
List<User> contactList = await _repository.fetchContacts();
List<User> contactList = await _provider.fetchContacts();
_contactsFetcher.sink.add(contactList);
}

View File

@ -1,19 +1,18 @@
import "package:rxdart/rxdart.dart";
import "../resources/repository.dart";
import "../resources/conversation_api_provider.dart";
import "../models/user_model.dart";
import "../models/conversation_model.dart";
class ConversationsBloc {
final _repository = Repository();
final _provider = ConversationApiProvider();
final _conversationsFetcher = PublishSubject<List<Conversation>>();
Observable<List<Conversation>> get conversations =>
_conversationsFetcher.stream;
fetchConversations() async {
List<Conversation> conversationList =
await _repository.fetchConversations();
List<Conversation> conversationList = await _provider.fetchConversations();
_conversationsFetcher.sink.add(conversationList);
}
@ -24,7 +23,7 @@ class ConversationsBloc {
class ConversationMembersBloc {
final String conversationId;
final _repository = Repository();
final _provider = ConversationApiProvider();
final _membersFetcher = PublishSubject<List<User>>();
ConversationMembersBloc(this.conversationId);
@ -33,7 +32,7 @@ class ConversationMembersBloc {
fetchMembers() async {
List<User> memberList =
await _repository.fetchConversationMembers(conversationId);
await _provider.fetchConversationMembers(conversationId);
_membersFetcher.sink.add(memberList);
}

View File

@ -1,43 +0,0 @@
import "package:rxdart/rxdart.dart";
import "package:flutter_webrtc/webrtc.dart";
import "../resources/conversation_api_provider.dart";
import "../models/user_model.dart";
import "../services/peer_manager.dart";
import "../../settings.dart";
class VoiceConnection {
final PeerManager _peerManager = PeerManager(globalUserId, "2");
final _conversationApiProvider = ConversationApiProvider();
final _bottomBarBus = PublishSubject<Map<String, dynamic>>();
VoiceConnection() {
_bottomBarBus.listen((data) => print(data));
_peerManager.initialize();
}
Observable<Map<String, dynamic>> get bus => _bottomBarBus.stream;
publish(Map<String, dynamic> message) async {
_bottomBarBus.sink.add(message);
}
join(String conversationId) async {
List<User> users =
await _conversationApiProvider.fetchConversationMembers(conversationId);
// Add the users to the streams
users.forEach((user) {
_peerManager.addPeer(user.id);
});
List<MediaStream> connectedStreams = _peerManager.streams;
}
dispose() {
_bottomBarBus.close();
}
}
// global instance for access throughout the app
final voiceConnection = VoiceConnection();

View File

@ -1,20 +0,0 @@
import "dart:async";
import "contact_api_provider.dart";
import "conversation_api_provider.dart";
import "../models/user_model.dart";
import "../models/conversation_model.dart";
class Repository {
final contactApiProvider = ContactApiProvider();
final conversationApiProvider = ConversationApiProvider();
Future<List<User>> fetchContacts() => contactApiProvider.fetchContacts();
Future<List<Conversation>> fetchConversations() =>
conversationApiProvider.fetchConversations();
Future<List<User>> fetchConversationMembers(String id) =>
conversationApiProvider.fetchConversationMembers(id);
}

View File

@ -0,0 +1,60 @@
import "package:flutter/material.dart";
import "../../blocs/bottom_bus_bloc.dart";
import "widgets/conversation_inactive_view.dart";
import "widgets/conversation_active_view.dart";
class BottomBar extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _BottomBarState();
}
}
class _BottomBarState extends State<BottomBar> {
final bloc = bottomBusBloc;
@override
void dispose() {
// bloc.dispose();
super.dispose();
}
Widget getWidgetForState(Map<String, String> message) {
if (message["state"] == "no_connection") {
return ConversationInactiveView();
} else if (message["state"] == "connection") {
return ConversationActiveView(conversationName: message["title"]);
} else {
return ConversationInactiveView();
}
}
@override
Widget build(BuildContext context) {
final double bottomPadding = MediaQuery.of(context).padding.bottom;
return Material(
type: MaterialType.canvas,
elevation: 10.0,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0), topRight: Radius.circular(40.0)),
child: Container(
padding: EdgeInsets.only(
top: 20.0,
left: 20.0,
right: 20.0,
bottom: 30.0 + bottomPadding),
child: StreamBuilder(
stream: bloc.bus,
builder:
(context, AsyncSnapshot<Map<String, String>> snapshot) {
if (snapshot.hasData) {
return getWidgetForState(snapshot.data);
} else {
final message = bloc.lastMessage;
return getWidgetForState(message);
}
})));
}
}

View File

@ -0,0 +1,66 @@
import "package:flutter/material.dart";
import "../../widgets/user_avatar.dart";
import "../../../models/user_model.dart";
import "../../../blocs/bottom_bus_bloc.dart";
class ConversationActiveView extends StatelessWidget {
final String conversationName;
final bus = bottomBusBloc;
ConversationActiveView({@required this.conversationName});
@override
Widget build(BuildContext context) {
return Container(
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 22.0,
height: 22.0,
decoration: BoxDecoration(
color: Theme.of(context).indicatorColor,
shape: BoxShape.circle)),
Container(
margin: EdgeInsets.only(left: 10.0),
child: Text(conversationName,
style: Theme.of(context)
.textTheme
.display1
.copyWith(color: Theme.of(context).accentColor))),
Spacer(),
IconButton(
color: Theme.of(context).accentColor,
icon: Icon(Icons.info),
onPressed: () {
print("Pressed info");
}),
IconButton(
color: Theme.of(context).accentColor,
icon: Icon(Icons.close),
onPressed: () {
// Call method to close connection
bus.publish({"state": "no_connection"});
print("Pressed close");
}),
]),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
UserAvatar(
padding: EdgeInsets.only(right: 5.0),
user: User("1", "Isaac", "Tay", "+65 91043593")),
UserAvatar(
padding: EdgeInsets.only(right: 5.0),
user: User("1", "Isaac", "Tay", "+65 91043593")),
UserAvatar(
padding: EdgeInsets.only(right: 5.0),
user: User("1", "Rui", "Juidfsdf", "+65 91043593"))
]),
]));
}
}

View File

@ -0,0 +1,25 @@
import "package:flutter/material.dart";
import "../../widgets/user_avatar.dart";
import "../../../models/user_model.dart";
class ConversationInactiveView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
UserAvatar(
padding: EdgeInsets.only(right: 5.0),
user: User("1", "Isaac", "Tay", "+65 91043593")),
UserAvatar(
padding: EdgeInsets.only(right: 5.0),
user: User("1", "Isaac", "Tay", "+65 91043593")),
UserAvatar(
padding: EdgeInsets.only(right: 5.0),
user: User("1", "Isaac", "Tay", "+65 91043593"))
]));
}
}

View File

@ -3,7 +3,7 @@ import "package:flutter/material.dart";
import "./widgets/top_bar.dart";
import "./widgets/conversation_list.dart";
import "./widgets/contact_list.dart";
import "./widgets/bottom_bar.dart";
import "../bottom_bar/bottom_bar.dart";
class Home extends StatefulWidget {
@override

View File

@ -1,79 +0,0 @@
import "package:flutter/material.dart";
import 'package:flutter_webrtc/webrtc.dart';
import "../../../blocs/voice_connection_bloc.dart";
class BottomBar extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _BottomBarState();
}
}
class _BottomBarState extends State<BottomBar> {
final double barHeight = 80.0;
final _renderer = new RTCVideoRenderer();
@override
void initState() {
super.initState();
initRenderers();
}
@override
void dispose() {
super.dispose();
}
initRenderers() async {
await _renderer.initialize();
}
@override
Widget build(BuildContext context) {
return Material(
type: MaterialType.canvas,
elevation: 10.0,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0), topRight: Radius.circular(40.0)),
child: Container(
padding: EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 20.0),
width: 22.0,
height: 22.0,
decoration: BoxDecoration(
color: Theme.of(context).indicatorColor,
shape: BoxShape.circle)),
Text("Family Chat",
style: Theme.of(context)
.textTheme
.display1
.copyWith(color: Theme.of(context).accentColor)),
Spacer(),
Container(
child: RTCVideoView(_renderer),
width: 0,
height: 0,
),
IconButton(
color: Theme.of(context).accentColor,
icon: Icon(Icons.info),
onPressed: () {
print("Pressed");
}),
IconButton(
color: Theme.of(context).accentColor,
icon: Icon(Icons.close),
onPressed: () {
print("Pressed close");
voiceConnection
.join("c-6f2ba396fb53961ff8a6ba9c5d286a25");
}),
])));
}
}

View File

@ -3,6 +3,7 @@ import "package:flutter/material.dart";
import "../../../models/user_model.dart";
import "../../../models/conversation_model.dart";
import "../../../blocs/conversation_bloc.dart";
import "../../../blocs/bottom_bus_bloc.dart";
import "../../widgets/user_avatar.dart";
@ -19,6 +20,7 @@ class ConversationItem extends StatefulWidget {
class _ConversationItemState extends State<ConversationItem> {
final bloc;
final Conversation conversation;
final bus = bottomBusBloc;
_ConversationItemState({@required this.conversation})
: bloc = ConversationMembersBloc(conversation.id);
@ -39,7 +41,8 @@ class _ConversationItemState extends State<ConversationItem> {
Widget build(BuildContext context) {
return ListTile(
isThreeLine: true,
onTap: () => {},
onTap: () =>
bus.publish({"state": "connection", "title": conversation.title}),
contentPadding:
EdgeInsets.only(top: 0.0, left: 20.0, right: 20.0, bottom: 0.0),
title: Text(conversation.title, style: Theme.of(context).textTheme.title),

View File

@ -11,12 +11,12 @@ dependencies:
json_annotation: ^2.0.0
rxdart: ^0.20.0
http: ^0.12.0+1
eventsource: ^0.2.1
flutter_webrtc: ^0.1.0
pin_code_text_field: ^1.1.3
flutter_svg: ^0.10.3
shared_preferences: ^0.5.1
sqflite: ^1.1.0
eventsource:
path: ./utility_packages/dart-eventsource
dev_dependencies:
flutter_test:

@ -0,0 +1 @@
Subproject commit 5ab96112ea37e1120e0ee815c3dfa38843b1a34d