From 3a2fc67cb2bf78c14a4ad36db178f97891efc3cd Mon Sep 17 00:00:00 2001 From: Kima Date: Wed, 14 Aug 2024 00:53:12 +0200 Subject: [PATCH] new login system complete, that's it for today :3 --- refilc/assets/images/btn_kreten_login.png | Bin 0 -> 7764 bytes refilc/lib/api/login.dart | 117 ++++- refilc/lib/app.dart | 2 +- refilc/lib/utils/jwt.dart | 12 + .../lib/screens/login/kreten_login.dart | 119 +---- .../lib/screens/login/login_screen.dart | 427 +++++++++++------- .../lib/screens/login/login_screen.i18n.dart | 3 + 7 files changed, 412 insertions(+), 268 deletions(-) create mode 100644 refilc/assets/images/btn_kreten_login.png diff --git a/refilc/assets/images/btn_kreten_login.png b/refilc/assets/images/btn_kreten_login.png new file mode 100644 index 0000000000000000000000000000000000000000..0af9566c178fb0f6f0a49bcae010c8d11ee1fbaa GIT binary patch literal 7764 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 literal 0 HcmV?d00001 diff --git a/refilc/lib/api/login.dart b/refilc/lib/api/login.dart index 0977ce88..1074dff2 100644 --- a/refilc/lib/api/login.dart +++ b/refilc/lib/api/login.dart @@ -1,5 +1,6 @@ // ignore_for_file: avoid_print, use_build_context_synchronously +import 'package:flutter/foundation.dart'; import 'package:refilc/utils/jwt.dart'; import 'package:refilc_kreta_api/models/school.dart'; import 'package:refilc_kreta_api/providers/absence_provider.dart'; @@ -107,7 +108,9 @@ Future loginAPI({ default: // normal login from here Provider.of(context, listen: false).userAgent = - Provider.of(context, listen: false).config.userAgent; + Provider.of(context, listen: false) + .config + .userAgent; Map headers = { "content-type": "application/x-www-form-urlencoded", @@ -157,7 +160,8 @@ Future loginAPI({ .store .storeUser(user); Provider.of(context, listen: false).addUser(user); - Provider.of(context, listen: false).setUser(user.id); + Provider.of(context, listen: false) + .setUser(user.id); // Get user data try { @@ -167,7 +171,8 @@ Future loginAPI({ .fetch(week: Week.current()), Provider.of(context, listen: false).fetch(), Provider.of(context, listen: false).fetch(), - Provider.of(context, listen: false).fetchAll(), + Provider.of(context, listen: false) + .fetchAll(), Provider.of(context, listen: false) .fetchAllRecipients(), Provider.of(context, listen: false).fetch(), @@ -195,3 +200,109 @@ Future loginAPI({ return LoginState.failed; } + +// new login api +Future newLoginAPI({ + required String code, + required BuildContext context, + void Function(User)? onLogin, + void Function()? onSuccess, +}) async { + // actual login (token grant) logic + Map headers = { + "content-type": "application/x-www-form-urlencoded; charset=UTF-8", + "accept": "*/*", + "user-agent": "eKretaStudent/264745 CFNetwork/1494.0.7 Darwin/23.4.0", + }; + + Map? res = await Provider.of(context, listen: false) + .postAPI(KretaAPI.login, autoHeader: false, headers: headers, body: { + "code": code, + "code_verifier": "DSpuqj_HhDX4wzQIbtn8lr8NLE5wEi1iVLMtMK0jY6c", + "redirect_uri": + "https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect", + "client_id": "kreta-ellenorzo-student-mobile-ios", + "grant_type": "authorization_code", + }); + + if (res != null) { + if (kDebugMode) { + print(res); + } + + if (res.containsKey("error")) { + if (res["error"] == "invalid_grant") { + print("ERROR: invalid_grant"); + return; + } + } else { + // print("MUKODIK GECI"); + // print("ACCESS TOKEN: ${res["access_token"]}"); + if (res.containsKey("access_token")) { + print(JwtUtils.decodeJwt(res["access_token"])); + try { + Provider.of(context, listen: false).accessToken = + res["access_token"]; + + String instituteCode = + JwtUtils.getInstituteFromJWT(res["access_token"])!; + String username = JwtUtils.getUsernameFromJWT(res["access_token"])!; + Role role = JwtUtils.getRoleFromJWT(res["access_token"])!; + + Map? studentJson = + await Provider.of(context, listen: false) + .getAPI(KretaAPI.student(instituteCode)); + Student student = Student.fromJson(studentJson!); + + var user = User( + username: username, + password: '', + instituteCode: instituteCode, + name: student.name, + student: student, + role: role, + ); + + if (onLogin != null) onLogin(user); + + // Store User in the database + await Provider.of(context, listen: false) + .store + .storeUser(user); + Provider.of(context, listen: false).addUser(user); + Provider.of(context, listen: false).setUser(user.id); + + // Get user data + try { + await Future.wait([ + Provider.of(context, listen: false).fetch(), + Provider.of(context, listen: false) + .fetch(week: Week.current()), + Provider.of(context, listen: false).fetch(), + Provider.of(context, listen: false).fetch(), + Provider.of(context, listen: false).fetchAll(), + Provider.of(context, listen: false) + .fetchAllRecipients(), + Provider.of(context, listen: false).fetch(), + Provider.of(context, listen: false).fetch(), + Provider.of(context, listen: false).fetch(), + ]); + } catch (error) { + print("WARNING: failed to fetch user data: $error"); + } + + if (onSuccess != null) onSuccess(); + + return LoginState.success; + } catch (error) { + print("ERROR: loginAPI: $error"); + // maybe check debug mode + // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error"))); + return LoginState.failed; + } + } + } + } + + return LoginState.failed; +} diff --git a/refilc/lib/app.dart b/refilc/lib/app.dart index 7bfb9c09..ef2207d4 100644 --- a/refilc/lib/app.dart +++ b/refilc/lib/app.dart @@ -262,7 +262,7 @@ class App extends StatelessWidget { switch (route.name) { case "login_back": return CupertinoPageRoute( - builder: (context) => const mobile.LoginScreen()); + builder: (context) => const mobile.LoginScreen(back: true)); case "login": return _rootRoute(const mobile.LoginScreen()); case "navigation": diff --git a/refilc/lib/utils/jwt.dart b/refilc/lib/utils/jwt.dart index 2e0898b5..d933693d 100644 --- a/refilc/lib/utils/jwt.dart +++ b/refilc/lib/utils/jwt.dart @@ -39,4 +39,16 @@ class JwtUtils { } return null; } + + static String? getInstituteFromJWT(String jwt) { + var jwtData = decodeJwt(jwt); + + return jwtData?["kreta:institute_code"]; + } + + static String? getUsernameFromJWT(String jwt) { + var jwtData = decodeJwt(jwt); + + return jwtData?["kreta:user_name"]; + } } diff --git a/refilc_mobile_ui/lib/screens/login/kreten_login.dart b/refilc_mobile_ui/lib/screens/login/kreten_login.dart index d809af67..1b5cfd35 100644 --- a/refilc_mobile_ui/lib/screens/login/kreten_login.dart +++ b/refilc_mobile_ui/lib/screens/login/kreten_login.dart @@ -1,14 +1,13 @@ // ignore_for_file: use_build_context_synchronously -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:refilc_kreta_api/client/api.dart'; -import 'package:refilc_kreta_api/client/client.dart'; import 'package:webview_flutter/webview_flutter.dart'; class KretenLoginScreen extends StatefulWidget { - const KretenLoginScreen({super.key}); + const KretenLoginScreen({super.key, required this.onLogin}); + + // final String selectedSchool; + final void Function(String code) onLogin; @override State createState() => _KretenLoginScreenState(); @@ -31,6 +30,12 @@ class _KretenLoginScreenState extends State { currentUrl = url; }); + // final String instituteCode = widget.selectedSchool; + if (!url.startsWith( + 'https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect?code=')) { + return; + } + List requiredThings = url .replaceAll( 'https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect?code=', @@ -47,103 +52,11 @@ class _KretenLoginScreenState extends State { print(code); - // actual login (token grant) logic - Map headers = { - "content-type": "application/x-www-form-urlencoded; charset=UTF-8", - "accept": "*/*", - "user-agent": - "eKretaStudent/264745 CFNetwork/1494.0.7 Darwin/23.4.0", - }; - - Map? res = await Provider.of(context, listen: false) - .postAPI(KretaAPI.login, - autoHeader: false, - headers: headers, - body: { - "code": code, - "code_verifier": "DSpuqj_HhDX4wzQIbtn8lr8NLE5wEi1iVLMtMK0jY6c", - "redirect_uri": - "https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect", - "client_id": "kreta-ellenorzo-student-mobile-ios", - "grant_type": "authorization_code", - }); - if (res != null) { - if (kDebugMode) { - print(res); - } - - if (res.containsKey("error")) { - if (res["error"] == "invalid_grant") { - print("ERROR: invalid_grant"); - return; - } - } else { - print("MUKODIK GECI"); - print("ACCESS TOKEN: ${res["access_token"]}"); - // if (res.containsKey("access_token")) { - // try { - // Provider.of(context, listen: false).accessToken = - // res["access_token"]; - // Map? studentJson = - // await Provider.of(context, listen: false) - // .getAPI(KretaAPI.student(instituteCode)); - // Student student = Student.fromJson(studentJson!); - // var user = User( - // username: username, - // password: password, - // instituteCode: instituteCode, - // name: student.name, - // student: student, - // role: JwtUtils.getRoleFromJWT(res["access_token"])!, - // ); - - // if (onLogin != null) onLogin(user); - - // // Store User in the database - // await Provider.of(context, listen: false) - // .store - // .storeUser(user); - // Provider.of(context, listen: false) - // .addUser(user); - // Provider.of(context, listen: false) - // .setUser(user.id); - - // // Get user data - // try { - // await Future.wait([ - // Provider.of(context, listen: false) - // .fetch(), - // Provider.of(context, listen: false) - // .fetch(week: Week.current()), - // Provider.of(context, listen: false).fetch(), - // Provider.of(context, listen: false) - // .fetch(), - // Provider.of(context, listen: false) - // .fetchAll(), - // Provider.of(context, listen: false) - // .fetchAllRecipients(), - // Provider.of(context, listen: false).fetch(), - // Provider.of(context, listen: false) - // .fetch(), - // Provider.of(context, listen: false) - // .fetch(), - // ]); - // } catch (error) { - // print("WARNING: failed to fetch user data: $error"); - // } - - // if (onSuccess != null) onSuccess(); - - // return LoginState.success; - // } catch (error) { - // print("ERROR: loginAPI: $error"); - // // maybe check debug mode - // // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error"))); - // return LoginState.failed; - // } - // } - } - } + widget.onLogin(code); + // Future.delayed(const Duration(milliseconds: 500), () { + // Navigator.of(context).pop(); + // }); + // Navigator.of(context).pop(); }, onProgress: (progress) { setState(() { @@ -158,7 +71,7 @@ class _KretenLoginScreenState extends State { )) ..loadRequest( Uri.parse( - 'https://idp.e-kreta.hu/connect/authorize?prompt=login&nonce=wylCrqT4oN6PPgQn2yQB0euKei9nJeZ6_ffJ-VpSKZU&response_type=code&code_challenge_method=S256&scope=openid%20email%20offline_access%20kreta-ellenorzo-webapi.public%20kreta-eugyintezes-webapi.public%20kreta-fileservice-webapi.public%20kreta-mobile-global-webapi.public%20kreta-dkt-webapi.public%20kreta-ier-webapi.public&code_challenge=HByZRRnPGb-Ko_wTI7ibIba1HQ6lor0ws4bcgReuYSQ&redirect_uri=https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect&client_id=kreta-ellenorzo-student-mobile-ios&state=refilc_student_mobile'), + 'https://idp.e-kreta.hu/connect/authorize?prompt=login&nonce=wylCrqT4oN6PPgQn2yQB0euKei9nJeZ6_ffJ-VpSKZU&response_type=code&code_challenge_method=S256&scope=openid%20email%20offline_access%20kreta-ellenorzo-webapi.public%20kreta-eugyintezes-webapi.public%20kreta-fileservice-webapi.public%20kreta-mobile-global-webapi.public%20kreta-dkt-webapi.public%20kreta-ier-webapi.public&code_challenge=HByZRRnPGb-Ko_wTI7ibIba1HQ6lor0ws4bcgReuYSQ&redirect_uri=https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect&client_id=kreta-ellenorzo-student-mobile-ios&state=refilc_student_mobile'), // &institute_code=${widget.selectedSchool} ); } diff --git a/refilc_mobile_ui/lib/screens/login/login_screen.dart b/refilc_mobile_ui/lib/screens/login/login_screen.dart index 123b046d..0d8d9768 100644 --- a/refilc_mobile_ui/lib/screens/login/login_screen.dart +++ b/refilc_mobile_ui/lib/screens/login/login_screen.dart @@ -1,13 +1,11 @@ // import 'dart:async'; -import 'package:refilc/api/client.dart'; +import 'package:flutter/widgets.dart'; import 'package:refilc/api/login.dart'; import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc_mobile_ui/common/custom_snack_bar.dart'; import 'package:refilc_mobile_ui/common/system_chrome.dart'; import 'package:refilc_mobile_ui/screens/login/kreten_login.dart'; -import 'package:refilc_mobile_ui/screens/login/login_button.dart'; -import 'package:refilc_mobile_ui/screens/login/login_input.dart'; import 'package:refilc_mobile_ui/screens/login/school_input/school_input.dart'; import 'package:refilc_mobile_ui/screens/settings/privacy_view.dart'; import 'package:flutter/material.dart'; @@ -29,6 +27,9 @@ class LoginScreenState extends State { final schoolController = SchoolInputController(); final _scrollController = ScrollController(); + // new controllers + final codeController = TextEditingController(); + LoginState _loginState = LoginState.normal; bool showBack = false; @@ -58,20 +59,20 @@ class LoginScreenState extends State { systemNavigationBarIconBrightness: Brightness.dark, )); - FilcAPI.getSchools().then((schools) { - if (schools != null) { - schoolController.update(() { - schoolController.schools = schools; - }); - } else { - ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar( - content: Text("schools_error".i18n, - style: const TextStyle(color: Colors.white)), - backgroundColor: AppColors.of(context).red, - context: context, - )); - } - }); + // FilcAPI.getSchools().then((schools) { + // if (schools != null) { + // schoolController.update(() { + // schoolController.schools = schools; + // }); + // } else { + // ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar( + // content: Text("schools_error".i18n, + // style: const TextStyle(color: Colors.white)), + // backgroundColor: AppColors.of(context).red, + // context: context, + // )); + // } + // }); } @override @@ -105,17 +106,6 @@ class LoginScreenState extends State { ), ), - TextButton( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const KretenLoginScreen(), - ), - ); - }, - child: const Text("login_w_kreten"), - ), - // app icon Padding( padding: EdgeInsets.zero, @@ -160,149 +150,218 @@ class LoginScreenState extends State { flex: 2, ), - // inputs - Padding( - padding: const EdgeInsets.only( - left: 22.0, - right: 22.0, - top: 0.0, - ), - child: AutofillGroup( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // username - Padding( - padding: const EdgeInsets.only(bottom: 6.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - "username".i18n, - maxLines: 1, - style: TextStyle( - color: AppColors.of(context).loginPrimary, - fontWeight: FontWeight.w500, - fontSize: 12.0, - ), - ), - ), - Expanded( - child: Text( - "usernameHint".i18n, - maxLines: 1, - textAlign: TextAlign.right, - style: TextStyle( - color: - AppColors.of(context).loginSecondary, - fontWeight: FontWeight.w500, - fontSize: 12.0, - ), - ), - ), - ], - ), + // kreten login button + GestureDetector( + onTap: () { + final NavigatorState navigator = Navigator.of(context); + navigator + .push( + MaterialPageRoute( + builder: (context) => KretenLoginScreen( + onLogin: (String code) { + codeController.text = code; + navigator.pop(); + }, ), - Padding( - padding: const EdgeInsets.only(bottom: 12.0), - child: LoginInput( - style: LoginInputStyle.username, - controller: usernameController, + ), + ) + .then((value) { + if (codeController.text != "") { + _NewLoginAPI(context: context); + } + }); + }, + child: Container( + width: MediaQuery.of(context).size.width * 0.75, + height: 50.0, + decoration: BoxDecoration( + // image: const DecorationImage( + // image: + // AssetImage('assets/images/btn_kreten_login.png'), + // fit: BoxFit.scaleDown, + // ), + borderRadius: BorderRadius.circular(12.0), + color: const Color(0xFF0097C1), + ), + padding: const EdgeInsets.only( + top: 5.0, left: 5.0, right: 5.0, bottom: 5.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/btn_kreten_login.png', ), - ), - - // password - Padding( - padding: const EdgeInsets.only(bottom: 6.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - "password".i18n, - maxLines: 1, - style: TextStyle( - color: AppColors.of(context).loginPrimary, - fontWeight: FontWeight.w500, - fontSize: 12.0, - ), - ), - ), - Expanded( - child: Text( - "passwordHint".i18n, - maxLines: 1, - textAlign: TextAlign.right, - style: TextStyle( - color: - AppColors.of(context).loginSecondary, - fontWeight: FontWeight.w500, - fontSize: 12.0, - ), - ), - ), - ], + const SizedBox( + width: 10.0, ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 12.0), - child: LoginInput( - style: LoginInputStyle.password, - controller: passwordController, + Container( + width: 1.0, + height: 30.0, + color: Colors.white, ), - ), - - // school - Padding( - padding: const EdgeInsets.only(bottom: 6.0), - child: Text( - "school".i18n, - maxLines: 1, - style: TextStyle( - color: AppColors.of(context).loginPrimary, - fontWeight: FontWeight.w500, - fontSize: 12.0, + const SizedBox( + width: 10.0, + ), + Text( + 'login_w_kreta_acc'.i18n, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 15.0, ), ), - ), - SchoolInput( - scroll: _scrollController, - controller: schoolController, - ), - ], - ), - ), + ], + )), ), - // login button - Padding( - padding: const EdgeInsets.only( - top: 35.0, - left: 22.0, - right: 22.0, - ), - child: Visibility( - visible: _loginState != LoginState.inProgress, - replacement: const Padding( - padding: EdgeInsets.symmetric(vertical: 6.0), - child: CircularProgressIndicator( - valueColor: - AlwaysStoppedAnimation(Colors.white), - ), - ), - child: LoginButton( - child: Text("login".i18n, - maxLines: 1, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20.0, - )), - onPressed: () => _loginAPI(context: context), - ), - ), + const Spacer( + flex: 1, ), + // inputs + // Padding( + // padding: const EdgeInsets.only( + // left: 22.0, + // right: 22.0, + // top: 0.0, + // ), + // child: AutofillGroup( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // username + // Padding( + // padding: const EdgeInsets.only(bottom: 6.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Expanded( + // child: Text( + // "username".i18n, + // maxLines: 1, + // style: TextStyle( + // color: AppColors.of(context).loginPrimary, + // fontWeight: FontWeight.w500, + // fontSize: 12.0, + // ), + // ), + // ), + // Expanded( + // child: Text( + // "usernameHint".i18n, + // maxLines: 1, + // textAlign: TextAlign.right, + // style: TextStyle( + // color: + // AppColors.of(context).loginSecondary, + // fontWeight: FontWeight.w500, + // fontSize: 12.0, + // ), + // ), + // ), + // ], + // ), + // ), + // Padding( + // padding: const EdgeInsets.only(bottom: 12.0), + // child: LoginInput( + // style: LoginInputStyle.username, + // controller: usernameController, + // ), + // ), + + // // password + // Padding( + // padding: const EdgeInsets.only(bottom: 6.0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Expanded( + // child: Text( + // "password".i18n, + // maxLines: 1, + // style: TextStyle( + // color: AppColors.of(context).loginPrimary, + // fontWeight: FontWeight.w500, + // fontSize: 12.0, + // ), + // ), + // ), + // Expanded( + // child: Text( + // "passwordHint".i18n, + // maxLines: 1, + // textAlign: TextAlign.right, + // style: TextStyle( + // color: + // AppColors.of(context).loginSecondary, + // fontWeight: FontWeight.w500, + // fontSize: 12.0, + // ), + // ), + // ), + // ], + // ), + // ), + // Padding( + // padding: const EdgeInsets.only(bottom: 12.0), + // child: LoginInput( + // style: LoginInputStyle.password, + // controller: passwordController, + // ), + // ), + + // // school + // Padding( + // padding: const EdgeInsets.only(bottom: 6.0), + // child: Text( + // "school".i18n, + // maxLines: 1, + // style: TextStyle( + // color: AppColors.of(context).loginPrimary, + // fontWeight: FontWeight.w500, + // fontSize: 12.0, + // ), + // ), + // ), + // SchoolInput( + // scroll: _scrollController, + // controller: schoolController, + // ), + // ], + // ), + // ), + // ), + + // login button + // Padding( + // padding: const EdgeInsets.only( + // top: 35.0, + // left: 22.0, + // right: 22.0, + // ), + // child: Visibility( + // visible: _loginState != LoginState.inProgress, + // replacement: const Padding( + // padding: EdgeInsets.symmetric(vertical: 6.0), + // child: CircularProgressIndicator( + // valueColor: + // AlwaysStoppedAnimation(Colors.white), + // ), + // ), + // child: LoginButton( + // child: Text("login".i18n, + // maxLines: 1, + // style: const TextStyle( + // fontWeight: FontWeight.bold, + // fontSize: 20.0, + // )), + // onPressed: () => _loginAPI(context: context), + // ), + // ), + // ), + // error messages if (_loginState == LoginState.missingFields || _loginState == LoginState.invalidGrant || @@ -351,6 +410,52 @@ class LoginScreenState extends State { ); } + // new login api + void _NewLoginAPI({required BuildContext context}) { + String code = codeController.text; + + if (code == "") { + return setState(() => _loginState = LoginState.failed); + } + + // ignore: no_leading_underscores_for_local_identifiers + void _callAPI() { + newLoginAPI( + code: code, + context: context, + onLogin: (user) { + ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar( + context: context, + brightness: Brightness.light, + content: Text("welcome".i18n.fill([user.name]), + overflow: TextOverflow.ellipsis), + )); + }, + onSuccess: () { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + setSystemChrome(context); + Navigator.of(context).pushReplacementNamed("login_to_navigation"); + }).then( + (res) => setState(() { + // if (res == LoginState.invalidGrant && + // tempUsername.replaceAll(username, '').length <= 3) { + // tempUsername = username + ' '; + // Timer( + // const Duration(milliseconds: 500), + // () => _loginAPI(context: context), + // ); + // // _loginAPI(context: context); + // } else { + _loginState = res; + // } + }), + ); + } + + setState(() => _loginState = LoginState.inProgress); + _callAPI(); + } + void _loginAPI({required BuildContext context}) { String username = usernameController.text; String password = passwordController.text; diff --git a/refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart b/refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart index b9ef3b23..f8a07f86 100644 --- a/refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart +++ b/refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart @@ -33,6 +33,7 @@ extension Localization on String { "welcome_title_4": "Take as many notes as you want.", "welcome_text_4": "You can also organise your notes by lesson in the built-in notebook, so you can find everything in one app.", + "login_w_kreta_acc": "Log in with\ne-KRÉTA account", }, "hu_hu": { "username": "Felhasználónév", @@ -64,6 +65,7 @@ extension Localization on String { "welcome_title_4": "Füzetelj annyit, amennyit csak szeretnél.", "welcome_text_4": "A beépített jegyzetfüzetbe órák szerint is rendezheted a jegyzeteidet, így mindent megtalálsz egy appban.", + "login_w_kreta_acc": "Belépés e-KRÉTA\nfiókkal", }, "de_de": { "username": "Benutzername", @@ -95,6 +97,7 @@ extension Localization on String { "welcome_title_4": "Take as many notes as you want.", "welcome_text_4": "You can also organise your notes by lesson in the built-in notebook, so you can find everything in one app.", + "login_w_kreta_acc": "Mit e-KRÉTA-Konto\nanmelden", }, };