diff --git a/lib/main.dart b/lib/main.dart index 1e8fb5c8..aa63e407 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -32,7 +32,7 @@ void main() async { Preferences.getString(Constants.PREF_ICON_STYLE_CODE, AppIcon.OUTLINED); AppTheme.code = Preferences.getString(Constants.PREF_THEME_CODE, AppTheme.LIGHT); - if (kIsWeb) { + if (kIsWeb || Constants.isInDebugMode) { } else if (Platform.isIOS || Platform.isAndroid) { Crashlytics.instance.enableInDevMode = true; // Pass all uncaught errors from the framework to Crashlytics. diff --git a/lib/models/announcements_data.dart b/lib/models/announcements_data.dart index 928f7ffa..2ce8d8ca 100644 --- a/lib/models/announcements_data.dart +++ b/lib/models/announcements_data.dart @@ -33,6 +33,7 @@ class Announcements { int id; int nextId; int lastId; + int weight; String imgUrl; String url; String description; @@ -43,6 +44,7 @@ class Announcements { this.id, this.nextId, this.lastId, + this.weight, this.imgUrl, this.url, this.description, @@ -59,6 +61,7 @@ class Announcements { id: json["id"], nextId: json["nextId"], lastId: json["lastId"], + weight: json["weight"], imgUrl: json["imgUrl"], url: json["url"], description: json["description"], @@ -70,6 +73,7 @@ class Announcements { "id": id, "nextId": nextId, "lastId": lastId, + "weight": weight, "imgUrl": imgUrl, "url": url, "description": description, diff --git a/lib/models/semester_data.dart b/lib/models/semester_data.dart index 50f7e3d5..2e76575e 100644 --- a/lib/models/semester_data.dart +++ b/lib/models/semester_data.dart @@ -44,6 +44,8 @@ class Semester { String value; String text; + String get code => '$year$value'; + Semester({ this.year, this.value, diff --git a/lib/pages/home/bus/bus_reservations_page.dart b/lib/pages/home/bus/bus_reservations_page.dart index 7df2ff74..0fcc6735 100644 --- a/lib/pages/home/bus/bus_reservations_page.dart +++ b/lib/pages/home/bus/bus_reservations_page.dart @@ -12,7 +12,15 @@ import 'package:nkust_ap/widgets/hint_content.dart'; import 'package:nkust_ap/widgets/progress_dialog.dart'; import 'package:nkust_ap/widgets/yes_no_dialog.dart'; -enum _State { loading, finish, error, empty, offlineEmpty } +enum _State { + loading, + finish, + error, + empty, + campusNotSupport, + userNotSupport, + offlineEmpty, +} class BusReservationsPage extends StatefulWidget { static const String routerName = "/bus/reservations"; @@ -68,13 +76,31 @@ class BusReservationsPageState extends State ); } + String get errorText { + switch (state) { + case _State.error: + return app.clickToRetry; + case _State.empty: + return app.busEmpty; + case _State.campusNotSupport: + return app.campusNotSupport; + case _State.userNotSupport: + return app.userNotSupport; + default: + return ''; + } + } + Widget _body() { switch (state) { case _State.loading: - return Container( - child: CircularProgressIndicator(), alignment: Alignment.center); + return Center( + child: CircularProgressIndicator(), + ); case _State.error: case _State.empty: + case _State.campusNotSupport: + case _State.userNotSupport: return FlatButton( onPressed: () { _getBusReservations(); @@ -82,9 +108,7 @@ class BusReservationsPageState extends State }, child: HintContent( icon: AppIcon.assignment, - content: state == _State.error - ? app.clickToRetry - : app.busReservationEmpty, + content: errorText, ), ); case _State.offlineEmpty: @@ -231,12 +255,20 @@ class BusReservationsPageState extends State switch (e.type) { case DioErrorType.RESPONSE: if (e.response.statusCode == 401) { + setState(() { + state = _State.userNotSupport; + }); + } else if (e.response.statusCode == 403) { + setState(() { + state = _State.campusNotSupport; + }); + } else { setState(() { state = _State.error; }); - } else Utils.handleResponseError( context, 'getBusReservations', mounted, e); + } break; case DioErrorType.DEFAULT: if (e.message.contains("HttpException")) { diff --git a/lib/pages/home/bus/bus_reserve_page.dart b/lib/pages/home/bus/bus_reserve_page.dart index d47fe5a4..7d9e812f 100644 --- a/lib/pages/home/bus/bus_reserve_page.dart +++ b/lib/pages/home/bus/bus_reserve_page.dart @@ -13,7 +13,15 @@ import 'package:nkust_ap/widgets/hint_content.dart'; import 'package:nkust_ap/widgets/progress_dialog.dart'; import 'package:nkust_ap/widgets/yes_no_dialog.dart'; -enum _State { loading, finish, error, empty, offline } +enum _State { + loading, + finish, + error, + empty, + campusNotSupport, + userNotSupport, + offline +} enum Station { janGong, yanchao } class BusReservePage extends StatefulWidget { @@ -56,89 +64,92 @@ class BusReservePageState extends State super.build(context); app = AppLocalizations.of(context); return Scaffold( - body: OrientationBuilder(builder: (_, orientation) { - return NestedScrollView( - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverAppBar( - leading: Container(), - expandedHeight: orientation == Orientation.portrait - ? MediaQuery.of(context).size.height * 0.20 - : MediaQuery.of(context).size.width * 0.19, - floating: true, - backgroundColor: Colors.transparent, - flexibleSpace: FlexibleSpaceBar( - background: Column( - children: [ - Container( - color: Colors.transparent, - padding: EdgeInsets.symmetric( - horizontal: 16.0, vertical: 0.0), - child: Calendar( - isExpandable: false, - showTodayAction: false, - showCalendarPickerIcon: true, - showChevronsToChangeRange: true, - onDateSelected: (DateTime datetime) { - dateTime = datetime; - _getBusTimeTables(); - FA.logAction('date_select', 'click'); - }, - initialCalendarDateOverride: dateTime, - dayChildAspectRatio: - orientation == Orientation.portrait ? 1.5 : 3, - weekdays: app.weekdays, + body: OrientationBuilder( + builder: (_, orientation) { + return NestedScrollView( + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverAppBar( + leading: Container(), + expandedHeight: orientation == Orientation.portrait + ? MediaQuery.of(context).size.height * 0.20 + : MediaQuery.of(context).size.width * 0.19, + floating: true, + backgroundColor: Colors.transparent, + flexibleSpace: FlexibleSpaceBar( + background: Column( + children: [ + Container( + color: Colors.transparent, + padding: EdgeInsets.symmetric( + horizontal: 16.0, vertical: 0.0), + child: Calendar( + isExpandable: false, + showTodayAction: false, + showCalendarPickerIcon: true, + showChevronsToChangeRange: true, + onDateSelected: (DateTime datetime) { + dateTime = datetime; + _getBusTimeTables(); + FA.logAction('date_select', 'click'); + }, + initialCalendarDateOverride: dateTime, + dayChildAspectRatio: + orientation == Orientation.portrait ? 1.5 : 3, + weekdays: app.weekdays, + ), ), - ), - Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: Divider(color: Colors.grey), - ), - ], + Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: Divider(color: Colors.grey), + ), + ], + ), ), ), - ), - ]; - }, - body: Column( - children: [ - Container( - padding: EdgeInsets.symmetric(vertical: 8.0), - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: double.infinity), - child: CupertinoSegmentedControl( - selectedColor: Resource.Colors.blueAccent, - borderColor: Resource.Colors.blueAccent, - unselectedColor: Resource.Colors.segmentControlUnSelect, - groupValue: selectStartStation, - children: { - Station.janGong: Container( - padding: EdgeInsets.symmetric(vertical: 8.0), - child: Text(app.fromJiangong), - ), - Station.yanchao: Container( - padding: EdgeInsets.symmetric(vertical: 8.0), - child: Text(app.fromYanchao), - ) - }, - onValueChanged: (Station text) { - if (mounted) { - setState(() { - selectStartStation = text; - }); - } - FA.logAction('segment', 'click'); - }, + ]; + }, + body: Column( + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: double.infinity), + child: CupertinoSegmentedControl( + selectedColor: Resource.Colors.blueAccent, + borderColor: Resource.Colors.blueAccent, + unselectedColor: Resource.Colors.segmentControlUnSelect, + groupValue: selectStartStation, + children: { + Station.janGong: Container( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Text(app.fromJiangong), + ), + Station.yanchao: Container( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Text(app.fromYanchao), + ) + }, + onValueChanged: (Station text) { + if (mounted) { + setState(() { + selectStartStation = text; + }); + } + FA.logAction('segment', 'click'); + }, + ), ), ), - ), - Expanded( - child: _body(), - ), - ], - ), - ); - }), + Expanded( + child: _body(), + ), + ], + ), + ); + }, + ), ); } @@ -147,6 +158,21 @@ class BusReservePageState extends State fontSize: 18.0, decorationColor: Colors.grey); + String get errorText { + switch (state) { + case _State.error: + return app.clickToRetry; + case _State.empty: + return app.busEmpty; + case _State.campusNotSupport: + return app.campusNotSupport; + case _State.userNotSupport: + return app.userNotSupport; + default: + return ''; + } + } + Widget _body() { switch (state) { case _State.loading: @@ -154,6 +180,8 @@ class BusReservePageState extends State child: CircularProgressIndicator(), alignment: Alignment.center); case _State.error: case _State.empty: + case _State.campusNotSupport: + case _State.userNotSupport: return FlatButton( onPressed: () { _getBusTimeTables(); @@ -161,7 +189,7 @@ class BusReservePageState extends State }, child: HintContent( icon: AppIcon.assignment, - content: state == _State.error ? app.clickToRetry : app.busEmpty, + content: errorText, ), ); case _State.offline: @@ -366,12 +394,20 @@ class BusReservePageState extends State switch (e.type) { case DioErrorType.RESPONSE: if (e.response.statusCode == 401) { + setState(() { + state = _State.userNotSupport; + }); + } else if (e.response.statusCode == 403) { + setState(() { + state = _State.campusNotSupport; + }); + } else { setState(() { state = _State.error; }); - } else Utils.handleResponseError( context, 'getBusTimeTables', mounted, e); + } break; case DioErrorType.DEFAULT: if (e.message.contains("HttpException")) { diff --git a/lib/pages/home/leaves/leave_record_page.dart b/lib/pages/home/leaves/leave_record_page.dart index cf595b52..69486147 100644 --- a/lib/pages/home/leaves/leave_record_page.dart +++ b/lib/pages/home/leaves/leave_record_page.dart @@ -280,7 +280,7 @@ class LeaveRecordPageState extends State state = _State.finish; } }); - CacheUtils.saveLeaveData(selectSemester.value, leaveData); + CacheUtils.saveLeaveData(selectSemester.code, leaveData); }).catchError((e) { if (e is DioError) { switch (e.type) { @@ -307,7 +307,7 @@ class LeaveRecordPageState extends State } void _loadOfflineLeaveData() async { - leaveData = await CacheUtils.loadLeaveData(selectSemester.value); + leaveData = await CacheUtils.loadLeaveData(selectSemester.code); if (mounted) { setState(() { isOffline = true; diff --git a/lib/pages/home/setting_page.dart b/lib/pages/home/setting_page.dart index 470b2eba..fe4199b7 100644 --- a/lib/pages/home/setting_page.dart +++ b/lib/pages/home/setting_page.dart @@ -87,23 +87,16 @@ class SettingPageState extends State { value: busNotify, onChanged: (b) async { FA.logAction('notify_bus', 'create'); - bool bus = Preferences.getBool(Constants.PREF_BUS_ENABLE, true); - if (bus) { - setState(() { - busNotify = !busNotify; - }); - if (busNotify) - _setupBusNotify(context); - else { - await Utils.cancelBusNotify(); - } - Preferences.setBool(Constants.PREF_BUS_NOTIFY, busNotify); - FA.logAction('notify_bus', 'click', message: '$busNotify'); - } else { - Utils.showToast(context, app.canNotUseFeature); - FA.logAction('notify_bus', 'staus', - message: 'can\'t use feature'); + setState(() { + busNotify = !busNotify; + }); + if (busNotify) + _setupBusNotify(context); + else { + await Utils.cancelBusNotify(); } + Preferences.setBool(Constants.PREF_BUS_NOTIFY, busNotify); + FA.logAction('notify_bus', 'click', message: '$busNotify'); }, ), Divider( diff --git a/lib/pages/home/calculate_units_page.dart b/lib/pages/home/study/calculate_units_page.dart similarity index 100% rename from lib/pages/home/calculate_units_page.dart rename to lib/pages/home/study/calculate_units_page.dart diff --git a/lib/pages/home/course_page.dart b/lib/pages/home/study/course_page.dart similarity index 96% rename from lib/pages/home/course_page.dart rename to lib/pages/home/study/course_page.dart index 7767931d..c89609a8 100644 --- a/lib/pages/home/course_page.dart +++ b/lib/pages/home/study/course_page.dart @@ -74,7 +74,7 @@ class CoursePageState extends State { }); if (Preferences.getBool( Constants.PREF_IS_OFFLINE_LOGIN, false)) - _loadCourseData(semester.value); + _loadCourseData(semester.code); else _getCourseTables(); }, @@ -278,12 +278,8 @@ class CoursePageState extends State { isOffline = true; if (this.courseData == null) { state = _State.offlineEmpty; - } else if (courseData.status == 204) { - state = _State.empty; - } else if (courseData.status == 200) { - state = _State.finish; } else { - state = _State.error; + state = _State.finish; } }); } @@ -302,7 +298,7 @@ class CoursePageState extends State { } else { courseData = response; isOffline = false; - CacheUtils.saveCourseData(selectSemester.value, courseData); + CacheUtils.saveCourseData(selectSemester.code, courseData); state = _State.finish; } }); @@ -325,7 +321,7 @@ class CoursePageState extends State { } else { throw e; } - _loadCourseData(selectSemester.value); + _loadCourseData(selectSemester.code); }); } } diff --git a/lib/pages/home/midterm_alerts_page.dart b/lib/pages/home/study/midterm_alerts_page.dart similarity index 100% rename from lib/pages/home/midterm_alerts_page.dart rename to lib/pages/home/study/midterm_alerts_page.dart diff --git a/lib/pages/home/reward_and_penalty_page.dart b/lib/pages/home/study/reward_and_penalty_page.dart similarity index 100% rename from lib/pages/home/reward_and_penalty_page.dart rename to lib/pages/home/study/reward_and_penalty_page.dart diff --git a/lib/pages/home/score_page.dart b/lib/pages/home/study/score_page.dart similarity index 95% rename from lib/pages/home/score_page.dart rename to lib/pages/home/study/score_page.dart index 586cd267..d7ed717d 100644 --- a/lib/pages/home/score_page.dart +++ b/lib/pages/home/study/score_page.dart @@ -252,7 +252,7 @@ class ScorePageState extends State { } else { scoreData = response; state = _State.finish; - CacheUtils.saveScoreData(selectSemester.value, scoreData); + CacheUtils.saveScoreData(selectSemester.code, scoreData); } }); }).catchError((e) { @@ -282,18 +282,15 @@ class ScorePageState extends State { } _loadOfflineScoreData() async { - scoreData = await CacheUtils.loadScoreData(selectSemester.value); + scoreData = await CacheUtils.loadScoreData(selectSemester.code); if (mounted) { setState(() { isOffline = true; - if (scoreData == null) state = _State.offlineEmpty; -// else if (scoreData.status == 204) -// state = _State.empty; -// else if (scoreData.status == 200) { -// state = _State.finish; -// } else { -// state = _State.error; -// } + if (scoreData == null) + state = _State.offlineEmpty; + else { + state = _State.finish; + } }); } } diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 819db1be..d79abc50 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -245,9 +245,9 @@ class HomePageState extends State { } else Helper.instance.getAllAnnouncements().then((announcementsResponse) { this.announcementsResponse = announcementsResponse; -// this.announcementsList.data.sort((a, b) { -// return b.weight.compareTo(a.weight); -// }); + this.announcementsResponse.data.sort((a, b) { + return b.weight.compareTo(a.weight); + }); setState(() { state = announcementsResponse.data.length == 0 ? _State.empty @@ -277,7 +277,8 @@ class HomePageState extends State { Helper.instance .getBusReservations() .then((BusReservationsData response) async { - await Utils.setBusNotify(context, response.reservations); + if (response != null) + await Utils.setBusNotify(context, response.reservations); }).catchError((e) { if (e is DioError) { switch (e.type) { diff --git a/lib/pages/page.dart b/lib/pages/page.dart index 6c13e778..335c331f 100644 --- a/lib/pages/page.dart +++ b/lib/pages/page.dart @@ -3,14 +3,14 @@ export 'home/about/open_source_page.dart'; export 'home/bus/bus_reservations_page.dart'; export 'home/bus/bus_reserve_page.dart'; export 'home/bus_page.dart'; -export 'home/calculate_units_page.dart'; -export 'home/course_page.dart'; +export 'home/study/calculate_units_page.dart'; +export 'home/study/course_page.dart'; export 'home/info/notification_page.dart'; export 'home/info/phone_page.dart'; export 'home/info/schedule_page.dart'; export 'home/leave_page.dart'; export 'home/news_content_page.dart'; -export 'home/score_page.dart'; +export 'home/study/score_page.dart'; export 'home/setting_page.dart'; export 'home/shcool_info_page.dart'; export 'home/user_info_page.dart'; diff --git a/lib/res/app_icon.dart b/lib/res/app_icon.dart index 5d966160..9c9e71fa 100644 --- a/lib/res/app_icon.dart +++ b/lib/res/app_icon.dart @@ -296,4 +296,24 @@ class AppIcon { return OMIcons.exitToApp; } } + + static IconData get warning { + switch (AppIcon.code) { + case AppIcon.FILLED: + return Icons.warning; + case AppIcon.OUTLINED: + default: + return OMIcons.warning; + } + } + + static IconData get folder { + switch (AppIcon.code) { + case AppIcon.FILLED: + return Icons.folder; + case AppIcon.OUTLINED: + default: + return OMIcons.folder; + } + } } diff --git a/lib/utils/app_localizations.dart b/lib/utils/app_localizations.dart index de5c33d8..4344d4d7 100644 --- a/lib/utils/app_localizations.dart +++ b/lib/utils/app_localizations.dart @@ -65,7 +65,7 @@ class AppLocalizations { 'app_name': 'NKUST AP', 'update_note_title': 'Update Notes', 'update_note_content': - '1.Add search student id page.\n2.Page can swipe to back(Android).\n3.Add other section picture\n4.Fix some error.', + '1.Release new API version(will clear old preference data).\n2.Add midterm warning page.\n3.Add reward and penalty page.', 'splash_content': '我們全都包了\n只剩下學校不包我們', 'share': 'Share', 'teacher_confirm_title': 'Are you a teacher?', @@ -370,12 +370,14 @@ class AppLocalizations { 'rewardAndPenaltyEmpty': 'Oops!No reward and penalty for this semester~\n Please choose another semester \uD83D\uDE0B', 'rewardAndPenaltyContent': 'Counts:%s\nDate:%s', + 'campusNotSupport': 'Campus not support this feature ~', + 'userNotSupport': 'User can\'t use this feature ~', }, 'zh': { 'app_name': '高科校務通', 'update_note_title': '更新日誌', 'update_note_content': - '1.新增查詢學號頁面\n2.可滑動返回上一頁(Android)\n3.新增其他校區照片\n4.修正部分錯誤', + '1.全新推出新的API(此更新會清除先前資料)\n2.新增期中預警\n3.新增獎懲紀錄\n4.修正部分錯誤', 'splash_content': '我們全都包了\n只剩下學校不包我們', 'share': '分享', 'teacher_confirm_title': '您是老師嗎?', @@ -659,6 +661,8 @@ class AppLocalizations { 'rewardAndPenalty': '獎懲紀錄', 'rewardAndPenaltyEmpty': 'Oops!本學期沒有任何獎懲紀錄哦~\n請選擇其他學期 \uD83D\uDE0B', 'rewardAndPenaltyContent': '數量:%s\n日期:%s', + 'campusNotSupport': '所在的校區無法使用此功能', + 'userNotSupport': '使用者無法使用此功能', }, }; @@ -1171,6 +1175,10 @@ class AppLocalizations { String get rewardAndPenaltyContent => _vocabularies['rewardAndPenaltyContent']; + + String get campusNotSupport => _vocabularies['campusNotSupport']; + + String get userNotSupport => _vocabularies['userNotSupport']; } class AppLocalizationsDelegate extends LocalizationsDelegate { diff --git a/lib/utils/preferences.dart b/lib/utils/preferences.dart index 599f5da4..e6970372 100644 --- a/lib/utils/preferences.dart +++ b/lib/utils/preferences.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:encrypt/encrypt.dart'; import 'package:flutter/foundation.dart'; import 'package:nkust_ap/config/constants.dart'; +import 'package:package_info/package_info.dart'; import 'package:shared_preferences/shared_preferences.dart'; class Preferences { @@ -18,8 +19,17 @@ class Preferences { static init() async { if (kIsWeb) { - } else if (Platform.isIOS || Platform.isAndroid) + } else if (Platform.isIOS || Platform.isAndroid) { prefs = await SharedPreferences.getInstance(); + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + var currentVersion = + Preferences.getString(Constants.PREF_CURRENT_VERSION, '0'); + if (currentVersion == '0') return; + var buildNumber = int.parse(currentVersion); + if (buildNumber <= 30202) { + prefs.clear(); + } + } } static Future setStringSecurity(String key, String data) async { diff --git a/lib/widgets/drawer_body.dart b/lib/widgets/drawer_body.dart index 410ffea6..6224ed4e 100644 --- a/lib/widgets/drawer_body.dart +++ b/lib/widgets/drawer_body.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:nkust_ap/config/constants.dart'; import 'package:nkust_ap/models/models.dart'; -import 'package:nkust_ap/pages/home/midterm_alerts_page.dart'; -import 'package:nkust_ap/pages/home/reward_and_penalty_page.dart'; +import 'package:nkust_ap/pages/home/study/midterm_alerts_page.dart'; +import 'package:nkust_ap/pages/home/study/reward_and_penalty_page.dart'; import 'package:nkust_ap/pages/page.dart'; import 'package:nkust_ap/res/app_icon.dart'; import 'package:nkust_ap/res/app_theme.dart'; @@ -109,9 +109,10 @@ class DrawerBodyState extends State { decoration: BoxDecoration( color: Resource.Colors.blue, image: DecorationImage( - image: AssetImage(ImageAssets.drawerBackground), - fit: BoxFit.fitWidth, - alignment: Alignment.bottomCenter), + image: AssetImage(ImageAssets.drawerBackground), + fit: BoxFit.fitWidth, + alignment: Alignment.bottomCenter, + ), ), ), Positioned( @@ -158,12 +159,12 @@ class DrawerBodyState extends State { page: CalculateUnitsPage(), ), _subItem( - icon: Icons.warning, + icon: AppIcon.warning, title: app.midtermAlerts, page: MidtermAlertsPage(), ), _subItem( - icon: Icons.folder, + icon: AppIcon.folder, title: app.rewardAndPenalty, page: RewardAndPenaltyPage(), ), diff --git a/pubspec.yaml b/pubspec.yaml index 93ec02ab..ff13d995 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nkust_ap description: A new Flutter application. -version: 3.2.4+30204 +version: 3.2.5+30205 environment: sdk: ">=2.2.2 <3.0.0"