diff --git a/assets/images/drawer-backbroud.png b/assets/images/drawer-backbroud.png new file mode 100644 index 00000000..163bb874 Binary files /dev/null and b/assets/images/drawer-backbroud.png differ diff --git a/assets/images/drawer-icon.png b/assets/images/drawer-icon.png new file mode 100644 index 00000000..796dce96 Binary files /dev/null and b/assets/images/drawer-icon.png differ diff --git a/lib/pages/home/bus/bus_reserve_page.dart b/lib/pages/home/bus/bus_reserve_page.dart index 0e2b4895..40e005fa 100644 --- a/lib/pages/home/bus/bus_reserve_page.dart +++ b/lib/pages/home/bus/bus_reserve_page.dart @@ -273,10 +273,12 @@ class BusReservePageState extends State break; case DioErrorType.DEFAULT: if (dioError.message.contains("HttpException")) { - setState(() { - state = BusReserveState.error; - Utils.showToast(local.busFailInfinity); - }); + if (mounted) { + setState(() { + state = BusReserveState.error; + Utils.showToast(local.busFailInfinity); + }); + } } break; case DioErrorType.CANCEL: diff --git a/lib/pages/home/bus_page.dart b/lib/pages/home/bus_page.dart index 7ab508fa..80218de2 100644 --- a/lib/pages/home/bus_page.dart +++ b/lib/pages/home/bus_page.dart @@ -8,12 +8,18 @@ import 'package:nkust_ap/pages/page.dart'; import 'package:nkust_ap/utils/app_localizations.dart'; class BusPageRoute extends MaterialPageRoute { - BusPageRoute() : super(builder: (BuildContext context) => new BusPage()); + BusPageRoute({this.initIndex = 0}) + : super( + builder: (BuildContext context) => + new BusPage(initIndex: initIndex)); + + final int initIndex; @override Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { - return new FadeTransition(opacity: animation, child: new BusPage()); + return new FadeTransition( + opacity: animation, child: new BusPage(initIndex: initIndex)); } } @@ -23,14 +29,17 @@ class BusPage extends StatefulWidget { new BusReservePage(), new BusReservationsPage() ]; + final int initIndex; + + BusPage({this.initIndex = 0}); @override - BusPageState createState() => new BusPageState(_children); + BusPageState createState() => new BusPageState(_children, initIndex); } -class BusPageState extends State - with SingleTickerProviderStateMixin { +class BusPageState extends State with SingleTickerProviderStateMixin { final List _children; + final int initIndex; int _currentIndex = 0; List _title; @@ -38,12 +47,14 @@ class BusPageState extends State TabController controller; - BusPageState(this._children); + BusPageState(this._children, this.initIndex) { + _currentIndex = initIndex; + } @override void initState() { super.initState(); - controller = TabController(length: 2, vsync: this); + controller = TabController(length: 2, initialIndex: initIndex, vsync: this); } @override @@ -63,7 +74,10 @@ class BusPageState extends State title: new Text(_title[_currentIndex]), backgroundColor: Resource.Colors.blue, ), - body: TabBarView(children: _children,controller: controller,physics: new NeverScrollableScrollPhysics()), + body: TabBarView( + children: _children, + controller: controller, + physics: new NeverScrollableScrollPhysics()), bottomNavigationBar: new BottomNavigationBar( currentIndex: _currentIndex, onTap: onTabTapped, diff --git a/lib/pages/home/score_page.dart b/lib/pages/home/score_page.dart index e9417722..7a96aaab 100644 --- a/lib/pages/home/score_page.dart +++ b/lib/pages/home/score_page.dart @@ -88,7 +88,7 @@ class ScorePageState extends State Widget _scoreTextBorder(String text, bool isTitle) { return Container( width: double.maxFinite, - padding: EdgeInsets.symmetric(vertical:2.0,horizontal: 4.0), + padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 4.0), alignment: Alignment.center, child: Text( text ?? "", @@ -310,22 +310,24 @@ class ScorePageState extends State } }); }).catchError((e) { - assert(e is DioError); - DioError dioError = e as DioError; - switch (dioError.type) { - case DioErrorType.RESPONSE: - Utils.showToast(AppLocalizations.of(context).tokenExpiredContent); - Navigator.popUntil( - context, ModalRoute.withName(Navigator.defaultRouteName)); - break; - case DioErrorType.CANCEL: - break; - default: - setState(() { - state = ScoreState.error; - Utils.handleDioError(dioError, local); - }); - break; + if (e is DioError) { + switch (e.type) { + case DioErrorType.RESPONSE: + Utils.showToast(AppLocalizations.of(context).tokenExpiredContent); + Navigator.popUntil( + context, ModalRoute.withName(Navigator.defaultRouteName)); + break; + case DioErrorType.CANCEL: + break; + default: + setState(() { + state = ScoreState.error; + Utils.handleDioError(e, local); + }); + break; + } + } else { + throw e; } }); } else { diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 4cfbbbf0..e705191f 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -98,6 +98,8 @@ class LoginPageState extends State onTap: () => _onChanged(!isRememberPassword), ), RaisedButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(24.0))), padding: EdgeInsets.all(12.0), onPressed: _login, color: Colors.grey[300], diff --git a/lib/utils/app_localizations.dart b/lib/utils/app_localizations.dart index 31bc4655..d1ad403e 100644 --- a/lib/utils/app_localizations.dart +++ b/lib/utils/app_localizations.dart @@ -409,7 +409,7 @@ class AppLocalizations { 'course': '學期課表', 'score': '學期成績', 'leave': '缺曠系統', - 'bus': '校車系統', + 'bus': '校車系統(建工/燕巢)', 'simcourse': '模擬選課', 'school_info': '校園資訊', 'notifications': '最新消息', @@ -728,6 +728,8 @@ class AppLocalizations { String get reserving => _vocabularies['reserving']; String get canceling => _vocabularies['canceling']; + + String get logout => _vocabularies['logout']; } class AppLocalizationsDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/drawer_body.dart b/lib/widgets/drawer_body.dart index 580a4adb..20b36feb 100644 --- a/lib/widgets/drawer_body.dart +++ b/lib/widgets/drawer_body.dart @@ -23,6 +23,11 @@ class DrawerBodyState extends State { SharedPreferences prefs; bool displayPicture = true; + AppLocalizations app; + + bool isStudyExpanded = false; + bool isBusExpanded = false; + @override void initState() { super.initState(); @@ -36,103 +41,158 @@ class DrawerBodyState extends State { super.dispose(); } + _defaultStyle() => TextStyle(color: Resource.Colors.grey, fontSize: 16.0); + @override Widget build(BuildContext context) { + app = AppLocalizations.of(context); return Drawer( - semanticLabel: "測試", - child: Column( - children: [ - Container( - decoration: new BoxDecoration( - image: new DecorationImage( - image: new AssetImage("assets/images/kuasap3.png"), - fit: BoxFit.fill, - ), - ), - width: double.infinity, - child: Container( - padding: EdgeInsets.all(20.0), - child: Flex( - direction: Axis.vertical, - crossAxisAlignment: CrossAxisAlignment.start, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + color: Color(0xff0071FF), + width: double.infinity, + child: Stack( children: [ - SizedBox(height: 40.0), - pictureUrl != "" && displayPicture - ? Container( - width: 72.0, - height: 72.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - image: new DecorationImage( - fit: BoxFit.fill, - image: NetworkImage(pictureUrl), - ), - ), + Container( + width: double.infinity, + decoration: new BoxDecoration( + image: new DecorationImage( + image: new AssetImage( + "assets/images/drawer-backbroud.png"), + fit: BoxFit.fitWidth, + alignment: Alignment.bottomCenter), + ), + padding: EdgeInsets.all(20.0), + child: Flex( + direction: Axis.vertical, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 40.0), + pictureUrl != "" && displayPicture + ? Container( + width: 72.0, + height: 72.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: new DecorationImage( + fit: BoxFit.fill, + image: NetworkImage(pictureUrl), + ), + ), + ) + : Container( + width: 72.0, + height: 72.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + ), + child: Icon( + Icons.account_circle, + color: Colors.white, + size: 72.0, + ), + ), + SizedBox(height: 16.0), + Text( + userInfo == null + ? "" + : "${userInfo.nameCht}\n" + "${userInfo.id}", + style: TextStyle(color: Colors.white), ) - : Container( - width: 72.0, - height: 72.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - ), - child: Icon( - Icons.account_circle, - color: Colors.white, - size: 72.0, - ), - ), - SizedBox(height: 16.0), - Text( - userInfo == null - ? "" - : "${userInfo.nameCht}\n" - "${userInfo.id}", - style: TextStyle(color: Colors.white), - ) + ], + ), + ), + Positioned( + bottom: 20.0, + right: 20.0, + child: Container( + child: Image.asset( + "assets/images/drawer-icon.png", + width: 90.0, + ), + ), + ), ], ), ), - ), - _item(Icons.class_, AppLocalizations.of(context).course, - CoursePageRoute()), - _item(Icons.assignment, AppLocalizations.of(context).score, - ScorePageRoute()), - _item(Icons.directions_bus, AppLocalizations.of(context).bus, - BusPageRoute()), - _item(Icons.info, AppLocalizations.of(context).schoolInfo, - SchoolInfoPageRoute()), - _item(Icons.face, AppLocalizations.of(context).about, - AboutUsPageRoute()), - _item(Icons.settings, AppLocalizations.of(context).settings, - SettingPageRoute()), - ], + ExpansionTile( + onExpansionChanged: (bool) { + setState(() { + isStudyExpanded = bool; + }); + }, + leading: Icon( + Icons.class_, + color: isStudyExpanded + ? Resource.Colors.blue + : Resource.Colors.grey, + ), + title: Text(app.course, style: _defaultStyle()), + children: [ + _subItem(Icons.class_, app.course, CoursePageRoute()), + _subItem(Icons.assignment, app.score, ScorePageRoute()), + ], + ), + ExpansionTile( + onExpansionChanged: (bool) { + setState(() { + isBusExpanded = bool; + }); + }, + leading: Icon( + Icons.directions_bus, + color: + isBusExpanded ? Resource.Colors.blue : Resource.Colors.grey, + ), + title: Text(app.bus, style: _defaultStyle()), + children: [ + _subItem(Icons.date_range, app.busReserve, + BusPageRoute(initIndex: 0)), + _subItem(Icons.assignment, app.busReservations, + BusPageRoute(initIndex: 1)), + ], + ), + _item(Icons.info, app.schoolInfo, SchoolInfoPageRoute()), + _item(Icons.face, app.about, AboutUsPageRoute()), + _item(Icons.settings, app.settings, SettingPageRoute()), + ListTile( + leading: Icon( + Icons.power_settings_new, + color: Resource.Colors.grey, + ), + onTap: () { + Navigator.popUntil( + context, ModalRoute.withName(Navigator.defaultRouteName)); + }, + title: Text(app.logout, style: _defaultStyle()), + ), + ], + ), ), ); } - _item(IconData icon, String title, MaterialPageRoute route) => FlatButton( - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).push(route); - }, - child: Row( - children: [ - Container( - padding: EdgeInsets.all(18.0), - child: Icon( - icon, - size: 24.0, - color: Resource.Colors.grey, - ), - ), - SizedBox(width: 4.0), - Text( - title, - textAlign: TextAlign.center, - style: TextStyle(color: Resource.Colors.grey, fontSize: 16.0), - ) - ], - )); + _item(IconData icon, String title, MaterialPageRoute route) => ListTile( + leading: Icon(icon, color: Resource.Colors.grey), + title: Text(title, style: _defaultStyle()), + onTap: () { + Navigator.of(context).pop(); + Navigator.of(context).push(route); + }, + ); + + _subItem(IconData icon, String title, MaterialPageRoute route) => ListTile( + contentPadding: EdgeInsets.symmetric(horizontal: 72.0), + leading: Icon(icon, color: Resource.Colors.grey), + title: Text(title, style: _defaultStyle()), + onTap: () { + Navigator.of(context).pop(); + Navigator.of(context).push(route); + }, + ); _getUserPicture() { Helper.instance.getUsersPicture().then((url) { @@ -146,7 +206,7 @@ class DrawerBodyState extends State { DioError dioError = e as DioError; switch (dioError.type) { case DioErrorType.RESPONSE: - Utils.showToast(AppLocalizations.of(context).tokenExpiredContent); + Utils.showToast(app.tokenExpiredContent); Navigator.popUntil( context, ModalRoute.withName(LoginPage.routerName)); break; @@ -168,7 +228,7 @@ class DrawerBodyState extends State { DioError dioError = e as DioError; switch (dioError.type) { case DioErrorType.RESPONSE: - Utils.showToast(AppLocalizations.of(context).tokenExpiredContent); + Utils.showToast(app.tokenExpiredContent); Navigator.popUntil( context, ModalRoute.withName(LoginPage.routerName)); break; diff --git a/pubspec.yaml b/pubspec.yaml index 4b84a646..21729dbb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nkust_ap description: A new Flutter application. -version: 0.3.4+304 +version: 0.4.1+401 environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" @@ -48,6 +48,8 @@ flutter: - assets/images/ic_fb.png - assets/images/ic_github.png - assets/images/ic_email.png + - assets/images/drawer-backbroud.png + - assets/images/drawer-icon.png # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg