diff --git a/android/build.gradle b/android/build.gradle index 711e687d..f646430c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -10,7 +10,7 @@ buildscript { classpath 'io.fabric.tools:gradle:1.+' classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:3.1.2' + classpath 'com.google.gms:google-services:4.2.0' } } @@ -18,6 +18,9 @@ allprojects { repositories { google() jcenter() + maven { + url 'https://maven.google.com/' + } } } diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4a865813..5627f9fb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -241,6 +241,7 @@ "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework", "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", + "${BUILT_PRODUCTS_DIR}/package_info/package_info.framework", "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", ); @@ -251,6 +252,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", ); diff --git a/lib/config/constants.dart b/lib/config/constants.dart index 756d1097..16f9714a 100644 --- a/lib/config/constants.dart +++ b/lib/config/constants.dart @@ -1,4 +1,10 @@ class Constants { + static bool get isInDebugMode { + bool inDebugMode = false; + assert(inDebugMode = true); + return inDebugMode; + } + static const PREF_FIRST_ENTER_APP = "pref_first_enter_app"; static const PREF_REMEMBER_PASSWORD = "pref_remember_password"; static const PREF_USERNAME = "pref_username"; @@ -9,6 +15,4 @@ class Constants { static const PREF_VIBRATE_COURSE = "pref_vibrate_course"; static const SCHEDULE_DATA = "schedule_data"; - - static const APP_VERSION = "v0.3.1"; } diff --git a/lib/main.dart b/lib/main.dart index 5f5f8bc1..326ba6c9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:nkust_ap/config/constants.dart'; import 'package:nkust_ap/pages/page.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_analytics/observer.dart'; @@ -10,7 +11,7 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_crashlytics/flutter_crashlytics.dart'; void main() async { - bool isInDebugMode = false; + bool isInDebugMode = Constants.isInDebugMode; FlutterError.onError = (FlutterErrorDetails details) { if (isInDebugMode) { // In development mode simply print to console. diff --git a/lib/models/course_data.dart b/lib/models/course_data.dart index b1926ac0..027e7e38 100644 --- a/lib/models/course_data.dart +++ b/lib/models/course_data.dart @@ -17,8 +17,7 @@ class CourseData { ); } - Map toJson() => - { + Map toJson() => { 'status': status, 'messages': messages, 'coursetables': courseTables, @@ -73,8 +72,7 @@ class CourseTables { int maxTimeCodes = 10; for (int i = 0; i < weeks.length; i++) { if (getCourseList(weeks[i]) != null) - for (var data - in getCourseList(weeks[i])) { + for (var data in getCourseList(weeks[i])) { for (int j = 0; j < timeCode.length; j++) { if (timeCode[j] == data.section) { if ((j + 1) > maxTimeCodes) maxTimeCodes = (j + 1); @@ -87,22 +85,18 @@ class CourseTables { static CourseTables fromJson(Map json) { return CourseTables( - sunday: Course.toList(json['Sunday']), - tuesday: Course.toList(json['Tuesday']), - friday: Course.toList(json['Friday']), - saturday: Course.toList(json['Saturday']), - thursday: Course.toList(json['Thursday']), - wednesday: Course.toList(json['Wednesday']), - monday: Course.toList(json['Monday']), - timeCode: List < String - > - .from(json['timecode'] ?? - [ - ]),); + sunday: Course.toList(json['Sunday']), + tuesday: Course.toList(json['Tuesday']), + friday: Course.toList(json['Friday']), + saturday: Course.toList(json['Saturday']), + thursday: Course.toList(json['Thursday']), + wednesday: Course.toList(json['Wednesday']), + monday: Course.toList(json['Monday']), + timeCode: List.from(json['timecode'] ?? []), + ); } - Map toJson() => - { + Map toJson() => { 'Sunday': sunday, 'Tuesday': tuesday, 'Friday': friday, @@ -137,26 +131,36 @@ class Course { static List toList(List jsonArray) { List list = []; - for (var item in (jsonArray ?? [])) - list.add(Course.fromJson(item)); + for (var item in (jsonArray ?? [])) list.add(Course.fromJson(item)); return list; } static Course fromJson(Map json) { + print(json['instructors']); return Course( - title: json['title'], - startTime: json['date']["start_time"], - endTime: json['date']["end_time"], - weekday: json['date']["weekday"], - section: json['date']["section"], - building: json['location']["building"], - room: json['location']["room"], - instructors: List.from(json['instructors']),); + title: json['title'], + startTime: json['date']["start_time"], + endTime: json['date']["end_time"], + weekday: json['date']["weekday"], + section: json['date']["section"], + building: json['location']["building"], + room: json['location']["room"], + instructors: List.from(json['instructors']) + ); + } + + String getInstructors() { + String text = ""; + if(instructors.length>0){ + text += instructors[0]; + for(var i = 1 ; i < instructors.length ; i++) + text += ",${instructors[i]}"; + } + return text; } - Map toJson() => - { + Map toJson() => { 'title': title, 'instructors': instructors, }; -} \ No newline at end of file +} diff --git a/lib/pages/home/about/about_us_page.dart b/lib/pages/home/about/about_us_page.dart index 31c6c4cb..db586046 100644 --- a/lib/pages/home/about/about_us_page.dart +++ b/lib/pages/home/about/about_us_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:nkust_ap/res/resource.dart' as Resource; import 'package:nkust_ap/api/helper.dart'; @@ -55,7 +57,8 @@ class AboutUsPageState extends State IconButton( icon: Icon(Icons.code), onPressed: () { - Navigator.of(context).pushNamed(OpenSourcePage.routerName); + Navigator.of(context) + .pushNamed(OpenSourcePage.routerName); }) ], backgroundColor: Resource.Colors.blue, @@ -116,14 +119,26 @@ class AboutUsPageState extends State IconButton( icon: Image.asset("assets/images/ic_fb.png"), onPressed: () { - Utils.launchUrl('https://www.facebook.com/NKUST.ITC/'); + if (Platform.isAndroid) + Utils.launchUrl('fb://page/735951703168873') + .catchError((onError) => Utils.launchUrl( + 'https://www.facebook.com/NKUST.ITC/')); + else + Utils.launchUrl( + 'https://www.facebook.com/NKUST.ITC/'); }, iconSize: 48.0, ), IconButton( icon: Image.asset("assets/images/ic_github.png"), onPressed: () { - Utils.launchUrl('https://github.com/NKUST-ITC'); + if (Platform.isAndroid) + Utils.launchUrl( + 'github://organization/NKUST-ITC') + .catchError((onError) => Utils.launchUrl( + 'https://github.com/NKUST-ITC')); + else + Utils.launchUrl('https://github.com/NKUST-ITC'); }, iconSize: 48.0, ), diff --git a/lib/pages/home/bus/bus_reservations_page.dart b/lib/pages/home/bus/bus_reservations_page.dart index 775d69f3..3a93940b 100644 --- a/lib/pages/home/bus/bus_reservations_page.dart +++ b/lib/pages/home/bus/bus_reservations_page.dart @@ -32,7 +32,10 @@ class BusReservationsPage extends StatefulWidget { } class BusReservationsPageState extends State - with SingleTickerProviderStateMixin { + with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + BusReservationsState state = BusReservationsState.loading; BusReservationsData busReservationsData; List busReservationWeights = []; diff --git a/lib/pages/home/bus/bus_reserve_page.dart b/lib/pages/home/bus/bus_reserve_page.dart index 125e344d..0e2b4895 100644 --- a/lib/pages/home/bus/bus_reserve_page.dart +++ b/lib/pages/home/bus/bus_reserve_page.dart @@ -32,7 +32,10 @@ class BusReservePage extends StatefulWidget { } class BusReservePageState extends State - with SingleTickerProviderStateMixin { + with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + BusReserveState state = BusReserveState.loading; BusData busData; List busTimeWeights = []; diff --git a/lib/pages/home/bus_page.dart b/lib/pages/home/bus_page.dart index 60b013f6..7ab508fa 100644 --- a/lib/pages/home/bus_page.dart +++ b/lib/pages/home/bus_page.dart @@ -19,29 +19,37 @@ class BusPageRoute extends MaterialPageRoute { class BusPage extends StatefulWidget { static const String routerName = "/bus"; + final List _children = [ + new BusReservePage(), + new BusReservationsPage() + ]; @override - BusPageState createState() => new BusPageState(); + BusPageState createState() => new BusPageState(_children); } -class BusPageState extends State with SingleTickerProviderStateMixin { +class BusPageState extends State + with SingleTickerProviderStateMixin { + final List _children; int _currentIndex = 0; - final List _children = [ - new BusReservePage(), - new BusReservationsPage() - ]; List _title; AppLocalizations local; + TabController controller; + + BusPageState(this._children); + @override void initState() { super.initState(); + controller = TabController(length: 2, vsync: this); } @override void dispose() { super.dispose(); + controller.dispose(); } @override @@ -55,7 +63,7 @@ class BusPageState extends State with SingleTickerProviderStateMixin { title: new Text(_title[_currentIndex]), backgroundColor: Resource.Colors.blue, ), - body: _children[_currentIndex], + body: TabBarView(children: _children,controller: controller,physics: new NeverScrollableScrollPhysics()), bottomNavigationBar: new BottomNavigationBar( currentIndex: _currentIndex, onTap: onTabTapped, @@ -77,6 +85,7 @@ class BusPageState extends State with SingleTickerProviderStateMixin { void onTabTapped(int index) { setState(() { _currentIndex = index; + controller.animateTo(_currentIndex); }); } } diff --git a/lib/pages/home/course_page.dart b/lib/pages/home/course_page.dart index 622a6ee6..463c1600 100644 --- a/lib/pages/home/course_page.dart +++ b/lib/pages/home/course_page.dart @@ -100,7 +100,7 @@ class CoursePageState extends State Widget _courseBorder(Course course) { String content = "${local.courseDialogName}:${course.title}\n" - "${local.courseDialogProfessor}:${course.instructors[0] ?? ""}\n" + "${local.courseDialogProfessor}:${course.getInstructors()}\n" "${local.courseDialogLocation}:${course.building}${course.room}\n" "${local.courseDialogTime}:${course.startTime}-${course.endTime}"; return new Container( @@ -112,7 +112,10 @@ class CoursePageState extends State showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(local.courseDialogTitle), + title: Text( + local.courseDialogTitle, + style: TextStyle(color: Resource.Colors.blue), + ), content: Text(content), actions: [ FlatButton( diff --git a/lib/pages/home/score_page.dart b/lib/pages/home/score_page.dart index eab0bd99..e9417722 100644 --- a/lib/pages/home/score_page.dart +++ b/lib/pages/home/score_page.dart @@ -27,7 +27,7 @@ class ScorePage extends StatefulWidget { class ScorePageState extends State with SingleTickerProviderStateMixin { - List scoreWeightList = []; + List scoreWeightList = []; var selectSemesterIndex; Semester selectSemester; @@ -58,15 +58,12 @@ class ScorePageState extends State return TextStyle(color: Colors.black, fontSize: 14.0); } - _scoreTitle() => Container( - width: double.infinity, - child: Row( - children: [ - Expanded(child: _scoreTextBorder(local.subject, false, true)), - Expanded(child: _scoreTextBorder(local.midtermScore, false, true)), - Expanded(child: _scoreTextBorder(local.finalScore, true, true)), - ], - ), + _scoreTitle() => TableRow( + children: [ + _scoreTextBorder(local.subject, true), + _scoreTextBorder(local.midtermScore, true), + _scoreTextBorder(local.finalScore, true), + ], ); Widget _textBorder(String text, bool isTop) { @@ -88,17 +85,10 @@ class ScorePageState extends State ); } - Widget _scoreTextBorder(String text, bool isEnd, bool isTitle) { + Widget _scoreTextBorder(String text, bool isTitle) { return Container( width: double.maxFinite, - padding: EdgeInsets.symmetric(vertical: 2.0), - decoration: new BoxDecoration( - border: new Border( - right: isEnd - ? BorderSide.none - : BorderSide(color: Colors.grey, width: 0.5), - ), - ), + padding: EdgeInsets.symmetric(vertical:2.0,horizontal: 4.0), alignment: Alignment.center, child: Text( text ?? "", @@ -108,22 +98,12 @@ class ScorePageState extends State ); } - Widget _scoreBorder(Score score) { - return Container( - width: double.infinity, - decoration: new BoxDecoration( - border: new Border( - top: BorderSide(color: Colors.grey, width: 0.5), - ), - ), - child: Row( - children: [ - Expanded(child: _scoreTextBorder(score.title, false, false)), - Expanded(child: _scoreTextBorder(score.middleScore, false, false)), - Expanded(child: _scoreTextBorder(score.finalScore, true, false)), - ], - ), - ); + _scoreBorder(Score score) { + return TableRow(children: [ + _scoreTextBorder(score.title, false), + _scoreTextBorder(score.middleScore, false), + _scoreTextBorder(score.finalScore, false) + ]); } @override @@ -219,10 +199,12 @@ class ScorePageState extends State 10.0, ), ), - border: new Border.all(color: Colors.grey, width: 1.0), + border: new Border.all(color: Colors.grey, width: 1.5), ), - child: Flex( - direction: Axis.vertical, + child: Table( + defaultVerticalAlignment: TableCellVerticalAlignment.middle, + border: TableBorder.symmetric( + inside: BorderSide(color: Colors.grey)), children: scoreWeightList, ), ), @@ -236,7 +218,7 @@ class ScorePageState extends State 10.0, ), ), - border: new Border.all(color: Colors.grey, width: 1.0), + border: new Border.all(color: Colors.grey, width: 1.5), ), child: Column( children: [ diff --git a/lib/pages/home/setting_page.dart b/lib/pages/home/setting_page.dart index 6af80555..1ab76b2c 100644 --- a/lib/pages/home/setting_page.dart +++ b/lib/pages/home/setting_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:nkust_ap/res/resource.dart' as Resource; import 'package:nkust_ap/api/helper.dart'; @@ -8,6 +10,7 @@ import 'package:nkust_ap/utils/app_localizations.dart'; import 'package:nkust_ap/utils/utils.dart'; import 'package:nkust_ap/config/constants.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:package_info/package_info.dart'; class SettingPageRoute extends MaterialPageRoute { SettingPageRoute() @@ -38,6 +41,8 @@ class SettingPageState extends State AppLocalizations local; + String appVersion = "1.0.0"; + @override void initState() { super.initState(); @@ -96,13 +101,18 @@ class SettingPageState extends State ), _titleItem(local.otherInfo), _item(local.feedback, local.feedbackViaFacebook, () { - Utils.launchUrl('https://www.facebook.com/954175941266264/'); + if (Platform.isAndroid) + Utils.launchUrl('fb://messaging/954175941266264').catchError( + (onError) => Utils.launchUrl( + 'https://www.facebook.com/954175941266264/')); + else + Utils.launchUrl('https://www.facebook.com/954175941266264/'); }), _item(local.donateTitle, local.donateContent, () { Utils.launchUrl( "https://payment.ecpay.com.tw/QuickCollect/PayData?mLM7iy8RpUGk%2fyBotSDMdvI0qGI5ToToqBW%2bOQbOE80%3d"); }), - _item(local.appVersion, Constants.APP_VERSION, () {}), + _item(local.appVersion, "v$appVersion", () {}), ]), ), ); @@ -141,6 +151,8 @@ class SettingPageState extends State _getPreference() async { prefs = await SharedPreferences.getInstance(); + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + appVersion = packageInfo.version; displayPicture = prefs.getBool(Constants.PREF_DISPLAY_PICTURE) ?? true; setState(() {}); } diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index ff795d2e..4cfbbbf0 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -10,6 +10,7 @@ import 'package:nkust_ap/config/constants.dart'; import 'package:nkust_ap/api/helper.dart'; import 'package:nkust_ap/utils/app_localizations.dart'; import 'package:nkust_ap/widgets/checkbox_title.dart'; +import 'package:package_info/package_info.dart'; class LoginPage extends StatefulWidget { static const String routerName = "/login"; @@ -114,12 +115,13 @@ class LoginPageState extends State _showDialog() async { prefs = await SharedPreferences.getInstance(); + PackageInfo packageInfo = await PackageInfo.fromPlatform(); await Future.delayed(Duration(milliseconds: 50)); if (prefs.getBool(Constants.PREF_FIRST_ENTER_APP) ?? true) Utils.showDefaultDialog( context, AppLocalizations.of(context).updateNoteTitle, - "${Constants.APP_VERSION}\n" + "v${packageInfo.version}\n" "${AppLocalizations.of(context).updateNoteContent}", AppLocalizations.of(context).ok, () { prefs.setBool(Constants.PREF_FIRST_ENTER_APP, false); diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 7c95e3e5..1bcf6537 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -55,7 +55,7 @@ class Utils { )); } - static launchUrl(var url) async { + static Future launchUrl(var url) async { if (await canLaunch(url)) { await launch(url); } else { diff --git a/lib/widgets/drawer_body.dart b/lib/widgets/drawer_body.dart index 447b4fe5..580a4adb 100644 --- a/lib/widgets/drawer_body.dart +++ b/lib/widgets/drawer_body.dart @@ -136,9 +136,11 @@ class DrawerBodyState extends State { _getUserPicture() { Helper.instance.getUsersPicture().then((url) { - setState(() { - pictureUrl = url; - }); + if (this.mounted) { + setState(() { + pictureUrl = url; + }); + } }).catchError((e) { assert(e is DioError); DioError dioError = e as DioError; @@ -156,9 +158,11 @@ class DrawerBodyState extends State { _getUserInfo() { Helper.instance.getUsersInfo().then((response) { - setState(() { - userInfo = response; - }); + if (this.mounted) { + setState(() { + userInfo = response; + }); + } }).catchError((e) { assert(e is DioError); DioError dioError = e as DioError; diff --git a/pubspec.yaml b/pubspec.yaml index c204842d..4b84a646 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nkust_ap description: A new Flutter application. -version: 0.3.3+303 +version: 0.3.4+304 environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" @@ -13,8 +13,8 @@ dependencies: sdk: flutter shared_preferences: ^0.4.2 cupertino_icons: ^0.1.2 - dio: 1.0.4 - fluttertoast: ^2.0.9 + dio: 1.0.9 + fluttertoast: ^2.1.2 firebase_core: ^0.2.5+1 firebase_analytics: 1.0.4 firebase_remote_config: ^0.0.6+1 @@ -23,6 +23,7 @@ dependencies: url_launcher: ^4.0.1 carousel_slider: ^0.0.7 flutter_crashlytics: 0.1.1 + package_info: ^0.3.2 dev_dependencies: flutter_test: sdk: flutter