diff --git a/filcnaplo/lib/api/client.dart b/filcnaplo/lib/api/client.dart
index bf290be..0a78545 100644
--- a/filcnaplo/lib/api/client.dart
+++ b/filcnaplo/lib/api/client.dart
@@ -53,9 +53,14 @@ class FilcAPI {
             .map((json) => School.fromJson(json))
             .toList();
         schools.add(School(
-          city: "Tiszabura",
-          instituteCode: "supporttest-reni-tiszabura-teszt01",
-          name: "FILC Éles Reni tiszabura-teszt",
+          city: "Stockholm",
+          instituteCode: "refilc-test-sweden",
+          name: "reFilc Test SE - Leo Ekström High School",
+        ));
+        schools.add(School(
+          city: "Madrid",
+          instituteCode: "refilc-test-spain",
+          name: "reFilc Test ES - Emilio Obrero University",
         ));
         return schools;
       } else {
diff --git a/filcnaplo/lib/api/login.dart b/filcnaplo/lib/api/login.dart
index 4afc7ce..f0834c8 100644
--- a/filcnaplo/lib/api/login.dart
+++ b/filcnaplo/lib/api/login.dart
@@ -1,6 +1,7 @@
 // ignore_for_file: avoid_print, use_build_context_synchronously
 
 import 'package:filcnaplo/utils/jwt.dart';
+import 'package:filcnaplo_kreta_api/models/school.dart';
 import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
 import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
 import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
@@ -20,6 +21,7 @@ import 'package:filcnaplo_kreta_api/models/week.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 import 'package:filcnaplo/api/nonce.dart';
+import 'package:uuid/uuid.dart';
 
 enum LoginState {
   missingFields,
@@ -47,87 +49,141 @@ Future loginAPI({
   void Function(User)? onLogin,
   void Function()? onSuccess,
 }) async {
-  Provider.of<KretaClient>(context, listen: false).userAgent =
-      Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
+  Future testLogin(School school) async {
+    var user = User(
+      username: username,
+      password: password,
+      instituteCode: instituteCode,
+      name: 'Teszt Lajos',
+      student: Student(
+        birth: DateTime.now(),
+        id: const Uuid().v4(),
+        name: 'Teszt Lajos',
+        school: school,
+        yearId: '1',
+        parents: ['Teszt András', 'Teszt Linda'],
+        json: {"a": "b"},
+        address: '1117 Budapest, Gábor Dénes utca 4.',
+      ),
+      role: Role.parent,
+    );
 
-  Map<String, String> headers = {
-    "content-type": "application/x-www-form-urlencoded",
-  };
+    if (onLogin != null) onLogin(user);
 
-  String nonceStr = await Provider.of<KretaClient>(context, listen: false)
-      .getAPI(KretaAPI.nonce, json: false);
+    // store test user in db
+    await Provider.of<DatabaseProvider>(context, listen: false)
+        .store
+        .storeUser(user);
+    Provider.of<UserProvider>(context, listen: false).addUser(user);
+    Provider.of<UserProvider>(context, listen: false).setUser(user.id);
 
-  Nonce nonce = getNonce(nonceStr, username, instituteCode);
-  headers.addAll(nonce.header());
+    if (onSuccess != null) onSuccess();
 
-  Map? res = await Provider.of<KretaClient>(context, listen: false)
-      .postAPI(KretaAPI.login,
-          headers: headers,
-          body: User.loginBody(
-            username: username,
-            password: password,
-            instituteCode: instituteCode,
-          ));
-  if (res != null) {
-    if (res.containsKey("error")) {
-      if (res["error"] == "invalid_grant") {
-        return LoginState.invalidGrant;
-      }
-    } else {
-      if (res.containsKey("access_token")) {
-        try {
-          Provider.of<KretaClient>(context, listen: false).accessToken =
-              res["access_token"];
-          Map? studentJson =
-              await Provider.of<KretaClient>(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"])!,
-          );
+    return LoginState.success;
+  }
 
-          if (onLogin != null) onLogin(user);
+  // if institute matches one of test things do test login
+  if (instituteCode == 'refilc-test-sweden') {
+    School school = School(
+      city: "Stockholm",
+      instituteCode: "refilc-test-sweden",
+      name: "reFilc Test SE - Leo Ekström High School",
+    );
 
-          // Store User in the database
-          await Provider.of<DatabaseProvider>(context, listen: false)
-              .store
-              .storeUser(user);
-          Provider.of<UserProvider>(context, listen: false).addUser(user);
-          Provider.of<UserProvider>(context, listen: false).setUser(user.id);
+    await testLogin(school);
+  } else if (instituteCode == 'refilc-test-spain') {
+    School school = School(
+      city: "Madrid",
+      instituteCode: "refilc-test-spain",
+      name: "reFilc Test ES - Emilio Obrero University",
+    );
 
-          // Get user data
+    await testLogin(school);
+  } else {
+    // normal login from here
+    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",
+    };
+
+    String nonceStr = await Provider.of<KretaClient>(context, listen: false)
+        .getAPI(KretaAPI.nonce, json: false);
+
+    Nonce nonce = getNonce(nonceStr, username, instituteCode);
+    headers.addAll(nonce.header());
+
+    Map? res = await Provider.of<KretaClient>(context, listen: false)
+        .postAPI(KretaAPI.login,
+            headers: headers,
+            body: User.loginBody(
+              username: username,
+              password: password,
+              instituteCode: instituteCode,
+            ));
+    if (res != null) {
+      if (res.containsKey("error")) {
+        if (res["error"] == "invalid_grant") {
+          return LoginState.invalidGrant;
+        }
+      } else {
+        if (res.containsKey("access_token")) {
           try {
-            await Future.wait([
-              Provider.of<GradeProvider>(context, listen: false).fetch(),
-              Provider.of<TimetableProvider>(context, listen: false)
-                  .fetch(week: Week.current()),
-              Provider.of<ExamProvider>(context, listen: false).fetch(),
-              Provider.of<HomeworkProvider>(context, listen: false).fetch(),
-              Provider.of<MessageProvider>(context, listen: false).fetchAll(),
-              Provider.of<NoteProvider>(context, listen: false).fetch(),
-              Provider.of<EventProvider>(context, listen: false).fetch(),
-              Provider.of<AbsenceProvider>(context, listen: false).fetch(),
-            ]);
+            Provider.of<KretaClient>(context, listen: false).accessToken =
+                res["access_token"];
+            Map? studentJson =
+                await Provider.of<KretaClient>(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<DatabaseProvider>(context, listen: false)
+                .store
+                .storeUser(user);
+            Provider.of<UserProvider>(context, listen: false).addUser(user);
+            Provider.of<UserProvider>(context, listen: false).setUser(user.id);
+
+            // Get user data
+            try {
+              await Future.wait([
+                Provider.of<GradeProvider>(context, listen: false).fetch(),
+                Provider.of<TimetableProvider>(context, listen: false)
+                    .fetch(week: Week.current()),
+                Provider.of<ExamProvider>(context, listen: false).fetch(),
+                Provider.of<HomeworkProvider>(context, listen: false).fetch(),
+                Provider.of<MessageProvider>(context, listen: false).fetchAll(),
+                Provider.of<NoteProvider>(context, listen: false).fetch(),
+                Provider.of<EventProvider>(context, listen: false).fetch(),
+                Provider.of<AbsenceProvider>(context, listen: false).fetch(),
+              ]);
+            } catch (error) {
+              print("WARNING: failed to fetch user data: $error");
+            }
+
+            if (onSuccess != null) onSuccess();
+
+            return LoginState.success;
           } catch (error) {
-            print("WARNING: failed to fetch user data: $error");
+            print("ERROR: loginAPI: $error");
+            // maybe check debug mode
+            // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
+            return LoginState.failed;
           }
-
-          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/filcnaplo/lib/api/providers/status_provider.dart b/filcnaplo/lib/api/providers/status_provider.dart
index 5822366..a556a40 100644
--- a/filcnaplo/lib/api/providers/status_provider.dart
+++ b/filcnaplo/lib/api/providers/status_provider.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
 import 'package:connectivity_plus/connectivity_plus.dart';
 import 'package:flutter/widgets.dart';
 import 'package:http/http.dart' as http;
@@ -12,6 +14,7 @@ class StatusProvider extends ChangeNotifier {
 
   StatusProvider() {
     _handleNetworkChanges();
+    _handleDNSFailure();
     Connectivity().checkConnectivity().then((value) => _networkType = value);
   }
 
@@ -24,6 +27,7 @@ class StatusProvider extends ChangeNotifier {
       _networkType = event;
       if (event == ConnectivityResult.none) {
         if (!_stack.contains(Status.network)) {
+          _stack.remove(Status.apiError);
           _stack.insert(0, Status.network);
           notifyListeners();
         }
@@ -36,6 +40,31 @@ class StatusProvider extends ChangeNotifier {
     });
   }
 
+  void _handleDNSFailure() {
+    try {
+      InternetAddress.lookup('api.refilc.hu').then((status) {
+        if (status.isEmpty) {
+          if (!_stack.contains(Status.network)) {
+            _stack.remove(Status.apiError);
+            _stack.insert(0, Status.network);
+            notifyListeners();
+          }
+        } else {
+          if (_stack.contains(Status.network)) {
+            _stack.remove(Status.network);
+            notifyListeners();
+          }
+        }
+      });
+    } on SocketException catch (_) {
+      if (!_stack.contains(Status.network)) {
+        _stack.remove(Status.apiError);
+        _stack.insert(0, Status.network);
+        notifyListeners();
+      }
+    }
+  }
+
   void triggerRequest(http.Response res) {
     if (res.headers.containsKey("x-maintenance-mode") ||
         res.statusCode == 503) {
@@ -50,6 +79,7 @@ class StatusProvider extends ChangeNotifier {
       }
     }
 
+    if (_stack.contains(Status.network)) return;
     if (res.body == "invalid_grant" ||
         res.body.replaceAll(' ', '') == '' ||
         res.statusCode == 400) {
diff --git a/filcnaplo/lib/database/init.dart b/filcnaplo/lib/database/init.dart
index 4f7d1ed..274dbce 100644
--- a/filcnaplo/lib/database/init.dart
+++ b/filcnaplo/lib/database/init.dart
@@ -33,6 +33,7 @@ const settingsDB = DatabaseStruct("settings", {
   "renamed_subjects_italics": int, "renamed_teachers_enabled": int,
   "renamed_teachers_italics": int,
   "live_activity_color": String,
+  "welcome_message": String,
 });
 // DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
 // YOU'VE BEEN WARNED!!!
diff --git a/filcnaplo/lib/models/ad.dart b/filcnaplo/lib/models/ad.dart
index dcc4b0c..09eba03 100644
--- a/filcnaplo/lib/models/ad.dart
+++ b/filcnaplo/lib/models/ad.dart
@@ -20,7 +20,6 @@ class Ad {
   });
 
   factory Ad.fromJson(Map json) {
-    print(json);
     return Ad(
       title: json['title'] ?? 'Ad',
       description: json['description'] ?? '',
diff --git a/filcnaplo/lib/models/settings.dart b/filcnaplo/lib/models/settings.dart
index 3e42b26..05989b6 100644
--- a/filcnaplo/lib/models/settings.dart
+++ b/filcnaplo/lib/models/settings.dart
@@ -76,6 +76,7 @@ class SettingsProvider extends ChangeNotifier {
   bool _renamedTeachersEnabled;
   bool _renamedTeachersItalics;
   Color _liveActivityColor;
+  String _welcomeMessage;
 
   SettingsProvider({
     DatabaseProvider? database,
@@ -120,6 +121,7 @@ class SettingsProvider extends ChangeNotifier {
     required bool renameTeachersEnabled,
     required bool renameTeachersItalics,
     required Color liveActivityColor,
+    required String welcomeMessage,
   })  : _database = database,
         _language = language,
         _startPage = startPage,
@@ -161,7 +163,8 @@ class SettingsProvider extends ChangeNotifier {
         _renamedSubjectsItalics = renameSubjectsItalics,
         _renamedTeachersEnabled = renameTeachersEnabled,
         _renamedTeachersItalics = renameTeachersItalics,
-        _liveActivityColor = liveActivityColor;
+        _liveActivityColor = liveActivityColor,
+        _welcomeMessage = welcomeMessage;
 
   factory SettingsProvider.fromMap(Map map,
       {required DatabaseProvider database}) {
@@ -223,6 +226,7 @@ class SettingsProvider extends ChangeNotifier {
       renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
       renameTeachersItalics: map["renamed_teachers_italics"] == 1,
       liveActivityColor: Color(map["live_activity_color"]),
+      welcomeMessage: map["welcome_message"],
     );
   }
 
@@ -272,6 +276,7 @@ class SettingsProvider extends ChangeNotifier {
       "renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
       "renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
       "live_activity_color": _liveActivityColor.value,
+      "welcome_message": _welcomeMessage,
     };
   }
 
@@ -325,6 +330,7 @@ class SettingsProvider extends ChangeNotifier {
       renameTeachersEnabled: false,
       renameTeachersItalics: false,
       liveActivityColor: const Color(0xFF676767),
+      welcomeMessage: '',
     );
   }
 
@@ -373,6 +379,7 @@ class SettingsProvider extends ChangeNotifier {
   bool get renamedTeachersEnabled => _renamedTeachersEnabled;
   bool get renamedTeachersItalics => _renamedTeachersItalics;
   Color get liveActivityColor => _liveActivityColor;
+  String get welcomeMessage => _welcomeMessage;
 
   Future<void> update({
     bool store = true,
@@ -417,6 +424,7 @@ class SettingsProvider extends ChangeNotifier {
     bool? renamedTeachersEnabled,
     bool? renamedTeachersItalics,
     Color? liveActivityColor,
+    String? welcomeMessage,
   }) async {
     if (language != null && language != _language) _language = language;
     if (startPage != null && startPage != _startPage) _startPage = startPage;
@@ -535,6 +543,9 @@ class SettingsProvider extends ChangeNotifier {
     if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
       _liveActivityColor = liveActivityColor;
     }
+    if (welcomeMessage != null && welcomeMessage != _welcomeMessage) {
+      _welcomeMessage = welcomeMessage;
+    }
     if (store) await _database?.store.storeSettings(this);
     notifyListeners();
   }
diff --git a/filcnaplo/lib/models/user.dart b/filcnaplo/lib/models/user.dart
index 2cf88e2..9de5718 100644
--- a/filcnaplo/lib/models/user.dart
+++ b/filcnaplo/lib/models/user.dart
@@ -93,4 +93,13 @@ class User {
       "refresh_user_data": "false",
     };
   }
+
+  static Map<String, Object?> logoutBody({
+    required String refreshToken,
+  }) {
+    return {
+      "refresh_token": refreshToken,
+      "client_id": KretaAPI.clientId,
+    };
+  }
 }
diff --git a/filcnaplo/pubspec.yaml b/filcnaplo/pubspec.yaml
index f56bc27..d6d03a7 100644
--- a/filcnaplo/pubspec.yaml
+++ b/filcnaplo/pubspec.yaml
@@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
 homepage: https://refilc.hu
 publish_to: "none"
 
-version: 4.2.3+223
+version: 4.2.4+224
 
 environment:
   sdk: ">=2.17.0 <3.0.0"
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart b/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
index 1c0f5fa..5421f06 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
+++ b/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
@@ -176,13 +176,16 @@ class _SidebarState extends State<Sidebar> {
           String? userId = user.id;
           if (userId == null) return;
 
-          // Delete User
+          // revoke refresh token
+          await Provider.of<KretaClient>(context, listen: false).logout();
+
+          // delete user from app
           user.removeUser(userId);
           await Provider.of<DatabaseProvider>(context, listen: false)
               .store
               .removeUser(userId);
 
-          // If no other Users left, go back to LoginScreen
+          // if no other users left, go back to login screen
           if (user.getUsers().isNotEmpty) {
             user.setUser(user.getUsers().first.id);
             restore().then((_) => user.setUser(user.getUsers().first.id));
diff --git a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart b/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
index 530a2bf..fb5102f 100644
--- a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
+++ b/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
@@ -5,7 +5,7 @@ extension SettingsLocalization on String {
       {
         "en_en": {
           "personal_details": "Personal Details",
-          "open_dkt": "Open DKT",
+          "open_dkt": "Open DCS",
           "edit_nickname": "Edit Nickname",
           "edit_profile_picture": "Edit Profile Picture",
           "remove_profile_picture": "Remove Profile Picture",
@@ -39,7 +39,8 @@ extension SettingsLocalization on String {
           "done": "Done",
           "reset": "Reset",
           "open": "Open",
-          "data_collected": "Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
+          "data_collected":
+              "Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
           "Analytics": "Analytics",
           "Anonymous Usage Analytics": "Anonymous Usage Analytics",
           "graph_class_avg": "Class average on graph",
@@ -98,7 +99,8 @@ extension SettingsLocalization on String {
           "done": "Kész",
           "reset": "Visszaállítás",
           "open": "Megnyitás",
-          "data_collected": "Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
+          "data_collected":
+              "Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
           "Analytics": "Analitika",
           "Anonymous Usage Analytics": "Névtelen használati analitika",
           "graph_class_avg": "Osztályátlag a grafikonon",
@@ -123,7 +125,7 @@ extension SettingsLocalization on String {
         },
         "de_de": {
           "personal_details": "Persönliche Angaben",
-          "open_dkt": "Öffnen DKT",
+          "open_dkt": "Öffnen RDZ",
           "edit_nickname": "Spitznamen bearbeiten",
           "edit_profile_picture": "Profilbild bearbeiten",
           "remove_profile_picture": "Profilbild entfernen",
@@ -157,7 +159,8 @@ extension SettingsLocalization on String {
           "done": "Fertig",
           "reset": "Zurücksetzen",
           "open": "Öffnen",
-          "data_collected": "Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
+          "data_collected":
+              "Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
           "Analytics": "Analytik",
           "Anonymous Usage Analytics": "Anonyme Nutzungsanalyse",
           "graph_class_avg": "Klassendurchschnitt in der Grafik",
diff --git a/filcnaplo_kreta_api/lib/client/api.dart b/filcnaplo_kreta_api/lib/client/api.dart
index f3c18d0..4c2f775 100644
--- a/filcnaplo_kreta_api/lib/client/api.dart
+++ b/filcnaplo_kreta_api/lib/client/api.dart
@@ -3,6 +3,7 @@ import 'package:intl/intl.dart';
 class KretaAPI {
   // IDP API
   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";
 
@@ -86,6 +87,7 @@ class BaseKreta {
 
 class KretaApiEndpoints {
   static const token = "/connect/token";
+  static const revoke = "/connect/revocation";
   static const nonce = "/nonce";
   static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
   static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
diff --git a/filcnaplo_kreta_api/lib/client/client.dart b/filcnaplo_kreta_api/lib/client/client.dart
index f150e3b..d4ed845 100644
--- a/filcnaplo_kreta_api/lib/client/client.dart
+++ b/filcnaplo_kreta_api/lib/client/client.dart
@@ -26,6 +26,8 @@ class KretaClient {
   late final UserProvider _user;
   late final StatusProvider _status;
 
+  bool _loginRefreshing = false;
+
   KretaClient({
     this.accessToken,
     required SettingsProvider settings,
@@ -164,6 +166,9 @@ class KretaClient {
   }
 
   Future<void> refreshLogin() async {
+    if (_loginRefreshing) return;
+    _loginRefreshing = true;
+
     User? loginUser = _user.user;
     if (loginUser == null) return;
 
@@ -182,13 +187,15 @@ class KretaClient {
       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,
-        ));
+    Map? loginRes = await postAPI(
+      KretaAPI.login,
+      headers: headers,
+      body: User.loginBody(
+        username: loginUser.username,
+        password: loginUser.password,
+        instituteCode: loginUser.instituteCode,
+      ),
+    );
 
     if (loginRes != null) {
       if (loginRes.containsKey("access_token")) {
@@ -215,5 +222,25 @@ class KretaClient {
         }
       }
     }
+
+    _loginRefreshing = false;
+  }
+
+  Future<void> logout() async {
+    User? loginUser = _user.user;
+    if (loginUser == null) return;
+
+    Map<String, String> headers = {
+      "content-type": "application/x-www-form-urlencoded",
+    };
+
+    await postAPI(
+      KretaAPI.logout,
+      headers: headers,
+      body: User.logoutBody(
+        refreshToken: refreshToken!,
+      ),
+      json: false,
+    );
   }
 }
diff --git a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
index 1b9a3ef..b7d235f 100644
--- a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
+++ b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
@@ -5,7 +5,7 @@ import 'package:filcnaplo_kreta_api/client/api.dart';
 import 'package:filcnaplo_kreta_api/client/client.dart';
 import 'package:filcnaplo_kreta_api/models/lesson.dart';
 import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:flutter/material.dart';
+import 'package:flutter/foundation.dart';
 
 class TimetableProvider with ChangeNotifier {
   Map<Week, List<Lesson>> lessons = {};
@@ -69,14 +69,14 @@ class TimetableProvider with ChangeNotifier {
         .getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
 
     if (lessonsJson == null) {
+      if (kDebugMode) print('Cannot fetch Lessons for User ${user.id}');
+
       return;
       // throw "Cannot fetch Lessons for User ${user.id}";
     } else {
       List<Lesson> lessonsList =
           lessonsJson.map((e) => Lesson.fromJson(e)).toList();
 
-      if (lessons.isEmpty) return;
-
       lessons[week] = lessonsList;
 
       await store();
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart b/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart
index 12add1b..fb9c943 100644
--- a/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart
+++ b/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart
@@ -13,9 +13,6 @@ class AdTile extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    print('geic');
-    print(ad);
-
     return Padding(
       padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
       child: PanelButton(
@@ -38,12 +35,15 @@ class AdTile extends StatelessWidget {
           ],
         ),
         leading: ad.logoUrl != null
-            ? Image.network(
-                ad.logoUrl.toString(),
-                errorBuilder: (context, error, stackTrace) {
-                  ad.logoUrl = null;
-                  return const SizedBox();
-                },
+            ? ClipRRect(
+                borderRadius: BorderRadius.circular(50.0),
+                child: Image.network(
+                  ad.logoUrl.toString(),
+                  errorBuilder: (context, error, stackTrace) {
+                    ad.logoUrl = null;
+                    return const SizedBox();
+                  },
+                ),
               )
             : null,
         trailing: const Icon(FeatherIcons.externalLink),
diff --git a/filcnaplo_mobile_ui/lib/pages/home/home_page.dart b/filcnaplo_mobile_ui/lib/pages/home/home_page.dart
index 02298d7..158472c 100755
--- a/filcnaplo_mobile_ui/lib/pages/home/home_page.dart
+++ b/filcnaplo_mobile_ui/lib/pages/home/home_page.dart
@@ -30,6 +30,7 @@ import 'package:provider/provider.dart';
 import 'home_page.i18n.dart';
 import 'package:filcnaplo/ui/filter/widgets.dart';
 import 'package:filcnaplo/ui/filter/sort.dart';
+import 'package:i18n_extension/i18n_extension.dart';
 
 class HomePage extends StatefulWidget {
   const HomePage({Key? key}) : super(key: key);
@@ -94,6 +95,13 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
 
   void setGreeting() {
     DateTime now = DateTime.now();
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    if (!settings.presentationMode) {
+      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+    } else {
+      firstName = "János";
+    }
+
     if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
         now.isAfter(DateTime(now.year, DateTime.june, 14))) {
       greeting = "goodrest";
@@ -104,16 +112,16 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
         Future.delayed(const Duration(seconds: 1))
             .then((value) => mounted ? _confettiController?.play() : null);
       }
-    } else if (now.month == user.student?.birth.month &&
-        now.day == user.student?.birth.day) {
-      greeting = "happybirthday";
+      // } else if (now.month == user.student?.birth.month &&
+      //     now.day == user.student?.birth.day) {
+      //   greeting = "happybirthday";
 
-      if (NavigationScreen.of(context)?.init("confetti") ?? false) {
-        _confettiController =
-            ConfettiController(duration: const Duration(seconds: 3));
-        Future.delayed(const Duration(seconds: 1))
-            .then((value) => mounted ? _confettiController?.play() : null);
-      }
+      //   if (NavigationScreen.of(context)?.init("confetti") ?? false) {
+      //     _confettiController =
+      //         ConfettiController(duration: const Duration(seconds: 3));
+      //     Future.delayed(const Duration(seconds: 1))
+      //         .then((value) => mounted ? _confettiController?.play() : null);
+      //   }
     } else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) &&
         now.isBefore(DateTime(now.year, DateTime.may, 30))) {
       greeting = "refilcopen";
@@ -130,6 +138,12 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
       greeting = "merryxmas";
     } else if (now.month == DateTime.january && now.day == 1) {
       greeting = "happynewyear";
+    } else if (settings.welcomeMessage.replaceAll(' ', '') != '') {
+      greeting = settings.welcomeMessage;
+      greeting = localizeFill(
+        settings.welcomeMessage,
+        [firstName],
+      );
     } else if (now.hour >= 18) {
       greeting = "goodevening";
     } else if (now.hour >= 10) {
@@ -155,13 +169,6 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
 
     setGreeting();
 
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    if (!settings.presentationMode) {
-      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-    } else {
-      firstName = "János";
-    }
-
     return Scaffold(
       body: Stack(
         children: [
diff --git a/filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart b/filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart
index 6e24d7c..c73dff0 100755
--- a/filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart
+++ b/filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart
@@ -13,7 +13,8 @@ extension Localization on String {
           "welcome": "Welcome, %s!",
           "missing_fields": "Missing Fields!",
           "invalid_grant":
-              "Invalid Username/Password! (Try adding spaces after Username)",
+              // "Invalid Username/Password! (Try adding spaces after Username)",
+              "Invalid Username/Password!",
           "error": "Failed to log in.",
           "schools_error": "Failed to get schools."
         },
@@ -27,7 +28,8 @@ extension Localization on String {
           "welcome": "Üdv, %s!",
           "missing_fields": "Hiányzó adatok!",
           "invalid_grant":
-              "Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
+              // "Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
+              "Helytelen Felhasználónév/Jelszó!",
           "error": "Sikertelen bejelentkezés.",
           "schools_error": "Nem sikerült lekérni az iskolákat."
         },
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart
index 6a6339c..8d1df64 100755
--- a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart
+++ b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart
@@ -43,6 +43,7 @@ import 'package:filcnaplo_premium/ui/mobile/settings/profile_pic.dart';
 import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
 import 'package:filcnaplo_premium/ui/mobile/settings/modify_subject_names.dart';
 import 'package:filcnaplo_premium/ui/mobile/settings/modify_teacher_names.dart';
+import 'package:filcnaplo_premium/ui/mobile/settings/welcome_message.dart';
 
 class SettingsScreen extends StatefulWidget {
   const SettingsScreen({Key? key}) : super(key: key);
@@ -206,7 +207,7 @@ class _SettingsScreenState extends State<SettingsScreen>
         opacity: 1 - _hideContainersController.value,
         child: Column(
           children: [
-            const SizedBox(height: 32.0),
+            const SizedBox(height: 45.0),
 
             Row(
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -454,6 +455,7 @@ class _SettingsScreenState extends State<SettingsScreen>
                     Material(
                         type: MaterialType.transparency,
                         child: MenuNotifications(settings: settings)),
+                    WelcomeMessagePanelButton(settings, user),
                   ],
                 ),
               ),
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
index 3ff52aa..d6c242d 100755
--- a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
+++ b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
@@ -73,6 +73,9 @@ extension SettingsLocalization on String {
           "devsettings": "Developer Settings",
           "devmode": "Developer Mode",
           "copy_jwt": "Copy JWT",
+          "welcome_msg": "Welcome Message",
+          "default": "Default",
+          "edit_welcome_msg": "Edit welcome message",
         },
         "hu_hu": {
           "personal_details": "Személyes információk",
@@ -144,6 +147,9 @@ extension SettingsLocalization on String {
           "devsettings": "Fejlesztői Beállítások",
           "devmode": "Fejlesztői mód",
           "copy_jwt": "JWT másolása",
+          "welcome_msg": "Üdvözlő üzenet",
+          "default": "Alapértelmezett",
+          "edit_welcome_msg": "Üdvözlő üzenet szerkesztése",
         },
         "de_de": {
           "personal_details": "Persönliche Angaben",
@@ -214,6 +220,9 @@ extension SettingsLocalization on String {
           "devsettings": "Entwickleroptionen",
           "devmode": "Entwicklermodus",
           "copy_jwt": "JWT kopieren",
+          "welcome_msg": "Willkommensnachricht",
+          "default": "Standard",
+          "edit_welcome_msg": "Begrüßungsnachricht bearbeiten",
         },
       };
 
diff --git a/filcnaplo_premium/lib/api/auth.dart b/filcnaplo_premium/lib/api/auth.dart
index 3408919..45ddf5c 100644
--- a/filcnaplo_premium/lib/api/auth.dart
+++ b/filcnaplo_premium/lib/api/auth.dart
@@ -82,12 +82,12 @@ class PremiumAuth {
     //}
 
     // Skip premium check when disconnected
-    //try {
+    // try {
     //  final status = await InternetAddress.lookup('github.com');
     //  if (status.isEmpty) return false;
-    //} on SocketException catch (_) {
+    // } on SocketException catch (_) {
     //  return false;
-    //}
+    // }
 
     //for (int tries = 0; tries < 3; tries++) {
     //  try {
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/theme.dart b/filcnaplo_premium/lib/ui/mobile/settings/theme.dart
index 33cff7a..bcd0468 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/theme.dart
+++ b/filcnaplo_premium/lib/ui/mobile/settings/theme.dart
@@ -8,6 +8,7 @@ import 'package:filcnaplo/ui/widgets/message/message_tile.dart';
 import 'package:filcnaplo_kreta_api/models/grade.dart';
 import 'package:filcnaplo_kreta_api/models/homework.dart';
 import 'package:filcnaplo_kreta_api/models/message.dart';
+import 'package:filcnaplo_mobile_ui/common/action_button.dart';
 import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
 import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
 import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
@@ -268,10 +269,32 @@ class _PremiumCustomAccentColorSettingState
                           //     ),
                           //   ),
                           // );
-                          SharedTheme theme =
-                              await shareProvider.shareCurrentTheme(context);
-                          Share.share(theme.id,
-                              subject: 'reFilc Téma / reFilc Theme');
+                          showDialog(
+                            context: context,
+                            builder: (context) => WillPopScope(
+                              onWillPop: () async => false,
+                              child: AlertDialog(
+                                shape: RoundedRectangleBorder(
+                                    borderRadius: BorderRadius.circular(12.0)),
+                                title: Text("attention".i18n),
+                                content: Text("share_disclaimer".i18n),
+                                actions: [
+                                  ActionButton(
+                                    label: "understand".i18n,
+                                    onTap: () async {
+                                      Navigator.of(context).pop();
+                                      SharedTheme theme = await shareProvider
+                                          .shareCurrentTheme(context);
+                                      Share.share(
+                                        theme.id,
+                                        subject: 'share_subj_theme'.i18n,
+                                      );
+                                    },
+                                  ),
+                                ],
+                              ),
+                            ),
+                          );
                         },
                         icon: const Icon(
                           FeatherIcons.share2,
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart b/filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart
index 40ac863..f578ff3 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart
+++ b/filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart
@@ -14,6 +14,10 @@ extension SettingsLocalization on String {
           "enter_id": "Enter ID",
           "theme_id": "Theme ID...",
           "theme_not_found": "Theme not found!",
+          "attention": "Attention!",
+          "share_disclaimer":
+              "By sharing the theme, you agree that the nickname you set and all settings of the theme will be shared publicly.",
+          "understand": "I understand",
         },
         "hu_hu": {
           "theme_prev": "Előnézet",
@@ -26,6 +30,10 @@ extension SettingsLocalization on String {
           "enter_id": "ID megadása",
           "theme_id": "Téma azonosító...",
           "theme_not_found": "A téma nem található!",
+          "attention": "Figyelem!",
+          "share_disclaimer":
+              "A téma megosztásával elfogadod, hogy az általad beállított becenév és a téma minden beállítása nyilvánosan megosztásra kerüljön.",
+          "understand": "Értem",
         },
         "de_de": {
           "theme_prev": "Vorschau",
@@ -39,6 +47,10 @@ extension SettingsLocalization on String {
           "enter_id": "Geben Sie die ID ein",
           "theme_id": "Themen-ID...",
           "theme_not_found": "Thema nicht gefunden!",
+          "attention": "Achtung!",
+          "share_disclaimer":
+              "Durch das Teilen des Themes erklären Sie sich damit einverstanden, dass der von Ihnen festgelegte Spitzname und alle Einstellungen des Themes öffentlich geteilt werden.",
+          "understand": "Ich verstehe",
         },
       };
 
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart b/filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart
new file mode 100644
index 0000000..5e412f9
--- /dev/null
+++ b/filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart
@@ -0,0 +1,142 @@
+import 'package:filcnaplo/api/providers/user_provider.dart';
+import 'package:filcnaplo/models/settings.dart';
+import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
+import 'package:filcnaplo_premium/models/premium_scopes.dart';
+import 'package:filcnaplo_premium/providers/premium_provider.dart';
+import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
+import 'package:provider/provider.dart';
+import 'package:i18n_extension/i18n_extension.dart';
+
+// ignore: must_be_immutable
+class WelcomeMessagePanelButton extends StatelessWidget {
+  late SettingsProvider settingsProvider;
+  late UserProvider user;
+
+  WelcomeMessagePanelButton(this.settingsProvider, this.user, {Key? key})
+      : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    String finalName = ((user.nickname ?? '') != ''
+            ? user.nickname
+            : (user.displayName ?? '') != ''
+                ? user.displayName
+                : 'János') ??
+        'János';
+
+    return PanelButton(
+      onPressed: () {
+        if (!Provider.of<PremiumProvider>(context, listen: false)
+            .hasScope(PremiumScopes.all)) {
+          PremiumLockedFeatureUpsell.show(
+              context: context, feature: PremiumFeature.profile);
+          return;
+        }
+        showDialog(
+            context: context,
+            builder: (context) => WelcomeMessageEditor(settingsProvider));
+      },
+      title: Text("welcome_msg".i18n),
+      leading: const Icon(FeatherIcons.smile),
+      trailing: SizedBox(
+        width: 100,
+        child: Expanded(
+          child: Text(
+            settingsProvider.welcomeMessage.replaceAll(' ', '') != ''
+                ? localizeFill(
+                    settingsProvider.welcomeMessage,
+                    [finalName],
+                  )
+                : 'default'.i18n,
+            style: const TextStyle(fontSize: 14.0),
+            textAlign: TextAlign.end,
+            softWrap: true,
+            overflow: TextOverflow.ellipsis,
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+// ignore: must_be_immutable
+class WelcomeMessageEditor extends StatefulWidget {
+  late SettingsProvider settingsProvider;
+
+  WelcomeMessageEditor(this.settingsProvider, {Key? key}) : super(key: key);
+
+  @override
+  State<WelcomeMessageEditor> createState() => _WelcomeMessageEditorState();
+}
+
+class _WelcomeMessageEditorState extends State<WelcomeMessageEditor> {
+  final _welcomeMsg = TextEditingController();
+
+  @override
+  void initState() {
+    super.initState();
+    _welcomeMsg.text =
+        widget.settingsProvider.welcomeMessage.replaceAll('%s', '%name%');
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return AlertDialog(
+      title: Text("edit_welcome_msg".i18n),
+      content: TextField(
+        controller: _welcomeMsg,
+        autofocus: true,
+        decoration: InputDecoration(
+          border: const OutlineInputBorder(),
+          label: Text('welcome_msg'.i18n),
+          suffixIcon: IconButton(
+            icon: const Icon(FeatherIcons.x),
+            onPressed: () {
+              setState(() {
+                _welcomeMsg.text = "";
+              });
+            },
+          ),
+        ),
+      ),
+      actions: [
+        TextButton(
+          child: Text(
+            "cancel".i18n,
+            style: const TextStyle(fontWeight: FontWeight.w500),
+          ),
+          onPressed: () {
+            Navigator.of(context).maybePop();
+          },
+        ),
+        TextButton(
+          child: Text(
+            "done".i18n,
+            style: const TextStyle(fontWeight: FontWeight.w500),
+          ),
+          onPressed: () {
+            // var trimmed = _welcomeMsg.text.trim();
+
+            // var defLen = trimmed.length;
+            // var replacedLen = trimmed.replaceAll('%s', '').length;
+
+            // if (defLen - 2 > replacedLen) {
+            //   print('fuck yourself rn');
+            // }
+            var finalText = _welcomeMsg.text
+                .trim()
+                .replaceAll('%s', '')
+                .replaceFirst('%name%', '%s');
+
+            widget.settingsProvider
+                .update(welcomeMessage: finalText, store: true);
+            Navigator.of(context).pop(true);
+          },
+        ),
+      ],
+    );
+  }
+}