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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, 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 7bfb9c0..ef2207d 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 2e0898b..d933693 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 d809af6..1b5cfd3 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 123b046..0d8d976 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 b9ef3b2..f8a07f8 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", }, };