From efd85c78ea7d52d28a3f47874f23a67ec07c6321 Mon Sep 17 00:00:00 2001 From: RainVisitor Date: Mon, 10 Jun 2019 10:42:41 +0800 Subject: [PATCH 1/3] Add webView official plugin --- ios/Podfile.lock | 6 ++++++ ios/Runner.xcodeproj/project.pbxproj | 2 ++ ios/Runner/Info.plist | 7 +++++++ lib/pages/example_page.dart | 0 pubspec.lock | 7 +++++++ pubspec.yaml | 1 + 6 files changed, 23 insertions(+) create mode 100644 lib/pages/example_page.dart diff --git a/ios/Podfile.lock b/ios/Podfile.lock index e80ee22..4018471 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -109,6 +109,8 @@ PODS: - FMDB (~> 2.7.2) - url_launcher (0.0.1): - Flutter + - webview_flutter (0.0.1): + - Flutter DEPENDENCIES: - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) @@ -122,6 +124,7 @@ DEPENDENCIES: - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`) - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`) SPEC REPOS: https://github.com/cocoapods/specs.git: @@ -162,6 +165,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/sqflite/ios" url_launcher: :path: ".symlinks/plugins/url_launcher/ios" + webview_flutter: + :path: ".symlinks/plugins/webview_flutter/ios" SPEC CHECKSUMS: Firebase: 8d77bb33624ae9b62d745d82ec023de5f70f7e4f @@ -188,6 +193,7 @@ SPEC CHECKSUMS: shared_preferences: 1feebfa37bb57264736e16865e7ffae7fc99b523 sqflite: ff1d9da63c06588cc8d1faf7256d741f16989d5a url_launcher: 0067ddb8f10d36786672aa0722a21717dba3a298 + webview_flutter: 1aa7604e6cdb451a9b7ed2c37d5454c0b440246b PODFILE CHECKSUM: ebd43b443038e611b86ede96e613bd6033c49497 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 5c1b0c0..d7fa6f6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -302,6 +302,7 @@ "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + "${BUILT_PRODUCTS_DIR}/webview_flutter/webview_flutter.framework", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( @@ -318,6 +319,7 @@ "${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", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/webview_flutter.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 92c0032..632faaa 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -44,6 +44,13 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + io.flutter.embedded_views_preview + YES + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + UIViewControllerBasedStatusBarAppearance diff --git a/lib/pages/example_page.dart b/lib/pages/example_page.dart new file mode 100644 index 0000000..e69de29 diff --git a/pubspec.lock b/pubspec.lock index 353c240..91c330e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -336,6 +336,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.8" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.9+1" sdks: dart: ">=2.2.2 <3.0.0" flutter: ">=1.5.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index d97a184..315438d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: shared_preferences: ^0.5.3+1 package_info: ^0.4.0+4 url_launcher: ^5.0.3 + webview_flutter: ^0.3.9+1 firebase_core: ^0.4.0+3 firebase_analytics: ^3.0.2 firebase_remote_config: ^0.2.0+2 From 9ba06690df17faa8e3ddb76fd60f660018c5239f Mon Sep 17 00:00:00 2001 From: RainVisitor Date: Mon, 10 Jun 2019 14:17:15 +0800 Subject: [PATCH 2/3] Update login implement by webview --- lib/pages/example_page.dart | 0 lib/pages/login_page.dart | 63 ++++++++++++++++++++++++++----------- lib/utils/helper.dart | 42 ++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 20 deletions(-) delete mode 100644 lib/pages/example_page.dart diff --git a/lib/pages/example_page.dart b/lib/pages/example_page.dart deleted file mode 100644 index e69de29..0000000 diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 49af2cf..c112ffc 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -14,6 +14,7 @@ import 'package:nsysu_ap/widgets/progress_dialog.dart'; import 'package:nsysu_ap/widgets/yes_no_dialog.dart'; import 'package:package_info/package_info.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:webview_flutter/webview_flutter.dart'; import 'home_page.dart'; @@ -39,6 +40,8 @@ class LoginPageState extends State final encrypter = Encrypter(AES(Constants.key, mode: AESMode.cbc)); + var _controller; + @override void initState() { super.initState(); @@ -65,22 +68,39 @@ class LoginPageState extends State return OrientationBuilder(builder: (_, orientation) { return Scaffold( resizeToAvoidBottomPadding: orientation == Orientation.portrait, - backgroundColor: Resource.Colors.blue, - body: Center( - child: Container( - padding: EdgeInsets.symmetric(horizontal: 30.0), - child: orientation == Orientation.portrait - ? Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.spaceAround, - mainAxisSize: MainAxisSize.min, - children: _renderContent(orientation), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: _renderContent(orientation), - ), - ), + body: Stack( + alignment: Alignment(0, 0), + children: [ + SizedBox( + child: WebView( + initialUrl: 'https://sso.nsysu.edu.tw/index.php/passport/login', + javascriptMode: JavascriptMode.unrestricted, + onWebViewCreated: (controller) { + _controller = controller; + }, + onPageFinished: (s) { + //print('onPageFinished = $s'); + }, + debuggingEnabled: true, + ), + ), + Container( + alignment: Alignment(0, 0), + color: Resource.Colors.blue, + padding: EdgeInsets.symmetric(horizontal: 30.0), + child: orientation == Orientation.portrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisSize: MainAxisSize.min, + children: _renderContent(orientation), + ) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: _renderContent(orientation), + ), + ) + ], ), ); }); @@ -410,19 +430,24 @@ class LoginPageState extends State if (Platform.isAndroid || Platform.isIOS) prefs.setString(Constants.PREF_USERNAME, _username.text); + var base64md5Password = await _controller + ?.evaluateJavascript('base64_md5("${_password.text}")'); + base64md5Password = base64md5Password.replaceAll('\"', ''); Helper.instance - .login(_username.text, _password.text) + .selcrsLogin(_username.text, base64md5Password) .then((response) async { if (Navigator.canPop(context)) Navigator.pop(context, 'dialog'); - if (Platform.isAndroid || Platform.isIOS) { + if (response == 403) { + Utils.showToast(context, app.loginFail); + } else if (Platform.isAndroid || Platform.isIOS) { prefs.setString(Constants.PREF_USERNAME, _username.text); if (isRememberPassword) { await prefs.setString(Constants.PREF_PASSWORD, encrypter.encrypt(_password.text, iv: Constants.iv).base64); } prefs.setBool(Constants.PREF_IS_OFFLINE_LOGIN, false); + _navigateToFilterObject(context); } - _navigateToFilterObject(context); }).catchError((e) { if (Navigator.canPop(context)) Navigator.pop(context, 'dialog'); }); diff --git a/lib/utils/helper.dart b/lib/utils/helper.dart index 654f1e0..7248e04 100644 --- a/lib/utils/helper.dart +++ b/lib/utils/helper.dart @@ -43,6 +43,46 @@ class Helper { } } + Future selcrsLogin(String username, String password) async { + print(DateTime.now()); + bool score = true, course = true; + var scoreResponse = await http.post( + 'http://selcrs.nsysu.edu.tw/scoreqry/sco_query_prs_sso2.asp', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: { + 'SID': username, + 'PASSWD': password, + 'ACTION': '0', + 'INTYPE': '1', + }, + ); + String text = big5.decode(scoreResponse.bodyBytes); + if (text.contains("資料錯誤請重新輸入")) score = false; + //print('text = ${text}'); + scoreCookie = scoreResponse.headers['set-cookie']; + var courseResponse = await http.post( + 'http://selcrs.nsysu.edu.tw/menu4/Studcheck_sso2.asp', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: { + 'stuid': username, + 'SPassword': password, + }, + ); + text = big5.decode(courseResponse.bodyBytes); + if (text.contains("學號碼密碼不符")) course = false; + courseCookie = courseResponse.headers['set-cookie']; + //print('text = ${text}'); + print(DateTime.now()); + if (score && course) + return 200; + else + return 403; + } + Future login(String username, String password) async { print(DateTime.now()); var response = await http.post( @@ -74,7 +114,7 @@ class Helper { headers: {'Cookie': courseCookie}, ); String text = big5.decode(response.bodyBytes); - print('text = ${text}'); + //print('text = ${text}'); var document = parse(text, encoding: 'BIG-5'); var tdDoc = document.getElementsByTagName('td'); var userInfo = UserInfo(); From 7ced7287863cdf7173f4ac02ed6319addb3f7726 Mon Sep 17 00:00:00 2001 From: RainVisitor Date: Mon, 10 Jun 2019 14:37:38 +0800 Subject: [PATCH 3/3] Add lose images and update to v0.0.3 Fix: open source page open error code tune for course and score page --- assets/images/ic_email.webp | Bin 0 -> 1060 bytes assets/images/ic_fb.webp | Bin 0 -> 842 bytes assets/images/ic_github.webp | Bin 0 -> 1154 bytes lib/main.dart | 11 +++++++++++ lib/pages/course_page.dart | 25 ++++++++++++++++--------- lib/pages/score_page.dart | 24 +++++++++++++++--------- lib/utils/helper.dart | 4 ++-- pubspec.yaml | 2 +- 8 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 assets/images/ic_email.webp create mode 100644 assets/images/ic_fb.webp create mode 100644 assets/images/ic_github.webp diff --git a/assets/images/ic_email.webp b/assets/images/ic_email.webp new file mode 100644 index 0000000000000000000000000000000000000000..19a6c99f2c50539df4607cb47647500c0c67489a GIT binary patch literal 1060 zcmV+<1l#*kNk&E-1ONb6MM6+kP&il$0000G0000-002h-06|PpNWlXD00BS7plu^b z=gi*m=lmaoh{(+~_mFc@?uVyb%C(sxztgPL?#v9yTaW~qaxWht(Y9^VkxtOIZQHhO z+qUiQvTfUD_$s;k!-9M6yZr$X{ht6*Iez=Ck4YuXJzm4vT$cR#?ykwC;h2LUbXYF8fjXjZQfZ0erJ=Q#P9ux^E6vYo_nPcFsdMK~EIY6CtYm9&iMf7H?qLI(L zVbZRrBb6+Q6fmubSfpTM4NP6PnXCU*2Tbm`)}N){Jr7Lpx!<4TiW?ewt}|?MKuhOl zsYNx=v~Hoq$S7zVH8L#gGog=oY7J*gH#F|r9LB&{XdOKu)E($8ZiJZIpc!gs1$zYT z9|jp)EOTk~O7$DEB?`v`92YWHGUEdYah!+-CqkA?c~=4{Lx@%x{{v$U(RKU}aGU6t z+yWu#W4Q*Lr~_cM zNa5}$hFw2BfG9jWio?Dw(gXP8c0QB)lEOd(_T>W*SxYTa<2{J8VY1+ad44s<4+&p%RD?J z$h=oA07}n|ATC!Q82*5bS*IdeGJJ|sgEGO!>BckHfEFzi^ z2{a$Da+M@=^}E~)WKE|)`&bG(H3#V0!Ik`xY2Xt#kT9EMXH^0f>zF>@9mB*308x{OcYh~PFoU6XBK?w^pAU!^ z{fK*a50F1i?ibNDxkjMt{!n7K9c%$IzDr#rT4_iDp7Rz`dD?)yv4UuDyjCpqegxJ0RH&S@kjsw0000GY4K|S literal 0 HcmV?d00001 diff --git a/assets/images/ic_fb.webp b/assets/images/ic_fb.webp new file mode 100644 index 0000000000000000000000000000000000000000..9c2d943460ac67388e9d7f2c098f1a48f2a7f0d8 GIT binary patch literal 842 zcmV-Q1GW58Nk&FO0{{S5MM6+kP&il$0000G0000-002h-06|PpNaz9p00F1Pplu^b z=gi(6f6PCGh{(-rk$bt~G_Dmbbh12lk%Tmm*E$TL^Dn&dAe+O};v(h178 zZQHhO+qUhhwrwk@^M{?>+;iXifQbH208pBR{-63Z%e_7igcG@EKAjz`(vUnKmyTjn8#vhWU)-ziWE5H+tw0kw0HRFZ2XRd8FWN1LzYJf$OcYX|mL<`{ZoW_@7g6NrZvQ{3nNwp{sSTimc z<2!P({Xj16zu~h#Ww_6YA#cq1V?J+w^2r9$RX#tp;wg^#X!YW`z2u|&BVNRBKEFSR zmxg@bKM}8z)8j+&x;P!oi?_sSu2nemV@@p@w_JvE4QJRgMCTeVd&}oGBj7C;xcbwU3d8 z6unaGQWyfq3u&F&gYoRYQu>n#jOG(k8Z&1B&m-v^c>sI-N2z>_0}~ZF8fj><6s7?5 z=%k?Q297rUI`MSQoQQOqpx_7KHTzGLzcXGyYf*3` z#&y0qkh_e0qx(MO3?eFHhhNdW8jVwdsDW*d_&sb32BF>4y7qsV_H(}{%@xE~hZl7? zGqmjtl|-n45LQq)AT$5~01yNKodGIH07w8nkw~FTrKBSwAxHqQ5(#Ml015G0bVU1OZ?SNy=!=*|Tliwr$(CZQHhO+qM?N z?#?f|I#r#$2SoIL0>DmJ;Z8GmTzc~9Z|d*&4^D5G&@wkfWSY9bYlo-p z1LSKQFRRWq)`zU$H&x|bl7Y#m@Kj+ydrX{lNtF_YdX zB$0Rltqp@0Zg!JA^L49l9jbR@bbJK_1nC*@(p!R8fBpMegJ^@j+fM3X%h_q zu)zv{RwYCoLgF+NfVcNm0}=l{xqNuX#*Nz!Uws)sMC1OLY#sk2b-JbAbkv%zBJtK2FUqbVj-6)68|a!v_|@mT3pJ1q~S<_*);zE z2N&p;PTK}>ly=MmY+d_kkK(ewqV)#G9d(kgW@C-?E;lFdLlO=djpWS^POzM|Vl8br zuEB`{--hl6uc zDoXYMsOpzMoSSH0%y=CoKj#C8JR+r^XdGdWr_R1G%C2?*K)aB@cV*4xkO|Shy+M?^ zh+3O6P&%~+06@$+!K)$=)8x2eLiAml-=$ofTzrKt^UkNE!UJv-^bz3B>;T@ahQRE< zGu=T;Sa~mqYK<-+Ot~a5u2%x^9wi{o0m+G|`fQR2>isn#-pUP7={q4MSxoGqX751pjDIhN4_EY z?=DY}%dO;3d!Ucf1^;S8MArNx>knB_rDPM3k5IA*B;%F|@KSDol-_wO&hymiqX0Ao zM{~$P)HMNai3dAFa_@72e8KYq?R0|}8^Ti0>Ve8aw@iq^(-Yg*t5&6IO}7GF=5qs3 zoByc5Yy<;AEk(|OlDBJs>Kq3Q3t?6{r^K~lpgwVKDk;01i{x981MGCRdB){MS2x&P zbVY_$HaVx2Z&h(%*!-d)^2#|x#^sj4GpXawpNObM$-y5){I|DDGO%@&nsw*%T2MIs z%ag^GUGRSg09H^qAT$5~01yNKodGIH07w8nkw~FTrKBSwAxHqQ5(#Ml015G runApp(MyApp()); class MyApp extends StatelessWidget { @@ -37,7 +43,12 @@ class MyApp extends StatelessWidget { debugShowCheckedModeBanner: false, routes: { Navigator.defaultRouteName: (context) => LoginPage(), + HomePage.routerName: (context) => HomePage(), + CoursePage.routerName: (context) => CoursePage(), ScorePage.routerName: (context) => ScorePage(), + SettingPage.routerName: (context) => SettingPage(), + AboutUsPage.routerName: (context) => AboutUsPage(), + OpenSourcePage.routerName: (context) => OpenSourcePage(), }, theme: ThemeData( brightness: brightness, diff --git a/lib/pages/course_page.dart b/lib/pages/course_page.dart index 62cfd62..1eda104 100644 --- a/lib/pages/course_page.dart +++ b/lib/pages/course_page.dart @@ -45,6 +45,8 @@ class CoursePageState extends State bool isOffline = false; + List list = []; + @override void initState() { super.initState(); @@ -334,17 +336,22 @@ class CoursePageState extends State state = _State.loading; }); var prefs = await SharedPreferences.getInstance(); - courseData = await Helper.instance.getCourseData( + Helper.instance + .getCourseData( prefs.getString(Constants.PREF_USERNAME), semesterData.semester.value, - ); - setState(() { - if (courseData.status == 200) - state = _State.finish; - else if (courseData.status == 204) - state = _State.empty; - else - state = _State.error; + ) + .then((courseData) { + this.courseData = courseData; + if (mounted) + setState(() { + if (courseData.status == 200) + state = _State.finish; + else if (courseData.status == 204) + state = _State.empty; + else + state = _State.error; + }); }); } } diff --git a/lib/pages/score_page.dart b/lib/pages/score_page.dart index ed04ede..8bf7db6 100644 --- a/lib/pages/score_page.dart +++ b/lib/pages/score_page.dart @@ -384,15 +384,21 @@ class ScorePageState extends State setState(() { state = _State.loading; }); - scoreData = await Helper.instance.getScoreData( - scoreSemesterData.year.value, scoreSemesterData.semester.value); - setState(() { - if (scoreData.status == 200) { - state = _State.finish; - } else if (scoreData.status == 204) { - state = _State.empty; - } else { - state = _State.error; + Helper.instance + .getScoreData( + scoreSemesterData.year.value, scoreSemesterData.semester.value) + .then((scoreData) { + this.scoreData = scoreData; + if (mounted) { + setState(() { + if (scoreData.status == 200) { + state = _State.finish; + } else if (scoreData.status == 204) { + state = _State.empty; + } else { + state = _State.error; + } + }); } }); } diff --git a/lib/utils/helper.dart b/lib/utils/helper.dart index 7248e04..26b722a 100644 --- a/lib/utils/helper.dart +++ b/lib/utils/helper.dart @@ -173,7 +173,7 @@ class Helper { status: (trDoc.length == 0) ? 204 : 200, messages: '', courseTables: (trDoc.length == 0) ? null : CourseTables()); - print(DateTime.now()); + //print(DateTime.now()); for (var i = 0; i < trDoc.length; i++) { var tdDoc = trDoc[i].getElementsByTagName('td'); if (i == 0) continue; @@ -214,7 +214,7 @@ class Helper { if (courseData.courseTables.sunday.length == 0) courseData.courseTables.sunday = null; } - print(DateTime.now()); + //print(DateTime.now()); return courseData; } diff --git a/pubspec.yaml b/pubspec.yaml index 315438d..74ae9c9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nsysu_ap description: NSYSU AP -version: 0.0.2+2 +version: 0.0.3+3 environment: sdk: ">=2.2.2 <3.0.0"