From b4f2d38e9970d6c6be23773e10f6c68d02c7712a Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Wed, 14 Aug 2024 23:28:57 +0200
Subject: [PATCH 1/6] changed launch mode to in-app

---
 .../lib/screens/settings/settings_screen.dart             | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/refilc_mobile_ui/lib/screens/settings/settings_screen.dart b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
index 0e15d79..b30e7d0 100644
--- a/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
@@ -960,11 +960,13 @@ class SettingsScreenState extends State<SettingsScreen>
                     color: AppColors.of(context).text.withOpacity(0.95),
                   ),
                   title: Text("stickermap".i18n),
-                  onPressed: () =>
-                      launchUrl(Uri.parse("https://stickermap.refilc.hu")),
+                  onPressed: () => launchUrl(
+                    Uri.parse("https://stickermap.refilc.hu"),
+                    mode: LaunchMode.inAppBrowserView,
+                  ),
                   borderRadius: const BorderRadius.vertical(
                     top: Radius.circular(12.0),
-                    bottom: Radius.circular(4.0),
+                    bottom: Radius.circular(12.0),
                   ),
                 ),
               ],

From f2c8e869b539fa552f5ba332b8c1814e0875dfef Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Wed, 14 Aug 2024 23:42:26 +0200
Subject: [PATCH 2/6] moved news

---
 .../lib/screens/settings/settings_screen.dart | 28 +++++++++----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/refilc_mobile_ui/lib/screens/settings/settings_screen.dart b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
index b30e7d0..58bdb64 100644
--- a/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
@@ -966,6 +966,19 @@ class SettingsScreenState extends State<SettingsScreen>
                   ),
                   borderRadius: const BorderRadius.vertical(
                     top: Radius.circular(12.0),
+                    bottom: Radius.circular(4.0),
+                  ),
+                ),
+                PanelButton(
+                  leading: Icon(
+                    FeatherIcons.mail,
+                    size: 22.0,
+                    color: AppColors.of(context).text.withOpacity(0.95),
+                  ),
+                  title: Text("news".i18n),
+                  onPressed: () => _openNews(context),
+                  borderRadius: const BorderRadius.vertical(
+                    top: Radius.circular(4.0),
                     bottom: Radius.circular(12.0),
                   ),
                 ),
@@ -1004,19 +1017,6 @@ class SettingsScreenState extends State<SettingsScreen>
               title: Text("about".i18n),
               cardPadding: const EdgeInsets.all(4.0),
               children: [
-                PanelButton(
-                  leading: Icon(
-                    FeatherIcons.mail,
-                    size: 22.0,
-                    color: AppColors.of(context).text.withOpacity(0.95),
-                  ),
-                  title: Text("news".i18n),
-                  onPressed: () => _openNews(context),
-                  borderRadius: const BorderRadius.vertical(
-                    top: Radius.circular(12.0),
-                    bottom: Radius.circular(4.0),
-                  ),
-                ),
                 PanelButton(
                   leading: Icon(
                     FeatherIcons.lock,
@@ -1029,7 +1029,7 @@ class SettingsScreenState extends State<SettingsScreen>
                   //     mode: LaunchMode.inAppWebView),
                   onPressed: () => _openPrivacy(context),
                   borderRadius: const BorderRadius.vertical(
-                    top: Radius.circular(4.0),
+                    top: Radius.circular(12.0),
                     bottom: Radius.circular(4.0),
                   ),
                 ),

From a673d3f1b30b1e2eac3b7df3ad234a469f1bdf8a Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Fri, 16 Aug 2024 00:25:46 +0200
Subject: [PATCH 3/6] finally the new login is completely working with refresh
 token as well

---
 refilc/lib/api/login.dart                     |  16 +-
 refilc/lib/app.dart                           |   3 +-
 refilc/lib/database/init.dart                 |   4 +-
 refilc/lib/helpers/notification_helper.dart   |   8 +-
 refilc/lib/models/user.dart                   |   6 +
 refilc_kreta_api/lib/client/api.dart          |   2 +-
 refilc_kreta_api/lib/client/client.dart       |  97 ++--
 .../lib/screens/login/kreten_login.dart       |   4 -
 .../lib/screens/login/login_screen.dart       |  95 ++--
 .../lib/screens/login/login_screen_old.dart   | 436 +++++++++---------
 .../lib/screens/settings/settings_screen.dart |  57 ++-
 11 files changed, 406 insertions(+), 322 deletions(-)

diff --git a/refilc/lib/api/login.dart b/refilc/lib/api/login.dart
index 1074dff..6db0229 100644
--- a/refilc/lib/api/login.dart
+++ b/refilc/lib/api/login.dart
@@ -67,6 +67,7 @@ Future loginAPI({
         address: '1117 Budapest, Gábor Dénes utca 4.',
       ),
       role: Role.parent,
+      refreshToken: '',
     );
 
     if (onLogin != null) onLogin(user);
@@ -130,6 +131,7 @@ Future loginAPI({
                 password: password,
                 instituteCode: instituteCode,
               ));
+
       if (res != null) {
         if (res.containsKey("error")) {
           if (res["error"] == "invalid_grant") {
@@ -151,6 +153,7 @@ Future loginAPI({
                 name: student.name,
                 student: student,
                 role: JwtUtils.getRoleFromJWT(res["access_token"])!,
+                refreshToken: '',
               );
 
               if (onLogin != null) onLogin(user);
@@ -209,6 +212,9 @@ Future newLoginAPI({
   void Function()? onSuccess,
 }) async {
   // actual login (token grant) logic
+  Provider.of<KretaClient>(context, listen: false).userAgent =
+      Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
+
   Map<String, String> headers = {
     "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
     "accept": "*/*",
@@ -216,12 +222,12 @@ Future newLoginAPI({
   };
 
   Map? res = await Provider.of<KretaClient>(context, listen: false)
-      .postAPI(KretaAPI.login, autoHeader: false, headers: headers, body: {
+      .postAPI(KretaAPI.login, 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",
+    "client_id": KretaAPI.clientId,
     "grant_type": "authorization_code",
   });
 
@@ -236,13 +242,12 @@ Future newLoginAPI({
         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<KretaClient>(context, listen: false).accessToken =
               res["access_token"];
+          Provider.of<KretaClient>(context, listen: false).refreshToken =
+              res["refresh_token"];
 
           String instituteCode =
               JwtUtils.getInstituteFromJWT(res["access_token"])!;
@@ -261,6 +266,7 @@ Future newLoginAPI({
             name: student.name,
             student: student,
             role: role,
+            refreshToken: res["refresh_token"],
           );
 
           if (onLogin != null) onLogin(user);
diff --git a/refilc/lib/app.dart b/refilc/lib/app.dart
index ef2207d..7a94f25 100644
--- a/refilc/lib/app.dart
+++ b/refilc/lib/app.dart
@@ -81,7 +81,8 @@ class App extends StatelessWidget {
     CorePalette? corePalette;
 
     final status = StatusProvider();
-    final kreta = KretaClient(user: user, settings: settings, status: status);
+    final kreta = KretaClient(
+        user: user, settings: settings, database: database, status: status);
     final timetable =
         TimetableProvider(user: user, database: database, kreta: kreta);
     final premium = PlusProvider(settings: settings);
diff --git a/refilc/lib/database/init.dart b/refilc/lib/database/init.dart
index 84d4444..cde1c14 100644
--- a/refilc/lib/database/init.dart
+++ b/refilc/lib/database/init.dart
@@ -66,6 +66,7 @@ const usersDB = DatabaseStruct("users", {
   "institute_code": String, "student": String, "role": int,
   "nickname": String, "picture": String, // premium only (it's now plus btw)
   "grade_streak": int,
+  "refresh_token": String,
 });
 const userDataDB = DatabaseStruct("user_data", {
   "id": String, "grades": String, "timetable": String, "exams": String,
@@ -138,7 +139,8 @@ Future<Database> initDB(DatabaseProvider database) async {
         "role": 0,
         "nickname": "",
         "picture": "",
-        "grade_streak": 0
+        "grade_streak": 0,
+        "refresh_token": "",
       },
     );
     await migrateDB(db, struct: userDataDB, defaultValues: {
diff --git a/refilc/lib/helpers/notification_helper.dart b/refilc/lib/helpers/notification_helper.dart
index 4313fad..f99ebfe 100644
--- a/refilc/lib/helpers/notification_helper.dart
+++ b/refilc/lib/helpers/notification_helper.dart
@@ -71,9 +71,11 @@ class NotificationsHelper {
         // Refresh kreta login for current user
         final status = StatusProvider();
         KretaClient kretaClientForUser = KretaClient(
-            user: userProviderForUser,
-            settings: settingsProvider,
-            status: status);
+          user: userProviderForUser,
+          settings: settingsProvider,
+          database: database,
+          status: status,
+        );
         await kretaClientForUser.refreshLogin();
 
         // Process notifications for current user
diff --git a/refilc/lib/models/user.dart b/refilc/lib/models/user.dart
index 83d15d3..1b76ec2 100644
--- a/refilc/lib/models/user.dart
+++ b/refilc/lib/models/user.dart
@@ -17,6 +17,8 @@ class User {
   String nickname;
   String picture;
   int gradeStreak;
+  // new login method
+  String refreshToken;
 
   String get displayName => nickname != '' ? nickname : name;
   bool get hasStreak => gradeStreak > 0;
@@ -32,6 +34,7 @@ class User {
     this.nickname = "",
     this.picture = "",
     this.gradeStreak = 0,
+    required this.refreshToken,
   }) {
     if (id != null) {
       this.id = id;
@@ -61,6 +64,7 @@ class User {
       nickname: map["nickname"] ?? "",
       picture: map["picture"] ?? "",
       gradeStreak: map["grade_streak"] ?? 0,
+      refreshToken: map["refresh_token"] ?? "",
     );
   }
 
@@ -75,6 +79,8 @@ class User {
       "role": role.index,
       "nickname": nickname,
       "picture": picture,
+      "grade_streak": gradeStreak,
+      "refresh_token": refreshToken,
     };
   }
 
diff --git a/refilc_kreta_api/lib/client/api.dart b/refilc_kreta_api/lib/client/api.dart
index aea3b85..d689d64 100644
--- a/refilc_kreta_api/lib/client/api.dart
+++ b/refilc_kreta_api/lib/client/api.dart
@@ -5,7 +5,7 @@ class KretaAPI {
   static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
   static const logout = BaseKreta.kretaIdp + KretaApiEndpoints.revoke;
   static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
-  static const clientId = "kreta-ellenorzo-mobile-android";
+  static const clientId = "kreta-ellenorzo-student-mobile-ios";
 
   // ELLENORZO API
   static String notes(String iss) =>
diff --git a/refilc_kreta_api/lib/client/client.dart b/refilc_kreta_api/lib/client/client.dart
index b075ec1..a198731 100644
--- a/refilc_kreta_api/lib/client/client.dart
+++ b/refilc_kreta_api/lib/client/client.dart
@@ -1,15 +1,16 @@
-// ignore_for_file: avoid_print
+// ignore_for_file: avoid_print, use_build_context_synchronously
 
 import 'dart:convert';
 import 'dart:io';
 
-import 'package:refilc/api/login.dart';
-import 'package:refilc/api/nonce.dart';
+// import 'package:refilc/api/login.dart';
+// import 'package:refilc/api/nonce.dart';
+import 'package:refilc/api/providers/database_provider.dart';
 import 'package:refilc/api/providers/user_provider.dart';
 import 'package:refilc/api/providers/status_provider.dart';
 import 'package:refilc/models/settings.dart';
 import 'package:refilc/models/user.dart';
-import 'package:refilc/utils/jwt.dart';
+// import 'package:refilc/utils/jwt.dart';
 import 'package:refilc_kreta_api/client/api.dart';
 import 'package:http/http.dart' as http;
 import 'package:http/io_client.dart' as http;
@@ -24,6 +25,7 @@ class KretaClient {
 
   late final SettingsProvider _settings;
   late final UserProvider _user;
+  late final DatabaseProvider _database;
   late final StatusProvider _status;
 
   bool _loginRefreshing = false;
@@ -32,9 +34,11 @@ class KretaClient {
     this.accessToken,
     required SettingsProvider settings,
     required UserProvider user,
+    required DatabaseProvider database,
     required StatusProvider status,
   })  : _settings = settings,
         _user = user,
+        _database = database,
         _status = status,
         userAgent = settings.config.userAgent {
     var ioclient = HttpClient();
@@ -212,7 +216,7 @@ class KretaClient {
         res = await request.send();
 
         if (res.statusCode == 401) {
-          headerMap.remove("authorization"); 
+          headerMap.remove("authorization");
           await refreshLogin();
         } else {
           break;
@@ -232,65 +236,74 @@ class KretaClient {
     }
   }
 
-  Future<void> refreshLogin() async {
-    if (_loginRefreshing) return;
+  Future<String?> refreshLogin() async {
+    if (_loginRefreshing) return null;
     _loginRefreshing = true;
 
     User? loginUser = _user.user;
-    if (loginUser == null) return;
+    if (loginUser == null) return null;
 
     Map<String, String> headers = {
-      "content-type": "application/x-www-form-urlencoded",
+      "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+      "accept": "*/*",
+      "user-agent": "eKretaStudent/264745 CFNetwork/1494.0.7 Darwin/23.4.0",
     };
 
-    String nonceStr = await getAPI(KretaAPI.nonce, json: false);
-    Nonce nonce =
-        getNonce(nonceStr, loginUser.username, loginUser.instituteCode);
-    headers.addAll(nonce.header());
-
     if (_settings.presentationMode) {
       print("DEBUG: refreshLogin: ${loginUser.id}");
     } else {
       print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
     }
 
-    Map? loginRes = await postAPI(
-      KretaAPI.login,
-      headers: headers,
-      body: User.loginBody(
-        username: loginUser.username,
-        password: loginUser.password,
-        instituteCode: loginUser.instituteCode,
-      ),
-    );
+    refreshToken ??= loginUser.refreshToken;
 
-    if (loginRes != null) {
-      if (loginRes.containsKey("access_token")) {
-        accessToken = loginRes["access_token"];
-      }
-      if (loginRes.containsKey("refresh_token")) {
-        refreshToken = loginRes["refresh_token"];
-      }
-
-      // Update role
-      loginUser.role =
-          JwtUtils.getRoleFromJWT(accessToken ?? "") ?? Role.student;
-    }
+    print("REFRESH TOKEN BELOW");
+    print(refreshToken);
 
     if (refreshToken != null) {
-      Map? refreshRes = await postAPI(KretaAPI.login,
+      print("REFRESHING LOGIN");
+      Map? res = await postAPI(KretaAPI.login,
           headers: headers,
           body: User.refreshBody(
-              refreshToken: refreshToken!,
-              instituteCode: loginUser.instituteCode));
-      if (refreshRes != null) {
-        if (refreshRes.containsKey("id_token")) {
-          idToken = refreshRes["id_token"];
+            refreshToken: loginUser.refreshToken,
+            instituteCode: loginUser.instituteCode,
+          ));
+      print("REFRESH RESPONSE BELOW");
+      print(res);
+      if (res != null) {
+        if (res.containsKey("error")) {
+          // remove user if refresh token expired
+          if (res["error"] == "invalid_grant") {
+            // remove user from app
+            _user.removeUser(loginUser.id);
+            await _database.store.removeUser(loginUser.id);
+
+            // return error
+            return "refresh_token_expired";
+          }
         }
+
+        if (res.containsKey("access_token")) {
+          accessToken = res["access_token"];
+        }
+        if (res.containsKey("refresh_token")) {
+          refreshToken = res["refresh_token"];
+          loginUser.refreshToken = res["refresh_token"];
+          _database.store.storeUser(loginUser);
+          _user.refresh();
+        }
+        if (res.containsKey("id_token")) {
+          idToken = res["id_token"];
+        }
+        _loginRefreshing = false;
+      } else {
+        _loginRefreshing = false;
       }
+    } else {
+      _loginRefreshing = false;
     }
 
-    _loginRefreshing = false;
+    return null;
   }
 
   Future<void> logout() async {
diff --git a/refilc_mobile_ui/lib/screens/login/kreten_login.dart b/refilc_mobile_ui/lib/screens/login/kreten_login.dart
index 1b5cfd3..8396f8c 100644
--- a/refilc_mobile_ui/lib/screens/login/kreten_login.dart
+++ b/refilc_mobile_ui/lib/screens/login/kreten_login.dart
@@ -48,10 +48,6 @@ class _KretenLoginScreenState extends State<KretenLoginScreen> {
           String code = requiredThings[0];
           // String sessionState = requiredThings[1];
 
-          debugPrint('url: $url');
-
-          print(code);
-
           widget.onLogin(code);
           // Future.delayed(const Duration(milliseconds: 500), () {
           //   Navigator.of(context).pop();
diff --git a/refilc_mobile_ui/lib/screens/login/login_screen.dart b/refilc_mobile_ui/lib/screens/login/login_screen.dart
index 19c6004..e574253 100644
--- a/refilc_mobile_ui/lib/screens/login/login_screen.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_screen.dart
@@ -341,59 +341,60 @@ class LoginScreenState extends State<LoginScreen> {
     );
   }
 
-  void _loginAPI({required BuildContext context}) {
-    String username = usernameController.text;
-    String password = passwordController.text;
+  // void _loginAPI({required BuildContext context}) {
+  //   String username = usernameController.text;
+  //   String password = passwordController.text;
 
-    tempUsername = username;
+  //   tempUsername = username;
 
-    if (username == "" ||
-        password == "" ||
-        schoolController.selectedSchool == null) {
-      return setState(() => _loginState = LoginState.missingFields);
-    }
+  //   if (username == "" ||
+  //       password == "" ||
+  //       schoolController.selectedSchool == null) {
+  //     return setState(() => _loginState = LoginState.missingFields);
+  //   }
 
-    // ignore: no_leading_underscores_for_local_identifiers
-    void _callAPI() {
-      loginAPI(
-          username: username,
-          password: password,
-          instituteCode: schoolController.selectedSchool!.instituteCode,
-          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;
-          // }
-        }),
-      );
-    }
+  //   // ignore: no_leading_underscores_for_local_identifiers
+  //   void _callAPI() {
+  //     loginAPI(
+  //         username: username,
+  //         password: password,
+  //         instituteCode: schoolController.selectedSchool!.instituteCode,
+  //         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();
-  }
+  //   setState(() => _loginState = LoginState.inProgress);
+  //   _callAPI();
+  // }
 
   // new login api
+  // ignore: non_constant_identifier_names
   void _NewLoginAPI({required BuildContext context}) {
     String code = codeController.text;
 
diff --git a/refilc_mobile_ui/lib/screens/login/login_screen_old.dart b/refilc_mobile_ui/lib/screens/login/login_screen_old.dart
index 75c7d2a..aaeb615 100644
--- a/refilc_mobile_ui/lib/screens/login/login_screen_old.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_screen_old.dart
@@ -1,10 +1,13 @@
 // import 'dart:async';
 
+import 'package:refilc/api/client.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/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';
@@ -58,20 +61,20 @@ class LoginScreenState extends State<LoginScreen> {
       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
@@ -150,217 +153,217 @@ class LoginScreenState extends State<LoginScreen> {
                   ),
 
                   // 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();
-                            },
-                          ),
-                        ),
-                      )
-                          .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',
-                            ),
-                            const SizedBox(
-                              width: 10.0,
-                            ),
-                            Container(
-                              width: 1.0,
-                              height: 30.0,
-                              color: Colors.white,
-                            ),
-                            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,
-                              ),
-                            ),
-                          ],
-                        )),
-                  ),
-
-                  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,
-                  //                   ),
-                  //                 ),
-                  //               ),
-                  //             ],
-                  //           ),
+                  // 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<Color>(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<Color>(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 ||
@@ -410,6 +413,7 @@ class LoginScreenState extends State<LoginScreen> {
   }
 
   // new login api
+  // ignore: non_constant_identifier_names, unused_element
   void _NewLoginAPI({required BuildContext context}) {
     String code = codeController.text;
 
diff --git a/refilc_mobile_ui/lib/screens/settings/settings_screen.dart b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
index 58bdb64..cb6b2bb 100644
--- a/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
@@ -30,6 +30,7 @@ import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
 import 'package:refilc_mobile_ui/common/soon_alert/soon_alert.dart';
 // import 'package:refilc_mobile_ui/common/soon_alert/soon_alert.dart';
 import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
+import 'package:refilc_mobile_ui/common/system_chrome.dart';
 // import 'package:refilc_mobile_ui/common/system_chrome.dart';
 import 'package:refilc_mobile_ui/common/widgets/update/updates_view.dart';
 import 'package:refilc_mobile_ui/screens/news/news_screen.dart';
@@ -105,9 +106,11 @@ class SettingsScreenState extends State<SettingsScreen>
         Provider.of<NoteProvider>(context, listen: false).restore(),
         Provider.of<EventProvider>(context, listen: false).restore(),
         Provider.of<AbsenceProvider>(context, listen: false).restore(),
-        Provider.of<KretaClient>(context, listen: false).refreshLogin(),
       ]);
 
+  Future<String?> refresh() =>
+      Provider.of<KretaClient>(context, listen: false).refreshLogin();
+
   void buildAccountTiles() {
     accountTiles = [];
     user.getUsers().forEach((account) {
@@ -143,8 +146,58 @@ class SettingsScreenState extends State<SettingsScreen>
             //? ColorUtils.stringToColor(account.name)
             //: Theme.of(context).colorScheme.secondary,
           ),
-          onTap: () {
+          onTap: () async {
             user.setUser(account.id);
+
+            // check if refresh token is still valid
+            String? err = await refresh();
+            if (err != null) {
+              showDialog(
+                context: context,
+                builder: (_) => AlertDialog(
+                  shape: RoundedRectangleBorder(
+                      borderRadius: BorderRadius.circular(12.0)),
+                  title: Text('oopsie'.i18n),
+                  content: Text('session_expired'.i18n),
+                  actions: [
+                    ActionButton(
+                        label: "Ok",
+                        onTap: () async {
+                          String? userId = user.id;
+                          if (userId == null) return;
+
+                          // delete user
+                          user.removeUser(userId);
+                          await Provider.of<DatabaseProvider>(context,
+                                  listen: false)
+                              .store
+                              .removeUser(userId);
+
+                          // if no users, show login, else login with back button
+                          if (user.getUsers().isNotEmpty) {
+                            user.setUser(user.getUsers().first.id);
+                            restore().then(
+                                (_) => user.setUser(user.getUsers().first.id));
+
+                            Navigator.of(context).pop();
+                            Navigator.of(context)
+                                .pushNamed("login_back")
+                                .then((value) {
+                              setSystemChrome(context);
+                            });
+                          } else {
+                            Navigator.of(context).pop();
+                            Navigator.of(context)
+                                .pushNamedAndRemoveUntil("login", (_) => false);
+                          }
+                        })
+                  ],
+                ),
+              );
+              return;
+            }
+
+            // switch user
             restore().then((_) => user.setUser(account.id));
             Navigator.of(context).pop();
           },

From fd9794f3bf75d53b07b5058f02919fc0a08ab364 Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Fri, 16 Aug 2024 00:49:00 +0200
Subject: [PATCH 4/6] changed build number

---
 refilc/pubspec.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/refilc/pubspec.yaml b/refilc/pubspec.yaml
index 72f03dd..fa73090 100644
--- a/refilc/pubspec.yaml
+++ b/refilc/pubspec.yaml
@@ -3,7 +3,7 @@ description: "Egy nem hivatalos e-KRÉTA kliens, diákoktól diákoknak."
 homepage: https://refilc.hu
 publish_to: "none"
 
-version: 5.0.4+271
+version: 5.0.4+272
 
 environment:
   sdk: ">=3.3.2 <=3.4.3"

From 75a2fa372635b9f0f6346a4d03039ee7f9f4c6c6 Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Fri, 16 Aug 2024 11:48:41 +0200
Subject: [PATCH 5/6] changed location of privacy button

---
 .../plus/components/active_sponsor_card.dart  |  2 +-
 .../lib/screens/login/login_screen.dart       | 24 +++++++++----------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/refilc_mobile_ui/lib/plus/components/active_sponsor_card.dart b/refilc_mobile_ui/lib/plus/components/active_sponsor_card.dart
index af904a6..72663df 100644
--- a/refilc_mobile_ui/lib/plus/components/active_sponsor_card.dart
+++ b/refilc_mobile_ui/lib/plus/components/active_sponsor_card.dart
@@ -51,7 +51,7 @@ class ActiveSponsorCard extends StatelessWidget {
       return const SizedBox();
     }
 
-    Color? glow = Colors.white; //TODO: only temp fix kima (idk what but die)
+    Color? glow = Colors.white;
 
     switch (level) {
       case PremiumFeatureLevel.cap:
diff --git a/refilc_mobile_ui/lib/screens/login/login_screen.dart b/refilc_mobile_ui/lib/screens/login/login_screen.dart
index e574253..328f5f9 100644
--- a/refilc_mobile_ui/lib/screens/login/login_screen.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_screen.dart
@@ -293,6 +293,18 @@ class LoginScreenState extends State<LoginScreen> {
                                 ),
                               ),
                               const SizedBox(height: 8),
+                              // privacy policy
+                              GestureDetector(
+                                onTap: () => PrivacyView.show(context),
+                                child: Text(
+                                  'privacy'.i18n,
+                                  style: TextStyle(
+                                    color: AppColors.of(context).loginSecondary,
+                                    fontWeight: FontWeight.w500,
+                                    fontSize: 14.0,
+                                  ),
+                                ),
+                              ),
                             ],
                           ),
                         ),
@@ -320,18 +332,6 @@ class LoginScreenState extends State<LoginScreen> {
                         textAlign: TextAlign.center,
                       ),
                     ),
-                  // privacy policy
-                  GestureDetector(
-                    onTap: () => PrivacyView.show(context),
-                    child: Text(
-                      'privacy'.i18n,
-                      style: TextStyle(
-                        color: AppColors.of(context).loginSecondary,
-                        fontWeight: FontWeight.w500,
-                        fontSize: 14.0,
-                      ),
-                    ),
-                  ),
                 ],
               ),
             ),

From 52b9b4f5db9f4b84c57f13c7d3484eba8b04e370 Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Fri, 16 Aug 2024 14:40:48 +0200
Subject: [PATCH 6/6] maybe fixed ios login

---
 refilc_mobile_ui/lib/screens/login/kreten_login.dart | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/refilc_mobile_ui/lib/screens/login/kreten_login.dart b/refilc_mobile_ui/lib/screens/login/kreten_login.dart
index 8396f8c..95feb83 100644
--- a/refilc_mobile_ui/lib/screens/login/kreten_login.dart
+++ b/refilc_mobile_ui/lib/screens/login/kreten_login.dart
@@ -24,6 +24,14 @@ class _KretenLoginScreenState extends State<KretenLoginScreen> {
     controller = WebViewController()
       ..setJavaScriptMode(JavaScriptMode.unrestricted)
       ..setNavigationDelegate(NavigationDelegate(
+        onNavigationRequest: (n) async {
+          if (n.url.startsWith('https://mobil.e-kreta.hu') ||
+              n.url.startsWith('https://idp.e-kreta.hu')) {
+            return NavigationDecision.navigate;
+          } else {
+            return NavigationDecision.prevent;
+          }
+        },
         onPageStarted: (url) async {
           setState(() {
             loadingPercentage = 0;