diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..55eab7c4 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2018 RainVisitor + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 366e1a1a..ed507bbb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -248,7 +248,8 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", + "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework", "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework", @@ -258,12 +259,15 @@ "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", "${BUILT_PRODUCTS_DIR}/package_info/package_info.framework", + "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/share/share.framework", "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework", @@ -274,8 +278,10 @@ "${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}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/lib/pages/home/about/open_source_page.dart b/lib/pages/home/about/open_source_page.dart index ce1aa4c1..2b63d05e 100644 --- a/lib/pages/home/about/open_source_page.dart +++ b/lib/pages/home/about/open_source_page.dart @@ -343,7 +343,18 @@ class OpenSourcePageState extends State "Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n" + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), _item('add_2_calendar', - 'MIT License\n\nCopyright (c) 2018 Javi Hurtado\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.') + 'MIT License\n\nCopyright (c) 2018 Javi Hurtado\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.'), + _item( + 'flutter_cached_network_image', + "The MIT License (MIT)\n" + + "\n" + + "Copyright (c) 2018 Rene Floor\n" + + "\n" + + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n" + + "\n" + + "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n" + + "\n" + + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.") ], ), ); diff --git a/lib/pages/home/bus/bus_reserve_page.dart b/lib/pages/home/bus/bus_reserve_page.dart index 5f9d1c96..a16ffa82 100644 --- a/lib/pages/home/bus/bus_reserve_page.dart +++ b/lib/pages/home/bus/bus_reserve_page.dart @@ -223,7 +223,7 @@ class BusReservePageState extends State { child: Calendar( isExpandable: false, showTodayAction: false, - showCalendarPickerIcon: false, + showCalendarPickerIcon: true, showChevronsToChangeRange: true, onDateSelected: (DateTime datetime) { dateTime = datetime; @@ -252,6 +252,8 @@ class BusReservePageState extends State { child: ConstrainedBox( constraints: BoxConstraints(minWidth: double.infinity), child: CupertinoSegmentedControl( + selectedColor: Resource.Colors.blue, + borderColor: Resource.Colors.blue, groupValue: selectStartStation, children: { Station.janGong: Container( diff --git a/lib/pages/home/course_page.dart b/lib/pages/home/course_page.dart index 5f2a54b9..f27ea56f 100644 --- a/lib/pages/home/course_page.dart +++ b/lib/pages/home/course_page.dart @@ -236,11 +236,13 @@ class CoursePageState extends State Helper.instance.getSemester().then((semesterData) { this.semesterData = semesterData; CacheUtils.saveSemesterData(semesterData); - setState(() { - selectSemester = semesterData.defaultSemester; - selectSemesterIndex = semesterData.defaultIndex; - _getCourseTables(); - }); + if (mounted) { + setState(() { + selectSemester = semesterData.defaultSemester; + selectSemesterIndex = semesterData.defaultIndex; + _getCourseTables(); + }); + } }).catchError((e) { if (e is DioError) { switch (e.type) { @@ -274,15 +276,17 @@ class CoursePageState extends State courseData = await CacheUtils.loadCourseData(value); if (this.courseData == null) return; isOffline = true; - setState(() { - if (courseData.status == 204) { - state = _State.empty; - } else if (courseData.status == 200) { - state = _State.finish; - } else { - state = _State.error; - } - }); + if (mounted) { + setState(() { + if (courseData.status == 204) { + state = _State.empty; + } else if (courseData.status == 200) { + state = _State.finish; + } else { + state = _State.error; + } + }); + } } void _selectSemester() { diff --git a/lib/pages/home/leaves/leave_record_page.dart b/lib/pages/home/leaves/leave_record_page.dart index 11ecd2a9..83059bf5 100644 --- a/lib/pages/home/leaves/leave_record_page.dart +++ b/lib/pages/home/leaves/leave_record_page.dart @@ -267,11 +267,13 @@ class LeaveRecordPageState extends State void _getSemester() { _loadSemesterData(); Helper.instance.getSemester().then((semesterData) { - setState(() { - this.semesterData = semesterData; - selectSemester = semesterData.defaultSemester; - selectSemesterIndex = semesterData.defaultIndex; - }); + if (mounted) { + setState(() { + this.semesterData = semesterData; + selectSemester = semesterData.defaultSemester; + selectSemesterIndex = semesterData.defaultIndex; + }); + } CacheUtils.saveSemesterData(semesterData); _getSemesterLeaveRecord(); }).catchError((e) { diff --git a/lib/pages/home/news_content_page.dart b/lib/pages/home/news_content_page.dart index 4e1af3fb..5e4cc4c9 100644 --- a/lib/pages/home/news_content_page.dart +++ b/lib/pages/home/news_content_page.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:nkust_ap/models/models.dart'; import 'package:nkust_ap/res/resource.dart' as Resource; @@ -94,7 +95,10 @@ class NewsContentPageState extends State List list = [ AspectRatio( aspectRatio: orientation == Orientation.portrait ? 4 / 3 : 9 / 16, - child: Image.network(news.image), + child: CachedNetworkImage( + imageUrl: news.image, + errorWidget: (context, url, error) => Icon(Icons.error), + ), ), SizedBox( height: orientation == Orientation.portrait ? 16.0 : 0.0, @@ -136,7 +140,7 @@ class NewsContentPageState extends State ), ), onPressed: () { - Utils.launchUrl(news.url); + if (news.url.isNotEmpty) Utils.launchUrl(news.url); }, padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 0.0), color: Resource.Colors.yellow, diff --git a/lib/pages/home/score_page.dart b/lib/pages/home/score_page.dart index 5fc2f4a3..673ce095 100644 --- a/lib/pages/home/score_page.dart +++ b/lib/pages/home/score_page.dart @@ -259,12 +259,12 @@ class ScorePageState extends State void _getSemester() { _loadSemesterData(); Helper.instance.getSemester().then((semesterData) { - _getSemesterScore(); setState(() { this.semesterData = semesterData; selectSemester = semesterData.defaultSemester; selectSemesterIndex = semesterData.defaultIndex; }); + _getSemesterScore(); CacheUtils.saveSemesterData(semesterData); }).catchError((e) { if (e is DioError) { diff --git a/lib/pages/home/setting_page.dart b/lib/pages/home/setting_page.dart index 7d6170a1..874b410c 100644 --- a/lib/pages/home/setting_page.dart +++ b/lib/pages/home/setting_page.dart @@ -212,15 +212,15 @@ class SettingPageState extends State } if (courseData.status != 200) { setState(() { - busNotify = false; - prefs.setBool(Constants.PREF_BUS_NOTIFY, busNotify); + courseNotify = false; + prefs.setBool(Constants.PREF_COURSE_NOTIFY, courseNotify); }); } if (Navigator.canPop(context)) Navigator.pop(context, 'dialog'); }).catchError((e) { setState(() { - busNotify = false; - prefs.setBool(Constants.PREF_BUS_NOTIFY, busNotify); + courseNotify = false; + prefs.setBool(Constants.PREF_COURSE_NOTIFY, courseNotify); }); if (e is DioError) { switch (e.type) { @@ -241,8 +241,8 @@ class SettingPageState extends State } }).catchError((e) { setState(() { - busNotify = false; - prefs.setBool(Constants.PREF_BUS_NOTIFY, busNotify); + courseNotify = false; + prefs.setBool(Constants.PREF_COURSE_NOTIFY, courseNotify); }); if (e is DioError) { switch (e.type) { diff --git a/lib/pages/home/user_info_page.dart b/lib/pages/home/user_info_page.dart index a75d8697..484a0617 100644 --- a/lib/pages/home/user_info_page.dart +++ b/lib/pages/home/user_info_page.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:nkust_ap/res/colors.dart' as Resource; @@ -59,8 +60,10 @@ class UserInfoPageState extends State child: pictureUrl != "" ? Hero( tag: Constants.TAG_STUDENT_PICTURE, - child: Image.network( - pictureUrl, + child: CachedNetworkImage( + imageUrl: pictureUrl, + errorWidget: (context, url, error) => + Icon(Icons.error), ), ) : null, diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index d6341fd9..bfa26740 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; @@ -59,7 +60,10 @@ class HomePageState extends State { onTap: () { Navigator.of(context).push(NewsContentPageRoute(news)); }, - child: Image.network(news.image), + child: CachedNetworkImage( + imageUrl: news.image, + errorWidget: (context, url, error) => Icon(Icons.error), + ), ), ); } diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 8a462ef1..da32b846 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -282,27 +282,23 @@ class LoginPageState extends State isRememberPassword = prefs.getBool(Constants.PREF_REMEMBER_PASSWORD) ?? true; isAutoLogin = prefs.getBool(Constants.PREF_AUTO_LOGIN) ?? false; + var username = prefs.getString(Constants.PREF_USERNAME) ?? ""; + var password = ""; + if (isRememberPassword) { + final encrypter = + Encrypter(AES(Constants.key, Constants.iv, mode: AESMode.cbc)); + var encryptPassword = prefs.getString(Constants.PREF_PASSWORD) ?? ""; + if (encryptPassword != "") + password = encrypter.decrypt64(encryptPassword); + } setState(() { - _username.text = prefs.getString(Constants.PREF_USERNAME) ?? ""; - if (isRememberPassword) { - final encrypter = - Encrypter(AES(Constants.key, Constants.iv, mode: AESMode.cbc)); - String password = prefs.getString(Constants.PREF_PASSWORD) ?? ""; - var currentVersion = - prefs.getString(Constants.PREF_CURRENT_VERSION) ?? ""; - //if build number below 604 - if (int.parse(currentVersion) < 604) { - password = prefs.getString(Constants.PREF_PASSWORD) ?? ""; - } else { - var encryptPassword = prefs.getString(Constants.PREF_PASSWORD) ?? ""; - password = encrypter.decrypt64(encryptPassword); - } - _password.text = password; - } - if (isAutoLogin) { - _login(); - } + _username.text = username; + _password.text = password; }); + await Future.delayed(Duration(microseconds: 50)); + if (isAutoLogin) { + _login(); + } } _login() async { diff --git a/lib/utils/app_localizations.dart b/lib/utils/app_localizations.dart index c2920092..42a0b0e3 100644 --- a/lib/utils/app_localizations.dart +++ b/lib/utils/app_localizations.dart @@ -20,8 +20,7 @@ class AppLocalizations { 'en': { 'app_name': 'NKUST AP', 'update_note_title': 'Update Notes', - 'update_note_content': - '1.Release absent system.\n2.Add offline access of feature semester course.\n3.Calendar can add schedule to calendar app.\n4.Fix some crash.', + 'update_note_content': '1.Fix some crash.', 'splash_content': '我們全都包了\n只剩下學校不包我們', 'share': 'Share', 'teacher_confirm_title': 'Are you a teacher?', @@ -186,7 +185,7 @@ class AppLocalizations { 'The best KUAS Campus App\nKUAS AP\n\nAre you afreshman?\nDon\'t know about school info, telephone numbers, or up coming events?\nBeenhere a few years?\nHave checking class schedule, report card and reserving bus seatsdrove you crazy?\n\nNo more, no more worries, anymore!\n\nKUAS AP lets no matter old or newfellow\nhave control over your life in KUAS!\n\nFrom checking class schedule, report card toyour absence records!\nPlus reserving/canceling bus seats with newest school feeds!\n\n\n\nMuch Simple, Many Convenient, Very instinct, wow!\n\n☆FABULOUS☆', 'about_author_title': 'Made by', 'about_author_content': - '呂紹榕(Louie Lu), 姜尚德(JohnThunder), \nregisterAutumn, 詹濬鍵(Evans), \n陳建霖(HearSilent), \n房志剛(Rainvisitor),林義翔(buluni.ha)', + '呂紹榕(Louie Lu), 姜尚德(JohnThunder), \nregisterAutumn, 詹濬鍵(Evans), \n陳建霖(HearSilent), \n房志剛(Rainvisitor),林義翔(takidog)', 'about_us': '“Ask not why nobody is doing this. You are \'nobody\'.”\n\nWe did this cause no one did it.\nWe created KUAS Wifi Login, KUASAP and KUAS Gourmet, Course Selection Sim, etc…\nTo bring convenience to everyone\'s on campus!', 'about_recruit_title': 'We Need You !', @@ -269,8 +268,7 @@ class AppLocalizations { 'zh': { 'app_name': '高科校務通', 'update_note_title': '更新日誌', - 'update_note_content': - '1.推出缺曠系統\n2.新增學期課表可透過先前紀錄離線存取\n3.行事曆現在可加入行程到手機行事曆了\n4.修正部分崩潰', + 'update_note_content': '1.修正部分崩潰', 'splash_content': '我們全都包了\n只剩下學校不包我們', 'share': '分享', 'teacher_confirm_title': '您是老師嗎?', @@ -416,7 +414,7 @@ class AppLocalizations { 'app_version': 'App 版本', 'about_author_title': '作者群', 'about_author_content': - '呂紹榕(Louie Lu), 姜尚德(JohnThunder), \nregisterAutumn, 詹濬鍵(Evans), \n陳建霖(HearSilent), \n房志剛(Rainvisitor),林義翔(buluni.ha)', + '呂紹榕(Louie Lu), 姜尚德(JohnThunder), \nregisterAutumn, 詹濬鍵(Evans), \n陳建霖(HearSilent), \n房志剛(Rainvisitor),林義翔(takidog)', 'about_us': '「不要問為何沒有人做這個,\n先承認你就是『沒有人』」。\n因為,「沒有人」是萬能的。\n\n因為沒有人做這些,所以我們跳下來做。\n先後完成了高應無線通、高應校務通,到後來的高應美食通、模擬選課等等.......\n無非是希望帶給大家更便利的校園生活!', 'about_recruit_title': 'We Need You !', diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 0373ca17..b7a06d1c 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -367,6 +367,7 @@ class Utils { courseTables.getCourseListByDayObject(Day.values[i]); List keyList = []; List saveCourseList = []; + if (course == null) continue; for (int j = 0; j < course.length; j++) { if (!keyList.contains(course[j].title)) { keyList.add(course[j].title); diff --git a/lib/widgets/drawer_body.dart b/lib/widgets/drawer_body.dart index cab56ec6..627b5be5 100644 --- a/lib/widgets/drawer_body.dart +++ b/lib/widgets/drawer_body.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:nkust_ap/api/helper.dart'; @@ -88,7 +89,8 @@ class DrawerBodyState extends State { shape: BoxShape.circle, image: new DecorationImage( fit: BoxFit.fitWidth, - image: NetworkImage(pictureUrl), + image: CachedNetworkImageProvider( + pictureUrl), ), ), ), diff --git a/pubspec.yaml b/pubspec.yaml index 7dd163f3..b1647f37 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nkust_ap description: A new Flutter application. -version: 3.0.3+30003 +version: 3.0.4+30004 environment: sdk: ">=2.1.0 <3.0.0" @@ -30,6 +30,7 @@ dependencies: flutter_local_notifications: ^0.4.5 sprintf: ^4.0.2 add_2_calendar: ^1.2.2 + cached_network_image: ^0.7.0 dev_dependencies: flutter_test: sdk: flutter