diff --git a/lib/src/ia_bloc.dart b/lib/src/ia_bloc.dart new file mode 100644 index 00000000..10189376 --- /dev/null +++ b/lib/src/ia_bloc.dart @@ -0,0 +1,27 @@ +import 'package:instiapp/src/api/apiclient.dart'; +import 'package:instiapp/src/api/model/mess.dart'; +import 'dart:collection'; +import 'package:rxdart/rxdart.dart'; +import 'package:http/io_client.dart'; +import 'package:jaguar_retrofit/jaguar_retrofit.dart'; + +class InstiAppBloc { + Stream> get hostels => _hostelsSubject.stream; + final _hostelsSubject = BehaviorSubject>(); + + final client = InstiAppApi(); + + var _hostels = []; + + InstiAppBloc() { + globalClient = IOClient(); + _updateHostels().then((_) { + _hostelsSubject.add(UnmodifiableListView(_hostels)); + }); + } + + Future _updateHostels() async { + final hostels = await client.getSortedHostelMess(); + _hostels = hostels; + } +} \ No newline at end of file diff --git a/lib/src/routes/homepage.dart b/lib/src/routes/homepage.dart index 14ae7dda..7dfa6482 100644 --- a/lib/src/routes/homepage.dart +++ b/lib/src/routes/homepage.dart @@ -1,13 +1,27 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:http/io_client.dart'; -import 'package:instiapp/src/api/apiclient.dart'; -import 'package:jaguar_retrofit/jaguar_retrofit.dart'; +import 'package:instiapp/src/ia_bloc.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:instiapp/src/api/model/mess.dart'; -import 'package:instiapp/src/json_parsing.dart'; + +import 'dart:collection'; + +class BlocProvider extends InheritedWidget { + final InstiAppBloc bloc; + + BlocProvider(this.bloc, {child}) : super(child: child); + + @override + bool updateShouldNotify(InheritedWidget oldWidget) { + return false; + } + + static BlocProvider of(BuildContext context) { + return context.inheritFromWidgetOfExactType(BlocProvider); + } +} class MyHomePage extends StatefulWidget { final String title = "InstiApp"; @@ -18,66 +32,94 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - final client = InstiAppApi(); - - int hostelIndex; - + int hostelIndex = 3; + InstiAppBloc _bloc; @override void initState() { super.initState(); - globalClient = IOClient(); - hostelIndex = 3; + _bloc = InstiAppBloc(); } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - leading: Padding( - padding: const EdgeInsets.only(left: 8.0), - child: ImageIcon(AssetImage('assets/lotus.png'), color: Colors.white,), - ), - title: Text("Mess", - style: Theme.of(context).textTheme.headline.copyWith( - fontFamily: "Bitter", color: Colors.white)), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(48.0), - child: Container( - color: Colors.white, - height: 48.0, - padding: EdgeInsets.only(left: 16.0), - alignment: Alignment.centerLeft, - child: DropdownButton( - hint: Text("Hostel"), - items: [ - DropdownMenuItem( - child: Text("H1"), - ), - ], - onChanged: (a) {}, + return BlocProvider( + _bloc, + child: Scaffold( + appBar: AppBar( + leading: Padding( + padding: const EdgeInsets.only(left: 8.0), + child: ImageIcon( + AssetImage('assets/lotus.png'), + color: Colors.white, + ), + ), + title: Text("Mess", + style: Theme.of(context) + .textTheme + .headline + .copyWith(fontFamily: "Bitter", color: Colors.white)), + bottom: PreferredSize( + preferredSize: const Size.fromHeight(48.0), + child: Container( + color: Colors.white, + height: 48.0, + padding: EdgeInsets.only(left: 16.0), + alignment: Alignment.centerLeft, + child: buildDropdownButton(), ), ), ), + body: StreamBuilder>( + stream: _bloc.hostels, + builder: (BuildContext context, + AsyncSnapshot> hostels) { + if (hostels.hasData) { + hostels.data[hostelIndex].mess.sort((h1, h2) => h1.compareTo(h2)); + return ListView( + children: hostels.data[hostelIndex].mess + .map(_buildSingleDayMess) + .toList(), + // children: [], + physics: BouncingScrollPhysics(), + ); + } else { + return Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).accentColor, + ), + ); + } + }, + ), ), - body: FutureBuilder>( - builder: (BuildContext context, AsyncSnapshot> hostels) { - if (hostels.hasData) { - return ListView( - children: (hostels.data[hostelIndex].mess - ..sort((h1, h2) => h1.compareTo(h2))) - .map(_buildSingleDayMess).toList(), - physics: BouncingScrollPhysics(), - ); - } else { - return Center( - child: CircularProgressIndicator( - backgroundColor: Theme.of(context).accentColor, - ), - ); - } - }, - future: client.getSortedHostelMess(), - ), + ); + } + + Widget buildDropdownButton() { + return StreamBuilder>( + stream: _bloc.hostels, + builder: (context, snapshot) { + if (snapshot.hasData) { + return DropdownButton( + value: hostelIndex, + items: snapshot.data + .asMap() + .entries + .map((entry) => DropdownMenuItem( + child: Text(entry.value.name), + value: entry.key, + )) + .toList(), + onChanged: (h) { + setState(() { + hostelIndex = h; + }); + }, + ); + } else { + return Center(child: CircularProgressIndicator()); + } + }, ); } diff --git a/lib/src/routes/loginpage.dart b/lib/src/routes/loginpage.dart index 8a913041..83c3f0dd 100644 --- a/lib/src/routes/loginpage.dart +++ b/lib/src/routes/loginpage.dart @@ -5,9 +5,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; import 'package:instiapp/src/api/apiclient.dart'; -import 'package:instiapp/src/api/model/user.dart'; - - const String api = "https://api.insti.app/api"; const String authority = "api.insti.app"; @@ -55,27 +52,28 @@ class _LoginPageState extends State { @override Widget build(BuildContext context) { return Material( - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Image( - color: Theme.of(context).accentColor, - image: AssetImage('assets/lotus.png'), - width: 250.0, - fit: BoxFit.scaleDown, - ), - CircularProgressIndicator( - backgroundColor: Theme.of(context).accentColor, - ), - Text( - "InstiApp", - style: Theme.of(context).textTheme.display1.copyWith( - fontFamily: "Bitter", color: Theme.of(context).accentColor), - ), - ], + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Image( + color: Theme.of(context).accentColor, + image: AssetImage('assets/lotus.png'), + width: 250.0, + fit: BoxFit.scaleDown, + ), + CircularProgressIndicator( + backgroundColor: Theme.of(context).accentColor, + ), + Text( + "InstiApp", + style: Theme.of(context).textTheme.display1.copyWith( + fontFamily: "Bitter", color: Theme.of(context).accentColor), + ), + ], + ), ), - )); + ); } Future startLoginPageServer() async { diff --git a/pubspec.yaml b/pubspec.yaml index aa208d6a..06a2afd5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: http: ^0.12.0 jaguar_retrofit: ^2.5.12 jaguar_serializer: ^2.2.4 + rxdart: ^0.19.0 dev_dependencies: flutter_test: diff --git a/test/mess_test.dart b/test/mess_test.dart index 27e467f7..fb92062d 100644 --- a/test/mess_test.dart +++ b/test/mess_test.dart @@ -17,7 +17,7 @@ void main() { final hostels = parseMess(messJsonString); expect(hostels[0].name, "Hostel 1"); expect(hostels[0].mess[0].day, 7); - }); + }, timeout: Timeout.parse("10s")); } const messJsonString = r"""