diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index 5316cb2..5927722 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -15,10 +15,10 @@ jobs:
           encodedString: ${{ secrets.KEYSTORE_BASE64 }}
       - name: Create key.properties
         run: |
-          echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > filcnaplo/android/key.properties
-          echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> filcnaplo/android/key.properties
-          echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> filcnaplo/android/key.properties
-          echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> filcnaplo/android/key.properties
+          echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > refilc/android/key.properties
+          echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> refilc/android/key.properties
+          echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> refilc/android/key.properties
+          echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> refilc/android/key.properties
       - uses: actions/setup-java@v3
         with:
           distribution: "zulu"
@@ -32,7 +32,7 @@ jobs:
       - name: Install dependencies
         run: ./fix-pub.sh
       - name: Build
-        run: cd filcnaplo && ./build.sh
+        run: cd refilc && ./build.sh
       - name: Upload Android Release
         uses: actions/upload-artifact@v2
         with:
diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml
index 604d8ea..c456926 100644
--- a/.github/workflows/ios.yml
+++ b/.github/workflows/ios.yml
@@ -46,7 +46,7 @@ jobs:
 
       # Build and sign the ipa using a single flutter command
       - name: Building IPA
-        working-directory: filcnaplo
+        working-directory: refilc
         run: bash build-ipa.sh
           
       # Collect the file and upload as artifact         
@@ -55,7 +55,7 @@ jobs:
         with:
          name: release-ipa
          # Path to the release files
-         path: filcnaplo/build/ios/ipa/*.ipa
+         path: refilc/build/ios/ipa/*.ipa
 
       # Important! Cleanup: remove the certificate and provisioning profile from the runner!
       - name: Clean up keychain and provisioning profile
diff --git a/.idea/naplo.iml b/.idea/naplo.iml
index ab2f482..1d81c0f 100644
--- a/.idea/naplo.iml
+++ b/.idea/naplo.iml
@@ -3,63 +3,63 @@
   <component name="NewModuleRootManager" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_desktop_ui/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_desktop_ui/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_desktop_ui/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/share_plus/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/share_plus/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/share_plus/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_premium/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_premium/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_premium/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/share_plus/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/share_plus/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/share_plus/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_kreta_api/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_kreta_api/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_kreta_api/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_mobile_ui/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_mobile_ui/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo_mobile_ui/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/example/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/example/.dart_tool" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/example/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/build" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.pub" />
-      <excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_desktop_ui/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_desktop_ui/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_desktop_ui/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/share_plus/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/share_plus/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/share_plus/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/dynamic_color/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_premium/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_premium/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_premium/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/share_plus/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/share_plus/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/share_plus/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_kreta_api/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_kreta_api/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_kreta_api/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_mobile_ui/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_mobile_ui/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc_mobile_ui/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/example/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/build" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.pub" />
+      <excludeFolder url="file://$MODULE_DIR$/refilc/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.dart_tool" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index b2035b9..699c55f 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,9 +2,9 @@
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/filcnaplo_desktop_ui" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/filcnaplo_kreta_api" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/filcnaplo_mobile_ui" vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/filcnaplo_premium" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/refilc_desktop_ui" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/refilc_kreta_api" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/refilc_mobile_ui" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/refilc_premium" vcs="Git" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 3c003e4..7acbc65 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -2,8 +2,8 @@
   "version": "0.2.0",
   "configurations": [
     {
-      "name": "filcnaplo",
-      "cwd": "filcnaplo",
+      "name": "refilc",
+      "cwd": "refilc",
       "request": "launch",
       "type": "dart",
       "toolArgs": [
@@ -11,8 +11,8 @@
       ]
     },
     // {
-    //   "name": "filcnaplo release",
-    //   "cwd": "filcnaplo release",
+    //   "name": "refilc release",
+    //   "cwd": "refilc release",
     //   "request": "launch",
     //   "type": "dart",
     //   "program": "lib/main.dart",
@@ -23,7 +23,7 @@
     {
       "name": "Flutter",
       "program": "lib/main.dart",
-      "cwd": "filcnaplo",
+      "cwd": "refilc",
       "request": "launch",
       "type": "dart",
       "flutterMode": "debug"
@@ -31,7 +31,7 @@
     {
       "name": "Flutter (release)",
       "program": "lib/main.dart",
-      "cwd": "filcnaplo",
+      "cwd": "refilc",
       "request": "launch",
       "type": "dart",
       "flutterMode": "release"
diff --git a/README.md b/README.md
index 03b692c..1f127f0 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Run `fix-pub.sh`
 ### Run the app
 
 ```sh
-cd filcnaplo
+cd refilc
 flutter run
 ```
 
diff --git a/filcnaplo/.gitignore b/filcnaplo/.gitignore
deleted file mode 100644
index 7900af4..0000000
--- a/filcnaplo/.gitignore
+++ /dev/null
@@ -1,47 +0,0 @@
-# Miscellaneous
-*.class
-*.log
-*.pyc
-*.swp
-.DS_Store
-.atom/
-.buildlog/
-.history
-.svn/
-
-# IntelliJ related
-*.iml
-*.ipr
-*.iws
-.idea/
-
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
-#.vscode/
-
-# Flutter/Dart/Pub related
-**/doc/api/
-**/ios/Flutter/.last_build_id
-.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
-.packages
-.pub-cache/
-.pub/
-/build/
-
-# Web related
-lib/generated_plugin_registrant.dart
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
-key.properties
diff --git a/filcnaplo/analysis_options.yaml b/filcnaplo/analysis_options.yaml
deleted file mode 100644
index a7acf24..0000000
--- a/filcnaplo/analysis_options.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
-  # The lint rules applied to this project can be customized in the
-  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
-  # included above or to enable additional rules. A list of all available lints
-  # and their documentation is published at
-  # https://dart-lang.github.io/linter/lints/index.html.
-  #
-  # Instead of disabling a lint rule for the entire project in the
-  # section below, it can also be suppressed for a single line of code
-  # or a specific dart file by using the `// ignore: name_of_lint` and
-  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
-  # producing the lint.
-  rules:
-    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
-    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
diff --git a/filcnaplo/android/.gitignore b/filcnaplo/android/.gitignore
deleted file mode 100644
index a2ea94a..0000000
--- a/filcnaplo/android/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-gradle-wrapper.jar
-/.gradle
-/captures/
-/gradlew
-/gradlew.bat
-/local.properties
-GeneratedPluginRegistrant.java
-
-# Remember to never publicly share your keystore.
-# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
-key.properties
-.project
\ No newline at end of file
diff --git a/filcnaplo/assets/fonts/Montserrat/OFL.txt b/filcnaplo/assets/fonts/Montserrat/OFL.txt
deleted file mode 100644
index 7881887..0000000
--- a/filcnaplo/assets/fonts/Montserrat/OFL.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat)
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/filcnaplo/ios/.gitignore b/filcnaplo/ios/.gitignore
deleted file mode 100644
index 8adea5a..0000000
--- a/filcnaplo/ios/.gitignore
+++ /dev/null
@@ -1,33 +0,0 @@
-*.mode1v3
-*.mode2v3
-*.moved-aside
-*.pbxuser
-*.perspectivev3
-**/*sync/
-.sconsign.dblite
-.tags*
-**/.vagrant/
-**/DerivedData/
-Icon?
-**/Pods/
-**/.symlinks/
-profile
-xcuserdata
-**/.generated/
-Flutter/App.framework
-Flutter/Flutter.framework
-Flutter/Flutter.podspec
-Flutter/Generated.xcconfig
-Flutter/ephemeral/
-Flutter/app.flx
-Flutter/app.zip
-Flutter/flutter_assets/
-Flutter/flutter_export_environment.sh
-ServiceDefinitions.json
-Runner/GeneratedPluginRegistrant.*
-
-# Exceptions to above rules.
-!default.mode1v3
-!default.mode2v3
-!default.pbxuser
-!default.perspectivev3
diff --git a/filcnaplo/lib/helpers/subject.dart b/filcnaplo/lib/helpers/subject.dart
deleted file mode 100644
index 2880d17..0000000
--- a/filcnaplo/lib/helpers/subject.dart
+++ /dev/null
@@ -1,144 +0,0 @@
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo/models/icon_pack.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-typedef SubjectIconVariants = Map<IconPack, IconData>;
-
-class SubjectIconData {
-  final SubjectIconVariants data;
-  final String name; // for iOS live activities compatibilty
-
-  SubjectIconData({
-    this.data = const {
-      IconPack.material: Icons.widgets_outlined,
-      IconPack.cupertino: CupertinoIcons.rectangle_grid_2x2,
-    },
-    this.name = "square.grid.2x2",
-  });
-}
-
-SubjectIconVariants createIcon({required IconData material, required IconData cupertino}) {
-  return {
-    IconPack.material: material,
-    IconPack.cupertino: cupertino,
-  };
-}
-
-class SubjectIcon {
-  static String resolveName({Subject? subject, String? subjectName}) => _resolve(subject: subject, subjectName: subjectName).name;
-  static IconData resolveVariant({Subject? subject, String? subjectName, required BuildContext context}) =>
-      _resolve(subject: subject, subjectName: subjectName).data[Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
-
-  static SubjectIconData _resolve({Subject? subject, String? subjectName}) {
-    assert(!(subject == null && subjectName == null));
-
-    String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
-    String category = subject?.category.description.toLowerCase().specialChars() ?? "";
-
-    // todo: check for categories
-    if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.function, material: Icons.calculate_outlined), name: "function");
-    } else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.textformat_alt, material: Icons.spellcheck_outlined), name: "textformat.alt");
-    } else if (RegExp("irodalom").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.book, material: Icons.menu_book_outlined), name: "book");
-    } else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.compass, material: Icons.hourglass_empty_outlined), name: "safari");
-    } else if (RegExp("foldrajz").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.map, material: Icons.public_outlined), name: "map");
-    } else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paintbrush, material: Icons.palette_outlined), name: "paintbrush");
-    } else if (RegExp("fizika").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lightbulb, material: Icons.emoji_objects_outlined), name: "lightbulb");
-    } else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_note, material: Icons.music_note_outlined), name: "music.note");
-    } else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.sportscourt, material: Icons.sports_soccer_outlined), name: "sportscourt");
-    } else if (RegExp("kemia").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lab_flask, material: Icons.science_outlined), name: "testtube.2");
-    } else if (RegExp("biologia").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paw, material: Icons.pets_outlined), name: "pawprint");
-    } else if (RegExp("kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) {
-      return SubjectIconData(
-          data: createIcon(cupertino: CupertinoIcons.arrow_3_trianglepath, material: Icons.eco_outlined), name: "arrow.3.trianglepath");
-    } else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.heart, material: Icons.favorite_border_outlined), name: "heart");
-    } else if (RegExp("penzugy").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.money_dollar, material: Icons.savings_outlined), name: "dollarsign");
-    } else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.device_laptop, material: Icons.computer_outlined), name: "laptopcomputer");
-    } else if (RegExp("prog").hasMatch(name)) {
-      return SubjectIconData(
-          data: createIcon(cupertino: CupertinoIcons.chevron_left_slash_chevron_right, material: Icons.code_outlined),
-          name: "chevron.left.forwardslash.chevron.right");
-    } else if (RegExp("halozat").hasMatch(name)) {
-      return SubjectIconData(
-          data: createIcon(cupertino: CupertinoIcons.antenna_radiowaves_left_right, material: Icons.wifi_tethering_outlined),
-          name: "antenna.radiowaves.left.and.right");
-    } else if (RegExp("szinhaz").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hifispeaker, material: Icons.theater_comedy_outlined), name: "hifispeaker");
-    } else if (RegExp("film|media").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.film, material: Icons.theaters_outlined), name: "film");
-    } else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bolt, material: Icons.electrical_services_outlined), name: "bolt");
-    } else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.wrench, material: Icons.precision_manufacturing_outlined), name: "wrench");
-    } else if (RegExp("technika").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hammer, material: Icons.build_outlined), name: "hammer");
-    } else if (RegExp("tanc").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_mic, material: Icons.speaker_outlined), name: "music.mic");
-    } else if (RegExp("filozofia").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bubble_left, material: Icons.psychology_outlined), name: "bubble.left");
-    } else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.group, material: Icons.groups_outlined), name: "person.3");
-    } else if (RegExp("gazdasag").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.chart_pie, material: Icons.account_balance_outlined), name: "chart.pie");
-    } else if (RegExp("szorgalom").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.checkmark_seal, material: Icons.verified_outlined), name: "checkmark.seal");
-    } else if (RegExp("magatartas").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.smiley, material: Icons.emoji_people_outlined), name: "face.smiling");
-    } else if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.globe, material: Icons.translate_outlined), name: "globe");
-    } else if (RegExp("linux").hasMatch(name)) {
-      return SubjectIconData(data: createIcon(material: FilcIcons.linux, cupertino: FilcIcons.linux));
-    }
-
-    return SubjectIconData();
-  }
-}
-
-class ShortSubject {
-  static String resolve({Subject? subject, String? subjectName}) {
-    assert(!(subject == null && subjectName == null));
-
-    String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
-    // String category = subject?.category.description.toLowerCase().specialChars() ?? "";
-
-    if (RegExp("magyar irodalom").hasMatch(name)) {
-      return "Irodalom";
-    } else if (RegExp("magyar nyelv").hasMatch(name)) {
-      return "Nyelvtan";
-    } else if (RegExp("matematika").hasMatch(name)) {
-      return "Matek";
-    } else if (RegExp("digitalis kultura").hasMatch(name)) {
-      return "Dig. kult.";
-    } else if (RegExp("testneveles").hasMatch(name)) {
-      return "Tesi";
-    } else if (RegExp("tortenelem").hasMatch(name)) {
-      return "Töri";
-    } else if (RegExp("(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv").hasMatch(name)) {
-      return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", "");
-    } else if (RegExp("informatika").hasMatch(name)) {
-      return "Infó";
-    } else if (RegExp("osztalyfonoki").hasMatch(name)) {
-      return "Ofő";
-    }
-
-    return subject?.name.capital() ?? subjectName?.capital() ?? "?";
-  }
-}
diff --git a/filcnaplo/lib/ui/filter/widgets/absences.dart b/filcnaplo/lib/ui/filter/widgets/absences.dart
deleted file mode 100644
index 4e4748d..0000000
--- a/filcnaplo/lib/ui/filter/widgets/absences.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Absence> providerAbsences, {bool noExcused = false}) {
-  List<DateWidget> items = [];
-  providerAbsences.where((a) => !noExcused || a.state != Justification.excused).forEach((absence) {
-    items.add(DateWidget(
-      key: absence.id,
-      date: absence.date,
-      widget: mobile.AbsenceViewable(absence),
-    ));
-  });
-  return items;
-}
diff --git a/filcnaplo/lib/ui/filter/widgets/grades.dart b/filcnaplo/lib/ui/filter/widgets/grades.dart
deleted file mode 100644
index 667e58a..0000000
--- a/filcnaplo/lib/ui/filter/widgets/grades.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo/utils/platform.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_viewable.dart' as mobile;
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart' as mobile;
-import 'package:filcnaplo_desktop_ui/common/widgets/grade/grade_viewable.dart' as desktop;
-
-List<DateWidget> getWidgets(List<Grade> providerGrades, DateTime? lastSeenDate) {
-  List<DateWidget> items = [];
-  for (var grade in providerGrades) {
-    final surprise = (!(lastSeenDate != null && grade.date.isAfter(lastSeenDate)) || grade.value.value == 0);
-    if (grade.type == GradeType.midYear && surprise) {
-      items.add(DateWidget(
-        key: grade.id,
-        date: grade.date,
-        widget: PlatformUtils.isMobile ? mobile.GradeViewable(grade) : desktop.GradeViewable(grade),
-      ));
-    }
-  }
-  return items;
-}
-
-List<DateWidget> getNewWidgets(List<Grade> providerGrades, DateTime? lastSeenDate) {
-  List<DateWidget> items = [];
-  List<Grade> newGrades = [];
-  for (var grade in providerGrades) {
-    final surprise = !(lastSeenDate != null && !grade.date.isAfter(lastSeenDate)) && grade.value.value != 0;
-    if (grade.type == GradeType.midYear && surprise) {
-      newGrades.add(grade);
-    }
-  }
-  newGrades.sort((a, b) => a.date.compareTo(b.date));
-  if (newGrades.isNotEmpty) {
-    items.add(DateWidget(
-      key: newGrades.last.id,
-      date: newGrades.last.date,
-      widget: mobile.NewGradesSurprise(newGrades),
-    ));
-  }
-  return items;
-}
diff --git a/filcnaplo/lib/ui/filter/widgets/lessons.dart b/filcnaplo/lib/ui/filter/widgets/lessons.dart
deleted file mode 100644
index 676126a..0000000
--- a/filcnaplo/lib/ui/filter/widgets/lessons.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Lesson> providerLessons) {
-  List<DateWidget> items = [];
-  providerLessons.where((l) => l.isChanged && l.start.isAfter(DateTime.now())).forEach((lesson) {
-    items.add(DateWidget(
-      key: lesson.id,
-      date: DateTime(lesson.date.year, lesson.date.month, lesson.date.day, lesson.start.hour, lesson.start.minute),
-      widget: mobile.ChangedLessonViewable(lesson),
-    ));
-  });
-  return items;
-}
diff --git a/filcnaplo/lib/ui/filter/widgets/messages.dart b/filcnaplo/lib/ui/filter/widgets/messages.dart
deleted file mode 100644
index 4181ce7..0000000
--- a/filcnaplo/lib/ui/filter/widgets/messages.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo/ui/filter/widgets/notes.dart' as note_filter;
-import 'package:filcnaplo/ui/filter/widgets/events.dart' as event_filter;
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/message_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Message> providerMessages, List<Note> providerNotes, List<Event> providerEvents) {
-  List<DateWidget> items = [];
-  for (var message in providerMessages) {
-    if (message.type == MessageType.inbox) {
-      items.add(DateWidget(
-        key: "${message.id}",
-        date: message.date,
-        widget: mobile.MessageViewable(message),
-      ));
-    }
-  }
-  items.addAll(note_filter.getWidgets(providerNotes));
-  items.addAll(event_filter.getWidgets(providerEvents));
-  return items;
-}
diff --git a/filcnaplo/lib/ui/filter/widgets/update.dart b/filcnaplo/lib/ui/filter/widgets/update.dart
deleted file mode 100644
index 6b35e63..0000000
--- a/filcnaplo/lib/ui/filter/widgets/update.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:filcnaplo/models/release.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/update/update_viewable.dart' as mobile;
-
-DateWidget getWidget(Release providerRelease) {
-  return DateWidget(
-    date: DateTime.now(),
-    widget: mobile.UpdateViewable(providerRelease),
-  );
-}
diff --git a/filcnaplo/lib/utils/reverse_search.dart b/filcnaplo/lib/utils/reverse_search.dart
deleted file mode 100644
index e313937..0000000
--- a/filcnaplo/lib/utils/reverse_search.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'dart:developer';
-
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:provider/provider.dart';
-
-class ReverseSearch {
-  static Future<Lesson?> getLessonByAbsence(Absence absence, BuildContext context) async {
-    final timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
-
-    List<Lesson> lessons = [];
-    final week = Week.fromDate(absence.date);
-    try {
-      await timetableProvider.fetch(week: week);
-    } catch (e) {
-      log("[ERROR] getLessonByAbsence: $e");
-    }
-    lessons = timetableProvider.getWeek(week) ?? [];
-
-    // Find absence lesson in timetable
-    Lesson lesson = lessons.firstWhere(
-      (l) => _sameDate(l.date, absence.date) && l.subject.id == absence.subject.id && l.lessonIndex == absence.lessonIndex.toString(),
-      orElse: () => Lesson.fromJson({'isEmpty': true}),
-    );
-
-    if (lesson.isEmpty) {
-      return null;
-    } else {
-      return lesson;
-    }
-  }
-
-  // difference.inDays is not reliable
-  static bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
-}
diff --git a/filcnaplo/linux/.gitignore b/filcnaplo/linux/.gitignore
deleted file mode 100644
index c7ea17f..0000000
--- a/filcnaplo/linux/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-flutter/ephemeral
diff --git a/filcnaplo/linux/CMakeLists.txt b/filcnaplo/linux/CMakeLists.txt
deleted file mode 100644
index 900368d..0000000
--- a/filcnaplo/linux/CMakeLists.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(runner LANGUAGES CXX)
-
-set(BINARY_NAME "filcnaplo")
-set(APPLICATION_ID "hu.filc.filcnaplo")
-
-cmake_policy(SET CMP0063 NEW)
-
-set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
-
-# Root filesystem for cross-building.
-if(FLUTTER_TARGET_PLATFORM_SYSROOT)
-  set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
-  set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
-  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
-  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-endif()
-
-# Configure build options.
-if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
-  set(CMAKE_BUILD_TYPE "Debug" CACHE
-    STRING "Flutter build mode" FORCE)
-  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
-    "Debug" "Profile" "Release")
-endif()
-
-# Compilation settings that should be applied to most targets.
-function(APPLY_STANDARD_SETTINGS TARGET)
-  target_compile_features(${TARGET} PUBLIC cxx_std_14)
-  target_compile_options(${TARGET} PRIVATE -Wall -Werror)
-  target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
-  target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
-endfunction()
-
-set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
-
-# Flutter library and tool build rules.
-add_subdirectory(${FLUTTER_MANAGED_DIR})
-
-# System-level dependencies.
-find_package(PkgConfig REQUIRED)
-pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
-
-add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
-
-# Application build
-add_executable(${BINARY_NAME}
-  "main.cc"
-  "my_application.cc"
-  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
-)
-apply_standard_settings(${BINARY_NAME})
-target_link_libraries(${BINARY_NAME} PRIVATE flutter)
-target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
-add_dependencies(${BINARY_NAME} flutter_assemble)
-# Only the install-generated bundle's copy of the executable will launch
-# correctly, since the resources must in the right relative locations. To avoid
-# people trying to run the unbundled copy, put it in a subdirectory instead of
-# the default top-level location.
-set_target_properties(${BINARY_NAME}
-  PROPERTIES
-  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
-)
-
-# Generated plugin build rules, which manage building the plugins and adding
-# them to the application.
-include(flutter/generated_plugins.cmake)
-
-
-# === Installation ===
-# By default, "installing" just makes a relocatable bundle in the build
-# directory.
-set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
-if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
-  set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
-endif()
-
-# Start with a clean build bundle directory every time.
-install(CODE "
-  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
-  " COMPONENT Runtime)
-
-set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
-set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
-
-install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
-  COMPONENT Runtime)
-
-install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
-  COMPONENT Runtime)
-
-install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
-  COMPONENT Runtime)
-
-if(PLUGIN_BUNDLED_LIBRARIES)
-  install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
-    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
-    COMPONENT Runtime)
-endif()
-
-# Fully re-copy the assets directory on each build to avoid having stale files
-# from a previous install.
-set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
-install(CODE "
-  file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
-  " COMPONENT Runtime)
-install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
-  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
-
-# Install the AOT library on non-Debug builds only.
-if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
-  install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
-    COMPONENT Runtime)
-endif()
diff --git a/filcnaplo/linux/flutter/CMakeLists.txt b/filcnaplo/linux/flutter/CMakeLists.txt
deleted file mode 100644
index 7a0003d..0000000
--- a/filcnaplo/linux/flutter/CMakeLists.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-
-set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
-
-# Configuration provided via flutter tool.
-include(${EPHEMERAL_DIR}/generated_config.cmake)
-
-# TODO: Move the rest of this into files in ephemeral. See
-# https://github.com/flutter/flutter/issues/57146.
-
-# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
-# which isn't available in 3.10.
-function(list_prepend LIST_NAME PREFIX)
-    set(NEW_LIST "")
-    foreach(element ${${LIST_NAME}})
-        list(APPEND NEW_LIST "${PREFIX}${element}")
-    endforeach(element)
-    set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
-endfunction()
-
-# === Flutter Library ===
-# System-level dependencies.
-find_package(PkgConfig REQUIRED)
-pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
-pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
-pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
-
-set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
-
-# Published to parent scope for install step.
-set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
-set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
-set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
-set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
-
-list(APPEND FLUTTER_LIBRARY_HEADERS
-  "fl_basic_message_channel.h"
-  "fl_binary_codec.h"
-  "fl_binary_messenger.h"
-  "fl_dart_project.h"
-  "fl_engine.h"
-  "fl_json_message_codec.h"
-  "fl_json_method_codec.h"
-  "fl_message_codec.h"
-  "fl_method_call.h"
-  "fl_method_channel.h"
-  "fl_method_codec.h"
-  "fl_method_response.h"
-  "fl_plugin_registrar.h"
-  "fl_plugin_registry.h"
-  "fl_standard_message_codec.h"
-  "fl_standard_method_codec.h"
-  "fl_string_codec.h"
-  "fl_value.h"
-  "fl_view.h"
-  "flutter_linux.h"
-)
-list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
-add_library(flutter INTERFACE)
-target_include_directories(flutter INTERFACE
-  "${EPHEMERAL_DIR}"
-)
-target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
-target_link_libraries(flutter INTERFACE
-  PkgConfig::GTK
-  PkgConfig::GLIB
-  PkgConfig::GIO
-)
-add_dependencies(flutter flutter_assemble)
-
-# === Flutter tool backend ===
-# _phony_ is a non-existent file to force this command to run every time,
-# since currently there's no way to get a full input/output list from the
-# flutter tool.
-add_custom_command(
-  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
-    ${CMAKE_CURRENT_BINARY_DIR}/_phony_
-  COMMAND ${CMAKE_COMMAND} -E env
-    ${FLUTTER_TOOL_ENVIRONMENT}
-    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
-      ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
-  VERBATIM
-)
-add_custom_target(flutter_assemble DEPENDS
-  "${FLUTTER_LIBRARY}"
-  ${FLUTTER_LIBRARY_HEADERS}
-)
diff --git a/filcnaplo/macos/.gitignore b/filcnaplo/macos/.gitignore
deleted file mode 100644
index d4e0569..0000000
--- a/filcnaplo/macos/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# Flutter-related
-**/Flutter/ephemeral/
-**/Pods/
-
-# Xcode-related
-**/dgph
-**/xcuserdata/
diff --git a/filcnaplo/windows/.gitignore b/filcnaplo/windows/.gitignore
deleted file mode 100644
index d492d0d..0000000
--- a/filcnaplo/windows/.gitignore
+++ /dev/null
@@ -1,17 +0,0 @@
-flutter/ephemeral/
-
-# Visual Studio user-specific files.
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# Visual Studio build-related files.
-x64/
-x86/
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
diff --git a/filcnaplo_desktop_ui/.gitignore b/filcnaplo_desktop_ui/.gitignore
deleted file mode 100644
index 516bea4..0000000
--- a/filcnaplo_desktop_ui/.gitignore
+++ /dev/null
@@ -1,47 +0,0 @@
-# Miscellaneous
-*.class
-*.log
-*.pyc
-*.swp
-.DS_Store
-.atom/
-.buildlog/
-.history
-.svn/
-
-# IntelliJ related
-*.iml
-*.ipr
-*.iws
-.idea/
-
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
-#.vscode/
-
-# Flutter/Dart/Pub related
-**/doc/api/
-**/ios/Flutter/.last_build_id
-.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
-.packages
-.pub-cache/
-.pub/
-/build/
-
-# Web related
-lib/generated_plugin_registrant.dart
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
-pubspec.lock
diff --git a/filcnaplo_desktop_ui/lib/pages/grades/grades_count.dart b/filcnaplo_desktop_ui/lib/pages/grades/grades_count.dart
deleted file mode 100644
index c3c75f6..0000000
--- a/filcnaplo_desktop_ui/lib/pages/grades/grades_count.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_desktop_ui/pages/grades/grades_count_item.dart';
-import 'package:collection/collection.dart';
-
-class GradesCount extends StatelessWidget {
-  const GradesCount({Key? key, required this.grades}) : super(key: key);
-
-  final List<Grade> grades;
-
-  @override
-  Widget build(BuildContext context) {
-    List<int> gradesCount = List.generate(5, (int index) => grades.where((e) => e.value.value == index + 1).length);
-
-    return Container(
-      width: 75,
-      padding: const EdgeInsets.only(bottom: 6.0, top: 6.0, left: 12.0, right: 0.0),
-      margin: const EdgeInsets.symmetric(horizontal: 12.0),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.spaceAround,
-        children: gradesCount.mapIndexed((index, e) => GradesCountItem(count: e, value: index + 1)).toList(),
-      ),
-    );
-  }
-}
diff --git a/filcnaplo_kreta_api/.gitignore b/filcnaplo_kreta_api/.gitignore
deleted file mode 100644
index 516bea4..0000000
--- a/filcnaplo_kreta_api/.gitignore
+++ /dev/null
@@ -1,47 +0,0 @@
-# Miscellaneous
-*.class
-*.log
-*.pyc
-*.swp
-.DS_Store
-.atom/
-.buildlog/
-.history
-.svn/
-
-# IntelliJ related
-*.iml
-*.ipr
-*.iws
-.idea/
-
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
-#.vscode/
-
-# Flutter/Dart/Pub related
-**/doc/api/
-**/ios/Flutter/.last_build_id
-.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
-.packages
-.pub-cache/
-.pub/
-/build/
-
-# Web related
-lib/generated_plugin_registrant.dart
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
-pubspec.lock
diff --git a/filcnaplo_mobile_ui/.gitignore b/filcnaplo_mobile_ui/.gitignore
deleted file mode 100644
index 516bea4..0000000
--- a/filcnaplo_mobile_ui/.gitignore
+++ /dev/null
@@ -1,47 +0,0 @@
-# Miscellaneous
-*.class
-*.log
-*.pyc
-*.swp
-.DS_Store
-.atom/
-.buildlog/
-.history
-.svn/
-
-# IntelliJ related
-*.iml
-*.ipr
-*.iws
-.idea/
-
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
-#.vscode/
-
-# Flutter/Dart/Pub related
-**/doc/api/
-**/ios/Flutter/.last_build_id
-.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
-.packages
-.pub-cache/
-.pub/
-/build/
-
-# Web related
-lib/generated_plugin_registrant.dart
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
-pubspec.lock
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_view.dart b/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_view.dart
deleted file mode 100755
index 15cb282..0000000
--- a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_view.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_card.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/hero_scrollview.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-class CertificationView extends StatelessWidget {
-  const CertificationView(this.grades, {Key? key, required this.gradeType}) : super(key: key);
-
-  final List<Grade> grades;
-  final GradeType gradeType;
-
-  static show(List<Grade> grades, {required BuildContext context, required GradeType gradeType}) =>
-      Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(builder: (context) => CertificationView(grades, gradeType: gradeType)));
-
-  @override
-  Widget build(BuildContext context) {
-    grades.sort((a, b) => a.subject.name.compareTo(b.subject.name));
-    List<Widget> tiles = grades.map((e) => CertificationTile(e)).toList();
-    return Scaffold(
-        body: HeroScrollView(
-        title: getGradeTypeTitle(gradeType),
-        icon: FeatherIcons.award,
-        iconSize: 50,
-            child: ListView(
-          children: [
-            SafeArea(
-              child: Panel(
-                child: Column(
-                  children: tiles,
-                ),
-              ),
-            )
-          ],
-          shrinkWrap: true,
-          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-          physics: const BouncingScrollPhysics(),
-        )));
-  }
-}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_viewable.dart b/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_viewable.dart
deleted file mode 100755
index c931bae..0000000
--- a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_viewable.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:filcnaplo_mobile_ui/common/viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/card_handle.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_view.dart';
-import 'package:flutter/material.dart';
-
-class ExamViewable extends StatelessWidget {
-  const ExamViewable(this.exam, {Key? key}) : super(key: key);
-
-  final Exam exam;
-
-  @override
-  Widget build(BuildContext context) {
-    return Viewable(
-      tile: ExamTile(exam),
-      view: CardHandle(child: ExamView(exam)),
-    );
-  }
-}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/grades_count.dart b/filcnaplo_mobile_ui/lib/pages/grades/grades_count.dart
deleted file mode 100755
index f2a2e70..0000000
--- a/filcnaplo_mobile_ui/lib/pages/grades/grades_count.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/grades_count_item.dart';
-import 'package:collection/collection.dart';
-
-class GradesCount extends StatelessWidget {
-  const GradesCount({Key? key, required this.grades}) : super(key: key);
-
-  final List<Grade> grades;
-
-  @override
-  Widget build(BuildContext context) {
-    List<int> gradesCount = List.generate(5, (int index) => grades.where((e) => e.value.value == index + 1).length);
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 6.0, top: 6.0, left: 12.0, right: 6.0),
-      child: Row(
-        mainAxisAlignment: MainAxisAlignment.spaceAround,
-        children: gradesCount.mapIndexed((index, e) => GradesCountItem(count: e, value: index + 1)).toList(),
-      ),
-    );
-  }
-}
diff --git a/filcnaplo_premium/.gitignore b/filcnaplo_premium/.gitignore
deleted file mode 100644
index 5de5aa0..0000000
--- a/filcnaplo_premium/.gitignore
+++ /dev/null
@@ -1,48 +0,0 @@
-# Miscellaneous
-*.class
-*.log
-*.pyc
-*.swp
-.DS_Store
-.atom/
-.buildlog/
-.history
-.svn/
-
-# IntelliJ related
-*.iml
-*.ipr
-*.iws
-.idea/
-
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
-#.vscode/
-
-# Flutter/Dart/Pub related
-**/doc/api/
-**/ios/Flutter/.last_build_id
-.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
-.packages
-.pub-cache/
-.pub/
-/build/
-
-# Web related
-lib/generated_plugin_registrant.dart
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
-pubspec.lock
-android/local.properties
diff --git a/fix-pub.sh b/fix-pub.sh
index 27e50db..6fa5eea 100755
--- a/fix-pub.sh
+++ b/fix-pub.sh
@@ -1,7 +1,7 @@
-cd filcnaplo && flutter clean && flutter pub get && cd ..
-cd filcnaplo_kreta_api && flutter clean && flutter pub get && cd ..
-cd filcnaplo_mobile_ui && flutter clean && flutter pub get && cd ..
-cd filcnaplo_desktop_ui && flutter clean && flutter pub get && cd ..
-cd filcnaplo_premium && flutter clean && flutter pub get && cd ..
+cd refilc && flutter clean && flutter pub get && cd ..
+cd refilc_kreta_api && flutter clean && flutter pub get && cd ..
+cd refilc_mobile_ui && flutter clean && flutter pub get && cd ..
+cd refilc_desktop_ui && flutter clean && flutter pub get && cd ..
+cd refilc_premium && flutter clean && flutter pub get && cd ..
 
 echo Fixed pub.
\ No newline at end of file
diff --git a/filcnaplo/.metadata b/refilc/.metadata
similarity index 100%
rename from filcnaplo/.metadata
rename to refilc/.metadata
diff --git a/filcnaplo/README.md b/refilc/README.md
similarity index 86%
rename from filcnaplo/README.md
rename to refilc/README.md
index 02c4c20..775cf06 100644
--- a/filcnaplo/README.md
+++ b/refilc/README.md
@@ -1,3 +1,3 @@
-# refilc
-
-Main lib
+# refilc
+
+Main lib
diff --git a/filcnaplo_mobile_ui/analysis_options.yaml b/refilc/analysis_options.yaml
old mode 100755
new mode 100644
similarity index 98%
rename from filcnaplo_mobile_ui/analysis_options.yaml
rename to refilc/analysis_options.yaml
index 16f5f56..61b6c4d
--- a/filcnaplo_mobile_ui/analysis_options.yaml
+++ b/refilc/analysis_options.yaml
@@ -1,28 +1,29 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
-  # The lint rules applied to this project can be customized in the
-  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
-  # included above or to enable additional rules. A list of all available lints
-  # and their documentation is published at
-  # https://dart-lang.github.io/linter/lints/index.html.
-  #
-  # Instead of disabling a lint rule for the entire project in the
-  # section below, it can also be suppressed for a single line of code
-  # or a specific dart file by using the `// ignore: name_of_lint` and
-  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
-  # producing the lint.
-  rules:
-    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
-    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/filcnaplo/android/app/build.gradle b/refilc/android/app/build.gradle
similarity index 96%
rename from filcnaplo/android/app/build.gradle
rename to refilc/android/app/build.gradle
index 49825fb..b697642 100644
--- a/filcnaplo/android/app/build.gradle
+++ b/refilc/android/app/build.gradle
@@ -1,99 +1,99 @@
-def localProperties = new Properties()
-def localPropertiesFile = rootProject.file('local.properties')
-if (localPropertiesFile.exists()) {
-    localPropertiesFile.withReader('UTF-8') { reader ->
-        localProperties.load(reader)
-    }
-}
-
-def flutterRoot = localProperties.getProperty('flutter.sdk')
-if (flutterRoot == null) {
-    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
-}
-
-def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
-if (flutterVersionCode == null) {
-    throw new GradleException("Undefined VersionCode")
-}
-
-def flutterVersionName = localProperties.getProperty('flutter.versionName')
-if (flutterVersionName == null) {
-    throw new GradleException("Undefined VersionName")
-}
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
-
-def keystoreProperties = new Properties()
-def keystorePropertiesFile = rootProject.file("key.properties")
-keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
-
-android {
-    compileSdkVersion rootProject.ext.compileSdkVersion
-
-    sourceSets {
-        main.java.srcDirs += 'src/main/kotlin'
-    }
-
-    lintOptions {
-        disable 'InvalidPackage'
-        disable "Instantiatable"
-        checkReleaseBuilds false
-        abortOnError false
-    }
-
-    defaultConfig {
-        applicationId "hu.refilc.naplo"
-        minSdkVersion 21
-        targetSdkVersion rootProject.ext.targetSdkVersion
-        versionCode flutterVersionCode.toInteger()
-        versionName flutterVersionName
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        multiDexEnabled true
-    }
-
-    compileOptions {
-      // Flag to enable support for the new language APIs
-      coreLibraryDesugaringEnabled true
-      // Sets Java compatibility to Java 8
-      sourceCompatibility JavaVersion.VERSION_1_8
-      targetCompatibility JavaVersion.VERSION_1_8
-    }
-
-    signingConfigs {
-        release {
-            keyAlias keystoreProperties['keyAlias']
-            keyPassword keystoreProperties['keyPassword']
-            storeFile file(keystoreProperties['storeFile'])
-            storePassword keystoreProperties['storePassword']
-        }
-    }
-
-    buildTypes {
-        release {
-            signingConfig signingConfigs.release
-            shrinkResources false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-    }
-    
-    buildFeatures {
-        viewBinding true
-    }
-}
-
-flutter {
-    source '../..'
-}
-
-dependencies {
-    implementation 'com.android.support:multidex:2.0.1'
-    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-    implementation 'joda-time:joda-time:2.9.4'
-    androidTestImplementation 'androidx.test:runner:1.1.1'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
-    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
-    implementation 'androidx.window:window:1.0.0'
-    implementation 'androidx.window:window-java:1.0.0'
-}
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    throw new GradleException("Undefined VersionCode")
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    throw new GradleException("Undefined VersionName")
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+def keystoreProperties = new Properties()
+def keystorePropertiesFile = rootProject.file("key.properties")
+keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+
+android {
+    compileSdkVersion rootProject.ext.compileSdkVersion
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+
+    lintOptions {
+        disable 'InvalidPackage'
+        disable "Instantiatable"
+        checkReleaseBuilds false
+        abortOnError false
+    }
+
+    defaultConfig {
+        applicationId "hu.refilc.naplo"
+        minSdkVersion 21
+        targetSdkVersion rootProject.ext.targetSdkVersion
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        multiDexEnabled true
+    }
+
+    compileOptions {
+      // Flag to enable support for the new language APIs
+      coreLibraryDesugaringEnabled true
+      // Sets Java compatibility to Java 8
+      sourceCompatibility JavaVersion.VERSION_1_8
+      targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    signingConfigs {
+        release {
+            keyAlias keystoreProperties['keyAlias']
+            keyPassword keystoreProperties['keyPassword']
+            storeFile file(keystoreProperties['storeFile'])
+            storePassword keystoreProperties['storePassword']
+        }
+    }
+
+    buildTypes {
+        release {
+            signingConfig signingConfigs.release
+            shrinkResources false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    
+    buildFeatures {
+        viewBinding true
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation 'com.android.support:multidex:2.0.1'
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    implementation 'joda-time:joda-time:2.9.4'
+    androidTestImplementation 'androidx.test:runner:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
+    implementation 'androidx.window:window:1.0.0'
+    implementation 'androidx.window:window-java:1.0.0'
+}
diff --git a/filcnaplo/android/app/proguard-rules.pro b/refilc/android/app/proguard-rules.pro
similarity index 86%
rename from filcnaplo/android/app/proguard-rules.pro
rename to refilc/android/app/proguard-rules.pro
index 56fe627..0940b69 100644
--- a/filcnaplo/android/app/proguard-rules.pro
+++ b/refilc/android/app/proguard-rules.pro
@@ -1,5 +1,5 @@
--keep class io.flutter.plugin.editing.** { *; }
--keep class androidx.lifecycle.DefaultLifecycleObserver
--keep class com.pauldemarco.flutter_blue.** { *; }
--keep class com.mr.flutter.plugin.filepicker.** { *; }
+-keep class io.flutter.plugin.editing.** { *; }
+-keep class androidx.lifecycle.DefaultLifecycleObserver
+-keep class com.pauldemarco.flutter_blue.** { *; }
+-keep class com.mr.flutter.plugin.filepicker.** { *; }
 -keep class com.shockwave.**
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/debug/AndroidManifest.xml b/refilc/android/app/src/debug/AndroidManifest.xml
similarity index 98%
rename from filcnaplo/android/app/src/debug/AndroidManifest.xml
rename to refilc/android/app/src/debug/AndroidManifest.xml
index 826ca84..fcc14fa 100644
--- a/filcnaplo/android/app/src/debug/AndroidManifest.xml
+++ b/refilc/android/app/src/debug/AndroidManifest.xml
@@ -1,8 +1,8 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hu.refilc.naplo">
-  <!-- Permissions -->
-  <uses-permission android:name="android.permission.INTERNET"/>
-  <uses-permission android:name="android.permission.VIBRATE" />
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-  <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
-</manifest>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hu.refilc.naplo">
+  <!-- Permissions -->
+  <uses-permission android:name="android.permission.INTERNET"/>
+  <uses-permission android:name="android.permission.VIBRATE" />
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+  <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
+</manifest>
diff --git a/filcnaplo/android/app/src/main/AndroidManifest.xml b/refilc/android/app/src/main/AndroidManifest.xml
similarity index 98%
rename from filcnaplo/android/app/src/main/AndroidManifest.xml
rename to refilc/android/app/src/main/AndroidManifest.xml
index 14d49f3..3cdc402 100644
--- a/filcnaplo/android/app/src/main/AndroidManifest.xml
+++ b/refilc/android/app/src/main/AndroidManifest.xml
@@ -1,86 +1,86 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
-    <application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
-        android:requestLegacyExternalStorage="true">
-        <activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
-            android:launchMode="singleTop" android:theme="@style/LaunchTheme"
-            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
-            android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"
-            android:showWhenLocked="true"
-            android:turnScreenOn="true">
-            <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable"
-                android:resource="@drawable/launch_background" />
-            <meta-data android:name="io.flutter.embedding.android.NormalTheme"
-                android:resource="@style/NormalTheme" />
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-            <intent-filter android:autoVerify="true">
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <!-- Accepts URIs that begin with https://api.refilcapp.hu -->
-                <data
-                    android:scheme="https"
-                    android:host="api.refilcapp.hu"
-                    android:pathPrefix="/v1/auth/callback" />
-            </intent-filter>
-            <intent-filter android:autoVerify="true">
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <!-- Accepts URIs that begin with https://refilc.hu -->
-                <data
-                    android:scheme="https"
-                    android:host="refilc.hu"
-                    android:pathPrefix="/app" />
-            </intent-filter>
-        </activity>
-        <meta-data android:name="flutterEmbedding" android:value="2" />
-
-        <receiver android:name="hu.refilc.naplo.widget_timetable.WidgetTimetable"
-            android:exported="true">
-            <intent-filter>
-                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
-                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_LEFT" />
-                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT" />
-                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_TODAY" />
-                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH" />
-                <action android:name="list_widget.ACTION_WIDGET_CLICK_BUY_PREMIUM" />
-            </intent-filter>
-
-            <meta-data
-                android:name="android.appwidget.provider"
-                android:resource="@xml/home_widget_test_info" />
-        </receiver>
-
-        <service android:name="hu.refilc.naplo.widget_timetable.WidgetTimetableService"
-            android:permission="android.permission.BIND_REMOTEVIEWS" />
-
-        <receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
-            android:exported="true">
-            <intent-filter>
-                <action android:name="es.antonborri.home_widget.action.BACKGROUND" />
-            </intent-filter>
-        </receiver>
-
-        <service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
-            android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
-    </application>
-
-    <meta-data android:name="flutterEmbedding" android:value="2" />
-
-    <!-- Permissions -->
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
-    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
-    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
-</manifest>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
+    <application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
+        android:requestLegacyExternalStorage="true">
+        <activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
+            android:launchMode="singleTop" android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"
+            android:showWhenLocked="true"
+            android:turnScreenOn="true">
+            <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable"
+                android:resource="@drawable/launch_background" />
+            <meta-data android:name="io.flutter.embedding.android.NormalTheme"
+                android:resource="@style/NormalTheme" />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <intent-filter android:autoVerify="true">
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <!-- Accepts URIs that begin with https://api.refilcapp.hu -->
+                <data
+                    android:scheme="https"
+                    android:host="api.refilcapp.hu"
+                    android:pathPrefix="/v1/auth/callback" />
+            </intent-filter>
+            <intent-filter android:autoVerify="true">
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <!-- Accepts URIs that begin with https://refilc.hu -->
+                <data
+                    android:scheme="https"
+                    android:host="refilc.hu"
+                    android:pathPrefix="/app" />
+            </intent-filter>
+        </activity>
+        <meta-data android:name="flutterEmbedding" android:value="2" />
+
+        <receiver android:name="hu.refilc.naplo.widget_timetable.WidgetTimetable"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_LEFT" />
+                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT" />
+                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_TODAY" />
+                <action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH" />
+                <action android:name="list_widget.ACTION_WIDGET_CLICK_BUY_PREMIUM" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/home_widget_test_info" />
+        </receiver>
+
+        <service android:name="hu.refilc.naplo.widget_timetable.WidgetTimetableService"
+            android:permission="android.permission.BIND_REMOTEVIEWS" />
+
+        <receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="es.antonborri.home_widget.action.BACKGROUND" />
+            </intent-filter>
+        </receiver>
+
+        <service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
+            android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
+    </application>
+
+    <meta-data android:name="flutterEmbedding" android:value="2" />
+
+    <!-- Permissions -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+</manifest>
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/MainActivity.java b/refilc/android/app/src/main/java/hu/refilc/naplo/MainActivity.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/MainActivity.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/MainActivity.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/database/DBManager.java b/refilc/android/app/src/main/java/hu/refilc/naplo/database/DBManager.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/database/DBManager.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/database/DBManager.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/database/SQLiteHelper.java b/refilc/android/app/src/main/java/hu/refilc/naplo/database/SQLiteHelper.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/database/SQLiteHelper.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/database/SQLiteHelper.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/utils/Utils.java b/refilc/android/app/src/main/java/hu/refilc/naplo/utils/Utils.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/utils/Utils.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/utils/Utils.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/utils/Week.java b/refilc/android/app/src/main/java/hu/refilc/naplo/utils/Week.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/utils/Week.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/utils/Week.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetable.java b/refilc/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetable.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetable.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetable.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableDataProvider.java b/refilc/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableDataProvider.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableDataProvider.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableDataProvider.java
diff --git a/filcnaplo/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableService.java b/refilc/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableService.java
similarity index 100%
rename from filcnaplo/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableService.java
rename to refilc/android/app/src/main/java/hu/refilc/naplo/widget_timetable/WidgetTimetableService.java
diff --git a/filcnaplo/android/app/src/main/res/drawable-hdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-hdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-hdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-hdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-hdpi/ic_stat_splash_logo.png b/refilc/android/app/src/main/res/drawable-hdpi/ic_stat_splash_logo.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-hdpi/ic_stat_splash_logo.png
rename to refilc/android/app/src/main/res/drawable-hdpi/ic_stat_splash_logo.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-hdpi/splash.png b/refilc/android/app/src/main/res/drawable-hdpi/splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-hdpi/splash.png
rename to refilc/android/app/src/main/res/drawable-hdpi/splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-hdpi/tinta_image.png b/refilc/android/app/src/main/res/drawable-hdpi/tinta_image.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-hdpi/tinta_image.png
rename to refilc/android/app/src/main/res/drawable-hdpi/tinta_image.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-mdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-mdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-mdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-mdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-mdpi/ic_stat_splash_logo.png b/refilc/android/app/src/main/res/drawable-mdpi/ic_stat_splash_logo.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-mdpi/ic_stat_splash_logo.png
rename to refilc/android/app/src/main/res/drawable-mdpi/ic_stat_splash_logo.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-mdpi/splash.png b/refilc/android/app/src/main/res/drawable-mdpi/splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-mdpi/splash.png
rename to refilc/android/app/src/main/res/drawable-mdpi/splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-night-hdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-night-hdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-night-hdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-night-hdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-night-mdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-night-mdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-night-mdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-night-mdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-night-xhdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-night-xhdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-night-xhdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-night-xhdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_check.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_check.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_check.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_check.xml
index 4545224..62d6723 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_check.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_check.xml
@@ -1,13 +1,13 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M20,6l-11,11l-5,-5"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-</vector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M20,6l-11,11l-5,-5"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_chevron_left.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_chevron_left.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_chevron_left.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_chevron_left.xml
index a7f5dd6..01e9d40 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_chevron_left.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_chevron_left.xml
@@ -1,13 +1,13 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M15,18l-6,-6l6,-6"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-</vector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M15,18l-6,-6l6,-6"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_chevron_right.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_chevron_right.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_chevron_right.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_chevron_right.xml
index 93ad67e..c1e9015 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_chevron_right.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_chevron_right.xml
@@ -1,13 +1,13 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M9,18l6,-6l-6,-6"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-</vector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M9,18l6,-6l-6,-6"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_droplet.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_droplet.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_droplet.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_droplet.xml
index 865d06c..cc3690b 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_droplet.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_droplet.xml
@@ -1,13 +1,13 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M12,2.69l5.66,5.66a8,8 0,1 1,-11.31 0z"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-</vector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M12,2.69l5.66,5.66a8,8 0,1 1,-11.31 0z"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_launcher_background.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_launcher_background.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_launcher_background.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_launcher_background.xml
index a4f78de..07d5da9 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_launcher_background.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_launcher_background.xml
@@ -1,170 +1,170 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="108dp"
-    android:height="108dp"
-    android:viewportWidth="108"
-    android:viewportHeight="108">
-    <path
-        android:fillColor="#3DDC84"
-        android:pathData="M0,0h108v108h-108z" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M9,0L9,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,0L19,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M29,0L29,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M39,0L39,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M49,0L49,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M59,0L59,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M69,0L69,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M79,0L79,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M89,0L89,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M99,0L99,108"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,9L108,9"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,19L108,19"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,29L108,29"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,39L108,39"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,49L108,49"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,59L108,59"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,69L108,69"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,79L108,79"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,89L108,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0,99L108,99"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,29L89,29"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,39L89,39"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,49L89,49"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,59L89,59"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,69L89,69"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M19,79L89,79"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M29,19L29,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M39,19L39,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M49,19L49,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M59,19L59,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M69,19L69,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M79,19L79,89"
-        android:strokeWidth="0.8"
-        android:strokeColor="#33FFFFFF" />
-</vector>
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#3DDC84"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_launcher_foreground.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_launcher_foreground.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_launcher_foreground.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_launcher_foreground.xml
index cc14f03..2b068d1 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_launcher_foreground.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_launcher_foreground.xml
@@ -1,30 +1,30 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:aapt="http://schemas.android.com/aapt"
-    android:width="108dp"
-    android:height="108dp"
-    android:viewportWidth="108"
-    android:viewportHeight="108">
-    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
-        <aapt:attr name="android:fillColor">
-            <gradient
-                android:endX="85.84757"
-                android:endY="92.4963"
-                android:startX="42.9492"
-                android:startY="49.59793"
-                android:type="linear">
-                <item
-                    android:color="#44000000"
-                    android:offset="0.0" />
-                <item
-                    android:color="#00000000"
-                    android:offset="1.0" />
-            </gradient>
-        </aapt:attr>
-    </path>
-    <path
-        android:fillColor="#FFFFFF"
-        android:fillType="nonZero"
-        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
-        android:strokeWidth="1"
-        android:strokeColor="#00000000" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="85.84757"
+                android:endY="92.4963"
+                android:startX="42.9492"
+                android:startY="49.59793"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
 </vector>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_navigation_2.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_navigation_2.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_navigation_2.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_navigation_2.xml
index 90b35d8..273720c 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_navigation_2.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_navigation_2.xml
@@ -1,13 +1,13 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M12,2l7,19l-7,-4l-7,4l7,-19z"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-</vector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M12,2l7,19l-7,-4l-7,4l7,-19z"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_refresh_cw.xml b/refilc/android/app/src/main/res/drawable-nodpi/ic_refresh_cw.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/drawable-nodpi/ic_refresh_cw.xml
rename to refilc/android/app/src/main/res/drawable-nodpi/ic_refresh_cw.xml
index 289cd49..f2365a8 100644
--- a/filcnaplo/android/app/src/main/res/drawable-nodpi/ic_refresh_cw.xml
+++ b/refilc/android/app/src/main/res/drawable-nodpi/ic_refresh_cw.xml
@@ -1,27 +1,27 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M23,4l0,6l-6,0"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-  <path
-      android:pathData="M1,20l0,-6l6,0"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-  <path
-      android:pathData="M3.51,9a9,9 0,0 1,14.85 -3.36L23,10M1,14l4.64,4.36A9,9 0,0 0,20.49 15"
-      android:strokeLineJoin="round"
-      android:strokeWidth="2"
-      android:fillColor="#00000000"
-      android:strokeColor="#ff141516"
-      android:strokeLineCap="round"/>
-</vector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M23,4l0,6l-6,0"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+  <path
+      android:pathData="M1,20l0,-6l6,0"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+  <path
+      android:pathData="M3.51,9a9,9 0,0 1,14.85 -3.36L23,10M1,14l4.64,4.36A9,9 0,0 0,20.49 15"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ff141516"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/filcnaplo/android/app/src/main/res/drawable-v21/app_widget_background.xml b/refilc/android/app/src/main/res/drawable-v21/app_widget_background.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable-v21/app_widget_background.xml
rename to refilc/android/app/src/main/res/drawable-v21/app_widget_background.xml
index 6721d42..785445c 100644
--- a/filcnaplo/android/app/src/main/res/drawable-v21/app_widget_background.xml
+++ b/refilc/android/app/src/main/res/drawable-v21/app_widget_background.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-Background for widgets to make the rounded corners based on the
-appWidgetRadius attribute value
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <corners android:radius="?attr/appWidgetRadius" />
-    <solid android:color="?android:attr/colorBackground" />
+<?xml version="1.0" encoding="utf-8"?><!--
+Background for widgets to make the rounded corners based on the
+appWidgetRadius attribute value
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners android:radius="?attr/appWidgetRadius" />
+    <solid android:color="?android:attr/colorBackground" />
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-v21/app_widget_inner_view_background.xml b/refilc/android/app/src/main/res/drawable-v21/app_widget_inner_view_background.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable-v21/app_widget_inner_view_background.xml
rename to refilc/android/app/src/main/res/drawable-v21/app_widget_inner_view_background.xml
index 5ae60cf..007e287 100644
--- a/filcnaplo/android/app/src/main/res/drawable-v21/app_widget_inner_view_background.xml
+++ b/refilc/android/app/src/main/res/drawable-v21/app_widget_inner_view_background.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-Background for views inside widgets to make the rounded corners based on the
-appWidgetInnerRadius attribute value
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <corners android:radius="?attr/appWidgetInnerRadius" />
-    <solid android:color="?android:attr/colorAccent" />
+<?xml version="1.0" encoding="utf-8"?><!--
+Background for views inside widgets to make the rounded corners based on the
+appWidgetInnerRadius attribute value
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners android:radius="?attr/appWidgetInnerRadius" />
+    <solid android:color="?android:attr/colorAccent" />
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-v21/background.png b/refilc/android/app/src/main/res/drawable-v21/background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-v21/background.png
rename to refilc/android/app/src/main/res/drawable-v21/background.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-v21/launch_background.xml b/refilc/android/app/src/main/res/drawable-v21/launch_background.xml
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-v21/launch_background.xml
rename to refilc/android/app/src/main/res/drawable-v21/launch_background.xml
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-xhdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-xhdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_bg.xml b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_bg.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_bg.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/card_layout_bg.xml
index 0def536..860b811 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_bg.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_bg.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/white"/>
-    <stroke android:width="1dp" android:color="#D8E0E1" />
-    <corners android:radius="10dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/white"/>
+    <stroke android:width="1dp" android:color="#D8E0E1" />
+    <corners android:radius="10dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile.xml b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile.xml
index f12f731..6466eba 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#00FFFFFF"/>
-    <corners android:radius="10dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#00FFFFFF"/>
+    <corners android:radius="10dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile_elmarad.xml b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile_elmarad.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile_elmarad.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile_elmarad.xml
index ee09eea..426d5c1 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile_elmarad.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile_elmarad.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/light_red"/>
-    <corners android:radius="10dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/light_red"/>
+    <corners android:radius="10dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile_helyetesitett.xml b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile_helyetesitett.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile_helyetesitett.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile_helyetesitett.xml
index 030aaf2..6e5cbff 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/card_layout_tile_helyetesitett.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/card_layout_tile_helyetesitett.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/light_yellow"/>
-    <corners android:radius="10dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/light_yellow"/>
+    <corners android:radius="10dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/ic_stat_splash_logo.png b/refilc/android/app/src/main/res/drawable-xhdpi/ic_stat_splash_logo.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/ic_stat_splash_logo.png
rename to refilc/android/app/src/main/res/drawable-xhdpi/ic_stat_splash_logo.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/splash.png b/refilc/android/app/src/main/res/drawable-xhdpi/splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/splash.png
rename to refilc/android/app/src/main/res/drawable-xhdpi/splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/timetable_widget_preview.png b/refilc/android/app/src/main/res/drawable-xhdpi/timetable_widget_preview.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/timetable_widget_preview.png
rename to refilc/android/app/src/main/res/drawable-xhdpi/timetable_widget_preview.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_bottom.xml b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_bottom.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_bottom.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/widget_card_bottom.xml
index 80b52be..8a99162 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_bottom.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_bottom.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/highlight_light"/>
-    <stroke android:width="1dp" android:color="@color/highlight_light" />
-    <corners android:bottomLeftRadius="14dp" android:bottomRightRadius="14dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/highlight_light"/>
+    <stroke android:width="1dp" android:color="@color/highlight_light" />
+    <corners android:bottomLeftRadius="14dp" android:bottomRightRadius="14dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_bottom_dark.xml b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_bottom_dark.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_bottom_dark.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/widget_card_bottom_dark.xml
index f2d52b0..2551ee3 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_bottom_dark.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_bottom_dark.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/highlight"/>
-    <stroke android:width="1dp" android:color="@color/highlight" />
-    <corners android:bottomLeftRadius="14dp" android:bottomRightRadius="14dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/highlight"/>
+    <stroke android:width="1dp" android:color="@color/highlight" />
+    <corners android:bottomLeftRadius="14dp" android:bottomRightRadius="14dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_top.xml b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_top.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_top.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/widget_card_top.xml
index a37fed6..e0e9376 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_top.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_top.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/highlight_light"/>
-    <stroke android:width="1dp" android:color="@color/highlight_light" />
-    <corners android:topLeftRadius="14dp" android:topRightRadius="14dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/highlight_light"/>
+    <stroke android:width="1dp" android:color="@color/highlight_light" />
+    <corners android:topLeftRadius="14dp" android:topRightRadius="14dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_top_dark.xml b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_top_dark.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_top_dark.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/widget_card_top_dark.xml
index c41e2b5..4bbd0bb 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_card_top_dark.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/widget_card_top_dark.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/highlight"/>
-    <stroke android:width="1dp" android:color="@color/highlight" />
-    <corners android:topLeftRadius="14dp" android:topRightRadius="14dp"/>
-    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/highlight"/>
+    <stroke android:width="1dp" android:color="@color/highlight" />
+    <corners android:topLeftRadius="14dp" android:topRightRadius="14dp"/>
+    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp"/>
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_scroll_style.xml b/refilc/android/app/src/main/res/drawable-xhdpi/widget_scroll_style.xml
similarity index 94%
rename from filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_scroll_style.xml
rename to refilc/android/app/src/main/res/drawable-xhdpi/widget_scroll_style.xml
index a4eab7e..a8f281e 100644
--- a/filcnaplo/android/app/src/main/res/drawable-xhdpi/widget_scroll_style.xml
+++ b/refilc/android/app/src/main/res/drawable-xhdpi/widget_scroll_style.xml
@@ -1,17 +1,17 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <!--<gradient
-        android:angle="45"
-        android:endColor="@color/filc"
-        android:startColor="@color/filc" />-->
-
-    <solid android:color="@color/highlight_light"/>
-
-    <corners android:radius="12dp" />
-    <size android:width="2dp"/>
-    <padding
-        android:left="0.5dp"
-        android:right="0.5dp" />
-
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <!--<gradient
+        android:angle="45"
+        android:endColor="@color/filc"
+        android:startColor="@color/filc" />-->
+
+    <solid android:color="@color/highlight_light"/>
+
+    <corners android:radius="12dp" />
+    <size android:width="2dp"/>
+    <padding
+        android:left="0.5dp"
+        android:right="0.5dp" />
+
 </shape>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxhdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-xxhdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxhdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-xxhdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxhdpi/ic_stat_splash_logo.png b/refilc/android/app/src/main/res/drawable-xxhdpi/ic_stat_splash_logo.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxhdpi/ic_stat_splash_logo.png
rename to refilc/android/app/src/main/res/drawable-xxhdpi/ic_stat_splash_logo.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxhdpi/splash.png b/refilc/android/app/src/main/res/drawable-xxhdpi/splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxhdpi/splash.png
rename to refilc/android/app/src/main/res/drawable-xxhdpi/splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxxhdpi/android12splash.png b/refilc/android/app/src/main/res/drawable-xxxhdpi/android12splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxxhdpi/android12splash.png
rename to refilc/android/app/src/main/res/drawable-xxxhdpi/android12splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxxhdpi/ic_stat_splash_logo.png b/refilc/android/app/src/main/res/drawable-xxxhdpi/ic_stat_splash_logo.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxxhdpi/ic_stat_splash_logo.png
rename to refilc/android/app/src/main/res/drawable-xxxhdpi/ic_stat_splash_logo.png
diff --git a/filcnaplo/android/app/src/main/res/drawable-xxxhdpi/splash.png b/refilc/android/app/src/main/res/drawable-xxxhdpi/splash.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable-xxxhdpi/splash.png
rename to refilc/android/app/src/main/res/drawable-xxxhdpi/splash.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/background.png b/refilc/android/app/src/main/res/drawable/background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/background.png
rename to refilc/android/app/src/main/res/drawable/background.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/btn_shape.xml b/refilc/android/app/src/main/res/drawable/btn_shape.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable/btn_shape.xml
rename to refilc/android/app/src/main/res/drawable/btn_shape.xml
index b820ec8..d91b3b2 100644
--- a/filcnaplo/android/app/src/main/res/drawable/btn_shape.xml
+++ b/refilc/android/app/src/main/res/drawable/btn_shape.xml
@@ -1,18 +1,18 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="true">
-        <shape android:shape="rectangle">
-            <solid android:color="#ffE0CCEC"></solid>
-            <corners android:radius="10dp" />
-        </shape>
-    </item>
-
-    <item>
-        <shape android:shape="rectangle">
-            <gradient android:endColor="#ffE0CCEC" android:startColor="#ffC9ABDC" />
-            <corners android:radius="10dp" />
-        </shape>
-    </item>
-
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="true">
+        <shape android:shape="rectangle">
+            <solid android:color="#ffE0CCEC"></solid>
+            <corners android:radius="10dp" />
+        </shape>
+    </item>
+
+    <item>
+        <shape android:shape="rectangle">
+            <gradient android:endColor="#ffE0CCEC" android:startColor="#ffC9ABDC" />
+            <corners android:radius="10dp" />
+        </shape>
+    </item>
+
 </selector>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable/btn_shape_login.xml b/refilc/android/app/src/main/res/drawable/btn_shape_login.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/drawable/btn_shape_login.xml
rename to refilc/android/app/src/main/res/drawable/btn_shape_login.xml
index 84bb6fe..22c1d8f 100644
--- a/filcnaplo/android/app/src/main/res/drawable/btn_shape_login.xml
+++ b/refilc/android/app/src/main/res/drawable/btn_shape_login.xml
@@ -1,18 +1,18 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="true">
-        <shape android:shape="rectangle">
-            <solid android:color="#ff1D8868"></solid>
-            <corners android:radius="10dp" />
-        </shape>
-    </item>
-
-    <item>
-        <shape android:shape="rectangle">
-            <gradient android:endColor="#ff1D8868" android:startColor="#ff1EA18F" />
-            <corners android:radius="10dp" />
-        </shape>
-    </item>
-
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="true">
+        <shape android:shape="rectangle">
+            <solid android:color="#ff1D8868"></solid>
+            <corners android:radius="10dp" />
+        </shape>
+    </item>
+
+    <item>
+        <shape android:shape="rectangle">
+            <gradient android:endColor="#ff1D8868" android:startColor="#ff1EA18F" />
+            <corners android:radius="10dp" />
+        </shape>
+    </item>
+
 </selector>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/drawable/ic_absences.png b/refilc/android/app/src/main/res/drawable/ic_absences.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/ic_absences.png
rename to refilc/android/app/src/main/res/drawable/ic_absences.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/ic_grades.png b/refilc/android/app/src/main/res/drawable/ic_grades.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/ic_grades.png
rename to refilc/android/app/src/main/res/drawable/ic_grades.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/ic_home.png b/refilc/android/app/src/main/res/drawable/ic_home.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/ic_home.png
rename to refilc/android/app/src/main/res/drawable/ic_home.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/ic_messages.png b/refilc/android/app/src/main/res/drawable/ic_messages.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/ic_messages.png
rename to refilc/android/app/src/main/res/drawable/ic_messages.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/ic_notification.png b/refilc/android/app/src/main/res/drawable/ic_notification.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/ic_notification.png
rename to refilc/android/app/src/main/res/drawable/ic_notification.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/ic_timetable.png b/refilc/android/app/src/main/res/drawable/ic_timetable.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/ic_timetable.png
rename to refilc/android/app/src/main/res/drawable/ic_timetable.png
diff --git a/filcnaplo/android/app/src/main/res/drawable/launch_background.xml b/refilc/android/app/src/main/res/drawable/launch_background.xml
similarity index 100%
rename from filcnaplo/android/app/src/main/res/drawable/launch_background.xml
rename to refilc/android/app/src/main/res/drawable/launch_background.xml
diff --git a/filcnaplo/android/app/src/main/res/font/montserrat_medium.ttf b/refilc/android/app/src/main/res/font/montserrat_medium.ttf
similarity index 100%
rename from filcnaplo/android/app/src/main/res/font/montserrat_medium.ttf
rename to refilc/android/app/src/main/res/font/montserrat_medium.ttf
diff --git a/filcnaplo/android/app/src/main/res/ic_launcher-web.png b/refilc/android/app/src/main/res/ic_launcher-web.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/ic_launcher-web.png
rename to refilc/android/app/src/main/res/ic_launcher-web.png
diff --git a/filcnaplo/android/app/src/main/res/layout/home_widget_test.xml b/refilc/android/app/src/main/res/layout/home_widget_test.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/layout/home_widget_test.xml
rename to refilc/android/app/src/main/res/layout/home_widget_test.xml
index b12af8d..f0a315a 100644
--- a/filcnaplo/android/app/src/main/res/layout/home_widget_test.xml
+++ b/refilc/android/app/src/main/res/layout/home_widget_test.xml
@@ -1,26 +1,26 @@
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_margin="8dp"
-    android:orientation="vertical"
-    android:background="@drawable/app_widget_background"
-    android:padding="8dp"
-    android:id="@+id/widget_container">
-
-    <TextView
-        android:id="@+id/widget_title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="36sp"
-        android:textStyle="bold"
-        tools:text="Title" />
-
-    <TextView
-        android:id="@+id/widget_message"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="18sp"
-        tools:text="Message" />
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_margin="8dp"
+    android:orientation="vertical"
+    android:background="@drawable/app_widget_background"
+    android:padding="8dp"
+    android:id="@+id/widget_container">
+
+    <TextView
+        android:id="@+id/widget_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="36sp"
+        android:textStyle="bold"
+        tools:text="Title" />
+
+    <TextView
+        android:id="@+id/widget_message"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="18sp"
+        tools:text="Message" />
 </LinearLayout>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/layout/timetable_item.xml b/refilc/android/app/src/main/res/layout/timetable_item.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/layout/timetable_item.xml
rename to refilc/android/app/src/main/res/layout/timetable_item.xml
index aa23af8..f057d2d 100644
--- a/filcnaplo/android/app/src/main/res/layout/timetable_item.xml
+++ b/refilc/android/app/src/main/res/layout/timetable_item.xml
@@ -1,113 +1,113 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:id="@+id/main_lay"
-    android:layout_height="50dp"
-    android:paddingTop="0dp"
-    android:paddingBottom="0dp"
-    android:layout_marginTop="2.5dp"
-    android:layout_marginBottom="2.5dp"
-    android:layout_marginLeft="7.5dp"
-    android:layout_marginRight="7.5dp"
-    android:background="@drawable/card_layout_tile">
-
-    <TextView
-        android:id="@+id/tt_item_num"
-        android:layout_width="50dp"
-        android:layout_height="match_parent"
-        android:fontFamily="@font/montserrat_medium"
-        android:gravity="center"
-        android:text="1."
-        android:textColor="@color/filc"
-        android:textColorLink="#ff3D7BF4"
-        android:textSize="30sp"
-        android:textStyle="bold"
-        tools:ignore="HardcodedText" />
-
-    <TextView
-        android:id="@+id/tt_item_name"
-        android:layout_width="match_parent"
-        android:layout_height="20dp"
-        android:textSize="15.5sp"
-        android:textFontWeight="700"
-        android:fontFamily="@font/montserrat_medium"
-        android:layout_marginTop="2.5dp"
-        android:text="Óra neve"
-        android:maxLines="1"
-        android:ellipsize="end"
-        android:layout_toStartOf="@id/tt_item_room"
-        android:gravity="center_vertical"
-        android:layout_toEndOf="@id/tt_item_num"
-        android:textColor="@color/text"
-        tools:ignore="HardcodedText" />
-
-    <TextView
-        android:id="@+id/tt_item_name_nodesc"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:textSize="15.5sp"
-        android:textStyle="bold"
-        android:fontFamily="@font/montserrat_medium"
-        android:visibility="gone"
-        android:layout_marginTop="2.5dp"
-        android:layout_toStartOf="@id/tt_item_room"
-        android:text="Óra neve"
-        android:maxLines="1"
-        android:ellipsize="end"
-        android:gravity="center_vertical"
-        android:layout_toEndOf="@id/tt_item_num"
-        android:textColor="@color/text"
-        tools:ignore="HardcodedText" />
-
-    <TextView
-        android:id="@+id/tt_item_desc"
-        android:layout_width="match_parent"
-        android:layout_height="20dp"
-        android:textSize="14sp"
-        android:textStyle="bold"
-        android:textFontWeight="600"
-        android:fontFamily="@font/montserrat_medium"
-        android:text="Óra leírása"
-        android:maxLines="1"
-        android:ellipsize="end"
-        android:gravity="center_vertical"
-        android:layout_toEndOf="@id/tt_item_num"
-        android:layout_toStartOf="@id/tt_item_room"
-        android:layout_below="@id/tt_item_name"
-        android:textColor="@color/text_desc"
-        tools:ignore="HardcodedText" />
-
-    <TextView
-        android:id="@+id/tt_item_room"
-        android:layout_width="40dp"
-        android:layout_height="match_parent"
-        android:textSize="14sp"
-        android:textFontWeight="500"
-        android:fontFamily="@font/montserrat_medium"
-        android:textStyle="bold"
-        android:text="56."
-        android:ellipsize="end"
-        android:maxLines="2"
-        android:gravity="center"
-        android:layout_toStartOf="@id/tt_item_time"
-        android:textColor="@color/text_desc"
-        tools:ignore="HardcodedText" />
-
-    <TextView
-        android:id="@+id/tt_item_time"
-        android:layout_width="50dp"
-        android:layout_height="match_parent"
-        android:textSize="14sp"
-        android:textFontWeight="500"
-        android:fontFamily="@font/montserrat_medium"
-        android:textStyle="bold"
-        android:layout_marginStart="2dp"
-        android:layout_marginTop="-2dp"
-        android:text="8:30\n9:10"
-        android:gravity="center"
-        android:layout_alignParentEnd="true"
-        android:textColor="@color/white"
-        tools:ignore="HardcodedText" />
-
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:id="@+id/main_lay"
+    android:layout_height="50dp"
+    android:paddingTop="0dp"
+    android:paddingBottom="0dp"
+    android:layout_marginTop="2.5dp"
+    android:layout_marginBottom="2.5dp"
+    android:layout_marginLeft="7.5dp"
+    android:layout_marginRight="7.5dp"
+    android:background="@drawable/card_layout_tile">
+
+    <TextView
+        android:id="@+id/tt_item_num"
+        android:layout_width="50dp"
+        android:layout_height="match_parent"
+        android:fontFamily="@font/montserrat_medium"
+        android:gravity="center"
+        android:text="1."
+        android:textColor="@color/filc"
+        android:textColorLink="#ff3D7BF4"
+        android:textSize="30sp"
+        android:textStyle="bold"
+        tools:ignore="HardcodedText" />
+
+    <TextView
+        android:id="@+id/tt_item_name"
+        android:layout_width="match_parent"
+        android:layout_height="20dp"
+        android:textSize="15.5sp"
+        android:textFontWeight="700"
+        android:fontFamily="@font/montserrat_medium"
+        android:layout_marginTop="2.5dp"
+        android:text="Óra neve"
+        android:maxLines="1"
+        android:ellipsize="end"
+        android:layout_toStartOf="@id/tt_item_room"
+        android:gravity="center_vertical"
+        android:layout_toEndOf="@id/tt_item_num"
+        android:textColor="@color/text"
+        tools:ignore="HardcodedText" />
+
+    <TextView
+        android:id="@+id/tt_item_name_nodesc"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:textSize="15.5sp"
+        android:textStyle="bold"
+        android:fontFamily="@font/montserrat_medium"
+        android:visibility="gone"
+        android:layout_marginTop="2.5dp"
+        android:layout_toStartOf="@id/tt_item_room"
+        android:text="Óra neve"
+        android:maxLines="1"
+        android:ellipsize="end"
+        android:gravity="center_vertical"
+        android:layout_toEndOf="@id/tt_item_num"
+        android:textColor="@color/text"
+        tools:ignore="HardcodedText" />
+
+    <TextView
+        android:id="@+id/tt_item_desc"
+        android:layout_width="match_parent"
+        android:layout_height="20dp"
+        android:textSize="14sp"
+        android:textStyle="bold"
+        android:textFontWeight="600"
+        android:fontFamily="@font/montserrat_medium"
+        android:text="Óra leírása"
+        android:maxLines="1"
+        android:ellipsize="end"
+        android:gravity="center_vertical"
+        android:layout_toEndOf="@id/tt_item_num"
+        android:layout_toStartOf="@id/tt_item_room"
+        android:layout_below="@id/tt_item_name"
+        android:textColor="@color/text_desc"
+        tools:ignore="HardcodedText" />
+
+    <TextView
+        android:id="@+id/tt_item_room"
+        android:layout_width="40dp"
+        android:layout_height="match_parent"
+        android:textSize="14sp"
+        android:textFontWeight="500"
+        android:fontFamily="@font/montserrat_medium"
+        android:textStyle="bold"
+        android:text="56."
+        android:ellipsize="end"
+        android:maxLines="2"
+        android:gravity="center"
+        android:layout_toStartOf="@id/tt_item_time"
+        android:textColor="@color/text_desc"
+        tools:ignore="HardcodedText" />
+
+    <TextView
+        android:id="@+id/tt_item_time"
+        android:layout_width="50dp"
+        android:layout_height="match_parent"
+        android:textSize="14sp"
+        android:textFontWeight="500"
+        android:fontFamily="@font/montserrat_medium"
+        android:textStyle="bold"
+        android:layout_marginStart="2dp"
+        android:layout_marginTop="-2dp"
+        android:text="8:30\n9:10"
+        android:gravity="center"
+        android:layout_alignParentEnd="true"
+        android:textColor="@color/white"
+        tools:ignore="HardcodedText" />
+
 </RelativeLayout>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/layout/widget_timetable.xml b/refilc/android/app/src/main/res/layout/widget_timetable.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/layout/widget_timetable.xml
rename to refilc/android/app/src/main/res/layout/widget_timetable.xml
index 69b80b0..86aaea9 100644
--- a/filcnaplo/android/app/src/main/res/layout/widget_timetable.xml
+++ b/refilc/android/app/src/main/res/layout/widget_timetable.xml
@@ -1,232 +1,232 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_margin="@dimen/widget_margin">
-
-    <RelativeLayout
-        android:id="@+id/tt_grid_cont"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:backgroundTint="#00000000"
-        android:background="@drawable/card_layout_bg"
-        android:orientation="vertical">
-
-
-        <TextView
-            android:id="@+id/empty_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center"
-            android:text="Üres / Empty"
-            android:background="@drawable/widget_card_bottom_dark"
-            android:textColor="@color/text"
-            android:textSize="20sp"
-            android:textStyle="bold"
-            tools:ignore="HardcodedText" />
-
-        <ListView
-            android:id="@+id/widget_list"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_below="@id/bottom_nav"
-            android:layout_marginTop="-8dp"
-            android:background="@drawable/widget_card_bottom_dark"
-            android:divider="#00000000"
-            android:paddingTop="5dp"
-            android:paddingBottom="16dp"
-            android:scrollbarFadeDuration="150"
-            android:scrollbarSize="10dp"
-            android:scrollbarThumbVertical="@drawable/widget_scroll_style" />
-
-        <RelativeLayout
-            android:id="@+id/bottom_nav"
-            android:layout_width="match_parent"
-            android:layout_height="45dp"
-            android:background="@drawable/widget_card_top_dark">
-
-            <ImageView
-                android:id="@+id/nav_refresh"
-                android:layout_width="40dp"
-                android:layout_height="match_parent"
-                android:layout_toStartOf="@id/nav_to_left"
-                android:clickable="true"
-                android:foreground="?android:attr/selectableItemBackground"
-                android:padding="10dp"
-                android:src="@drawable/ic_refresh_cw"
-                android:tint="@color/text_desc"
-                tools:ignore="UseAppTint"
-                android:focusable="true" />
-
-            <ImageView
-                android:id="@+id/nav_to_left"
-                android:layout_width="45dp"
-                android:layout_height="match_parent"
-                android:layout_toStartOf="@id/nav_to_right"
-                android:clickable="true"
-                android:foreground="?android:attr/selectableItemBackground"
-                android:padding="10dp"
-                android:src="@drawable/ic_chevron_left"
-                android:tint="@color/text_desc"
-                tools:ignore="UseAppTint"
-                android:focusable="true" />
-
-            <ImageView
-                android:id="@+id/nav_to_right"
-                android:layout_width="45dp"
-                android:layout_height="match_parent"
-                android:layout_alignParentEnd="true"
-                android:layout_marginEnd="5dp"
-                android:clickable="true"
-                android:foreground="?android:attr/selectableItemBackground"
-                android:padding="10dp"
-                android:src="@drawable/ic_chevron_right"
-                android:tint="@color/text_desc"
-                tools:ignore="UseAppTint"
-                android:focusable="true" />
-
-            <TextView
-                android:id="@+id/nav_current"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_alignParentStart="true"
-                android:layout_marginStart="15sp"
-                android:layout_marginTop="2sp"
-                android:layout_toStartOf="@id/nav_refresh"
-                android:fontFamily="@font/montserrat_medium"
-                android:gravity="center_vertical"
-                android:maxLines="1"
-                android:text="Órarend"
-                android:textColor="@color/text"
-                android:textSize="22sp"
-                android:textStyle="bold"
-                tools:ignore="HardcodedText" />
-        </RelativeLayout>
-    </RelativeLayout>
-
-    <RelativeLayout
-        android:visibility="gone"
-        android:id="@+id/need_login"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:backgroundTint="#ffF4F4F4"
-        android:background="@drawable/card_layout_bg"
-        android:orientation="vertical" >
-
-        <!--<ImageView
-            android:layout_width="45dp"
-            android:layout_height="45dp"
-            android:paddingHorizontal="10dp"
-            android:paddingTop="5dp"
-            android:src="@drawable/tinta_icon" />-->
-
-        <ImageView
-            android:id="@+id/iv_1"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:adjustViewBounds="true"
-            android:paddingHorizontal="10dp"
-            android:paddingTop="10dp"
-            android:src="@drawable/tinta_image" />
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/iv_1"
-            android:layout_marginHorizontal="15dp"
-            android:fontFamily="@font/montserrat_medium"
-            android:text="A widget használatához, bejelentkezés szükséges."
-            android:textColor="@color/black"
-            android:paddingTop="10dp"
-            android:textSize="17sp"
-            android:textStyle="bold"
-            tools:ignore="HardcodedText" />
-
-        <Button
-            android:id="@+id/open_login"
-            android:layout_width="match_parent"
-            android:layout_height="40dp"
-            android:layout_alignParentBottom="true"
-            android:background="@drawable/btn_shape_login"
-            android:text="Alkalmazás megnyitása"
-            android:padding="0dp"
-            android:layout_margin="10dp"
-            android:textColor="@color/white"
-            android:fontFamily="@font/montserrat_medium"
-            android:textSize="16sp"
-            android:textStyle="bold"
-            tools:ignore="HardcodedText" />
-
-    </RelativeLayout>
-
-    <RelativeLayout
-        android:visibility="gone"
-        android:id="@+id/need_premium"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:backgroundTint="#ffF4F4F4"
-        android:background="@drawable/card_layout_bg"
-        android:orientation="vertical" >
-
-        <!--<ImageView
-            android:layout_width="45dp"
-            android:layout_height="45dp"
-            android:paddingHorizontal="10dp"
-            android:paddingTop="5dp"
-            android:src="@drawable/tinta_icon" />-->
-
-        <ImageView
-            android:id="@+id/iv_2"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:adjustViewBounds="true"
-            android:paddingHorizontal="10dp"
-            android:paddingTop="10dp"
-            android:src="@drawable/tinta_image" />
-
-        <TextView
-            android:id="@+id/tw_1"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/iv_2"
-            android:layout_marginHorizontal="15dp"
-            android:fontFamily="@font/montserrat_medium"
-            android:text="Órák a kezdőképernyőd kényelméből."
-            android:textColor="@color/black"
-            android:paddingTop="10dp"
-            android:textSize="16sp"
-            android:textStyle="bold"
-            tools:ignore="HardcodedText" />
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/tw_1"
-            android:fontFamily="@font/montserrat_medium"
-            android:text="Támogass Tinta szinten és helyezz egy widgetet a kezdőképernyődre."
-            android:textColor="@color/black"
-            android:layout_marginTop="0dp"
-            android:layout_marginHorizontal="15dp"
-            android:textSize="14sp"
-            tools:ignore="HardcodedText" />
-
-        <Button
-            android:id="@+id/buy_premium"
-            android:layout_width="match_parent"
-            android:layout_height="40dp"
-            android:background="@drawable/btn_shape"
-            android:gravity="center"
-            android:text="Vigyél oda!"
-            android:padding="0dp"
-            android:layout_alignParentBottom="true"
-            android:layout_margin="10dp"
-            android:textColor="#ff691A9B"
-            android:fontFamily="@font/montserrat_medium"
-            android:textSize="16sp"
-            android:textStyle="bold"
-            tools:ignore="HardcodedText" />
-
-    </RelativeLayout>
-
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_margin="@dimen/widget_margin">
+
+    <RelativeLayout
+        android:id="@+id/tt_grid_cont"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:backgroundTint="#00000000"
+        android:background="@drawable/card_layout_bg"
+        android:orientation="vertical">
+
+
+        <TextView
+            android:id="@+id/empty_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center"
+            android:text="Üres / Empty"
+            android:background="@drawable/widget_card_bottom_dark"
+            android:textColor="@color/text"
+            android:textSize="20sp"
+            android:textStyle="bold"
+            tools:ignore="HardcodedText" />
+
+        <ListView
+            android:id="@+id/widget_list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_below="@id/bottom_nav"
+            android:layout_marginTop="-8dp"
+            android:background="@drawable/widget_card_bottom_dark"
+            android:divider="#00000000"
+            android:paddingTop="5dp"
+            android:paddingBottom="16dp"
+            android:scrollbarFadeDuration="150"
+            android:scrollbarSize="10dp"
+            android:scrollbarThumbVertical="@drawable/widget_scroll_style" />
+
+        <RelativeLayout
+            android:id="@+id/bottom_nav"
+            android:layout_width="match_parent"
+            android:layout_height="45dp"
+            android:background="@drawable/widget_card_top_dark">
+
+            <ImageView
+                android:id="@+id/nav_refresh"
+                android:layout_width="40dp"
+                android:layout_height="match_parent"
+                android:layout_toStartOf="@id/nav_to_left"
+                android:clickable="true"
+                android:foreground="?android:attr/selectableItemBackground"
+                android:padding="10dp"
+                android:src="@drawable/ic_refresh_cw"
+                android:tint="@color/text_desc"
+                tools:ignore="UseAppTint"
+                android:focusable="true" />
+
+            <ImageView
+                android:id="@+id/nav_to_left"
+                android:layout_width="45dp"
+                android:layout_height="match_parent"
+                android:layout_toStartOf="@id/nav_to_right"
+                android:clickable="true"
+                android:foreground="?android:attr/selectableItemBackground"
+                android:padding="10dp"
+                android:src="@drawable/ic_chevron_left"
+                android:tint="@color/text_desc"
+                tools:ignore="UseAppTint"
+                android:focusable="true" />
+
+            <ImageView
+                android:id="@+id/nav_to_right"
+                android:layout_width="45dp"
+                android:layout_height="match_parent"
+                android:layout_alignParentEnd="true"
+                android:layout_marginEnd="5dp"
+                android:clickable="true"
+                android:foreground="?android:attr/selectableItemBackground"
+                android:padding="10dp"
+                android:src="@drawable/ic_chevron_right"
+                android:tint="@color/text_desc"
+                tools:ignore="UseAppTint"
+                android:focusable="true" />
+
+            <TextView
+                android:id="@+id/nav_current"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentStart="true"
+                android:layout_marginStart="15sp"
+                android:layout_marginTop="2sp"
+                android:layout_toStartOf="@id/nav_refresh"
+                android:fontFamily="@font/montserrat_medium"
+                android:gravity="center_vertical"
+                android:maxLines="1"
+                android:text="Órarend"
+                android:textColor="@color/text"
+                android:textSize="22sp"
+                android:textStyle="bold"
+                tools:ignore="HardcodedText" />
+        </RelativeLayout>
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:visibility="gone"
+        android:id="@+id/need_login"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:backgroundTint="#ffF4F4F4"
+        android:background="@drawable/card_layout_bg"
+        android:orientation="vertical" >
+
+        <!--<ImageView
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:paddingHorizontal="10dp"
+            android:paddingTop="5dp"
+            android:src="@drawable/tinta_icon" />-->
+
+        <ImageView
+            android:id="@+id/iv_1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:adjustViewBounds="true"
+            android:paddingHorizontal="10dp"
+            android:paddingTop="10dp"
+            android:src="@drawable/tinta_image" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/iv_1"
+            android:layout_marginHorizontal="15dp"
+            android:fontFamily="@font/montserrat_medium"
+            android:text="A widget használatához, bejelentkezés szükséges."
+            android:textColor="@color/black"
+            android:paddingTop="10dp"
+            android:textSize="17sp"
+            android:textStyle="bold"
+            tools:ignore="HardcodedText" />
+
+        <Button
+            android:id="@+id/open_login"
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:layout_alignParentBottom="true"
+            android:background="@drawable/btn_shape_login"
+            android:text="Alkalmazás megnyitása"
+            android:padding="0dp"
+            android:layout_margin="10dp"
+            android:textColor="@color/white"
+            android:fontFamily="@font/montserrat_medium"
+            android:textSize="16sp"
+            android:textStyle="bold"
+            tools:ignore="HardcodedText" />
+
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:visibility="gone"
+        android:id="@+id/need_premium"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:backgroundTint="#ffF4F4F4"
+        android:background="@drawable/card_layout_bg"
+        android:orientation="vertical" >
+
+        <!--<ImageView
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:paddingHorizontal="10dp"
+            android:paddingTop="5dp"
+            android:src="@drawable/tinta_icon" />-->
+
+        <ImageView
+            android:id="@+id/iv_2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:adjustViewBounds="true"
+            android:paddingHorizontal="10dp"
+            android:paddingTop="10dp"
+            android:src="@drawable/tinta_image" />
+
+        <TextView
+            android:id="@+id/tw_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/iv_2"
+            android:layout_marginHorizontal="15dp"
+            android:fontFamily="@font/montserrat_medium"
+            android:text="Órák a kezdőképernyőd kényelméből."
+            android:textColor="@color/black"
+            android:paddingTop="10dp"
+            android:textSize="16sp"
+            android:textStyle="bold"
+            tools:ignore="HardcodedText" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/tw_1"
+            android:fontFamily="@font/montserrat_medium"
+            android:text="Támogass Tinta szinten és helyezz egy widgetet a kezdőképernyődre."
+            android:textColor="@color/black"
+            android:layout_marginTop="0dp"
+            android:layout_marginHorizontal="15dp"
+            android:textSize="14sp"
+            tools:ignore="HardcodedText" />
+
+        <Button
+            android:id="@+id/buy_premium"
+            android:layout_width="match_parent"
+            android:layout_height="40dp"
+            android:background="@drawable/btn_shape"
+            android:gravity="center"
+            android:text="Vigyél oda!"
+            android:padding="0dp"
+            android:layout_alignParentBottom="true"
+            android:layout_margin="10dp"
+            android:textColor="#ff691A9B"
+            android:fontFamily="@font/montserrat_medium"
+            android:textSize="16sp"
+            android:textStyle="bold"
+            tools:ignore="HardcodedText" />
+
+    </RelativeLayout>
+
 </RelativeLayout>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/refilc/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
rename to refilc/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
diff --git a/filcnaplo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/refilc/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
similarity index 98%
rename from filcnaplo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
rename to refilc/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index 9173f3f..456e2d5 100644
--- a/filcnaplo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/refilc/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-  <background android:drawable="@mipmap/ic_launcher_background"/>
-  <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
-  <monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
-</adaptive-icon>
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+  <background android:drawable="@mipmap/ic_launcher_background"/>
+  <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
+  <monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
+</adaptive-icon>
diff --git a/filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
rename to refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
rename to refilc/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
rename to refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
rename to refilc/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
rename to refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
rename to refilc/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
rename to refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png
rename to refilc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
rename to refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
rename to refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
diff --git a/filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
rename to refilc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
diff --git a/filcnaplo/android/app/src/main/res/playstore-icon.png b/refilc/android/app/src/main/res/playstore-icon.png
similarity index 100%
rename from filcnaplo/android/app/src/main/res/playstore-icon.png
rename to refilc/android/app/src/main/res/playstore-icon.png
diff --git a/filcnaplo/android/app/src/main/res/values-night-v31/styles.xml b/refilc/android/app/src/main/res/values-night-v31/styles.xml
similarity index 100%
rename from filcnaplo/android/app/src/main/res/values-night-v31/styles.xml
rename to refilc/android/app/src/main/res/values-night-v31/styles.xml
diff --git a/filcnaplo/android/app/src/main/res/values-night-v31/themes.xml b/refilc/android/app/src/main/res/values-night-v31/themes.xml
similarity index 95%
rename from filcnaplo/android/app/src/main/res/values-night-v31/themes.xml
rename to refilc/android/app/src/main/res/values-night-v31/themes.xml
index beed9ab..f253c9d 100644
--- a/filcnaplo/android/app/src/main/res/values-night-v31/themes.xml
+++ b/refilc/android/app/src/main/res/values-night-v31/themes.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <!--
-    Having themes.xml for night-v31 because of the priority order of the resource qualifiers.
-    -->
-    <style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
-        <item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
-        <item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
-    </style>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!--
+    Having themes.xml for night-v31 because of the priority order of the resource qualifiers.
+    -->
+    <style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
+        <item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
+        <item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/values-night/styles.xml b/refilc/android/app/src/main/res/values-night/styles.xml
similarity index 97%
rename from filcnaplo/android/app/src/main/res/values-night/styles.xml
rename to refilc/android/app/src/main/res/values-night/styles.xml
index 9b14563..4de7564 100644
--- a/filcnaplo/android/app/src/main/res/values-night/styles.xml
+++ b/refilc/android/app/src/main/res/values-night/styles.xml
@@ -1,19 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
-    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
-        <!-- Show a splash screen on the activity. Automatically removed when
-             Flutter draws its first frame -->
-        <item name="android:windowBackground">@drawable/launch_background</item>
-        <item name="android:windowFullscreen">false</item>
-    </style>
-    <!-- Theme applied to the Android Window as soon as the process has started.
-         This theme determines the color of the Android Window while your
-         Flutter UI initializes, as well as behind your Flutter UI while its
-         running.
-         
-         This Theme is only used starting with V2 of Flutter's Android embedding. -->
-    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
-        <item name="android:windowBackground">?android:colorBackground</item>
-    </style>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             Flutter draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+        <item name="android:windowFullscreen">false</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+         
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/values-v31/styles.xml b/refilc/android/app/src/main/res/values-v31/styles.xml
similarity index 100%
rename from filcnaplo/android/app/src/main/res/values-v31/styles.xml
rename to refilc/android/app/src/main/res/values-v31/styles.xml
diff --git a/filcnaplo/android/app/src/main/res/values-v31/themes.xml b/refilc/android/app/src/main/res/values-v31/themes.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/values-v31/themes.xml
rename to refilc/android/app/src/main/res/values-v31/themes.xml
index 52d24ca..badd306 100644
--- a/filcnaplo/android/app/src/main/res/values-v31/themes.xml
+++ b/refilc/android/app/src/main/res/values-v31/themes.xml
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <!--
-    Having themes.xml for v31 variant because @android:dimen/system_app_widget_background_radius
-     and @android:dimen/system_app_widget_internal_padding requires API level 31
-    -->
-    <style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
-        <item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
-        <item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
-    </style>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!--
+    Having themes.xml for v31 variant because @android:dimen/system_app_widget_background_radius
+     and @android:dimen/system_app_widget_internal_padding requires API level 31
+    -->
+    <style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
+        <item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
+        <item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/values/attrs.xml b/refilc/android/app/src/main/res/values/attrs.xml
similarity index 93%
rename from filcnaplo/android/app/src/main/res/values/attrs.xml
rename to refilc/android/app/src/main/res/values/attrs.xml
index f8430c2..7781ac8 100644
--- a/filcnaplo/android/app/src/main/res/values/attrs.xml
+++ b/refilc/android/app/src/main/res/values/attrs.xml
@@ -1,7 +1,7 @@
-<resources>
-    <declare-styleable name="AppWidgetAttrs">
-        <attr name="appWidgetPadding" format="dimension" />
-        <attr name="appWidgetInnerRadius" format="dimension" />
-        <attr name="appWidgetRadius" format="dimension" />
-    </declare-styleable>
+<resources>
+    <declare-styleable name="AppWidgetAttrs">
+        <attr name="appWidgetPadding" format="dimension" />
+        <attr name="appWidgetInnerRadius" format="dimension" />
+        <attr name="appWidgetRadius" format="dimension" />
+    </declare-styleable>
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/values/colors.xml b/refilc/android/app/src/main/res/values/colors.xml
similarity index 100%
rename from filcnaplo/android/app/src/main/res/values/colors.xml
rename to refilc/android/app/src/main/res/values/colors.xml
diff --git a/filcnaplo/android/app/src/main/res/values/dimens.xml b/refilc/android/app/src/main/res/values/dimens.xml
similarity index 92%
rename from filcnaplo/android/app/src/main/res/values/dimens.xml
rename to refilc/android/app/src/main/res/values/dimens.xml
index 50a85e6..4db8c59 100644
--- a/filcnaplo/android/app/src/main/res/values/dimens.xml
+++ b/refilc/android/app/src/main/res/values/dimens.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <!--
-Refer to App Widget Documentation for margin information
-http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
-    -->
-    <dimen name="widget_margin">0dp</dimen>
-
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!--
+Refer to App Widget Documentation for margin information
+http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
+    -->
+    <dimen name="widget_margin">0dp</dimen>
+
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/values/strings.xml b/refilc/android/app/src/main/res/values/strings.xml
similarity index 94%
rename from filcnaplo/android/app/src/main/res/values/strings.xml
rename to refilc/android/app/src/main/res/values/strings.xml
index 4e16b58..3a76198 100644
--- a/filcnaplo/android/app/src/main/res/values/strings.xml
+++ b/refilc/android/app/src/main/res/values/strings.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="appwidget_text">Órarend Widget</string>
-    <string name="add_widget">Add widget</string>
-    <string name="app_widget_description">Mindig lásd, milyen órád lesz, a kezdőképernyőd kényelméből.</string>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="appwidget_text">Órarend Widget</string>
+    <string name="add_widget">Add widget</string>
+    <string name="app_widget_description">Mindig lásd, milyen órád lesz, a kezdőképernyőd kényelméből.</string>
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/values/styles.xml b/refilc/android/app/src/main/res/values/styles.xml
similarity index 99%
rename from filcnaplo/android/app/src/main/res/values/styles.xml
rename to refilc/android/app/src/main/res/values/styles.xml
index 30e86bc..b66fe75 100644
--- a/filcnaplo/android/app/src/main/res/values/styles.xml
+++ b/refilc/android/app/src/main/res/values/styles.xml
@@ -2,7 +2,7 @@
 <resources>
     <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
     <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
-        <!-- Show a splash screen on the activity. Automatically removed when
+        <!-- Show a splash screen on the activity. Automatically removed when
              Flutter draws its first frame -->
         <item name="android:windowBackground">@drawable/launch_background</item>
         <item name="android:forceDarkAllowed">false</item>
@@ -10,11 +10,11 @@
         <item name="android:windowDrawsSystemBarBackgrounds">false</item>
         <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
     </style>
-    <!-- Theme applied to the Android Window as soon as the process has started.
-         This theme determines the color of the Android Window while your
-         Flutter UI initializes, as well as behind your Flutter UI while its
-         running.
-         
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+         
          This Theme is only used starting with V2 of Flutter's Android embedding. -->
     <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
         <item name="android:windowBackground">?android:colorBackground</item>
diff --git a/filcnaplo/android/app/src/main/res/values/themes.xml b/refilc/android/app/src/main/res/values/themes.xml
similarity index 96%
rename from filcnaplo/android/app/src/main/res/values/themes.xml
rename to refilc/android/app/src/main/res/values/themes.xml
index 5e2e5e0..f6846b8 100644
--- a/filcnaplo/android/app/src/main/res/values/themes.xml
+++ b/refilc/android/app/src/main/res/values/themes.xml
@@ -1,16 +1,16 @@
-<resources>
-    <style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
-        <!-- Radius of the outer bound of widgets to make the rounded corners -->
-        <item name="appWidgetRadius">16dp</item>
-        <!--
-        Radius of the inner view's bound of widgets to make the rounded corners.
-        It needs to be 8dp or less than the value of appWidgetRadius
-        -->
-        <item name="appWidgetInnerRadius">8dp</item>
-    </style>
-
-    <style name="Theme.Android.AppWidgetContainer" parent="Theme.Android.AppWidgetContainerParent">
-        <!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
-        <item name="appWidgetPadding">16dp</item>
-    </style>
+<resources>
+    <style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
+        <!-- Radius of the outer bound of widgets to make the rounded corners -->
+        <item name="appWidgetRadius">16dp</item>
+        <!--
+        Radius of the inner view's bound of widgets to make the rounded corners.
+        It needs to be 8dp or less than the value of appWidgetRadius
+        -->
+        <item name="appWidgetInnerRadius">8dp</item>
+    </style>
+
+    <style name="Theme.Android.AppWidgetContainer" parent="Theme.Android.AppWidgetContainerParent">
+        <!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
+        <item name="appWidgetPadding">16dp</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/main/res/xml/home_widget_test_info.xml b/refilc/android/app/src/main/res/xml/home_widget_test_info.xml
similarity index 91%
rename from filcnaplo/android/app/src/main/res/xml/home_widget_test_info.xml
rename to refilc/android/app/src/main/res/xml/home_widget_test_info.xml
index 9beb272..bd311e0 100644
--- a/filcnaplo/android/app/src/main/res/xml/home_widget_test_info.xml
+++ b/refilc/android/app/src/main/res/xml/home_widget_test_info.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8"?>
-<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
-    android:description="@string/app_widget_description"
-    android:initialKeyguardLayout="@layout/widget_timetable"
-    android:initialLayout="@layout/widget_timetable"
-    android:minWidth="250dp"
-    android:minHeight="110dp"
-    android:previewImage="@drawable/timetable_widget_preview"
-    android:resizeMode="horizontal|vertical"
-    android:targetCellWidth="2"
-    android:targetCellHeight="2"
-    android:updatePeriodMillis="86400000"
+<?xml version="1.0" encoding="utf-8"?>
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/app_widget_description"
+    android:initialKeyguardLayout="@layout/widget_timetable"
+    android:initialLayout="@layout/widget_timetable"
+    android:minWidth="250dp"
+    android:minHeight="110dp"
+    android:previewImage="@drawable/timetable_widget_preview"
+    android:resizeMode="horizontal|vertical"
+    android:targetCellWidth="2"
+    android:targetCellHeight="2"
+    android:updatePeriodMillis="86400000"
     android:widgetCategory="home_screen" />
\ No newline at end of file
diff --git a/filcnaplo/android/app/src/profile/AndroidManifest.xml b/refilc/android/app/src/profile/AndroidManifest.xml
similarity index 98%
rename from filcnaplo/android/app/src/profile/AndroidManifest.xml
rename to refilc/android/app/src/profile/AndroidManifest.xml
index 826ca84..fcc14fa 100644
--- a/filcnaplo/android/app/src/profile/AndroidManifest.xml
+++ b/refilc/android/app/src/profile/AndroidManifest.xml
@@ -1,8 +1,8 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hu.refilc.naplo">
-  <!-- Permissions -->
-  <uses-permission android:name="android.permission.INTERNET"/>
-  <uses-permission android:name="android.permission.VIBRATE" />
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-  <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
-</manifest>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hu.refilc.naplo">
+  <!-- Permissions -->
+  <uses-permission android:name="android.permission.INTERNET"/>
+  <uses-permission android:name="android.permission.VIBRATE" />
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+  <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
+</manifest>
diff --git a/filcnaplo/android/build.gradle b/refilc/android/build.gradle
similarity index 95%
rename from filcnaplo/android/build.gradle
rename to refilc/android/build.gradle
index 36f752c..29fb197 100644
--- a/filcnaplo/android/build.gradle
+++ b/refilc/android/build.gradle
@@ -1,53 +1,53 @@
-buildscript {
-    ext.kotlin_version = '1.8.21'
-
-    ext {
-        compileSdkVersion   = 33
-        targetSdkVersion    = 33
-        appCompatVersion    = "1.1.0"
-    }
-
-    repositories {
-        google()
-        jcenter()
-    }
-
-    dependencies {
-        classpath 'com.android.tools.build:gradle:7.1.1'
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-    }
-}
-
-allprojects {
-    repositories {
-        google()
-        jcenter()
-        maven {
-            // [required] background_fetch
-            url "${project(':background_fetch').projectDir}/libs"
-        }
-    }
-}
-
-subprojects {
-    afterEvaluate {project ->
-        if (project.plugins.hasPlugin('android') || project.plugins.hasPlugin('android-library')) {
-            android {
-                compileSdkVersion 33
-                buildToolsVersion '31.0.0'
-            }
-        }
-    }
-}
-
-rootProject.buildDir = '../build'
-subprojects {
-    project.buildDir = "${rootProject.buildDir}/${project.name}"
-}
-subprojects {
-    project.evaluationDependsOn(':app')
-}
-
-tasks.register("clean", Delete) {
-    delete rootProject.buildDir
-}
+buildscript {
+    ext.kotlin_version = '1.8.21'
+
+    ext {
+        compileSdkVersion   = 33
+        targetSdkVersion    = 33
+        appCompatVersion    = "1.1.0"
+    }
+
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:7.1.1'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+        maven {
+            // [required] background_fetch
+            url "${project(':background_fetch').projectDir}/libs"
+        }
+    }
+}
+
+subprojects {
+    afterEvaluate {project ->
+        if (project.plugins.hasPlugin('android') || project.plugins.hasPlugin('android-library')) {
+            android {
+                compileSdkVersion 33
+                buildToolsVersion '31.0.0'
+            }
+        }
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+tasks.register("clean", Delete) {
+    delete rootProject.buildDir
+}
diff --git a/filcnaplo/android/gradle.properties b/refilc/android/gradle.properties
similarity index 97%
rename from filcnaplo/android/gradle.properties
rename to refilc/android/gradle.properties
index 183b8aa..80db790 100644
--- a/filcnaplo/android/gradle.properties
+++ b/refilc/android/gradle.properties
@@ -1,8 +1,8 @@
-org.gradle.jvmargs=-Xmx1536M \
---add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
---add-opens=java.base/java.lang=ALL-UNNAMED \
---add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
---add-opens=java.base/java.io=ALL-UNNAMED \
---add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
-android.useAndroidX=true
-android.enableJetifier=true
+org.gradle.jvmargs=-Xmx1536M \
+--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
+--add-opens=java.base/java.lang=ALL-UNNAMED \
+--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
+--add-opens=java.base/java.io=ALL-UNNAMED \
+--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/filcnaplo/android/gradle/wrapper/gradle-wrapper.properties b/refilc/android/gradle/wrapper/gradle-wrapper.properties
similarity index 97%
rename from filcnaplo/android/gradle/wrapper/gradle-wrapper.properties
rename to refilc/android/gradle/wrapper/gradle-wrapper.properties
index 51d7af8..a965008 100644
--- a/filcnaplo/android/gradle/wrapper/gradle-wrapper.properties
+++ b/refilc/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Jun 23 08:50:38 CEST 2017
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https://services.gradle.org/distributions/gradle-7.3.3-all.zip
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https://services.gradle.org/distributions/gradle-7.3.3-all.zip
diff --git a/filcnaplo/android/settings.gradle b/refilc/android/settings.gradle
similarity index 97%
rename from filcnaplo/android/settings.gradle
rename to refilc/android/settings.gradle
index 33f0745..44e62bc 100644
--- a/filcnaplo/android/settings.gradle
+++ b/refilc/android/settings.gradle
@@ -1,11 +1,11 @@
-include ':app'
-
-def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
-def properties = new Properties()
-
-assert localPropertiesFile.exists()
-localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
-
-def flutterSdkPath = properties.getProperty("flutter.sdk")
-assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
-apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/filcnaplo/android/settings_aar.gradle b/refilc/android/settings_aar.gradle
similarity index 93%
rename from filcnaplo/android/settings_aar.gradle
rename to refilc/android/settings_aar.gradle
index d3db109..e7b4def 100644
--- a/filcnaplo/android/settings_aar.gradle
+++ b/refilc/android/settings_aar.gradle
@@ -1 +1 @@
-include ':app'
+include ':app'
diff --git a/filcnaplo/assets/animations/backpack-2.riv b/refilc/assets/animations/backpack-2.riv
similarity index 100%
rename from filcnaplo/assets/animations/backpack-2.riv
rename to refilc/assets/animations/backpack-2.riv
diff --git a/filcnaplo/assets/animations/bell-alert.json b/refilc/assets/animations/bell-alert.json
similarity index 100%
rename from filcnaplo/assets/animations/bell-alert.json
rename to refilc/assets/animations/bell-alert.json
diff --git a/filcnaplo/assets/fonts/FilcIcons.ttf b/refilc/assets/fonts/FilcIcons.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/FilcIcons.ttf
rename to refilc/assets/fonts/FilcIcons.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Black.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Black.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Black.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Black.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-BlackItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-BlackItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-BlackItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-BlackItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Bold.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Bold.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Bold.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Bold.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-BoldItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-BoldItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-BoldItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-BoldItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraBold.ttf b/refilc/assets/fonts/Montserrat/Montserrat-ExtraBold.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraBold.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-ExtraBold.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraLight.ttf b/refilc/assets/fonts/Montserrat/Montserrat-ExtraLight.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraLight.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-ExtraLight.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Italic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Italic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Italic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Italic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Light.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Light.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Light.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Light.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-LightItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-LightItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-LightItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-LightItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Medium.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Medium.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Medium.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Medium.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-MediumItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-MediumItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-MediumItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-MediumItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Regular.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Regular.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Regular.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Regular.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-SemiBold.ttf b/refilc/assets/fonts/Montserrat/Montserrat-SemiBold.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-SemiBold.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-SemiBold.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-Thin.ttf b/refilc/assets/fonts/Montserrat/Montserrat-Thin.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-Thin.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-Thin.ttf
diff --git a/filcnaplo/assets/fonts/Montserrat/Montserrat-ThinItalic.ttf b/refilc/assets/fonts/Montserrat/Montserrat-ThinItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/Montserrat/Montserrat-ThinItalic.ttf
rename to refilc/assets/fonts/Montserrat/Montserrat-ThinItalic.ttf
diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Bold.ttf b/refilc/assets/fonts/SpaceMono/SpaceMono-Bold.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/SpaceMono/SpaceMono-Bold.ttf
rename to refilc/assets/fonts/SpaceMono/SpaceMono-Bold.ttf
diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf b/refilc/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf
rename to refilc/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf
diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Italic.ttf b/refilc/assets/fonts/SpaceMono/SpaceMono-Italic.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/SpaceMono/SpaceMono-Italic.ttf
rename to refilc/assets/fonts/SpaceMono/SpaceMono-Italic.ttf
diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Regular.ttf b/refilc/assets/fonts/SpaceMono/SpaceMono-Regular.ttf
similarity index 100%
rename from filcnaplo/assets/fonts/SpaceMono/SpaceMono-Regular.ttf
rename to refilc/assets/fonts/SpaceMono/SpaceMono-Regular.ttf
diff --git a/filcnaplo/assets/icons/ic_android.png b/refilc/assets/icons/ic_android.png
similarity index 100%
rename from filcnaplo/assets/icons/ic_android.png
rename to refilc/assets/icons/ic_android.png
diff --git a/filcnaplo/assets/icons/ic_launcher.png b/refilc/assets/icons/ic_launcher.png
similarity index 100%
rename from filcnaplo/assets/icons/ic_launcher.png
rename to refilc/assets/icons/ic_launcher.png
diff --git a/filcnaplo/assets/icons/ic_launcher_foreground.png b/refilc/assets/icons/ic_launcher_foreground.png
similarity index 100%
rename from filcnaplo/assets/icons/ic_launcher_foreground.png
rename to refilc/assets/icons/ic_launcher_foreground.png
diff --git a/filcnaplo/assets/icons/ic_launcher_monochrome.png b/refilc/assets/icons/ic_launcher_monochrome.png
similarity index 100%
rename from filcnaplo/assets/icons/ic_launcher_monochrome.png
rename to refilc/assets/icons/ic_launcher_monochrome.png
diff --git a/filcnaplo/assets/icons/ic_splash.png b/refilc/assets/icons/ic_splash.png
similarity index 100%
rename from filcnaplo/assets/icons/ic_splash.png
rename to refilc/assets/icons/ic_splash.png
diff --git a/filcnaplo/assets/images/card_border.png b/refilc/assets/images/card_border.png
similarity index 100%
rename from filcnaplo/assets/images/card_border.png
rename to refilc/assets/images/card_border.png
diff --git a/filcnaplo/assets/images/desktop_icon.svg b/refilc/assets/images/desktop_icon.svg
similarity index 99%
rename from filcnaplo/assets/images/desktop_icon.svg
rename to refilc/assets/images/desktop_icon.svg
index b0abc6a..547426f 100644
--- a/filcnaplo/assets/images/desktop_icon.svg
+++ b/refilc/assets/images/desktop_icon.svg
@@ -1,3 +1,3 @@
-<svg width="19" height="13" viewBox="0 0 19 13" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M15.8333 11.375C16.7042 11.375 17.4088 10.6438 17.4088 9.75L17.4167 1.625C17.4167 0.73125 16.7042 0 15.8333 0H3.16667C2.29583 0 1.58333 0.73125 1.58333 1.625V9.75C1.58333 10.6438 2.29583 11.375 3.16667 11.375H0V13H19V11.375H15.8333ZM3.16667 1.625H15.8333V9.75H3.16667V1.625Z" fill="white"/>
-</svg>
+<svg width="19" height="13" viewBox="0 0 19 13" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M15.8333 11.375C16.7042 11.375 17.4088 10.6438 17.4088 9.75L17.4167 1.625C17.4167 0.73125 16.7042 0 15.8333 0H3.16667C2.29583 0 1.58333 0.73125 1.58333 1.625V9.75C1.58333 10.6438 2.29583 11.375 3.16667 11.375H0V13H19V11.375H15.8333ZM3.16667 1.625H15.8333V9.75H3.16667V1.625Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/github.svg b/refilc/assets/images/github.svg
similarity index 99%
rename from filcnaplo/assets/images/github.svg
rename to refilc/assets/images/github.svg
index 2b3a4e3..849d5c6 100644
--- a/filcnaplo/assets/images/github.svg
+++ b/refilc/assets/images/github.svg
@@ -1,3 +1,3 @@
-<svg width="23" height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M11.5 0C9.9898 0 8.49438 0.291587 7.09914 0.858113C5.7039 1.42464 4.43615 2.25501 3.36827 3.30181C1.2116 5.41593 0 8.28329 0 11.2731C0 16.2558 3.3005 20.4832 7.866 21.9825C8.441 22.0727 8.625 21.7233 8.625 21.4189V19.5137C5.4395 20.1901 4.761 18.0031 4.761 18.0031C4.232 16.6955 3.4845 16.346 3.4845 16.346C2.438 15.6471 3.565 15.6696 3.565 15.6696C4.715 15.7485 5.3245 16.8307 5.3245 16.8307C6.325 18.5442 8.0155 18.037 8.671 17.7664C8.7745 17.0336 9.0735 16.5376 9.3955 16.2558C6.8425 15.974 4.163 15.0045 4.163 10.7094C4.163 9.45813 4.6 8.45482 5.3475 7.65443C5.2325 7.37261 4.83 6.2002 5.4625 4.67834C5.4625 4.67834 6.4285 4.37396 8.625 5.82819C9.5335 5.58018 10.5225 5.45618 11.5 5.45618C12.4775 5.45618 13.4665 5.58018 14.375 5.82819C16.5715 4.37396 17.5375 4.67834 17.5375 4.67834C18.17 6.2002 17.7675 7.37261 17.6525 7.65443C18.4 8.45482 18.837 9.45813 18.837 10.7094C18.837 15.0158 16.146 15.9627 13.5815 16.2445C13.9955 16.594 14.375 17.2817 14.375 18.3301V21.4189C14.375 21.7233 14.559 22.084 15.1455 21.9825C19.711 20.4719 23 16.2558 23 11.2731C23 9.79269 22.7025 8.32678 22.1246 6.95907C21.5467 5.59135 20.6996 4.34862 19.6317 3.30181C18.5639 2.25501 17.2961 1.42464 15.9009 0.858113C14.5056 0.291587 13.0102 0 11.5 0Z" fill="white"/>
-</svg>
+<svg width="23" height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11.5 0C9.9898 0 8.49438 0.291587 7.09914 0.858113C5.7039 1.42464 4.43615 2.25501 3.36827 3.30181C1.2116 5.41593 0 8.28329 0 11.2731C0 16.2558 3.3005 20.4832 7.866 21.9825C8.441 22.0727 8.625 21.7233 8.625 21.4189V19.5137C5.4395 20.1901 4.761 18.0031 4.761 18.0031C4.232 16.6955 3.4845 16.346 3.4845 16.346C2.438 15.6471 3.565 15.6696 3.565 15.6696C4.715 15.7485 5.3245 16.8307 5.3245 16.8307C6.325 18.5442 8.0155 18.037 8.671 17.7664C8.7745 17.0336 9.0735 16.5376 9.3955 16.2558C6.8425 15.974 4.163 15.0045 4.163 10.7094C4.163 9.45813 4.6 8.45482 5.3475 7.65443C5.2325 7.37261 4.83 6.2002 5.4625 4.67834C5.4625 4.67834 6.4285 4.37396 8.625 5.82819C9.5335 5.58018 10.5225 5.45618 11.5 5.45618C12.4775 5.45618 13.4665 5.58018 14.375 5.82819C16.5715 4.37396 17.5375 4.67834 17.5375 4.67834C18.17 6.2002 17.7675 7.37261 17.6525 7.65443C18.4 8.45482 18.837 9.45813 18.837 10.7094C18.837 15.0158 16.146 15.9627 13.5815 16.2445C13.9955 16.594 14.375 17.2817 14.375 18.3301V21.4189C14.375 21.7233 14.559 22.084 15.1455 21.9825C19.711 20.4719 23 16.2558 23 11.2731C23 9.79269 22.7025 8.32678 22.1246 6.95907C21.5467 5.59135 20.6996 4.34862 19.6317 3.30181C18.5639 2.25501 17.2961 1.42464 15.9009 0.858113C14.5056 0.291587 13.0102 0 11.5 0Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/goal_icon.svg b/refilc/assets/images/goal_icon.svg
similarity index 99%
rename from filcnaplo/assets/images/goal_icon.svg
rename to refilc/assets/images/goal_icon.svg
index cb3aeff..a4bd0e5 100644
--- a/filcnaplo/assets/images/goal_icon.svg
+++ b/refilc/assets/images/goal_icon.svg
@@ -1,3 +1,3 @@
-<svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M1.33331 0C0.979692 0 0.64056 0.142984 0.390517 0.397498C0.140473 0.652012 0 0.997206 0 1.35714V19H2.66661V1.35714C2.66661 0.997206 2.52614 0.652012 2.2761 0.397498C2.02605 0.142984 1.68692 0 1.33331 0ZM15.7504 7.50229L3.33327 12.6187V1.63129L15.7504 6.74704C15.8241 6.77749 15.8873 6.82967 15.9318 6.89688C15.9762 6.96409 16 7.04329 16 7.12432C16 7.20536 15.9762 7.28455 15.9318 7.35176C15.8873 7.41897 15.8241 7.47115 15.7504 7.50161V7.50229Z" fill="white"/>
-</svg>
+<svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.33331 0C0.979692 0 0.64056 0.142984 0.390517 0.397498C0.140473 0.652012 0 0.997206 0 1.35714V19H2.66661V1.35714C2.66661 0.997206 2.52614 0.652012 2.2761 0.397498C2.02605 0.142984 1.68692 0 1.33331 0ZM15.7504 7.50229L3.33327 12.6187V1.63129L15.7504 6.74704C15.8241 6.77749 15.8873 6.82967 15.9318 6.89688C15.9762 6.96409 16 7.04329 16 7.12432C16 7.20536 15.9762 7.28455 15.9318 7.35176C15.8873 7.41897 15.8241 7.47115 15.7504 7.50161V7.50229Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/heart.png b/refilc/assets/images/heart.png
similarity index 100%
rename from filcnaplo/assets/images/heart.png
rename to refilc/assets/images/heart.png
diff --git a/filcnaplo/assets/images/kupak.svg b/refilc/assets/images/kupak.svg
similarity index 99%
rename from filcnaplo/assets/images/kupak.svg
rename to refilc/assets/images/kupak.svg
index 5cedfa9..9a7c0df 100644
--- a/filcnaplo/assets/images/kupak.svg
+++ b/refilc/assets/images/kupak.svg
@@ -1,3 +1,3 @@
-<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M9.61217 0.411889C9.48161 0.281306 9.32661 0.17772 9.15602 0.107047C8.98543 0.0363749 8.80259 0 8.61794 0C8.43329 0 8.25045 0.0363749 8.07986 0.107047C7.90927 0.17772 7.75427 0.281306 7.62372 0.411889L5.96753 2.06861C5.6922 2.34397 5.50939 2.69821 5.44447 3.08217C5.37956 3.46613 5.43576 3.86077 5.60527 4.21134L3.03383 5.49501C2.68443 5.66957 2.37523 5.91499 2.12591 6.21564C1.87658 6.51629 1.69262 6.86558 1.58572 7.24125L0.0392041 12.6857C-0.0109899 12.8626 -0.0130219 13.0497 0.0333182 13.2277C0.0796583 13.4057 0.172689 13.568 0.302791 13.698C0.432894 13.828 0.595347 13.9208 0.773354 13.967C0.951362 14.0131 1.13846 14.0109 1.31532 13.9605L6.75673 12.4115C7.1321 12.3047 7.48112 12.1209 7.78159 11.8718C8.08205 11.6228 8.32738 11.3139 8.50195 10.9648L9.78603 8.39323C10.1367 8.56347 10.5317 8.62033 10.9161 8.55592C11.3006 8.4915 11.6554 8.30901 11.9315 8.03376L13.5881 6.37704C13.7187 6.24648 13.8223 6.09147 13.893 5.92087C13.9636 5.75028 14 5.56743 14 5.38277C14 5.19811 13.9636 5.01526 13.893 4.84466C13.8223 4.67407 13.7187 4.51906 13.5881 4.3885L9.6117 0.411889H9.61217ZM8.28638 1.07458C8.3299 1.031 8.38159 0.996437 8.43848 0.972851C8.49537 0.949266 8.55635 0.937127 8.61794 0.937127C8.67953 0.937127 8.74051 0.949266 8.7974 0.972851C8.85429 0.996437 8.90598 1.031 8.9495 1.07458L12.9259 5.05119C13.0138 5.13908 13.0631 5.25826 13.0631 5.38253C13.0631 5.50681 13.0138 5.62599 12.9259 5.71388L11.2688 7.37107L6.62926 2.73131L8.28638 1.07458ZM6.62972 4.71984L9.27756 7.36779C9.24199 7.40344 9.2124 7.44458 9.18992 7.48965L7.66402 10.5453C7.54772 10.7781 7.38424 10.9841 7.18398 11.1502C6.98373 11.3164 6.75108 11.439 6.50085 11.5103L1.82145 12.8418L4.69798 9.96513C4.99727 10.1077 5.3373 10.14 5.65807 10.0562C5.97883 9.97251 6.25971 9.77815 6.45112 9.50747C6.64253 9.23679 6.73218 8.90719 6.70424 8.57684C6.67629 8.24649 6.53256 7.93663 6.29839 7.70195C6.064 7.46672 5.75392 7.32205 5.42307 7.29357C5.09223 7.26509 4.76198 7.35464 4.49084 7.54635C4.2197 7.73807 4.02516 8.01958 3.9417 8.341C3.85824 8.66242 3.89124 9.00301 4.03485 9.30244L1.15739 12.18L2.48833 7.49714C2.55947 7.24677 2.68196 7.01396 2.84801 6.81353C3.01406 6.6131 3.22003 6.44944 3.4528 6.33298L6.50788 4.80748C6.55297 4.78487 6.59412 4.75512 6.62972 4.71938V4.71984Z" fill="black"/>
-</svg>
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.61217 0.411889C9.48161 0.281306 9.32661 0.17772 9.15602 0.107047C8.98543 0.0363749 8.80259 0 8.61794 0C8.43329 0 8.25045 0.0363749 8.07986 0.107047C7.90927 0.17772 7.75427 0.281306 7.62372 0.411889L5.96753 2.06861C5.6922 2.34397 5.50939 2.69821 5.44447 3.08217C5.37956 3.46613 5.43576 3.86077 5.60527 4.21134L3.03383 5.49501C2.68443 5.66957 2.37523 5.91499 2.12591 6.21564C1.87658 6.51629 1.69262 6.86558 1.58572 7.24125L0.0392041 12.6857C-0.0109899 12.8626 -0.0130219 13.0497 0.0333182 13.2277C0.0796583 13.4057 0.172689 13.568 0.302791 13.698C0.432894 13.828 0.595347 13.9208 0.773354 13.967C0.951362 14.0131 1.13846 14.0109 1.31532 13.9605L6.75673 12.4115C7.1321 12.3047 7.48112 12.1209 7.78159 11.8718C8.08205 11.6228 8.32738 11.3139 8.50195 10.9648L9.78603 8.39323C10.1367 8.56347 10.5317 8.62033 10.9161 8.55592C11.3006 8.4915 11.6554 8.30901 11.9315 8.03376L13.5881 6.37704C13.7187 6.24648 13.8223 6.09147 13.893 5.92087C13.9636 5.75028 14 5.56743 14 5.38277C14 5.19811 13.9636 5.01526 13.893 4.84466C13.8223 4.67407 13.7187 4.51906 13.5881 4.3885L9.6117 0.411889H9.61217ZM8.28638 1.07458C8.3299 1.031 8.38159 0.996437 8.43848 0.972851C8.49537 0.949266 8.55635 0.937127 8.61794 0.937127C8.67953 0.937127 8.74051 0.949266 8.7974 0.972851C8.85429 0.996437 8.90598 1.031 8.9495 1.07458L12.9259 5.05119C13.0138 5.13908 13.0631 5.25826 13.0631 5.38253C13.0631 5.50681 13.0138 5.62599 12.9259 5.71388L11.2688 7.37107L6.62926 2.73131L8.28638 1.07458ZM6.62972 4.71984L9.27756 7.36779C9.24199 7.40344 9.2124 7.44458 9.18992 7.48965L7.66402 10.5453C7.54772 10.7781 7.38424 10.9841 7.18398 11.1502C6.98373 11.3164 6.75108 11.439 6.50085 11.5103L1.82145 12.8418L4.69798 9.96513C4.99727 10.1077 5.3373 10.14 5.65807 10.0562C5.97883 9.97251 6.25971 9.77815 6.45112 9.50747C6.64253 9.23679 6.73218 8.90719 6.70424 8.57684C6.67629 8.24649 6.53256 7.93663 6.29839 7.70195C6.064 7.46672 5.75392 7.32205 5.42307 7.29357C5.09223 7.26509 4.76198 7.35464 4.49084 7.54635C4.2197 7.73807 4.02516 8.01958 3.9417 8.341C3.85824 8.66242 3.89124 9.00301 4.03485 9.30244L1.15739 12.18L2.48833 7.49714C2.55947 7.24677 2.68196 7.01396 2.84801 6.81353C3.01406 6.6131 3.22003 6.44944 3.4528 6.33298L6.50788 4.80748C6.55297 4.78487 6.59412 4.75512 6.62972 4.71938V4.71984Z" fill="black"/>
+</svg>
diff --git a/filcnaplo/assets/images/logo.png b/refilc/assets/images/logo.png
similarity index 100%
rename from filcnaplo/assets/images/logo.png
rename to refilc/assets/images/logo.png
diff --git a/filcnaplo/assets/images/nickname_icon.svg b/refilc/assets/images/nickname_icon.svg
similarity index 99%
rename from filcnaplo/assets/images/nickname_icon.svg
rename to refilc/assets/images/nickname_icon.svg
index cf0ded3..90269de 100644
--- a/filcnaplo/assets/images/nickname_icon.svg
+++ b/refilc/assets/images/nickname_icon.svg
@@ -1,3 +1,3 @@
-<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M9.97258 0H8.02016C7.50351 0.000653543 6.99296 0.11297 6.52264 0.329438C6.05233 0.545906 5.63309 0.861535 5.29297 1.25522C4.95286 1.6489 4.6997 2.11155 4.55043 2.61225C4.40116 3.11294 4.35922 3.64013 4.42742 4.15855L4.48403 5.04316C4.12638 5.10009 3.80265 5.29026 3.57636 5.57636C3.35008 5.86247 3.23758 6.22384 3.26094 6.58958C3.2843 6.95531 3.44183 7.29901 3.70263 7.55324C3.96342 7.80746 4.30864 7.95385 4.67056 7.96369L4.75403 9.25754C4.84634 9.95556 5.1451 10.609 5.61106 11.1319C6.07701 11.6549 6.68836 12.0229 7.36476 12.1876C5.58243 12.5072 3.92957 13.3421 2.60565 14.5916V14.5843C1.42818 15.6953 0.553297 17.0946 0.0653227 18.6473V18.7282C0.0392656 18.8052 0.0174577 18.8837 0 18.9633L2.60347 18.9927L2.60492 19H15.3936L15.3958 18.9927L18 18.9633L17.984 18.9199C17.9565 18.8595 17.9398 18.7945 17.9347 18.7282V18.6473C17.444 17.0959 16.5696 15.6972 15.3944 14.5843V14.5916C14.0712 13.3434 12.4197 12.509 10.6389 12.1891C11.3162 12.025 11.9285 11.6571 12.3952 11.1338C12.8619 10.6105 13.161 9.95634 13.2532 9.25754L13.3323 7.96148C13.6852 7.93871 14.0176 7.78639 14.2674 7.53309C14.5171 7.27979 14.667 6.94293 14.6888 6.58573C14.7107 6.22853 14.603 5.87554 14.3859 5.59302C14.1689 5.31049 13.8575 5.11785 13.5102 5.05124L13.5653 4.15855C13.6336 3.64011 13.5918 3.11287 13.4426 2.61213C13.2933 2.11138 13.0402 1.64867 12.7001 1.25497C12.3599 0.861257 11.9406 0.545628 11.4703 0.3292C10.9999 0.112771 10.4893 0.00053424 9.97258 0Z" fill="white"/>
-</svg>
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.97258 0H8.02016C7.50351 0.000653543 6.99296 0.11297 6.52264 0.329438C6.05233 0.545906 5.63309 0.861535 5.29297 1.25522C4.95286 1.6489 4.6997 2.11155 4.55043 2.61225C4.40116 3.11294 4.35922 3.64013 4.42742 4.15855L4.48403 5.04316C4.12638 5.10009 3.80265 5.29026 3.57636 5.57636C3.35008 5.86247 3.23758 6.22384 3.26094 6.58958C3.2843 6.95531 3.44183 7.29901 3.70263 7.55324C3.96342 7.80746 4.30864 7.95385 4.67056 7.96369L4.75403 9.25754C4.84634 9.95556 5.1451 10.609 5.61106 11.1319C6.07701 11.6549 6.68836 12.0229 7.36476 12.1876C5.58243 12.5072 3.92957 13.3421 2.60565 14.5916V14.5843C1.42818 15.6953 0.553297 17.0946 0.0653227 18.6473V18.7282C0.0392656 18.8052 0.0174577 18.8837 0 18.9633L2.60347 18.9927L2.60492 19H15.3936L15.3958 18.9927L18 18.9633L17.984 18.9199C17.9565 18.8595 17.9398 18.7945 17.9347 18.7282V18.6473C17.444 17.0959 16.5696 15.6972 15.3944 14.5843V14.5916C14.0712 13.3434 12.4197 12.509 10.6389 12.1891C11.3162 12.025 11.9285 11.6571 12.3952 11.1338C12.8619 10.6105 13.161 9.95634 13.2532 9.25754L13.3323 7.96148C13.6852 7.93871 14.0176 7.78639 14.2674 7.53309C14.5171 7.27979 14.667 6.94293 14.6888 6.58573C14.7107 6.22853 14.603 5.87554 14.3859 5.59302C14.1689 5.31049 13.8575 5.11785 13.5102 5.05124L13.5653 4.15855C13.6336 3.64011 13.5918 3.11287 13.4426 2.61213C13.2933 2.11138 13.0402 1.64867 12.7001 1.25497C12.3599 0.861257 11.9406 0.545628 11.4703 0.3292C10.9999 0.112771 10.4893 0.00053424 9.97258 0Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/static_confetti.png b/refilc/assets/images/static_confetti.png
similarity index 100%
rename from filcnaplo/assets/images/static_confetti.png
rename to refilc/assets/images/static_confetti.png
diff --git a/filcnaplo/assets/images/stats_icon.svg b/refilc/assets/images/stats_icon.svg
similarity index 99%
rename from filcnaplo/assets/images/stats_icon.svg
rename to refilc/assets/images/stats_icon.svg
index 43be2f6..8bb9e56 100644
--- a/filcnaplo/assets/images/stats_icon.svg
+++ b/refilc/assets/images/stats_icon.svg
@@ -1,3 +1,3 @@
-<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M3.16667 0C2.75081 0 2.33903 0.0819083 1.95484 0.241048C1.57064 0.400188 1.22155 0.633443 0.927495 0.927495C0.33363 1.52136 0 2.32681 0 3.16667V15.8333C0 16.6732 0.33363 17.4786 0.927495 18.0725C1.22155 18.3666 1.57064 18.5998 1.95484 18.759C2.33903 18.9181 2.75081 19 3.16667 19H15.8333C16.6732 19 17.4786 18.6664 18.0725 18.0725C18.6664 17.4786 19 16.6732 19 15.8333V3.16667C19 2.75081 18.9181 2.33903 18.759 1.95484C18.5998 1.57064 18.3666 1.22155 18.0725 0.927495C17.7785 0.633443 17.4294 0.400188 17.0452 0.241048C16.661 0.0819083 16.2492 0 15.8333 0H3.16667ZM1.26667 3.16667C1.26667 2.66276 1.46684 2.17948 1.82316 1.82316C2.17948 1.46684 2.66276 1.26667 3.16667 1.26667H15.8333C16.7371 1.26667 17.4927 1.89747 17.6858 2.74233L8.84767 11.6071C8.78933 11.6658 8.71034 11.6993 8.62761 11.7005C8.54487 11.7017 8.46496 11.6704 8.40497 11.6134L7.04457 10.3214C6.78224 10.0725 6.43338 9.93524 6.07172 9.93878C5.71007 9.94233 5.36396 10.0864 5.10657 10.3404L1.26667 14.1297V3.16667ZM1.26793 15.8979L5.84947 11.3582C5.90766 11.3005 5.98598 11.2675 6.06796 11.2663C6.14993 11.2652 6.22917 11.2958 6.289 11.3519L7.65067 12.6299C7.91356 12.8766 8.2618 13.0117 8.62224 13.007C8.98268 13.0023 9.32726 12.858 9.5836 12.6046L17.7333 4.5448V15.8333C17.7333 16.3372 17.5332 16.8205 17.1768 17.1768C16.8205 17.5332 16.3372 17.7333 15.8333 17.7333H3.16667C2.67397 17.7333 2.20056 17.5419 1.84631 17.1994C1.49206 16.857 1.28469 16.3903 1.26793 15.8979Z" fill="white"/>
-</svg>
+<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.16667 0C2.75081 0 2.33903 0.0819083 1.95484 0.241048C1.57064 0.400188 1.22155 0.633443 0.927495 0.927495C0.33363 1.52136 0 2.32681 0 3.16667V15.8333C0 16.6732 0.33363 17.4786 0.927495 18.0725C1.22155 18.3666 1.57064 18.5998 1.95484 18.759C2.33903 18.9181 2.75081 19 3.16667 19H15.8333C16.6732 19 17.4786 18.6664 18.0725 18.0725C18.6664 17.4786 19 16.6732 19 15.8333V3.16667C19 2.75081 18.9181 2.33903 18.759 1.95484C18.5998 1.57064 18.3666 1.22155 18.0725 0.927495C17.7785 0.633443 17.4294 0.400188 17.0452 0.241048C16.661 0.0819083 16.2492 0 15.8333 0H3.16667ZM1.26667 3.16667C1.26667 2.66276 1.46684 2.17948 1.82316 1.82316C2.17948 1.46684 2.66276 1.26667 3.16667 1.26667H15.8333C16.7371 1.26667 17.4927 1.89747 17.6858 2.74233L8.84767 11.6071C8.78933 11.6658 8.71034 11.6993 8.62761 11.7005C8.54487 11.7017 8.46496 11.6704 8.40497 11.6134L7.04457 10.3214C6.78224 10.0725 6.43338 9.93524 6.07172 9.93878C5.71007 9.94233 5.36396 10.0864 5.10657 10.3404L1.26667 14.1297V3.16667ZM1.26793 15.8979L5.84947 11.3582C5.90766 11.3005 5.98598 11.2675 6.06796 11.2663C6.14993 11.2652 6.22917 11.2958 6.289 11.3519L7.65067 12.6299C7.91356 12.8766 8.2618 13.0117 8.62224 13.007C8.98268 13.0023 9.32726 12.858 9.5836 12.6046L17.7333 4.5448V15.8333C17.7333 16.3372 17.5332 16.8205 17.1768 17.1768C16.8205 17.5332 16.3372 17.7333 15.8333 17.7333H3.16667C2.67397 17.7333 2.20056 17.5419 1.84631 17.1994C1.49206 16.857 1.28469 16.3903 1.26793 15.8979Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/subject_covers/math_light.png b/refilc/assets/images/subject_covers/math_light.png
similarity index 100%
rename from filcnaplo/assets/images/subject_covers/math_light.png
rename to refilc/assets/images/subject_covers/math_light.png
diff --git a/filcnaplo/assets/images/theme_icon.svg b/refilc/assets/images/theme_icon.svg
similarity index 99%
rename from filcnaplo/assets/images/theme_icon.svg
rename to refilc/assets/images/theme_icon.svg
index 33f2db5..0cb9a51 100644
--- a/filcnaplo/assets/images/theme_icon.svg
+++ b/refilc/assets/images/theme_icon.svg
@@ -1,3 +1,3 @@
-<svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M19.2777 0.748963C18.8178 0.280979 18.1938 0.0123079 17.5392 0.000412436C16.8846 -0.011483 16.2513 0.234342 15.7749 0.68531L6.27841 9.67238L6.26855 9.67097L4.76926 11.1562C4.65745 11.2668 4.56485 11.3954 4.49532 11.5367C3.90325 11.5167 3.32013 11.6859 2.82983 12.0198C2.30986 12.3226 1.87751 12.7564 1.57544 13.2783C1.27337 13.8002 1.11201 14.3922 1.1073 14.9959C1.11849 15.2442 1.0807 15.4924 0.996102 15.726C0.911504 15.9597 0.781767 16.1742 0.614346 16.3573L0.0587138 16.88L0.0171647 17.1092C-0.0290688 17.3612 0.0188538 17.6216 0.151766 17.8404C0.284678 18.0592 0.49325 18.2212 0.737585 18.2952L2.55378 18.849L2.90589 18.9197C3.76665 19.0771 4.6536 19.0022 5.47605 18.7024C6.29849 18.4027 7.02692 17.889 7.58686 17.2138C7.99108 16.7301 8.22066 16.1254 8.24179 15.498C8.41784 15.4308 8.58404 15.3255 8.7277 15.184L9.28967 14.6267L9.30023 14.6479L19.2953 4.26755C19.7503 3.795 20.0033 3.1624 20 2.50501C19.9967 1.84762 19.7374 1.2169 19.2777 0.748963ZM8.99037 12.9349L7.01151 10.9221L16.7411 1.71436C16.9499 1.51759 17.227 1.41053 17.5132 1.41602C17.7995 1.42151 18.0723 1.53911 18.2735 1.74374C18.4747 1.94836 18.5883 2.22383 18.5901 2.5114C18.592 2.79896 18.4819 3.07586 18.2833 3.28305L8.99037 12.9349ZM3.15941 17.5293L2.92701 17.4861L1.81152 17.1466C2.24317 16.5719 2.48631 15.8767 2.5073 15.1571C2.48871 14.7622 2.58091 14.37 2.77339 14.0252C2.96587 13.6803 3.2509 13.3967 3.59603 13.2065C3.86776 13.0169 4.19727 12.9295 4.52679 12.9595C4.8563 12.9895 5.16478 13.135 5.39813 13.3706L6.42207 14.4025C6.66996 14.6525 6.81583 14.9866 6.83108 15.3391C6.84632 15.6916 6.72983 16.0371 6.50447 16.3078C6.10445 16.7906 5.58401 17.158 4.99631 17.3726C4.40861 17.5872 3.77472 17.6413 3.15941 17.5293Z" fill="white"/>
-</svg>
+<svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.2777 0.748963C18.8178 0.280979 18.1938 0.0123079 17.5392 0.000412436C16.8846 -0.011483 16.2513 0.234342 15.7749 0.68531L6.27841 9.67238L6.26855 9.67097L4.76926 11.1562C4.65745 11.2668 4.56485 11.3954 4.49532 11.5367C3.90325 11.5167 3.32013 11.6859 2.82983 12.0198C2.30986 12.3226 1.87751 12.7564 1.57544 13.2783C1.27337 13.8002 1.11201 14.3922 1.1073 14.9959C1.11849 15.2442 1.0807 15.4924 0.996102 15.726C0.911504 15.9597 0.781767 16.1742 0.614346 16.3573L0.0587138 16.88L0.0171647 17.1092C-0.0290688 17.3612 0.0188538 17.6216 0.151766 17.8404C0.284678 18.0592 0.49325 18.2212 0.737585 18.2952L2.55378 18.849L2.90589 18.9197C3.76665 19.0771 4.6536 19.0022 5.47605 18.7024C6.29849 18.4027 7.02692 17.889 7.58686 17.2138C7.99108 16.7301 8.22066 16.1254 8.24179 15.498C8.41784 15.4308 8.58404 15.3255 8.7277 15.184L9.28967 14.6267L9.30023 14.6479L19.2953 4.26755C19.7503 3.795 20.0033 3.1624 20 2.50501C19.9967 1.84762 19.7374 1.2169 19.2777 0.748963ZM8.99037 12.9349L7.01151 10.9221L16.7411 1.71436C16.9499 1.51759 17.227 1.41053 17.5132 1.41602C17.7995 1.42151 18.0723 1.53911 18.2735 1.74374C18.4747 1.94836 18.5883 2.22383 18.5901 2.5114C18.592 2.79896 18.4819 3.07586 18.2833 3.28305L8.99037 12.9349ZM3.15941 17.5293L2.92701 17.4861L1.81152 17.1466C2.24317 16.5719 2.48631 15.8767 2.5073 15.1571C2.48871 14.7622 2.58091 14.37 2.77339 14.0252C2.96587 13.6803 3.2509 13.3967 3.59603 13.2065C3.86776 13.0169 4.19727 12.9295 4.52679 12.9595C4.8563 12.9895 5.16478 13.135 5.39813 13.3706L6.42207 14.4025C6.66996 14.6525 6.81583 14.9866 6.83108 15.3391C6.84632 15.6916 6.72983 16.0371 6.50447 16.3078C6.10445 16.7906 5.58401 17.158 4.99631 17.3726C4.40861 17.5872 3.77472 17.6413 3.15941 17.5293Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/timetable_icon.svg b/refilc/assets/images/timetable_icon.svg
similarity index 99%
rename from filcnaplo/assets/images/timetable_icon.svg
rename to refilc/assets/images/timetable_icon.svg
index 212098d..f77b745 100644
--- a/filcnaplo/assets/images/timetable_icon.svg
+++ b/refilc/assets/images/timetable_icon.svg
@@ -1,5 +1,5 @@
-<svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M4.58619 1.96552V0.854345C4.58619 0.38131 4.95178 0 5.40516 0C5.85854 0 6.22412 0.38131 6.22412 0.854345V1.96552H4.58619ZM12.7758 11.269C12.7758 11.1473 12.8242 11.0307 12.9102 10.9447C12.9962 10.8587 13.1128 10.8103 13.2345 10.8103H14.9379C15.0595 10.8103 15.1762 10.8587 15.2622 10.9447C15.3482 11.0307 15.3965 11.1473 15.3965 11.269V12.9724C15.3965 13.094 15.3482 13.2107 15.2622 13.2967C15.1762 13.3827 15.0595 13.431 14.9379 13.431H13.2345C13.1128 13.431 12.9962 13.3827 12.9102 13.2967C12.8242 13.2107 12.7758 13.094 12.7758 12.9724V11.269ZM4.25861 7.9931C4.25861 7.87147 4.30692 7.75482 4.39293 7.66881C4.47894 7.5828 4.59559 7.53448 4.71723 7.53448H6.42068C6.54231 7.53448 6.65896 7.5828 6.74497 7.66881C6.83098 7.75482 6.8793 7.87147 6.8793 7.9931V9.69655C6.8793 9.81818 6.83098 9.93484 6.74497 10.0208C6.65896 10.1069 6.54231 10.1552 6.42068 10.1552H4.71723C4.59559 10.1552 4.47894 10.1069 4.39293 10.0208C4.30692 9.93484 4.25861 9.81818 4.25861 9.69655V7.9931ZM4.91378 8.18966V9.5H6.22412V8.18966H4.91378ZM8.51723 7.9931C8.51723 7.87147 8.56555 7.75482 8.65155 7.66881C8.73756 7.5828 8.85421 7.53448 8.97585 7.53448H10.6793C10.8009 7.53448 10.9176 7.5828 11.0036 7.66881C11.0896 7.75482 11.1379 7.87147 11.1379 7.9931V9.69655C11.1379 9.81818 11.0896 9.93484 11.0036 10.0208C10.9176 10.1069 10.8009 10.1552 10.6793 10.1552H8.97585C8.85421 10.1552 8.73756 10.1069 8.65155 10.0208C8.56555 9.93484 8.51723 9.81818 8.51723 9.69655V7.9931ZM9.1724 8.18966V9.5H10.4827V8.18966H9.1724ZM12.7758 7.9931C12.7758 7.87147 12.8242 7.75482 12.9102 7.66881C12.9962 7.5828 13.1128 7.53448 13.2345 7.53448H14.9379C15.0595 7.53448 15.1762 7.5828 15.2622 7.66881C15.3482 7.75482 15.3965 7.87147 15.3965 7.9931V9.69655C15.3965 9.81818 15.3482 9.93484 15.2622 10.0208C15.1762 10.1069 15.0595 10.1552 14.9379 10.1552H13.2345C13.1128 10.1552 12.9962 10.1069 12.9102 10.0208C12.8242 9.93484 12.7758 9.81818 12.7758 9.69655V7.9931ZM13.431 8.18966V9.5H14.7414V8.18966H13.431ZM4.25861 11.269C4.25861 11.1473 4.30692 11.0307 4.39293 10.9447C4.47894 10.8587 4.59559 10.8103 4.71723 10.8103H6.42068C6.54231 10.8103 6.65896 10.8587 6.74497 10.9447C6.83098 11.0307 6.8793 11.1473 6.8793 11.269V12.9724C6.8793 13.094 6.83098 13.2107 6.74497 13.2967C6.65896 13.3827 6.54231 13.431 6.42068 13.431H4.71723C4.59559 13.431 4.47894 13.3827 4.39293 13.2967C4.30692 13.2107 4.25861 13.094 4.25861 12.9724V11.269ZM4.91378 11.4655V12.7759H6.22412V11.4655H4.91378ZM8.51723 11.269C8.51723 11.1473 8.56555 11.0307 8.65155 10.9447C8.73756 10.8587 8.85421 10.8103 8.97585 10.8103H10.6793C10.8009 10.8103 10.9176 10.8587 11.0036 10.9447C11.0896 11.0307 11.1379 11.1473 11.1379 11.269V12.9724C11.1379 13.094 11.0896 13.2107 11.0036 13.2967C10.9176 13.3827 10.8009 13.431 10.6793 13.431H8.97585C8.85421 13.431 8.73756 13.3827 8.65155 13.2967C8.56555 13.2107 8.51723 13.094 8.51723 12.9724V11.269ZM9.1724 11.4655V12.7759H10.4827V11.4655H9.1724ZM4.25861 14.5448C4.25861 14.4232 4.30692 14.3065 4.39293 14.2205C4.47894 14.1345 4.59559 14.0862 4.71723 14.0862H6.42068C6.54231 14.0862 6.65896 14.1345 6.74497 14.2205C6.83098 14.3065 6.8793 14.4232 6.8793 14.5448V16.2483C6.8793 16.3699 6.83098 16.4866 6.74497 16.5726C6.65896 16.6586 6.54231 16.7069 6.42068 16.7069H4.71723C4.59559 16.7069 4.47894 16.6586 4.39293 16.5726C4.30692 16.4866 4.25861 16.3699 4.25861 16.2483V14.5448ZM4.91378 14.7414V16.0517H6.22412V14.7414H4.91378ZM8.51723 14.5448C8.51723 14.4232 8.56555 14.3065 8.65155 14.2205C8.73756 14.1345 8.85421 14.0862 8.97585 14.0862H10.6793C10.8009 14.0862 10.9176 14.1345 11.0036 14.2205C11.0896 14.3065 11.1379 14.4232 11.1379 14.5448V16.2483C11.1379 16.3699 11.0896 16.4866 11.0036 16.5726C10.9176 16.6586 10.8009 16.7069 10.6793 16.7069H8.97585C8.85421 16.7069 8.73756 16.6586 8.65155 16.5726C8.56555 16.4866 8.51723 16.3699 8.51723 16.2483V14.5448ZM9.1724 14.7414V16.0517H10.4827V14.7414H9.1724Z" fill="white"/>
-<path d="M4.58621 3.07672C4.58621 3.54975 4.95179 3.93106 5.40517 3.93106C5.85855 3.93106 6.22414 3.54975 6.22414 3.07672V1.96554H13.431V3.07672C13.431 3.54975 13.7966 3.93106 14.25 3.93106C14.7034 3.93106 15.069 3.54975 15.069 3.07672V1.96554H17.1924C18.5486 1.96554 19.6552 3.07344 19.6552 4.44537V15.8814C19.6552 17.598 18.2629 19 16.5372 19H3.11862C2.29194 18.9986 1.49951 18.6696 0.914954 18.0851C0.330399 17.5005 0.00138589 16.7081 0 15.8814V4.44537C0 3.07344 1.10724 1.95899 2.46279 1.96554H4.58621V3.07672ZM1.31034 5.89658V15.8814C1.31173 16.3605 1.5026 16.8195 1.84127 17.1583C2.17995 17.4971 2.63892 17.6881 3.11797 17.6897H14.0928V16.7069H13.2345C13.1128 16.7069 12.9962 16.6586 12.9102 16.5726C12.8242 16.4866 12.7759 16.3699 12.7759 16.2483V14.5449C12.7759 14.4232 12.8242 14.3066 12.9102 14.2206C12.9962 14.1346 13.1128 14.0862 13.2345 14.0862H14.9379C14.9823 14.0862 15.0264 14.0926 15.069 14.1052C15.5735 13.6702 16.2176 13.4309 16.8838 13.4311H18.3448V5.89658H1.31034ZM14.1 16.017C14.1331 15.5639 14.2771 15.1258 14.5193 14.7414H13.431V16.0518H14.098L14.1 16.017ZM14.7479 17.5541L18.2158 14.0862H16.8838C16.3179 14.088 15.7756 14.3135 15.3754 14.7137C14.9752 15.1139 14.7497 15.6562 14.7479 16.2221V17.5541Z" fill="white"/>
-<path d="M13.431 0.854345V1.96552H15.069V0.854345C15.069 0.38131 14.7034 0 14.25 0C13.7966 0 13.431 0.38131 13.431 0.854345Z" fill="white"/>
-</svg>
+<svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.58619 1.96552V0.854345C4.58619 0.38131 4.95178 0 5.40516 0C5.85854 0 6.22412 0.38131 6.22412 0.854345V1.96552H4.58619ZM12.7758 11.269C12.7758 11.1473 12.8242 11.0307 12.9102 10.9447C12.9962 10.8587 13.1128 10.8103 13.2345 10.8103H14.9379C15.0595 10.8103 15.1762 10.8587 15.2622 10.9447C15.3482 11.0307 15.3965 11.1473 15.3965 11.269V12.9724C15.3965 13.094 15.3482 13.2107 15.2622 13.2967C15.1762 13.3827 15.0595 13.431 14.9379 13.431H13.2345C13.1128 13.431 12.9962 13.3827 12.9102 13.2967C12.8242 13.2107 12.7758 13.094 12.7758 12.9724V11.269ZM4.25861 7.9931C4.25861 7.87147 4.30692 7.75482 4.39293 7.66881C4.47894 7.5828 4.59559 7.53448 4.71723 7.53448H6.42068C6.54231 7.53448 6.65896 7.5828 6.74497 7.66881C6.83098 7.75482 6.8793 7.87147 6.8793 7.9931V9.69655C6.8793 9.81818 6.83098 9.93484 6.74497 10.0208C6.65896 10.1069 6.54231 10.1552 6.42068 10.1552H4.71723C4.59559 10.1552 4.47894 10.1069 4.39293 10.0208C4.30692 9.93484 4.25861 9.81818 4.25861 9.69655V7.9931ZM4.91378 8.18966V9.5H6.22412V8.18966H4.91378ZM8.51723 7.9931C8.51723 7.87147 8.56555 7.75482 8.65155 7.66881C8.73756 7.5828 8.85421 7.53448 8.97585 7.53448H10.6793C10.8009 7.53448 10.9176 7.5828 11.0036 7.66881C11.0896 7.75482 11.1379 7.87147 11.1379 7.9931V9.69655C11.1379 9.81818 11.0896 9.93484 11.0036 10.0208C10.9176 10.1069 10.8009 10.1552 10.6793 10.1552H8.97585C8.85421 10.1552 8.73756 10.1069 8.65155 10.0208C8.56555 9.93484 8.51723 9.81818 8.51723 9.69655V7.9931ZM9.1724 8.18966V9.5H10.4827V8.18966H9.1724ZM12.7758 7.9931C12.7758 7.87147 12.8242 7.75482 12.9102 7.66881C12.9962 7.5828 13.1128 7.53448 13.2345 7.53448H14.9379C15.0595 7.53448 15.1762 7.5828 15.2622 7.66881C15.3482 7.75482 15.3965 7.87147 15.3965 7.9931V9.69655C15.3965 9.81818 15.3482 9.93484 15.2622 10.0208C15.1762 10.1069 15.0595 10.1552 14.9379 10.1552H13.2345C13.1128 10.1552 12.9962 10.1069 12.9102 10.0208C12.8242 9.93484 12.7758 9.81818 12.7758 9.69655V7.9931ZM13.431 8.18966V9.5H14.7414V8.18966H13.431ZM4.25861 11.269C4.25861 11.1473 4.30692 11.0307 4.39293 10.9447C4.47894 10.8587 4.59559 10.8103 4.71723 10.8103H6.42068C6.54231 10.8103 6.65896 10.8587 6.74497 10.9447C6.83098 11.0307 6.8793 11.1473 6.8793 11.269V12.9724C6.8793 13.094 6.83098 13.2107 6.74497 13.2967C6.65896 13.3827 6.54231 13.431 6.42068 13.431H4.71723C4.59559 13.431 4.47894 13.3827 4.39293 13.2967C4.30692 13.2107 4.25861 13.094 4.25861 12.9724V11.269ZM4.91378 11.4655V12.7759H6.22412V11.4655H4.91378ZM8.51723 11.269C8.51723 11.1473 8.56555 11.0307 8.65155 10.9447C8.73756 10.8587 8.85421 10.8103 8.97585 10.8103H10.6793C10.8009 10.8103 10.9176 10.8587 11.0036 10.9447C11.0896 11.0307 11.1379 11.1473 11.1379 11.269V12.9724C11.1379 13.094 11.0896 13.2107 11.0036 13.2967C10.9176 13.3827 10.8009 13.431 10.6793 13.431H8.97585C8.85421 13.431 8.73756 13.3827 8.65155 13.2967C8.56555 13.2107 8.51723 13.094 8.51723 12.9724V11.269ZM9.1724 11.4655V12.7759H10.4827V11.4655H9.1724ZM4.25861 14.5448C4.25861 14.4232 4.30692 14.3065 4.39293 14.2205C4.47894 14.1345 4.59559 14.0862 4.71723 14.0862H6.42068C6.54231 14.0862 6.65896 14.1345 6.74497 14.2205C6.83098 14.3065 6.8793 14.4232 6.8793 14.5448V16.2483C6.8793 16.3699 6.83098 16.4866 6.74497 16.5726C6.65896 16.6586 6.54231 16.7069 6.42068 16.7069H4.71723C4.59559 16.7069 4.47894 16.6586 4.39293 16.5726C4.30692 16.4866 4.25861 16.3699 4.25861 16.2483V14.5448ZM4.91378 14.7414V16.0517H6.22412V14.7414H4.91378ZM8.51723 14.5448C8.51723 14.4232 8.56555 14.3065 8.65155 14.2205C8.73756 14.1345 8.85421 14.0862 8.97585 14.0862H10.6793C10.8009 14.0862 10.9176 14.1345 11.0036 14.2205C11.0896 14.3065 11.1379 14.4232 11.1379 14.5448V16.2483C11.1379 16.3699 11.0896 16.4866 11.0036 16.5726C10.9176 16.6586 10.8009 16.7069 10.6793 16.7069H8.97585C8.85421 16.7069 8.73756 16.6586 8.65155 16.5726C8.56555 16.4866 8.51723 16.3699 8.51723 16.2483V14.5448ZM9.1724 14.7414V16.0517H10.4827V14.7414H9.1724Z" fill="white"/>
+<path d="M4.58621 3.07672C4.58621 3.54975 4.95179 3.93106 5.40517 3.93106C5.85855 3.93106 6.22414 3.54975 6.22414 3.07672V1.96554H13.431V3.07672C13.431 3.54975 13.7966 3.93106 14.25 3.93106C14.7034 3.93106 15.069 3.54975 15.069 3.07672V1.96554H17.1924C18.5486 1.96554 19.6552 3.07344 19.6552 4.44537V15.8814C19.6552 17.598 18.2629 19 16.5372 19H3.11862C2.29194 18.9986 1.49951 18.6696 0.914954 18.0851C0.330399 17.5005 0.00138589 16.7081 0 15.8814V4.44537C0 3.07344 1.10724 1.95899 2.46279 1.96554H4.58621V3.07672ZM1.31034 5.89658V15.8814C1.31173 16.3605 1.5026 16.8195 1.84127 17.1583C2.17995 17.4971 2.63892 17.6881 3.11797 17.6897H14.0928V16.7069H13.2345C13.1128 16.7069 12.9962 16.6586 12.9102 16.5726C12.8242 16.4866 12.7759 16.3699 12.7759 16.2483V14.5449C12.7759 14.4232 12.8242 14.3066 12.9102 14.2206C12.9962 14.1346 13.1128 14.0862 13.2345 14.0862H14.9379C14.9823 14.0862 15.0264 14.0926 15.069 14.1052C15.5735 13.6702 16.2176 13.4309 16.8838 13.4311H18.3448V5.89658H1.31034ZM14.1 16.017C14.1331 15.5639 14.2771 15.1258 14.5193 14.7414H13.431V16.0518H14.098L14.1 16.017ZM14.7479 17.5541L18.2158 14.0862H16.8838C16.3179 14.088 15.7756 14.3135 15.3754 14.7137C14.9752 15.1139 14.7497 15.6562 14.7479 16.2221V17.5541Z" fill="white"/>
+<path d="M13.431 0.854345V1.96552H15.069V0.854345C15.069 0.38131 14.7034 0 14.25 0C13.7966 0 13.431 0.38131 13.431 0.854345Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/assets/images/tinta.svg b/refilc/assets/images/tinta.svg
similarity index 99%
rename from filcnaplo/assets/images/tinta.svg
rename to refilc/assets/images/tinta.svg
index a9dfd9e..29fbd76 100644
--- a/filcnaplo/assets/images/tinta.svg
+++ b/refilc/assets/images/tinta.svg
@@ -1,3 +1,3 @@
-<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M6.63347 1.46773e-08C4.17718 1.46773e-08 2.15934 1.9315 1.9387 4.3981C1.66876 4.46542 1.43013 4.6275 1.26399 4.85636C1.09784 5.08522 1.01461 5.36652 1.02863 5.65173C1.04265 5.93694 1.15306 6.20817 1.34081 6.41864C1.52855 6.62911 1.78186 6.76561 2.05704 6.8046C2.099 6.97812 2.14991 7.14776 2.20932 7.31353L2.18622 7.30965C2.06688 7.28651 1.94628 7.27097 1.82508 7.26312H1.80057C1.49035 7.27282 1.31025 7.5234 1.25273 7.72988C1.19144 7.94993 1.22916 8.18792 1.32062 8.41621L1.35834 8.51024L0.640782 8.70217L0.637482 8.70314C0.400811 8.76809 0.0575906 8.92126 0.0057304 9.32016C-0.0140708 9.47187 0.0222314 9.60128 0.0420326 9.66381C0.0514617 9.69483 0.0627766 9.72536 0.0703199 9.7462L0.0722057 9.75153L0.0882353 9.79855C0.166497 10.0603 0.331035 10.3206 0.519618 10.5489C0.897617 11.0007 1.36672 11.3626 1.89439 11.6094L1.64357 11.8372C1.5589 11.9114 1.4921 12.0048 1.44839 12.11C1.39862 12.2346 1.38969 12.3724 1.42293 12.5027C1.44839 12.6054 1.49506 12.6868 1.52335 12.7338C1.54456 12.7687 1.57191 12.8099 1.59265 12.841L1.60963 12.8662C1.78642 13.1347 2.09805 13.3901 2.46155 13.5855C2.83447 13.7866 3.30074 13.9451 3.81934 13.9882C4.816 14.0716 5.96164 13.7241 6.96066 12.5419C7.96014 13.7246 9.10578 14.0716 10.102 13.9882C10.5761 13.9484 11.0377 13.8116 11.4598 13.5859C11.8233 13.3901 12.1349 13.1347 12.3117 12.8662L12.3287 12.841C12.3494 12.8099 12.3772 12.7683 12.398 12.7338C12.4428 12.6625 12.4766 12.5845 12.4984 12.5027C12.5316 12.3724 12.5227 12.2346 12.4729 12.11C12.4293 12.0051 12.3627 11.9118 12.2782 11.8377L12.0529 11.6326C12.6017 11.386 13.0896 11.0156 13.4804 10.5489C13.669 10.3206 13.8335 10.0603 13.9118 9.79855L13.9278 9.75153L13.9297 9.7462C13.9373 9.72536 13.9481 9.69483 13.958 9.66381C13.9773 9.60079 14.0141 9.47187 13.9943 9.32016C13.9425 8.92126 13.5992 8.76809 13.3626 8.70314L13.3593 8.70217L12.6412 8.51024L12.679 8.41621C12.7704 8.1884 12.8086 7.94993 12.7473 7.72988C12.6898 7.5234 12.5092 7.27282 12.199 7.26312H12.1754C12.0584 7.27055 11.9418 7.28544 11.8266 7.30771C11.8893 7.13128 11.9425 6.95001 11.9859 6.76486C12.2221 6.69215 12.4306 6.54602 12.5828 6.34656C12.735 6.14709 12.8233 5.90408 12.8357 5.6509C12.8481 5.39773 12.784 5.14681 12.6521 4.93264C12.5202 4.71847 12.327 4.55155 12.0991 4.45481C12.0032 3.24113 11.4666 2.10899 10.5958 1.28357C9.72506 0.45814 8.584 -9.46918e-05 7.39958 1.46773e-08H6.63347ZM11.1538 4.46984C10.9539 4.56225 10.7825 4.70948 10.6586 4.89538C10.5347 5.08128 10.4629 5.29868 10.4513 5.52373C10.4396 5.74877 10.4884 5.97279 10.5923 6.1712C10.6963 6.36961 10.8514 6.53476 11.0406 6.64853C10.8238 7.47062 10.3497 8.19645 9.69163 8.71399C9.03357 9.23153 8.22811 9.512 7.39958 9.5121H6.63347C5.78749 9.51203 4.96607 9.21968 4.30113 8.68199C3.63619 8.1443 3.16631 7.39247 2.96695 6.54723C3.11456 6.42609 3.23205 6.27062 3.30974 6.09363C3.38744 5.91665 3.4231 5.72321 3.4138 5.52927C3.4045 5.33533 3.3505 5.14644 3.25625 4.97817C3.162 4.8099 3.0302 4.66707 2.87171 4.56144C2.94183 3.58507 3.3686 2.67211 4.06635 2.00583C4.7641 1.33956 5.68117 0.969298 6.63347 0.969386H7.39958C8.33646 0.969275 9.23984 1.32765 9.93382 1.97471C10.6278 2.62178 11.0627 3.51122 11.1538 4.46984ZM10.7799 9.01335L12.9755 9.60128C12.935 9.68513 12.8661 9.79516 12.7615 9.92118C12.62 10.0928 12.4343 10.2702 12.224 10.4253C11.8718 10.6851 11.5107 10.8421 11.2113 10.8697C10.7876 10.485 10.3623 10.1021 9.93555 9.721C10.2425 9.51928 10.5259 9.28183 10.7799 9.01335ZM9.06665 10.1698C9.09494 10.2357 9.13784 10.2963 9.19536 10.3458C9.45466 10.5692 10.7201 11.716 11.4706 12.3975C11.3857 12.4896 11.2377 12.6107 11.0227 12.7271C10.7127 12.8925 10.3737 12.9928 10.0256 13.0222C9.28729 13.0838 8.36324 12.8293 7.51273 11.7058L7.5099 11.7024C7.4802 11.6636 7.41467 11.5764 7.32509 11.5105C7.21945 11.4319 7.09092 11.3925 6.96066 11.399C6.83039 11.3925 6.70186 11.4319 6.59622 11.5105C6.50664 11.5764 6.44064 11.6636 6.41141 11.7024L6.40905 11.7058C5.55807 12.8293 4.63402 13.0838 3.89619 13.0222C3.54787 12.9927 3.20875 12.8922 2.89859 12.7266C2.6836 12.6112 2.53557 12.4891 2.4507 12.3975L3.07303 11.8328C3.09377 11.8304 3.11499 11.828 3.13573 11.8246L3.1296 11.7809C3.65861 11.2991 4.19074 10.8208 4.72595 10.3463C4.7922 10.2895 4.84195 10.215 4.86975 10.131C5.43028 10.3633 6.02912 10.4823 6.63347 10.4815H7.39958C7.96904 10.4822 8.53389 10.3766 9.06665 10.1698ZM4.03338 9.67835C3.78775 9.895 3.25265 10.3778 2.71896 10.861C2.43373 10.8179 2.10041 10.6657 1.77511 10.4248C1.57712 10.2796 1.39669 10.1108 1.23765 9.92166C1.15436 9.82394 1.08267 9.71639 1.02408 9.60128L3.24605 9.00559C3.48319 9.25763 3.74721 9.4835 4.03338 9.67786V9.67835ZM2.31822 12.2123L2.31917 12.2147C2.31883 12.2139 2.31852 12.2131 2.31822 12.2123ZM11.6021 12.2123L11.6012 12.2147C11.6015 12.2139 11.6019 12.2131 11.6021 12.2123Z" fill="black"/>
-</svg>
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.63347 1.46773e-08C4.17718 1.46773e-08 2.15934 1.9315 1.9387 4.3981C1.66876 4.46542 1.43013 4.6275 1.26399 4.85636C1.09784 5.08522 1.01461 5.36652 1.02863 5.65173C1.04265 5.93694 1.15306 6.20817 1.34081 6.41864C1.52855 6.62911 1.78186 6.76561 2.05704 6.8046C2.099 6.97812 2.14991 7.14776 2.20932 7.31353L2.18622 7.30965C2.06688 7.28651 1.94628 7.27097 1.82508 7.26312H1.80057C1.49035 7.27282 1.31025 7.5234 1.25273 7.72988C1.19144 7.94993 1.22916 8.18792 1.32062 8.41621L1.35834 8.51024L0.640782 8.70217L0.637482 8.70314C0.400811 8.76809 0.0575906 8.92126 0.0057304 9.32016C-0.0140708 9.47187 0.0222314 9.60128 0.0420326 9.66381C0.0514617 9.69483 0.0627766 9.72536 0.0703199 9.7462L0.0722057 9.75153L0.0882353 9.79855C0.166497 10.0603 0.331035 10.3206 0.519618 10.5489C0.897617 11.0007 1.36672 11.3626 1.89439 11.6094L1.64357 11.8372C1.5589 11.9114 1.4921 12.0048 1.44839 12.11C1.39862 12.2346 1.38969 12.3724 1.42293 12.5027C1.44839 12.6054 1.49506 12.6868 1.52335 12.7338C1.54456 12.7687 1.57191 12.8099 1.59265 12.841L1.60963 12.8662C1.78642 13.1347 2.09805 13.3901 2.46155 13.5855C2.83447 13.7866 3.30074 13.9451 3.81934 13.9882C4.816 14.0716 5.96164 13.7241 6.96066 12.5419C7.96014 13.7246 9.10578 14.0716 10.102 13.9882C10.5761 13.9484 11.0377 13.8116 11.4598 13.5859C11.8233 13.3901 12.1349 13.1347 12.3117 12.8662L12.3287 12.841C12.3494 12.8099 12.3772 12.7683 12.398 12.7338C12.4428 12.6625 12.4766 12.5845 12.4984 12.5027C12.5316 12.3724 12.5227 12.2346 12.4729 12.11C12.4293 12.0051 12.3627 11.9118 12.2782 11.8377L12.0529 11.6326C12.6017 11.386 13.0896 11.0156 13.4804 10.5489C13.669 10.3206 13.8335 10.0603 13.9118 9.79855L13.9278 9.75153L13.9297 9.7462C13.9373 9.72536 13.9481 9.69483 13.958 9.66381C13.9773 9.60079 14.0141 9.47187 13.9943 9.32016C13.9425 8.92126 13.5992 8.76809 13.3626 8.70314L13.3593 8.70217L12.6412 8.51024L12.679 8.41621C12.7704 8.1884 12.8086 7.94993 12.7473 7.72988C12.6898 7.5234 12.5092 7.27282 12.199 7.26312H12.1754C12.0584 7.27055 11.9418 7.28544 11.8266 7.30771C11.8893 7.13128 11.9425 6.95001 11.9859 6.76486C12.2221 6.69215 12.4306 6.54602 12.5828 6.34656C12.735 6.14709 12.8233 5.90408 12.8357 5.6509C12.8481 5.39773 12.784 5.14681 12.6521 4.93264C12.5202 4.71847 12.327 4.55155 12.0991 4.45481C12.0032 3.24113 11.4666 2.10899 10.5958 1.28357C9.72506 0.45814 8.584 -9.46918e-05 7.39958 1.46773e-08H6.63347ZM11.1538 4.46984C10.9539 4.56225 10.7825 4.70948 10.6586 4.89538C10.5347 5.08128 10.4629 5.29868 10.4513 5.52373C10.4396 5.74877 10.4884 5.97279 10.5923 6.1712C10.6963 6.36961 10.8514 6.53476 11.0406 6.64853C10.8238 7.47062 10.3497 8.19645 9.69163 8.71399C9.03357 9.23153 8.22811 9.512 7.39958 9.5121H6.63347C5.78749 9.51203 4.96607 9.21968 4.30113 8.68199C3.63619 8.1443 3.16631 7.39247 2.96695 6.54723C3.11456 6.42609 3.23205 6.27062 3.30974 6.09363C3.38744 5.91665 3.4231 5.72321 3.4138 5.52927C3.4045 5.33533 3.3505 5.14644 3.25625 4.97817C3.162 4.8099 3.0302 4.66707 2.87171 4.56144C2.94183 3.58507 3.3686 2.67211 4.06635 2.00583C4.7641 1.33956 5.68117 0.969298 6.63347 0.969386H7.39958C8.33646 0.969275 9.23984 1.32765 9.93382 1.97471C10.6278 2.62178 11.0627 3.51122 11.1538 4.46984ZM10.7799 9.01335L12.9755 9.60128C12.935 9.68513 12.8661 9.79516 12.7615 9.92118C12.62 10.0928 12.4343 10.2702 12.224 10.4253C11.8718 10.6851 11.5107 10.8421 11.2113 10.8697C10.7876 10.485 10.3623 10.1021 9.93555 9.721C10.2425 9.51928 10.5259 9.28183 10.7799 9.01335ZM9.06665 10.1698C9.09494 10.2357 9.13784 10.2963 9.19536 10.3458C9.45466 10.5692 10.7201 11.716 11.4706 12.3975C11.3857 12.4896 11.2377 12.6107 11.0227 12.7271C10.7127 12.8925 10.3737 12.9928 10.0256 13.0222C9.28729 13.0838 8.36324 12.8293 7.51273 11.7058L7.5099 11.7024C7.4802 11.6636 7.41467 11.5764 7.32509 11.5105C7.21945 11.4319 7.09092 11.3925 6.96066 11.399C6.83039 11.3925 6.70186 11.4319 6.59622 11.5105C6.50664 11.5764 6.44064 11.6636 6.41141 11.7024L6.40905 11.7058C5.55807 12.8293 4.63402 13.0838 3.89619 13.0222C3.54787 12.9927 3.20875 12.8922 2.89859 12.7266C2.6836 12.6112 2.53557 12.4891 2.4507 12.3975L3.07303 11.8328C3.09377 11.8304 3.11499 11.828 3.13573 11.8246L3.1296 11.7809C3.65861 11.2991 4.19074 10.8208 4.72595 10.3463C4.7922 10.2895 4.84195 10.215 4.86975 10.131C5.43028 10.3633 6.02912 10.4823 6.63347 10.4815H7.39958C7.96904 10.4822 8.53389 10.3766 9.06665 10.1698ZM4.03338 9.67835C3.78775 9.895 3.25265 10.3778 2.71896 10.861C2.43373 10.8179 2.10041 10.6657 1.77511 10.4248C1.57712 10.2796 1.39669 10.1108 1.23765 9.92166C1.15436 9.82394 1.08267 9.71639 1.02408 9.60128L3.24605 9.00559C3.48319 9.25763 3.74721 9.4835 4.03338 9.67786V9.67835ZM2.31822 12.2123L2.31917 12.2147C2.31883 12.2139 2.31852 12.2131 2.31822 12.2123ZM11.6021 12.2123L11.6012 12.2147C11.6015 12.2139 11.6019 12.2131 11.6021 12.2123Z" fill="black"/>
+</svg>
diff --git a/filcnaplo/assets/images/widget_icon.svg b/refilc/assets/images/widget_icon.svg
similarity index 98%
rename from filcnaplo/assets/images/widget_icon.svg
rename to refilc/assets/images/widget_icon.svg
index 4b6be9f..73e4782 100644
--- a/filcnaplo/assets/images/widget_icon.svg
+++ b/refilc/assets/images/widget_icon.svg
@@ -1,3 +1,3 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M13.65 11.3L8 5.65L13.65 0L19.3 5.65L13.65 11.3ZM0 9.3V1.3H8V9.3H0ZM10 19.3V11.3H18V19.3H10ZM0 19.3V11.3H8V19.3H0Z" fill="white"/>
-</svg>
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13.65 11.3L8 5.65L13.65 0L19.3 5.65L13.65 11.3ZM0 9.3V1.3H8V9.3H0ZM10 19.3V11.3H18V19.3H10ZM0 19.3V11.3H8V19.3H0Z" fill="white"/>
+</svg>
diff --git a/filcnaplo/build-ipa.sh b/refilc/build-ipa.sh
old mode 100755
new mode 100644
similarity index 100%
rename from filcnaplo/build-ipa.sh
rename to refilc/build-ipa.sh
diff --git a/filcnaplo/build.sh b/refilc/build.sh
old mode 100755
new mode 100644
similarity index 100%
rename from filcnaplo/build.sh
rename to refilc/build.sh
diff --git a/filcnaplo/ios/Flutter/AppFrameworkInfo.plist b/refilc/ios/Flutter/AppFrameworkInfo.plist
similarity index 96%
rename from filcnaplo/ios/Flutter/AppFrameworkInfo.plist
rename to refilc/ios/Flutter/AppFrameworkInfo.plist
index 0d9747f..9625e10 100644
--- a/filcnaplo/ios/Flutter/AppFrameworkInfo.plist
+++ b/refilc/ios/Flutter/AppFrameworkInfo.plist
@@ -1,26 +1,26 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-  <key>CFBundleDevelopmentRegion</key>
-  <string>en</string>
-  <key>CFBundleExecutable</key>
-  <string>App</string>
-  <key>CFBundleIdentifier</key>
-  <string>io.flutter.flutter.app</string>
-  <key>CFBundleInfoDictionaryVersion</key>
-  <string>6.0</string>
-  <key>CFBundleName</key>
-  <string>App</string>
-  <key>CFBundlePackageType</key>
-  <string>FMWK</string>
-  <key>CFBundleShortVersionString</key>
-  <string>1.0</string>
-  <key>CFBundleSignature</key>
-  <string>????</string>
-  <key>CFBundleVersion</key>
-  <string>1.0</string>
-  <key>MinimumOSVersion</key>
-  <string>11.0</string>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleExecutable</key>
+  <string>App</string>
+  <key>CFBundleIdentifier</key>
+  <string>io.flutter.flutter.app</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>App</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>1.0</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1.0</string>
+  <key>MinimumOSVersion</key>
+  <string>11.0</string>
+</dict>
+</plist>
diff --git a/filcnaplo/ios/Flutter/Debug.xcconfig b/refilc/ios/Flutter/Debug.xcconfig
similarity index 98%
rename from filcnaplo/ios/Flutter/Debug.xcconfig
rename to refilc/ios/Flutter/Debug.xcconfig
index 553cfac..ec97fc6 100644
--- a/filcnaplo/ios/Flutter/Debug.xcconfig
+++ b/refilc/ios/Flutter/Debug.xcconfig
@@ -1,2 +1,2 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
-#include "Generated.xcconfig"
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "Generated.xcconfig"
diff --git a/filcnaplo/ios/Flutter/Release.xcconfig b/refilc/ios/Flutter/Release.xcconfig
similarity index 98%
rename from filcnaplo/ios/Flutter/Release.xcconfig
rename to refilc/ios/Flutter/Release.xcconfig
index 4b6e1f6..c4855bf 100644
--- a/filcnaplo/ios/Flutter/Release.xcconfig
+++ b/refilc/ios/Flutter/Release.xcconfig
@@ -1,2 +1,2 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
-#include "Generated.xcconfig"
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "Generated.xcconfig"
diff --git a/filcnaplo/ios/Podfile b/refilc/ios/Podfile
similarity index 97%
rename from filcnaplo/ios/Podfile
rename to refilc/ios/Podfile
index 4cbad0e..d805285 100644
--- a/filcnaplo/ios/Podfile
+++ b/refilc/ios/Podfile
@@ -1,43 +1,43 @@
-# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
-
-# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
-ENV['COCOAPODS_DISABLE_STATS'] = 'true'
-
-project 'Runner', {
-  'Debug' => :debug,
-  'Profile' => :release,
-  'Release' => :release,
-}
-
-def flutter_root
-  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
-  unless File.exist?(generated_xcode_build_settings_path)
-    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
-  end
-
-  File.foreach(generated_xcode_build_settings_path) do |line|
-    matches = line.match(/FLUTTER_ROOT\=(.*)/)
-    return matches[1].strip if matches
-  end
-  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
-end
-
-require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
-
-flutter_ios_podfile_setup
-
-target 'Runner' do
-  use_frameworks!
-  use_modular_headers!
-
-  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
-
-  pod 'DKImagePickerController/PhotoGallery', :git => 'https://github.com/zhangao0086/DKImagePickerController.git'
-end
-
-post_install do |installer|
-  installer.pods_project.targets.each do |target|
-    flutter_additional_ios_build_settings(target)
-  end
-end
+# Uncomment this line to define a global platform for your project
+# platform :ios, '11.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+  'Debug' => :debug,
+  'Profile' => :release,
+  'Release' => :release,
+}
+
+def flutter_root
+  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+  unless File.exist?(generated_xcode_build_settings_path)
+    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+  end
+
+  File.foreach(generated_xcode_build_settings_path) do |line|
+    matches = line.match(/FLUTTER_ROOT\=(.*)/)
+    return matches[1].strip if matches
+  end
+  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+  use_frameworks!
+  use_modular_headers!
+
+  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+
+  pod 'DKImagePickerController/PhotoGallery', :git => 'https://github.com/zhangao0086/DKImagePickerController.git'
+end
+
+post_install do |installer|
+  installer.pods_project.targets.each do |target|
+    flutter_additional_ios_build_settings(target)
+  end
+end
diff --git a/filcnaplo/ios/Runner.xcodeproj/project.pbxproj b/refilc/ios/Runner.xcodeproj/project.pbxproj
similarity index 100%
rename from filcnaplo/ios/Runner.xcodeproj/project.pbxproj
rename to refilc/ios/Runner.xcodeproj/project.pbxproj
diff --git a/filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/refilc/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 95%
rename from filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to refilc/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index c4b79bd..919434a 100644
--- a/filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/refilc/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
-   version = "1.0">
-   <FileRef
-      location = "self:">
-   </FileRef>
-</Workspace>
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git a/filcnaplo/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/refilc/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 96%
rename from filcnaplo/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to refilc/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index fc6bf80..18d9810 100644
--- a/filcnaplo/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/refilc/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>IDEDidComputeMac32BitWarning</key>
-	<true/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/filcnaplo/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/refilc/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
similarity index 96%
rename from filcnaplo/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
rename to refilc/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
index af0309c..f9b0d7c 100644
--- a/filcnaplo/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ b/refilc/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>PreviewsEnabled</key>
-	<false/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>PreviewsEnabled</key>
+	<false/>
+</dict>
+</plist>
diff --git a/filcnaplo/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/refilc/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
similarity index 97%
rename from filcnaplo/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
rename to refilc/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index f9cbb25..c87d15a 100644
--- a/filcnaplo/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/refilc/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,87 +1,87 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1300"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
-               BuildableName = "Runner.app"
-               BlueprintName = "Runner"
-               ReferencedContainer = "container:Runner.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
-            BuildableName = "Runner.app"
-            BlueprintName = "Runner"
-            ReferencedContainer = "container:Runner.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <Testables>
-      </Testables>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
-            BuildableName = "Runner.app"
-            BlueprintName = "Runner"
-            ReferencedContainer = "container:Runner.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Profile"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
-            BuildableName = "Runner.app"
-            BlueprintName = "Runner"
-            ReferencedContainer = "container:Runner.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1300"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+               BuildableName = "Runner.app"
+               BlueprintName = "Runner"
+               ReferencedContainer = "container:Runner.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+            BuildableName = "Runner.app"
+            BlueprintName = "Runner"
+            ReferencedContainer = "container:Runner.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+            BuildableName = "Runner.app"
+            BlueprintName = "Runner"
+            ReferencedContainer = "container:Runner.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Profile"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
+            BuildableName = "Runner.app"
+            BlueprintName = "Runner"
+            ReferencedContainer = "container:Runner.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/filcnaplo/macos/Runner.xcworkspace/contents.xcworkspacedata b/refilc/ios/Runner.xcworkspace/contents.xcworkspacedata
similarity index 95%
rename from filcnaplo/macos/Runner.xcworkspace/contents.xcworkspacedata
rename to refilc/ios/Runner.xcworkspace/contents.xcworkspacedata
index 17ccc03..21a3cc1 100644
--- a/filcnaplo/macos/Runner.xcworkspace/contents.xcworkspacedata
+++ b/refilc/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
-   version = "1.0">
-   <FileRef
-      location = "group:Runner.xcodeproj">
-   </FileRef>
-   <FileRef
-      location = "group:Pods/Pods.xcodeproj">
-   </FileRef>
-</Workspace>
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:Runner.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/refilc/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 96%
rename from filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to refilc/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index fc6bf80..18d9810 100644
--- a/filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/refilc/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>IDEDidComputeMac32BitWarning</key>
-	<true/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/refilc/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
similarity index 96%
rename from filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
rename to refilc/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
index af0309c..f9b0d7c 100644
--- a/filcnaplo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ b/refilc/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>PreviewsEnabled</key>
-	<false/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>PreviewsEnabled</key>
+	<false/>
+</dict>
+</plist>
diff --git a/filcnaplo/ios/Runner/AppDelegate.swift b/refilc/ios/Runner/AppDelegate.swift
similarity index 96%
rename from filcnaplo/ios/Runner/AppDelegate.swift
rename to refilc/ios/Runner/AppDelegate.swift
index 028b1bd..2c4c46e 100644
--- a/filcnaplo/ios/Runner/AppDelegate.swift
+++ b/refilc/ios/Runner/AppDelegate.swift
@@ -1,25 +1,25 @@
-import UIKit
-import Flutter
-
-@UIApplicationMain
-@objc class AppDelegate: FlutterAppDelegate {
-  override func application(
-    _ application: UIApplication,
-    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
-  ) -> Bool {
-    GeneratedPluginRegistrant.register(with: self)
-
-    // here, Without this code the task will not work.
-    //SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback(registerPlugins)
-    if #available(iOS 10.0, *) {
-      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
-    }
-
-    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
-  }
-}
-
-// here
-func registerPlugins(registry: FlutterPluginRegistry) {
-  GeneratedPluginRegistrant.register(with: registry)
-}
+import UIKit
+import Flutter
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+  override func application(
+    _ application: UIApplication,
+    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+  ) -> Bool {
+    GeneratedPluginRegistrant.register(with: self)
+
+    // here, Without this code the task will not work.
+    //SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback(registerPlugins)
+    if #available(iOS 10.0, *) {
+      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
+    }
+
+    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+  }
+}
+
+// here
+func registerPlugins(registry: FlutterPluginRegistry) {
+  GeneratedPluginRegistrant.register(with: registry)
+}
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/refilc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png b/refilc/ios/Runner/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png
rename to refilc/ios/Runner/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/Contents.json b/refilc/ios/Runner/Assets.xcassets/Contents.json
similarity index 91%
rename from filcnaplo/ios/Runner/Assets.xcassets/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/Contents.json
index b2cf395..73c0059 100644
--- a/filcnaplo/ios/Runner/Assets.xcassets/Contents.json
+++ b/refilc/ios/Runner/Assets.xcassets/Contents.json
@@ -1,6 +1,6 @@
-{
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json b/refilc/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/refilc/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
rename to refilc/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
rename to refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
rename to refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
rename to refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
similarity index 97%
rename from filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
rename to refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
index 65a94b5..89c2725 100644
--- a/filcnaplo/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
+++ b/refilc/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
@@ -1,5 +1,5 @@
-# Launch Screen Assets
-
-You can customize the launch screen with your own desired assets by replacing the image files in this directory.
-
+# Launch Screen Assets
+
+You can customize the launch screen with your own desired assets by replacing the image files in this directory.
+
 You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json b/refilc/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json
similarity index 93%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json
index 49eded8..2945b36 100644
--- a/filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json
+++ b/refilc/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json
@@ -1,21 +1,21 @@
-{
-  "images" : [
-    {
-      "filename" : "icon.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "images" : [
+    {
+      "filename" : "icon.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/icon.png b/refilc/ios/Runner/Assets.xcassets/ic_absences.imageset/icon.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/icon.png
rename to refilc/ios/Runner/Assets.xcassets/ic_absences.imageset/icon.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json b/refilc/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json
similarity index 93%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json
index 49eded8..2945b36 100644
--- a/filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json
+++ b/refilc/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json
@@ -1,21 +1,21 @@
-{
-  "images" : [
-    {
-      "filename" : "icon.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "images" : [
+    {
+      "filename" : "icon.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/icon.png b/refilc/ios/Runner/Assets.xcassets/ic_grades.imageset/icon.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/icon.png
rename to refilc/ios/Runner/Assets.xcassets/ic_grades.imageset/icon.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json b/refilc/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json
similarity index 93%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json
index 49eded8..2945b36 100644
--- a/filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json
+++ b/refilc/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json
@@ -1,21 +1,21 @@
-{
-  "images" : [
-    {
-      "filename" : "icon.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "images" : [
+    {
+      "filename" : "icon.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/icon.png b/refilc/ios/Runner/Assets.xcassets/ic_messages.imageset/icon.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/icon.png
rename to refilc/ios/Runner/Assets.xcassets/ic_messages.imageset/icon.png
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json b/refilc/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json
similarity index 93%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json
rename to refilc/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json
index 49eded8..2945b36 100644
--- a/filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json
+++ b/refilc/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json
@@ -1,21 +1,21 @@
-{
-  "images" : [
-    {
-      "filename" : "icon.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "images" : [
+    {
+      "filename" : "icon.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/icon.png b/refilc/ios/Runner/Assets.xcassets/ic_timetable.imageset/icon.png
similarity index 100%
rename from filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/icon.png
rename to refilc/ios/Runner/Assets.xcassets/ic_timetable.imageset/icon.png
diff --git a/filcnaplo/ios/Runner/Base.lproj/LaunchScreen.storyboard b/refilc/ios/Runner/Base.lproj/LaunchScreen.storyboard
similarity index 100%
rename from filcnaplo/ios/Runner/Base.lproj/LaunchScreen.storyboard
rename to refilc/ios/Runner/Base.lproj/LaunchScreen.storyboard
diff --git a/filcnaplo/ios/Runner/Base.lproj/Main.storyboard b/refilc/ios/Runner/Base.lproj/Main.storyboard
similarity index 98%
rename from filcnaplo/ios/Runner/Base.lproj/Main.storyboard
rename to refilc/ios/Runner/Base.lproj/Main.storyboard
index bbb83ca..f3c2851 100644
--- a/filcnaplo/ios/Runner/Base.lproj/Main.storyboard
+++ b/refilc/ios/Runner/Base.lproj/Main.storyboard
@@ -1,26 +1,26 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
-    </dependencies>
-    <scenes>
-        <!--Flutter View Controller-->
-        <scene sceneID="tne-QT-ifu">
-            <objects>
-                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
-                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
-                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
-            </objects>
-        </scene>
-    </scenes>
-</document>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+    </dependencies>
+    <scenes>
+        <!--Flutter View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
+                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+</document>
diff --git a/filcnaplo/ios/Runner/Info.plist b/refilc/ios/Runner/Info.plist
similarity index 100%
rename from filcnaplo/ios/Runner/Info.plist
rename to refilc/ios/Runner/Info.plist
diff --git a/filcnaplo/ios/Runner/Runner-Bridging-Header.h b/refilc/ios/Runner/Runner-Bridging-Header.h
similarity index 97%
rename from filcnaplo/ios/Runner/Runner-Bridging-Header.h
rename to refilc/ios/Runner/Runner-Bridging-Header.h
index fae207f..308a2a5 100644
--- a/filcnaplo/ios/Runner/Runner-Bridging-Header.h
+++ b/refilc/ios/Runner/Runner-Bridging-Header.h
@@ -1 +1 @@
-#import "GeneratedPluginRegistrant.h"
+#import "GeneratedPluginRegistrant.h"
diff --git a/filcnaplo/ios/Runner/Runner.entitlements b/refilc/ios/Runner/Runner.entitlements
similarity index 87%
rename from filcnaplo/ios/Runner/Runner.entitlements
rename to refilc/ios/Runner/Runner.entitlements
index 36e7279..30901d6 100644
--- a/filcnaplo/ios/Runner/Runner.entitlements
+++ b/refilc/ios/Runner/Runner.entitlements
@@ -6,7 +6,7 @@
 	<string>development</string>
 	<key>com.apple.security.application-groups</key>
 	<array>
-		<string>group.refilcnaplo.livecard</string>
+		<string>group.rerefilc.livecard</string>
 	</array>
 </dict>
 </plist>
diff --git a/filcnaplo/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json b/refilc/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json
similarity index 91%
rename from filcnaplo/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json
rename to refilc/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json
index 78e16c0..eb87897 100644
--- a/filcnaplo/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json
+++ b/refilc/ios/livecard/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -1,11 +1,11 @@
-{
-  "colors" : [
-    {
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json b/refilc/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to refilc/ios/livecard/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png b/refilc/ios/livecard/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png
similarity index 100%
rename from filcnaplo/ios/livecard/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png
rename to refilc/ios/livecard/Assets.xcassets/AppIcon.appiconset/reFilc_Logo.png
diff --git a/filcnaplo/ios/livecard/Assets.xcassets/Contents.json b/refilc/ios/livecard/Assets.xcassets/Contents.json
similarity index 91%
rename from filcnaplo/ios/livecard/Assets.xcassets/Contents.json
rename to refilc/ios/livecard/Assets.xcassets/Contents.json
index b2cf395..73c0059 100644
--- a/filcnaplo/ios/livecard/Assets.xcassets/Contents.json
+++ b/refilc/ios/livecard/Assets.xcassets/Contents.json
@@ -1,6 +1,6 @@
-{
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json b/refilc/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json
similarity index 91%
rename from filcnaplo/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json
rename to refilc/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json
index 78e16c0..eb87897 100644
--- a/filcnaplo/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json
+++ b/refilc/ios/livecard/Assets.xcassets/WidgetBackground.colorset/Contents.json
@@ -1,11 +1,11 @@
-{
-  "colors" : [
-    {
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/filcnaplo/ios/livecard/Info.plist b/refilc/ios/livecard/Info.plist
similarity index 100%
rename from filcnaplo/ios/livecard/Info.plist
rename to refilc/ios/livecard/Info.plist
diff --git a/filcnaplo/ios/livecard/lesson_model.swift b/refilc/ios/livecard/lesson_model.swift
similarity index 97%
rename from filcnaplo/ios/livecard/lesson_model.swift
rename to refilc/ios/livecard/lesson_model.swift
index 7ca85b0..83545b2 100644
--- a/filcnaplo/ios/livecard/lesson_model.swift
+++ b/refilc/ios/livecard/lesson_model.swift
@@ -1,31 +1,31 @@
-import Foundation
-
-class LessonData {
-  var color: String
-  var icon: String
-  var index: String
-  var title: String
-  var subtitle: String
-  var description: String
-  var startDate: Date
-  var endDate: Date
-  var date: ClosedRange<Date>
-  var nextSubject: String
-  var nextRoom: String
-    
-  init?() {
-    let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
-      
-    self.color = sharedDefault.string(forKey: "color")!
-    self.icon = sharedDefault.string(forKey: "icon")!
-    self.index = sharedDefault.string(forKey: "index")!
-    self.title = sharedDefault.string(forKey: "title")!
-    self.subtitle = sharedDefault.string(forKey: "subtitle")!
-    self.description = sharedDefault.string(forKey: "description")!
-    self.startDate = Date(timeIntervalSince1970: Double(sharedDefault.string(forKey: "startDate")!)! / 1000)
-    self.endDate = Date(timeIntervalSince1970: Double(sharedDefault.string(forKey: "endDate")!)! / 1000)
-    date = self.startDate...self.endDate
-    self.nextSubject = sharedDefault.string(forKey: "nextSubject")!
-    self.nextRoom = sharedDefault.string(forKey: "nextRoom")!
-  }
-}
+import Foundation
+
+class LessonData {
+  var color: String
+  var icon: String
+  var index: String
+  var title: String
+  var subtitle: String
+  var description: String
+  var startDate: Date
+  var endDate: Date
+  var date: ClosedRange<Date>
+  var nextSubject: String
+  var nextRoom: String
+    
+  init?() {
+    let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
+      
+    self.color = sharedDefault.string(forKey: "color")!
+    self.icon = sharedDefault.string(forKey: "icon")!
+    self.index = sharedDefault.string(forKey: "index")!
+    self.title = sharedDefault.string(forKey: "title")!
+    self.subtitle = sharedDefault.string(forKey: "subtitle")!
+    self.description = sharedDefault.string(forKey: "description")!
+    self.startDate = Date(timeIntervalSince1970: Double(sharedDefault.string(forKey: "startDate")!)! / 1000)
+    self.endDate = Date(timeIntervalSince1970: Double(sharedDefault.string(forKey: "endDate")!)! / 1000)
+    date = self.startDate...self.endDate
+    self.nextSubject = sharedDefault.string(forKey: "nextSubject")!
+    self.nextRoom = sharedDefault.string(forKey: "nextRoom")!
+  }
+}
diff --git a/filcnaplo/ios/livecard/livecard.entitlements b/refilc/ios/livecard/livecard.entitlements
similarity index 87%
rename from filcnaplo/ios/livecard/livecard.entitlements
rename to refilc/ios/livecard/livecard.entitlements
index 36e7279..30901d6 100644
--- a/filcnaplo/ios/livecard/livecard.entitlements
+++ b/refilc/ios/livecard/livecard.entitlements
@@ -6,7 +6,7 @@
 	<string>development</string>
 	<key>com.apple.security.application-groups</key>
 	<array>
-		<string>group.refilcnaplo.livecard</string>
+		<string>group.rerefilc.livecard</string>
 	</array>
 </dict>
 </plist>
diff --git a/filcnaplo/ios/livecard/livecard.intentdefinition b/refilc/ios/livecard/livecard.intentdefinition
similarity index 96%
rename from filcnaplo/ios/livecard/livecard.intentdefinition
rename to refilc/ios/livecard/livecard.intentdefinition
index b3d4023..bdb4045 100644
--- a/filcnaplo/ios/livecard/livecard.intentdefinition
+++ b/refilc/ios/livecard/livecard.intentdefinition
@@ -1,59 +1,59 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>INEnums</key>
-	<array/>
-	<key>INIntentDefinitionModelVersion</key>
-	<string>1.2</string>
-	<key>INIntentDefinitionNamespace</key>
-	<string>88xZPY</string>
-	<key>INIntentDefinitionSystemVersion</key>
-	<string>20A294</string>
-	<key>INIntentDefinitionToolsBuildVersion</key>
-	<string>12A6144</string>
-	<key>INIntentDefinitionToolsVersion</key>
-	<string>12.0</string>
-	<key>INIntents</key>
-	<array>
-		<dict>
-			<key>INIntentCategory</key>
-			<string>information</string>
-			<key>INIntentDescriptionID</key>
-			<string>tVvJ9c</string>
-			<key>INIntentEligibleForWidgets</key>
-			<true/>
-			<key>INIntentIneligibleForSuggestions</key>
-			<true/>
-			<key>INIntentName</key>
-			<string>Configuration</string>
-			<key>INIntentResponse</key>
-			<dict>
-				<key>INIntentResponseCodes</key>
-				<array>
-					<dict>
-						<key>INIntentResponseCodeName</key>
-						<string>success</string>
-						<key>INIntentResponseCodeSuccess</key>
-						<true/>
-					</dict>
-					<dict>
-						<key>INIntentResponseCodeName</key>
-						<string>failure</string>
-					</dict>
-				</array>
-			</dict>
-			<key>INIntentTitle</key>
-			<string>Configuration</string>
-			<key>INIntentTitleID</key>
-			<string>gpCwrM</string>
-			<key>INIntentType</key>
-			<string>Custom</string>
-			<key>INIntentVerb</key>
-			<string>View</string>
-		</dict>
-	</array>
-	<key>INTypes</key>
-	<array/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>INEnums</key>
+	<array/>
+	<key>INIntentDefinitionModelVersion</key>
+	<string>1.2</string>
+	<key>INIntentDefinitionNamespace</key>
+	<string>88xZPY</string>
+	<key>INIntentDefinitionSystemVersion</key>
+	<string>20A294</string>
+	<key>INIntentDefinitionToolsBuildVersion</key>
+	<string>12A6144</string>
+	<key>INIntentDefinitionToolsVersion</key>
+	<string>12.0</string>
+	<key>INIntents</key>
+	<array>
+		<dict>
+			<key>INIntentCategory</key>
+			<string>information</string>
+			<key>INIntentDescriptionID</key>
+			<string>tVvJ9c</string>
+			<key>INIntentEligibleForWidgets</key>
+			<true/>
+			<key>INIntentIneligibleForSuggestions</key>
+			<true/>
+			<key>INIntentName</key>
+			<string>Configuration</string>
+			<key>INIntentResponse</key>
+			<dict>
+				<key>INIntentResponseCodes</key>
+				<array>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>success</string>
+						<key>INIntentResponseCodeSuccess</key>
+						<true/>
+					</dict>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>failure</string>
+					</dict>
+				</array>
+			</dict>
+			<key>INIntentTitle</key>
+			<string>Configuration</string>
+			<key>INIntentTitleID</key>
+			<string>gpCwrM</string>
+			<key>INIntentType</key>
+			<string>Custom</string>
+			<key>INIntentVerb</key>
+			<string>View</string>
+		</dict>
+	</array>
+	<key>INTypes</key>
+	<array/>
+</dict>
+</plist>
diff --git a/filcnaplo/ios/livecard/livecard.swift b/refilc/ios/livecard/livecard.swift
similarity index 96%
rename from filcnaplo/ios/livecard/livecard.swift
rename to refilc/ios/livecard/livecard.swift
index ab37a77..00ff666 100644
--- a/filcnaplo/ios/livecard/livecard.swift
+++ b/refilc/ios/livecard/livecard.swift
@@ -1,186 +1,186 @@
-import ActivityKit
-import WidgetKit
-import SwiftUI
-
-@main
-struct Widgets: WidgetBundle {
-  var body: some Widget {
-    if #available(iOS 16.1, *) {
-      LiveCardWidget()
-    }
-  }
-}
-
-// Color Converter
-extension Color {
-    init(hex: String, alpha: Double = 1.0) {
-        var hexValue = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
-
-        if hexValue.hasPrefix("#") {
-            hexValue.remove(at: hexValue.startIndex)
-        }
-
-        var rgbValue: UInt64 = 0
-        Scanner(string: hexValue).scanHexInt64(&rgbValue)
-
-        let red = Double((rgbValue & 0xFF0000) >> 16) / 255.0
-        let green = Double((rgbValue & 0x00FF00) >> 8) / 255.0
-        let blue = Double(rgbValue & 0x0000FF) / 255.0
-
-        self.init(
-            .sRGB,
-            red: red,
-            green: green,
-            blue: blue,
-            opacity: alpha
-        )
-    }
-}
-
-
-// We need to redefined live activities pipe
-struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable {
-  public struct ContentState: Codable, Hashable { }
-  
-  var id = UUID()
-}
-
-struct LockScreenLiveActivityView: View {
-  let context: ActivityViewContext<LiveActivitiesAppAttributes>
-
-  let lesson = LessonData()
-
-  var body: some View {
-    HStack(alignment: .center) {
-      Image(systemName: lesson!.icon)
-        .resizable()
-        .aspectRatio(contentMode: .fit)
-        .frame(width: CGFloat(30), height: CGFloat(30))
-        .padding(.leading, CGFloat(24))
-
-      VStack(alignment: .leading) {
-        HStack(alignment: .center) {
-          Text(lesson!.index + lesson!.title)
-            .font(.title3)
-            .bold()
-
-          Text(lesson!.subtitle)
-            .font(.subheadline)
-            .padding(.trailing, 12)
-        }
-        
-        if (lesson!.description != "") {
-          Text(lesson!.description)
-            .font(.subheadline)
-        }
-
-        HStack {
-          Image(systemName: "arrow.right")
-            .resizable()
-            .aspectRatio(contentMode: .fit)
-            .frame(width: CGFloat(8), height: CGFloat(8))
-          Text(lesson!.nextSubject)
-            .font(.caption)
-          Text(lesson!.nextRoom)
-            .font(.caption2)
-        }
-      }.padding(15)
-
-      Spacer()
-      
-      Text(timerInterval: lesson!.date, countsDown: true)
-          .multilineTextAlignment(.center)
-          .frame(width: 85)
-          .font(.title)
-          .monospacedDigit()
-          .padding(.trailing, CGFloat(24))
-    }
-    .activityBackgroundTint(
-        lesson!.color == "#676767"
-        ? nil
-        : Color(hex: lesson!.color)
-    )
-  }
-}
-
-@available(iOSApplicationExtension 16.1, *)
-struct LiveCardWidget: Widget {
-  var body: some WidgetConfiguration {
-    /// Live Activity Notification
-    ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
-      LockScreenLiveActivityView(context: context)
-    /// Dynamic Island
-    } dynamicIsland: { context in
-      let lesson = LessonData()
-      
-      /// Expanded
-      return DynamicIsland {
-        DynamicIslandExpandedRegion(.leading) {
-          VStack {
-            Spacer()
-            Image(systemName: lesson!.icon)
-              .resizable()
-              .aspectRatio(contentMode: .fit)
-              .frame(width: CGFloat(30), height: CGFloat(30))
-              .padding(.leading, CGFloat(6))
-              .padding(.bottom, CGFloat(6))
-          }
-        }
-        DynamicIslandExpandedRegion(.center) {
-          VStack(alignment: .leading) {
-            Text(lesson!.index + lesson!.title)
-              .lineLimit(1)
-              .font(.title3)
-              .bold()
-              
-            Text(lesson!.description)
-              .lineLimit(2)
-              .font(.caption)
-          }
-        }
-        DynamicIslandExpandedRegion(.trailing) {
-          VStack {
-            Spacer()
-            Text(lesson!.subtitle)
-              .lineLimit(1)
-              .font(.subheadline)
-            Spacer()
-          }
-        }
-
-      /// Compact
-      } compactLeading: {
-        Label {
-          Text(lesson!.title)
-        } icon: {
-          Image(systemName: lesson!.icon)
-        }
-        .font(.caption2)
-      } compactTrailing: {
-          Text(timerInterval: lesson!.date, countsDown: true)
-            .multilineTextAlignment(.center)
-            .frame(width: 40)
-            .font(.caption2)
-
-      /// Collapsed
-      } minimal: {
-        VStack(alignment: .center) {
-          Image(systemName: lesson!.icon)
-            .resizable()
-            .aspectRatio(contentMode: .fit)
-            .frame(width: CGFloat(12), height: CGFloat(12))
-
-          Text(timerInterval: lesson!.date, countsDown: true)
-            .multilineTextAlignment(.center)
-            .monospacedDigit()
-            .font(.system(size: CGFloat(10)))
-        }
-      }
-      .keylineTint(
-        lesson!.color == "#676767"
-        ? nil
-        : Color(hex: lesson!.color)
-      )
-    }
-  }
-}
+import ActivityKit
+import WidgetKit
+import SwiftUI
+
+@main
+struct Widgets: WidgetBundle {
+  var body: some Widget {
+    if #available(iOS 16.1, *) {
+      LiveCardWidget()
+    }
+  }
+}
+
+// Color Converter
+extension Color {
+    init(hex: String, alpha: Double = 1.0) {
+        var hexValue = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
+
+        if hexValue.hasPrefix("#") {
+            hexValue.remove(at: hexValue.startIndex)
+        }
+
+        var rgbValue: UInt64 = 0
+        Scanner(string: hexValue).scanHexInt64(&rgbValue)
+
+        let red = Double((rgbValue & 0xFF0000) >> 16) / 255.0
+        let green = Double((rgbValue & 0x00FF00) >> 8) / 255.0
+        let blue = Double(rgbValue & 0x0000FF) / 255.0
+
+        self.init(
+            .sRGB,
+            red: red,
+            green: green,
+            blue: blue,
+            opacity: alpha
+        )
+    }
+}
+
+
+// We need to redefined live activities pipe
+struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable {
+  public struct ContentState: Codable, Hashable { }
+  
+  var id = UUID()
+}
+
+struct LockScreenLiveActivityView: View {
+  let context: ActivityViewContext<LiveActivitiesAppAttributes>
+
+  let lesson = LessonData()
+
+  var body: some View {
+    HStack(alignment: .center) {
+      Image(systemName: lesson!.icon)
+        .resizable()
+        .aspectRatio(contentMode: .fit)
+        .frame(width: CGFloat(30), height: CGFloat(30))
+        .padding(.leading, CGFloat(24))
+
+      VStack(alignment: .leading) {
+        HStack(alignment: .center) {
+          Text(lesson!.index + lesson!.title)
+            .font(.title3)
+            .bold()
+
+          Text(lesson!.subtitle)
+            .font(.subheadline)
+            .padding(.trailing, 12)
+        }
+        
+        if (lesson!.description != "") {
+          Text(lesson!.description)
+            .font(.subheadline)
+        }
+
+        HStack {
+          Image(systemName: "arrow.right")
+            .resizable()
+            .aspectRatio(contentMode: .fit)
+            .frame(width: CGFloat(8), height: CGFloat(8))
+          Text(lesson!.nextSubject)
+            .font(.caption)
+          Text(lesson!.nextRoom)
+            .font(.caption2)
+        }
+      }.padding(15)
+
+      Spacer()
+      
+      Text(timerInterval: lesson!.date, countsDown: true)
+          .multilineTextAlignment(.center)
+          .frame(width: 85)
+          .font(.title)
+          .monospacedDigit()
+          .padding(.trailing, CGFloat(24))
+    }
+    .activityBackgroundTint(
+        lesson!.color == "#676767"
+        ? nil
+        : Color(hex: lesson!.color)
+    )
+  }
+}
+
+@available(iOSApplicationExtension 16.1, *)
+struct LiveCardWidget: Widget {
+  var body: some WidgetConfiguration {
+    /// Live Activity Notification
+    ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
+      LockScreenLiveActivityView(context: context)
+    /// Dynamic Island
+    } dynamicIsland: { context in
+      let lesson = LessonData()
+      
+      /// Expanded
+      return DynamicIsland {
+        DynamicIslandExpandedRegion(.leading) {
+          VStack {
+            Spacer()
+            Image(systemName: lesson!.icon)
+              .resizable()
+              .aspectRatio(contentMode: .fit)
+              .frame(width: CGFloat(30), height: CGFloat(30))
+              .padding(.leading, CGFloat(6))
+              .padding(.bottom, CGFloat(6))
+          }
+        }
+        DynamicIslandExpandedRegion(.center) {
+          VStack(alignment: .leading) {
+            Text(lesson!.index + lesson!.title)
+              .lineLimit(1)
+              .font(.title3)
+              .bold()
+              
+            Text(lesson!.description)
+              .lineLimit(2)
+              .font(.caption)
+          }
+        }
+        DynamicIslandExpandedRegion(.trailing) {
+          VStack {
+            Spacer()
+            Text(lesson!.subtitle)
+              .lineLimit(1)
+              .font(.subheadline)
+            Spacer()
+          }
+        }
+
+      /// Compact
+      } compactLeading: {
+        Label {
+          Text(lesson!.title)
+        } icon: {
+          Image(systemName: lesson!.icon)
+        }
+        .font(.caption2)
+      } compactTrailing: {
+          Text(timerInterval: lesson!.date, countsDown: true)
+            .multilineTextAlignment(.center)
+            .frame(width: 40)
+            .font(.caption2)
+
+      /// Collapsed
+      } minimal: {
+        VStack(alignment: .center) {
+          Image(systemName: lesson!.icon)
+            .resizable()
+            .aspectRatio(contentMode: .fit)
+            .frame(width: CGFloat(12), height: CGFloat(12))
+
+          Text(timerInterval: lesson!.date, countsDown: true)
+            .multilineTextAlignment(.center)
+            .monospacedDigit()
+            .font(.system(size: CGFloat(10)))
+        }
+      }
+      .keylineTint(
+        lesson!.color == "#676767"
+        ? nil
+        : Color(hex: lesson!.color)
+      )
+    }
+  }
+}
diff --git a/filcnaplo/lib/api/client.dart b/refilc/lib/api/client.dart
similarity index 90%
rename from filcnaplo/lib/api/client.dart
rename to refilc/lib/api/client.dart
index bf290be..99abda5 100644
--- a/filcnaplo/lib/api/client.dart
+++ b/refilc/lib/api/client.dart
@@ -1,251 +1,251 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:developer';
-
-import 'package:filcnaplo/models/ad.dart';
-import 'package:filcnaplo/models/config.dart';
-import 'package:filcnaplo/models/news.dart';
-import 'package:filcnaplo/models/release.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/shared_theme.dart';
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:filcnaplo_kreta_api/models/school.dart';
-import 'package:flutter/foundation.dart';
-import 'package:http/http.dart' as http;
-import 'package:connectivity_plus/connectivity_plus.dart';
-
-class FilcAPI {
-  // API base
-  static const baseUrl = "https://api.refilc.hu";
-
-  // Public API
-  static const schoolList = "$baseUrl/v1/public/school-list";
-  static const news = "$baseUrl/v1/public/news";
-  static const supporters = "$baseUrl/v1/public/supporters";
-
-  // Private API
-  static const ads = "$baseUrl/v1/private/ads";
-  static const config = "$baseUrl/v1/private/config";
-  static const reportApi = "$baseUrl/v1/private/crash-report";
-  static const premiumApi = "https://api.filcnaplo.hu/premium/activate";
-  // static const premiumScopesApi = "https://api.filcnaplo.hu/premium/scopes";
-
-  // Updates
-  static const repo = "refilc/naplo";
-  static const releases = "https://api.github.com/repos/$repo/releases";
-
-  // Share API
-  static const themeShare = "$baseUrl/v2/shared/theme/add";
-  static const themeGet = "$baseUrl/v2/shared/theme/get";
-  static const allThemes = "$themeGet/all";
-  static const themeByID = "$themeGet/";
-
-  static Future<bool> checkConnectivity() async =>
-      (await Connectivity().checkConnectivity()) != ConnectivityResult.none;
-
-  static Future<List<School>?> getSchools() async {
-    try {
-      http.Response res = await http.get(Uri.parse(schoolList));
-
-      if (res.statusCode == 200) {
-        List<School> schools = (jsonDecode(res.body) as List)
-            .cast<Map>()
-            .map((json) => School.fromJson(json))
-            .toList();
-        schools.add(School(
-          city: "Tiszabura",
-          instituteCode: "supporttest-reni-tiszabura-teszt01",
-          name: "FILC Éles Reni tiszabura-teszt",
-        ));
-        return schools;
-      } else {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.getSchools: $error $stacktrace");
-    }
-    return null;
-  }
-
-  static Future<Config?> getConfig(SettingsProvider settings) async {
-    final userAgent = SettingsProvider.defaultSettings().config.userAgent;
-
-    Map<String, String> headers = {
-      "x-filc-id": settings.xFilcId,
-      "user-agent": userAgent,
-    };
-
-    log("[CONFIG] x-filc-id: \"${settings.xFilcId}\"");
-    log("[CONFIG] user-agent: \"$userAgent\"");
-
-    try {
-      http.Response res = await http.get(Uri.parse(config), headers: headers);
-
-      if (res.statusCode == 200) {
-        if (kDebugMode) {
-          print(jsonDecode(res.body));
-        }
-        return Config.fromJson(jsonDecode(res.body));
-      } else if (res.statusCode == 429) {
-        res = await http.get(Uri.parse(config));
-        if (res.statusCode == 200) return Config.fromJson(jsonDecode(res.body));
-      }
-      throw "HTTP ${res.statusCode}: ${res.body}";
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.getConfig: $error $stacktrace");
-    }
-    return null;
-  }
-
-  static Future<List<News>?> getNews() async {
-    try {
-      http.Response res = await http.get(Uri.parse(news));
-
-      if (res.statusCode == 200) {
-        return (jsonDecode(res.body) as List)
-            .cast<Map>()
-            .map((e) => News.fromJson(e))
-            .toList();
-      } else {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.getNews: $error $stacktrace");
-    }
-    return null;
-  }
-
-  static Future<Supporters?> getSupporters() async {
-    try {
-      http.Response res = await http.get(Uri.parse(supporters));
-
-      if (res.statusCode == 200) {
-        return Supporters.fromJson(jsonDecode(res.body));
-      } else {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.getSupporters: $error $stacktrace");
-    }
-    return null;
-  }
-
-  static Future<List<Ad>?> getAds() async {
-    try {
-      http.Response res = await http.get(Uri.parse(ads));
-
-      if (res.statusCode == 200) {
-        return (jsonDecode(res.body) as List)
-            .cast<Map>()
-            .map((e) => Ad.fromJson(e))
-            .toList();
-      } else {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.getAds: $error $stacktrace");
-    }
-    return null;
-  }
-
-  static Future<List<Release>?> getReleases() async {
-    try {
-      http.Response res = await http.get(Uri.parse(releases));
-
-      if (res.statusCode == 200) {
-        return (jsonDecode(res.body) as List)
-            .cast<Map>()
-            .map((e) => Release.fromJson(e))
-            .toList();
-      } else {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.getReleases: $error $stacktrace");
-    }
-    return null;
-  }
-
-  static Future<http.StreamedResponse?> downloadRelease(
-      ReleaseDownload release) {
-    try {
-      var client = http.Client();
-      var request = http.Request('GET', Uri.parse(release.url));
-      return client.send(request);
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.downloadRelease: $error $stacktrace");
-      return Future.value(null);
-    }
-  }
-
-  static Future<void> sendReport(ErrorReport report) async {
-    try {
-      http.Response res = await http.post(Uri.parse(reportApi), body: {
-        "os": report.os,
-        "version": report.version,
-        "error": report.error,
-        "stack_trace": report.stack,
-      });
-
-      if (res.statusCode != 200) {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.sendReport: $error $stacktrace");
-    }
-  }
-
-  // sharing
-  static Future<void> addSharedTheme(SharedTheme theme) async {
-    try {
-      theme.json.remove('json');
-      theme.json['is_public'] = theme.isPublic.toString();
-      theme.json['background_color'] = theme.backgroundColor.value.toString();
-      theme.json['panels_color'] = theme.panelsColor.value.toString();
-      theme.json['accent_color'] = theme.accentColor.value.toString();
-
-      http.Response res = await http.post(
-        Uri.parse(themeShare),
-        body: theme.json,
-        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
-      );
-
-      if (res.statusCode != 201) {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-
-      log('Shared theme successfully with ID: ${theme.id}');
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
-    }
-  }
-
-  static Future<Map?> getSharedTheme(String id) async {
-    try {
-      http.Response res = await http.get(Uri.parse(themeByID + id));
-
-      if (res.statusCode == 200) {
-        return (jsonDecode(res.body) as Map);
-      } else {
-        throw "HTTP ${res.statusCode}: ${res.body}";
-      }
-    } on Exception catch (error, stacktrace) {
-      log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
-    }
-    return null;
-  }
-}
-
-class ErrorReport {
-  String stack;
-  String os;
-  String version;
-  String error;
-
-  ErrorReport({
-    required this.stack,
-    required this.os,
-    required this.version,
-    required this.error,
-  });
-}
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+
+import 'package:refilc/models/ad.dart';
+import 'package:refilc/models/config.dart';
+import 'package:refilc/models/news.dart';
+import 'package:refilc/models/release.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/shared_theme.dart';
+import 'package:refilc/models/supporter.dart';
+import 'package:refilc_kreta_api/models/school.dart';
+import 'package:flutter/foundation.dart';
+import 'package:http/http.dart' as http;
+import 'package:connectivity_plus/connectivity_plus.dart';
+
+class FilcAPI {
+  // API base
+  static const baseUrl = "https://api.refilc.hu";
+
+  // Public API
+  static const schoolList = "$baseUrl/v1/public/school-list";
+  static const news = "$baseUrl/v1/public/news";
+  static const supporters = "$baseUrl/v1/public/supporters";
+
+  // Private API
+  static const ads = "$baseUrl/v1/private/ads";
+  static const config = "$baseUrl/v1/private/config";
+  static const reportApi = "$baseUrl/v1/private/crash-report";
+  static const premiumApi = "https://api.refilc.hu/premium/activate";
+  // static const premiumScopesApi = "https://api.refilc.hu/premium/scopes";
+
+  // Updates
+  static const repo = "refilc/naplo";
+  static const releases = "https://api.github.com/repos/$repo/releases";
+
+  // Share API
+  static const themeShare = "$baseUrl/v2/shared/theme/add";
+  static const themeGet = "$baseUrl/v2/shared/theme/get";
+  static const allThemes = "$themeGet/all";
+  static const themeByID = "$themeGet/";
+
+  static Future<bool> checkConnectivity() async =>
+      (await Connectivity().checkConnectivity()) != ConnectivityResult.none;
+
+  static Future<List<School>?> getSchools() async {
+    try {
+      http.Response res = await http.get(Uri.parse(schoolList));
+
+      if (res.statusCode == 200) {
+        List<School> schools = (jsonDecode(res.body) as List)
+            .cast<Map>()
+            .map((json) => School.fromJson(json))
+            .toList();
+        schools.add(School(
+          city: "Tiszabura",
+          instituteCode: "supporttest-reni-tiszabura-teszt01",
+          name: "FILC Éles Reni tiszabura-teszt",
+        ));
+        return schools;
+      } else {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.getSchools: $error $stacktrace");
+    }
+    return null;
+  }
+
+  static Future<Config?> getConfig(SettingsProvider settings) async {
+    final userAgent = SettingsProvider.defaultSettings().config.userAgent;
+
+    Map<String, String> headers = {
+      "x-filc-id": settings.xFilcId,
+      "user-agent": userAgent,
+    };
+
+    log("[CONFIG] x-filc-id: \"${settings.xFilcId}\"");
+    log("[CONFIG] user-agent: \"$userAgent\"");
+
+    try {
+      http.Response res = await http.get(Uri.parse(config), headers: headers);
+
+      if (res.statusCode == 200) {
+        if (kDebugMode) {
+          print(jsonDecode(res.body));
+        }
+        return Config.fromJson(jsonDecode(res.body));
+      } else if (res.statusCode == 429) {
+        res = await http.get(Uri.parse(config));
+        if (res.statusCode == 200) return Config.fromJson(jsonDecode(res.body));
+      }
+      throw "HTTP ${res.statusCode}: ${res.body}";
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.getConfig: $error $stacktrace");
+    }
+    return null;
+  }
+
+  static Future<List<News>?> getNews() async {
+    try {
+      http.Response res = await http.get(Uri.parse(news));
+
+      if (res.statusCode == 200) {
+        return (jsonDecode(res.body) as List)
+            .cast<Map>()
+            .map((e) => News.fromJson(e))
+            .toList();
+      } else {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.getNews: $error $stacktrace");
+    }
+    return null;
+  }
+
+  static Future<Supporters?> getSupporters() async {
+    try {
+      http.Response res = await http.get(Uri.parse(supporters));
+
+      if (res.statusCode == 200) {
+        return Supporters.fromJson(jsonDecode(res.body));
+      } else {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.getSupporters: $error $stacktrace");
+    }
+    return null;
+  }
+
+  static Future<List<Ad>?> getAds() async {
+    try {
+      http.Response res = await http.get(Uri.parse(ads));
+
+      if (res.statusCode == 200) {
+        return (jsonDecode(res.body) as List)
+            .cast<Map>()
+            .map((e) => Ad.fromJson(e))
+            .toList();
+      } else {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.getAds: $error $stacktrace");
+    }
+    return null;
+  }
+
+  static Future<List<Release>?> getReleases() async {
+    try {
+      http.Response res = await http.get(Uri.parse(releases));
+
+      if (res.statusCode == 200) {
+        return (jsonDecode(res.body) as List)
+            .cast<Map>()
+            .map((e) => Release.fromJson(e))
+            .toList();
+      } else {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.getReleases: $error $stacktrace");
+    }
+    return null;
+  }
+
+  static Future<http.StreamedResponse?> downloadRelease(
+      ReleaseDownload release) {
+    try {
+      var client = http.Client();
+      var request = http.Request('GET', Uri.parse(release.url));
+      return client.send(request);
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.downloadRelease: $error $stacktrace");
+      return Future.value(null);
+    }
+  }
+
+  static Future<void> sendReport(ErrorReport report) async {
+    try {
+      http.Response res = await http.post(Uri.parse(reportApi), body: {
+        "os": report.os,
+        "version": report.version,
+        "error": report.error,
+        "stack_trace": report.stack,
+      });
+
+      if (res.statusCode != 200) {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.sendReport: $error $stacktrace");
+    }
+  }
+
+  // sharing
+  static Future<void> addSharedTheme(SharedTheme theme) async {
+    try {
+      theme.json.remove('json');
+      theme.json['is_public'] = theme.isPublic.toString();
+      theme.json['background_color'] = theme.backgroundColor.value.toString();
+      theme.json['panels_color'] = theme.panelsColor.value.toString();
+      theme.json['accent_color'] = theme.accentColor.value.toString();
+
+      http.Response res = await http.post(
+        Uri.parse(themeShare),
+        body: theme.json,
+        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
+      );
+
+      if (res.statusCode != 201) {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+
+      log('Shared theme successfully with ID: ${theme.id}');
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
+    }
+  }
+
+  static Future<Map?> getSharedTheme(String id) async {
+    try {
+      http.Response res = await http.get(Uri.parse(themeByID + id));
+
+      if (res.statusCode == 200) {
+        return (jsonDecode(res.body) as Map);
+      } else {
+        throw "HTTP ${res.statusCode}: ${res.body}";
+      }
+    } on Exception catch (error, stacktrace) {
+      log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
+    }
+    return null;
+  }
+}
+
+class ErrorReport {
+  String stack;
+  String os;
+  String version;
+  String error;
+
+  ErrorReport({
+    required this.stack,
+    required this.os,
+    required this.version,
+    required this.error,
+  });
+}
diff --git a/filcnaplo/lib/api/login.dart b/refilc/lib/api/login.dart
similarity index 76%
rename from filcnaplo/lib/api/login.dart
rename to refilc/lib/api/login.dart
index 4afc7ce..5d45097 100644
--- a/filcnaplo/lib/api/login.dart
+++ b/refilc/lib/api/login.dart
@@ -1,133 +1,133 @@
-// ignore_for_file: avoid_print, use_build_context_synchronously
-
-import 'package:filcnaplo/utils/jwt.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/student.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/api/nonce.dart';
-
-enum LoginState {
-  missingFields,
-  invalidGrant,
-  failed,
-  normal,
-  inProgress,
-  success,
-}
-
-Nonce getNonce(String nonce, String username, String instituteCode) {
-  Nonce nonceEncoder = Nonce(
-      key: [98, 97, 83, 115, 120, 79, 119, 108, 85, 49, 106, 77], nonce: nonce);
-  nonceEncoder
-      .encode(instituteCode.toUpperCase() + nonce + username.toUpperCase());
-
-  return nonceEncoder;
-}
-
-Future loginAPI({
-  required String username,
-  required String password,
-  required String instituteCode,
-  required BuildContext context,
-  void Function(User)? onLogin,
-  void Function()? onSuccess,
-}) async {
-  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 {
-          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("ERROR: loginAPI: $error");
-          // maybe check debug mode
-          // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
-          return LoginState.failed;
-        }
-      }
-    }
-  }
-  return LoginState.failed;
-}
+// ignore_for_file: avoid_print, use_build_context_synchronously
+
+import 'package:refilc/utils/jwt.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/student.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/api/nonce.dart';
+
+enum LoginState {
+  missingFields,
+  invalidGrant,
+  failed,
+  normal,
+  inProgress,
+  success,
+}
+
+Nonce getNonce(String nonce, String username, String instituteCode) {
+  Nonce nonceEncoder = Nonce(
+      key: [98, 97, 83, 115, 120, 79, 119, 108, 85, 49, 106, 77], nonce: nonce);
+  nonceEncoder
+      .encode(instituteCode.toUpperCase() + nonce + username.toUpperCase());
+
+  return nonceEncoder;
+}
+
+Future loginAPI({
+  required String username,
+  required String password,
+  required String instituteCode,
+  required BuildContext context,
+  void Function(User)? onLogin,
+  void Function()? onSuccess,
+}) async {
+  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 {
+          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("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/nonce.dart b/refilc/lib/api/nonce.dart
similarity index 96%
rename from filcnaplo/lib/api/nonce.dart
rename to refilc/lib/api/nonce.dart
index 0cc13e6..2a1195b 100644
--- a/filcnaplo/lib/api/nonce.dart
+++ b/refilc/lib/api/nonce.dart
@@ -1,25 +1,25 @@
-import 'dart:convert';
-import 'package:crypto/crypto.dart';
-
-class Nonce {
-  String nonce;
-  List<int> key;
-  String? encoded;
-
-  Nonce({required this.nonce, required this.key});
-
-  Future encode(String message) async {
-    List<int> messageBytes = utf8.encode(message);
-    Hmac hmac = Hmac(sha512, key);
-    Digest digest = hmac.convert(messageBytes);
-    encoded = base64.encode(digest.bytes);
-  }
-
-  Map<String, String> header() {
-    return {
-      "X-Authorizationpolicy-Nonce": nonce,
-      "X-Authorizationpolicy-Key": encoded ?? "",
-      "X-Authorizationpolicy-Version": "v2",
-    };
-  }
-}
+import 'dart:convert';
+import 'package:crypto/crypto.dart';
+
+class Nonce {
+  String nonce;
+  List<int> key;
+  String? encoded;
+
+  Nonce({required this.nonce, required this.key});
+
+  Future encode(String message) async {
+    List<int> messageBytes = utf8.encode(message);
+    Hmac hmac = Hmac(sha512, key);
+    Digest digest = hmac.convert(messageBytes);
+    encoded = base64.encode(digest.bytes);
+  }
+
+  Map<String, String> header() {
+    return {
+      "X-Authorizationpolicy-Nonce": nonce,
+      "X-Authorizationpolicy-Key": encoded ?? "",
+      "X-Authorizationpolicy-Version": "v2",
+    };
+  }
+}
diff --git a/filcnaplo/lib/api/providers/ad_provider.dart b/refilc/lib/api/providers/ad_provider.dart
similarity index 86%
rename from filcnaplo/lib/api/providers/ad_provider.dart
rename to refilc/lib/api/providers/ad_provider.dart
index a479935..dc369d1 100644
--- a/filcnaplo/lib/api/providers/ad_provider.dart
+++ b/refilc/lib/api/providers/ad_provider.dart
@@ -1,5 +1,5 @@
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/models/ad.dart';
+import 'package:refilc/api/client.dart';
+import 'package:refilc/models/ad.dart';
 import 'package:flutter/material.dart';
 
 class AdProvider extends ChangeNotifier {
diff --git a/filcnaplo/lib/api/providers/database_provider.dart b/refilc/lib/api/providers/database_provider.dart
similarity index 84%
rename from filcnaplo/lib/api/providers/database_provider.dart
rename to refilc/lib/api/providers/database_provider.dart
index 37bede3..e242c45 100644
--- a/filcnaplo/lib/api/providers/database_provider.dart
+++ b/refilc/lib/api/providers/database_provider.dart
@@ -1,29 +1,29 @@
-import 'dart:io';
-
-import 'package:filcnaplo/database/query.dart';
-import 'package:filcnaplo/database/store.dart';
-// ignore: depend_on_referenced_packages
-import 'package:sqflite_common_ffi/sqflite_ffi.dart';
-
-class DatabaseProvider {
-  // late Database _database;
-  late DatabaseQuery query;
-  late UserDatabaseQuery userQuery;
-  late DatabaseStore store;
-  late UserDatabaseStore userStore;
-
-  Future<void> init() async {
-    Database db;
-
-    if (Platform.isLinux || Platform.isWindows) {
-      db = await databaseFactoryFfi.openDatabase("app.db");
-    } else {
-      db = await openDatabase("app.db");
-    }
-
-    query = DatabaseQuery(db: db);
-    store = DatabaseStore(db: db);
-    userQuery = UserDatabaseQuery(db: db);
-    userStore = UserDatabaseStore(db: db);
-  }
-}
+import 'dart:io';
+
+import 'package:refilc/database/query.dart';
+import 'package:refilc/database/store.dart';
+// ignore: depend_on_referenced_packages
+import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+
+class DatabaseProvider {
+  // late Database _database;
+  late DatabaseQuery query;
+  late UserDatabaseQuery userQuery;
+  late DatabaseStore store;
+  late UserDatabaseStore userStore;
+
+  Future<void> init() async {
+    Database db;
+
+    if (Platform.isLinux || Platform.isWindows) {
+      db = await databaseFactoryFfi.openDatabase("app.db");
+    } else {
+      db = await openDatabase("app.db");
+    }
+
+    query = DatabaseQuery(db: db);
+    store = DatabaseStore(db: db);
+    userQuery = UserDatabaseQuery(db: db);
+    userStore = UserDatabaseStore(db: db);
+  }
+}
diff --git a/filcnaplo/lib/api/providers/live_card_provider.dart b/refilc/lib/api/providers/live_card_provider.dart
similarity index 92%
rename from filcnaplo/lib/api/providers/live_card_provider.dart
rename to refilc/lib/api/providers/live_card_provider.dart
index 7f126d4..ef372dd 100644
--- a/filcnaplo/lib/api/providers/live_card_provider.dart
+++ b/refilc/lib/api/providers/live_card_provider.dart
@@ -1,294 +1,294 @@
-// ignore_for_file: no_leading_underscores_for_local_identifiers
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:flutter/foundation.dart';
-import 'package:live_activities/live_activities.dart';
-import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card.i18n.dart';
-
-enum LiveCardState {
-  empty,
-  duringLesson,
-  duringBreak,
-  morning,
-  afternoon,
-  night,
-  summary
-}
-
-class LiveCardProvider extends ChangeNotifier {
-  Lesson? currentLesson;
-  Lesson? nextLesson;
-  Lesson? prevLesson;
-  List<Lesson>? nextLessons;
-
-  LiveCardState currentState = LiveCardState.empty;
-  late Timer _timer;
-  late final TimetableProvider _timetable;
-  late final SettingsProvider _settings;
-
-  late Duration _delay;
-
-  final _liveActivitiesPlugin = LiveActivities();
-  String? _latestActivityId;
-  Map<String, String> _lastActivity = {};
-
-  bool _hasCheckedTimetable = false;
-
-  LiveCardProvider({
-    required TimetableProvider timetable,
-    required SettingsProvider settings,
-  })  : _timetable = timetable,
-        _settings = settings {
-    if (Platform.isIOS) {
-      _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
-        // Console log
-        if (kDebugMode) {
-          print("Live card enabled: $value");
-        }
-
-        if (value) {
-          _liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
-
-          _liveActivitiesPlugin.getAllActivitiesIds().then((value) {
-            _latestActivityId = value.isNotEmpty ? value.first : null;
-          });
-        }
-      });
-
-      _timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
-      _delay = settings.bellDelayEnabled
-          ? Duration(seconds: settings.bellDelay)
-          : Duration.zero;
-      update();
-    }
-  }
-
-  @override
-  void dispose() {
-    _timer.cancel();
-    if (Platform.isIOS) {
-      _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
-        if (value) {
-          if (_latestActivityId != null) {
-            _liveActivitiesPlugin.endActivity(_latestActivityId!);
-          }
-        }
-      });
-    }
-    super.dispose();
-  }
-
-  // Debugging
-  static DateTime _now() {
-    // return DateTime(2023, 8, 31, 8, 0);
-    return DateTime.now();
-  }
-
-  String getFloorDifference() {
-    final prevFloor = prevLesson!.getFloor();
-    final nextFloor = nextLesson!.getFloor();
-    if (prevFloor == null || nextFloor == null || prevFloor == nextFloor) {
-      return "to room";
-    }
-    if (nextFloor == 0) {
-      return "ground floor";
-    }
-    if (nextFloor > prevFloor) {
-      return "up floor";
-    } else {
-      return "down floor";
-    }
-  }
-
-  Map<String, String> toMap() {
-    switch (currentState) {
-      case LiveCardState.duringLesson:
-        return {
-          "color":
-              '#${_settings.liveActivityColor.toString().substring(10, 16)}',
-          "icon": currentLesson != null
-              ? SubjectIcon.resolveName(subject: currentLesson?.subject)
-              : "book",
-          "index":
-              currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
-          "title": currentLesson != null
-              ? ShortSubject.resolve(subject: currentLesson?.subject).capital()
-              : "",
-          "subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
-          "description": currentLesson?.description ?? "",
-          "startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
-                  _delay.inMilliseconds)
-              .toString(),
-          "endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) -
-                  _delay.inMilliseconds)
-              .toString(),
-          "nextSubject": nextLesson != null
-              ? ShortSubject.resolve(subject: nextLesson?.subject).capital()
-              : "",
-          "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
-        };
-      case LiveCardState.duringBreak:
-        final iconFloorMap = {
-          "to room": "chevron.right.2",
-          "up floor": "arrow.up.right",
-          "down floor": "arrow.down.left",
-          "ground floor": "arrow.down.left",
-        };
-
-        final diff = getFloorDifference();
-
-        return {
-          "color":
-              '#${_settings.liveActivityColor.toString().substring(10, 16)}',
-          "icon": iconFloorMap[diff] ?? "cup.and.saucer",
-          "title": "Szünet",
-          "description": "go $diff".i18n.fill([
-            diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room
-          ]),
-          "startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) -
-                  _delay.inMilliseconds)
-              .toString(),
-          "endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
-                  _delay.inMilliseconds)
-              .toString(),
-          "nextSubject": (nextLesson != null
-                  ? ShortSubject.resolve(subject: nextLesson?.subject)
-                  : "")
-              .capital(),
-          "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
-          "index": "",
-          "subtitle": "",
-        };
-      default:
-        return {};
-    }
-  }
-
-  void update() async {
-    if (Platform.isIOS) {
-      _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
-        if (value) {
-          final cmap = toMap();
-          if (!mapEquals(cmap, _lastActivity)) {
-            _lastActivity = cmap;
-            try {
-              if (_lastActivity.isNotEmpty) {
-                if (_latestActivityId == null) {
-                  _liveActivitiesPlugin
-                      .createActivity(_lastActivity)
-                      .then((value) => _latestActivityId = value);
-                } else {
-                  _liveActivitiesPlugin.updateActivity(
-                      _latestActivityId!, _lastActivity);
-                }
-              } else {
-                if (_latestActivityId != null) {
-                  _liveActivitiesPlugin.endActivity(_latestActivityId!);
-                }
-              }
-            } catch (e) {
-              if (kDebugMode) {
-                print('ERROR: Unable to create or update iOS LiveCard!');
-              }
-            }
-          }
-        }
-      });
-    }
-
-    List<Lesson> today = _today(_timetable);
-
-    if (today.isEmpty && !_hasCheckedTimetable) {
-      _hasCheckedTimetable = true;
-      await _timetable.fetch(week: Week.current());
-      today = _today(_timetable);
-    }
-
-    _delay = _settings.bellDelayEnabled
-        ? Duration(seconds: _settings.bellDelay)
-        : Duration.zero;
-
-    final now = _now().add(_delay);
-
-    // Filter cancelled lessons #20
-    // Filter label lessons #128
-    today = today
-        .where((lesson) =>
-            lesson.status?.name != "Elmaradt" &&
-            lesson.subject.id != '' &&
-            !lesson.isEmpty)
-        .toList();
-
-    if (today.isNotEmpty) {
-      // sort
-      today.sort((a, b) => a.start.compareTo(b.start));
-
-      final _lesson = today.firstWhere(
-          (l) => l.start.isBefore(now) && l.end.isAfter(now),
-          orElse: () => Lesson.fromJson({}));
-
-      if (_lesson.start.year != 0) {
-        currentLesson = _lesson;
-      } else {
-        currentLesson = null;
-      }
-
-      final _next = today.firstWhere((l) => l.start.isAfter(now),
-          orElse: () => Lesson.fromJson({}));
-      nextLessons = today.where((l) => l.start.isAfter(now)).toList();
-
-      if (_next.start.year != 0) {
-        nextLesson = _next;
-      } else {
-        nextLesson = null;
-      }
-
-      final _prev = today.lastWhere((l) => l.end.isBefore(now),
-          orElse: () => Lesson.fromJson({}));
-
-      if (_prev.start.year != 0) {
-        prevLesson = _prev;
-      } else {
-        prevLesson = null;
-      }
-    }
-
-    if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
-        now.isAfter(DateTime(now.year, DateTime.june, 14))) {
-      currentState = LiveCardState.summary;
-    } else if (currentLesson != null) {
-      currentState = LiveCardState.duringLesson;
-    } else if (nextLesson != null && prevLesson != null) {
-      currentState = LiveCardState.duringBreak;
-    } else if (now.hour >= 12 && now.hour < 20) {
-      currentState = LiveCardState.afternoon;
-    } else if (now.hour >= 20) {
-      currentState = LiveCardState.night;
-    } else if (now.hour >= 5 && now.hour <= 10) {
-      currentState = LiveCardState.morning;
-    } else {
-      currentState = LiveCardState.empty;
-    }
-
-    notifyListeners();
-  }
-
-  bool get show => currentState != LiveCardState.empty;
-
-  Duration get delay => _delay;
-
-  bool _sameDate(DateTime a, DateTime b) =>
-      (a.year == b.year && a.month == b.month && a.day == b.day);
-
-  List<Lesson> _today(TimetableProvider p) => (p.getWeek(Week.current()) ?? [])
-      .where((l) => _sameDate(l.date, _now()))
-      .toList();
-}
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:flutter/foundation.dart';
+import 'package:live_activities/live_activities.dart';
+import 'package:refilc_mobile_ui/pages/home/live_card/live_card.i18n.dart';
+
+enum LiveCardState {
+  empty,
+  duringLesson,
+  duringBreak,
+  morning,
+  afternoon,
+  night,
+  summary
+}
+
+class LiveCardProvider extends ChangeNotifier {
+  Lesson? currentLesson;
+  Lesson? nextLesson;
+  Lesson? prevLesson;
+  List<Lesson>? nextLessons;
+
+  LiveCardState currentState = LiveCardState.empty;
+  late Timer _timer;
+  late final TimetableProvider _timetable;
+  late final SettingsProvider _settings;
+
+  late Duration _delay;
+
+  final _liveActivitiesPlugin = LiveActivities();
+  String? _latestActivityId;
+  Map<String, String> _lastActivity = {};
+
+  bool _hasCheckedTimetable = false;
+
+  LiveCardProvider({
+    required TimetableProvider timetable,
+    required SettingsProvider settings,
+  })  : _timetable = timetable,
+        _settings = settings {
+    if (Platform.isIOS) {
+      _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
+        // Console log
+        if (kDebugMode) {
+          print("Live card enabled: $value");
+        }
+
+        if (value) {
+          _liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
+
+          _liveActivitiesPlugin.getAllActivitiesIds().then((value) {
+            _latestActivityId = value.isNotEmpty ? value.first : null;
+          });
+        }
+      });
+
+      _timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
+      _delay = settings.bellDelayEnabled
+          ? Duration(seconds: settings.bellDelay)
+          : Duration.zero;
+      update();
+    }
+  }
+
+  @override
+  void dispose() {
+    _timer.cancel();
+    if (Platform.isIOS) {
+      _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
+        if (value) {
+          if (_latestActivityId != null) {
+            _liveActivitiesPlugin.endActivity(_latestActivityId!);
+          }
+        }
+      });
+    }
+    super.dispose();
+  }
+
+  // Debugging
+  static DateTime _now() {
+    // return DateTime(2023, 8, 31, 8, 0);
+    return DateTime.now();
+  }
+
+  String getFloorDifference() {
+    final prevFloor = prevLesson!.getFloor();
+    final nextFloor = nextLesson!.getFloor();
+    if (prevFloor == null || nextFloor == null || prevFloor == nextFloor) {
+      return "to room";
+    }
+    if (nextFloor == 0) {
+      return "ground floor";
+    }
+    if (nextFloor > prevFloor) {
+      return "up floor";
+    } else {
+      return "down floor";
+    }
+  }
+
+  Map<String, String> toMap() {
+    switch (currentState) {
+      case LiveCardState.duringLesson:
+        return {
+          "color":
+              '#${_settings.liveActivityColor.toString().substring(10, 16)}',
+          "icon": currentLesson != null
+              ? SubjectIcon.resolveName(subject: currentLesson?.subject)
+              : "book",
+          "index":
+              currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
+          "title": currentLesson != null
+              ? ShortSubject.resolve(subject: currentLesson?.subject).capital()
+              : "",
+          "subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
+          "description": currentLesson?.description ?? "",
+          "startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
+                  _delay.inMilliseconds)
+              .toString(),
+          "endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) -
+                  _delay.inMilliseconds)
+              .toString(),
+          "nextSubject": nextLesson != null
+              ? ShortSubject.resolve(subject: nextLesson?.subject).capital()
+              : "",
+          "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
+        };
+      case LiveCardState.duringBreak:
+        final iconFloorMap = {
+          "to room": "chevron.right.2",
+          "up floor": "arrow.up.right",
+          "down floor": "arrow.down.left",
+          "ground floor": "arrow.down.left",
+        };
+
+        final diff = getFloorDifference();
+
+        return {
+          "color":
+              '#${_settings.liveActivityColor.toString().substring(10, 16)}',
+          "icon": iconFloorMap[diff] ?? "cup.and.saucer",
+          "title": "Szünet",
+          "description": "go $diff".i18n.fill([
+            diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room
+          ]),
+          "startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) -
+                  _delay.inMilliseconds)
+              .toString(),
+          "endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
+                  _delay.inMilliseconds)
+              .toString(),
+          "nextSubject": (nextLesson != null
+                  ? ShortSubject.resolve(subject: nextLesson?.subject)
+                  : "")
+              .capital(),
+          "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
+          "index": "",
+          "subtitle": "",
+        };
+      default:
+        return {};
+    }
+  }
+
+  void update() async {
+    if (Platform.isIOS) {
+      _liveActivitiesPlugin.areActivitiesEnabled().then((value) {
+        if (value) {
+          final cmap = toMap();
+          if (!mapEquals(cmap, _lastActivity)) {
+            _lastActivity = cmap;
+            try {
+              if (_lastActivity.isNotEmpty) {
+                if (_latestActivityId == null) {
+                  _liveActivitiesPlugin
+                      .createActivity(_lastActivity)
+                      .then((value) => _latestActivityId = value);
+                } else {
+                  _liveActivitiesPlugin.updateActivity(
+                      _latestActivityId!, _lastActivity);
+                }
+              } else {
+                if (_latestActivityId != null) {
+                  _liveActivitiesPlugin.endActivity(_latestActivityId!);
+                }
+              }
+            } catch (e) {
+              if (kDebugMode) {
+                print('ERROR: Unable to create or update iOS LiveCard!');
+              }
+            }
+          }
+        }
+      });
+    }
+
+    List<Lesson> today = _today(_timetable);
+
+    if (today.isEmpty && !_hasCheckedTimetable) {
+      _hasCheckedTimetable = true;
+      await _timetable.fetch(week: Week.current());
+      today = _today(_timetable);
+    }
+
+    _delay = _settings.bellDelayEnabled
+        ? Duration(seconds: _settings.bellDelay)
+        : Duration.zero;
+
+    final now = _now().add(_delay);
+
+    // Filter cancelled lessons #20
+    // Filter label lessons #128
+    today = today
+        .where((lesson) =>
+            lesson.status?.name != "Elmaradt" &&
+            lesson.subject.id != '' &&
+            !lesson.isEmpty)
+        .toList();
+
+    if (today.isNotEmpty) {
+      // sort
+      today.sort((a, b) => a.start.compareTo(b.start));
+
+      final _lesson = today.firstWhere(
+          (l) => l.start.isBefore(now) && l.end.isAfter(now),
+          orElse: () => Lesson.fromJson({}));
+
+      if (_lesson.start.year != 0) {
+        currentLesson = _lesson;
+      } else {
+        currentLesson = null;
+      }
+
+      final _next = today.firstWhere((l) => l.start.isAfter(now),
+          orElse: () => Lesson.fromJson({}));
+      nextLessons = today.where((l) => l.start.isAfter(now)).toList();
+
+      if (_next.start.year != 0) {
+        nextLesson = _next;
+      } else {
+        nextLesson = null;
+      }
+
+      final _prev = today.lastWhere((l) => l.end.isBefore(now),
+          orElse: () => Lesson.fromJson({}));
+
+      if (_prev.start.year != 0) {
+        prevLesson = _prev;
+      } else {
+        prevLesson = null;
+      }
+    }
+
+    if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
+        now.isAfter(DateTime(now.year, DateTime.june, 14))) {
+      currentState = LiveCardState.summary;
+    } else if (currentLesson != null) {
+      currentState = LiveCardState.duringLesson;
+    } else if (nextLesson != null && prevLesson != null) {
+      currentState = LiveCardState.duringBreak;
+    } else if (now.hour >= 12 && now.hour < 20) {
+      currentState = LiveCardState.afternoon;
+    } else if (now.hour >= 20) {
+      currentState = LiveCardState.night;
+    } else if (now.hour >= 5 && now.hour <= 10) {
+      currentState = LiveCardState.morning;
+    } else {
+      currentState = LiveCardState.empty;
+    }
+
+    notifyListeners();
+  }
+
+  bool get show => currentState != LiveCardState.empty;
+
+  Duration get delay => _delay;
+
+  bool _sameDate(DateTime a, DateTime b) =>
+      (a.year == b.year && a.month == b.month && a.day == b.day);
+
+  List<Lesson> _today(TimetableProvider p) => (p.getWeek(Week.current()) ?? [])
+      .where((l) => _sameDate(l.date, _now()))
+      .toList();
+}
diff --git a/filcnaplo/lib/api/providers/news_provider.dart b/refilc/lib/api/providers/news_provider.dart
similarity index 90%
rename from filcnaplo/lib/api/providers/news_provider.dart
rename to refilc/lib/api/providers/news_provider.dart
index 45acb1e..927fcd8 100644
--- a/filcnaplo/lib/api/providers/news_provider.dart
+++ b/refilc/lib/api/providers/news_provider.dart
@@ -1,109 +1,109 @@
-// ignore_for_file: use_build_context_synchronously
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/models/news.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class NewsProvider extends ChangeNotifier {
-  // Private
-  late List<News> _news;
-  //late int _state;
-  late int _fresh;
-  bool show = false;
-  late BuildContext _context;
-
-  // Public
-  List<News> get news => _news;
-  int get state => _fresh - 1;
-
-  NewsProvider({
-    List<News> initialNews = const [],
-    required BuildContext context,
-  }) {
-    _news = List.castFrom(initialNews);
-    _context = context;
-  }
-
-  Future<void> restore() async {
-    // Load news state from the database
-    var seen_ = Provider.of<SettingsProvider>(_context, listen: false).seenNews;
-
-    if (seen_.isEmpty) {
-      var news_ = await FilcAPI.getNews();
-      if (news_ != null) {
-        _news = news_;
-        show = true;
-      }
-    }
-
-    //_state = seen_;
-    // Provider.of<SettingsProvider>(_context, listen: false)
-    //     .update(seenNewsId: news_.id);
-  }
-
-  Future<void> fetch() async {
-    var news_ = await FilcAPI.getNews();
-    if (news_ == null) return;
-
-    show = false;
-
-    _news = news_;
-
-    for (var news in news_) {
-      if (news.expireDate.isAfter(DateTime.now()) &&
-          Provider.of<SettingsProvider>(_context, listen: false)
-                  .seenNews
-                  .contains(news.id) ==
-              false) {
-        show = true;
-        Provider.of<SettingsProvider>(_context, listen: false)
-            .update(seenNewsId: news.id);
-
-        notifyListeners();
-      }
-    }
-    // print(news_.length);
-    // print(_state);
-
-    // _news = news_;
-    // _fresh = news_.length - _state;
-
-    // if (_fresh < 0) {
-    //   _state = news_.length;
-    //   Provider.of<SettingsProvider>(_context, listen: false)
-    //       .update(newsState: _state);
-    // }
-
-    // _fresh = max(_fresh, 0);
-
-    // if (_fresh > 0) {
-    //   show = true;
-    //   notifyListeners();
-    // }
-
-    // print(_fresh);
-    // print(_state);
-    // print(show);
-  }
-
-  void lock() => show = false;
-
-  void release() {
-    // if (_fresh == 0) return;
-
-    // _fresh--;
-    // //_state++;
-
-    // // Provider.of<SettingsProvider>(_context, listen: false)
-    // //     .update(seenNewsId: _state);
-
-    // if (_fresh > 0) {
-    //   show = true;
-    // } else {
-    //   show = false;
-    // }
-
-    // notifyListeners();
-  }
-}
+// ignore_for_file: use_build_context_synchronously
+import 'package:refilc/api/client.dart';
+import 'package:refilc/models/news.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class NewsProvider extends ChangeNotifier {
+  // Private
+  late List<News> _news;
+  //late int _state;
+  late int _fresh;
+  bool show = false;
+  late BuildContext _context;
+
+  // Public
+  List<News> get news => _news;
+  int get state => _fresh - 1;
+
+  NewsProvider({
+    List<News> initialNews = const [],
+    required BuildContext context,
+  }) {
+    _news = List.castFrom(initialNews);
+    _context = context;
+  }
+
+  Future<void> restore() async {
+    // Load news state from the database
+    var seen_ = Provider.of<SettingsProvider>(_context, listen: false).seenNews;
+
+    if (seen_.isEmpty) {
+      var news_ = await FilcAPI.getNews();
+      if (news_ != null) {
+        _news = news_;
+        show = true;
+      }
+    }
+
+    //_state = seen_;
+    // Provider.of<SettingsProvider>(_context, listen: false)
+    //     .update(seenNewsId: news_.id);
+  }
+
+  Future<void> fetch() async {
+    var news_ = await FilcAPI.getNews();
+    if (news_ == null) return;
+
+    show = false;
+
+    _news = news_;
+
+    for (var news in news_) {
+      if (news.expireDate.isAfter(DateTime.now()) &&
+          Provider.of<SettingsProvider>(_context, listen: false)
+                  .seenNews
+                  .contains(news.id) ==
+              false) {
+        show = true;
+        Provider.of<SettingsProvider>(_context, listen: false)
+            .update(seenNewsId: news.id);
+
+        notifyListeners();
+      }
+    }
+    // print(news_.length);
+    // print(_state);
+
+    // _news = news_;
+    // _fresh = news_.length - _state;
+
+    // if (_fresh < 0) {
+    //   _state = news_.length;
+    //   Provider.of<SettingsProvider>(_context, listen: false)
+    //       .update(newsState: _state);
+    // }
+
+    // _fresh = max(_fresh, 0);
+
+    // if (_fresh > 0) {
+    //   show = true;
+    //   notifyListeners();
+    // }
+
+    // print(_fresh);
+    // print(_state);
+    // print(show);
+  }
+
+  void lock() => show = false;
+
+  void release() {
+    // if (_fresh == 0) return;
+
+    // _fresh--;
+    // //_state++;
+
+    // // Provider.of<SettingsProvider>(_context, listen: false)
+    // //     .update(seenNewsId: _state);
+
+    // if (_fresh > 0) {
+    //   show = true;
+    // } else {
+    //   show = false;
+    // }
+
+    // notifyListeners();
+  }
+}
diff --git a/filcnaplo/lib/api/providers/status_provider.dart b/refilc/lib/api/providers/status_provider.dart
similarity index 96%
rename from filcnaplo/lib/api/providers/status_provider.dart
rename to refilc/lib/api/providers/status_provider.dart
index 5822366..11a2a3a 100644
--- a/filcnaplo/lib/api/providers/status_provider.dart
+++ b/refilc/lib/api/providers/status_provider.dart
@@ -1,95 +1,95 @@
-import 'package:connectivity_plus/connectivity_plus.dart';
-import 'package:flutter/widgets.dart';
-import 'package:http/http.dart' as http;
-
-enum Status { network, maintenance, syncing, apiError }
-
-class StatusProvider extends ChangeNotifier {
-  final List<Status> _stack = [];
-  double _progress = 0.0;
-  ConnectivityResult _networkType = ConnectivityResult.none;
-  ConnectivityResult get networkType => _networkType;
-
-  StatusProvider() {
-    _handleNetworkChanges();
-    Connectivity().checkConnectivity().then((value) => _networkType = value);
-  }
-
-  Status? getStatus() => _stack.isNotEmpty ? _stack[0] : null;
-  // Status progress from 0.0 to 1.0
-  double get progress => _progress;
-
-  void _handleNetworkChanges() {
-    Connectivity().onConnectivityChanged.listen((event) {
-      _networkType = event;
-      if (event == ConnectivityResult.none) {
-        if (!_stack.contains(Status.network)) {
-          _stack.insert(0, Status.network);
-          notifyListeners();
-        }
-      } else {
-        if (_stack.contains(Status.network)) {
-          _stack.remove(Status.network);
-          notifyListeners();
-        }
-      }
-    });
-  }
-
-  void triggerRequest(http.Response res) {
-    if (res.headers.containsKey("x-maintenance-mode") ||
-        res.statusCode == 503) {
-      if (!_stack.contains(Status.maintenance)) {
-        _stack.insert(0, Status.maintenance);
-        notifyListeners();
-      }
-    } else {
-      if (_stack.contains(Status.maintenance)) {
-        _stack.remove(Status.maintenance);
-        notifyListeners();
-      }
-    }
-
-    if (res.body == "invalid_grant" ||
-        res.body.replaceAll(' ', '') == '' ||
-        res.statusCode == 400) {
-      if (!_stack.contains(Status.apiError)) {
-        _stack.insert(0, Status.apiError);
-        notifyListeners();
-      }
-    } else {
-      if (_stack.contains(Status.apiError) &&
-          res.request?.url.path != '/nonce') {
-        _stack.remove(Status.apiError);
-        notifyListeners();
-      }
-    }
-  }
-
-  void triggerSync({required int current, required int max}) {
-    double prev = _progress;
-
-    if (!_stack.contains(Status.syncing)) {
-      _stack.add(Status.syncing);
-      _progress = 0.0;
-      notifyListeners();
-    }
-
-    if (max == 0) {
-      _progress = 0.0;
-    } else {
-      _progress = current / max;
-    }
-
-    if (_progress == 1.0) {
-      notifyListeners();
-      // Wait for animation
-      Future.delayed(const Duration(milliseconds: 250), () {
-        _stack.remove(Status.syncing);
-        notifyListeners();
-      });
-    } else if (progress != prev) {
-      notifyListeners();
-    }
-  }
-}
+import 'package:connectivity_plus/connectivity_plus.dart';
+import 'package:flutter/widgets.dart';
+import 'package:http/http.dart' as http;
+
+enum Status { network, maintenance, syncing, apiError }
+
+class StatusProvider extends ChangeNotifier {
+  final List<Status> _stack = [];
+  double _progress = 0.0;
+  ConnectivityResult _networkType = ConnectivityResult.none;
+  ConnectivityResult get networkType => _networkType;
+
+  StatusProvider() {
+    _handleNetworkChanges();
+    Connectivity().checkConnectivity().then((value) => _networkType = value);
+  }
+
+  Status? getStatus() => _stack.isNotEmpty ? _stack[0] : null;
+  // Status progress from 0.0 to 1.0
+  double get progress => _progress;
+
+  void _handleNetworkChanges() {
+    Connectivity().onConnectivityChanged.listen((event) {
+      _networkType = event;
+      if (event == ConnectivityResult.none) {
+        if (!_stack.contains(Status.network)) {
+          _stack.insert(0, Status.network);
+          notifyListeners();
+        }
+      } else {
+        if (_stack.contains(Status.network)) {
+          _stack.remove(Status.network);
+          notifyListeners();
+        }
+      }
+    });
+  }
+
+  void triggerRequest(http.Response res) {
+    if (res.headers.containsKey("x-maintenance-mode") ||
+        res.statusCode == 503) {
+      if (!_stack.contains(Status.maintenance)) {
+        _stack.insert(0, Status.maintenance);
+        notifyListeners();
+      }
+    } else {
+      if (_stack.contains(Status.maintenance)) {
+        _stack.remove(Status.maintenance);
+        notifyListeners();
+      }
+    }
+
+    if (res.body == "invalid_grant" ||
+        res.body.replaceAll(' ', '') == '' ||
+        res.statusCode == 400) {
+      if (!_stack.contains(Status.apiError)) {
+        _stack.insert(0, Status.apiError);
+        notifyListeners();
+      }
+    } else {
+      if (_stack.contains(Status.apiError) &&
+          res.request?.url.path != '/nonce') {
+        _stack.remove(Status.apiError);
+        notifyListeners();
+      }
+    }
+  }
+
+  void triggerSync({required int current, required int max}) {
+    double prev = _progress;
+
+    if (!_stack.contains(Status.syncing)) {
+      _stack.add(Status.syncing);
+      _progress = 0.0;
+      notifyListeners();
+    }
+
+    if (max == 0) {
+      _progress = 0.0;
+    } else {
+      _progress = current / max;
+    }
+
+    if (_progress == 1.0) {
+      notifyListeners();
+      // Wait for animation
+      Future.delayed(const Duration(milliseconds: 250), () {
+        _stack.remove(Status.syncing);
+        notifyListeners();
+      });
+    } else if (progress != prev) {
+      notifyListeners();
+    }
+  }
+}
diff --git a/filcnaplo/lib/api/providers/sync.dart b/refilc/lib/api/providers/sync.dart
similarity index 61%
rename from filcnaplo/lib/api/providers/sync.dart
rename to refilc/lib/api/providers/sync.dart
index 42f6277..2743aef 100644
--- a/filcnaplo/lib/api/providers/sync.dart
+++ b/refilc/lib/api/providers/sync.dart
@@ -1,88 +1,94 @@
-// ignore_for_file: use_build_context_synchronously
-
-import 'dart:io';
-
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/student.dart';
-import 'package:filcnaplo_kreta_api/models/week.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter/widgets.dart';
-import 'package:provider/provider.dart';
-import 'package:home_widget/home_widget.dart';
-
-// Mutex
-bool lock = false;
-
-Future<void> syncAll(BuildContext context) {
-  if (lock) return Future.value();
-  // Lock
-  lock = true;
-
-  // ignore: avoid_print
-  print("INFO Syncing all");
-
-  UserProvider user = Provider.of<UserProvider>(context, listen: false);
-  StatusProvider statusProvider = Provider.of<StatusProvider>(context, listen: false);
-
-  List<Future<void>> tasks = [];
-  int taski = 0;
-
-  Future<void> syncStatus(Future<void> future) async {
-    await future.onError((error, stackTrace) => null);
-    taski++;
-    statusProvider.triggerSync(current: taski, max: tasks.length);
-  }
-
-  tasks = [
-    syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
-    syncStatus(Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current())),
-    syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
-    syncStatus(Provider.of<HomeworkProvider>(context, listen: false).fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
-    syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
-    syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
-    syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
-    syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
-
-    // Sync student
-    syncStatus(() async {
-      if (user.user == null) return;
-      Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(user.instituteCode!));
-      if (studentJson == null) return;
-      Student student = Student.fromJson(studentJson);
-
-      user.user?.name = student.name;
-
-      // Store user
-      await Provider.of<DatabaseProvider>(context, listen: false).store.storeUser(user.user!);
-    }()),
-  ];
-
-  Future<bool?> updateWidget() async {
-    try {
-      return HomeWidget.updateWidget(name: 'widget_timetable.WidgetTimetable');
-    } on PlatformException catch (exception) {
-      debugPrint('Error Updating Widget. $exception');
-    }
-    return false;
-  }
-
-  return Future.wait(tasks).then((value) {
-    // Unlock
-    lock = false;
-
-    // Update Widget
-    if (Platform.isAndroid) updateWidget();
-  });
-}
+// ignore_for_file: use_build_context_synchronously
+
+import 'dart:io';
+
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/status_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/student.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:provider/provider.dart';
+import 'package:home_widget/home_widget.dart';
+
+// Mutex
+bool lock = false;
+
+Future<void> syncAll(BuildContext context) {
+  if (lock) return Future.value();
+  // Lock
+  lock = true;
+
+  // ignore: avoid_print
+  print("INFO Syncing all");
+
+  UserProvider user = Provider.of<UserProvider>(context, listen: false);
+  StatusProvider statusProvider =
+      Provider.of<StatusProvider>(context, listen: false);
+
+  List<Future<void>> tasks = [];
+  int taski = 0;
+
+  Future<void> syncStatus(Future<void> future) async {
+    await future.onError((error, stackTrace) => null);
+    taski++;
+    statusProvider.triggerSync(current: taski, max: tasks.length);
+  }
+
+  tasks = [
+    syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
+    syncStatus(Provider.of<TimetableProvider>(context, listen: false)
+        .fetch(week: Week.current())),
+    syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
+    syncStatus(Provider.of<HomeworkProvider>(context, listen: false)
+        .fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
+    syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
+    syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
+    syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
+    syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
+
+    // Sync student
+    syncStatus(() async {
+      if (user.user == null) return;
+      Map? studentJson = await Provider.of<KretaClient>(context, listen: false)
+          .getAPI(KretaAPI.student(user.instituteCode!));
+      if (studentJson == null) return;
+      Student student = Student.fromJson(studentJson);
+
+      user.user?.name = student.name;
+
+      // Store user
+      await Provider.of<DatabaseProvider>(context, listen: false)
+          .store
+          .storeUser(user.user!);
+    }()),
+  ];
+
+  Future<bool?> updateWidget() async {
+    try {
+      return HomeWidget.updateWidget(name: 'widget_timetable.WidgetTimetable');
+    } on PlatformException catch (exception) {
+      debugPrint('Error Updating Widget. $exception');
+    }
+    return false;
+  }
+
+  return Future.wait(tasks).then((value) {
+    // Unlock
+    lock = false;
+
+    // Update Widget
+    if (Platform.isAndroid) updateWidget();
+  });
+}
diff --git a/filcnaplo/lib/api/providers/update_provider.dart b/refilc/lib/api/providers/update_provider.dart
similarity index 91%
rename from filcnaplo/lib/api/providers/update_provider.dart
rename to refilc/lib/api/providers/update_provider.dart
index a942df6..7363c47 100644
--- a/filcnaplo/lib/api/providers/update_provider.dart
+++ b/refilc/lib/api/providers/update_provider.dart
@@ -1,62 +1,62 @@
-import 'dart:io';
-
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/models/release.dart';
-import 'package:flutter/material.dart';
-import 'package:package_info_plus/package_info_plus.dart';
-
-class UpdateProvider extends ChangeNotifier {
-  // Private
-  late List<Release> _releases;
-  bool _available = false;
-  bool get available => _available && _releases.isNotEmpty;
-
-  // Public
-  List<Release> get releases => _releases;
-
-  UpdateProvider({
-    List<Release> initialReleases = const [],
-    required BuildContext context,
-  }) {
-    _releases = List.castFrom(initialReleases);
-  }
-
-  Future<void> fetch() async {
-    late String currentVersion;
-    PackageInfo packageInfo = await PackageInfo.fromPlatform();
-    currentVersion = packageInfo.version;
-
-    if (!Platform.isAndroid) return;
-
-    _releases = await FilcAPI.getReleases() ?? [];
-    _releases.sort((a, b) => -a.version.compareTo(b.version));
-
-    // Check for new releases
-    if (_releases.isNotEmpty) {
-      _available = _releases.first.version
-              .compareTo(Version.fromString(currentVersion)) ==
-          1;
-      // ignore: avoid_print
-      if (_available) print("INFO: New update: ${releases.first.version}");
-      notifyListeners();
-    }
-  }
-
-  Future<Map> installedVersion() async {
-    PackageInfo packageInfo = await PackageInfo.fromPlatform();
-
-    String appName = packageInfo.appName;
-    String packageName = packageInfo.packageName;
-    String version = packageInfo.version;
-    String buildNumber = packageInfo.buildNumber;
-
-    Map<String, String> release = {
-      "app_name": appName,
-      "package_name": packageName,
-      "version": version,
-      "build_number": buildNumber,
-    };
-
-    return release;
-  }
-}
+import 'dart:io';
+
+import 'package:refilc/api/client.dart';
+import 'package:refilc/models/release.dart';
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+class UpdateProvider extends ChangeNotifier {
+  // Private
+  late List<Release> _releases;
+  bool _available = false;
+  bool get available => _available && _releases.isNotEmpty;
+
+  // Public
+  List<Release> get releases => _releases;
+
+  UpdateProvider({
+    List<Release> initialReleases = const [],
+    required BuildContext context,
+  }) {
+    _releases = List.castFrom(initialReleases);
+  }
+
+  Future<void> fetch() async {
+    late String currentVersion;
+    PackageInfo packageInfo = await PackageInfo.fromPlatform();
+    currentVersion = packageInfo.version;
+
+    if (!Platform.isAndroid) return;
+
+    _releases = await FilcAPI.getReleases() ?? [];
+    _releases.sort((a, b) => -a.version.compareTo(b.version));
+
+    // Check for new releases
+    if (_releases.isNotEmpty) {
+      _available = _releases.first.version
+              .compareTo(Version.fromString(currentVersion)) ==
+          1;
+      // ignore: avoid_print
+      if (_available) print("INFO: New update: ${releases.first.version}");
+      notifyListeners();
+    }
+  }
+
+  Future<Map> installedVersion() async {
+    PackageInfo packageInfo = await PackageInfo.fromPlatform();
+
+    String appName = packageInfo.appName;
+    String packageName = packageInfo.packageName;
+    String version = packageInfo.version;
+    String buildNumber = packageInfo.buildNumber;
+
+    Map<String, String> release = {
+      "app_name": appName,
+      "package_name": packageName,
+      "version": version,
+      "build_number": buildNumber,
+    };
+
+    return release;
+  }
+}
diff --git a/filcnaplo/lib/api/providers/user_provider.dart b/refilc/lib/api/providers/user_provider.dart
similarity index 89%
rename from filcnaplo/lib/api/providers/user_provider.dart
rename to refilc/lib/api/providers/user_provider.dart
index 776586f..a71028c 100644
--- a/filcnaplo/lib/api/providers/user_provider.dart
+++ b/refilc/lib/api/providers/user_provider.dart
@@ -1,78 +1,78 @@
-import 'dart:io';
-
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/models/student.dart';
-import 'package:flutter/foundation.dart';
-import 'package:home_widget/home_widget.dart';
-import 'package:flutter/services.dart';
-
-class UserProvider with ChangeNotifier {
-  final Map<String, User> _users = {};
-  String? _selectedUserId;
-  User? get user => _users[_selectedUserId];
-
-  // _user properties
-  String? get instituteCode => user?.instituteCode;
-  String? get id => user?.id;
-  String? get name => user?.name;
-  String? get username => user?.username;
-  String? get password => user?.password;
-  Role? get role => user?.role;
-  Student? get student => user?.student;
-  String? get nickname => user?.nickname;
-  String get picture => user?.picture ?? "";
-  String? get displayName => user?.displayName;
-
-  final SettingsProvider _settings;
-
-  UserProvider({required SettingsProvider settings}) : _settings = settings;
-
-  void setUser(String userId) async {
-    _selectedUserId = userId;
-    await _settings.update(lastAccountId: userId);
-    if (Platform.isAndroid) updateWidget();
-    notifyListeners();
-  }
-
-  Future<bool?> updateWidget() async {
-    try {
-      return HomeWidget.updateWidget(name: 'widget_timetable.WidgetTimetable');
-    } on PlatformException catch (exception) {
-      if (kDebugMode) {
-        print('Error Updating Widget After setUser. $exception');
-      }
-    }
-    return false;
-  }
-
-  void addUser(User user) {
-    _users[user.id] = user;
-    if (kDebugMode) {
-      print("DEBUG: Added User: ${user.id}");
-    }
-  }
-
-  void removeUser(String userId) async {
-    _users.removeWhere((key, value) => key == userId);
-    if (_users.isNotEmpty) {
-      setUser(_users.keys.first);
-    } else {
-      await _settings.update(lastAccountId: "");
-    }
-    if (Platform.isAndroid) updateWidget();
-    notifyListeners();
-  }
-
-  User getUser(String userId) {
-    return _users[userId]!;
-  }
-
-  List<User> getUsers() {
-    return _users.values.toList();
-  }
-
-  void refresh() {
-    notifyListeners();
-  }
-}
+import 'dart:io';
+
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/models/student.dart';
+import 'package:flutter/foundation.dart';
+import 'package:home_widget/home_widget.dart';
+import 'package:flutter/services.dart';
+
+class UserProvider with ChangeNotifier {
+  final Map<String, User> _users = {};
+  String? _selectedUserId;
+  User? get user => _users[_selectedUserId];
+
+  // _user properties
+  String? get instituteCode => user?.instituteCode;
+  String? get id => user?.id;
+  String? get name => user?.name;
+  String? get username => user?.username;
+  String? get password => user?.password;
+  Role? get role => user?.role;
+  Student? get student => user?.student;
+  String? get nickname => user?.nickname;
+  String get picture => user?.picture ?? "";
+  String? get displayName => user?.displayName;
+
+  final SettingsProvider _settings;
+
+  UserProvider({required SettingsProvider settings}) : _settings = settings;
+
+  void setUser(String userId) async {
+    _selectedUserId = userId;
+    await _settings.update(lastAccountId: userId);
+    if (Platform.isAndroid) updateWidget();
+    notifyListeners();
+  }
+
+  Future<bool?> updateWidget() async {
+    try {
+      return HomeWidget.updateWidget(name: 'widget_timetable.WidgetTimetable');
+    } on PlatformException catch (exception) {
+      if (kDebugMode) {
+        print('Error Updating Widget After setUser. $exception');
+      }
+    }
+    return false;
+  }
+
+  void addUser(User user) {
+    _users[user.id] = user;
+    if (kDebugMode) {
+      print("DEBUG: Added User: ${user.id}");
+    }
+  }
+
+  void removeUser(String userId) async {
+    _users.removeWhere((key, value) => key == userId);
+    if (_users.isNotEmpty) {
+      setUser(_users.keys.first);
+    } else {
+      await _settings.update(lastAccountId: "");
+    }
+    if (Platform.isAndroid) updateWidget();
+    notifyListeners();
+  }
+
+  User getUser(String userId) {
+    return _users[userId]!;
+  }
+
+  List<User> getUsers() {
+    return _users.values.toList();
+  }
+
+  void refresh() {
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo/lib/app.dart b/refilc/lib/app.dart
similarity index 77%
rename from filcnaplo/lib/app.dart
rename to refilc/lib/app.dart
index 32ecb6d..dc385fe 100644
--- a/filcnaplo/lib/app.dart
+++ b/refilc/lib/app.dart
@@ -1,282 +1,281 @@
-import 'dart:io';
-import 'dart:math';
-
-import 'package:dynamic_color/dynamic_color.dart';
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/api/providers/ad_provider.dart';
-import 'package:filcnaplo/api/providers/live_card_provider.dart';
-import 'package:filcnaplo/api/providers/news_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'package:filcnaplo/models/config.dart';
-import 'package:filcnaplo/theme/observer.dart';
-import 'package:filcnaplo/theme/theme.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_premium/providers/goal_provider.dart';
-import 'package:filcnaplo_premium/providers/share_provider.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_localizations/flutter_localizations.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:material_color_utilities/palettes/core_palette.dart';
-import 'package:provider/provider.dart';
-
-// Mobile UI
-import 'package:filcnaplo_mobile_ui/common/system_chrome.dart' as mobile;
-import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart' as mobile;
-import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart' as mobile;
-import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart'
-    as mobile;
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart'
-    as mobile;
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart'
-    as mobile;
-
-// Desktop UI
-import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart'
-    as desktop;
-import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart'
-    as desktop;
-import 'package:filcnaplo_desktop_ui/screens/login/login_route.dart' as desktop;
-
-// Providers
-import 'package:filcnaplo/models/settings.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';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
-import 'package:flutter_displaymode/flutter_displaymode.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-
-class App extends StatelessWidget {
-  final SettingsProvider settings;
-  final UserProvider user;
-  final DatabaseProvider database;
-
-  const App(
-      {Key? key,
-      required this.database,
-      required this.settings,
-      required this.user})
-      : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    mobile.setSystemChrome(context);
-
-    // Set high refresh mode #28
-    if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate();
-
-    CorePalette? corePalette;
-
-    final status = StatusProvider();
-    final kreta = KretaClient(user: user, settings: settings, status: status);
-    final timetable =
-        TimetableProvider(user: user, database: database, kreta: kreta);
-    final premium = PremiumProvider(settings: settings);
-
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      FilcAPI.getConfig(settings).then((Config? config) {
-        if (config != null) settings.update(config: config);
-      });
-      premium.activate();
-    });
-
-    return MultiProvider(
-      providers: [
-        // refilc providers
-        ChangeNotifierProvider<PremiumProvider>(create: (_) => premium),
-        ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
-        ChangeNotifierProvider<UserProvider>(create: (_) => user),
-        ChangeNotifierProvider<StatusProvider>(create: (_) => status),
-        Provider<KretaClient>(create: (_) => kreta),
-        Provider<DatabaseProvider>(create: (context) => database),
-        ChangeNotifierProvider<ThemeModeObserver>(
-          create: (context) => ThemeModeObserver(
-            initialTheme: settings.theme,
-          ),
-        ),
-        ChangeNotifierProvider<NewsProvider>(
-          create: (context) => NewsProvider(context: context),
-        ),
-        ChangeNotifierProvider<UpdateProvider>(
-          create: (context) => UpdateProvider(context: context),
-        ),
-        ChangeNotifierProvider<AdProvider>(
-          create: (context) => AdProvider(context: context),
-        ),
-
-        // user data (kreten) providers
-        ChangeNotifierProvider<GradeProvider>(
-          create: (_) => GradeProvider(
-            settings: settings,
-            user: user,
-            database: database,
-            kreta: kreta,
-          ),
-        ),
-        ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
-        ChangeNotifierProvider<ExamProvider>(
-          create: (context) => ExamProvider(context: context),
-        ),
-        ChangeNotifierProvider<HomeworkProvider>(
-          create: (context) => HomeworkProvider(
-            context: context,
-            database: database,
-          ),
-        ),
-        ChangeNotifierProvider<MessageProvider>(
-          create: (context) => MessageProvider(context: context),
-        ),
-        ChangeNotifierProvider<NoteProvider>(
-          create: (context) => NoteProvider(context: context),
-        ),
-        ChangeNotifierProvider<EventProvider>(
-          create: (context) => EventProvider(context: context),
-        ),
-        ChangeNotifierProvider<AbsenceProvider>(
-          create: (context) => AbsenceProvider(context: context),
-        ),
-
-        // other providers
-        ChangeNotifierProvider<GradeCalculatorProvider>(
-          create: (_) => GradeCalculatorProvider(
-            settings: settings,
-            user: user,
-            database: database,
-            kreta: kreta,
-          ),
-        ),
-        ChangeNotifierProvider<LiveCardProvider>(
-          create: (context) => LiveCardProvider(
-            timetable: timetable,
-            settings: settings,
-          ),
-        ),
-        ChangeNotifierProvider<GoalProvider>(
-          create: (context) => GoalProvider(
-            database: database,
-            user: user,
-          ),
-        ),
-        ChangeNotifierProvider<ShareProvider>(
-          create: (context) => ShareProvider(
-            user: user,
-          ),
-        ),
-      ],
-      child: Consumer<ThemeModeObserver>(
-        builder: (context, themeMode, child) {
-          return FutureBuilder<CorePalette?>(
-            future: DynamicColorPlugin.getCorePalette(),
-            builder: (context, snapshot) {
-              corePalette = snapshot.data;
-              return MaterialApp(
-                builder: (context, child) {
-                  // Limit font size scaling to 1.0
-                  double textScaleFactor =
-                      min(MediaQuery.of(context).textScaleFactor, 1.0);
-
-                  return I18n(
-                    initialLocale: Locale(
-                        settings.language, settings.language.toUpperCase()),
-                    child: MediaQuery(
-                      data: MediaQuery.of(context)
-                          .copyWith(textScaleFactor: textScaleFactor),
-                      child: child ?? Container(),
-                    ),
-                  );
-                },
-                title: "reFilc",
-                debugShowCheckedModeBanner: false,
-                theme: AppTheme.lightTheme(context, palette: corePalette),
-                darkTheme: AppTheme.darkTheme(context, palette: corePalette),
-                themeMode: themeMode.themeMode,
-                localizationsDelegates: const [
-                  GlobalMaterialLocalizations.delegate,
-                  GlobalWidgetsLocalizations.delegate,
-                  GlobalCupertinoLocalizations.delegate,
-                ],
-                supportedLocales: const [
-                  Locale('en', 'EN'),
-                  Locale('hu', 'HU'),
-                  Locale('de', 'DE'),
-                ],
-                localeListResolutionCallback: (locales, supported) {
-                  Locale locale = const Locale('hu', 'HU');
-
-                  for (var loc in locales ?? []) {
-                    if (supported.contains(loc)) {
-                      locale = loc;
-                      break;
-                    }
-                  }
-
-                  return locale;
-                },
-                onGenerateRoute: (settings) => rootNavigator(settings),
-                initialRoute:
-                    user.getUsers().isNotEmpty ? "navigation" : "login",
-              );
-            },
-          );
-        },
-      ),
-    );
-  }
-
-  Route? rootNavigator(RouteSettings route) {
-    if (kIsWeb) {
-      switch (route.name) {
-        case "login_back":
-          return CupertinoPageRoute(
-              builder: (context) => const desktop.LoginScreen(back: true));
-        case "login":
-          return _rootRoute(const desktop.LoginScreen());
-        case "navigation":
-          return _rootRoute(const desktop.NavigationScreen());
-        case "login_to_navigation":
-          return desktop.loginRoute(const desktop.NavigationScreen());
-      }
-    } else if (Platform.isAndroid || Platform.isIOS) {
-      switch (route.name) {
-        case "login_back":
-          return CupertinoPageRoute(
-              builder: (context) => const mobile.LoginScreen(back: true));
-        case "login":
-          return _rootRoute(const mobile.LoginScreen());
-        case "navigation":
-          return _rootRoute(const mobile.NavigationScreen());
-        case "login_to_navigation":
-          return mobile.loginRoute(const mobile.NavigationScreen());
-        case "settings":
-          return mobile.settingsRoute(const mobile.SettingsScreen());
-      }
-    } else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
-      switch (route.name) {
-        case "login_back":
-          return CupertinoPageRoute(
-              builder: (context) => const desktop.LoginScreen(back: true));
-        case "login":
-          return _rootRoute(const desktop.LoginScreen());
-        case "navigation":
-          return _rootRoute(const desktop.NavigationScreen());
-        case "login_to_navigation":
-          return desktop.loginRoute(const desktop.NavigationScreen());
-      }
-    }
-    return null;
-  }
-
-  Route _rootRoute(Widget widget) {
-    return PageRouteBuilder(pageBuilder: (context, _, __) => widget);
-  }
-}
+import 'dart:io';
+import 'dart:math';
+
+import 'package:dynamic_color/dynamic_color.dart';
+import 'package:refilc/api/client.dart';
+import 'package:refilc/api/providers/ad_provider.dart';
+import 'package:refilc/api/providers/live_card_provider.dart';
+import 'package:refilc/api/providers/news_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/status_provider.dart';
+import 'package:refilc/models/config.dart';
+import 'package:refilc/theme/observer.dart';
+import 'package:refilc/theme/theme.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_premium/providers/goal_provider.dart';
+import 'package:refilc_premium/providers/share_provider.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:material_color_utilities/palettes/core_palette.dart';
+import 'package:provider/provider.dart';
+
+// Mobile UI
+import 'package:refilc_mobile_ui/common/system_chrome.dart' as mobile;
+import 'package:refilc_mobile_ui/screens/login/login_route.dart' as mobile;
+import 'package:refilc_mobile_ui/screens/login/login_screen.dart' as mobile;
+import 'package:refilc_mobile_ui/screens/navigation/navigation_screen.dart'
+    as mobile;
+import 'package:refilc_mobile_ui/screens/settings/settings_route.dart'
+    as mobile;
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.dart'
+    as mobile;
+
+// Desktop UI
+import 'package:refilc_desktop_ui/screens/navigation/navigation_screen.dart'
+    as desktop;
+import 'package:refilc_desktop_ui/screens/login/login_screen.dart' as desktop;
+import 'package:refilc_desktop_ui/screens/login/login_route.dart' as desktop;
+
+// Providers
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
+import 'package:flutter_displaymode/flutter_displaymode.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+
+class App extends StatelessWidget {
+  final SettingsProvider settings;
+  final UserProvider user;
+  final DatabaseProvider database;
+
+  const App(
+      {Key? key,
+      required this.database,
+      required this.settings,
+      required this.user})
+      : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    mobile.setSystemChrome(context);
+
+    // Set high refresh mode #28
+    if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate();
+
+    CorePalette? corePalette;
+
+    final status = StatusProvider();
+    final kreta = KretaClient(user: user, settings: settings, status: status);
+    final timetable =
+        TimetableProvider(user: user, database: database, kreta: kreta);
+    final premium = PremiumProvider(settings: settings);
+
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      FilcAPI.getConfig(settings).then((Config? config) {
+        if (config != null) settings.update(config: config);
+      });
+      premium.activate();
+    });
+
+    return MultiProvider(
+      providers: [
+        // refilc providers
+        ChangeNotifierProvider<PremiumProvider>(create: (_) => premium),
+        ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
+        ChangeNotifierProvider<UserProvider>(create: (_) => user),
+        ChangeNotifierProvider<StatusProvider>(create: (_) => status),
+        Provider<KretaClient>(create: (_) => kreta),
+        Provider<DatabaseProvider>(create: (context) => database),
+        ChangeNotifierProvider<ThemeModeObserver>(
+          create: (context) => ThemeModeObserver(
+            initialTheme: settings.theme,
+          ),
+        ),
+        ChangeNotifierProvider<NewsProvider>(
+          create: (context) => NewsProvider(context: context),
+        ),
+        ChangeNotifierProvider<UpdateProvider>(
+          create: (context) => UpdateProvider(context: context),
+        ),
+        ChangeNotifierProvider<AdProvider>(
+          create: (context) => AdProvider(context: context),
+        ),
+
+        // user data (kreten) providers
+        ChangeNotifierProvider<GradeProvider>(
+          create: (_) => GradeProvider(
+            settings: settings,
+            user: user,
+            database: database,
+            kreta: kreta,
+          ),
+        ),
+        ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
+        ChangeNotifierProvider<ExamProvider>(
+          create: (context) => ExamProvider(context: context),
+        ),
+        ChangeNotifierProvider<HomeworkProvider>(
+          create: (context) => HomeworkProvider(
+            context: context,
+            database: database,
+          ),
+        ),
+        ChangeNotifierProvider<MessageProvider>(
+          create: (context) => MessageProvider(context: context),
+        ),
+        ChangeNotifierProvider<NoteProvider>(
+          create: (context) => NoteProvider(context: context),
+        ),
+        ChangeNotifierProvider<EventProvider>(
+          create: (context) => EventProvider(context: context),
+        ),
+        ChangeNotifierProvider<AbsenceProvider>(
+          create: (context) => AbsenceProvider(context: context),
+        ),
+
+        // other providers
+        ChangeNotifierProvider<GradeCalculatorProvider>(
+          create: (_) => GradeCalculatorProvider(
+            settings: settings,
+            user: user,
+            database: database,
+            kreta: kreta,
+          ),
+        ),
+        ChangeNotifierProvider<LiveCardProvider>(
+          create: (context) => LiveCardProvider(
+            timetable: timetable,
+            settings: settings,
+          ),
+        ),
+        ChangeNotifierProvider<GoalProvider>(
+          create: (context) => GoalProvider(
+            database: database,
+            user: user,
+          ),
+        ),
+        ChangeNotifierProvider<ShareProvider>(
+          create: (context) => ShareProvider(
+            user: user,
+          ),
+        ),
+      ],
+      child: Consumer<ThemeModeObserver>(
+        builder: (context, themeMode, child) {
+          return FutureBuilder<CorePalette?>(
+            future: DynamicColorPlugin.getCorePalette(),
+            builder: (context, snapshot) {
+              corePalette = snapshot.data;
+              return MaterialApp(
+                builder: (context, child) {
+                  // Limit font size scaling to 1.0
+                  double textScaleFactor =
+                      min(MediaQuery.of(context).textScaleFactor, 1.0);
+
+                  return I18n(
+                    initialLocale: Locale(
+                        settings.language, settings.language.toUpperCase()),
+                    child: MediaQuery(
+                      data: MediaQuery.of(context)
+                          .copyWith(textScaleFactor: textScaleFactor),
+                      child: child ?? Container(),
+                    ),
+                  );
+                },
+                title: "reFilc",
+                debugShowCheckedModeBanner: false,
+                theme: AppTheme.lightTheme(context, palette: corePalette),
+                darkTheme: AppTheme.darkTheme(context, palette: corePalette),
+                themeMode: themeMode.themeMode,
+                localizationsDelegates: const [
+                  GlobalMaterialLocalizations.delegate,
+                  GlobalWidgetsLocalizations.delegate,
+                  GlobalCupertinoLocalizations.delegate,
+                ],
+                supportedLocales: const [
+                  Locale('en', 'EN'),
+                  Locale('hu', 'HU'),
+                  Locale('de', 'DE'),
+                ],
+                localeListResolutionCallback: (locales, supported) {
+                  Locale locale = const Locale('hu', 'HU');
+
+                  for (var loc in locales ?? []) {
+                    if (supported.contains(loc)) {
+                      locale = loc;
+                      break;
+                    }
+                  }
+
+                  return locale;
+                },
+                onGenerateRoute: (settings) => rootNavigator(settings),
+                initialRoute:
+                    user.getUsers().isNotEmpty ? "navigation" : "login",
+              );
+            },
+          );
+        },
+      ),
+    );
+  }
+
+  Route? rootNavigator(RouteSettings route) {
+    if (kIsWeb) {
+      switch (route.name) {
+        case "login_back":
+          return CupertinoPageRoute(
+              builder: (context) => const desktop.LoginScreen(back: true));
+        case "login":
+          return _rootRoute(const desktop.LoginScreen());
+        case "navigation":
+          return _rootRoute(const desktop.NavigationScreen());
+        case "login_to_navigation":
+          return desktop.loginRoute(const desktop.NavigationScreen());
+      }
+    } else if (Platform.isAndroid || Platform.isIOS) {
+      switch (route.name) {
+        case "login_back":
+          return CupertinoPageRoute(
+              builder: (context) => const mobile.LoginScreen(back: true));
+        case "login":
+          return _rootRoute(const mobile.LoginScreen());
+        case "navigation":
+          return _rootRoute(const mobile.NavigationScreen());
+        case "login_to_navigation":
+          return mobile.loginRoute(const mobile.NavigationScreen());
+        case "settings":
+          return mobile.settingsRoute(const mobile.SettingsScreen());
+      }
+    } else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
+      switch (route.name) {
+        case "login_back":
+          return CupertinoPageRoute(
+              builder: (context) => const desktop.LoginScreen(back: true));
+        case "login":
+          return _rootRoute(const desktop.LoginScreen());
+        case "navigation":
+          return _rootRoute(const desktop.NavigationScreen());
+        case "login_to_navigation":
+          return desktop.loginRoute(const desktop.NavigationScreen());
+      }
+    }
+    return null;
+  }
+
+  Route _rootRoute(Widget widget) {
+    return PageRouteBuilder(pageBuilder: (context, _, __) => widget);
+  }
+}
diff --git a/filcnaplo/lib/database/init.dart b/refilc/lib/database/init.dart
similarity index 94%
rename from filcnaplo/lib/database/init.dart
rename to refilc/lib/database/init.dart
index 4f7d1ed..30747fe 100644
--- a/filcnaplo/lib/database/init.dart
+++ b/refilc/lib/database/init.dart
@@ -1,180 +1,180 @@
-// ignore_for_file: avoid_print
-
-import 'dart:io';
-
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/database/struct.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:flutter/foundation.dart';
-// ignore: depend_on_referenced_packages
-import 'package:sqflite_common_ffi/sqflite_ffi.dart';
-import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
-
-const settingsDB = DatabaseStruct("settings", {
-  "language": String, "start_page": int, "rounding": int, "theme": int,
-  "accent_color": int, "news": int, "seen_news": String,
-  "developer_mode": int,
-  "update_channel": int, "config": String, "custom_accent_color": int,
-  "custom_background_color": int, "custom_highlight_color": int, // general
-  "grade_color1": int, "grade_color2": int, "grade_color3": int,
-  "grade_color4": int, "grade_color5": int, // grade colors
-  "vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
-  "notifications": int, "notifications_bitfield": int,
-  "notification_poll_interval": int,
-  "notifications_grades": int,
-  "notifications_absences": int,
-  "notifications_messages": int,
-  "notifications_lessons": int, // notifications
-  "x_filc_id": String, "graph_class_avg": int, "presentation_mode": int,
-  "bell_delay": int, "bell_delay_enabled": int,
-  "grade_opening_fun": int, "icon_pack": String, "premium_scopes": String,
-  "premium_token": String, "premium_login": String,
-  "last_account_id": String, "renamed_subjects_enabled": int,
-  "renamed_subjects_italics": int, "renamed_teachers_enabled": int,
-  "renamed_teachers_italics": int,
-  "live_activity_color": String,
-});
-// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
-// YOU'VE BEEN WARNED!!!
-const usersDB = DatabaseStruct("users", {
-  "id": String, "name": String, "username": String, "password": String,
-  "institute_code": String, "student": String, "role": int,
-  "nickname": String, "picture": String // premium only
-});
-const userDataDB = DatabaseStruct("user_data", {
-  "id": String, "grades": String, "timetable": String, "exams": String,
-  "homework": String, "messages": String, "notes": String,
-  "events": String, "absences": String, "group_averages": String,
-  // renamed subjects // non kreta data
-  "renamed_subjects": String,
-  // renamed teachers // non kreta data
-  "renamed_teachers": String,
-  // "subject_lesson_count": String, // non kreta data
-  "last_seen_grade": int,
-  // goal planning // non kreta data
-  "goal_plans": String,
-  "goal_averages": String,
-  "goal_befores": String,
-  "goal_pin_dates": String,
-});
-
-Future<void> createTable(Database db, DatabaseStruct struct) =>
-    db.execute("CREATE TABLE IF NOT EXISTS ${struct.table} ($struct)");
-
-Future<Database> initDB(DatabaseProvider database) async {
-  Database db;
-
-  if (kIsWeb) {
-    db = await databaseFactoryFfiWeb.openDatabase("app.db");
-  } else if (Platform.isLinux || Platform.isWindows) {
-    sqfliteFfiInit();
-    db = await databaseFactoryFfi.openDatabase("app.db");
-  } else {
-    db = await openDatabase("app.db");
-  }
-
-  await createTable(db, settingsDB);
-  await createTable(db, usersDB);
-  await createTable(db, userDataDB);
-
-  if ((await db.rawQuery("SELECT COUNT(*) FROM settings"))[0].values.first ==
-      0) {
-    // Set default values for table Settings
-    await db.insert("settings",
-        SettingsProvider.defaultSettings(database: database).toMap());
-  }
-
-  // Migrate Databases
-  try {
-    await migrateDB(
-      db,
-      struct: settingsDB,
-      defaultValues:
-          SettingsProvider.defaultSettings(database: database).toMap(),
-    );
-    await migrateDB(
-      db,
-      struct: usersDB,
-      defaultValues: {"role": 0, "nickname": "", "picture": ""},
-    );
-    await migrateDB(db, struct: userDataDB, defaultValues: {
-      "grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]",
-      "messages": "[]", "notes": "[]", "events": "[]", "absences": "[]",
-      "group_averages": "[]",
-      // renamed subjects // non kreta data
-      "renamed_subjects": "{}",
-      // renamed teachers // non kreta data
-      "renamed_teachers": "{}",
-      // "subject_lesson_count": "{}", // non kreta data
-      "last_seen_grade": 0,
-      // goal planning // non kreta data
-      "goal_plans": "{}",
-      "goal_averages": "{}",
-      "goal_befores": "{}",
-      "goal_pin_dates": "{}",
-    });
-  } catch (error) {
-    print("ERROR: migrateDB: $error");
-  }
-
-  return db;
-}
-
-Future<void> migrateDB(
-  Database db, {
-  required DatabaseStruct struct,
-  required Map<String, Object?> defaultValues,
-}) async {
-  var originalRows = await db.query(struct.table);
-
-  if (originalRows.isEmpty) {
-    await db.execute("drop table ${struct.table}");
-    await createTable(db, struct);
-    return;
-  }
-
-  List<Map<String, dynamic>> migrated = [];
-
-  // go through each row and add missing keys or delete non existing keys
-  await Future.forEach<Map<String, Object?>>(originalRows, (original) async {
-    bool migrationRequired = struct.struct.keys.any(
-            (key) => !original.containsKey(key) || original[key] == null) ||
-        original.keys.any((key) => !struct.struct.containsKey(key));
-
-    if (migrationRequired) {
-      print("INFO: Migrating ${struct.table}");
-      var copy = Map<String, Object?>.from(original);
-
-      // Fill missing columns
-      for (var key in struct.struct.keys) {
-        if (!original.containsKey(key) || original[key] == null) {
-          print("DEBUG: migrating $key");
-          copy[key] = defaultValues[key];
-        }
-      }
-
-      for (var key in original.keys) {
-        if (!struct.struct.keys.contains(key)) {
-          print("DEBUG: dropping $key");
-          copy.remove(key);
-        }
-      }
-
-      migrated.add(copy);
-    }
-  });
-
-  // replace the old table with the migrated one
-  if (migrated.isNotEmpty) {
-    // Delete table
-    await db.execute("drop table ${struct.table}");
-
-    // Recreate table
-    await createTable(db, struct);
-    await Future.forEach(migrated, (Map<String, Object?> copy) async {
-      await db.insert(struct.table, copy);
-    });
-
-    print("INFO: Database migrated");
-  }
-}
+// ignore_for_file: avoid_print
+
+import 'dart:io';
+
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/database/struct.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:flutter/foundation.dart';
+// ignore: depend_on_referenced_packages
+import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
+
+const settingsDB = DatabaseStruct("settings", {
+  "language": String, "start_page": int, "rounding": int, "theme": int,
+  "accent_color": int, "news": int, "seen_news": String,
+  "developer_mode": int,
+  "update_channel": int, "config": String, "custom_accent_color": int,
+  "custom_background_color": int, "custom_highlight_color": int, // general
+  "grade_color1": int, "grade_color2": int, "grade_color3": int,
+  "grade_color4": int, "grade_color5": int, // grade colors
+  "vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
+  "notifications": int, "notifications_bitfield": int,
+  "notification_poll_interval": int,
+  "notifications_grades": int,
+  "notifications_absences": int,
+  "notifications_messages": int,
+  "notifications_lessons": int, // notifications
+  "x_filc_id": String, "graph_class_avg": int, "presentation_mode": int,
+  "bell_delay": int, "bell_delay_enabled": int,
+  "grade_opening_fun": int, "icon_pack": String, "premium_scopes": String,
+  "premium_token": String, "premium_login": String,
+  "last_account_id": String, "renamed_subjects_enabled": int,
+  "renamed_subjects_italics": int, "renamed_teachers_enabled": int,
+  "renamed_teachers_italics": int,
+  "live_activity_color": String,
+});
+// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
+// YOU'VE BEEN WARNED!!!
+const usersDB = DatabaseStruct("users", {
+  "id": String, "name": String, "username": String, "password": String,
+  "institute_code": String, "student": String, "role": int,
+  "nickname": String, "picture": String // premium only
+});
+const userDataDB = DatabaseStruct("user_data", {
+  "id": String, "grades": String, "timetable": String, "exams": String,
+  "homework": String, "messages": String, "notes": String,
+  "events": String, "absences": String, "group_averages": String,
+  // renamed subjects // non kreta data
+  "renamed_subjects": String,
+  // renamed teachers // non kreta data
+  "renamed_teachers": String,
+  // "subject_lesson_count": String, // non kreta data
+  "last_seen_grade": int,
+  // goal planning // non kreta data
+  "goal_plans": String,
+  "goal_averages": String,
+  "goal_befores": String,
+  "goal_pin_dates": String,
+});
+
+Future<void> createTable(Database db, DatabaseStruct struct) =>
+    db.execute("CREATE TABLE IF NOT EXISTS ${struct.table} ($struct)");
+
+Future<Database> initDB(DatabaseProvider database) async {
+  Database db;
+
+  if (kIsWeb) {
+    db = await databaseFactoryFfiWeb.openDatabase("app.db");
+  } else if (Platform.isLinux || Platform.isWindows) {
+    sqfliteFfiInit();
+    db = await databaseFactoryFfi.openDatabase("app.db");
+  } else {
+    db = await openDatabase("app.db");
+  }
+
+  await createTable(db, settingsDB);
+  await createTable(db, usersDB);
+  await createTable(db, userDataDB);
+
+  if ((await db.rawQuery("SELECT COUNT(*) FROM settings"))[0].values.first ==
+      0) {
+    // Set default values for table Settings
+    await db.insert("settings",
+        SettingsProvider.defaultSettings(database: database).toMap());
+  }
+
+  // Migrate Databases
+  try {
+    await migrateDB(
+      db,
+      struct: settingsDB,
+      defaultValues:
+          SettingsProvider.defaultSettings(database: database).toMap(),
+    );
+    await migrateDB(
+      db,
+      struct: usersDB,
+      defaultValues: {"role": 0, "nickname": "", "picture": ""},
+    );
+    await migrateDB(db, struct: userDataDB, defaultValues: {
+      "grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]",
+      "messages": "[]", "notes": "[]", "events": "[]", "absences": "[]",
+      "group_averages": "[]",
+      // renamed subjects // non kreta data
+      "renamed_subjects": "{}",
+      // renamed teachers // non kreta data
+      "renamed_teachers": "{}",
+      // "subject_lesson_count": "{}", // non kreta data
+      "last_seen_grade": 0,
+      // goal planning // non kreta data
+      "goal_plans": "{}",
+      "goal_averages": "{}",
+      "goal_befores": "{}",
+      "goal_pin_dates": "{}",
+    });
+  } catch (error) {
+    print("ERROR: migrateDB: $error");
+  }
+
+  return db;
+}
+
+Future<void> migrateDB(
+  Database db, {
+  required DatabaseStruct struct,
+  required Map<String, Object?> defaultValues,
+}) async {
+  var originalRows = await db.query(struct.table);
+
+  if (originalRows.isEmpty) {
+    await db.execute("drop table ${struct.table}");
+    await createTable(db, struct);
+    return;
+  }
+
+  List<Map<String, dynamic>> migrated = [];
+
+  // go through each row and add missing keys or delete non existing keys
+  await Future.forEach<Map<String, Object?>>(originalRows, (original) async {
+    bool migrationRequired = struct.struct.keys.any(
+            (key) => !original.containsKey(key) || original[key] == null) ||
+        original.keys.any((key) => !struct.struct.containsKey(key));
+
+    if (migrationRequired) {
+      print("INFO: Migrating ${struct.table}");
+      var copy = Map<String, Object?>.from(original);
+
+      // Fill missing columns
+      for (var key in struct.struct.keys) {
+        if (!original.containsKey(key) || original[key] == null) {
+          print("DEBUG: migrating $key");
+          copy[key] = defaultValues[key];
+        }
+      }
+
+      for (var key in original.keys) {
+        if (!struct.struct.keys.contains(key)) {
+          print("DEBUG: dropping $key");
+          copy.remove(key);
+        }
+      }
+
+      migrated.add(copy);
+    }
+  });
+
+  // replace the old table with the migrated one
+  if (migrated.isNotEmpty) {
+    // Delete table
+    await db.execute("drop table ${struct.table}");
+
+    // Recreate table
+    await createTable(db, struct);
+    await Future.forEach(migrated, (Map<String, Object?> copy) async {
+      await db.insert(struct.table, copy);
+    });
+
+    print("INFO: Database migrated");
+  }
+}
diff --git a/filcnaplo/lib/database/query.dart b/refilc/lib/database/query.dart
similarity index 89%
rename from filcnaplo/lib/database/query.dart
rename to refilc/lib/database/query.dart
index fb3094c..465ec70 100644
--- a/filcnaplo/lib/database/query.dart
+++ b/refilc/lib/database/query.dart
@@ -1,262 +1,262 @@
-import 'dart:convert';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/subject_lesson_count.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-// ignore: depend_on_referenced_packages
-import 'package:sqflite_common/sqlite_api.dart';
-
-// Models
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/group_average.dart';
-
-class DatabaseQuery {
-  DatabaseQuery({required this.db});
-
-  final Database db;
-
-  Future<SettingsProvider> getSettings(DatabaseProvider database) async {
-    Map settingsMap = (await db.query("settings")).elementAt(0);
-    SettingsProvider settings =
-        SettingsProvider.fromMap(settingsMap, database: database);
-    return settings;
-  }
-
-  Future<UserProvider> getUsers(SettingsProvider settings) async {
-    var userProvider = UserProvider(settings: settings);
-    List<Map> usersMap = await db.query("users");
-    for (var user in usersMap) {
-      userProvider.addUser(User.fromMap(user));
-    }
-    if (userProvider
-        .getUsers()
-        .map((e) => e.id)
-        .contains(settings.lastAccountId)) {
-      userProvider.setUser(settings.lastAccountId);
-    } else {
-      if (usersMap.isNotEmpty) {
-        userProvider.setUser(userProvider.getUsers().first.id);
-        settings.update(lastAccountId: userProvider.id);
-      }
-    }
-    return userProvider;
-  }
-}
-
-class UserDatabaseQuery {
-  UserDatabaseQuery({required this.db});
-
-  final Database db;
-
-  Future<List<Grade>> getGrades({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? gradesJson = userData.elementAt(0)["grades"] as String?;
-    if (gradesJson == null) return [];
-    List<Grade> grades =
-        (jsonDecode(gradesJson) as List).map((e) => Grade.fromJson(e)).toList();
-    return grades;
-  }
-
-  Future<Map<Week, List<Lesson>>> getLessons({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? lessonsJson = userData.elementAt(0)["timetable"] as String?;
-    if (lessonsJson == null) return {};
-    if (jsonDecode(lessonsJson) is List) return {};
-    Map<Week, List<Lesson>> lessons =
-        (jsonDecode(lessonsJson) as Map).cast<String, List>().map((key, value) {
-      return MapEntry(
-          Week.fromId(int.parse(key)),
-          value
-              .cast<Map<String, Object?>>()
-              .map((e) => Lesson.fromJson(e))
-              .toList());
-    }).cast();
-    return lessons;
-  }
-
-  Future<List<Exam>> getExams({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? examsJson = userData.elementAt(0)["exams"] as String?;
-    if (examsJson == null) return [];
-    List<Exam> exams =
-        (jsonDecode(examsJson) as List).map((e) => Exam.fromJson(e)).toList();
-    return exams;
-  }
-
-  Future<List<Homework>> getHomework({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? homeworkJson = userData.elementAt(0)["homework"] as String?;
-    if (homeworkJson == null) return [];
-    List<Homework> homework = (jsonDecode(homeworkJson) as List)
-        .map((e) => Homework.fromJson(e))
-        .toList();
-    return homework;
-  }
-
-  Future<List<Message>> getMessages({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? messagesJson = userData.elementAt(0)["messages"] as String?;
-    if (messagesJson == null) return [];
-    List<Message> messages = (jsonDecode(messagesJson) as List)
-        .map((e) => Message.fromJson(e))
-        .toList();
-    return messages;
-  }
-
-  Future<List<Note>> getNotes({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? notesJson = userData.elementAt(0)["notes"] as String?;
-    if (notesJson == null) return [];
-    List<Note> notes =
-        (jsonDecode(notesJson) as List).map((e) => Note.fromJson(e)).toList();
-    return notes;
-  }
-
-  Future<List<Event>> getEvents({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? eventsJson = userData.elementAt(0)["events"] as String?;
-    if (eventsJson == null) return [];
-    List<Event> events =
-        (jsonDecode(eventsJson) as List).map((e) => Event.fromJson(e)).toList();
-    return events;
-  }
-
-  Future<List<Absence>> getAbsences({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? absencesJson = userData.elementAt(0)["absences"] as String?;
-    if (absencesJson == null) return [];
-    List<Absence> absences = (jsonDecode(absencesJson) as List)
-        .map((e) => Absence.fromJson(e))
-        .toList();
-    return absences;
-  }
-
-  Future<List<GroupAverage>> getGroupAverages({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return [];
-    String? groupAveragesJson =
-        userData.elementAt(0)["group_averages"] as String?;
-    if (groupAveragesJson == null) return [];
-    List<GroupAverage> groupAverages = (jsonDecode(groupAveragesJson) as List)
-        .map((e) => GroupAverage.fromJson(e))
-        .toList();
-    return groupAverages;
-  }
-
-  Future<SubjectLessonCount> getSubjectLessonCount(
-      {required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return SubjectLessonCount.fromMap({});
-    String? lessonCountJson =
-        userData.elementAt(0)["subject_lesson_count"] as String?;
-    if (lessonCountJson == null) return SubjectLessonCount.fromMap({});
-    SubjectLessonCount lessonCount =
-        SubjectLessonCount.fromMap(jsonDecode(lessonCountJson) as Map);
-    return lessonCount;
-  }
-
-  Future<DateTime> lastSeenGrade({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return DateTime(0);
-    int? lastSeenDate = userData.elementAt(0)["last_seen_grade"] as int?;
-    if (lastSeenDate == null) return DateTime(0);
-    DateTime lastSeen = DateTime.fromMillisecondsSinceEpoch(lastSeenDate);
-    return lastSeen;
-  }
-
-  // renamed things
-  Future<Map<String, String>> renamedSubjects({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? renamedSubjectsJson =
-        userData.elementAt(0)["renamed_subjects"] as String?;
-    if (renamedSubjectsJson == null) return {};
-    return (jsonDecode(renamedSubjectsJson) as Map)
-        .map((key, value) => MapEntry(key.toString(), value.toString()));
-  }
-
-  Future<Map<String, String>> renamedTeachers({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? renamedTeachersJson =
-        userData.elementAt(0)["renamed_teachers"] as String?;
-    if (renamedTeachersJson == null) return {};
-    return (jsonDecode(renamedTeachersJson) as Map)
-        .map((key, value) => MapEntry(key.toString(), value.toString()));
-  }
-
-  // goal planner
-  Future<Map<String, String>> subjectGoalPlans({required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? goalPlansJson = userData.elementAt(0)["goal_plans"] as String?;
-    if (goalPlansJson == null) return {};
-    return (jsonDecode(goalPlansJson) as Map)
-        .map((key, value) => MapEntry(key.toString(), value.toString()));
-  }
-
-  Future<Map<String, String>> subjectGoalAverages(
-      {required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? goalAvgsJson = userData.elementAt(0)["goal_averages"] as String?;
-    if (goalAvgsJson == null) return {};
-    return (jsonDecode(goalAvgsJson) as Map)
-        .map((key, value) => MapEntry(key.toString(), value.toString()));
-  }
-
-  Future<Map<String, String>> subjectGoalBefores(
-      {required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? goalBeforesJson = userData.elementAt(0)["goal_befores"] as String?;
-    if (goalBeforesJson == null) return {};
-    return (jsonDecode(goalBeforesJson) as Map)
-        .map((key, value) => MapEntry(key.toString(), value.toString()));
-  }
-
-  Future<Map<String, String>> subjectGoalPinDates(
-      {required String userId}) async {
-    List<Map> userData =
-        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
-    if (userData.isEmpty) return {};
-    String? goalPinDatesJson =
-        userData.elementAt(0)["goal_pin_dates"] as String?;
-    if (goalPinDatesJson == null) return {};
-    return (jsonDecode(goalPinDatesJson) as Map)
-        .map((key, value) => MapEntry(key.toString(), value.toString()));
-  }
-}
+import 'dart:convert';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/subject_lesson_count.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+// ignore: depend_on_referenced_packages
+import 'package:sqflite_common/sqlite_api.dart';
+
+// Models
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/group_average.dart';
+
+class DatabaseQuery {
+  DatabaseQuery({required this.db});
+
+  final Database db;
+
+  Future<SettingsProvider> getSettings(DatabaseProvider database) async {
+    Map settingsMap = (await db.query("settings")).elementAt(0);
+    SettingsProvider settings =
+        SettingsProvider.fromMap(settingsMap, database: database);
+    return settings;
+  }
+
+  Future<UserProvider> getUsers(SettingsProvider settings) async {
+    var userProvider = UserProvider(settings: settings);
+    List<Map> usersMap = await db.query("users");
+    for (var user in usersMap) {
+      userProvider.addUser(User.fromMap(user));
+    }
+    if (userProvider
+        .getUsers()
+        .map((e) => e.id)
+        .contains(settings.lastAccountId)) {
+      userProvider.setUser(settings.lastAccountId);
+    } else {
+      if (usersMap.isNotEmpty) {
+        userProvider.setUser(userProvider.getUsers().first.id);
+        settings.update(lastAccountId: userProvider.id);
+      }
+    }
+    return userProvider;
+  }
+}
+
+class UserDatabaseQuery {
+  UserDatabaseQuery({required this.db});
+
+  final Database db;
+
+  Future<List<Grade>> getGrades({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? gradesJson = userData.elementAt(0)["grades"] as String?;
+    if (gradesJson == null) return [];
+    List<Grade> grades =
+        (jsonDecode(gradesJson) as List).map((e) => Grade.fromJson(e)).toList();
+    return grades;
+  }
+
+  Future<Map<Week, List<Lesson>>> getLessons({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? lessonsJson = userData.elementAt(0)["timetable"] as String?;
+    if (lessonsJson == null) return {};
+    if (jsonDecode(lessonsJson) is List) return {};
+    Map<Week, List<Lesson>> lessons =
+        (jsonDecode(lessonsJson) as Map).cast<String, List>().map((key, value) {
+      return MapEntry(
+          Week.fromId(int.parse(key)),
+          value
+              .cast<Map<String, Object?>>()
+              .map((e) => Lesson.fromJson(e))
+              .toList());
+    }).cast();
+    return lessons;
+  }
+
+  Future<List<Exam>> getExams({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? examsJson = userData.elementAt(0)["exams"] as String?;
+    if (examsJson == null) return [];
+    List<Exam> exams =
+        (jsonDecode(examsJson) as List).map((e) => Exam.fromJson(e)).toList();
+    return exams;
+  }
+
+  Future<List<Homework>> getHomework({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? homeworkJson = userData.elementAt(0)["homework"] as String?;
+    if (homeworkJson == null) return [];
+    List<Homework> homework = (jsonDecode(homeworkJson) as List)
+        .map((e) => Homework.fromJson(e))
+        .toList();
+    return homework;
+  }
+
+  Future<List<Message>> getMessages({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? messagesJson = userData.elementAt(0)["messages"] as String?;
+    if (messagesJson == null) return [];
+    List<Message> messages = (jsonDecode(messagesJson) as List)
+        .map((e) => Message.fromJson(e))
+        .toList();
+    return messages;
+  }
+
+  Future<List<Note>> getNotes({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? notesJson = userData.elementAt(0)["notes"] as String?;
+    if (notesJson == null) return [];
+    List<Note> notes =
+        (jsonDecode(notesJson) as List).map((e) => Note.fromJson(e)).toList();
+    return notes;
+  }
+
+  Future<List<Event>> getEvents({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? eventsJson = userData.elementAt(0)["events"] as String?;
+    if (eventsJson == null) return [];
+    List<Event> events =
+        (jsonDecode(eventsJson) as List).map((e) => Event.fromJson(e)).toList();
+    return events;
+  }
+
+  Future<List<Absence>> getAbsences({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? absencesJson = userData.elementAt(0)["absences"] as String?;
+    if (absencesJson == null) return [];
+    List<Absence> absences = (jsonDecode(absencesJson) as List)
+        .map((e) => Absence.fromJson(e))
+        .toList();
+    return absences;
+  }
+
+  Future<List<GroupAverage>> getGroupAverages({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return [];
+    String? groupAveragesJson =
+        userData.elementAt(0)["group_averages"] as String?;
+    if (groupAveragesJson == null) return [];
+    List<GroupAverage> groupAverages = (jsonDecode(groupAveragesJson) as List)
+        .map((e) => GroupAverage.fromJson(e))
+        .toList();
+    return groupAverages;
+  }
+
+  Future<SubjectLessonCount> getSubjectLessonCount(
+      {required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return SubjectLessonCount.fromMap({});
+    String? lessonCountJson =
+        userData.elementAt(0)["subject_lesson_count"] as String?;
+    if (lessonCountJson == null) return SubjectLessonCount.fromMap({});
+    SubjectLessonCount lessonCount =
+        SubjectLessonCount.fromMap(jsonDecode(lessonCountJson) as Map);
+    return lessonCount;
+  }
+
+  Future<DateTime> lastSeenGrade({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return DateTime(0);
+    int? lastSeenDate = userData.elementAt(0)["last_seen_grade"] as int?;
+    if (lastSeenDate == null) return DateTime(0);
+    DateTime lastSeen = DateTime.fromMillisecondsSinceEpoch(lastSeenDate);
+    return lastSeen;
+  }
+
+  // renamed things
+  Future<Map<String, String>> renamedSubjects({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? renamedSubjectsJson =
+        userData.elementAt(0)["renamed_subjects"] as String?;
+    if (renamedSubjectsJson == null) return {};
+    return (jsonDecode(renamedSubjectsJson) as Map)
+        .map((key, value) => MapEntry(key.toString(), value.toString()));
+  }
+
+  Future<Map<String, String>> renamedTeachers({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? renamedTeachersJson =
+        userData.elementAt(0)["renamed_teachers"] as String?;
+    if (renamedTeachersJson == null) return {};
+    return (jsonDecode(renamedTeachersJson) as Map)
+        .map((key, value) => MapEntry(key.toString(), value.toString()));
+  }
+
+  // goal planner
+  Future<Map<String, String>> subjectGoalPlans({required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? goalPlansJson = userData.elementAt(0)["goal_plans"] as String?;
+    if (goalPlansJson == null) return {};
+    return (jsonDecode(goalPlansJson) as Map)
+        .map((key, value) => MapEntry(key.toString(), value.toString()));
+  }
+
+  Future<Map<String, String>> subjectGoalAverages(
+      {required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? goalAvgsJson = userData.elementAt(0)["goal_averages"] as String?;
+    if (goalAvgsJson == null) return {};
+    return (jsonDecode(goalAvgsJson) as Map)
+        .map((key, value) => MapEntry(key.toString(), value.toString()));
+  }
+
+  Future<Map<String, String>> subjectGoalBefores(
+      {required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? goalBeforesJson = userData.elementAt(0)["goal_befores"] as String?;
+    if (goalBeforesJson == null) return {};
+    return (jsonDecode(goalBeforesJson) as Map)
+        .map((key, value) => MapEntry(key.toString(), value.toString()));
+  }
+
+  Future<Map<String, String>> subjectGoalPinDates(
+      {required String userId}) async {
+    List<Map> userData =
+        await db.query("user_data", where: "id = ?", whereArgs: [userId]);
+    if (userData.isEmpty) return {};
+    String? goalPinDatesJson =
+        userData.elementAt(0)["goal_pin_dates"] as String?;
+    if (goalPinDatesJson == null) return {};
+    return (jsonDecode(goalPinDatesJson) as Map)
+        .map((key, value) => MapEntry(key.toString(), value.toString()));
+  }
+}
diff --git a/filcnaplo/lib/database/store.dart b/refilc/lib/database/store.dart
similarity index 86%
rename from filcnaplo/lib/database/store.dart
rename to refilc/lib/database/store.dart
index 185462d..0d4497d 100644
--- a/filcnaplo/lib/database/store.dart
+++ b/refilc/lib/database/store.dart
@@ -1,173 +1,173 @@
-import 'dart:convert';
-import 'package:filcnaplo/models/subject_lesson_count.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-// ignore: depend_on_referenced_packages
-import 'package:sqflite_common/sqlite_api.dart';
-
-// Models
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/group_average.dart';
-
-class DatabaseStore {
-  DatabaseStore({required this.db});
-
-  final Database db;
-
-  Future<void> storeSettings(SettingsProvider settings) async {
-    await db.update("settings", settings.toMap());
-  }
-
-  Future<void> storeUser(User user) async {
-    List userRes =
-        await db.query("users", where: "id = ?", whereArgs: [user.id]);
-    if (userRes.isNotEmpty) {
-      await db
-          .update("users", user.toMap(), where: "id = ?", whereArgs: [user.id]);
-    } else {
-      await db.insert("users", user.toMap());
-      await db.insert("user_data", {"id": user.id});
-    }
-  }
-
-  Future<void> removeUser(String userId) async {
-    await db.delete("users", where: "id = ?", whereArgs: [userId]);
-    await db.delete("user_data", where: "id = ?", whereArgs: [userId]);
-  }
-}
-
-class UserDatabaseStore {
-  UserDatabaseStore({required this.db});
-
-  final Database db;
-
-  Future<void> storeGrades(List<Grade> grades, {required String userId}) async {
-    String gradesJson = jsonEncode(grades.map((e) => e.json).toList());
-    await db.update("user_data", {"grades": gradesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeLessons(Map<Week, List<Lesson>?> lessons,
-      {required String userId}) async {
-    final map = lessons.map<String, List<Map<String, Object?>>>(
-      (k, v) => MapEntry(k.id.toString(),
-          v!.where((e) => e.json != null).map((e) => e.json!).toList().cast()),
-    );
-    String lessonsJson = jsonEncode(map);
-    await db.update("user_data", {"timetable": lessonsJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeExams(List<Exam> exams, {required String userId}) async {
-    String examsJson = jsonEncode(exams.map((e) => e.json).toList());
-    await db.update("user_data", {"exams": examsJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeHomework(List<Homework> homework,
-      {required String userId}) async {
-    String homeworkJson = jsonEncode(homework.map((e) => e.json).toList());
-    await db.update("user_data", {"homework": homeworkJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeMessages(List<Message> messages,
-      {required String userId}) async {
-    String messagesJson = jsonEncode(messages.map((e) => e.json).toList());
-    await db.update("user_data", {"messages": messagesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeNotes(List<Note> notes, {required String userId}) async {
-    String notesJson = jsonEncode(notes.map((e) => e.json).toList());
-    await db.update("user_data", {"notes": notesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeEvents(List<Event> events, {required String userId}) async {
-    String eventsJson = jsonEncode(events.map((e) => e.json).toList());
-    await db.update("user_data", {"events": eventsJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeAbsences(List<Absence> absences,
-      {required String userId}) async {
-    String absencesJson = jsonEncode(absences.map((e) => e.json).toList());
-    await db.update("user_data", {"absences": absencesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeGroupAverages(List<GroupAverage> groupAverages,
-      {required String userId}) async {
-    String groupAveragesJson =
-        jsonEncode(groupAverages.map((e) => e.json).toList());
-    await db.update("user_data", {"group_averages": groupAveragesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeSubjectLessonCount(SubjectLessonCount lessonCount,
-      {required String userId}) async {
-    String lessonCountJson = jsonEncode(lessonCount.toMap());
-    await db.update("user_data", {"subject_lesson_count": lessonCountJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeLastSeenGrade(DateTime date,
-      {required String userId}) async {
-    int lastSeenDate = date.millisecondsSinceEpoch;
-    await db.update("user_data", {"last_seen_grade": lastSeenDate},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  // renamed things
-  Future<void> storeRenamedSubjects(Map<String, String> subjects,
-      {required String userId}) async {
-    String renamedSubjectsJson = jsonEncode(subjects);
-    await db.update("user_data", {"renamed_subjects": renamedSubjectsJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeRenamedTeachers(Map<String, String> teachers,
-      {required String userId}) async {
-    String renamedTeachersJson = jsonEncode(teachers);
-    await db.update("user_data", {"renamed_teachers": renamedTeachersJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  // goal planner
-  Future<void> storeSubjectGoalPlans(Map<String, String> plans,
-      {required String userId}) async {
-    String goalPlansJson = jsonEncode(plans);
-    await db.update("user_data", {"goal_plans": goalPlansJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeSubjectGoalAverages(Map<String, String> avgs,
-      {required String userId}) async {
-    String goalAvgsJson = jsonEncode(avgs);
-    await db.update("user_data", {"goal_averages": goalAvgsJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeSubjectGoalBefores(Map<String, String> befores,
-      {required String userId}) async {
-    String goalBeforesJson = jsonEncode(befores);
-    await db.update("user_data", {"goal_befores": goalBeforesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-
-  Future<void> storeSubjectGoalPinDates(Map<String, String> dates,
-      {required String userId}) async {
-    String goalPinDatesJson = jsonEncode(dates);
-    await db.update("user_data", {"goal_pin_dates": goalPinDatesJson},
-        where: "id = ?", whereArgs: [userId]);
-  }
-}
+import 'dart:convert';
+import 'package:refilc/models/subject_lesson_count.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+// ignore: depend_on_referenced_packages
+import 'package:sqflite_common/sqlite_api.dart';
+
+// Models
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/group_average.dart';
+
+class DatabaseStore {
+  DatabaseStore({required this.db});
+
+  final Database db;
+
+  Future<void> storeSettings(SettingsProvider settings) async {
+    await db.update("settings", settings.toMap());
+  }
+
+  Future<void> storeUser(User user) async {
+    List userRes =
+        await db.query("users", where: "id = ?", whereArgs: [user.id]);
+    if (userRes.isNotEmpty) {
+      await db
+          .update("users", user.toMap(), where: "id = ?", whereArgs: [user.id]);
+    } else {
+      await db.insert("users", user.toMap());
+      await db.insert("user_data", {"id": user.id});
+    }
+  }
+
+  Future<void> removeUser(String userId) async {
+    await db.delete("users", where: "id = ?", whereArgs: [userId]);
+    await db.delete("user_data", where: "id = ?", whereArgs: [userId]);
+  }
+}
+
+class UserDatabaseStore {
+  UserDatabaseStore({required this.db});
+
+  final Database db;
+
+  Future<void> storeGrades(List<Grade> grades, {required String userId}) async {
+    String gradesJson = jsonEncode(grades.map((e) => e.json).toList());
+    await db.update("user_data", {"grades": gradesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeLessons(Map<Week, List<Lesson>?> lessons,
+      {required String userId}) async {
+    final map = lessons.map<String, List<Map<String, Object?>>>(
+      (k, v) => MapEntry(k.id.toString(),
+          v!.where((e) => e.json != null).map((e) => e.json!).toList().cast()),
+    );
+    String lessonsJson = jsonEncode(map);
+    await db.update("user_data", {"timetable": lessonsJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeExams(List<Exam> exams, {required String userId}) async {
+    String examsJson = jsonEncode(exams.map((e) => e.json).toList());
+    await db.update("user_data", {"exams": examsJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeHomework(List<Homework> homework,
+      {required String userId}) async {
+    String homeworkJson = jsonEncode(homework.map((e) => e.json).toList());
+    await db.update("user_data", {"homework": homeworkJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeMessages(List<Message> messages,
+      {required String userId}) async {
+    String messagesJson = jsonEncode(messages.map((e) => e.json).toList());
+    await db.update("user_data", {"messages": messagesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeNotes(List<Note> notes, {required String userId}) async {
+    String notesJson = jsonEncode(notes.map((e) => e.json).toList());
+    await db.update("user_data", {"notes": notesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeEvents(List<Event> events, {required String userId}) async {
+    String eventsJson = jsonEncode(events.map((e) => e.json).toList());
+    await db.update("user_data", {"events": eventsJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeAbsences(List<Absence> absences,
+      {required String userId}) async {
+    String absencesJson = jsonEncode(absences.map((e) => e.json).toList());
+    await db.update("user_data", {"absences": absencesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeGroupAverages(List<GroupAverage> groupAverages,
+      {required String userId}) async {
+    String groupAveragesJson =
+        jsonEncode(groupAverages.map((e) => e.json).toList());
+    await db.update("user_data", {"group_averages": groupAveragesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeSubjectLessonCount(SubjectLessonCount lessonCount,
+      {required String userId}) async {
+    String lessonCountJson = jsonEncode(lessonCount.toMap());
+    await db.update("user_data", {"subject_lesson_count": lessonCountJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeLastSeenGrade(DateTime date,
+      {required String userId}) async {
+    int lastSeenDate = date.millisecondsSinceEpoch;
+    await db.update("user_data", {"last_seen_grade": lastSeenDate},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  // renamed things
+  Future<void> storeRenamedSubjects(Map<String, String> subjects,
+      {required String userId}) async {
+    String renamedSubjectsJson = jsonEncode(subjects);
+    await db.update("user_data", {"renamed_subjects": renamedSubjectsJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeRenamedTeachers(Map<String, String> teachers,
+      {required String userId}) async {
+    String renamedTeachersJson = jsonEncode(teachers);
+    await db.update("user_data", {"renamed_teachers": renamedTeachersJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  // goal planner
+  Future<void> storeSubjectGoalPlans(Map<String, String> plans,
+      {required String userId}) async {
+    String goalPlansJson = jsonEncode(plans);
+    await db.update("user_data", {"goal_plans": goalPlansJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeSubjectGoalAverages(Map<String, String> avgs,
+      {required String userId}) async {
+    String goalAvgsJson = jsonEncode(avgs);
+    await db.update("user_data", {"goal_averages": goalAvgsJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeSubjectGoalBefores(Map<String, String> befores,
+      {required String userId}) async {
+    String goalBeforesJson = jsonEncode(befores);
+    await db.update("user_data", {"goal_befores": goalBeforesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+
+  Future<void> storeSubjectGoalPinDates(Map<String, String> dates,
+      {required String userId}) async {
+    String goalPinDatesJson = jsonEncode(dates);
+    await db.update("user_data", {"goal_pin_dates": goalPinDatesJson},
+        where: "id = ?", whereArgs: [userId]);
+  }
+}
diff --git a/filcnaplo/lib/database/struct.dart b/refilc/lib/database/struct.dart
similarity index 95%
rename from filcnaplo/lib/database/struct.dart
rename to refilc/lib/database/struct.dart
index d730b60..bb33de6 100644
--- a/filcnaplo/lib/database/struct.dart
+++ b/refilc/lib/database/struct.dart
@@ -1,30 +1,30 @@
-class DatabaseStruct {
-  final String table;
-  final Map<String, dynamic> struct;
-
-  const DatabaseStruct(this.table, this.struct);
-
-  String _toDBfield(String name, dynamic type) {
-    String typeName = "";
-
-    switch (type.runtimeType) {
-      case int:
-        typeName = "integer";
-        break;
-      case String:
-        typeName = "text";
-        break;
-    }
-
-    return "$name ${typeName.toUpperCase()} ${name == 'id' ? 'NOT NULL' : ''}";
-  }
-
-  @override
-  String toString() {
-    List<String> columns = [];
-    struct.forEach((key, value) {
-      columns.add(_toDBfield(key, value));
-    });
-    return columns.join(",");
-  }
-}
+class DatabaseStruct {
+  final String table;
+  final Map<String, dynamic> struct;
+
+  const DatabaseStruct(this.table, this.struct);
+
+  String _toDBfield(String name, dynamic type) {
+    String typeName = "";
+
+    switch (type.runtimeType) {
+      case int:
+        typeName = "integer";
+        break;
+      case String:
+        typeName = "text";
+        break;
+    }
+
+    return "$name ${typeName.toUpperCase()} ${name == 'id' ? 'NOT NULL' : ''}";
+  }
+
+  @override
+  String toString() {
+    List<String> columns = [];
+    struct.forEach((key, value) {
+      columns.add(_toDBfield(key, value));
+    });
+    return columns.join(",");
+  }
+}
diff --git a/filcnaplo/lib/helpers/attachment_helper.dart b/refilc/lib/helpers/attachment_helper.dart
similarity index 60%
rename from filcnaplo/lib/helpers/attachment_helper.dart
rename to refilc/lib/helpers/attachment_helper.dart
index 187bef7..44f2519 100644
--- a/filcnaplo/lib/helpers/attachment_helper.dart
+++ b/refilc/lib/helpers/attachment_helper.dart
@@ -1,56 +1,63 @@
-// ignore_for_file: use_build_context_synchronously
-
-import 'dart:io';
-import 'dart:typed_data';
-
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/storage_helper.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/attachment.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:flutter/widgets.dart';
-import 'package:open_file/open_file.dart';
-import 'package:provider/provider.dart';
-
-extension AttachmentHelper on Attachment {
-  Future<String> download(BuildContext context, {bool overwrite = false}) async {
-    String downloads = await StorageHelper.downloadsPath();
-
-    if (!overwrite && await File("$downloads/$name").exists()) return "$downloads/$name";
-
-    Uint8List data = await Provider.of<KretaClient>(context, listen: false).getAPI(downloadUrl, rawResponse: true);
-    if (!await StorageHelper.write("$downloads/$name", data)) return "";
-
-    return "$downloads/$name";
-  }
-
-  Future<bool> open(BuildContext context) async {
-    String downloads = await StorageHelper.downloadsPath();
-
-    if (!await File("$downloads/$name").exists()) await download(context);
-    var result = await OpenFile.open("$downloads/$name");
-    return result.type == ResultType.done;
-  }
-}
-
-extension HomeworkAttachmentHelper on HomeworkAttachment {
-  Future<String> download(BuildContext context, {bool overwrite = false}) async {
-    String downloads = await StorageHelper.downloadsPath();
-
-    if (!overwrite && await File("$downloads/$name").exists()) return "$downloads/$name";
-
-    String url = downloadUrl(Provider.of<UserProvider>(context, listen: false).instituteCode ?? "");
-    Uint8List data = await Provider.of<KretaClient>(context, listen: false).getAPI(url, rawResponse: true);
-    if (!await StorageHelper.write("$downloads/$name", data)) return "";
-
-    return "$downloads/$name";
-  }
-
-  Future<bool> open(BuildContext context) async {
-    String downloads = await StorageHelper.downloadsPath();
-
-    if (!await File("$downloads/$name").exists()) await download(context);
-    var result = await OpenFile.open("$downloads/$name");
-    return result.type == ResultType.done;
-  }
-}
+// ignore_for_file: use_build_context_synchronously
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/storage_helper.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/attachment.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:flutter/widgets.dart';
+import 'package:open_file/open_file.dart';
+import 'package:provider/provider.dart';
+
+extension AttachmentHelper on Attachment {
+  Future<String> download(BuildContext context,
+      {bool overwrite = false}) async {
+    String downloads = await StorageHelper.downloadsPath();
+
+    if (!overwrite && await File("$downloads/$name").exists())
+      return "$downloads/$name";
+
+    Uint8List data = await Provider.of<KretaClient>(context, listen: false)
+        .getAPI(downloadUrl, rawResponse: true);
+    if (!await StorageHelper.write("$downloads/$name", data)) return "";
+
+    return "$downloads/$name";
+  }
+
+  Future<bool> open(BuildContext context) async {
+    String downloads = await StorageHelper.downloadsPath();
+
+    if (!await File("$downloads/$name").exists()) await download(context);
+    var result = await OpenFile.open("$downloads/$name");
+    return result.type == ResultType.done;
+  }
+}
+
+extension HomeworkAttachmentHelper on HomeworkAttachment {
+  Future<String> download(BuildContext context,
+      {bool overwrite = false}) async {
+    String downloads = await StorageHelper.downloadsPath();
+
+    if (!overwrite && await File("$downloads/$name").exists())
+      return "$downloads/$name";
+
+    String url = downloadUrl(
+        Provider.of<UserProvider>(context, listen: false).instituteCode ?? "");
+    Uint8List data = await Provider.of<KretaClient>(context, listen: false)
+        .getAPI(url, rawResponse: true);
+    if (!await StorageHelper.write("$downloads/$name", data)) return "";
+
+    return "$downloads/$name";
+  }
+
+  Future<bool> open(BuildContext context) async {
+    String downloads = await StorageHelper.downloadsPath();
+
+    if (!await File("$downloads/$name").exists()) await download(context);
+    var result = await OpenFile.open("$downloads/$name");
+    return result.type == ResultType.done;
+  }
+}
diff --git a/filcnaplo/lib/helpers/average_helper.dart b/refilc/lib/helpers/average_helper.dart
similarity index 55%
rename from filcnaplo/lib/helpers/average_helper.dart
rename to refilc/lib/helpers/average_helper.dart
index 5de132d..7a7fb2f 100644
--- a/filcnaplo/lib/helpers/average_helper.dart
+++ b/refilc/lib/helpers/average_helper.dart
@@ -1,21 +1,25 @@
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-
-class AverageHelper {
-  static double averageEvals(List<Grade> grades, {bool finalAvg = false}) {
-    double average = 0.0;
-
-    List<String> ignoreInFinal = ["5,SzorgalomErtek", "4,MagatartasErtek"];
-
-    if (finalAvg) {
-      grades.removeWhere((e) => (e.value.value == 0) || (ignoreInFinal.contains(e.gradeType?.id)));
-    }
-
-    for (var e in grades) {
-      average += e.value.value * ((finalAvg ? 100 : e.value.weight) / 100);
-    }
-
-    average = average / grades.map((e) => (finalAvg ? 100 : e.value.weight) / 100).fold(0.0, (a, b) => a + b);
-
-    return average.isNaN ? 0.0 : average;
-  }
-}
+import 'package:refilc_kreta_api/models/grade.dart';
+
+class AverageHelper {
+  static double averageEvals(List<Grade> grades, {bool finalAvg = false}) {
+    double average = 0.0;
+
+    List<String> ignoreInFinal = ["5,SzorgalomErtek", "4,MagatartasErtek"];
+
+    if (finalAvg) {
+      grades.removeWhere((e) =>
+          (e.value.value == 0) || (ignoreInFinal.contains(e.gradeType?.id)));
+    }
+
+    for (var e in grades) {
+      average += e.value.value * ((finalAvg ? 100 : e.value.weight) / 100);
+    }
+
+    average = average /
+        grades
+            .map((e) => (finalAvg ? 100 : e.value.weight) / 100)
+            .fold(0.0, (a, b) => a + b);
+
+    return average.isNaN ? 0.0 : average;
+  }
+}
diff --git a/filcnaplo/lib/helpers/notification_helper.dart b/refilc/lib/helpers/notification_helper.dart
similarity index 96%
rename from filcnaplo/lib/helpers/notification_helper.dart
rename to refilc/lib/helpers/notification_helper.dart
index fd70e10..1a5ad96 100644
--- a/filcnaplo/lib/helpers/notification_helper.dart
+++ b/refilc/lib/helpers/notification_helper.dart
@@ -1,21 +1,21 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/helpers/notification_helper.i18n.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/status_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/helpers/notification_helper.i18n.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
 import 'package:flutter_local_notifications/flutter_local_notifications.dart'
     hide Message;
 import 'package:i18n_extension/i18n_widget.dart';
 import 'package:intl/intl.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
+import 'package:refilc_kreta_api/models/message.dart';
 
 class NotificationsHelper {
   late DatabaseProvider database;
diff --git a/filcnaplo/lib/helpers/notification_helper.i18n.dart b/refilc/lib/helpers/notification_helper.i18n.dart
similarity index 100%
rename from filcnaplo/lib/helpers/notification_helper.i18n.dart
rename to refilc/lib/helpers/notification_helper.i18n.dart
diff --git a/filcnaplo/lib/helpers/quick_actions.dart b/refilc/lib/helpers/quick_actions.dart
similarity index 58%
rename from filcnaplo/lib/helpers/quick_actions.dart
rename to refilc/lib/helpers/quick_actions.dart
index e894264..3512716 100644
--- a/filcnaplo/lib/helpers/quick_actions.dart
+++ b/refilc/lib/helpers/quick_actions.dart
@@ -1,36 +1,48 @@
-import 'package:flutter/cupertino.dart';
-import 'package:quick_actions/quick_actions.dart';
-import 'package:filcnaplo_mobile_ui/common/screens.i18n.dart';
-
-const QuickActions quickActions = QuickActions();
-
-void setupQuickActions() {
-  quickActions.setShortcutItems(<ShortcutItem>[
-    ShortcutItem(type: 'action_grades', localizedTitle: 'grades'.i18n, icon: 'ic_grades'),
-    ShortcutItem(type: 'action_timetable', localizedTitle: 'timetable'.i18n, icon: 'ic_timetable'),
-    ShortcutItem(type: 'action_messages', localizedTitle: 'messages'.i18n, icon: 'ic_messages'),
-    ShortcutItem(type: 'action_absences', localizedTitle: 'absences'.i18n, icon: 'ic_absences')
-  ]);
-}
-
-void handleQuickActions(BuildContext context, void Function(String) callback) {
-  quickActions.initialize((shortcutType) {
-    switch (shortcutType) {
-      case 'action_home':
-        callback("home");
-        break;
-      case 'action_grades':
-        callback("grades");
-        break;
-      case 'action_timetable':
-        callback("timetable");
-        break;
-      case 'action_messages':
-        callback("messages");
-        break;
-      case 'action_absences':
-        callback("absences");
-        break;
-    }
-  });
-}
+import 'package:flutter/cupertino.dart';
+import 'package:quick_actions/quick_actions.dart';
+import 'package:refilc_mobile_ui/common/screens.i18n.dart';
+
+const QuickActions quickActions = QuickActions();
+
+void setupQuickActions() {
+  quickActions.setShortcutItems(<ShortcutItem>[
+    ShortcutItem(
+        type: 'action_grades',
+        localizedTitle: 'grades'.i18n,
+        icon: 'ic_grades'),
+    ShortcutItem(
+        type: 'action_timetable',
+        localizedTitle: 'timetable'.i18n,
+        icon: 'ic_timetable'),
+    ShortcutItem(
+        type: 'action_messages',
+        localizedTitle: 'messages'.i18n,
+        icon: 'ic_messages'),
+    ShortcutItem(
+        type: 'action_absences',
+        localizedTitle: 'absences'.i18n,
+        icon: 'ic_absences')
+  ]);
+}
+
+void handleQuickActions(BuildContext context, void Function(String) callback) {
+  quickActions.initialize((shortcutType) {
+    switch (shortcutType) {
+      case 'action_home':
+        callback("home");
+        break;
+      case 'action_grades':
+        callback("grades");
+        break;
+      case 'action_timetable':
+        callback("timetable");
+        break;
+      case 'action_messages':
+        callback("messages");
+        break;
+      case 'action_absences':
+        callback("absences");
+        break;
+    }
+  });
+}
diff --git a/filcnaplo/lib/helpers/share_helper.dart b/refilc/lib/helpers/share_helper.dart
similarity index 50%
rename from filcnaplo/lib/helpers/share_helper.dart
rename to refilc/lib/helpers/share_helper.dart
index 9b27793..b5884a3 100644
--- a/filcnaplo/lib/helpers/share_helper.dart
+++ b/refilc/lib/helpers/share_helper.dart
@@ -1,15 +1,18 @@
-import 'package:filcnaplo/helpers/attachment_helper.dart';
-import 'package:filcnaplo_kreta_api/models/attachment.dart';
-import 'package:flutter/widgets.dart';
-import 'package:share_plus/share_plus.dart';
-
-class ShareHelper {
-  static Future<void> shareText(String text, {String? subject}) => Share.share(text, subject: subject);
-  // ignore: deprecated_member_use
-  static Future<void> shareFile(String path, {String? text, String? subject}) => Share.shareFiles([path], text: text, subject: subject);
-
-  static Future<void> shareAttachment(Attachment attachment, {required BuildContext context}) async {
-    String path = await attachment.download(context);
-    await shareFile(path);
-  }
-}
+import 'package:refilc/helpers/attachment_helper.dart';
+import 'package:refilc_kreta_api/models/attachment.dart';
+import 'package:flutter/widgets.dart';
+import 'package:share_plus/share_plus.dart';
+
+class ShareHelper {
+  static Future<void> shareText(String text, {String? subject}) =>
+      Share.share(text, subject: subject);
+  // ignore: deprecated_member_use
+  static Future<void> shareFile(String path, {String? text, String? subject}) =>
+      Share.shareFiles([path], text: text, subject: subject);
+
+  static Future<void> shareAttachment(Attachment attachment,
+      {required BuildContext context}) async {
+    String path = await attachment.download(context);
+    await shareFile(path);
+  }
+}
diff --git a/filcnaplo/lib/helpers/storage_helper.dart b/refilc/lib/helpers/storage_helper.dart
similarity index 96%
rename from filcnaplo/lib/helpers/storage_helper.dart
rename to refilc/lib/helpers/storage_helper.dart
index 349a3c4..a94c0cd 100644
--- a/filcnaplo/lib/helpers/storage_helper.dart
+++ b/refilc/lib/helpers/storage_helper.dart
@@ -1,39 +1,39 @@
-// ignore_for_file: avoid_print
-
-import 'dart:io';
-import 'dart:typed_data';
-
-import 'package:path_provider/path_provider.dart';
-import 'package:permission_handler/permission_handler.dart';
-
-class StorageHelper {
-  static Future<bool> write(String path, Uint8List data) async {
-    try {
-      if (await Permission.manageExternalStorage.request().isGranted) {
-        await File(path).writeAsBytes(data);
-        return true;
-      } else {
-        if (await Permission.storage.isPermanentlyDenied) {
-          openAppSettings();
-        }
-        return false;
-      }
-    } catch (error) {
-      print("ERROR: StorageHelper.write: $error");
-      return false;
-    }
-  }
-
-  static Future<String> downloadsPath() async {
-    String downloads;
-
-    if (Platform.isAndroid) {
-      downloads = "/storage/self/primary/Download";
-    } else {
-      downloads = (await getTemporaryDirectory()).path;
-    }
-
-    return downloads;
-    // return (await getTemporaryDirectory()).path;
-  }
-}
+// ignore_for_file: avoid_print
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:path_provider/path_provider.dart';
+import 'package:permission_handler/permission_handler.dart';
+
+class StorageHelper {
+  static Future<bool> write(String path, Uint8List data) async {
+    try {
+      if (await Permission.manageExternalStorage.request().isGranted) {
+        await File(path).writeAsBytes(data);
+        return true;
+      } else {
+        if (await Permission.storage.isPermanentlyDenied) {
+          openAppSettings();
+        }
+        return false;
+      }
+    } catch (error) {
+      print("ERROR: StorageHelper.write: $error");
+      return false;
+    }
+  }
+
+  static Future<String> downloadsPath() async {
+    String downloads;
+
+    if (Platform.isAndroid) {
+      downloads = "/storage/self/primary/Download";
+    } else {
+      downloads = (await getTemporaryDirectory()).path;
+    }
+
+    return downloads;
+    // return (await getTemporaryDirectory()).path;
+  }
+}
diff --git a/refilc/lib/helpers/subject.dart b/refilc/lib/helpers/subject.dart
new file mode 100644
index 0000000..3688548
--- /dev/null
+++ b/refilc/lib/helpers/subject.dart
@@ -0,0 +1,273 @@
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc/models/icon_pack.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+typedef SubjectIconVariants = Map<IconPack, IconData>;
+
+class SubjectIconData {
+  final SubjectIconVariants data;
+  final String name; // for iOS live activities compatibilty
+
+  SubjectIconData({
+    this.data = const {
+      IconPack.material: Icons.widgets_outlined,
+      IconPack.cupertino: CupertinoIcons.rectangle_grid_2x2,
+    },
+    this.name = "square.grid.2x2",
+  });
+}
+
+SubjectIconVariants createIcon(
+    {required IconData material, required IconData cupertino}) {
+  return {
+    IconPack.material: material,
+    IconPack.cupertino: cupertino,
+  };
+}
+
+class SubjectIcon {
+  static String resolveName({Subject? subject, String? subjectName}) =>
+      _resolve(subject: subject, subjectName: subjectName).name;
+  static IconData resolveVariant(
+          {Subject? subject,
+          String? subjectName,
+          required BuildContext context}) =>
+      _resolve(subject: subject, subjectName: subjectName).data[
+          Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
+
+  static SubjectIconData _resolve({Subject? subject, String? subjectName}) {
+    assert(!(subject == null && subjectName == null));
+
+    String name = (subject?.name ?? subjectName ?? "")
+        .toLowerCase()
+        .specialChars()
+        .trim();
+    String category =
+        subject?.category.description.toLowerCase().specialChars() ?? "";
+
+    // todo: check for categories
+    if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.function,
+              material: Icons.calculate_outlined),
+          name: "function");
+    } else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.textformat_alt,
+              material: Icons.spellcheck_outlined),
+          name: "textformat.alt");
+    } else if (RegExp("irodalom").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.book,
+              material: Icons.menu_book_outlined),
+          name: "book");
+    } else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.compass,
+              material: Icons.hourglass_empty_outlined),
+          name: "safari");
+    } else if (RegExp("foldrajz").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.map, material: Icons.public_outlined),
+          name: "map");
+    } else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.paintbrush,
+              material: Icons.palette_outlined),
+          name: "paintbrush");
+    } else if (RegExp("fizika").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.lightbulb,
+              material: Icons.emoji_objects_outlined),
+          name: "lightbulb");
+    } else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.music_note,
+              material: Icons.music_note_outlined),
+          name: "music.note");
+    } else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.sportscourt,
+              material: Icons.sports_soccer_outlined),
+          name: "sportscourt");
+    } else if (RegExp("kemia").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.lab_flask,
+              material: Icons.science_outlined),
+          name: "testtube.2");
+    } else if (RegExp("biologia").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.paw, material: Icons.pets_outlined),
+          name: "pawprint");
+    } else if (RegExp(
+            "kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret")
+        .hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.arrow_3_trianglepath,
+              material: Icons.eco_outlined),
+          name: "arrow.3.trianglepath");
+    } else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.heart,
+              material: Icons.favorite_border_outlined),
+          name: "heart");
+    } else if (RegExp("penzugy").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.money_dollar,
+              material: Icons.savings_outlined),
+          name: "dollarsign");
+    } else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.device_laptop,
+              material: Icons.computer_outlined),
+          name: "laptopcomputer");
+    } else if (RegExp("prog").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.chevron_left_slash_chevron_right,
+              material: Icons.code_outlined),
+          name: "chevron.left.forwardslash.chevron.right");
+    } else if (RegExp("halozat").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.antenna_radiowaves_left_right,
+              material: Icons.wifi_tethering_outlined),
+          name: "antenna.radiowaves.left.and.right");
+    } else if (RegExp("szinhaz").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.hifispeaker,
+              material: Icons.theater_comedy_outlined),
+          name: "hifispeaker");
+    } else if (RegExp("film|media").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.film,
+              material: Icons.theaters_outlined),
+          name: "film");
+    } else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.bolt,
+              material: Icons.electrical_services_outlined),
+          name: "bolt");
+    } else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.wrench,
+              material: Icons.precision_manufacturing_outlined),
+          name: "wrench");
+    } else if (RegExp("technika").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.hammer, material: Icons.build_outlined),
+          name: "hammer");
+    } else if (RegExp("tanc").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.music_mic,
+              material: Icons.speaker_outlined),
+          name: "music.mic");
+    } else if (RegExp("filozofia").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.bubble_left,
+              material: Icons.psychology_outlined),
+          name: "bubble.left");
+    } else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) ||
+        name == "ofo") {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.group, material: Icons.groups_outlined),
+          name: "person.3");
+    } else if (RegExp("gazdasag").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.chart_pie,
+              material: Icons.account_balance_outlined),
+          name: "chart.pie");
+    } else if (RegExp("szorgalom").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.checkmark_seal,
+              material: Icons.verified_outlined),
+          name: "checkmark.seal");
+    } else if (RegExp("magatartas").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.smiley,
+              material: Icons.emoji_people_outlined),
+          name: "face.smiling");
+    } else if (RegExp(
+            "angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv")
+        .hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              cupertino: CupertinoIcons.globe,
+              material: Icons.translate_outlined),
+          name: "globe");
+    } else if (RegExp("linux").hasMatch(name)) {
+      return SubjectIconData(
+          data: createIcon(
+              material: FilcIcons.linux, cupertino: FilcIcons.linux));
+    }
+
+    return SubjectIconData();
+  }
+}
+
+class ShortSubject {
+  static String resolve({Subject? subject, String? subjectName}) {
+    assert(!(subject == null && subjectName == null));
+
+    String name = (subject?.name ?? subjectName ?? "")
+        .toLowerCase()
+        .specialChars()
+        .trim();
+    // String category = subject?.category.description.toLowerCase().specialChars() ?? "";
+
+    if (RegExp("magyar irodalom").hasMatch(name)) {
+      return "Irodalom";
+    } else if (RegExp("magyar nyelv").hasMatch(name)) {
+      return "Nyelvtan";
+    } else if (RegExp("matematika").hasMatch(name)) {
+      return "Matek";
+    } else if (RegExp("digitalis kultura").hasMatch(name)) {
+      return "Dig. kult.";
+    } else if (RegExp("testneveles").hasMatch(name)) {
+      return "Tesi";
+    } else if (RegExp("tortenelem").hasMatch(name)) {
+      return "Töri";
+    } else if (RegExp(
+            "(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv")
+        .hasMatch(name)) {
+      return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", "");
+    } else if (RegExp("informatika").hasMatch(name)) {
+      return "Infó";
+    } else if (RegExp("osztalyfonoki").hasMatch(name)) {
+      return "Ofő";
+    }
+
+    return subject?.name.capital() ?? subjectName?.capital() ?? "?";
+  }
+}
diff --git a/filcnaplo/lib/helpers/update_helper.dart b/refilc/lib/helpers/update_helper.dart
similarity index 90%
rename from filcnaplo/lib/helpers/update_helper.dart
rename to refilc/lib/helpers/update_helper.dart
index 0c33860..a2e5c3c 100644
--- a/filcnaplo/lib/helpers/update_helper.dart
+++ b/refilc/lib/helpers/update_helper.dart
@@ -1,80 +1,80 @@
-import 'dart:async';
-import 'dart:io';
-import 'dart:typed_data';
-
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/helpers/storage_helper.dart';
-import 'package:filcnaplo/models/release.dart';
-import 'package:open_file/open_file.dart';
-import 'package:permission_handler/permission_handler.dart';
-
-enum UpdateState { none, preparing, downloading, installing }
-
-typedef UpdateCallback = Function(double progress, UpdateState state);
-
-// ignore: todo
-// TODO: cleanup old apk files
-
-extension UpdateHelper on Release {
-  Future<void> install({UpdateCallback? updateCallback}) async {
-    updateCallback!(-1, UpdateState.preparing);
-
-    String downloads = await StorageHelper.downloadsPath();
-    File apk = File("$downloads/refilc-v$version.apk");
-
-    if (!await apk.exists()) {
-      updateCallback(-1, UpdateState.downloading);
-
-      var bytes = await download(updateCallback: updateCallback);
-      if (!await StorageHelper.write(apk.path, bytes)) {
-        throw "failed to write apk: permission denied";
-      }
-    }
-
-    updateCallback(-1, UpdateState.installing);
-
-    var installPerms =
-        (await Permission.manageExternalStorage.request().isGranted &&
-            await Permission.requestInstallPackages.request().isGranted);
-    if (installPerms) {
-      var result = await OpenFile.open(apk.path);
-
-      if (result.type != ResultType.done) {
-        // ignore: avoid_print
-        print("ERROR: installUpdate.openFile: ${result.message}");
-        throw result.message;
-      }
-    }
-
-    updateCallback(-1, UpdateState.none);
-  }
-
-  Future<Uint8List> download({UpdateCallback? updateCallback}) async {
-    var response = await FilcAPI.downloadRelease(downloads.first);
-
-    List<List<int>> chunks = [];
-    int downloaded = 0;
-
-    var completer = Completer<Uint8List>();
-
-    response?.stream.listen((List<int> chunk) {
-      updateCallback!(
-          downloaded / (response.contentLength ?? 0), UpdateState.downloading);
-
-      chunks.add(chunk);
-      downloaded += chunk.length;
-    }, onDone: () {
-      // Save the file
-      final Uint8List bytes = Uint8List(response.contentLength ?? 0);
-      int offset = 0;
-      for (List<int> chunk in chunks) {
-        bytes.setRange(offset, offset + chunk.length, chunk);
-        offset += chunk.length;
-      }
-
-      completer.complete(bytes);
-    });
-
-    return completer.future;
-  }
-}
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:refilc/api/client.dart';
+import 'package:refilc/helpers/storage_helper.dart';
+import 'package:refilc/models/release.dart';
+import 'package:open_file/open_file.dart';
+import 'package:permission_handler/permission_handler.dart';
+
+enum UpdateState { none, preparing, downloading, installing }
+
+typedef UpdateCallback = Function(double progress, UpdateState state);
+
+// ignore: todo
+// TODO: cleanup old apk files
+
+extension UpdateHelper on Release {
+  Future<void> install({UpdateCallback? updateCallback}) async {
+    updateCallback!(-1, UpdateState.preparing);
+
+    String downloads = await StorageHelper.downloadsPath();
+    File apk = File("$downloads/refilc-v$version.apk");
+
+    if (!await apk.exists()) {
+      updateCallback(-1, UpdateState.downloading);
+
+      var bytes = await download(updateCallback: updateCallback);
+      if (!await StorageHelper.write(apk.path, bytes)) {
+        throw "failed to write apk: permission denied";
+      }
+    }
+
+    updateCallback(-1, UpdateState.installing);
+
+    var installPerms =
+        (await Permission.manageExternalStorage.request().isGranted &&
+            await Permission.requestInstallPackages.request().isGranted);
+    if (installPerms) {
+      var result = await OpenFile.open(apk.path);
+
+      if (result.type != ResultType.done) {
+        // ignore: avoid_print
+        print("ERROR: installUpdate.openFile: ${result.message}");
+        throw result.message;
+      }
+    }
+
+    updateCallback(-1, UpdateState.none);
+  }
+
+  Future<Uint8List> download({UpdateCallback? updateCallback}) async {
+    var response = await FilcAPI.downloadRelease(downloads.first);
+
+    List<List<int>> chunks = [];
+    int downloaded = 0;
+
+    var completer = Completer<Uint8List>();
+
+    response?.stream.listen((List<int> chunk) {
+      updateCallback!(
+          downloaded / (response.contentLength ?? 0), UpdateState.downloading);
+
+      chunks.add(chunk);
+      downloaded += chunk.length;
+    }, onDone: () {
+      // Save the file
+      final Uint8List bytes = Uint8List(response.contentLength ?? 0);
+      int offset = 0;
+      for (List<int> chunk in chunks) {
+        bytes.setRange(offset, offset + chunk.length, chunk);
+        offset += chunk.length;
+      }
+
+      completer.complete(bytes);
+    });
+
+    return completer.future;
+  }
+}
diff --git a/filcnaplo/lib/icons/filc_icons.dart b/refilc/lib/icons/filc_icons.dart
similarity index 96%
rename from filcnaplo/lib/icons/filc_icons.dart
rename to refilc/lib/icons/filc_icons.dart
index dea6207..9063627 100644
--- a/filcnaplo/lib/icons/filc_icons.dart
+++ b/refilc/lib/icons/filc_icons.dart
@@ -1,46 +1,46 @@
-import 'package:flutter/widgets.dart';
-
-class FilcIcons {
-  FilcIcons._();
-
-  static const iconFontFamily = 'FilcIcons';
-
-  /// home
-  static const IconData home = IconData(0x21, fontFamily: iconFontFamily);
-
-  /// linux
-  static const IconData linux = IconData(0x22, fontFamily: iconFontFamily);
-
-  /// upstairs
-  static const IconData upstairs = IconData(0x23, fontFamily: iconFontFamily);
-
-  /// downstairs
-  static const IconData downstairs = IconData(0x24, fontFamily: iconFontFamily);
-
-  /// premium
-  static const IconData premium = IconData(0x25, fontFamily: iconFontFamily);
-
-  /// tinta
-  static const IconData tinta = IconData(0x26, fontFamily: iconFontFamily);
-
-  /// kupak
-  static const IconData kupak = IconData(0x27, fontFamily: iconFontFamily);
-
-  /// homefill
-  static const IconData homefill = IconData(0x28, fontFamily: iconFontFamily);
-
-  /// gradesfill
-  static const IconData gradesfill = IconData(0x29, fontFamily: iconFontFamily);
-
-  /// timetablefill
-  static const IconData timetablefill =
-      IconData(0x2a, fontFamily: iconFontFamily);
-
-  /// messagesfill
-  static const IconData messagesfill =
-      IconData(0x2b, fontFamily: iconFontFamily);
-
-  /// absencesfill
-  static const IconData absencesfill =
-      IconData(0x2c, fontFamily: iconFontFamily);
-}
+import 'package:flutter/widgets.dart';
+
+class FilcIcons {
+  FilcIcons._();
+
+  static const iconFontFamily = 'FilcIcons';
+
+  /// home
+  static const IconData home = IconData(0x21, fontFamily: iconFontFamily);
+
+  /// linux
+  static const IconData linux = IconData(0x22, fontFamily: iconFontFamily);
+
+  /// upstairs
+  static const IconData upstairs = IconData(0x23, fontFamily: iconFontFamily);
+
+  /// downstairs
+  static const IconData downstairs = IconData(0x24, fontFamily: iconFontFamily);
+
+  /// premium
+  static const IconData premium = IconData(0x25, fontFamily: iconFontFamily);
+
+  /// tinta
+  static const IconData tinta = IconData(0x26, fontFamily: iconFontFamily);
+
+  /// kupak
+  static const IconData kupak = IconData(0x27, fontFamily: iconFontFamily);
+
+  /// homefill
+  static const IconData homefill = IconData(0x28, fontFamily: iconFontFamily);
+
+  /// gradesfill
+  static const IconData gradesfill = IconData(0x29, fontFamily: iconFontFamily);
+
+  /// timetablefill
+  static const IconData timetablefill =
+      IconData(0x2a, fontFamily: iconFontFamily);
+
+  /// messagesfill
+  static const IconData messagesfill =
+      IconData(0x2b, fontFamily: iconFontFamily);
+
+  /// absencesfill
+  static const IconData absencesfill =
+      IconData(0x2c, fontFamily: iconFontFamily);
+}
diff --git a/filcnaplo/lib/main.dart b/refilc/lib/main.dart
similarity index 90%
rename from filcnaplo/lib/main.dart
rename to refilc/lib/main.dart
index 9ceab63..4451170 100644
--- a/filcnaplo/lib/main.dart
+++ b/refilc/lib/main.dart
@@ -1,197 +1,197 @@
-import 'dart:io';
-
-import 'package:background_fetch/background_fetch.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/database/init.dart';
-import 'package:filcnaplo/helpers/notification_helper.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/app.dart';
-import 'package:flutter/services.dart';
-import 'package:filcnaplo_mobile_ui/screens/error_screen.dart';
-import 'package:filcnaplo_mobile_ui/screens/error_report_screen.dart';
-import 'package:flutter_local_notifications/flutter_local_notifications.dart';
-
-void main() async {
-  // Initalize
-  WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
-  binding.renderView.automaticSystemUiAdjustment = false;
-  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
-  // Startup
-  Startup startup = Startup();
-  await startup.start();
-
-  // Custom error page
-  ErrorWidget.builder = errorBuilder;
-
-  BackgroundFetch.registerHeadlessTask(backgroundHeadlessTask);
-
-  // Run App
-  runApp(App(
-    database: startup.database,
-    settings: startup.settings,
-    user: startup.user,
-  ));
-}
-
-class Startup {
-  late SettingsProvider settings;
-  late UserProvider user;
-  late DatabaseProvider database;
-
-  Future<void> start() async {
-    database = DatabaseProvider();
-    var db = await initDB(database);
-    await db.close();
-    await database.init();
-    settings = await database.query.getSettings(database);
-    user = await database.query.getUsers(settings);
-
-    late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
-    // Notifications setup
-    if (!kIsWeb) {
-      initPlatformState();
-      flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
-    }
-
-    // Get permission to show notifications
-    if (kIsWeb) {
-      // do nothing
-    } else if (Platform.isAndroid) {
-      await flutterLocalNotificationsPlugin
-          .resolvePlatformSpecificImplementation<
-              AndroidFlutterLocalNotificationsPlugin>()!
-          .requestPermission();
-    } else if (Platform.isIOS) {
-      await flutterLocalNotificationsPlugin
-          .resolvePlatformSpecificImplementation<
-              IOSFlutterLocalNotificationsPlugin>()
-          ?.requestPermissions(
-            alert: false,
-            badge: true,
-            sound: true,
-          );
-    } else if (Platform.isMacOS) {
-      await flutterLocalNotificationsPlugin
-          .resolvePlatformSpecificImplementation<
-              MacOSFlutterLocalNotificationsPlugin>()
-          ?.requestPermissions(
-            alert: false,
-            badge: true,
-            sound: true,
-          );
-    } else if (Platform.isLinux) {
-      // no permissions are needed on linux
-    }
-
-    // Platform specific settings
-    if (!kIsWeb) {
-      const DarwinInitializationSettings initializationSettingsDarwin =
-          DarwinInitializationSettings(
-        requestSoundPermission: true,
-        requestBadgePermission: true,
-        requestAlertPermission: false,
-      );
-      const AndroidInitializationSettings initializationSettingsAndroid =
-          AndroidInitializationSettings('ic_notification');
-      const LinuxInitializationSettings initializationSettingsLinux =
-          LinuxInitializationSettings(defaultActionName: 'Open notification');
-      const InitializationSettings initializationSettings =
-          InitializationSettings(
-        android: initializationSettingsAndroid,
-        iOS: initializationSettingsDarwin,
-        macOS: initializationSettingsDarwin,
-        linux: initializationSettingsLinux,
-      );
-
-      // Initialize notifications
-      await flutterLocalNotificationsPlugin.initialize(
-        initializationSettings,
-      );
-    }
-  }
-}
-
-bool errorShown = false;
-String lastException = '';
-
-Widget errorBuilder(FlutterErrorDetails details) {
-  return Builder(builder: (context) {
-    if (Navigator.of(context).canPop()) Navigator.pop(context);
-
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      if (!errorShown && details.exceptionAsString() != lastException) {
-        errorShown = true;
-        lastException = details.exceptionAsString();
-        Navigator.of(context, rootNavigator: true)
-            .push(MaterialPageRoute(builder: (context) {
-          if (kReleaseMode) {
-            return ErrorReportScreen(details);
-          } else {
-            return ErrorScreen(details);
-          }
-        })).then((_) => errorShown = false);
-      }
-    });
-
-    return Container();
-  });
-}
-
-Future<void> initPlatformState() async {
-  // Configure BackgroundFetch.
-  int status = await BackgroundFetch.configure(
-      BackgroundFetchConfig(
-          minimumFetchInterval: 15,
-          stopOnTerminate: false,
-          enableHeadless: true,
-          requiresBatteryNotLow: false,
-          requiresCharging: false,
-          requiresStorageNotLow: false,
-          requiresDeviceIdle: false,
-          requiredNetworkType: NetworkType.ANY,
-          startOnBoot: true), (String taskId) async {
-    // <-- Event handler
-    if (kDebugMode) {
-      print("[BackgroundFetch] Event received $taskId");
-    }
-    NotificationsHelper().backgroundJob();
-    BackgroundFetch.finish(taskId);
-  }, (String taskId) async {
-    // <-- Task timeout handler.
-    if (kDebugMode) {
-      print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
-    }
-    BackgroundFetch.finish(taskId);
-  });
-  if (kDebugMode) {
-    print('[BackgroundFetch] configure success: $status');
-  }
-  BackgroundFetch.scheduleTask(TaskConfig(
-      taskId: "com.transistorsoft.refilcnotification",
-      delay: 900000, // 15 minutes
-      periodic: true,
-      forceAlarmManager: true,
-      stopOnTerminate: false,
-      enableHeadless: true));
-}
-
-@pragma('vm:entry-point')
-void backgroundHeadlessTask(HeadlessTask task) {
-  String taskId = task.taskId;
-  bool isTimeout = task.timeout;
-  if (isTimeout) {
-    if (kDebugMode) {
-      print("[BackgroundFetch] Headless task timed-out: $taskId");
-    }
-    BackgroundFetch.finish(taskId);
-    return;
-  }
-  if (kDebugMode) {
-    print('[BackgroundFetch] Headless event received.');
-  }
-  NotificationsHelper().backgroundJob();
-  BackgroundFetch.finish(task.taskId);
-}
+import 'dart:io';
+
+import 'package:background_fetch/background_fetch.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/database/init.dart';
+import 'package:refilc/helpers/notification_helper.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/app.dart';
+import 'package:flutter/services.dart';
+import 'package:refilc_mobile_ui/screens/error_screen.dart';
+import 'package:refilc_mobile_ui/screens/error_report_screen.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+
+void main() async {
+  // Initalize
+  WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
+  binding.renderView.automaticSystemUiAdjustment = false;
+  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
+  // Startup
+  Startup startup = Startup();
+  await startup.start();
+
+  // Custom error page
+  ErrorWidget.builder = errorBuilder;
+
+  BackgroundFetch.registerHeadlessTask(backgroundHeadlessTask);
+
+  // Run App
+  runApp(App(
+    database: startup.database,
+    settings: startup.settings,
+    user: startup.user,
+  ));
+}
+
+class Startup {
+  late SettingsProvider settings;
+  late UserProvider user;
+  late DatabaseProvider database;
+
+  Future<void> start() async {
+    database = DatabaseProvider();
+    var db = await initDB(database);
+    await db.close();
+    await database.init();
+    settings = await database.query.getSettings(database);
+    user = await database.query.getUsers(settings);
+
+    late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
+    // Notifications setup
+    if (!kIsWeb) {
+      initPlatformState();
+      flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
+    }
+
+    // Get permission to show notifications
+    if (kIsWeb) {
+      // do nothing
+    } else if (Platform.isAndroid) {
+      await flutterLocalNotificationsPlugin
+          .resolvePlatformSpecificImplementation<
+              AndroidFlutterLocalNotificationsPlugin>()!
+          .requestPermission();
+    } else if (Platform.isIOS) {
+      await flutterLocalNotificationsPlugin
+          .resolvePlatformSpecificImplementation<
+              IOSFlutterLocalNotificationsPlugin>()
+          ?.requestPermissions(
+            alert: false,
+            badge: true,
+            sound: true,
+          );
+    } else if (Platform.isMacOS) {
+      await flutterLocalNotificationsPlugin
+          .resolvePlatformSpecificImplementation<
+              MacOSFlutterLocalNotificationsPlugin>()
+          ?.requestPermissions(
+            alert: false,
+            badge: true,
+            sound: true,
+          );
+    } else if (Platform.isLinux) {
+      // no permissions are needed on linux
+    }
+
+    // Platform specific settings
+    if (!kIsWeb) {
+      const DarwinInitializationSettings initializationSettingsDarwin =
+          DarwinInitializationSettings(
+        requestSoundPermission: true,
+        requestBadgePermission: true,
+        requestAlertPermission: false,
+      );
+      const AndroidInitializationSettings initializationSettingsAndroid =
+          AndroidInitializationSettings('ic_notification');
+      const LinuxInitializationSettings initializationSettingsLinux =
+          LinuxInitializationSettings(defaultActionName: 'Open notification');
+      const InitializationSettings initializationSettings =
+          InitializationSettings(
+        android: initializationSettingsAndroid,
+        iOS: initializationSettingsDarwin,
+        macOS: initializationSettingsDarwin,
+        linux: initializationSettingsLinux,
+      );
+
+      // Initialize notifications
+      await flutterLocalNotificationsPlugin.initialize(
+        initializationSettings,
+      );
+    }
+  }
+}
+
+bool errorShown = false;
+String lastException = '';
+
+Widget errorBuilder(FlutterErrorDetails details) {
+  return Builder(builder: (context) {
+    if (Navigator.of(context).canPop()) Navigator.pop(context);
+
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      if (!errorShown && details.exceptionAsString() != lastException) {
+        errorShown = true;
+        lastException = details.exceptionAsString();
+        Navigator.of(context, rootNavigator: true)
+            .push(MaterialPageRoute(builder: (context) {
+          if (kReleaseMode) {
+            return ErrorReportScreen(details);
+          } else {
+            return ErrorScreen(details);
+          }
+        })).then((_) => errorShown = false);
+      }
+    });
+
+    return Container();
+  });
+}
+
+Future<void> initPlatformState() async {
+  // Configure BackgroundFetch.
+  int status = await BackgroundFetch.configure(
+      BackgroundFetchConfig(
+          minimumFetchInterval: 15,
+          stopOnTerminate: false,
+          enableHeadless: true,
+          requiresBatteryNotLow: false,
+          requiresCharging: false,
+          requiresStorageNotLow: false,
+          requiresDeviceIdle: false,
+          requiredNetworkType: NetworkType.ANY,
+          startOnBoot: true), (String taskId) async {
+    // <-- Event handler
+    if (kDebugMode) {
+      print("[BackgroundFetch] Event received $taskId");
+    }
+    NotificationsHelper().backgroundJob();
+    BackgroundFetch.finish(taskId);
+  }, (String taskId) async {
+    // <-- Task timeout handler.
+    if (kDebugMode) {
+      print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
+    }
+    BackgroundFetch.finish(taskId);
+  });
+  if (kDebugMode) {
+    print('[BackgroundFetch] configure success: $status');
+  }
+  BackgroundFetch.scheduleTask(TaskConfig(
+      taskId: "com.transistorsoft.refilcnotification",
+      delay: 900000, // 15 minutes
+      periodic: true,
+      forceAlarmManager: true,
+      stopOnTerminate: false,
+      enableHeadless: true));
+}
+
+@pragma('vm:entry-point')
+void backgroundHeadlessTask(HeadlessTask task) {
+  String taskId = task.taskId;
+  bool isTimeout = task.timeout;
+  if (isTimeout) {
+    if (kDebugMode) {
+      print("[BackgroundFetch] Headless task timed-out: $taskId");
+    }
+    BackgroundFetch.finish(taskId);
+    return;
+  }
+  if (kDebugMode) {
+    print('[BackgroundFetch] Headless event received.');
+  }
+  NotificationsHelper().backgroundJob();
+  BackgroundFetch.finish(task.taskId);
+}
diff --git a/filcnaplo/lib/models/ad.dart b/refilc/lib/models/ad.dart
similarity index 100%
rename from filcnaplo/lib/models/ad.dart
rename to refilc/lib/models/ad.dart
diff --git a/filcnaplo/lib/models/config.dart b/refilc/lib/models/config.dart
similarity index 95%
rename from filcnaplo/lib/models/config.dart
rename to refilc/lib/models/config.dart
index 1cc2557..fdbc12c 100644
--- a/filcnaplo/lib/models/config.dart
+++ b/refilc/lib/models/config.dart
@@ -1,41 +1,41 @@
-import 'dart:io';
-
-class Config {
-  String _userAgent;
-  Map? json;
-  static const String _version =
-      String.fromEnvironment("APPVER", defaultValue: "3.0.4");
-
-  Config({required String userAgent, this.json}) : _userAgent = userAgent;
-
-  factory Config.fromJson(Map json) {
-    return Config(
-      userAgent: json["user_agent"] ?? "hu.ekreta.student/\$0/\$1/\$2",
-      json: json,
-    );
-  }
-
-  String get userAgent => _userAgent
-      .replaceAll("\$0", _version)
-      .replaceAll("\$1", platform)
-      .replaceAll("\$2", "0");
-
-  static String get platform {
-    if (Platform.isAndroid) {
-      return "Android";
-    } else if (Platform.isIOS) {
-      return "iOS";
-    } else if (Platform.isLinux) {
-      return "Linux";
-    } else if (Platform.isWindows) {
-      return "Windows";
-    } else if (Platform.isMacOS) {
-      return "MacOS";
-    } else {
-      return "Unknown";
-    }
-  }
-
-  @override
-  String toString() => json.toString();
-}
+import 'dart:io';
+
+class Config {
+  String _userAgent;
+  Map? json;
+  static const String _version =
+      String.fromEnvironment("APPVER", defaultValue: "3.0.4");
+
+  Config({required String userAgent, this.json}) : _userAgent = userAgent;
+
+  factory Config.fromJson(Map json) {
+    return Config(
+      userAgent: json["user_agent"] ?? "hu.ekreta.student/\$0/\$1/\$2",
+      json: json,
+    );
+  }
+
+  String get userAgent => _userAgent
+      .replaceAll("\$0", _version)
+      .replaceAll("\$1", platform)
+      .replaceAll("\$2", "0");
+
+  static String get platform {
+    if (Platform.isAndroid) {
+      return "Android";
+    } else if (Platform.isIOS) {
+      return "iOS";
+    } else if (Platform.isLinux) {
+      return "Linux";
+    } else if (Platform.isWindows) {
+      return "Windows";
+    } else if (Platform.isMacOS) {
+      return "MacOS";
+    } else {
+      return "Unknown";
+    }
+  }
+
+  @override
+  String toString() => json.toString();
+}
diff --git a/filcnaplo/lib/models/icon_pack.dart b/refilc/lib/models/icon_pack.dart
similarity index 97%
rename from filcnaplo/lib/models/icon_pack.dart
rename to refilc/lib/models/icon_pack.dart
index 5fed429..4435c14 100644
--- a/filcnaplo/lib/models/icon_pack.dart
+++ b/refilc/lib/models/icon_pack.dart
@@ -1 +1 @@
-enum IconPack { material, cupertino }
+enum IconPack { material, cupertino }
diff --git a/filcnaplo/lib/models/news.dart b/refilc/lib/models/news.dart
similarity index 95%
rename from filcnaplo/lib/models/news.dart
rename to refilc/lib/models/news.dart
index e4e4ba9..05431d7 100644
--- a/filcnaplo/lib/models/news.dart
+++ b/refilc/lib/models/news.dart
@@ -1,37 +1,37 @@
-class News {
-  String id;
-  String title;
-  String content;
-  String link;
-  String openLabel;
-  String platform;
-  bool emergency;
-  DateTime expireDate;
-  Map? json;
-
-  News({
-    required this.id,
-    required this.title,
-    required this.content,
-    required this.link,
-    required this.openLabel,
-    required this.platform,
-    required this.emergency,
-    required this.expireDate,
-    this.json,
-  });
-
-  factory News.fromJson(Map json) {
-    return News(
-      id: json["id"] ?? "",
-      title: json["title"] ?? "",
-      content: json["content"] ?? "",
-      link: json["link"] ?? "",
-      openLabel: json["open_label"] ?? "",
-      platform: json["platform"] ?? "",
-      emergency: json["emergency"] ?? false,
-      expireDate: DateTime.parse(json["expire_date"] ?? ''),
-      json: json,
-    );
-  }
-}
+class News {
+  String id;
+  String title;
+  String content;
+  String link;
+  String openLabel;
+  String platform;
+  bool emergency;
+  DateTime expireDate;
+  Map? json;
+
+  News({
+    required this.id,
+    required this.title,
+    required this.content,
+    required this.link,
+    required this.openLabel,
+    required this.platform,
+    required this.emergency,
+    required this.expireDate,
+    this.json,
+  });
+
+  factory News.fromJson(Map json) {
+    return News(
+      id: json["id"] ?? "",
+      title: json["title"] ?? "",
+      content: json["content"] ?? "",
+      link: json["link"] ?? "",
+      openLabel: json["open_label"] ?? "",
+      platform: json["platform"] ?? "",
+      emergency: json["emergency"] ?? false,
+      expireDate: DateTime.parse(json["expire_date"] ?? ''),
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo/lib/models/personality.dart b/refilc/lib/models/personality.dart
similarity index 100%
rename from filcnaplo/lib/models/personality.dart
rename to refilc/lib/models/personality.dart
diff --git a/filcnaplo/lib/models/release.dart b/refilc/lib/models/release.dart
similarity index 96%
rename from filcnaplo/lib/models/release.dart
rename to refilc/lib/models/release.dart
index a2aad3e..52d5331 100644
--- a/filcnaplo/lib/models/release.dart
+++ b/refilc/lib/models/release.dart
@@ -1,151 +1,151 @@
-class ReleaseDownload {
-  String url;
-  int size;
-
-  ReleaseDownload({
-    required this.url,
-    required this.size,
-  });
-
-  factory ReleaseDownload.fromJson(Map json) {
-    return ReleaseDownload(
-      url: json["browser_download_url"] ?? "",
-      size: json["size"] ?? 0,
-    );
-  }
-}
-
-class Release {
-  String tag;
-  Version version;
-  String author;
-  String body;
-  List<ReleaseDownload> downloads;
-  bool prerelease;
-
-  Release({
-    required this.tag,
-    required this.author,
-    required this.body,
-    required this.downloads,
-    required this.prerelease,
-    required this.version,
-  });
-
-  factory Release.fromJson(Map json) {
-    return Release(
-      tag: json["tag_name"] ?? Version.zero.toString(),
-      author: json["author"] != null ? json["author"]["login"] ?? "" : "",
-      body: json["body"] ?? "",
-      downloads: json["assets"] != null ? json["assets"].map((a) => ReleaseDownload.fromJson(a)).toList().cast<ReleaseDownload>() : [],
-      prerelease: json["prerelease"] ?? false,
-      version: Version.fromString(json["tag_name"] ?? ""),
-    );
-  }
-}
-
-class Version {
-  final int major;
-  final int minor;
-  final int patch;
-  final String prerelease;
-  final int prever;
-
-  const Version(this.major, this.minor, this.patch, {this.prerelease = "", this.prever = 0});
-
-  factory Version.fromString(String o) {
-    String string = o;
-    int x = 0, y = 0, z = 0; // major, minor, patch (1.1.1)
-    String pre = ""; // prerelease string (-beta)
-    int prev = 0; // prerelease version (.1)
-
-    try {
-      // cut build
-      string = string.split("+")[0];
-
-      // cut prerelease
-      var p = string.split("-");
-      string = p[0];
-      if (p.length > 1) pre = p[1];
-
-      // prerelease
-      p = pre.split(".");
-
-      if (p.length > 1) prev = int.tryParse(p[1]) ?? 0;
-
-      // check for valid prerelease name
-      if (p[0] != "") {
-        if (prereleases.contains(p[0].toLowerCase().trim())) {
-          pre = p[0];
-        } else {
-          throw "invalid prerelease name: ${p[0]}";
-        }
-      }
-
-      // core
-      p = string.split(".");
-      if (p.length != 3) throw "invalid core length: ${p.length}";
-
-      x = int.tryParse(p[0]) ?? 0;
-      y = int.tryParse(p[1]) ?? 0;
-      z = int.tryParse(p[2]) ?? 0;
-
-      return Version(x, y, z, prerelease: pre, prever: prev);
-    } catch (error) {
-      // ignore: avoid_print
-      print("WARNING: Failed to parse version ($o): $error");
-      return Version.zero;
-    }
-  }
-
-  @override
-  bool operator ==(other) {
-    if (other is! Version) return false;
-    return other.major == major && other.minor == minor && other.patch == patch && other.prei == prei && other.prever == prever;
-  }
-
-  int compareTo(Version other) {
-    if (other == this) return 0;
-
-    if (major > other.major) {
-      return 1;
-    } else if (major == other.major) {
-      if (minor > other.minor) {
-        return 1;
-      } else if (minor == other.minor) {
-        if (patch > other.patch) {
-          return 1;
-        } else if (patch == other.patch) {
-          if (prei > other.prei) {
-            return 1;
-          } else if (other.prei == prei) {
-            if (prever > other.prever) {
-              return 1;
-            }
-          }
-        }
-      }
-    }
-
-    return -1;
-  }
-
-  @override
-  String toString() {
-    String str = "$major.$minor.$patch";
-    if (prerelease != "") str += "-$prerelease";
-    if (prever != 0) str += ".$prever";
-    return str;
-  }
-
-  int get prei {
-    if (prerelease != "") return prereleases.indexOf(prerelease);
-    return prereleases.length;
-  }
-
-  static const zero = Version(0, 0, 0);
-  static const List<String> prereleases = ["dev", "pre", "alpha", "beta", "rc", "nightly", "test"];
-
-  @override
-  int get hashCode => toString().hashCode;
-}
+class ReleaseDownload {
+  String url;
+  int size;
+
+  ReleaseDownload({
+    required this.url,
+    required this.size,
+  });
+
+  factory ReleaseDownload.fromJson(Map json) {
+    return ReleaseDownload(
+      url: json["browser_download_url"] ?? "",
+      size: json["size"] ?? 0,
+    );
+  }
+}
+
+class Release {
+  String tag;
+  Version version;
+  String author;
+  String body;
+  List<ReleaseDownload> downloads;
+  bool prerelease;
+
+  Release({
+    required this.tag,
+    required this.author,
+    required this.body,
+    required this.downloads,
+    required this.prerelease,
+    required this.version,
+  });
+
+  factory Release.fromJson(Map json) {
+    return Release(
+      tag: json["tag_name"] ?? Version.zero.toString(),
+      author: json["author"] != null ? json["author"]["login"] ?? "" : "",
+      body: json["body"] ?? "",
+      downloads: json["assets"] != null ? json["assets"].map((a) => ReleaseDownload.fromJson(a)).toList().cast<ReleaseDownload>() : [],
+      prerelease: json["prerelease"] ?? false,
+      version: Version.fromString(json["tag_name"] ?? ""),
+    );
+  }
+}
+
+class Version {
+  final int major;
+  final int minor;
+  final int patch;
+  final String prerelease;
+  final int prever;
+
+  const Version(this.major, this.minor, this.patch, {this.prerelease = "", this.prever = 0});
+
+  factory Version.fromString(String o) {
+    String string = o;
+    int x = 0, y = 0, z = 0; // major, minor, patch (1.1.1)
+    String pre = ""; // prerelease string (-beta)
+    int prev = 0; // prerelease version (.1)
+
+    try {
+      // cut build
+      string = string.split("+")[0];
+
+      // cut prerelease
+      var p = string.split("-");
+      string = p[0];
+      if (p.length > 1) pre = p[1];
+
+      // prerelease
+      p = pre.split(".");
+
+      if (p.length > 1) prev = int.tryParse(p[1]) ?? 0;
+
+      // check for valid prerelease name
+      if (p[0] != "") {
+        if (prereleases.contains(p[0].toLowerCase().trim())) {
+          pre = p[0];
+        } else {
+          throw "invalid prerelease name: ${p[0]}";
+        }
+      }
+
+      // core
+      p = string.split(".");
+      if (p.length != 3) throw "invalid core length: ${p.length}";
+
+      x = int.tryParse(p[0]) ?? 0;
+      y = int.tryParse(p[1]) ?? 0;
+      z = int.tryParse(p[2]) ?? 0;
+
+      return Version(x, y, z, prerelease: pre, prever: prev);
+    } catch (error) {
+      // ignore: avoid_print
+      print("WARNING: Failed to parse version ($o): $error");
+      return Version.zero;
+    }
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is! Version) return false;
+    return other.major == major && other.minor == minor && other.patch == patch && other.prei == prei && other.prever == prever;
+  }
+
+  int compareTo(Version other) {
+    if (other == this) return 0;
+
+    if (major > other.major) {
+      return 1;
+    } else if (major == other.major) {
+      if (minor > other.minor) {
+        return 1;
+      } else if (minor == other.minor) {
+        if (patch > other.patch) {
+          return 1;
+        } else if (patch == other.patch) {
+          if (prei > other.prei) {
+            return 1;
+          } else if (other.prei == prei) {
+            if (prever > other.prever) {
+              return 1;
+            }
+          }
+        }
+      }
+    }
+
+    return -1;
+  }
+
+  @override
+  String toString() {
+    String str = "$major.$minor.$patch";
+    if (prerelease != "") str += "-$prerelease";
+    if (prever != 0) str += ".$prever";
+    return str;
+  }
+
+  int get prei {
+    if (prerelease != "") return prereleases.indexOf(prerelease);
+    return prereleases.length;
+  }
+
+  static const zero = Version(0, 0, 0);
+  static const List<String> prereleases = ["dev", "pre", "alpha", "beta", "rc", "nightly", "test"];
+
+  @override
+  int get hashCode => toString().hashCode;
+}
diff --git a/filcnaplo/lib/models/settings.dart b/refilc/lib/models/settings.dart
similarity index 95%
rename from filcnaplo/lib/models/settings.dart
rename to refilc/lib/models/settings.dart
index 3e42b26..67835a4 100644
--- a/filcnaplo/lib/models/settings.dart
+++ b/refilc/lib/models/settings.dart
@@ -1,541 +1,541 @@
-import 'dart:convert';
-import 'dart:developer';
-
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/config.dart';
-import 'package:filcnaplo/models/icon_pack.dart';
-import 'package:filcnaplo/theme/colors/accent.dart';
-import 'package:filcnaplo/theme/colors/dark_mobile.dart';
-import 'package:filcnaplo_premium/models/premium_scopes.dart';
-import 'package:flutter/material.dart';
-import 'package:uuid/uuid.dart';
-
-enum Pages { home, grades, timetable, messages, absences }
-
-enum UpdateChannel { stable, beta, dev }
-
-enum VibrationStrength { off, light, medium, strong }
-
-class SettingsProvider extends ChangeNotifier {
-  final DatabaseProvider? _database;
-
-  // en_en, hu_hu, de_de
-  String _language;
-  Pages _startPage;
-  // divide by 10
-  int _rounding;
-  ThemeMode _theme;
-  AccentColor _accentColor;
-  // zero is one, ...
-  List<Color> _gradeColors;
-  bool _newsEnabled;
-  String _seenNews;
-  bool _notificationsEnabled;
-  bool _notificationsGradesEnabled;
-  bool _notificationsAbsencesEnabled;
-  bool _notificationsMessagesEnabled;
-  bool _notificationsLessonsEnabled;
-  /*
-  notificationsBitfield values:
-
-  1 << 0 current lesson
-  1 << 1 newsletter
-  1 << 2 grades
-  1 << 3 notes and events
-  1 << 4 inbox messages
-  1 << 5 substituted lessons and cancelled lessons
-  1 << 6 absences and misses
-  1 << 7 exams and homework
-  */
-  int _notificationsBitfield;
-  // minutes: times 15
-  int _notificationPollInterval;
-  bool _developerMode;
-  VibrationStrength _vibrate;
-  bool _abWeeks;
-  bool _swapABweeks;
-  UpdateChannel _updateChannel;
-  Config _config;
-  String _xFilcId;
-  bool _graphClassAvg;
-  bool _goodStudent;
-  bool _presentationMode;
-  bool _bellDelayEnabled;
-  int _bellDelay;
-  bool _gradeOpeningFun;
-  IconPack _iconPack;
-  Color _customAccentColor;
-  Color _customBackgroundColor;
-  Color _customHighlightColor;
-  List<String> _premiumScopes;
-  String _premiumAccessToken;
-  String _premiumLogin;
-  String _lastAccountId;
-  bool _renamedSubjectsEnabled;
-  bool _renamedSubjectsItalics;
-  bool _renamedTeachersEnabled;
-  bool _renamedTeachersItalics;
-  Color _liveActivityColor;
-
-  SettingsProvider({
-    DatabaseProvider? database,
-    required String language,
-    required Pages startPage,
-    required int rounding,
-    required ThemeMode theme,
-    required AccentColor accentColor,
-    required List<Color> gradeColors,
-    required bool newsEnabled,
-    required String seenNews,
-    required bool notificationsEnabled,
-    required bool notificationsGradesEnabled,
-    required bool notificationsAbsencesEnabled,
-    required bool notificationsMessagesEnabled,
-    required bool notificationsLessonsEnabled,
-    required int notificationsBitfield,
-    required bool developerMode,
-    required int notificationPollInterval,
-    required VibrationStrength vibrate,
-    required bool abWeeks,
-    required bool swapABweeks,
-    required UpdateChannel updateChannel,
-    required Config config,
-    required String xFilcId,
-    required bool graphClassAvg,
-    required bool goodStudent,
-    required bool presentationMode,
-    required bool bellDelayEnabled,
-    required int bellDelay,
-    required bool gradeOpeningFun,
-    required IconPack iconPack,
-    required Color customAccentColor,
-    required Color customBackgroundColor,
-    required Color customHighlightColor,
-    required List<String> premiumScopes,
-    required String premiumAccessToken,
-    required String premiumLogin,
-    required String lastAccountId,
-    required bool renameSubjectsEnabled,
-    required bool renameSubjectsItalics,
-    required bool renameTeachersEnabled,
-    required bool renameTeachersItalics,
-    required Color liveActivityColor,
-  })  : _database = database,
-        _language = language,
-        _startPage = startPage,
-        _rounding = rounding,
-        _theme = theme,
-        _accentColor = accentColor,
-        _gradeColors = gradeColors,
-        _newsEnabled = newsEnabled,
-        _seenNews = seenNews,
-        _notificationsEnabled = notificationsEnabled,
-        _notificationsGradesEnabled = notificationsGradesEnabled,
-        _notificationsAbsencesEnabled = notificationsAbsencesEnabled,
-        _notificationsMessagesEnabled = notificationsMessagesEnabled,
-        _notificationsLessonsEnabled = notificationsLessonsEnabled,
-        _notificationsBitfield = notificationsBitfield,
-        _developerMode = developerMode,
-        _notificationPollInterval = notificationPollInterval,
-        _vibrate = vibrate,
-        _abWeeks = abWeeks,
-        _swapABweeks = swapABweeks,
-        _updateChannel = updateChannel,
-        _config = config,
-        _xFilcId = xFilcId,
-        _graphClassAvg = graphClassAvg,
-        _goodStudent = goodStudent,
-        _presentationMode = presentationMode,
-        _bellDelayEnabled = bellDelayEnabled,
-        _bellDelay = bellDelay,
-        _gradeOpeningFun = gradeOpeningFun,
-        _iconPack = iconPack,
-        _customAccentColor = customAccentColor,
-        _customBackgroundColor = customBackgroundColor,
-        _customHighlightColor = customHighlightColor,
-        _premiumScopes = premiumScopes,
-        _premiumAccessToken = premiumAccessToken,
-        _premiumLogin = premiumLogin,
-        _lastAccountId = lastAccountId,
-        _renamedSubjectsEnabled = renameSubjectsEnabled,
-        _renamedSubjectsItalics = renameSubjectsItalics,
-        _renamedTeachersEnabled = renameTeachersEnabled,
-        _renamedTeachersItalics = renameTeachersItalics,
-        _liveActivityColor = liveActivityColor;
-
-  factory SettingsProvider.fromMap(Map map,
-      {required DatabaseProvider database}) {
-    Map<String, Object?>? configMap;
-
-    try {
-      configMap = jsonDecode(map["config"] ?? "{}");
-    } catch (e) {
-      log("[ERROR] SettingsProvider.fromMap: $e");
-    }
-
-    return SettingsProvider(
-      database: database,
-      language: map["language"],
-      startPage: Pages.values[map["start_page"]],
-      rounding: map["rounding"],
-      theme: ThemeMode.values[map["theme"]],
-      accentColor: AccentColor.values[map["accent_color"]],
-      gradeColors: [
-        Color(map["grade_color1"]),
-        Color(map["grade_color2"]),
-        Color(map["grade_color3"]),
-        Color(map["grade_color4"]),
-        Color(map["grade_color5"]),
-      ],
-      newsEnabled: map["news"] == 1,
-      seenNews: map["seen_news"],
-      notificationsEnabled: map["notifications"] == 1,
-      notificationsGradesEnabled: map["notifications_grades"] == 1,
-      notificationsAbsencesEnabled: map["notifications_absences"] == 1,
-      notificationsMessagesEnabled: map["notifications_messages"] == 1,
-      notificationsLessonsEnabled: map["notifications_lessons"] == 1,
-      notificationsBitfield: map["notifications_bitfield"],
-      notificationPollInterval: map["notification_poll_interval"],
-      developerMode: map["developer_mode"] == 1,
-      vibrate: VibrationStrength.values[map["vibration_strength"]],
-      abWeeks: map["ab_weeks"] == 1,
-      swapABweeks: map["swap_ab_weeks"] == 1,
-      updateChannel: UpdateChannel.values[map["update_channel"]],
-      config: Config.fromJson(configMap ?? {}),
-      xFilcId: map["x_filc_id"],
-      graphClassAvg: map["graph_class_avg"] == 1,
-      goodStudent: false,
-      presentationMode: map["presentation_mode"] == 1,
-      bellDelayEnabled: map["bell_delay_enabled"] == 1,
-      bellDelay: map["bell_delay"],
-      gradeOpeningFun: map["grade_opening_fun"] == 1,
-      iconPack: Map.fromEntries(
-          IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!,
-      customAccentColor: Color(map["custom_accent_color"]),
-      customBackgroundColor: Color(map["custom_background_color"]),
-      customHighlightColor: Color(map["custom_highlight_color"]),
-      premiumScopes: jsonDecode(map["premium_scopes"]).cast<String>(),
-      premiumAccessToken: map["premium_token"],
-      premiumLogin: map["premium_login"],
-      lastAccountId: map["last_account_id"],
-      renameSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
-      renameSubjectsItalics: map["renamed_subjects_italics"] == 1,
-      renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
-      renameTeachersItalics: map["renamed_teachers_italics"] == 1,
-      liveActivityColor: Color(map["live_activity_color"]),
-    );
-  }
-
-  Map<String, Object?> toMap() {
-    return {
-      "language": _language,
-      "start_page": _startPage.index,
-      "rounding": _rounding,
-      "theme": _theme.index,
-      "accent_color": _accentColor.index,
-      "news": _newsEnabled ? 1 : 0,
-      "seen_news": _seenNews,
-      "notifications": _notificationsEnabled ? 1 : 0,
-      "notifications_grades": _notificationsGradesEnabled ? 1 : 0,
-      "notifications_absences": _notificationsAbsencesEnabled ? 1 : 0,
-      "notifications_messages": _notificationsMessagesEnabled ? 1 : 0,
-      "notifications_lessons": _notificationsLessonsEnabled ? 1 : 0,
-      "notifications_bitfield": _notificationsBitfield,
-      "developer_mode": _developerMode ? 1 : 0,
-      "grade_color1": _gradeColors[0].value,
-      "grade_color2": _gradeColors[1].value,
-      "grade_color3": _gradeColors[2].value,
-      "grade_color4": _gradeColors[3].value,
-      "grade_color5": _gradeColors[4].value,
-      "update_channel": _updateChannel.index,
-      "vibration_strength": _vibrate.index,
-      "ab_weeks": _abWeeks ? 1 : 0,
-      "swap_ab_weeks": _swapABweeks ? 1 : 0,
-      "notification_poll_interval": _notificationPollInterval,
-      "config": jsonEncode(config.json),
-      "x_filc_id": _xFilcId,
-      "graph_class_avg": _graphClassAvg ? 1 : 0,
-      "presentation_mode": _presentationMode ? 1 : 0,
-      "bell_delay_enabled": _bellDelayEnabled ? 1 : 0,
-      "bell_delay": _bellDelay,
-      "grade_opening_fun": _gradeOpeningFun ? 1 : 0,
-      "icon_pack": _iconPack.name,
-      "custom_accent_color": _customAccentColor.value,
-      "custom_background_color": _customBackgroundColor.value,
-      "custom_highlight_color": _customHighlightColor.value,
-      "premium_scopes": jsonEncode(_premiumScopes),
-      "premium_token": _premiumAccessToken,
-      "premium_login": _premiumLogin,
-      "last_account_id": _lastAccountId,
-      "renamed_subjects_enabled": _renamedSubjectsEnabled ? 1 : 0,
-      "renamed_subjects_italics": _renamedSubjectsItalics ? 1 : 0,
-      "renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
-      "renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
-      "live_activity_color": _liveActivityColor.value,
-    };
-  }
-
-  factory SettingsProvider.defaultSettings({DatabaseProvider? database}) {
-    return SettingsProvider(
-      database: database,
-      language: "hu",
-      startPage: Pages.home,
-      rounding: 5,
-      theme: ThemeMode.system,
-      accentColor: AccentColor.filc,
-      gradeColors: [
-        DarkMobileAppColors().gradeOne,
-        DarkMobileAppColors().gradeTwo,
-        DarkMobileAppColors().gradeThree,
-        DarkMobileAppColors().gradeFour,
-        DarkMobileAppColors().gradeFive,
-      ],
-      newsEnabled: true,
-      seenNews: '',
-      notificationsEnabled: true,
-      notificationsGradesEnabled: true,
-      notificationsAbsencesEnabled: true,
-      notificationsMessagesEnabled: true,
-      notificationsLessonsEnabled: true,
-      notificationsBitfield: 255,
-      developerMode: false,
-      notificationPollInterval: 1,
-      vibrate: VibrationStrength.medium,
-      abWeeks: false,
-      swapABweeks: false,
-      updateChannel: UpdateChannel.stable,
-      config: Config.fromJson({}),
-      xFilcId: const Uuid().v4(),
-      graphClassAvg: false,
-      goodStudent: false,
-      presentationMode: false,
-      bellDelayEnabled: false,
-      bellDelay: 0,
-      gradeOpeningFun: true,
-      iconPack: IconPack.cupertino,
-      customAccentColor: const Color(0xff3D7BF4),
-      customBackgroundColor: const Color(0xff000000),
-      customHighlightColor: const Color(0xff222222),
-      premiumScopes: [PremiumScopes.all],
-      premiumAccessToken: "igen",
-      premiumLogin: "igen",
-      lastAccountId: "",
-      renameSubjectsEnabled: false,
-      renameSubjectsItalics: false,
-      renameTeachersEnabled: false,
-      renameTeachersItalics: false,
-      liveActivityColor: const Color(0xFF676767),
-    );
-  }
-
-  // Getters
-  String get language => _language;
-  Pages get startPage => _startPage;
-  int get rounding => _rounding;
-  ThemeMode get theme => _theme;
-  AccentColor get accentColor => _accentColor;
-  List<Color> get gradeColors => _gradeColors;
-  bool get newsEnabled => _newsEnabled;
-  List<String> get seenNews => _seenNews.split(',');
-  bool get notificationsEnabled => _notificationsEnabled;
-  bool get notificationsGradesEnabled => _notificationsGradesEnabled;
-  bool get notificationsAbsencesEnabled => _notificationsAbsencesEnabled;
-  bool get notificationsMessagesEnabled => _notificationsMessagesEnabled;
-  bool get notificationsLessonsEnabled => _notificationsLessonsEnabled;
-  int get notificationsBitfield => _notificationsBitfield;
-  bool get developerMode => _developerMode;
-  int get notificationPollInterval => _notificationPollInterval;
-  VibrationStrength get vibrate => _vibrate;
-  bool get abWeeks => _abWeeks;
-  bool get swapABweeks => _swapABweeks;
-  UpdateChannel get updateChannel => _updateChannel;
-  Config get config => _config;
-  String get xFilcId => _xFilcId;
-  bool get graphClassAvg => _graphClassAvg;
-  bool get goodStudent => _goodStudent;
-  bool get presentationMode => _presentationMode;
-  bool get bellDelayEnabled => _bellDelayEnabled;
-  int get bellDelay => _bellDelay;
-  bool get gradeOpeningFun => _gradeOpeningFun;
-  IconPack get iconPack => _iconPack;
-  Color? get customAccentColor =>
-      _customAccentColor == accentColorMap[AccentColor.custom]
-          ? null
-          : _customAccentColor;
-  Color? get customBackgroundColor => _customBackgroundColor;
-  Color? get customHighlightColor => _customHighlightColor;
-  List<String> get premiumScopes => _premiumScopes;
-  String get premiumAccessToken => _premiumAccessToken;
-  String get premiumLogin => _premiumLogin;
-  String get lastAccountId => _lastAccountId;
-  bool get renamedSubjectsEnabled => _renamedSubjectsEnabled;
-  bool get renamedSubjectsItalics => _renamedSubjectsItalics;
-  bool get renamedTeachersEnabled => _renamedTeachersEnabled;
-  bool get renamedTeachersItalics => _renamedTeachersItalics;
-  Color get liveActivityColor => _liveActivityColor;
-
-  Future<void> update({
-    bool store = true,
-    String? language,
-    Pages? startPage,
-    int? rounding,
-    ThemeMode? theme,
-    AccentColor? accentColor,
-    List<Color>? gradeColors,
-    bool? newsEnabled,
-    String? seenNewsId,
-    bool? notificationsEnabled,
-    bool? notificationsGradesEnabled,
-    bool? notificationsAbsencesEnabled,
-    bool? notificationsMessagesEnabled,
-    bool? notificationsLessonsEnabled,
-    int? notificationsBitfield,
-    bool? developerMode,
-    int? notificationPollInterval,
-    VibrationStrength? vibrate,
-    bool? abWeeks,
-    bool? swapABweeks,
-    UpdateChannel? updateChannel,
-    Config? config,
-    String? xFilcId,
-    bool? graphClassAvg,
-    bool? goodStudent,
-    bool? presentationMode,
-    bool? bellDelayEnabled,
-    int? bellDelay,
-    bool? gradeOpeningFun,
-    IconPack? iconPack,
-    Color? customAccentColor,
-    Color? customBackgroundColor,
-    Color? customHighlightColor,
-    List<String>? premiumScopes,
-    String? premiumAccessToken,
-    String? premiumLogin,
-    String? lastAccountId,
-    bool? renamedSubjectsEnabled,
-    bool? renamedSubjectsItalics,
-    bool? renamedTeachersEnabled,
-    bool? renamedTeachersItalics,
-    Color? liveActivityColor,
-  }) async {
-    if (language != null && language != _language) _language = language;
-    if (startPage != null && startPage != _startPage) _startPage = startPage;
-    if (rounding != null && rounding != _rounding) _rounding = rounding;
-    if (theme != null && theme != _theme) _theme = theme;
-    if (accentColor != null && accentColor != _accentColor) {
-      _accentColor = accentColor;
-    }
-    if (gradeColors != null && gradeColors != _gradeColors) {
-      _gradeColors = gradeColors;
-    }
-    if (newsEnabled != null && newsEnabled != _newsEnabled) {
-      _newsEnabled = newsEnabled;
-    }
-    if (seenNewsId != null && !_seenNews.split(',').contains(seenNewsId)) {
-      var tempList = _seenNews.split(',');
-      tempList.add(seenNewsId);
-      _seenNews = tempList.join(',');
-    }
-    if (notificationsEnabled != null &&
-        notificationsEnabled != _notificationsEnabled) {
-      _notificationsEnabled = notificationsEnabled;
-    }
-    if (notificationsGradesEnabled != null &&
-        notificationsGradesEnabled != _notificationsGradesEnabled) {
-      _notificationsGradesEnabled = notificationsGradesEnabled;
-    }
-    if (notificationsAbsencesEnabled != null &&
-        notificationsAbsencesEnabled != _notificationsAbsencesEnabled) {
-      _notificationsAbsencesEnabled = notificationsAbsencesEnabled;
-    }
-    if (notificationsMessagesEnabled != null &&
-        notificationsMessagesEnabled != _notificationsMessagesEnabled) {
-      _notificationsMessagesEnabled = notificationsMessagesEnabled;
-    }
-    if (notificationsLessonsEnabled != null &&
-        notificationsLessonsEnabled != _notificationsLessonsEnabled) {
-      _notificationsLessonsEnabled = notificationsLessonsEnabled;
-    }
-    if (notificationsBitfield != null &&
-        notificationsBitfield != _notificationsBitfield) {
-      _notificationsBitfield = notificationsBitfield;
-    }
-    if (developerMode != null && developerMode != _developerMode) {
-      _developerMode = developerMode;
-    }
-    if (notificationPollInterval != null &&
-        notificationPollInterval != _notificationPollInterval) {
-      _notificationPollInterval = notificationPollInterval;
-    }
-    if (vibrate != null && vibrate != _vibrate) _vibrate = vibrate;
-    if (abWeeks != null && abWeeks != _abWeeks) _abWeeks = abWeeks;
-    if (swapABweeks != null && swapABweeks != _swapABweeks) {
-      _swapABweeks = swapABweeks;
-    }
-    if (updateChannel != null && updateChannel != _updateChannel) {
-      _updateChannel = updateChannel;
-    }
-    if (config != null && config != _config) _config = config;
-    if (xFilcId != null && xFilcId != _xFilcId) _xFilcId = xFilcId;
-    if (graphClassAvg != null && graphClassAvg != _graphClassAvg) {
-      _graphClassAvg = graphClassAvg;
-    }
-    if (goodStudent != null) _goodStudent = goodStudent;
-    if (presentationMode != null && presentationMode != _presentationMode) {
-      _presentationMode = presentationMode;
-    }
-    if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay;
-    if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) {
-      _bellDelayEnabled = bellDelayEnabled;
-    }
-    if (gradeOpeningFun != null && gradeOpeningFun != _gradeOpeningFun) {
-      _gradeOpeningFun = gradeOpeningFun;
-    }
-    if (iconPack != null && iconPack != _iconPack) _iconPack = iconPack;
-    if (customAccentColor != null && customAccentColor != _customAccentColor) {
-      _customAccentColor = customAccentColor;
-    }
-    if (customBackgroundColor != null &&
-        customBackgroundColor != _customBackgroundColor) {
-      _customBackgroundColor = customBackgroundColor;
-    }
-    if (customHighlightColor != null &&
-        customHighlightColor != _customHighlightColor) {
-      _customHighlightColor = customHighlightColor;
-    }
-    if (premiumScopes != null && premiumScopes != _premiumScopes) {
-      _premiumScopes = premiumScopes;
-    }
-    if (premiumAccessToken != null &&
-        premiumAccessToken != _premiumAccessToken) {
-      _premiumAccessToken = premiumAccessToken;
-    }
-    if (premiumLogin != null && premiumLogin != _premiumLogin) {
-      _premiumLogin = premiumLogin;
-    }
-    if (lastAccountId != null && lastAccountId != _lastAccountId) {
-      _lastAccountId = lastAccountId;
-    }
-    if (renamedSubjectsEnabled != null &&
-        renamedSubjectsEnabled != _renamedSubjectsEnabled) {
-      _renamedSubjectsEnabled = renamedSubjectsEnabled;
-    }
-    if (renamedSubjectsItalics != null &&
-        renamedSubjectsItalics != _renamedSubjectsItalics) {
-      _renamedSubjectsItalics = renamedSubjectsItalics;
-    }
-    if (renamedTeachersEnabled != null &&
-        renamedTeachersEnabled != _renamedTeachersEnabled) {
-      _renamedTeachersEnabled = renamedTeachersEnabled;
-    }
-    if (renamedTeachersItalics != null &&
-        renamedTeachersItalics != _renamedTeachersItalics) {
-      _renamedTeachersItalics = renamedTeachersItalics;
-    }
-    if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
-      _liveActivityColor = liveActivityColor;
-    }
-    if (store) await _database?.store.storeSettings(this);
-    notifyListeners();
-  }
-}
+import 'dart:convert';
+import 'dart:developer';
+
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/config.dart';
+import 'package:refilc/models/icon_pack.dart';
+import 'package:refilc/theme/colors/accent.dart';
+import 'package:refilc/theme/colors/dark_mobile.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:flutter/material.dart';
+import 'package:uuid/uuid.dart';
+
+enum Pages { home, grades, timetable, messages, absences }
+
+enum UpdateChannel { stable, beta, dev }
+
+enum VibrationStrength { off, light, medium, strong }
+
+class SettingsProvider extends ChangeNotifier {
+  final DatabaseProvider? _database;
+
+  // en_en, hu_hu, de_de
+  String _language;
+  Pages _startPage;
+  // divide by 10
+  int _rounding;
+  ThemeMode _theme;
+  AccentColor _accentColor;
+  // zero is one, ...
+  List<Color> _gradeColors;
+  bool _newsEnabled;
+  String _seenNews;
+  bool _notificationsEnabled;
+  bool _notificationsGradesEnabled;
+  bool _notificationsAbsencesEnabled;
+  bool _notificationsMessagesEnabled;
+  bool _notificationsLessonsEnabled;
+  /*
+  notificationsBitfield values:
+
+  1 << 0 current lesson
+  1 << 1 newsletter
+  1 << 2 grades
+  1 << 3 notes and events
+  1 << 4 inbox messages
+  1 << 5 substituted lessons and cancelled lessons
+  1 << 6 absences and misses
+  1 << 7 exams and homework
+  */
+  int _notificationsBitfield;
+  // minutes: times 15
+  int _notificationPollInterval;
+  bool _developerMode;
+  VibrationStrength _vibrate;
+  bool _abWeeks;
+  bool _swapABweeks;
+  UpdateChannel _updateChannel;
+  Config _config;
+  String _xFilcId;
+  bool _graphClassAvg;
+  bool _goodStudent;
+  bool _presentationMode;
+  bool _bellDelayEnabled;
+  int _bellDelay;
+  bool _gradeOpeningFun;
+  IconPack _iconPack;
+  Color _customAccentColor;
+  Color _customBackgroundColor;
+  Color _customHighlightColor;
+  List<String> _premiumScopes;
+  String _premiumAccessToken;
+  String _premiumLogin;
+  String _lastAccountId;
+  bool _renamedSubjectsEnabled;
+  bool _renamedSubjectsItalics;
+  bool _renamedTeachersEnabled;
+  bool _renamedTeachersItalics;
+  Color _liveActivityColor;
+
+  SettingsProvider({
+    DatabaseProvider? database,
+    required String language,
+    required Pages startPage,
+    required int rounding,
+    required ThemeMode theme,
+    required AccentColor accentColor,
+    required List<Color> gradeColors,
+    required bool newsEnabled,
+    required String seenNews,
+    required bool notificationsEnabled,
+    required bool notificationsGradesEnabled,
+    required bool notificationsAbsencesEnabled,
+    required bool notificationsMessagesEnabled,
+    required bool notificationsLessonsEnabled,
+    required int notificationsBitfield,
+    required bool developerMode,
+    required int notificationPollInterval,
+    required VibrationStrength vibrate,
+    required bool abWeeks,
+    required bool swapABweeks,
+    required UpdateChannel updateChannel,
+    required Config config,
+    required String xFilcId,
+    required bool graphClassAvg,
+    required bool goodStudent,
+    required bool presentationMode,
+    required bool bellDelayEnabled,
+    required int bellDelay,
+    required bool gradeOpeningFun,
+    required IconPack iconPack,
+    required Color customAccentColor,
+    required Color customBackgroundColor,
+    required Color customHighlightColor,
+    required List<String> premiumScopes,
+    required String premiumAccessToken,
+    required String premiumLogin,
+    required String lastAccountId,
+    required bool renameSubjectsEnabled,
+    required bool renameSubjectsItalics,
+    required bool renameTeachersEnabled,
+    required bool renameTeachersItalics,
+    required Color liveActivityColor,
+  })  : _database = database,
+        _language = language,
+        _startPage = startPage,
+        _rounding = rounding,
+        _theme = theme,
+        _accentColor = accentColor,
+        _gradeColors = gradeColors,
+        _newsEnabled = newsEnabled,
+        _seenNews = seenNews,
+        _notificationsEnabled = notificationsEnabled,
+        _notificationsGradesEnabled = notificationsGradesEnabled,
+        _notificationsAbsencesEnabled = notificationsAbsencesEnabled,
+        _notificationsMessagesEnabled = notificationsMessagesEnabled,
+        _notificationsLessonsEnabled = notificationsLessonsEnabled,
+        _notificationsBitfield = notificationsBitfield,
+        _developerMode = developerMode,
+        _notificationPollInterval = notificationPollInterval,
+        _vibrate = vibrate,
+        _abWeeks = abWeeks,
+        _swapABweeks = swapABweeks,
+        _updateChannel = updateChannel,
+        _config = config,
+        _xFilcId = xFilcId,
+        _graphClassAvg = graphClassAvg,
+        _goodStudent = goodStudent,
+        _presentationMode = presentationMode,
+        _bellDelayEnabled = bellDelayEnabled,
+        _bellDelay = bellDelay,
+        _gradeOpeningFun = gradeOpeningFun,
+        _iconPack = iconPack,
+        _customAccentColor = customAccentColor,
+        _customBackgroundColor = customBackgroundColor,
+        _customHighlightColor = customHighlightColor,
+        _premiumScopes = premiumScopes,
+        _premiumAccessToken = premiumAccessToken,
+        _premiumLogin = premiumLogin,
+        _lastAccountId = lastAccountId,
+        _renamedSubjectsEnabled = renameSubjectsEnabled,
+        _renamedSubjectsItalics = renameSubjectsItalics,
+        _renamedTeachersEnabled = renameTeachersEnabled,
+        _renamedTeachersItalics = renameTeachersItalics,
+        _liveActivityColor = liveActivityColor;
+
+  factory SettingsProvider.fromMap(Map map,
+      {required DatabaseProvider database}) {
+    Map<String, Object?>? configMap;
+
+    try {
+      configMap = jsonDecode(map["config"] ?? "{}");
+    } catch (e) {
+      log("[ERROR] SettingsProvider.fromMap: $e");
+    }
+
+    return SettingsProvider(
+      database: database,
+      language: map["language"],
+      startPage: Pages.values[map["start_page"]],
+      rounding: map["rounding"],
+      theme: ThemeMode.values[map["theme"]],
+      accentColor: AccentColor.values[map["accent_color"]],
+      gradeColors: [
+        Color(map["grade_color1"]),
+        Color(map["grade_color2"]),
+        Color(map["grade_color3"]),
+        Color(map["grade_color4"]),
+        Color(map["grade_color5"]),
+      ],
+      newsEnabled: map["news"] == 1,
+      seenNews: map["seen_news"],
+      notificationsEnabled: map["notifications"] == 1,
+      notificationsGradesEnabled: map["notifications_grades"] == 1,
+      notificationsAbsencesEnabled: map["notifications_absences"] == 1,
+      notificationsMessagesEnabled: map["notifications_messages"] == 1,
+      notificationsLessonsEnabled: map["notifications_lessons"] == 1,
+      notificationsBitfield: map["notifications_bitfield"],
+      notificationPollInterval: map["notification_poll_interval"],
+      developerMode: map["developer_mode"] == 1,
+      vibrate: VibrationStrength.values[map["vibration_strength"]],
+      abWeeks: map["ab_weeks"] == 1,
+      swapABweeks: map["swap_ab_weeks"] == 1,
+      updateChannel: UpdateChannel.values[map["update_channel"]],
+      config: Config.fromJson(configMap ?? {}),
+      xFilcId: map["x_filc_id"],
+      graphClassAvg: map["graph_class_avg"] == 1,
+      goodStudent: false,
+      presentationMode: map["presentation_mode"] == 1,
+      bellDelayEnabled: map["bell_delay_enabled"] == 1,
+      bellDelay: map["bell_delay"],
+      gradeOpeningFun: map["grade_opening_fun"] == 1,
+      iconPack: Map.fromEntries(
+          IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!,
+      customAccentColor: Color(map["custom_accent_color"]),
+      customBackgroundColor: Color(map["custom_background_color"]),
+      customHighlightColor: Color(map["custom_highlight_color"]),
+      premiumScopes: jsonDecode(map["premium_scopes"]).cast<String>(),
+      premiumAccessToken: map["premium_token"],
+      premiumLogin: map["premium_login"],
+      lastAccountId: map["last_account_id"],
+      renameSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
+      renameSubjectsItalics: map["renamed_subjects_italics"] == 1,
+      renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
+      renameTeachersItalics: map["renamed_teachers_italics"] == 1,
+      liveActivityColor: Color(map["live_activity_color"]),
+    );
+  }
+
+  Map<String, Object?> toMap() {
+    return {
+      "language": _language,
+      "start_page": _startPage.index,
+      "rounding": _rounding,
+      "theme": _theme.index,
+      "accent_color": _accentColor.index,
+      "news": _newsEnabled ? 1 : 0,
+      "seen_news": _seenNews,
+      "notifications": _notificationsEnabled ? 1 : 0,
+      "notifications_grades": _notificationsGradesEnabled ? 1 : 0,
+      "notifications_absences": _notificationsAbsencesEnabled ? 1 : 0,
+      "notifications_messages": _notificationsMessagesEnabled ? 1 : 0,
+      "notifications_lessons": _notificationsLessonsEnabled ? 1 : 0,
+      "notifications_bitfield": _notificationsBitfield,
+      "developer_mode": _developerMode ? 1 : 0,
+      "grade_color1": _gradeColors[0].value,
+      "grade_color2": _gradeColors[1].value,
+      "grade_color3": _gradeColors[2].value,
+      "grade_color4": _gradeColors[3].value,
+      "grade_color5": _gradeColors[4].value,
+      "update_channel": _updateChannel.index,
+      "vibration_strength": _vibrate.index,
+      "ab_weeks": _abWeeks ? 1 : 0,
+      "swap_ab_weeks": _swapABweeks ? 1 : 0,
+      "notification_poll_interval": _notificationPollInterval,
+      "config": jsonEncode(config.json),
+      "x_filc_id": _xFilcId,
+      "graph_class_avg": _graphClassAvg ? 1 : 0,
+      "presentation_mode": _presentationMode ? 1 : 0,
+      "bell_delay_enabled": _bellDelayEnabled ? 1 : 0,
+      "bell_delay": _bellDelay,
+      "grade_opening_fun": _gradeOpeningFun ? 1 : 0,
+      "icon_pack": _iconPack.name,
+      "custom_accent_color": _customAccentColor.value,
+      "custom_background_color": _customBackgroundColor.value,
+      "custom_highlight_color": _customHighlightColor.value,
+      "premium_scopes": jsonEncode(_premiumScopes),
+      "premium_token": _premiumAccessToken,
+      "premium_login": _premiumLogin,
+      "last_account_id": _lastAccountId,
+      "renamed_subjects_enabled": _renamedSubjectsEnabled ? 1 : 0,
+      "renamed_subjects_italics": _renamedSubjectsItalics ? 1 : 0,
+      "renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
+      "renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
+      "live_activity_color": _liveActivityColor.value,
+    };
+  }
+
+  factory SettingsProvider.defaultSettings({DatabaseProvider? database}) {
+    return SettingsProvider(
+      database: database,
+      language: "hu",
+      startPage: Pages.home,
+      rounding: 5,
+      theme: ThemeMode.system,
+      accentColor: AccentColor.filc,
+      gradeColors: [
+        DarkMobileAppColors().gradeOne,
+        DarkMobileAppColors().gradeTwo,
+        DarkMobileAppColors().gradeThree,
+        DarkMobileAppColors().gradeFour,
+        DarkMobileAppColors().gradeFive,
+      ],
+      newsEnabled: true,
+      seenNews: '',
+      notificationsEnabled: true,
+      notificationsGradesEnabled: true,
+      notificationsAbsencesEnabled: true,
+      notificationsMessagesEnabled: true,
+      notificationsLessonsEnabled: true,
+      notificationsBitfield: 255,
+      developerMode: false,
+      notificationPollInterval: 1,
+      vibrate: VibrationStrength.medium,
+      abWeeks: false,
+      swapABweeks: false,
+      updateChannel: UpdateChannel.stable,
+      config: Config.fromJson({}),
+      xFilcId: const Uuid().v4(),
+      graphClassAvg: false,
+      goodStudent: false,
+      presentationMode: false,
+      bellDelayEnabled: false,
+      bellDelay: 0,
+      gradeOpeningFun: true,
+      iconPack: IconPack.cupertino,
+      customAccentColor: const Color(0xff3D7BF4),
+      customBackgroundColor: const Color(0xff000000),
+      customHighlightColor: const Color(0xff222222),
+      premiumScopes: [PremiumScopes.all],
+      premiumAccessToken: "igen",
+      premiumLogin: "igen",
+      lastAccountId: "",
+      renameSubjectsEnabled: false,
+      renameSubjectsItalics: false,
+      renameTeachersEnabled: false,
+      renameTeachersItalics: false,
+      liveActivityColor: const Color(0xFF676767),
+    );
+  }
+
+  // Getters
+  String get language => _language;
+  Pages get startPage => _startPage;
+  int get rounding => _rounding;
+  ThemeMode get theme => _theme;
+  AccentColor get accentColor => _accentColor;
+  List<Color> get gradeColors => _gradeColors;
+  bool get newsEnabled => _newsEnabled;
+  List<String> get seenNews => _seenNews.split(',');
+  bool get notificationsEnabled => _notificationsEnabled;
+  bool get notificationsGradesEnabled => _notificationsGradesEnabled;
+  bool get notificationsAbsencesEnabled => _notificationsAbsencesEnabled;
+  bool get notificationsMessagesEnabled => _notificationsMessagesEnabled;
+  bool get notificationsLessonsEnabled => _notificationsLessonsEnabled;
+  int get notificationsBitfield => _notificationsBitfield;
+  bool get developerMode => _developerMode;
+  int get notificationPollInterval => _notificationPollInterval;
+  VibrationStrength get vibrate => _vibrate;
+  bool get abWeeks => _abWeeks;
+  bool get swapABweeks => _swapABweeks;
+  UpdateChannel get updateChannel => _updateChannel;
+  Config get config => _config;
+  String get xFilcId => _xFilcId;
+  bool get graphClassAvg => _graphClassAvg;
+  bool get goodStudent => _goodStudent;
+  bool get presentationMode => _presentationMode;
+  bool get bellDelayEnabled => _bellDelayEnabled;
+  int get bellDelay => _bellDelay;
+  bool get gradeOpeningFun => _gradeOpeningFun;
+  IconPack get iconPack => _iconPack;
+  Color? get customAccentColor =>
+      _customAccentColor == accentColorMap[AccentColor.custom]
+          ? null
+          : _customAccentColor;
+  Color? get customBackgroundColor => _customBackgroundColor;
+  Color? get customHighlightColor => _customHighlightColor;
+  List<String> get premiumScopes => _premiumScopes;
+  String get premiumAccessToken => _premiumAccessToken;
+  String get premiumLogin => _premiumLogin;
+  String get lastAccountId => _lastAccountId;
+  bool get renamedSubjectsEnabled => _renamedSubjectsEnabled;
+  bool get renamedSubjectsItalics => _renamedSubjectsItalics;
+  bool get renamedTeachersEnabled => _renamedTeachersEnabled;
+  bool get renamedTeachersItalics => _renamedTeachersItalics;
+  Color get liveActivityColor => _liveActivityColor;
+
+  Future<void> update({
+    bool store = true,
+    String? language,
+    Pages? startPage,
+    int? rounding,
+    ThemeMode? theme,
+    AccentColor? accentColor,
+    List<Color>? gradeColors,
+    bool? newsEnabled,
+    String? seenNewsId,
+    bool? notificationsEnabled,
+    bool? notificationsGradesEnabled,
+    bool? notificationsAbsencesEnabled,
+    bool? notificationsMessagesEnabled,
+    bool? notificationsLessonsEnabled,
+    int? notificationsBitfield,
+    bool? developerMode,
+    int? notificationPollInterval,
+    VibrationStrength? vibrate,
+    bool? abWeeks,
+    bool? swapABweeks,
+    UpdateChannel? updateChannel,
+    Config? config,
+    String? xFilcId,
+    bool? graphClassAvg,
+    bool? goodStudent,
+    bool? presentationMode,
+    bool? bellDelayEnabled,
+    int? bellDelay,
+    bool? gradeOpeningFun,
+    IconPack? iconPack,
+    Color? customAccentColor,
+    Color? customBackgroundColor,
+    Color? customHighlightColor,
+    List<String>? premiumScopes,
+    String? premiumAccessToken,
+    String? premiumLogin,
+    String? lastAccountId,
+    bool? renamedSubjectsEnabled,
+    bool? renamedSubjectsItalics,
+    bool? renamedTeachersEnabled,
+    bool? renamedTeachersItalics,
+    Color? liveActivityColor,
+  }) async {
+    if (language != null && language != _language) _language = language;
+    if (startPage != null && startPage != _startPage) _startPage = startPage;
+    if (rounding != null && rounding != _rounding) _rounding = rounding;
+    if (theme != null && theme != _theme) _theme = theme;
+    if (accentColor != null && accentColor != _accentColor) {
+      _accentColor = accentColor;
+    }
+    if (gradeColors != null && gradeColors != _gradeColors) {
+      _gradeColors = gradeColors;
+    }
+    if (newsEnabled != null && newsEnabled != _newsEnabled) {
+      _newsEnabled = newsEnabled;
+    }
+    if (seenNewsId != null && !_seenNews.split(',').contains(seenNewsId)) {
+      var tempList = _seenNews.split(',');
+      tempList.add(seenNewsId);
+      _seenNews = tempList.join(',');
+    }
+    if (notificationsEnabled != null &&
+        notificationsEnabled != _notificationsEnabled) {
+      _notificationsEnabled = notificationsEnabled;
+    }
+    if (notificationsGradesEnabled != null &&
+        notificationsGradesEnabled != _notificationsGradesEnabled) {
+      _notificationsGradesEnabled = notificationsGradesEnabled;
+    }
+    if (notificationsAbsencesEnabled != null &&
+        notificationsAbsencesEnabled != _notificationsAbsencesEnabled) {
+      _notificationsAbsencesEnabled = notificationsAbsencesEnabled;
+    }
+    if (notificationsMessagesEnabled != null &&
+        notificationsMessagesEnabled != _notificationsMessagesEnabled) {
+      _notificationsMessagesEnabled = notificationsMessagesEnabled;
+    }
+    if (notificationsLessonsEnabled != null &&
+        notificationsLessonsEnabled != _notificationsLessonsEnabled) {
+      _notificationsLessonsEnabled = notificationsLessonsEnabled;
+    }
+    if (notificationsBitfield != null &&
+        notificationsBitfield != _notificationsBitfield) {
+      _notificationsBitfield = notificationsBitfield;
+    }
+    if (developerMode != null && developerMode != _developerMode) {
+      _developerMode = developerMode;
+    }
+    if (notificationPollInterval != null &&
+        notificationPollInterval != _notificationPollInterval) {
+      _notificationPollInterval = notificationPollInterval;
+    }
+    if (vibrate != null && vibrate != _vibrate) _vibrate = vibrate;
+    if (abWeeks != null && abWeeks != _abWeeks) _abWeeks = abWeeks;
+    if (swapABweeks != null && swapABweeks != _swapABweeks) {
+      _swapABweeks = swapABweeks;
+    }
+    if (updateChannel != null && updateChannel != _updateChannel) {
+      _updateChannel = updateChannel;
+    }
+    if (config != null && config != _config) _config = config;
+    if (xFilcId != null && xFilcId != _xFilcId) _xFilcId = xFilcId;
+    if (graphClassAvg != null && graphClassAvg != _graphClassAvg) {
+      _graphClassAvg = graphClassAvg;
+    }
+    if (goodStudent != null) _goodStudent = goodStudent;
+    if (presentationMode != null && presentationMode != _presentationMode) {
+      _presentationMode = presentationMode;
+    }
+    if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay;
+    if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) {
+      _bellDelayEnabled = bellDelayEnabled;
+    }
+    if (gradeOpeningFun != null && gradeOpeningFun != _gradeOpeningFun) {
+      _gradeOpeningFun = gradeOpeningFun;
+    }
+    if (iconPack != null && iconPack != _iconPack) _iconPack = iconPack;
+    if (customAccentColor != null && customAccentColor != _customAccentColor) {
+      _customAccentColor = customAccentColor;
+    }
+    if (customBackgroundColor != null &&
+        customBackgroundColor != _customBackgroundColor) {
+      _customBackgroundColor = customBackgroundColor;
+    }
+    if (customHighlightColor != null &&
+        customHighlightColor != _customHighlightColor) {
+      _customHighlightColor = customHighlightColor;
+    }
+    if (premiumScopes != null && premiumScopes != _premiumScopes) {
+      _premiumScopes = premiumScopes;
+    }
+    if (premiumAccessToken != null &&
+        premiumAccessToken != _premiumAccessToken) {
+      _premiumAccessToken = premiumAccessToken;
+    }
+    if (premiumLogin != null && premiumLogin != _premiumLogin) {
+      _premiumLogin = premiumLogin;
+    }
+    if (lastAccountId != null && lastAccountId != _lastAccountId) {
+      _lastAccountId = lastAccountId;
+    }
+    if (renamedSubjectsEnabled != null &&
+        renamedSubjectsEnabled != _renamedSubjectsEnabled) {
+      _renamedSubjectsEnabled = renamedSubjectsEnabled;
+    }
+    if (renamedSubjectsItalics != null &&
+        renamedSubjectsItalics != _renamedSubjectsItalics) {
+      _renamedSubjectsItalics = renamedSubjectsItalics;
+    }
+    if (renamedTeachersEnabled != null &&
+        renamedTeachersEnabled != _renamedTeachersEnabled) {
+      _renamedTeachersEnabled = renamedTeachersEnabled;
+    }
+    if (renamedTeachersItalics != null &&
+        renamedTeachersItalics != _renamedTeachersItalics) {
+      _renamedTeachersItalics = renamedTeachersItalics;
+    }
+    if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
+      _liveActivityColor = liveActivityColor;
+    }
+    if (store) await _database?.store.storeSettings(this);
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo/lib/models/shared_theme.dart b/refilc/lib/models/shared_theme.dart
similarity index 100%
rename from filcnaplo/lib/models/shared_theme.dart
rename to refilc/lib/models/shared_theme.dart
diff --git a/filcnaplo/lib/models/subject_lesson_count.dart b/refilc/lib/models/subject_lesson_count.dart
similarity index 64%
rename from filcnaplo/lib/models/subject_lesson_count.dart
rename to refilc/lib/models/subject_lesson_count.dart
index 8a8adde..606e736 100644
--- a/filcnaplo/lib/models/subject_lesson_count.dart
+++ b/refilc/lib/models/subject_lesson_count.dart
@@ -1,31 +1,35 @@
-import 'package:filcnaplo_kreta_api/models/category.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-
-enum SubjectLessonCountUpdateState { ready, updating }
-
-class SubjectLessonCount {
-  DateTime lastUpdated;
-  Map<Subject, int> subjects;
-  SubjectLessonCountUpdateState state;
-
-  SubjectLessonCount({required this.lastUpdated, required this.subjects, this.state = SubjectLessonCountUpdateState.ready});
-
-  factory SubjectLessonCount.fromMap(Map json) {
-    return SubjectLessonCount(
-      lastUpdated: DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0),
-      subjects: ((json["subjects"] as Map?) ?? {}).map(
-        (key, value) => MapEntry(
-          Subject(id: key, name: "", category: Category.fromJson({})),
-          value,
-        ),
-      ),
-    );
-  }
-
-  Map toMap() {
-    return {
-      "last_updated": lastUpdated.millisecondsSinceEpoch,
-      "subjects": subjects.map((key, value) => MapEntry(key.id, value)),
-    };
-  }
-}
+import 'package:refilc_kreta_api/models/category.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+
+enum SubjectLessonCountUpdateState { ready, updating }
+
+class SubjectLessonCount {
+  DateTime lastUpdated;
+  Map<Subject, int> subjects;
+  SubjectLessonCountUpdateState state;
+
+  SubjectLessonCount(
+      {required this.lastUpdated,
+      required this.subjects,
+      this.state = SubjectLessonCountUpdateState.ready});
+
+  factory SubjectLessonCount.fromMap(Map json) {
+    return SubjectLessonCount(
+      lastUpdated:
+          DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0),
+      subjects: ((json["subjects"] as Map?) ?? {}).map(
+        (key, value) => MapEntry(
+          Subject(id: key, name: "", category: Category.fromJson({})),
+          value,
+        ),
+      ),
+    );
+  }
+
+  Map toMap() {
+    return {
+      "last_updated": lastUpdated.millisecondsSinceEpoch,
+      "subjects": subjects.map((key, value) => MapEntry(key.id, value)),
+    };
+  }
+}
diff --git a/filcnaplo/lib/models/supporter.dart b/refilc/lib/models/supporter.dart
similarity index 96%
rename from filcnaplo/lib/models/supporter.dart
rename to refilc/lib/models/supporter.dart
index 4487094..ef5eced 100644
--- a/filcnaplo/lib/models/supporter.dart
+++ b/refilc/lib/models/supporter.dart
@@ -1,50 +1,50 @@
-enum DonationType { once, monthly }
-
-class Supporter {
-  final String avatar;
-  final String name;
-  final String comment;
-  final int price;
-  final DonationType type;
-
-  const Supporter({required this.avatar, required this.name, this.comment = "", this.price = 0, this.type = DonationType.once});
-
-  factory Supporter.fromJson(Map json, {String? avatarPattern}) {
-    return Supporter(
-      avatar: json["avatar"] ?? avatarPattern != null ? avatarPattern!.replaceFirst("\$", json["name"]) : "",
-      name: json["name"] ?? "Unknown",
-      comment: json["comment"] ?? "",
-      price: json["price"].toInt() ?? 0,
-      type: DonationType.values.asNameMap()[json["type"] ?? "once"] ?? DonationType.once,
-    );
-  }
-}
-
-class Supporters {
-  final double progress;
-  final double max;
-  final String description;
-  final List<Supporter> github;
-  final List<Supporter> patreon;
-
-  Supporters({
-    required this.progress,
-    required this.max,
-    required this.description,
-    required this.github,
-    required this.patreon,
-  });
-
-  factory Supporters.fromJson(Map json) {
-    return Supporters(
-      progress: json["percentage"].toDouble() ?? 100.0,
-      max: json["target"].toDouble() ?? 1.0,
-      description: json["description"] ?? "",
-      github: json["sponsors"]["github"]
-          .map((e) => Supporter.fromJson(e, avatarPattern: "https://github.com/\$.png?size=200"))
-          .cast<Supporter>()
-          .toList(),
-      patreon: json["sponsors"]["patreon"].map((e) => Supporter.fromJson(e)).cast<Supporter>().toList(),
-    );
-  }
-}
+enum DonationType { once, monthly }
+
+class Supporter {
+  final String avatar;
+  final String name;
+  final String comment;
+  final int price;
+  final DonationType type;
+
+  const Supporter({required this.avatar, required this.name, this.comment = "", this.price = 0, this.type = DonationType.once});
+
+  factory Supporter.fromJson(Map json, {String? avatarPattern}) {
+    return Supporter(
+      avatar: json["avatar"] ?? avatarPattern != null ? avatarPattern!.replaceFirst("\$", json["name"]) : "",
+      name: json["name"] ?? "Unknown",
+      comment: json["comment"] ?? "",
+      price: json["price"].toInt() ?? 0,
+      type: DonationType.values.asNameMap()[json["type"] ?? "once"] ?? DonationType.once,
+    );
+  }
+}
+
+class Supporters {
+  final double progress;
+  final double max;
+  final String description;
+  final List<Supporter> github;
+  final List<Supporter> patreon;
+
+  Supporters({
+    required this.progress,
+    required this.max,
+    required this.description,
+    required this.github,
+    required this.patreon,
+  });
+
+  factory Supporters.fromJson(Map json) {
+    return Supporters(
+      progress: json["percentage"].toDouble() ?? 100.0,
+      max: json["target"].toDouble() ?? 1.0,
+      description: json["description"] ?? "",
+      github: json["sponsors"]["github"]
+          .map((e) => Supporter.fromJson(e, avatarPattern: "https://github.com/\$.png?size=200"))
+          .cast<Supporter>()
+          .toList(),
+      patreon: json["sponsors"]["patreon"].map((e) => Supporter.fromJson(e)).cast<Supporter>().toList(),
+    );
+  }
+}
diff --git a/filcnaplo/lib/models/user.dart b/refilc/lib/models/user.dart
similarity index 91%
rename from filcnaplo/lib/models/user.dart
rename to refilc/lib/models/user.dart
index 2cf88e2..43dec18 100644
--- a/filcnaplo/lib/models/user.dart
+++ b/refilc/lib/models/user.dart
@@ -1,96 +1,96 @@
-import 'dart:convert';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/models/student.dart';
-import 'package:uuid/uuid.dart';
-
-enum Role { student, parent }
-
-class User {
-  late String id;
-  String username;
-  String password;
-  String instituteCode;
-  String name;
-  Student student;
-  Role role;
-  String nickname;
-  String picture;
-
-  String get displayName => nickname != '' ? nickname : name;
-
-  User({
-    String? id,
-    required this.name,
-    required this.username,
-    required this.password,
-    required this.instituteCode,
-    required this.student,
-    required this.role,
-    this.nickname = "",
-    this.picture = "",
-  }) {
-    if (id != null) {
-      this.id = id;
-    } else {
-      this.id = const Uuid().v4();
-    }
-  }
-
-  factory User.fromMap(Map map) {
-    return User(
-      id: map["id"],
-      instituteCode: map["institute_code"],
-      username: map["username"],
-      password: map["password"],
-      name: map["name"].trim(),
-      student: Student.fromJson(jsonDecode(map["student"])),
-      role: Role.values[map["role"] ?? 0],
-      nickname: map["nickname"] ?? "",
-      picture: map["picture"] ?? "",
-    );
-  }
-
-  Map<String, Object?> toMap() {
-    return {
-      "id": id,
-      "username": username,
-      "password": password,
-      "institute_code": instituteCode,
-      "name": name,
-      "student": jsonEncode(student.json),
-      "role": role.index,
-      "nickname": nickname,
-      "picture": picture,
-    };
-  }
-
-  @override
-  String toString() => jsonEncode(toMap());
-
-  static Map<String, Object?> loginBody({
-    required String username,
-    required String password,
-    required String instituteCode,
-  }) {
-    return {
-      "userName": username,
-      "password": password,
-      "institute_code": instituteCode,
-      "grant_type": "password",
-      "client_id": KretaAPI.clientId,
-    };
-  }
-
-  static Map<String, Object?> refreshBody({
-    required String refreshToken,
-    required String instituteCode,
-  }) {
-    return {
-      "refresh_token": refreshToken,
-      "institute_code": instituteCode,
-      "client_id": KretaAPI.clientId,
-      "grant_type": "refresh_token",
-      "refresh_user_data": "false",
-    };
-  }
-}
+import 'dart:convert';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/models/student.dart';
+import 'package:uuid/uuid.dart';
+
+enum Role { student, parent }
+
+class User {
+  late String id;
+  String username;
+  String password;
+  String instituteCode;
+  String name;
+  Student student;
+  Role role;
+  String nickname;
+  String picture;
+
+  String get displayName => nickname != '' ? nickname : name;
+
+  User({
+    String? id,
+    required this.name,
+    required this.username,
+    required this.password,
+    required this.instituteCode,
+    required this.student,
+    required this.role,
+    this.nickname = "",
+    this.picture = "",
+  }) {
+    if (id != null) {
+      this.id = id;
+    } else {
+      this.id = const Uuid().v4();
+    }
+  }
+
+  factory User.fromMap(Map map) {
+    return User(
+      id: map["id"],
+      instituteCode: map["institute_code"],
+      username: map["username"],
+      password: map["password"],
+      name: map["name"].trim(),
+      student: Student.fromJson(jsonDecode(map["student"])),
+      role: Role.values[map["role"] ?? 0],
+      nickname: map["nickname"] ?? "",
+      picture: map["picture"] ?? "",
+    );
+  }
+
+  Map<String, Object?> toMap() {
+    return {
+      "id": id,
+      "username": username,
+      "password": password,
+      "institute_code": instituteCode,
+      "name": name,
+      "student": jsonEncode(student.json),
+      "role": role.index,
+      "nickname": nickname,
+      "picture": picture,
+    };
+  }
+
+  @override
+  String toString() => jsonEncode(toMap());
+
+  static Map<String, Object?> loginBody({
+    required String username,
+    required String password,
+    required String instituteCode,
+  }) {
+    return {
+      "userName": username,
+      "password": password,
+      "institute_code": instituteCode,
+      "grant_type": "password",
+      "client_id": KretaAPI.clientId,
+    };
+  }
+
+  static Map<String, Object?> refreshBody({
+    required String refreshToken,
+    required String instituteCode,
+  }) {
+    return {
+      "refresh_token": refreshToken,
+      "institute_code": instituteCode,
+      "client_id": KretaAPI.clientId,
+      "grant_type": "refresh_token",
+      "refresh_user_data": "false",
+    };
+  }
+}
diff --git a/filcnaplo/lib/theme/colors/accent.dart b/refilc/lib/theme/colors/accent.dart
similarity index 96%
rename from filcnaplo/lib/theme/colors/accent.dart
rename to refilc/lib/theme/colors/accent.dart
index 779e82c..152046a 100644
--- a/filcnaplo/lib/theme/colors/accent.dart
+++ b/refilc/lib/theme/colors/accent.dart
@@ -1,33 +1,33 @@
-import 'package:flutter/material.dart';
-
-enum AccentColor {
-  filc,
-  blue,
-  green,
-  lime,
-  yellow,
-  orange,
-  red,
-  pink,
-  purple,
-  none,
-  ogfilc,
-  adaptive,
-  custom
-}
-
-Map<AccentColor, Color> accentColorMap = {
-  AccentColor.filc: const Color(0xFF3D7BF4),
-  AccentColor.blue: Colors.blue.shade300,
-  AccentColor.green: Colors.green.shade400,
-  AccentColor.lime: Colors.lightGreen.shade400,
-  AccentColor.yellow: Colors.orange.shade300,
-  AccentColor.orange: Colors.deepOrange.shade300,
-  AccentColor.red: Colors.red.shade300,
-  AccentColor.pink: Colors.pink.shade300,
-  AccentColor.purple: Colors.purple.shade300,
-  //AccentColor.none: Colors.black,
-  AccentColor.ogfilc: const Color(0xff20AC9B),
-  AccentColor.adaptive: const Color(0xFF3D7BF4),
-  AccentColor.custom: const Color(0xFF3D7BF4),
-};
+import 'package:flutter/material.dart';
+
+enum AccentColor {
+  filc,
+  blue,
+  green,
+  lime,
+  yellow,
+  orange,
+  red,
+  pink,
+  purple,
+  none,
+  ogfilc,
+  adaptive,
+  custom
+}
+
+Map<AccentColor, Color> accentColorMap = {
+  AccentColor.filc: const Color(0xFF3D7BF4),
+  AccentColor.blue: Colors.blue.shade300,
+  AccentColor.green: Colors.green.shade400,
+  AccentColor.lime: Colors.lightGreen.shade400,
+  AccentColor.yellow: Colors.orange.shade300,
+  AccentColor.orange: Colors.deepOrange.shade300,
+  AccentColor.red: Colors.red.shade300,
+  AccentColor.pink: Colors.pink.shade300,
+  AccentColor.purple: Colors.purple.shade300,
+  //AccentColor.none: Colors.black,
+  AccentColor.ogfilc: const Color(0xff20AC9B),
+  AccentColor.adaptive: const Color(0xFF3D7BF4),
+  AccentColor.custom: const Color(0xFF3D7BF4),
+};
diff --git a/filcnaplo/lib/theme/colors/colors.dart b/refilc/lib/theme/colors/colors.dart
similarity index 85%
rename from filcnaplo/lib/theme/colors/colors.dart
rename to refilc/lib/theme/colors/colors.dart
index e28ff48..893c628 100644
--- a/filcnaplo/lib/theme/colors/colors.dart
+++ b/refilc/lib/theme/colors/colors.dart
@@ -1,53 +1,53 @@
-import 'dart:io';
-
-import 'package:filcnaplo/theme/colors/dark_desktop.dart';
-import 'package:filcnaplo/theme/colors/dark_mobile.dart';
-import 'package:filcnaplo/theme/colors/light_desktop.dart';
-import 'package:filcnaplo/theme/colors/light_mobile.dart';
-import 'package:flutter/material.dart';
-
-class AppColors {
-  static ThemeAppColors of(BuildContext context) =>
-      fromBrightness(Theme.of(context).brightness);
-
-  static ThemeAppColors fromBrightness(Brightness brightness) {
-    if (Platform.isAndroid || Platform.isIOS) {
-      switch (brightness) {
-        case Brightness.light:
-          return LightMobileAppColors();
-        case Brightness.dark:
-          return DarkMobileAppColors();
-      }
-    } else {
-      switch (brightness) {
-        case Brightness.light:
-          return LightDesktopAppColors();
-        case Brightness.dark:
-          return DarkDesktopAppColors();
-      }
-    }
-  }
-}
-
-abstract class ThemeAppColors {
-  final Color shadow = const Color(0x00000000);
-  final Color text = const Color(0x00000000);
-  final Color background = const Color(0x00000000);
-  final Color highlight = const Color(0x00000000);
-  final Color red = const Color(0x00000000);
-  final Color orange = const Color(0x00000000);
-  final Color yellow = const Color(0x00000000);
-  final Color green = const Color(0x00000000);
-  final Color filc = const Color(0x00000000);
-  final Color teal = const Color(0x00000000);
-  final Color blue = const Color(0x00000000);
-  final Color indigo = const Color(0x00000000);
-  final Color purple = const Color(0x00000000);
-  final Color pink = const Color(0x00000000);
-  // new default grade colors
-  final Color gradeFive = const Color(0x00000000);
-  final Color gradeFour = const Color(0x00000000);
-  final Color gradeThree = const Color(0x00000000);
-  final Color gradeTwo = const Color(0x00000000);
-  final Color gradeOne = const Color(0x00000000);
-}
+import 'dart:io';
+
+import 'package:refilc/theme/colors/dark_desktop.dart';
+import 'package:refilc/theme/colors/dark_mobile.dart';
+import 'package:refilc/theme/colors/light_desktop.dart';
+import 'package:refilc/theme/colors/light_mobile.dart';
+import 'package:flutter/material.dart';
+
+class AppColors {
+  static ThemeAppColors of(BuildContext context) =>
+      fromBrightness(Theme.of(context).brightness);
+
+  static ThemeAppColors fromBrightness(Brightness brightness) {
+    if (Platform.isAndroid || Platform.isIOS) {
+      switch (brightness) {
+        case Brightness.light:
+          return LightMobileAppColors();
+        case Brightness.dark:
+          return DarkMobileAppColors();
+      }
+    } else {
+      switch (brightness) {
+        case Brightness.light:
+          return LightDesktopAppColors();
+        case Brightness.dark:
+          return DarkDesktopAppColors();
+      }
+    }
+  }
+}
+
+abstract class ThemeAppColors {
+  final Color shadow = const Color(0x00000000);
+  final Color text = const Color(0x00000000);
+  final Color background = const Color(0x00000000);
+  final Color highlight = const Color(0x00000000);
+  final Color red = const Color(0x00000000);
+  final Color orange = const Color(0x00000000);
+  final Color yellow = const Color(0x00000000);
+  final Color green = const Color(0x00000000);
+  final Color filc = const Color(0x00000000);
+  final Color teal = const Color(0x00000000);
+  final Color blue = const Color(0x00000000);
+  final Color indigo = const Color(0x00000000);
+  final Color purple = const Color(0x00000000);
+  final Color pink = const Color(0x00000000);
+  // new default grade colors
+  final Color gradeFive = const Color(0x00000000);
+  final Color gradeFour = const Color(0x00000000);
+  final Color gradeThree = const Color(0x00000000);
+  final Color gradeTwo = const Color(0x00000000);
+  final Color gradeOne = const Color(0x00000000);
+}
diff --git a/filcnaplo/lib/theme/colors/dark_desktop.dart b/refilc/lib/theme/colors/dark_desktop.dart
similarity index 92%
rename from filcnaplo/lib/theme/colors/dark_desktop.dart
rename to refilc/lib/theme/colors/dark_desktop.dart
index 6857f5b..72e5cef 100644
--- a/filcnaplo/lib/theme/colors/dark_desktop.dart
+++ b/refilc/lib/theme/colors/dark_desktop.dart
@@ -1,44 +1,44 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class DarkDesktopAppColors implements ThemeAppColors {
-  @override
-  final shadow = const Color(0x00000000);
-  @override
-  final text = Colors.white;
-  @override
-  final background = const Color.fromARGB(255, 42, 42, 42);
-  @override
-  final highlight = const Color.fromARGB(255, 46, 48, 50);
-  @override
-  final red = const Color(0xffFF453A);
-  @override
-  final orange = const Color(0xffFF9F0A);
-  @override
-  final yellow = const Color(0xffFFD60A);
-  @override
-  final green = const Color(0xff32D74B);
-  @override
-  final filc = const Color(0xff3d7bf4);
-  @override
-  final teal = const Color(0xff64D2FF);
-  @override
-  final blue = const Color(0xff0A84FF);
-  @override
-  final indigo = const Color(0xff5E5CE6);
-  @override
-  final purple = const Color(0xffBF5AF2);
-  @override
-  final pink = const Color(0xffFF375F);
-  // new default grade colors
-  @override
-  final gradeFive = const Color(0xff3d7bf4);
-  @override
-  final gradeFour = const Color(0xFF4C3DF4);
-  @override
-  final gradeThree = const Color(0xFF833DF4);
-  @override
-  final gradeTwo = const Color(0xFFAE3DF4);
-  @override
-  final gradeOne = const Color(0xFFF43DAB);
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class DarkDesktopAppColors implements ThemeAppColors {
+  @override
+  final shadow = const Color(0x00000000);
+  @override
+  final text = Colors.white;
+  @override
+  final background = const Color.fromARGB(255, 42, 42, 42);
+  @override
+  final highlight = const Color.fromARGB(255, 46, 48, 50);
+  @override
+  final red = const Color(0xffFF453A);
+  @override
+  final orange = const Color(0xffFF9F0A);
+  @override
+  final yellow = const Color(0xffFFD60A);
+  @override
+  final green = const Color(0xff32D74B);
+  @override
+  final filc = const Color(0xff3d7bf4);
+  @override
+  final teal = const Color(0xff64D2FF);
+  @override
+  final blue = const Color(0xff0A84FF);
+  @override
+  final indigo = const Color(0xff5E5CE6);
+  @override
+  final purple = const Color(0xffBF5AF2);
+  @override
+  final pink = const Color(0xffFF375F);
+  // new default grade colors
+  @override
+  final gradeFive = const Color(0xff3d7bf4);
+  @override
+  final gradeFour = const Color(0xFF4C3DF4);
+  @override
+  final gradeThree = const Color(0xFF833DF4);
+  @override
+  final gradeTwo = const Color(0xFFAE3DF4);
+  @override
+  final gradeOne = const Color(0xFFF43DAB);
+}
diff --git a/filcnaplo/lib/theme/colors/dark_mobile.dart b/refilc/lib/theme/colors/dark_mobile.dart
similarity index 92%
rename from filcnaplo/lib/theme/colors/dark_mobile.dart
rename to refilc/lib/theme/colors/dark_mobile.dart
index c2c9479..813a2e4 100644
--- a/filcnaplo/lib/theme/colors/dark_mobile.dart
+++ b/refilc/lib/theme/colors/dark_mobile.dart
@@ -1,45 +1,45 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class DarkMobileAppColors implements ThemeAppColors {
-  @override
-  final shadow = const Color(0x00000000);
-  @override
-  final text = Colors.white;
-  @override
-  final background = const Color(0xff000000);
-  @override
-  final highlight = const Color(0xff141516);
-  @override
-  final red = const Color(0xffFF453A);
-  @override
-  final orange = const Color(0xffFF9F0A);
-  @override
-  final yellow = const Color(0xffFFD60A);
-  @override
-  final green = const Color(0xff32D74B);
-  @override
-  final filc = const Color(0xff3d7bf4);
-  @override
-  final teal = const Color(0xff64D2FF);
-  @override
-  final blue = const Color(0xff0A84FF);
-  @override
-  final indigo = const Color(0xff5E5CE6);
-  @override
-  // new default grade colors
-  @override
-  final gradeFive = const Color(0xff3d7bf4);
-  @override
-  final gradeFour = const Color(0xFF4C3DF4);
-  @override
-  final gradeThree = const Color(0xFF833DF4);
-  @override
-  final gradeTwo = const Color(0xFFAE3DF4);
-  @override
-  final gradeOne = const Color(0xFFF43DAB);
-  @override
-  final purple = const Color(0xffBF5AF2);
-  @override
-  final pink = const Color(0xffFF375F);
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class DarkMobileAppColors implements ThemeAppColors {
+  @override
+  final shadow = const Color(0x00000000);
+  @override
+  final text = Colors.white;
+  @override
+  final background = const Color(0xff000000);
+  @override
+  final highlight = const Color(0xff141516);
+  @override
+  final red = const Color(0xffFF453A);
+  @override
+  final orange = const Color(0xffFF9F0A);
+  @override
+  final yellow = const Color(0xffFFD60A);
+  @override
+  final green = const Color(0xff32D74B);
+  @override
+  final filc = const Color(0xff3d7bf4);
+  @override
+  final teal = const Color(0xff64D2FF);
+  @override
+  final blue = const Color(0xff0A84FF);
+  @override
+  final indigo = const Color(0xff5E5CE6);
+  @override
+  // new default grade colors
+  @override
+  final gradeFive = const Color(0xff3d7bf4);
+  @override
+  final gradeFour = const Color(0xFF4C3DF4);
+  @override
+  final gradeThree = const Color(0xFF833DF4);
+  @override
+  final gradeTwo = const Color(0xFFAE3DF4);
+  @override
+  final gradeOne = const Color(0xFFF43DAB);
+  @override
+  final purple = const Color(0xffBF5AF2);
+  @override
+  final pink = const Color(0xffFF375F);
+}
diff --git a/filcnaplo/lib/theme/colors/light_desktop.dart b/refilc/lib/theme/colors/light_desktop.dart
similarity index 92%
rename from filcnaplo/lib/theme/colors/light_desktop.dart
rename to refilc/lib/theme/colors/light_desktop.dart
index a7236fa..e4bd147 100644
--- a/filcnaplo/lib/theme/colors/light_desktop.dart
+++ b/refilc/lib/theme/colors/light_desktop.dart
@@ -1,44 +1,44 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class LightDesktopAppColors implements ThemeAppColors {
-  @override
-  final shadow = const Color(0xffE8E8E8);
-  @override
-  final text = Colors.black;
-  @override
-  final background = const Color(0xffF4F9FF);
-  @override
-  final highlight = const Color(0xffFFFFFF);
-  @override
-  final red = const Color(0xffFF3B30);
-  @override
-  final orange = const Color(0xffFF9500);
-  @override
-  final yellow = const Color(0xffFFCC00);
-  @override
-  final green = const Color(0xff34C759);
-  @override
-  final filc = const Color(0xff3d7bf4);
-  @override
-  final teal = const Color(0xff5AC8FA);
-  @override
-  final blue = const Color(0xff007AFF);
-  @override
-  final indigo = const Color(0xff5856D6);
-  @override
-  final purple = const Color(0xffAF52DE);
-  @override
-  final pink = const Color(0xffFF2D55);
-  // new default grade colors
-  @override
-  final gradeFive = const Color(0xff3d7bf4);
-  @override
-  final gradeFour = const Color(0xFF4C3DF4);
-  @override
-  final gradeThree = const Color(0xFF833DF4);
-  @override
-  final gradeTwo = const Color(0xFFAE3DF4);
-  @override
-  final gradeOne = const Color(0xFFF43DAB);
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class LightDesktopAppColors implements ThemeAppColors {
+  @override
+  final shadow = const Color(0xffE8E8E8);
+  @override
+  final text = Colors.black;
+  @override
+  final background = const Color(0xffF4F9FF);
+  @override
+  final highlight = const Color(0xffFFFFFF);
+  @override
+  final red = const Color(0xffFF3B30);
+  @override
+  final orange = const Color(0xffFF9500);
+  @override
+  final yellow = const Color(0xffFFCC00);
+  @override
+  final green = const Color(0xff34C759);
+  @override
+  final filc = const Color(0xff3d7bf4);
+  @override
+  final teal = const Color(0xff5AC8FA);
+  @override
+  final blue = const Color(0xff007AFF);
+  @override
+  final indigo = const Color(0xff5856D6);
+  @override
+  final purple = const Color(0xffAF52DE);
+  @override
+  final pink = const Color(0xffFF2D55);
+  // new default grade colors
+  @override
+  final gradeFive = const Color(0xff3d7bf4);
+  @override
+  final gradeFour = const Color(0xFF4C3DF4);
+  @override
+  final gradeThree = const Color(0xFF833DF4);
+  @override
+  final gradeTwo = const Color(0xFFAE3DF4);
+  @override
+  final gradeOne = const Color(0xFFF43DAB);
+}
diff --git a/filcnaplo/lib/theme/colors/light_mobile.dart b/refilc/lib/theme/colors/light_mobile.dart
similarity index 92%
rename from filcnaplo/lib/theme/colors/light_mobile.dart
rename to refilc/lib/theme/colors/light_mobile.dart
index db3baf6..8920a5b 100644
--- a/filcnaplo/lib/theme/colors/light_mobile.dart
+++ b/refilc/lib/theme/colors/light_mobile.dart
@@ -1,44 +1,44 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class LightMobileAppColors implements ThemeAppColors {
-  @override
-  final shadow = const Color(0xffE8E8E8);
-  @override
-  final text = const Color(0xFF000000);
-  @override
-  final background = const Color(0xffF4F9FF);
-  @override
-  final highlight = const Color(0xffFFFFFF);
-  @override
-  final red = const Color(0xffFF3B30);
-  @override
-  final orange = const Color(0xffFF9500);
-  @override
-  final yellow = const Color(0xffFFCC00);
-  @override
-  final green = const Color(0xff34C759);
-  @override
-  final filc = const Color(0xff3d7bf4);
-  @override
-  final teal = const Color(0xff5AC8FA);
-  @override
-  final blue = const Color(0xff007AFF);
-  @override
-  final indigo = const Color(0xff5856D6);
-  @override
-  final purple = const Color(0xffAF52DE);
-  @override
-  final pink = const Color(0xffFF2D55);
-  // new default grade colors
-  @override
-  final gradeFive = const Color(0xff3d7bf4);
-  @override
-  final gradeFour = const Color(0xFF4C3DF4);
-  @override
-  final gradeThree = const Color(0xFF833DF4);
-  @override
-  final gradeTwo = const Color(0xFFAE3DF4);
-  @override
-  final gradeOne = const Color(0xFFF43DAB);
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class LightMobileAppColors implements ThemeAppColors {
+  @override
+  final shadow = const Color(0xffE8E8E8);
+  @override
+  final text = const Color(0xFF000000);
+  @override
+  final background = const Color(0xffF4F9FF);
+  @override
+  final highlight = const Color(0xffFFFFFF);
+  @override
+  final red = const Color(0xffFF3B30);
+  @override
+  final orange = const Color(0xffFF9500);
+  @override
+  final yellow = const Color(0xffFFCC00);
+  @override
+  final green = const Color(0xff34C759);
+  @override
+  final filc = const Color(0xff3d7bf4);
+  @override
+  final teal = const Color(0xff5AC8FA);
+  @override
+  final blue = const Color(0xff007AFF);
+  @override
+  final indigo = const Color(0xff5856D6);
+  @override
+  final purple = const Color(0xffAF52DE);
+  @override
+  final pink = const Color(0xffFF2D55);
+  // new default grade colors
+  @override
+  final gradeFive = const Color(0xff3d7bf4);
+  @override
+  final gradeFour = const Color(0xFF4C3DF4);
+  @override
+  final gradeThree = const Color(0xFF833DF4);
+  @override
+  final gradeTwo = const Color(0xFFAE3DF4);
+  @override
+  final gradeOne = const Color(0xFFF43DAB);
+}
diff --git a/filcnaplo/lib/theme/observer.dart b/refilc/lib/theme/observer.dart
similarity index 96%
rename from filcnaplo/lib/theme/observer.dart
rename to refilc/lib/theme/observer.dart
index c8a9bde..e5baaec 100644
--- a/filcnaplo/lib/theme/observer.dart
+++ b/refilc/lib/theme/observer.dart
@@ -1,18 +1,18 @@
-import 'package:flutter/material.dart';
-
-class ThemeModeObserver extends ChangeNotifier {
-  ThemeMode _themeMode;
-  bool _updateNavbarColor;
-  ThemeMode get themeMode => _themeMode;
-  bool get updateNavbarColor => _updateNavbarColor;
-
-  ThemeModeObserver({ThemeMode initialTheme = ThemeMode.system, bool updateNavbarColor = true})
-      : _themeMode = initialTheme,
-        _updateNavbarColor = updateNavbarColor;
-
-  void changeTheme(ThemeMode mode, {bool updateNavbarColor = true}) {
-    _themeMode = mode;
-    _updateNavbarColor = updateNavbarColor;
-    notifyListeners();
-  }
-}
+import 'package:flutter/material.dart';
+
+class ThemeModeObserver extends ChangeNotifier {
+  ThemeMode _themeMode;
+  bool _updateNavbarColor;
+  ThemeMode get themeMode => _themeMode;
+  bool get updateNavbarColor => _updateNavbarColor;
+
+  ThemeModeObserver({ThemeMode initialTheme = ThemeMode.system, bool updateNavbarColor = true})
+      : _themeMode = initialTheme,
+        _updateNavbarColor = updateNavbarColor;
+
+  void changeTheme(ThemeMode mode, {bool updateNavbarColor = true}) {
+    _themeMode = mode;
+    _updateNavbarColor = updateNavbarColor;
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo/lib/theme/theme.dart b/refilc/lib/theme/theme.dart
similarity index 59%
rename from filcnaplo/lib/theme/theme.dart
rename to refilc/lib/theme/theme.dart
index e6e7a0f..1a017a0 100644
--- a/filcnaplo/lib/theme/theme.dart
+++ b/refilc/lib/theme/theme.dart
@@ -1,160 +1,198 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/accent.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/theme/observer.dart';
-import 'package:flutter/material.dart';
-import 'package:material_color_utilities/material_color_utilities.dart';
-import 'package:provider/provider.dart';
-
-class AppTheme {
-  // Dev note: All of these could be constant variables, but this is better for
-  //           development (you don't have to hot-restart)
-
-  static const String _fontFamily = "Montserrat";
-
-  static Color? _paletteAccentLight(CorePalette? palette) => palette != null ? Color(palette.primary.get(70)) : null;
-  static Color? _paletteHighlightLight(CorePalette? palette) => palette != null ? Color(palette.neutral.get(100)) : null;
-  static Color? _paletteBackgroundLight(CorePalette? palette) => palette != null ? Color(palette.neutral.get(95)) : null;
-
-  static Color? _paletteAccentDark(CorePalette? palette) => palette != null ? Color(palette.primary.get(80)) : null;
-  static Color? _paletteBackgroundDark(CorePalette? palette) => palette != null ? Color(palette.neutralVariant.get(10)) : null;
-  static Color? _paletteHighlightDark(CorePalette? palette) => palette != null ? Color(palette.neutralVariant.get(20)) : null;
-
-  // Light Theme
-  static ThemeData lightTheme(BuildContext context, {CorePalette? palette}) {
-    var lightColors = AppColors.fromBrightness(Brightness.light);
-    final settings = Provider.of<SettingsProvider>(context, listen: false);
-    AccentColor accentColor = settings.accentColor;
-    final customAccentColor = accentColor == AccentColor.custom ? settings.customAccentColor : null;
-    Color accent = customAccentColor ?? accentColorMap[accentColor] ?? const Color(0x00000000);
-
-    if (accentColor == AccentColor.adaptive) {
-      if (palette != null) accent = _paletteAccentLight(palette)!;
-    } else {
-      palette = null;
-    }
-
-    Color backgroundColor =
-        (accentColor == AccentColor.custom ? settings.customBackgroundColor : _paletteBackgroundLight(palette)) ?? lightColors.background;
-    Color highlightColor =
-        (accentColor == AccentColor.custom ? settings.customHighlightColor : _paletteHighlightLight(palette)) ?? lightColors.highlight;
-
-    return ThemeData(
-      brightness: Brightness.light,
-      useMaterial3: true,
-      fontFamily: _fontFamily,
-      scaffoldBackgroundColor: backgroundColor,
-      primaryColor: lightColors.filc,
-      dividerColor: const Color(0x00000000),
-      colorScheme: ColorScheme(
-        primary: accent,
-        onPrimary: (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white).withOpacity(.9),
-        secondary: accent,
-        onSecondary: (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white).withOpacity(.9),
-        background: highlightColor,
-        onBackground: Colors.black.withOpacity(.9),
-        brightness: Brightness.light,
-        error: lightColors.red,
-        onError: Colors.white.withOpacity(.9),
-        surface: highlightColor,
-        onSurface: Colors.black.withOpacity(.9),
-      ),
-      shadowColor: lightColors.shadow.withOpacity(.5),
-      appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
-      indicatorColor: accent,
-      iconTheme: IconThemeData(color: lightColors.text.withOpacity(.75)),
-      navigationBarTheme: NavigationBarThemeData(
-        indicatorColor: accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
-        iconTheme: MaterialStateProperty.all(IconThemeData(color: lightColors.text)),
-        backgroundColor: highlightColor,
-        labelTextStyle: MaterialStateProperty.all(TextStyle(
-          fontSize: 13.0,
-          fontWeight: FontWeight.w500,
-          color: lightColors.text.withOpacity(0.8),
-        )),
-        labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
-        height: 76.0,
-      ),
-      sliderTheme: SliderThemeData(
-        inactiveTrackColor: accent.withOpacity(.3),
-      ),
-      progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
-      expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
-      cardColor: highlightColor,
-      bottomNavigationBarTheme: BottomNavigationBarThemeData(
-        backgroundColor: Provider.of<ThemeModeObserver>(context, listen: false).updateNavbarColor ? backgroundColor : null,
-      ),
-    );
-  }
-
-  // Dark Theme
-  static ThemeData darkTheme(BuildContext context, {CorePalette? palette}) {
-    var darkColors = AppColors.fromBrightness(Brightness.dark);
-    final settings = Provider.of<SettingsProvider>(context, listen: false);
-    AccentColor accentColor = settings.accentColor;
-    final customAccentColor = accentColor == AccentColor.custom ? settings.customAccentColor : null;
-    Color accent = customAccentColor ?? accentColorMap[accentColor] ?? const Color(0x00000000);
-
-    if (accentColor == AccentColor.adaptive) {
-      if (palette != null) accent = _paletteAccentDark(palette)!;
-    } else {
-      palette = null;
-    }
-
-    Color backgroundColor =
-        (accentColor == AccentColor.custom ? settings.customBackgroundColor : _paletteBackgroundDark(palette)) ?? darkColors.background;
-    Color highlightColor =
-        (accentColor == AccentColor.custom ? settings.customHighlightColor : _paletteHighlightDark(palette)) ?? darkColors.highlight;
-
-    return ThemeData(
-      brightness: Brightness.dark,
-      useMaterial3: true,
-      fontFamily: _fontFamily,
-      scaffoldBackgroundColor: backgroundColor,
-      primaryColor: darkColors.filc,
-      dividerColor: const Color(0x00000000),
-      colorScheme: ColorScheme(
-        primary: accent,
-        onPrimary: (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white).withOpacity(.9),
-        secondary: accent,
-        onSecondary: (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white).withOpacity(.9),
-        background: highlightColor,
-        onBackground: Colors.white.withOpacity(.9),
-        brightness: Brightness.dark,
-        error: darkColors.red,
-        onError: Colors.black.withOpacity(.9),
-        surface: highlightColor,
-        onSurface: Colors.white.withOpacity(.9),
-      ),
-      shadowColor: highlightColor.withOpacity(.5), //darkColors.shadow,
-      appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
-      indicatorColor: accent,
-      iconTheme: IconThemeData(color: darkColors.text.withOpacity(.75)),
-      navigationBarTheme: NavigationBarThemeData(
-        indicatorColor: accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
-        iconTheme: MaterialStateProperty.all(IconThemeData(color: darkColors.text)),
-        backgroundColor: highlightColor,
-        labelTextStyle: MaterialStateProperty.all(TextStyle(
-          fontSize: 13.0,
-          fontWeight: FontWeight.w500,
-          color: darkColors.text.withOpacity(0.8),
-        )),
-        labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
-        height: 76.0,
-      ),
-      sliderTheme: SliderThemeData(
-        inactiveTrackColor: accent.withOpacity(.3),
-      ),
-      progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
-      expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
-      cardColor: highlightColor,
-      chipTheme: ChipThemeData(
-        backgroundColor: accent.withOpacity(.2),
-        elevation: 1,
-      ),
-      bottomNavigationBarTheme: BottomNavigationBarThemeData(
-        backgroundColor: Provider.of<ThemeModeObserver>(context, listen: false).updateNavbarColor ? backgroundColor : null,
-      ),
-    );
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/accent.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/theme/observer.dart';
+import 'package:flutter/material.dart';
+import 'package:material_color_utilities/material_color_utilities.dart';
+import 'package:provider/provider.dart';
+
+class AppTheme {
+  // Dev note: All of these could be constant variables, but this is better for
+  //           development (you don't have to hot-restart)
+
+  static const String _fontFamily = "Montserrat";
+
+  static Color? _paletteAccentLight(CorePalette? palette) =>
+      palette != null ? Color(palette.primary.get(70)) : null;
+  static Color? _paletteHighlightLight(CorePalette? palette) =>
+      palette != null ? Color(palette.neutral.get(100)) : null;
+  static Color? _paletteBackgroundLight(CorePalette? palette) =>
+      palette != null ? Color(palette.neutral.get(95)) : null;
+
+  static Color? _paletteAccentDark(CorePalette? palette) =>
+      palette != null ? Color(palette.primary.get(80)) : null;
+  static Color? _paletteBackgroundDark(CorePalette? palette) =>
+      palette != null ? Color(palette.neutralVariant.get(10)) : null;
+  static Color? _paletteHighlightDark(CorePalette? palette) =>
+      palette != null ? Color(palette.neutralVariant.get(20)) : null;
+
+  // Light Theme
+  static ThemeData lightTheme(BuildContext context, {CorePalette? palette}) {
+    var lightColors = AppColors.fromBrightness(Brightness.light);
+    final settings = Provider.of<SettingsProvider>(context, listen: false);
+    AccentColor accentColor = settings.accentColor;
+    final customAccentColor =
+        accentColor == AccentColor.custom ? settings.customAccentColor : null;
+    Color accent = customAccentColor ??
+        accentColorMap[accentColor] ??
+        const Color(0x00000000);
+
+    if (accentColor == AccentColor.adaptive) {
+      if (palette != null) accent = _paletteAccentLight(palette)!;
+    } else {
+      palette = null;
+    }
+
+    Color backgroundColor = (accentColor == AccentColor.custom
+            ? settings.customBackgroundColor
+            : _paletteBackgroundLight(palette)) ??
+        lightColors.background;
+    Color highlightColor = (accentColor == AccentColor.custom
+            ? settings.customHighlightColor
+            : _paletteHighlightLight(palette)) ??
+        lightColors.highlight;
+
+    return ThemeData(
+      brightness: Brightness.light,
+      useMaterial3: true,
+      fontFamily: _fontFamily,
+      scaffoldBackgroundColor: backgroundColor,
+      primaryColor: lightColors.filc,
+      dividerColor: const Color(0x00000000),
+      colorScheme: ColorScheme(
+        primary: accent,
+        onPrimary:
+            (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
+                .withOpacity(.9),
+        secondary: accent,
+        onSecondary:
+            (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
+                .withOpacity(.9),
+        background: highlightColor,
+        onBackground: Colors.black.withOpacity(.9),
+        brightness: Brightness.light,
+        error: lightColors.red,
+        onError: Colors.white.withOpacity(.9),
+        surface: highlightColor,
+        onSurface: Colors.black.withOpacity(.9),
+      ),
+      shadowColor: lightColors.shadow.withOpacity(.5),
+      appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
+      indicatorColor: accent,
+      iconTheme: IconThemeData(color: lightColors.text.withOpacity(.75)),
+      navigationBarTheme: NavigationBarThemeData(
+        indicatorColor:
+            accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
+        iconTheme:
+            MaterialStateProperty.all(IconThemeData(color: lightColors.text)),
+        backgroundColor: highlightColor,
+        labelTextStyle: MaterialStateProperty.all(TextStyle(
+          fontSize: 13.0,
+          fontWeight: FontWeight.w500,
+          color: lightColors.text.withOpacity(0.8),
+        )),
+        labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
+        height: 76.0,
+      ),
+      sliderTheme: SliderThemeData(
+        inactiveTrackColor: accent.withOpacity(.3),
+      ),
+      progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
+      expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
+      cardColor: highlightColor,
+      bottomNavigationBarTheme: BottomNavigationBarThemeData(
+        backgroundColor: Provider.of<ThemeModeObserver>(context, listen: false)
+                .updateNavbarColor
+            ? backgroundColor
+            : null,
+      ),
+    );
+  }
+
+  // Dark Theme
+  static ThemeData darkTheme(BuildContext context, {CorePalette? palette}) {
+    var darkColors = AppColors.fromBrightness(Brightness.dark);
+    final settings = Provider.of<SettingsProvider>(context, listen: false);
+    AccentColor accentColor = settings.accentColor;
+    final customAccentColor =
+        accentColor == AccentColor.custom ? settings.customAccentColor : null;
+    Color accent = customAccentColor ??
+        accentColorMap[accentColor] ??
+        const Color(0x00000000);
+
+    if (accentColor == AccentColor.adaptive) {
+      if (palette != null) accent = _paletteAccentDark(palette)!;
+    } else {
+      palette = null;
+    }
+
+    Color backgroundColor = (accentColor == AccentColor.custom
+            ? settings.customBackgroundColor
+            : _paletteBackgroundDark(palette)) ??
+        darkColors.background;
+    Color highlightColor = (accentColor == AccentColor.custom
+            ? settings.customHighlightColor
+            : _paletteHighlightDark(palette)) ??
+        darkColors.highlight;
+
+    return ThemeData(
+      brightness: Brightness.dark,
+      useMaterial3: true,
+      fontFamily: _fontFamily,
+      scaffoldBackgroundColor: backgroundColor,
+      primaryColor: darkColors.filc,
+      dividerColor: const Color(0x00000000),
+      colorScheme: ColorScheme(
+        primary: accent,
+        onPrimary:
+            (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
+                .withOpacity(.9),
+        secondary: accent,
+        onSecondary:
+            (accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
+                .withOpacity(.9),
+        background: highlightColor,
+        onBackground: Colors.white.withOpacity(.9),
+        brightness: Brightness.dark,
+        error: darkColors.red,
+        onError: Colors.black.withOpacity(.9),
+        surface: highlightColor,
+        onSurface: Colors.white.withOpacity(.9),
+      ),
+      shadowColor: highlightColor.withOpacity(.5), //darkColors.shadow,
+      appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
+      indicatorColor: accent,
+      iconTheme: IconThemeData(color: darkColors.text.withOpacity(.75)),
+      navigationBarTheme: NavigationBarThemeData(
+        indicatorColor:
+            accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
+        iconTheme:
+            MaterialStateProperty.all(IconThemeData(color: darkColors.text)),
+        backgroundColor: highlightColor,
+        labelTextStyle: MaterialStateProperty.all(TextStyle(
+          fontSize: 13.0,
+          fontWeight: FontWeight.w500,
+          color: darkColors.text.withOpacity(0.8),
+        )),
+        labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
+        height: 76.0,
+      ),
+      sliderTheme: SliderThemeData(
+        inactiveTrackColor: accent.withOpacity(.3),
+      ),
+      progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
+      expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
+      cardColor: highlightColor,
+      chipTheme: ChipThemeData(
+        backgroundColor: accent.withOpacity(.2),
+        elevation: 1,
+      ),
+      bottomNavigationBarTheme: BottomNavigationBarThemeData(
+        backgroundColor: Provider.of<ThemeModeObserver>(context, listen: false)
+                .updateNavbarColor
+            ? backgroundColor
+            : null,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo/lib/ui/date_widget.dart b/refilc/lib/ui/date_widget.dart
similarity index 96%
rename from filcnaplo/lib/ui/date_widget.dart
rename to refilc/lib/ui/date_widget.dart
index 5295135..65cb12c 100644
--- a/filcnaplo/lib/ui/date_widget.dart
+++ b/refilc/lib/ui/date_widget.dart
@@ -1,8 +1,8 @@
-import 'package:flutter/widgets.dart';
-
-class DateWidget {
-  final DateTime date;
-  final Widget widget;
-  final String? key;
-  const DateWidget({required this.date, required this.widget, this.key});
-}
+import 'package:flutter/widgets.dart';
+
+class DateWidget {
+  final DateTime date;
+  final Widget widget;
+  final String? key;
+  const DateWidget({required this.date, required this.widget, this.key});
+}
diff --git a/filcnaplo/lib/ui/filter/sort.dart b/refilc/lib/ui/filter/sort.dart
similarity index 86%
rename from filcnaplo/lib/ui/filter/sort.dart
rename to refilc/lib/ui/filter/sort.dart
index dee8ba3..95279e8 100644
--- a/filcnaplo/lib/ui/filter/sort.dart
+++ b/refilc/lib/ui/filter/sort.dart
@@ -1,184 +1,184 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo/ui/filter/widgets.dart';
-import 'package:filcnaplo/ui/widgets/message/message_tile.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:animated_list_plus/animated_list_plus.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_tile.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-// difference.inDays is not reliable
-bool _sameDate(DateTime a, DateTime b) =>
-    (a.year == b.year && a.month == b.month && a.day == b.day);
-
-List<Widget> sortDateWidgets(
-  BuildContext context, {
-  required List<DateWidget> dateWidgets,
-  bool showTitle = true,
-  bool showDivider = false,
-  bool hasShadow = false,
-  EdgeInsetsGeometry? padding,
-}) {
-  dateWidgets.sort((a, b) => -a.date.compareTo(b.date));
-
-  List<Conversation> conversations = [];
-  List<DateWidget> convMessages = [];
-
-  // Group messages into conversations
-  for (var w in dateWidgets) {
-    if (w.widget.runtimeType == MessageTile) {
-      Message message = (w.widget as MessageTile).message;
-
-      if (message.conversationId != null) {
-        convMessages.add(w);
-
-        Conversation conv = conversations.firstWhere(
-            (e) => e.id == message.conversationId,
-            orElse: () => Conversation(id: message.conversationId!));
-        conv.add(message);
-        if (conv.messages.length == 1) conversations.add(conv);
-      }
-
-      if (conversations.any((c) => c.id == message.messageId)) {
-        Conversation conv =
-            conversations.firstWhere((e) => e.id == message.messageId);
-        convMessages.add(w);
-        conv.add(message);
-      }
-    }
-  }
-
-  // remove individual messages
-  for (var e in convMessages) {
-    dateWidgets.remove(e);
-  }
-
-  // Add conversations
-  for (var conv in conversations) {
-    conv.sort();
-
-    dateWidgets.add(DateWidget(
-      key: "${conv.newest.date.millisecondsSinceEpoch}-msg",
-      date: conv.newest.date,
-      widget: MessageTile(
-        conv.newest,
-      ),
-    ));
-  }
-
-  dateWidgets.sort((a, b) => -a.date.compareTo(b.date));
-
-  List<List<DateWidget>> groupedDateWidgets = [[]];
-  for (var element in dateWidgets) {
-    if (groupedDateWidgets.last.isNotEmpty) {
-      if (!_sameDate(element.date, groupedDateWidgets.last.last.date)) {
-        groupedDateWidgets.add([element]);
-        continue;
-      }
-    }
-    groupedDateWidgets.last.add(element);
-  }
-
-  List<DateWidget> items = [];
-
-  if (groupedDateWidgets.first.isNotEmpty) {
-    for (var elements in groupedDateWidgets) {
-      bool cst = showTitle;
-
-      // Group Absence Tiles
-      List<DateWidget> absenceTileWidgets = elements.where((element) {
-        return element.widget is AbsenceViewable &&
-            (element.widget as AbsenceViewable).absence.delay == 0;
-      }).toList();
-      List<AbsenceViewable> absenceTiles =
-          absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList();
-      if (absenceTiles.length > 1) {
-        elements.removeWhere((element) =>
-            element.widget.runtimeType == AbsenceViewable &&
-            (element.widget as AbsenceViewable).absence.delay == 0);
-        if (elements.isEmpty) {
-          cst = false;
-        }
-        elements.add(
-          DateWidget(
-              widget: AbsenceGroupTile(
-                absenceTiles,
-                showDate: !cst,
-                padding: const EdgeInsets.symmetric(horizontal: 6.0),
-              ),
-              date: absenceTileWidgets.first.date,
-              key:
-                  "${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group"),
-        );
-      }
-
-      // Bring Lesson Tiles to front & sort by index asc
-      List<DateWidget> lessonTiles = elements.where((element) {
-        return element.widget.runtimeType == ChangedLessonTile;
-      }).toList();
-      lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile)
-          .lesson
-          .lessonIndex
-          .compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex));
-      elements.removeWhere(
-          (element) => element.widget.runtimeType == ChangedLessonTile);
-      elements.insertAll(0, lessonTiles);
-
-      final date = (elements + absenceTileWidgets).first.date;
-      items.add(DateWidget(
-        date: date,
-        widget: Panel(
-          key: ValueKey(date),
-          padding: padding ?? const EdgeInsets.symmetric(vertical: 6.0),
-          title: cst ? Text(date.format(context, forceToday: true)) : null,
-          hasShadow: hasShadow,
-          child: ImplicitlyAnimatedList<DateWidget>(
-            areItemsTheSame: (a, b) => a.key == b.key,
-            spawnIsolate: false,
-            shrinkWrap: true,
-            physics: const NeverScrollableScrollPhysics(),
-            itemBuilder: (context, animation, item, index) =>
-                filterItemBuilder(context, animation, item.widget, index),
-            items: elements,
-          ),
-        ),
-      ));
-    }
-  }
-
-  final nh = DateTime.now();
-  final now =
-      DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1));
-
-  if (showDivider &&
-      items.any((i) => i.date.isBefore(now)) &&
-      items.any((i) => i.date.isAfter(now))) {
-    items.add(
-      DateWidget(
-        date: now,
-        widget: Center(
-          child: Container(
-            margin: const EdgeInsets.symmetric(vertical: 12.0),
-            height: 3.0,
-            width: 150.0,
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(12.0),
-              color: AppColors.of(context).text.withOpacity(.25),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  // Sort future dates asc, past dates desc
-  items.sort((a, b) =>
-      (a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) *
-      a.date.compareTo(b.date));
-
-  return items.map((e) => e.widget).toList();
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc/ui/filter/widgets.dart';
+import 'package:refilc/ui/widgets/message/message_tile.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence_group/absence_group_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:animated_list_plus/animated_list_plus.dart';
+import 'package:refilc_mobile_ui/common/widgets/lesson/changed_lesson_tile.dart';
+import 'package:refilc/utils/format.dart';
+
+// difference.inDays is not reliable
+bool _sameDate(DateTime a, DateTime b) =>
+    (a.year == b.year && a.month == b.month && a.day == b.day);
+
+List<Widget> sortDateWidgets(
+  BuildContext context, {
+  required List<DateWidget> dateWidgets,
+  bool showTitle = true,
+  bool showDivider = false,
+  bool hasShadow = false,
+  EdgeInsetsGeometry? padding,
+}) {
+  dateWidgets.sort((a, b) => -a.date.compareTo(b.date));
+
+  List<Conversation> conversations = [];
+  List<DateWidget> convMessages = [];
+
+  // Group messages into conversations
+  for (var w in dateWidgets) {
+    if (w.widget.runtimeType == MessageTile) {
+      Message message = (w.widget as MessageTile).message;
+
+      if (message.conversationId != null) {
+        convMessages.add(w);
+
+        Conversation conv = conversations.firstWhere(
+            (e) => e.id == message.conversationId,
+            orElse: () => Conversation(id: message.conversationId!));
+        conv.add(message);
+        if (conv.messages.length == 1) conversations.add(conv);
+      }
+
+      if (conversations.any((c) => c.id == message.messageId)) {
+        Conversation conv =
+            conversations.firstWhere((e) => e.id == message.messageId);
+        convMessages.add(w);
+        conv.add(message);
+      }
+    }
+  }
+
+  // remove individual messages
+  for (var e in convMessages) {
+    dateWidgets.remove(e);
+  }
+
+  // Add conversations
+  for (var conv in conversations) {
+    conv.sort();
+
+    dateWidgets.add(DateWidget(
+      key: "${conv.newest.date.millisecondsSinceEpoch}-msg",
+      date: conv.newest.date,
+      widget: MessageTile(
+        conv.newest,
+      ),
+    ));
+  }
+
+  dateWidgets.sort((a, b) => -a.date.compareTo(b.date));
+
+  List<List<DateWidget>> groupedDateWidgets = [[]];
+  for (var element in dateWidgets) {
+    if (groupedDateWidgets.last.isNotEmpty) {
+      if (!_sameDate(element.date, groupedDateWidgets.last.last.date)) {
+        groupedDateWidgets.add([element]);
+        continue;
+      }
+    }
+    groupedDateWidgets.last.add(element);
+  }
+
+  List<DateWidget> items = [];
+
+  if (groupedDateWidgets.first.isNotEmpty) {
+    for (var elements in groupedDateWidgets) {
+      bool cst = showTitle;
+
+      // Group Absence Tiles
+      List<DateWidget> absenceTileWidgets = elements.where((element) {
+        return element.widget is AbsenceViewable &&
+            (element.widget as AbsenceViewable).absence.delay == 0;
+      }).toList();
+      List<AbsenceViewable> absenceTiles =
+          absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList();
+      if (absenceTiles.length > 1) {
+        elements.removeWhere((element) =>
+            element.widget.runtimeType == AbsenceViewable &&
+            (element.widget as AbsenceViewable).absence.delay == 0);
+        if (elements.isEmpty) {
+          cst = false;
+        }
+        elements.add(
+          DateWidget(
+              widget: AbsenceGroupTile(
+                absenceTiles,
+                showDate: !cst,
+                padding: const EdgeInsets.symmetric(horizontal: 6.0),
+              ),
+              date: absenceTileWidgets.first.date,
+              key:
+                  "${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group"),
+        );
+      }
+
+      // Bring Lesson Tiles to front & sort by index asc
+      List<DateWidget> lessonTiles = elements.where((element) {
+        return element.widget.runtimeType == ChangedLessonTile;
+      }).toList();
+      lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile)
+          .lesson
+          .lessonIndex
+          .compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex));
+      elements.removeWhere(
+          (element) => element.widget.runtimeType == ChangedLessonTile);
+      elements.insertAll(0, lessonTiles);
+
+      final date = (elements + absenceTileWidgets).first.date;
+      items.add(DateWidget(
+        date: date,
+        widget: Panel(
+          key: ValueKey(date),
+          padding: padding ?? const EdgeInsets.symmetric(vertical: 6.0),
+          title: cst ? Text(date.format(context, forceToday: true)) : null,
+          hasShadow: hasShadow,
+          child: ImplicitlyAnimatedList<DateWidget>(
+            areItemsTheSame: (a, b) => a.key == b.key,
+            spawnIsolate: false,
+            shrinkWrap: true,
+            physics: const NeverScrollableScrollPhysics(),
+            itemBuilder: (context, animation, item, index) =>
+                filterItemBuilder(context, animation, item.widget, index),
+            items: elements,
+          ),
+        ),
+      ));
+    }
+  }
+
+  final nh = DateTime.now();
+  final now =
+      DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1));
+
+  if (showDivider &&
+      items.any((i) => i.date.isBefore(now)) &&
+      items.any((i) => i.date.isAfter(now))) {
+    items.add(
+      DateWidget(
+        date: now,
+        widget: Center(
+          child: Container(
+            margin: const EdgeInsets.symmetric(vertical: 12.0),
+            height: 3.0,
+            width: 150.0,
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.circular(12.0),
+              color: AppColors.of(context).text.withOpacity(.25),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  // Sort future dates asc, past dates desc
+  items.sort((a, b) =>
+      (a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) *
+      a.date.compareTo(b.date));
+
+  return items.map((e) => e.widget).toList();
+}
diff --git a/filcnaplo/lib/ui/filter/widgets.dart b/refilc/lib/ui/filter/widgets.dart
similarity index 75%
rename from filcnaplo/lib/ui/filter/widgets.dart
rename to refilc/lib/ui/filter/widgets.dart
index ec354a4..83b8e24 100644
--- a/filcnaplo/lib/ui/filter/widgets.dart
+++ b/refilc/lib/ui/filter/widgets.dart
@@ -1,236 +1,236 @@
-import 'package:filcnaplo/api/providers/ad_provider.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo/ui/filter/widgets/grades.dart' as grade_filter;
-import 'package:filcnaplo/ui/filter/widgets/certifications.dart'
-    as certification_filter;
-import 'package:filcnaplo/ui/filter/widgets/messages.dart' as message_filter;
-import 'package:filcnaplo/ui/filter/widgets/absences.dart' as absence_filter;
-import 'package:filcnaplo/ui/filter/widgets/homework.dart' as homework_filter;
-import 'package:filcnaplo/ui/filter/widgets/exams.dart' as exam_filter;
-import 'package:filcnaplo/ui/filter/widgets/notes.dart' as note_filter;
-import 'package:filcnaplo/ui/filter/widgets/events.dart' as event_filter;
-import 'package:filcnaplo/ui/filter/widgets/lessons.dart' as lesson_filter;
-import 'package:filcnaplo/ui/filter/widgets/update.dart' as update_filter;
-import 'package:filcnaplo/ui/filter/widgets/missed_exams.dart'
-    as missed_exam_filter;
-import 'package:filcnaplo/ui/filter/widgets/ads.dart' as ad_filter;
-import 'package:filcnaplo_kreta_api/models/week.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/premium_inline.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:flutter/material.dart';
-import 'package:animated_list_plus/transitions.dart';
-import 'package:provider/provider.dart';
-
-const List<FilterType> homeFilters = [
-  FilterType.all,
-  FilterType.grades,
-  FilterType.messages,
-  FilterType.absences
-];
-
-enum FilterType {
-  all,
-  grades,
-  newGrades,
-  messages,
-  absences,
-  homework,
-  exams,
-  notes,
-  events,
-  lessons,
-  updates,
-  certifications,
-  missedExams,
-  ads,
-}
-
-Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
-    {bool absencesNoExcused = false, required BuildContext context}) async {
-  final gradeProvider = Provider.of<GradeProvider>(context);
-  final timetableProvider = Provider.of<TimetableProvider>(context);
-  final messageProvider = Provider.of<MessageProvider>(context);
-  final absenceProvider = Provider.of<AbsenceProvider>(context);
-  final homeworkProvider = Provider.of<HomeworkProvider>(context);
-  final examProvider = Provider.of<ExamProvider>(context);
-  final noteProvider = Provider.of<NoteProvider>(context);
-  final eventProvider = Provider.of<EventProvider>(context);
-  final updateProvider = Provider.of<UpdateProvider>(context);
-  final settingsProvider = Provider.of<SettingsProvider>(context);
-  final adProvider = Provider.of<AdProvider>(context);
-
-  List<DateWidget> items = [];
-
-  switch (activeData) {
-    // All
-    case FilterType.all:
-      final all = await Future.wait<List<DateWidget>>([
-        getFilterWidgets(FilterType.grades, context: context),
-        getFilterWidgets(FilterType.lessons, context: context),
-        getFilterWidgets(FilterType.messages, context: context),
-        getFilterWidgets(FilterType.absences,
-            context: context, absencesNoExcused: true),
-        getFilterWidgets(FilterType.homework, context: context),
-        getFilterWidgets(FilterType.exams, context: context),
-        getFilterWidgets(FilterType.updates, context: context),
-        getFilterWidgets(FilterType.certifications, context: context),
-        getFilterWidgets(FilterType.missedExams, context: context),
-        getFilterWidgets(FilterType.ads, context: context),
-      ]);
-      items = all.expand((x) => x).toList();
-
-      break;
-
-    // Grades
-    case FilterType.grades:
-      if (!settingsProvider.gradeOpeningFun) {
-        gradeProvider.seenAll();
-      }
-      items = grade_filter.getWidgets(
-          gradeProvider.grades, gradeProvider.lastSeenDate);
-      if (settingsProvider.gradeOpeningFun) {
-        items.addAll(
-            await getFilterWidgets(FilterType.newGrades, context: context));
-      }
-      break;
-
-    // Grades
-    case FilterType.newGrades:
-      items = grade_filter.getNewWidgets(
-          gradeProvider.grades, gradeProvider.lastSeenDate);
-      break;
-
-    // Certifications
-    case FilterType.certifications:
-      items = certification_filter.getWidgets(gradeProvider.grades);
-      break;
-
-    // Messages
-    case FilterType.messages:
-      items = message_filter.getWidgets(
-        messageProvider.messages,
-        noteProvider.notes,
-        eventProvider.events,
-      );
-      break;
-
-    // Absences
-    case FilterType.absences:
-      items = absence_filter.getWidgets(absenceProvider.absences,
-          noExcused: absencesNoExcused);
-      break;
-
-    // Homework
-    case FilterType.homework:
-      items = homework_filter.getWidgets(homeworkProvider.homework);
-      break;
-
-    // Exams
-    case FilterType.exams:
-      items = exam_filter.getWidgets(examProvider.exams);
-      break;
-
-    // Notes
-    case FilterType.notes:
-      items = note_filter.getWidgets(noteProvider.notes);
-      break;
-
-    // Events
-    case FilterType.events:
-      items = event_filter.getWidgets(eventProvider.events);
-      break;
-
-    // Changed Lessons
-    case FilterType.lessons:
-      items = lesson_filter
-          .getWidgets(timetableProvider.getWeek(Week.current()) ?? []);
-      break;
-
-    // Updates
-    case FilterType.updates:
-      if (updateProvider.available) {
-        items = [update_filter.getWidget(updateProvider.releases.first)];
-      }
-      break;
-
-    // Missed Exams
-    case FilterType.missedExams:
-      items = missed_exam_filter
-          .getWidgets(timetableProvider.getWeek(Week.current()) ?? []);
-      break;
-
-    // Ads
-    case FilterType.ads:
-      if (adProvider.available) {
-        items = ad_filter.getWidgets(adProvider.ads);
-      }
-      break;
-  }
-  return items;
-}
-
-Widget filterItemBuilder(
-    BuildContext context, Animation<double> animation, Widget item, int index) {
-  if (item.key == const Key("\$premium")) {
-    return Provider.of<PremiumProvider>(context, listen: false).hasPremium ||
-            DateTime.now().weekday <= 5
-        ? const SizedBox()
-        : const Padding(
-            padding: EdgeInsets.only(bottom: 24.0),
-            child: PremiumInline(features: [
-              PremiumInlineFeature.nickname,
-              PremiumInlineFeature.theme,
-              PremiumInlineFeature.widget,
-            ]),
-          );
-  }
-
-  final wrappedItem = SizeFadeTransition(
-    curve: Curves.easeInOutCubic,
-    animation: animation,
-    child: item,
-  );
-
-  return item is Panel
-      // Re-add & animate shadow
-      ? AnimatedBuilder(
-          animation: animation,
-          child: wrappedItem,
-          builder: (context, child) {
-            return Padding(
-              padding: const EdgeInsets.only(bottom: 12.0),
-              child: DecoratedBox(
-                decoration: BoxDecoration(
-                  boxShadow: [
-                    BoxShadow(
-                      offset: const Offset(0, 21),
-                      blurRadius: 23.0,
-                      color: Theme.of(context).shadowColor.withOpacity(
-                            Theme.of(context).shadowColor.opacity *
-                                CurvedAnimation(
-                                  parent: CurvedAnimation(
-                                      parent: animation,
-                                      curve: Curves.easeInOutCubic),
-                                  curve: const Interval(2 / 3, 1.0),
-                                ).value,
-                          ),
-                    ),
-                  ],
-                ),
-                child: child,
-              ),
-            );
-          })
-      : wrappedItem;
-}
+import 'package:refilc/api/providers/ad_provider.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc/ui/filter/widgets/grades.dart' as grade_filter;
+import 'package:refilc/ui/filter/widgets/certifications.dart'
+    as certification_filter;
+import 'package:refilc/ui/filter/widgets/messages.dart' as message_filter;
+import 'package:refilc/ui/filter/widgets/absences.dart' as absence_filter;
+import 'package:refilc/ui/filter/widgets/homework.dart' as homework_filter;
+import 'package:refilc/ui/filter/widgets/exams.dart' as exam_filter;
+import 'package:refilc/ui/filter/widgets/notes.dart' as note_filter;
+import 'package:refilc/ui/filter/widgets/events.dart' as event_filter;
+import 'package:refilc/ui/filter/widgets/lessons.dart' as lesson_filter;
+import 'package:refilc/ui/filter/widgets/update.dart' as update_filter;
+import 'package:refilc/ui/filter/widgets/missed_exams.dart'
+    as missed_exam_filter;
+import 'package:refilc/ui/filter/widgets/ads.dart' as ad_filter;
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/premium_inline.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:flutter/material.dart';
+import 'package:animated_list_plus/transitions.dart';
+import 'package:provider/provider.dart';
+
+const List<FilterType> homeFilters = [
+  FilterType.all,
+  FilterType.grades,
+  FilterType.messages,
+  FilterType.absences
+];
+
+enum FilterType {
+  all,
+  grades,
+  newGrades,
+  messages,
+  absences,
+  homework,
+  exams,
+  notes,
+  events,
+  lessons,
+  updates,
+  certifications,
+  missedExams,
+  ads,
+}
+
+Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
+    {bool absencesNoExcused = false, required BuildContext context}) async {
+  final gradeProvider = Provider.of<GradeProvider>(context);
+  final timetableProvider = Provider.of<TimetableProvider>(context);
+  final messageProvider = Provider.of<MessageProvider>(context);
+  final absenceProvider = Provider.of<AbsenceProvider>(context);
+  final homeworkProvider = Provider.of<HomeworkProvider>(context);
+  final examProvider = Provider.of<ExamProvider>(context);
+  final noteProvider = Provider.of<NoteProvider>(context);
+  final eventProvider = Provider.of<EventProvider>(context);
+  final updateProvider = Provider.of<UpdateProvider>(context);
+  final settingsProvider = Provider.of<SettingsProvider>(context);
+  final adProvider = Provider.of<AdProvider>(context);
+
+  List<DateWidget> items = [];
+
+  switch (activeData) {
+    // All
+    case FilterType.all:
+      final all = await Future.wait<List<DateWidget>>([
+        getFilterWidgets(FilterType.grades, context: context),
+        getFilterWidgets(FilterType.lessons, context: context),
+        getFilterWidgets(FilterType.messages, context: context),
+        getFilterWidgets(FilterType.absences,
+            context: context, absencesNoExcused: true),
+        getFilterWidgets(FilterType.homework, context: context),
+        getFilterWidgets(FilterType.exams, context: context),
+        getFilterWidgets(FilterType.updates, context: context),
+        getFilterWidgets(FilterType.certifications, context: context),
+        getFilterWidgets(FilterType.missedExams, context: context),
+        getFilterWidgets(FilterType.ads, context: context),
+      ]);
+      items = all.expand((x) => x).toList();
+
+      break;
+
+    // Grades
+    case FilterType.grades:
+      if (!settingsProvider.gradeOpeningFun) {
+        gradeProvider.seenAll();
+      }
+      items = grade_filter.getWidgets(
+          gradeProvider.grades, gradeProvider.lastSeenDate);
+      if (settingsProvider.gradeOpeningFun) {
+        items.addAll(
+            await getFilterWidgets(FilterType.newGrades, context: context));
+      }
+      break;
+
+    // Grades
+    case FilterType.newGrades:
+      items = grade_filter.getNewWidgets(
+          gradeProvider.grades, gradeProvider.lastSeenDate);
+      break;
+
+    // Certifications
+    case FilterType.certifications:
+      items = certification_filter.getWidgets(gradeProvider.grades);
+      break;
+
+    // Messages
+    case FilterType.messages:
+      items = message_filter.getWidgets(
+        messageProvider.messages,
+        noteProvider.notes,
+        eventProvider.events,
+      );
+      break;
+
+    // Absences
+    case FilterType.absences:
+      items = absence_filter.getWidgets(absenceProvider.absences,
+          noExcused: absencesNoExcused);
+      break;
+
+    // Homework
+    case FilterType.homework:
+      items = homework_filter.getWidgets(homeworkProvider.homework);
+      break;
+
+    // Exams
+    case FilterType.exams:
+      items = exam_filter.getWidgets(examProvider.exams);
+      break;
+
+    // Notes
+    case FilterType.notes:
+      items = note_filter.getWidgets(noteProvider.notes);
+      break;
+
+    // Events
+    case FilterType.events:
+      items = event_filter.getWidgets(eventProvider.events);
+      break;
+
+    // Changed Lessons
+    case FilterType.lessons:
+      items = lesson_filter
+          .getWidgets(timetableProvider.getWeek(Week.current()) ?? []);
+      break;
+
+    // Updates
+    case FilterType.updates:
+      if (updateProvider.available) {
+        items = [update_filter.getWidget(updateProvider.releases.first)];
+      }
+      break;
+
+    // Missed Exams
+    case FilterType.missedExams:
+      items = missed_exam_filter
+          .getWidgets(timetableProvider.getWeek(Week.current()) ?? []);
+      break;
+
+    // Ads
+    case FilterType.ads:
+      if (adProvider.available) {
+        items = ad_filter.getWidgets(adProvider.ads);
+      }
+      break;
+  }
+  return items;
+}
+
+Widget filterItemBuilder(
+    BuildContext context, Animation<double> animation, Widget item, int index) {
+  if (item.key == const Key("\$premium")) {
+    return Provider.of<PremiumProvider>(context, listen: false).hasPremium ||
+            DateTime.now().weekday <= 5
+        ? const SizedBox()
+        : const Padding(
+            padding: EdgeInsets.only(bottom: 24.0),
+            child: PremiumInline(features: [
+              PremiumInlineFeature.nickname,
+              PremiumInlineFeature.theme,
+              PremiumInlineFeature.widget,
+            ]),
+          );
+  }
+
+  final wrappedItem = SizeFadeTransition(
+    curve: Curves.easeInOutCubic,
+    animation: animation,
+    child: item,
+  );
+
+  return item is Panel
+      // Re-add & animate shadow
+      ? AnimatedBuilder(
+          animation: animation,
+          child: wrappedItem,
+          builder: (context, child) {
+            return Padding(
+              padding: const EdgeInsets.only(bottom: 12.0),
+              child: DecoratedBox(
+                decoration: BoxDecoration(
+                  boxShadow: [
+                    BoxShadow(
+                      offset: const Offset(0, 21),
+                      blurRadius: 23.0,
+                      color: Theme.of(context).shadowColor.withOpacity(
+                            Theme.of(context).shadowColor.opacity *
+                                CurvedAnimation(
+                                  parent: CurvedAnimation(
+                                      parent: animation,
+                                      curve: Curves.easeInOutCubic),
+                                  curve: const Interval(2 / 3, 1.0),
+                                ).value,
+                          ),
+                    ),
+                  ],
+                ),
+                child: child,
+              ),
+            );
+          })
+      : wrappedItem;
+}
diff --git a/refilc/lib/ui/filter/widgets/absences.dart b/refilc/lib/ui/filter/widgets/absences.dart
new file mode 100644
index 0000000..2d4a99e
--- /dev/null
+++ b/refilc/lib/ui/filter/widgets/absences.dart
@@ -0,0 +1,19 @@
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Absence> providerAbsences,
+    {bool noExcused = false}) {
+  List<DateWidget> items = [];
+  providerAbsences
+      .where((a) => !noExcused || a.state != Justification.excused)
+      .forEach((absence) {
+    items.add(DateWidget(
+      key: absence.id,
+      date: absence.date,
+      widget: mobile.AbsenceViewable(absence),
+    ));
+  });
+  return items;
+}
diff --git a/filcnaplo/lib/ui/filter/widgets/ads.dart b/refilc/lib/ui/filter/widgets/ads.dart
similarity index 73%
rename from filcnaplo/lib/ui/filter/widgets/ads.dart
rename to refilc/lib/ui/filter/widgets/ads.dart
index 48c39b1..6be93f1 100644
--- a/filcnaplo/lib/ui/filter/widgets/ads.dart
+++ b/refilc/lib/ui/filter/widgets/ads.dart
@@ -1,7 +1,6 @@
-import 'package:filcnaplo/models/ad.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/ad/ad_viewable.dart'
-    as mobile;
+import 'package:refilc/models/ad.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_mobile_ui/common/widgets/ad/ad_viewable.dart' as mobile;
 
 List<DateWidget> getWidgets(List<Ad> providerAds) {
   List<DateWidget> items = [];
diff --git a/filcnaplo/lib/ui/filter/widgets/certifications.dart b/refilc/lib/ui/filter/widgets/certifications.dart
similarity index 57%
rename from filcnaplo/lib/ui/filter/widgets/certifications.dart
rename to refilc/lib/ui/filter/widgets/certifications.dart
index a7d0317..ade4419 100644
--- a/filcnaplo/lib/ui/filter/widgets/certifications.dart
+++ b/refilc/lib/ui/filter/widgets/certifications.dart
@@ -1,24 +1,27 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_card.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Grade> providerGrades) {
-  List<DateWidget> items = [];
-  for (var gradeType in GradeType.values) {
-    if ([GradeType.midYear, GradeType.unknown, GradeType.levelExam].contains(gradeType)) continue;
-
-    List<Grade> grades = providerGrades.where((grade) => grade.type == gradeType).toList();
-    if (grades.isNotEmpty) {
-      grades.sort((a, b) => -a.date.compareTo(b.date));
-
-      items.add(DateWidget(
-        date: grades.first.date,
-        widget: mobile.CertificationCard(
-          grades,
-          gradeType: gradeType,
-        ),
-      ));
-    }
-  }
-  return items;
-}
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/common/widgets/cretification/certification_card.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Grade> providerGrades) {
+  List<DateWidget> items = [];
+  for (var gradeType in GradeType.values) {
+    if ([GradeType.midYear, GradeType.unknown, GradeType.levelExam]
+        .contains(gradeType)) continue;
+
+    List<Grade> grades =
+        providerGrades.where((grade) => grade.type == gradeType).toList();
+    if (grades.isNotEmpty) {
+      grades.sort((a, b) => -a.date.compareTo(b.date));
+
+      items.add(DateWidget(
+        date: grades.first.date,
+        widget: mobile.CertificationCard(
+          grades,
+          gradeType: gradeType,
+        ),
+      ));
+    }
+  }
+  return items;
+}
diff --git a/filcnaplo/lib/ui/filter/widgets/events.dart b/refilc/lib/ui/filter/widgets/events.dart
similarity index 56%
rename from filcnaplo/lib/ui/filter/widgets/events.dart
rename to refilc/lib/ui/filter/widgets/events.dart
index c72d446..3704d7d 100644
--- a/filcnaplo/lib/ui/filter/widgets/events.dart
+++ b/refilc/lib/ui/filter/widgets/events.dart
@@ -1,15 +1,16 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/event/event_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Event> providerEvents) {
-  List<DateWidget> items = [];
-  for (var event in providerEvents) {
-    items.add(DateWidget(
-      key: event.id,
-      date: event.start,
-      widget: mobile.EventViewable(event),
-    ));
-  }
-  return items;
-}
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc_mobile_ui/common/widgets/event/event_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Event> providerEvents) {
+  List<DateWidget> items = [];
+  for (var event in providerEvents) {
+    items.add(DateWidget(
+      key: event.id,
+      date: event.start,
+      widget: mobile.EventViewable(event),
+    ));
+  }
+  return items;
+}
diff --git a/filcnaplo/lib/ui/filter/widgets/exams.dart b/refilc/lib/ui/filter/widgets/exams.dart
similarity index 60%
rename from filcnaplo/lib/ui/filter/widgets/exams.dart
rename to refilc/lib/ui/filter/widgets/exams.dart
index 98d0fc2..f6a6974 100644
--- a/filcnaplo/lib/ui/filter/widgets/exams.dart
+++ b/refilc/lib/ui/filter/widgets/exams.dart
@@ -1,15 +1,16 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Exam> providerExams) {
-  List<DateWidget> items = [];
-  for (var exam in providerExams) {
-    items.add(DateWidget(
-      key: exam.id,
-      date: exam.writeDate.year != 0 ? exam.writeDate : exam.date,
-      widget: mobile.ExamViewable(exam),
-    ));
-  }
-  return items;
-}
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:refilc_mobile_ui/common/widgets/exam/exam_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Exam> providerExams) {
+  List<DateWidget> items = [];
+  for (var exam in providerExams) {
+    items.add(DateWidget(
+      key: exam.id,
+      date: exam.writeDate.year != 0 ? exam.writeDate : exam.date,
+      widget: mobile.ExamViewable(exam),
+    ));
+  }
+  return items;
+}
diff --git a/refilc/lib/ui/filter/widgets/grades.dart b/refilc/lib/ui/filter/widgets/grades.dart
new file mode 100644
index 0000000..e8326ce
--- /dev/null
+++ b/refilc/lib/ui/filter/widgets/grades.dart
@@ -0,0 +1,52 @@
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc/utils/platform.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart'
+    as mobile;
+import 'package:refilc_mobile_ui/common/widgets/grade/new_grades.dart'
+    as mobile;
+import 'package:refilc_desktop_ui/common/widgets/grade/grade_viewable.dart'
+    as desktop;
+
+List<DateWidget> getWidgets(
+    List<Grade> providerGrades, DateTime? lastSeenDate) {
+  List<DateWidget> items = [];
+  for (var grade in providerGrades) {
+    final surprise =
+        (!(lastSeenDate != null && grade.date.isAfter(lastSeenDate)) ||
+            grade.value.value == 0);
+    if (grade.type == GradeType.midYear && surprise) {
+      items.add(DateWidget(
+        key: grade.id,
+        date: grade.date,
+        widget: PlatformUtils.isMobile
+            ? mobile.GradeViewable(grade)
+            : desktop.GradeViewable(grade),
+      ));
+    }
+  }
+  return items;
+}
+
+List<DateWidget> getNewWidgets(
+    List<Grade> providerGrades, DateTime? lastSeenDate) {
+  List<DateWidget> items = [];
+  List<Grade> newGrades = [];
+  for (var grade in providerGrades) {
+    final surprise =
+        !(lastSeenDate != null && !grade.date.isAfter(lastSeenDate)) &&
+            grade.value.value != 0;
+    if (grade.type == GradeType.midYear && surprise) {
+      newGrades.add(grade);
+    }
+  }
+  newGrades.sort((a, b) => a.date.compareTo(b.date));
+  if (newGrades.isNotEmpty) {
+    items.add(DateWidget(
+      key: newGrades.last.id,
+      date: newGrades.last.date,
+      widget: mobile.NewGradesSurprise(newGrades),
+    ));
+  }
+  return items;
+}
diff --git a/filcnaplo/lib/ui/filter/widgets/homework.dart b/refilc/lib/ui/filter/widgets/homework.dart
similarity index 61%
rename from filcnaplo/lib/ui/filter/widgets/homework.dart
rename to refilc/lib/ui/filter/widgets/homework.dart
index 5698666..8ceacbd 100644
--- a/filcnaplo/lib/ui/filter/widgets/homework.dart
+++ b/refilc/lib/ui/filter/widgets/homework.dart
@@ -1,15 +1,16 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Homework> providerHomework) {
-  List<DateWidget> items = [];
-  for (var homework in providerHomework) {
-    items.add(DateWidget(
-      key: homework.id,
-      date: homework.deadline.year != 0 ? homework.deadline : homework.date,
-      widget: mobile.HomeworkViewable(homework),
-    ));
-  }
-  return items;
-}
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc_mobile_ui/common/widgets/homework/homework_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Homework> providerHomework) {
+  List<DateWidget> items = [];
+  for (var homework in providerHomework) {
+    items.add(DateWidget(
+      key: homework.id,
+      date: homework.deadline.year != 0 ? homework.deadline : homework.date,
+      widget: mobile.HomeworkViewable(homework),
+    ));
+  }
+  return items;
+}
diff --git a/refilc/lib/ui/filter/widgets/lessons.dart b/refilc/lib/ui/filter/widgets/lessons.dart
new file mode 100644
index 0000000..74283a6
--- /dev/null
+++ b/refilc/lib/ui/filter/widgets/lessons.dart
@@ -0,0 +1,19 @@
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/widgets/lesson/changed_lesson_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Lesson> providerLessons) {
+  List<DateWidget> items = [];
+  providerLessons
+      .where((l) => l.isChanged && l.start.isAfter(DateTime.now()))
+      .forEach((lesson) {
+    items.add(DateWidget(
+      key: lesson.id,
+      date: DateTime(lesson.date.year, lesson.date.month, lesson.date.day,
+          lesson.start.hour, lesson.start.minute),
+      widget: mobile.ChangedLessonViewable(lesson),
+    ));
+  });
+  return items;
+}
diff --git a/refilc/lib/ui/filter/widgets/messages.dart b/refilc/lib/ui/filter/widgets/messages.dart
new file mode 100644
index 0000000..13bbed1
--- /dev/null
+++ b/refilc/lib/ui/filter/widgets/messages.dart
@@ -0,0 +1,25 @@
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc/ui/filter/widgets/notes.dart' as note_filter;
+import 'package:refilc/ui/filter/widgets/events.dart' as event_filter;
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/message_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Message> providerMessages,
+    List<Note> providerNotes, List<Event> providerEvents) {
+  List<DateWidget> items = [];
+  for (var message in providerMessages) {
+    if (message.type == MessageType.inbox) {
+      items.add(DateWidget(
+        key: "${message.id}",
+        date: message.date,
+        widget: mobile.MessageViewable(message),
+      ));
+    }
+  }
+  items.addAll(note_filter.getWidgets(providerNotes));
+  items.addAll(event_filter.getWidgets(providerEvents));
+  return items;
+}
diff --git a/filcnaplo/lib/ui/filter/widgets/missed_exams.dart b/refilc/lib/ui/filter/widgets/missed_exams.dart
similarity index 76%
rename from filcnaplo/lib/ui/filter/widgets/missed_exams.dart
rename to refilc/lib/ui/filter/widgets/missed_exams.dart
index c97d7c7..db596c0 100644
--- a/filcnaplo/lib/ui/filter/widgets/missed_exams.dart
+++ b/refilc/lib/ui/filter/widgets/missed_exams.dart
@@ -1,35 +1,35 @@
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/missed_exam/missed_exam_viewable.dart';
-
-List<DateWidget> getWidgets(List<Lesson> providerLessons) {
-  List<DateWidget> items = [];
-  List<Lesson> missedExams = [];
-
-  for (var lesson in providerLessons) {
-    final desc = lesson.description.toLowerCase().specialChars();
-    // Check if lesson description includes hints for an exam written during the lesson
-    if (!lesson.studentPresence &&
-        (lesson.exam != "" ||
-            desc.contains("dolgozat") ||
-            desc.contains("feleles") ||
-            desc.contains("temazaro") ||
-            desc.contains("szamonkeres") ||
-            desc == "tz") &&
-        !(desc.contains("felkeszules") || desc.contains("gyakorlas"))) {
-      missedExams.add(lesson);
-    }
-  }
-
-  if (missedExams.isNotEmpty) {
-    missedExams.sort((a, b) => -a.date.compareTo(b.date));
-
-    items.add(DateWidget(
-      date: missedExams.first.date,
-      widget: MissedExamViewable(missedExams),
-    ));
-  }
-
-  return items;
-}
+import 'package:refilc/utils/format.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/widgets/missed_exam/missed_exam_viewable.dart';
+
+List<DateWidget> getWidgets(List<Lesson> providerLessons) {
+  List<DateWidget> items = [];
+  List<Lesson> missedExams = [];
+
+  for (var lesson in providerLessons) {
+    final desc = lesson.description.toLowerCase().specialChars();
+    // Check if lesson description includes hints for an exam written during the lesson
+    if (!lesson.studentPresence &&
+        (lesson.exam != "" ||
+            desc.contains("dolgozat") ||
+            desc.contains("feleles") ||
+            desc.contains("temazaro") ||
+            desc.contains("szamonkeres") ||
+            desc == "tz") &&
+        !(desc.contains("felkeszules") || desc.contains("gyakorlas"))) {
+      missedExams.add(lesson);
+    }
+  }
+
+  if (missedExams.isNotEmpty) {
+    missedExams.sort((a, b) => -a.date.compareTo(b.date));
+
+    items.add(DateWidget(
+      date: missedExams.first.date,
+      widget: MissedExamViewable(missedExams),
+    ));
+  }
+
+  return items;
+}
diff --git a/filcnaplo/lib/ui/filter/widgets/notes.dart b/refilc/lib/ui/filter/widgets/notes.dart
similarity index 56%
rename from filcnaplo/lib/ui/filter/widgets/notes.dart
rename to refilc/lib/ui/filter/widgets/notes.dart
index 3959069..044ddc6 100644
--- a/filcnaplo/lib/ui/filter/widgets/notes.dart
+++ b/refilc/lib/ui/filter/widgets/notes.dart
@@ -1,15 +1,16 @@
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/note/note_viewable.dart' as mobile;
-
-List<DateWidget> getWidgets(List<Note> providerNotes) {
-  List<DateWidget> items = [];
-  for (var note in providerNotes) {
-    items.add(DateWidget(
-      key: note.id,
-      date: note.date,
-      widget: mobile.NoteViewable(note),
-    ));
-  }
-  return items;
-}
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_mobile_ui/common/widgets/note/note_viewable.dart'
+    as mobile;
+
+List<DateWidget> getWidgets(List<Note> providerNotes) {
+  List<DateWidget> items = [];
+  for (var note in providerNotes) {
+    items.add(DateWidget(
+      key: note.id,
+      date: note.date,
+      widget: mobile.NoteViewable(note),
+    ));
+  }
+  return items;
+}
diff --git a/refilc/lib/ui/filter/widgets/update.dart b/refilc/lib/ui/filter/widgets/update.dart
new file mode 100644
index 0000000..ce48969
--- /dev/null
+++ b/refilc/lib/ui/filter/widgets/update.dart
@@ -0,0 +1,11 @@
+import 'package:refilc/models/release.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_mobile_ui/common/widgets/update/update_viewable.dart'
+    as mobile;
+
+DateWidget getWidget(Release providerRelease) {
+  return DateWidget(
+    date: DateTime.now(),
+    widget: mobile.UpdateViewable(providerRelease),
+  );
+}
diff --git a/filcnaplo/lib/ui/widgets/grade/grade_tile.dart b/refilc/lib/ui/widgets/grade/grade_tile.dart
similarity index 87%
rename from filcnaplo/lib/ui/widgets/grade/grade_tile.dart
rename to refilc/lib/ui/widgets/grade/grade_tile.dart
index 50e0d3a..80ce9e8 100644
--- a/filcnaplo/lib/ui/widgets/grade/grade_tile.dart
+++ b/refilc/lib/ui/widgets/grade/grade_tile.dart
@@ -1,333 +1,336 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-
-class GradeTile extends StatelessWidget {
-  const GradeTile(this.grade,
-      {Key? key, this.onTap, this.padding, this.censored = false})
-      : super(key: key);
-
-  final Grade grade;
-  final void Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-  final bool censored;
-
-  @override
-  Widget build(BuildContext context) {
-    String title;
-    String subtitle;
-    bool isTitleItalic = false;
-    bool isSubtitleItalic = false;
-    EdgeInsets leadingPadding = EdgeInsets.zero;
-    bool isSubjectView = SubjectGradesContainer.of(context) != null;
-    String subjectName =
-        grade.subject.renamedTo ?? grade.subject.name.capital();
-    String modeDescription = grade.mode.description.capital();
-    String description = grade.description.capital();
-
-    GradeCalculatorProvider calculatorProvider =
-        Provider.of<GradeCalculatorProvider>(context, listen: false);
-    SettingsProvider settingsProvider =
-        Provider.of<SettingsProvider>(context);
-    // Test order:
-    // description
-    // mode
-    // value name
-    if (grade.type == GradeType.midYear || grade.type == GradeType.ghost) {
-      if (grade.description != "") {
-        title = description;
-      } else {
-        title = modeDescription != ""
-            ? modeDescription
-            : grade.value.valueName.split("(")[0];
-      }
-    } else {
-      title = subjectName;
-      isTitleItalic = grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
-    }
-
-    // Test order:
-    // subject name
-    // mode + weight != 100
-    if (grade.type == GradeType.midYear) {
-      subtitle = isSubjectView
-          ? description != ""
-              ? modeDescription
-              : ""
-          : subjectName;
-      isSubtitleItalic = isSubjectView ? false : grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
-    } else {
-      subtitle = grade.value.valueName.split("(")[0];
-    }
-
-    if (subtitle != "") leadingPadding = const EdgeInsets.only(top: 2.0);
-
-    return Material(
-      type: MaterialType.transparency,
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding: isSubjectView
-              ? grade.type != GradeType.ghost
-                  ? const EdgeInsets.symmetric(horizontal: 12.0)
-                  : const EdgeInsets.only(left: 12.0, right: 4.0)
-              : const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: onTap,
-          // onLongPress: kDebugMode ? () => log(jsonEncode(grade.json)) : null,
-          shape:
-              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-          leading: isSubjectView
-              ? GradeValueWidget(grade.value)
-              : SizedBox(
-                  width: 44,
-                  height: 44,
-                  child: censored
-                      ? Container(
-                          decoration: BoxDecoration(
-                            color: AppColors.of(context).text,
-                            borderRadius: BorderRadius.circular(60.0),
-                          ),
-                        )
-                      : Center(
-                          child: Padding(
-                            padding: leadingPadding,
-                            child: Icon(
-                              SubjectIcon.resolveVariant(
-                                  subject: grade.subject, context: context),
-                              size: 28.0,
-                              color: AppColors.of(context).text,
-                            ),
-                          ),
-                        ),
-                ),
-          title: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 110,
-                      height: 15,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text,
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  title,
-                  maxLines: 2,
-                  overflow: TextOverflow.ellipsis,
-                  style: TextStyle(
-                      fontWeight: FontWeight.w600,
-                      fontStyle: isTitleItalic
-                          ? FontStyle.italic
-                          : null),
-                ),
-          subtitle: subtitle != ""
-              ? censored
-                  ? Wrap(
-                      children: [
-                        Container(
-                          width: 50,
-                          height: 10,
-                          decoration: BoxDecoration(
-                            color: AppColors.of(context).text,
-                            borderRadius: BorderRadius.circular(8.0),
-                          ),
-                        ),
-                      ],
-                    )
-                  : Text(
-                      subtitle,
-                      maxLines: 1,
-                      overflow: TextOverflow.ellipsis,
-                      style: TextStyle(fontWeight: FontWeight.w500, fontStyle: isSubtitleItalic ? FontStyle.italic : null),
-                    )
-              : null,
-          trailing: isSubjectView
-              ? grade.type != GradeType.ghost
-                  ? Text(grade.date.format(context),
-                      style: const TextStyle(fontWeight: FontWeight.w500))
-                  : IconButton(
-                      splashRadius: 24.0,
-                      icon: Icon(FeatherIcons.trash2,
-                          color: AppColors.of(context).red),
-                      onPressed: () {
-                        calculatorProvider.removeGrade(grade);
-                      },
-                    )
-              : censored
-                  ? Container(
-                      width: 15,
-                      height: 15,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text,
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    )
-                  : GradeValueWidget(grade.value),
-          minLeadingWidth: isSubjectView ? 32.0 : 0,
-        ),
-      ),
-    );
-  }
-}
-
-class GradeValueWidget extends StatelessWidget {
-  const GradeValueWidget(
-    this.value, {
-    Key? key,
-    this.size = 38.0,
-    this.fill = false,
-    this.contrast = false,
-    this.shadow = false,
-    this.outline = false,
-    this.complemented = false,
-    this.nocolor = false,
-    this.color,
-  }) : super(key: key);
-
-  final GradeValue value;
-  final double size;
-  final bool fill;
-  final bool contrast;
-  final bool shadow;
-  final bool outline;
-  final bool complemented;
-  final bool nocolor;
-  final Color? color;
-
-  @override
-  Widget build(BuildContext context) {
-    GradeValue value = this.value;
-    bool isSubjectView = SubjectGradesContainer.of(context) != null;
-
-    Color color =
-        this.color ?? gradeColor(context: context, value: value.value, nocolor: nocolor);
-    Widget valueText;
-    final percentage = value.percentage;
-
-    if (percentage) {
-      double multiplier = 1.0;
-
-      if (isSubjectView) multiplier = 0.75;
-
-      valueText = Text.rich(
-        TextSpan(
-          text: value.value.toString(),
-          children: [
-            TextSpan(
-              text: "\n%",
-              style: TextStyle(
-                  fontWeight: FontWeight.w700,
-                  fontSize: size / 2.5 * multiplier,
-                  height: 0.7),
-            ),
-          ],
-          style: TextStyle(
-              fontWeight: FontWeight.w700,
-              fontSize: size / 1 * multiplier,
-              height: 1),
-        ),
-        textAlign: TextAlign.center,
-      );
-    } else if (value.valueName.toLowerCase().specialChars() == 'nem irt') {
-      valueText = const Icon(FeatherIcons.slash);
-    } else {
-      valueText = Stack(alignment: Alignment.topRight, children: [
-        Transform.translate(
-          offset: (value.weight >= 200) ? const Offset(2, 1.5) : Offset.zero,
-          child: Text(
-            value.value.toString(),
-            textAlign: TextAlign.center,
-            style: TextStyle(
-              fontWeight:
-                  value.weight == 50 ? FontWeight.w500 : FontWeight.bold,
-              fontSize: size,
-              color: contrast ? Colors.white : color,
-              shadows: [
-                if (value.weight >= 200)
-                  Shadow(
-                    color: (contrast ? Colors.white : color).withOpacity(.4),
-                    offset: const Offset(-4, -3),
-                  )
-              ],
-            ),
-          ),
-        ),
-        if (complemented)
-          Transform.translate(
-            offset: const Offset(9, 1),
-            child: Text(
-              "*",
-              style:
-                  TextStyle(fontSize: size / 1.6, fontWeight: FontWeight.bold),
-            ),
-          ),
-      ]);
-    }
-
-    return fill
-        ? Container(
-            width: size * 1.4,
-            height: size * 1.4,
-            decoration: BoxDecoration(
-              color: color.withOpacity(contrast ? 1.0 : .25),
-              shape: BoxShape.circle,
-              boxShadow: [
-                if (shadow)
-                  BoxShadow(
-                    color: color,
-                    blurRadius: 62.0,
-                  )
-              ],
-            ),
-            child: Center(child: valueText),
-          )
-        : valueText;
-  }
-}
-
-Color gradeColor(
-    {required BuildContext context, required num value, bool nocolor = false}) {
-  int valueInt = 0;
-
-  var settings = Provider.of<SettingsProvider>(context, listen: false);
-
-  try {
-    if (value < 2.0) {
-      valueInt = 1;
-    } else {
-      if (value >= value.floor() + settings.rounding / 10) {
-        valueInt = value.ceil();
-      } else {
-        valueInt = value.floor();
-      }
-    }
-  } catch (_) {}
-
-  if (nocolor) return AppColors.of(context).text;
-
-  switch (valueInt) {
-    case 5:
-      return settings.gradeColors[4];
-    case 4:
-      return settings.gradeColors[3];
-    case 3:
-      return settings.gradeColors[2];
-    case 2:
-      return settings.gradeColors[1];
-    case 1:
-      return settings.gradeColors[0];
-    default:
-      return AppColors.of(context).text;
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
+import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+
+class GradeTile extends StatelessWidget {
+  const GradeTile(this.grade,
+      {Key? key, this.onTap, this.padding, this.censored = false})
+      : super(key: key);
+
+  final Grade grade;
+  final void Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+  final bool censored;
+
+  @override
+  Widget build(BuildContext context) {
+    String title;
+    String subtitle;
+    bool isTitleItalic = false;
+    bool isSubtitleItalic = false;
+    EdgeInsets leadingPadding = EdgeInsets.zero;
+    bool isSubjectView = SubjectGradesContainer.of(context) != null;
+    String subjectName =
+        grade.subject.renamedTo ?? grade.subject.name.capital();
+    String modeDescription = grade.mode.description.capital();
+    String description = grade.description.capital();
+
+    GradeCalculatorProvider calculatorProvider =
+        Provider.of<GradeCalculatorProvider>(context, listen: false);
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+    // Test order:
+    // description
+    // mode
+    // value name
+    if (grade.type == GradeType.midYear || grade.type == GradeType.ghost) {
+      if (grade.description != "") {
+        title = description;
+      } else {
+        title = modeDescription != ""
+            ? modeDescription
+            : grade.value.valueName.split("(")[0];
+      }
+    } else {
+      title = subjectName;
+      isTitleItalic =
+          grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
+    }
+
+    // Test order:
+    // subject name
+    // mode + weight != 100
+    if (grade.type == GradeType.midYear) {
+      subtitle = isSubjectView
+          ? description != ""
+              ? modeDescription
+              : ""
+          : subjectName;
+      isSubtitleItalic = isSubjectView
+          ? false
+          : grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
+    } else {
+      subtitle = grade.value.valueName.split("(")[0];
+    }
+
+    if (subtitle != "") leadingPadding = const EdgeInsets.only(top: 2.0);
+
+    return Material(
+      type: MaterialType.transparency,
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: isSubjectView
+              ? grade.type != GradeType.ghost
+                  ? const EdgeInsets.symmetric(horizontal: 12.0)
+                  : const EdgeInsets.only(left: 12.0, right: 4.0)
+              : const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: onTap,
+          // onLongPress: kDebugMode ? () => log(jsonEncode(grade.json)) : null,
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+          leading: isSubjectView
+              ? GradeValueWidget(grade.value)
+              : SizedBox(
+                  width: 44,
+                  height: 44,
+                  child: censored
+                      ? Container(
+                          decoration: BoxDecoration(
+                            color: AppColors.of(context).text,
+                            borderRadius: BorderRadius.circular(60.0),
+                          ),
+                        )
+                      : Center(
+                          child: Padding(
+                            padding: leadingPadding,
+                            child: Icon(
+                              SubjectIcon.resolveVariant(
+                                  subject: grade.subject, context: context),
+                              size: 28.0,
+                              color: AppColors.of(context).text,
+                            ),
+                          ),
+                        ),
+                ),
+          title: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 110,
+                      height: 15,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text,
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  title,
+                  maxLines: 2,
+                  overflow: TextOverflow.ellipsis,
+                  style: TextStyle(
+                      fontWeight: FontWeight.w600,
+                      fontStyle: isTitleItalic ? FontStyle.italic : null),
+                ),
+          subtitle: subtitle != ""
+              ? censored
+                  ? Wrap(
+                      children: [
+                        Container(
+                          width: 50,
+                          height: 10,
+                          decoration: BoxDecoration(
+                            color: AppColors.of(context).text,
+                            borderRadius: BorderRadius.circular(8.0),
+                          ),
+                        ),
+                      ],
+                    )
+                  : Text(
+                      subtitle,
+                      maxLines: 1,
+                      overflow: TextOverflow.ellipsis,
+                      style: TextStyle(
+                          fontWeight: FontWeight.w500,
+                          fontStyle:
+                              isSubtitleItalic ? FontStyle.italic : null),
+                    )
+              : null,
+          trailing: isSubjectView
+              ? grade.type != GradeType.ghost
+                  ? Text(grade.date.format(context),
+                      style: const TextStyle(fontWeight: FontWeight.w500))
+                  : IconButton(
+                      splashRadius: 24.0,
+                      icon: Icon(FeatherIcons.trash2,
+                          color: AppColors.of(context).red),
+                      onPressed: () {
+                        calculatorProvider.removeGrade(grade);
+                      },
+                    )
+              : censored
+                  ? Container(
+                      width: 15,
+                      height: 15,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text,
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    )
+                  : GradeValueWidget(grade.value),
+          minLeadingWidth: isSubjectView ? 32.0 : 0,
+        ),
+      ),
+    );
+  }
+}
+
+class GradeValueWidget extends StatelessWidget {
+  const GradeValueWidget(
+    this.value, {
+    Key? key,
+    this.size = 38.0,
+    this.fill = false,
+    this.contrast = false,
+    this.shadow = false,
+    this.outline = false,
+    this.complemented = false,
+    this.nocolor = false,
+    this.color,
+  }) : super(key: key);
+
+  final GradeValue value;
+  final double size;
+  final bool fill;
+  final bool contrast;
+  final bool shadow;
+  final bool outline;
+  final bool complemented;
+  final bool nocolor;
+  final Color? color;
+
+  @override
+  Widget build(BuildContext context) {
+    GradeValue value = this.value;
+    bool isSubjectView = SubjectGradesContainer.of(context) != null;
+
+    Color color = this.color ??
+        gradeColor(context: context, value: value.value, nocolor: nocolor);
+    Widget valueText;
+    final percentage = value.percentage;
+
+    if (percentage) {
+      double multiplier = 1.0;
+
+      if (isSubjectView) multiplier = 0.75;
+
+      valueText = Text.rich(
+        TextSpan(
+          text: value.value.toString(),
+          children: [
+            TextSpan(
+              text: "\n%",
+              style: TextStyle(
+                  fontWeight: FontWeight.w700,
+                  fontSize: size / 2.5 * multiplier,
+                  height: 0.7),
+            ),
+          ],
+          style: TextStyle(
+              fontWeight: FontWeight.w700,
+              fontSize: size / 1 * multiplier,
+              height: 1),
+        ),
+        textAlign: TextAlign.center,
+      );
+    } else if (value.valueName.toLowerCase().specialChars() == 'nem irt') {
+      valueText = const Icon(FeatherIcons.slash);
+    } else {
+      valueText = Stack(alignment: Alignment.topRight, children: [
+        Transform.translate(
+          offset: (value.weight >= 200) ? const Offset(2, 1.5) : Offset.zero,
+          child: Text(
+            value.value.toString(),
+            textAlign: TextAlign.center,
+            style: TextStyle(
+              fontWeight:
+                  value.weight == 50 ? FontWeight.w500 : FontWeight.bold,
+              fontSize: size,
+              color: contrast ? Colors.white : color,
+              shadows: [
+                if (value.weight >= 200)
+                  Shadow(
+                    color: (contrast ? Colors.white : color).withOpacity(.4),
+                    offset: const Offset(-4, -3),
+                  )
+              ],
+            ),
+          ),
+        ),
+        if (complemented)
+          Transform.translate(
+            offset: const Offset(9, 1),
+            child: Text(
+              "*",
+              style:
+                  TextStyle(fontSize: size / 1.6, fontWeight: FontWeight.bold),
+            ),
+          ),
+      ]);
+    }
+
+    return fill
+        ? Container(
+            width: size * 1.4,
+            height: size * 1.4,
+            decoration: BoxDecoration(
+              color: color.withOpacity(contrast ? 1.0 : .25),
+              shape: BoxShape.circle,
+              boxShadow: [
+                if (shadow)
+                  BoxShadow(
+                    color: color,
+                    blurRadius: 62.0,
+                  )
+              ],
+            ),
+            child: Center(child: valueText),
+          )
+        : valueText;
+  }
+}
+
+Color gradeColor(
+    {required BuildContext context, required num value, bool nocolor = false}) {
+  int valueInt = 0;
+
+  var settings = Provider.of<SettingsProvider>(context, listen: false);
+
+  try {
+    if (value < 2.0) {
+      valueInt = 1;
+    } else {
+      if (value >= value.floor() + settings.rounding / 10) {
+        valueInt = value.ceil();
+      } else {
+        valueInt = value.floor();
+      }
+    }
+  } catch (_) {}
+
+  if (nocolor) return AppColors.of(context).text;
+
+  switch (valueInt) {
+    case 5:
+      return settings.gradeColors[4];
+    case 4:
+      return settings.gradeColors[3];
+    case 3:
+      return settings.gradeColors[2];
+    case 2:
+      return settings.gradeColors[1];
+    case 1:
+      return settings.gradeColors[0];
+    default:
+      return AppColors.of(context).text;
+  }
+}
diff --git a/filcnaplo/lib/ui/widgets/lesson/lesson_tile.dart b/refilc/lib/ui/widgets/lesson/lesson_tile.dart
similarity index 92%
rename from filcnaplo/lib/ui/widgets/lesson/lesson_tile.dart
rename to refilc/lib/ui/widgets/lesson/lesson_tile.dart
index 1aeb3ef..767b79a 100644
--- a/filcnaplo/lib/ui/widgets/lesson/lesson_tile.dart
+++ b/refilc/lib/ui/widgets/lesson/lesson_tile.dart
@@ -1,350 +1,350 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_view.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_view.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:intl/intl.dart';
-import 'package:provider/provider.dart';
-import 'lesson_tile.i18n.dart';
-
-class LessonTile extends StatelessWidget {
-  const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false})
-      : super(key: key);
-
-  final Lesson lesson;
-  final bool swapDesc;
-  final void Function()? onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> subtiles = [];
-
-    Color accent = Theme.of(context).colorScheme.secondary;
-    bool fill = false;
-    bool fillLeading = false;
-    String lessonIndexTrailing = "";
-
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    // Only put a trailing . if its a digit
-    if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
-
-    var now = DateTime.now();
-    if (lesson.start.isBefore(now) &&
-        lesson.end.isAfter(now) &&
-        lesson.status?.name != "Elmaradt") {
-      fillLeading = true;
-    }
-
-    if (lesson.substituteTeacher != null &&
-        lesson.substituteTeacher?.name != "") {
-      fill = true;
-      accent = AppColors.of(context).yellow;
-    }
-
-    if (lesson.status?.name == "Elmaradt") {
-      fill = true;
-      accent = AppColors.of(context).red;
-    }
-
-    if (lesson.isEmpty) {
-      accent = AppColors.of(context).text.withOpacity(0.6);
-    }
-
-    if (!lesson.studentPresence) {
-      subtiles.add(LessonSubtile(
-        type: LessonSubtileType.absence,
-        title: "absence".i18n,
-      ));
-    }
-
-    if (lesson.homeworkId != "") {
-      Homework homework = Provider.of<HomeworkProvider>(context, listen: false)
-          .homework
-          .firstWhere((h) => h.id == lesson.homeworkId,
-              orElse: () => Homework.fromJson({}));
-
-      if (homework.id != "") {
-        subtiles.add(LessonSubtile(
-          type: LessonSubtileType.homework,
-          title: homework.content,
-          onPressed: () => HomeworkView.show(homework, context: context),
-        ));
-      }
-    }
-
-    if (lesson.exam != "") {
-      Exam exam = Provider.of<ExamProvider>(context, listen: false)
-          .exams
-          .firstWhere((t) => t.id == lesson.exam,
-              orElse: () => Exam.fromJson({}));
-      if (exam.id != "") {
-        subtiles.add(LessonSubtile(
-          type: LessonSubtileType.exam,
-          title: exam.description != ""
-              ? exam.description
-              : exam.mode?.description ?? "exam".i18n,
-          onPressed: () => ExamView.show(exam, context: context),
-        ));
-      }
-    }
-
-    String description = '';
-    String room = '';
-
-    final cleanDesc = lesson.description
-        .specialChars()
-        .toLowerCase()
-        .replaceAll(lesson.subject.name.specialChars().toLowerCase(), '');
-
-    if (!swapDesc) {
-      if (cleanDesc != "") {
-        description = lesson.description;
-      }
-
-      // Changed lesson Description
-      if (lesson.isChanged) {
-        if (lesson.status?.name == "Elmaradt") {
-          description = 'cancelled'.i18n;
-        } else if (lesson.substituteTeacher?.name != "") {
-          description = 'substitution'.i18n;
-        }
-      }
-
-      room = lesson.room.replaceAll("_", " ");
-    } else {
-      description = lesson.room.replaceAll("_", " ");
-    }
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 2.0),
-      child: Material(
-        color: fill ? accent.withOpacity(.25) : Colors.transparent,
-        borderRadius: BorderRadius.circular(12.0),
-        child: Visibility(
-          visible: lesson.subject.id != '' || lesson.isEmpty,
-          replacement: Padding(
-            padding: const EdgeInsets.only(top: 6.0),
-            child: PanelTitle(title: Text(lesson.name)),
-          ),
-          child: Padding(
-            padding: EdgeInsets.only(bottom: subtiles.isEmpty ? 0.0 : 12.0),
-            child: Column(
-              mainAxisSize: MainAxisSize.min,
-              children: [
-                ListTile(
-                  minVerticalPadding: 12.0,
-                  dense: true,
-                  onTap: onTap,
-                  // onLongPress: kDebugMode ? () => log(jsonEncode(lesson.json)) : null,
-                  visualDensity: VisualDensity.compact,
-                  contentPadding: const EdgeInsets.symmetric(horizontal: 4.0),
-                  shape: RoundedRectangleBorder(
-                      borderRadius: BorderRadius.circular(12.0)),
-                  title: Text(
-                    !lesson.isEmpty
-                        ? lesson.subject.renamedTo ??
-                            lesson.subject.name.capital()
-                        : "empty".i18n,
-                    maxLines: 2,
-                    overflow: TextOverflow.ellipsis,
-                    style: TextStyle(
-                        fontWeight: FontWeight.w600,
-                        fontSize: 15.5,
-                        color: AppColors.of(context)
-                            .text
-                            .withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
-                        fontStyle: lesson.subject.isRenamed &&
-                                settingsProvider.renamedSubjectsItalics
-                            ? FontStyle.italic
-                            : null),
-                  ),
-                  subtitle: description != ""
-                      ? Text(
-                          description,
-                          style: const TextStyle(
-                            fontWeight: FontWeight.w500,
-                            fontSize: 14.0,
-                          ),
-                          maxLines: 1,
-                          softWrap: false,
-                          overflow: TextOverflow.ellipsis,
-                        )
-                      : null,
-                  minLeadingWidth: 34.0,
-                  leading: AspectRatio(
-                    aspectRatio: 1,
-                    child: Center(
-                      child: Stack(
-                        children: [
-                          Text(
-                            lesson.lessonIndex + lessonIndexTrailing,
-                            textAlign: TextAlign.center,
-                            style: TextStyle(
-                              fontSize: 30.0,
-                              fontWeight: FontWeight.w600,
-                              color: accent,
-                            ),
-                          ),
-
-                          // Current lesson indicator
-                          Transform.translate(
-                            offset: const Offset(-12.0, -2.0),
-                            child: Container(
-                              decoration: BoxDecoration(
-                                color: fillLeading
-                                    ? Theme.of(context)
-                                        .colorScheme
-                                        .secondary
-                                        .withOpacity(.3)
-                                    : const Color(0x00000000),
-                                borderRadius: BorderRadius.circular(12.0),
-                                boxShadow: [
-                                  if (fillLeading)
-                                    BoxShadow(
-                                      color: Theme.of(context)
-                                          .colorScheme
-                                          .secondary
-                                          .withOpacity(.25),
-                                      blurRadius: 6.0,
-                                    )
-                                ],
-                              ),
-                              margin: const EdgeInsets.symmetric(vertical: 4.0),
-                              width: 4.0,
-                              height: double.infinity,
-                            ),
-                          )
-                        ],
-                      ),
-                    ),
-                  ),
-                  trailing: !lesson.isEmpty
-                      ? Row(
-                          mainAxisSize: MainAxisSize.min,
-                          children: [
-                            if (!swapDesc)
-                              SizedBox(
-                                width: 52.0,
-                                child: Padding(
-                                  padding: const EdgeInsets.only(right: 6.0),
-                                  child: Text(
-                                    room,
-                                    textAlign: TextAlign.center,
-                                    overflow: TextOverflow.ellipsis,
-                                    maxLines: 2,
-                                    style: TextStyle(
-                                      fontWeight: FontWeight.w500,
-                                      color: AppColors.of(context)
-                                          .text
-                                          .withOpacity(.75),
-                                    ),
-                                  ),
-                                ),
-                              ),
-                            Stack(
-                              alignment: Alignment.center,
-                              children: [
-                                // Fix alignment hack
-                                const Opacity(opacity: 0, child: Text("EE:EE")),
-                                Text(
-                                  "${DateFormat("H:mm").format(lesson.start)}\n${DateFormat("H:mm").format(lesson.end)}",
-                                  textAlign: TextAlign.center,
-                                  style: TextStyle(
-                                    fontWeight: FontWeight.w500,
-                                    color: AppColors.of(context)
-                                        .text
-                                        .withOpacity(.9),
-                                  ),
-                                ),
-                              ],
-                            ),
-                          ],
-                        )
-                      : null,
-                ),
-
-                // Homework & Exams
-                ...subtiles,
-              ],
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-enum LessonSubtileType { homework, exam, absence }
-
-class LessonSubtile extends StatelessWidget {
-  const LessonSubtile(
-      {Key? key, this.onPressed, required this.title, required this.type})
-      : super(key: key);
-
-  final Function()? onPressed;
-  final String title;
-  final LessonSubtileType type;
-
-  @override
-  Widget build(BuildContext context) {
-    IconData icon;
-    Color iconColor = AppColors.of(context).text;
-
-    switch (type) {
-      case LessonSubtileType.absence:
-        icon = FeatherIcons.slash;
-        iconColor = AppColors.of(context).red;
-        break;
-      case LessonSubtileType.exam:
-        icon = FeatherIcons.file;
-        break;
-      case LessonSubtileType.homework:
-        icon = FeatherIcons.home;
-        break;
-    }
-
-    return Padding(
-      padding: const EdgeInsets.symmetric(horizontal: 8.0),
-      child: InkWell(
-        onTap: onPressed,
-        borderRadius: BorderRadius.circular(8.0),
-        child: Padding(
-          padding: const EdgeInsets.symmetric(vertical: 4.0),
-          child: Row(
-            children: [
-              Center(
-                child: SizedBox(
-                  width: 30.0,
-                  child:
-                      Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
-                ),
-              ),
-              Expanded(
-                child: Padding(
-                  padding: const EdgeInsets.only(left: 20.0),
-                  child: Text(
-                    title.escapeHtml(),
-                    maxLines: 1,
-                    overflow: TextOverflow.ellipsis,
-                    style: TextStyle(
-                        fontWeight: FontWeight.w500,
-                        color: AppColors.of(context).text.withOpacity(.65)),
-                  ),
-                ),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/widgets/exam/exam_view.dart';
+import 'package:refilc_mobile_ui/common/widgets/homework/homework_view.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:intl/intl.dart';
+import 'package:provider/provider.dart';
+import 'lesson_tile.i18n.dart';
+
+class LessonTile extends StatelessWidget {
+  const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false})
+      : super(key: key);
+
+  final Lesson lesson;
+  final bool swapDesc;
+  final void Function()? onTap;
+
+  @override
+  Widget build(BuildContext context) {
+    List<Widget> subtiles = [];
+
+    Color accent = Theme.of(context).colorScheme.secondary;
+    bool fill = false;
+    bool fillLeading = false;
+    String lessonIndexTrailing = "";
+
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    // Only put a trailing . if its a digit
+    if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
+
+    var now = DateTime.now();
+    if (lesson.start.isBefore(now) &&
+        lesson.end.isAfter(now) &&
+        lesson.status?.name != "Elmaradt") {
+      fillLeading = true;
+    }
+
+    if (lesson.substituteTeacher != null &&
+        lesson.substituteTeacher?.name != "") {
+      fill = true;
+      accent = AppColors.of(context).yellow;
+    }
+
+    if (lesson.status?.name == "Elmaradt") {
+      fill = true;
+      accent = AppColors.of(context).red;
+    }
+
+    if (lesson.isEmpty) {
+      accent = AppColors.of(context).text.withOpacity(0.6);
+    }
+
+    if (!lesson.studentPresence) {
+      subtiles.add(LessonSubtile(
+        type: LessonSubtileType.absence,
+        title: "absence".i18n,
+      ));
+    }
+
+    if (lesson.homeworkId != "") {
+      Homework homework = Provider.of<HomeworkProvider>(context, listen: false)
+          .homework
+          .firstWhere((h) => h.id == lesson.homeworkId,
+              orElse: () => Homework.fromJson({}));
+
+      if (homework.id != "") {
+        subtiles.add(LessonSubtile(
+          type: LessonSubtileType.homework,
+          title: homework.content,
+          onPressed: () => HomeworkView.show(homework, context: context),
+        ));
+      }
+    }
+
+    if (lesson.exam != "") {
+      Exam exam = Provider.of<ExamProvider>(context, listen: false)
+          .exams
+          .firstWhere((t) => t.id == lesson.exam,
+              orElse: () => Exam.fromJson({}));
+      if (exam.id != "") {
+        subtiles.add(LessonSubtile(
+          type: LessonSubtileType.exam,
+          title: exam.description != ""
+              ? exam.description
+              : exam.mode?.description ?? "exam".i18n,
+          onPressed: () => ExamView.show(exam, context: context),
+        ));
+      }
+    }
+
+    String description = '';
+    String room = '';
+
+    final cleanDesc = lesson.description
+        .specialChars()
+        .toLowerCase()
+        .replaceAll(lesson.subject.name.specialChars().toLowerCase(), '');
+
+    if (!swapDesc) {
+      if (cleanDesc != "") {
+        description = lesson.description;
+      }
+
+      // Changed lesson Description
+      if (lesson.isChanged) {
+        if (lesson.status?.name == "Elmaradt") {
+          description = 'cancelled'.i18n;
+        } else if (lesson.substituteTeacher?.name != "") {
+          description = 'substitution'.i18n;
+        }
+      }
+
+      room = lesson.room.replaceAll("_", " ");
+    } else {
+      description = lesson.room.replaceAll("_", " ");
+    }
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 2.0),
+      child: Material(
+        color: fill ? accent.withOpacity(.25) : Colors.transparent,
+        borderRadius: BorderRadius.circular(12.0),
+        child: Visibility(
+          visible: lesson.subject.id != '' || lesson.isEmpty,
+          replacement: Padding(
+            padding: const EdgeInsets.only(top: 6.0),
+            child: PanelTitle(title: Text(lesson.name)),
+          ),
+          child: Padding(
+            padding: EdgeInsets.only(bottom: subtiles.isEmpty ? 0.0 : 12.0),
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                ListTile(
+                  minVerticalPadding: 12.0,
+                  dense: true,
+                  onTap: onTap,
+                  // onLongPress: kDebugMode ? () => log(jsonEncode(lesson.json)) : null,
+                  visualDensity: VisualDensity.compact,
+                  contentPadding: const EdgeInsets.symmetric(horizontal: 4.0),
+                  shape: RoundedRectangleBorder(
+                      borderRadius: BorderRadius.circular(12.0)),
+                  title: Text(
+                    !lesson.isEmpty
+                        ? lesson.subject.renamedTo ??
+                            lesson.subject.name.capital()
+                        : "empty".i18n,
+                    maxLines: 2,
+                    overflow: TextOverflow.ellipsis,
+                    style: TextStyle(
+                        fontWeight: FontWeight.w600,
+                        fontSize: 15.5,
+                        color: AppColors.of(context)
+                            .text
+                            .withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
+                        fontStyle: lesson.subject.isRenamed &&
+                                settingsProvider.renamedSubjectsItalics
+                            ? FontStyle.italic
+                            : null),
+                  ),
+                  subtitle: description != ""
+                      ? Text(
+                          description,
+                          style: const TextStyle(
+                            fontWeight: FontWeight.w500,
+                            fontSize: 14.0,
+                          ),
+                          maxLines: 1,
+                          softWrap: false,
+                          overflow: TextOverflow.ellipsis,
+                        )
+                      : null,
+                  minLeadingWidth: 34.0,
+                  leading: AspectRatio(
+                    aspectRatio: 1,
+                    child: Center(
+                      child: Stack(
+                        children: [
+                          Text(
+                            lesson.lessonIndex + lessonIndexTrailing,
+                            textAlign: TextAlign.center,
+                            style: TextStyle(
+                              fontSize: 30.0,
+                              fontWeight: FontWeight.w600,
+                              color: accent,
+                            ),
+                          ),
+
+                          // Current lesson indicator
+                          Transform.translate(
+                            offset: const Offset(-12.0, -2.0),
+                            child: Container(
+                              decoration: BoxDecoration(
+                                color: fillLeading
+                                    ? Theme.of(context)
+                                        .colorScheme
+                                        .secondary
+                                        .withOpacity(.3)
+                                    : const Color(0x00000000),
+                                borderRadius: BorderRadius.circular(12.0),
+                                boxShadow: [
+                                  if (fillLeading)
+                                    BoxShadow(
+                                      color: Theme.of(context)
+                                          .colorScheme
+                                          .secondary
+                                          .withOpacity(.25),
+                                      blurRadius: 6.0,
+                                    )
+                                ],
+                              ),
+                              margin: const EdgeInsets.symmetric(vertical: 4.0),
+                              width: 4.0,
+                              height: double.infinity,
+                            ),
+                          )
+                        ],
+                      ),
+                    ),
+                  ),
+                  trailing: !lesson.isEmpty
+                      ? Row(
+                          mainAxisSize: MainAxisSize.min,
+                          children: [
+                            if (!swapDesc)
+                              SizedBox(
+                                width: 52.0,
+                                child: Padding(
+                                  padding: const EdgeInsets.only(right: 6.0),
+                                  child: Text(
+                                    room,
+                                    textAlign: TextAlign.center,
+                                    overflow: TextOverflow.ellipsis,
+                                    maxLines: 2,
+                                    style: TextStyle(
+                                      fontWeight: FontWeight.w500,
+                                      color: AppColors.of(context)
+                                          .text
+                                          .withOpacity(.75),
+                                    ),
+                                  ),
+                                ),
+                              ),
+                            Stack(
+                              alignment: Alignment.center,
+                              children: [
+                                // Fix alignment hack
+                                const Opacity(opacity: 0, child: Text("EE:EE")),
+                                Text(
+                                  "${DateFormat("H:mm").format(lesson.start)}\n${DateFormat("H:mm").format(lesson.end)}",
+                                  textAlign: TextAlign.center,
+                                  style: TextStyle(
+                                    fontWeight: FontWeight.w500,
+                                    color: AppColors.of(context)
+                                        .text
+                                        .withOpacity(.9),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ],
+                        )
+                      : null,
+                ),
+
+                // Homework & Exams
+                ...subtiles,
+              ],
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+enum LessonSubtileType { homework, exam, absence }
+
+class LessonSubtile extends StatelessWidget {
+  const LessonSubtile(
+      {Key? key, this.onPressed, required this.title, required this.type})
+      : super(key: key);
+
+  final Function()? onPressed;
+  final String title;
+  final LessonSubtileType type;
+
+  @override
+  Widget build(BuildContext context) {
+    IconData icon;
+    Color iconColor = AppColors.of(context).text;
+
+    switch (type) {
+      case LessonSubtileType.absence:
+        icon = FeatherIcons.slash;
+        iconColor = AppColors.of(context).red;
+        break;
+      case LessonSubtileType.exam:
+        icon = FeatherIcons.file;
+        break;
+      case LessonSubtileType.homework:
+        icon = FeatherIcons.home;
+        break;
+    }
+
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 8.0),
+      child: InkWell(
+        onTap: onPressed,
+        borderRadius: BorderRadius.circular(8.0),
+        child: Padding(
+          padding: const EdgeInsets.symmetric(vertical: 4.0),
+          child: Row(
+            children: [
+              Center(
+                child: SizedBox(
+                  width: 30.0,
+                  child:
+                      Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
+                ),
+              ),
+              Expanded(
+                child: Padding(
+                  padding: const EdgeInsets.only(left: 20.0),
+                  child: Text(
+                    title.escapeHtml(),
+                    maxLines: 1,
+                    overflow: TextOverflow.ellipsis,
+                    style: TextStyle(
+                        fontWeight: FontWeight.w500,
+                        color: AppColors.of(context).text.withOpacity(.65)),
+                  ),
+                ),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo/lib/ui/widgets/lesson/lesson_tile.i18n.dart b/refilc/lib/ui/widgets/lesson/lesson_tile.i18n.dart
similarity index 97%
rename from filcnaplo/lib/ui/widgets/lesson/lesson_tile.i18n.dart
rename to refilc/lib/ui/widgets/lesson/lesson_tile.i18n.dart
index 095d692..e2a0a9c 100644
--- a/filcnaplo/lib/ui/widgets/lesson/lesson_tile.i18n.dart
+++ b/refilc/lib/ui/widgets/lesson/lesson_tile.i18n.dart
@@ -1,33 +1,33 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "empty": "Free period",
-          "cancelled": "Cancelled",
-          "substitution": "Substituted",
-          "absence": "You were absent on this lesson",
-          "exam": "Exam"
-        },
-        "hu_hu": {
-          "empty": "Lyukasóra",
-          "cancelled": "Elmarad",
-          "substitution": "Helyettesítés",
-          "absence": "Hiányoztál ezen az órán",
-          "exam": "Dolgozat"
-        },
-        "de_de": {
-          "empty": "Springstunde",
-          "cancelled": "Abgesagte",
-          "substitution": "Vertretene",
-          "absence": "Sie waren in dieser Lektion nicht anwesend",
-          "exam": "Prüfung"
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "empty": "Free period",
+          "cancelled": "Cancelled",
+          "substitution": "Substituted",
+          "absence": "You were absent on this lesson",
+          "exam": "Exam"
+        },
+        "hu_hu": {
+          "empty": "Lyukasóra",
+          "cancelled": "Elmarad",
+          "substitution": "Helyettesítés",
+          "absence": "Hiányoztál ezen az órán",
+          "exam": "Dolgozat"
+        },
+        "de_de": {
+          "empty": "Springstunde",
+          "cancelled": "Abgesagte",
+          "substitution": "Vertretene",
+          "absence": "Sie waren in dieser Lektion nicht anwesend",
+          "exam": "Prüfung"
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo/lib/ui/widgets/message/message_tile.dart b/refilc/lib/ui/widgets/message/message_tile.dart
similarity index 79%
rename from filcnaplo/lib/ui/widgets/message/message_tile.dart
rename to refilc/lib/ui/widgets/message/message_tile.dart
index f866a34..78b65f8 100644
--- a/filcnaplo/lib/ui/widgets/message/message_tile.dart
+++ b/refilc/lib/ui/widgets/message/message_tile.dart
@@ -1,121 +1,129 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-
-class MessageTile extends StatelessWidget {
-  const MessageTile(
-    this.message, {
-    Key? key,
-    this.messages,
-    this.padding,
-    this.onTap,
-    this.censored = false,
-  }) : super(key: key);
-
-  final Message message;
-  final List<Message>? messages;
-  final EdgeInsetsGeometry? padding;
-  final Function()? onTap;
-  final bool censored;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      type: MaterialType.transparency,
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          onTap: onTap,
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 4.0),
-          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-          leading: !Provider.of<SettingsProvider>(context, listen: false).presentationMode
-              ? ProfileImage(
-                  name: message.author,
-                  radius: 22.0,
-                  backgroundColor: ColorUtils.stringToColor(message.author),
-                  censored: censored,
-                )
-              : ProfileImage(
-                  name: "Béla",
-                  radius: 22.0,
-                  backgroundColor: Theme.of(context).colorScheme.secondary,
-                  censored: censored,
-                ),
-          title: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 105,
-                      height: 15,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.85),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Row(
-                  children: [
-                    Expanded(
-                      child: Text(
-                        !Provider.of<SettingsProvider>(context, listen: false).presentationMode ? message.author : "Béla",
-                        maxLines: 2,
-                        overflow: TextOverflow.ellipsis,
-                        style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15.5),
-                      ),
-                    ),
-                    if (message.attachments.isNotEmpty) const Icon(FeatherIcons.paperclip, size: 16.0)
-                  ],
-                ),
-          subtitle: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 150,
-                      height: 10,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.45),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  message.subject,
-                  maxLines: 1,
-                  overflow: TextOverflow.ellipsis,
-                  style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0),
-                ),
-          trailing: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 35,
-                      height: 15,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.45),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  message.date.format(context),
-                  style: TextStyle(
-                    fontWeight: FontWeight.w500,
-                    fontSize: 14.0,
-                    color: AppColors.of(context).text.withOpacity(.75),
-                  ),
-                ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+
+class MessageTile extends StatelessWidget {
+  const MessageTile(
+    this.message, {
+    Key? key,
+    this.messages,
+    this.padding,
+    this.onTap,
+    this.censored = false,
+  }) : super(key: key);
+
+  final Message message;
+  final List<Message>? messages;
+  final EdgeInsetsGeometry? padding;
+  final Function()? onTap;
+  final bool censored;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      type: MaterialType.transparency,
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          onTap: onTap,
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 4.0),
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+          leading: !Provider.of<SettingsProvider>(context, listen: false)
+                  .presentationMode
+              ? ProfileImage(
+                  name: message.author,
+                  radius: 22.0,
+                  backgroundColor: ColorUtils.stringToColor(message.author),
+                  censored: censored,
+                )
+              : ProfileImage(
+                  name: "Béla",
+                  radius: 22.0,
+                  backgroundColor: Theme.of(context).colorScheme.secondary,
+                  censored: censored,
+                ),
+          title: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 105,
+                      height: 15,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.85),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Row(
+                  children: [
+                    Expanded(
+                      child: Text(
+                        !Provider.of<SettingsProvider>(context, listen: false)
+                                .presentationMode
+                            ? message.author
+                            : "Béla",
+                        maxLines: 2,
+                        overflow: TextOverflow.ellipsis,
+                        style: const TextStyle(
+                            fontWeight: FontWeight.w600, fontSize: 15.5),
+                      ),
+                    ),
+                    if (message.attachments.isNotEmpty)
+                      const Icon(FeatherIcons.paperclip, size: 16.0)
+                  ],
+                ),
+          subtitle: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 150,
+                      height: 10,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.45),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  message.subject,
+                  maxLines: 1,
+                  overflow: TextOverflow.ellipsis,
+                  style: const TextStyle(
+                      fontWeight: FontWeight.w500, fontSize: 14.0),
+                ),
+          trailing: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 35,
+                      height: 15,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.45),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  message.date.format(context),
+                  style: TextStyle(
+                    fontWeight: FontWeight.w500,
+                    fontSize: 14.0,
+                    color: AppColors.of(context).text.withOpacity(.75),
+                  ),
+                ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo/lib/utils/color.dart b/refilc/lib/utils/color.dart
similarity index 96%
rename from filcnaplo/lib/utils/color.dart
rename to refilc/lib/utils/color.dart
index 27e6a6b..f769e4f 100644
--- a/filcnaplo/lib/utils/color.dart
+++ b/refilc/lib/utils/color.dart
@@ -1,15 +1,15 @@
-import 'package:flutter/material.dart';
-
-class ColorUtils {
-  static Color stringToColor(String str) {
-    int hash = 0;
-    for (var i = 0; i < str.length; i++) {
-      hash = str.codeUnitAt(i) + ((hash << 5) - hash);
-    }
-
-    return HSLColor.fromAHSL(1, hash % 360, .8, .75).toColor();
-  }
-
-  static Color foregroundColor(Color color) =>
-      color.computeLuminance() >= .5 ? Colors.black : Colors.white;
-}
+import 'package:flutter/material.dart';
+
+class ColorUtils {
+  static Color stringToColor(String str) {
+    int hash = 0;
+    for (var i = 0; i < str.length; i++) {
+      hash = str.codeUnitAt(i) + ((hash << 5) - hash);
+    }
+
+    return HSLColor.fromAHSL(1, hash % 360, .8, .75).toColor();
+  }
+
+  static Color foregroundColor(Color color) =>
+      color.computeLuminance() >= .5 ? Colors.black : Colors.white;
+}
diff --git a/filcnaplo/lib/utils/format.dart b/refilc/lib/utils/format.dart
similarity index 75%
rename from filcnaplo/lib/utils/format.dart
rename to refilc/lib/utils/format.dart
index d104ef1..98c3a76 100644
--- a/filcnaplo/lib/utils/format.dart
+++ b/refilc/lib/utils/format.dart
@@ -1,70 +1,80 @@
-import 'dart:math';
-
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:flutter/widgets.dart';
-import 'package:intl/intl.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:html/parser.dart';
-import 'format.i18n.dart';
-
-extension StringFormatUtils on String {
-  String specialChars() => replaceAll("é", "e")
-      .replaceAll("á", "a")
-      .replaceAll("ó", "o")
-      .replaceAll("ő", "o")
-      .replaceAll("ö", "o")
-      .replaceAll("ú", "u")
-      .replaceAll("ű", "u")
-      .replaceAll("ü", "u")
-      .replaceAll("í", "i");
-
-  String capital() => isNotEmpty ? this[0].toUpperCase() + substring(1) : "";
-
-  String capitalize() => split(" ").map((w) => w.capital()).join(" ");
-
-  String escapeHtml() {
-    String htmlString = this;
-    htmlString = htmlString.replaceAll("\r", "");
-    htmlString = htmlString.replaceAll(RegExp(r'<br ?/?>'), "\n");
-    htmlString = htmlString.replaceAll(RegExp(r'<p ?>'), "");
-    htmlString = htmlString.replaceAll(RegExp(r'</p ?>'), "\n");
-    var document = parse(htmlString);
-    return document.body?.text.trim() ?? htmlString;
-  }
-
-  String limit(int max) {
-    if (length <= max) return this;
-    return '${substring(0, min(length, 14))}…';
-  }
-}
-
-extension DateFormatUtils on DateTime {
-  String format(BuildContext context, {bool timeOnly = false, bool forceToday = false, bool weekday = false}) {
-    // Time only
-    if (timeOnly) return DateFormat("HH:mm").format(this);
-
-    DateTime now = DateTime.now();
-    if (now.year == year && now.month == month && now.day == day) {
-      if (hour == 0 && minute == 0 && second == 0 || forceToday) return "Today".i18n;
-      return DateFormat("HH:mm").format(this);
-    }
-    if (now.year == year && now.month == month && now.subtract(const Duration(days: 1)).day == day) return "Yesterday".i18n;
-    if (now.year == year && now.month == month && now.add(const Duration(days: 1)).day == day) return "Tomorrow".i18n;
-
-    String formatString;
-
-    // If date is current week, show only weekday
-    if (Week.current().start.isBefore(this) && Week.current().end.isAfter(this)) {
-      formatString = "EEEE";
-    } else {
-      if (year == now.year) {
-        formatString = "MMM dd.";
-      } else {
-        formatString = "yy/MM/dd";
-      } // ex. 21/01/01
-
-      if (weekday) formatString += " (EEEE)"; // ex. (monday)
-    }
-    return DateFormat(formatString, I18n.of(context).locale.toString()).format(this).capital();
-  }
-}
+import 'dart:math';
+
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:flutter/widgets.dart';
+import 'package:intl/intl.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:html/parser.dart';
+import 'format.i18n.dart';
+
+extension StringFormatUtils on String {
+  String specialChars() => replaceAll("é", "e")
+      .replaceAll("á", "a")
+      .replaceAll("ó", "o")
+      .replaceAll("ő", "o")
+      .replaceAll("ö", "o")
+      .replaceAll("ú", "u")
+      .replaceAll("ű", "u")
+      .replaceAll("ü", "u")
+      .replaceAll("í", "i");
+
+  String capital() => isNotEmpty ? this[0].toUpperCase() + substring(1) : "";
+
+  String capitalize() => split(" ").map((w) => w.capital()).join(" ");
+
+  String escapeHtml() {
+    String htmlString = this;
+    htmlString = htmlString.replaceAll("\r", "");
+    htmlString = htmlString.replaceAll(RegExp(r'<br ?/?>'), "\n");
+    htmlString = htmlString.replaceAll(RegExp(r'<p ?>'), "");
+    htmlString = htmlString.replaceAll(RegExp(r'</p ?>'), "\n");
+    var document = parse(htmlString);
+    return document.body?.text.trim() ?? htmlString;
+  }
+
+  String limit(int max) {
+    if (length <= max) return this;
+    return '${substring(0, min(length, 14))}…';
+  }
+}
+
+extension DateFormatUtils on DateTime {
+  String format(BuildContext context,
+      {bool timeOnly = false, bool forceToday = false, bool weekday = false}) {
+    // Time only
+    if (timeOnly) return DateFormat("HH:mm").format(this);
+
+    DateTime now = DateTime.now();
+    if (now.year == year && now.month == month && now.day == day) {
+      if (hour == 0 && minute == 0 && second == 0 || forceToday)
+        return "Today".i18n;
+      return DateFormat("HH:mm").format(this);
+    }
+    if (now.year == year &&
+        now.month == month &&
+        now.subtract(const Duration(days: 1)).day == day)
+      return "Yesterday".i18n;
+    if (now.year == year &&
+        now.month == month &&
+        now.add(const Duration(days: 1)).day == day) return "Tomorrow".i18n;
+
+    String formatString;
+
+    // If date is current week, show only weekday
+    if (Week.current().start.isBefore(this) &&
+        Week.current().end.isAfter(this)) {
+      formatString = "EEEE";
+    } else {
+      if (year == now.year) {
+        formatString = "MMM dd.";
+      } else {
+        formatString = "yy/MM/dd";
+      } // ex. 21/01/01
+
+      if (weekday) formatString += " (EEEE)"; // ex. (monday)
+    }
+    return DateFormat(formatString, I18n.of(context).locale.toString())
+        .format(this)
+        .capital();
+  }
+}
diff --git a/filcnaplo/lib/utils/format.i18n.dart b/refilc/lib/utils/format.i18n.dart
similarity index 96%
rename from filcnaplo/lib/utils/format.i18n.dart
rename to refilc/lib/utils/format.i18n.dart
index 08fd17a..cb6fd38 100644
--- a/filcnaplo/lib/utils/format.i18n.dart
+++ b/refilc/lib/utils/format.i18n.dart
@@ -1,27 +1,27 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Today": "Today",
-          "Yesterday": "Yesterday",
-          "Tomorrow": "Tomorrow",
-        },
-        "hu_hu": {
-          "Today": "Ma",
-          "Yesterday": "Tegnap",
-          "Tomorrow": "Holnap",
-        },
-        "de_de": {
-          "Today": "Heute",
-          "Yesterday": "Gestern",
-          "Tomorrow": "Morgen",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Today": "Today",
+          "Yesterday": "Yesterday",
+          "Tomorrow": "Tomorrow",
+        },
+        "hu_hu": {
+          "Today": "Ma",
+          "Yesterday": "Tegnap",
+          "Tomorrow": "Holnap",
+        },
+        "de_de": {
+          "Today": "Heute",
+          "Yesterday": "Gestern",
+          "Tomorrow": "Morgen",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo/lib/utils/jwt.dart b/refilc/lib/utils/jwt.dart
similarity index 90%
rename from filcnaplo/lib/utils/jwt.dart
rename to refilc/lib/utils/jwt.dart
index c05838d..2e0898b 100644
--- a/filcnaplo/lib/utils/jwt.dart
+++ b/refilc/lib/utils/jwt.dart
@@ -1,42 +1,42 @@
-import 'dart:convert';
-
-import 'package:filcnaplo/models/user.dart';
-
-class JwtUtils {
-  static Map? decodeJwt(String jwt) {
-    var parts = jwt.split(".");
-    if (parts.length != 3) return null;
-
-    if (parts[1].length % 4 == 2) {
-      parts[1] += "==";
-    } else if (parts[1].length % 4 == 3) {
-      parts[1] += "=";
-    }
-
-    try {
-      var payload = utf8.decode(base64Url.decode(parts[1]));
-      return jsonDecode(payload);
-    } catch (error) {
-      // ignore: avoid_print
-      print("ERROR: JwtUtils.decodeJwt: $error");
-    }
-    return null;
-  }
-
-  static String? getNameFromJWT(String jwt) {
-    var jwtData = decodeJwt(jwt);
-    return jwtData?["name"];
-  }
-
-  static Role? getRoleFromJWT(String jwt) {
-    var jwtData = decodeJwt(jwt);
-
-    switch (jwtData?["role"]) {
-      case "Tanulo":
-        return Role.student;
-      case "Gondviselo":
-        return Role.parent;
-    }
-    return null;
-  }
-}
+import 'dart:convert';
+
+import 'package:refilc/models/user.dart';
+
+class JwtUtils {
+  static Map? decodeJwt(String jwt) {
+    var parts = jwt.split(".");
+    if (parts.length != 3) return null;
+
+    if (parts[1].length % 4 == 2) {
+      parts[1] += "==";
+    } else if (parts[1].length % 4 == 3) {
+      parts[1] += "=";
+    }
+
+    try {
+      var payload = utf8.decode(base64Url.decode(parts[1]));
+      return jsonDecode(payload);
+    } catch (error) {
+      // ignore: avoid_print
+      print("ERROR: JwtUtils.decodeJwt: $error");
+    }
+    return null;
+  }
+
+  static String? getNameFromJWT(String jwt) {
+    var jwtData = decodeJwt(jwt);
+    return jwtData?["name"];
+  }
+
+  static Role? getRoleFromJWT(String jwt) {
+    var jwtData = decodeJwt(jwt);
+
+    switch (jwtData?["role"]) {
+      case "Tanulo":
+        return Role.student;
+      case "Gondviselo":
+        return Role.parent;
+    }
+    return null;
+  }
+}
diff --git a/filcnaplo/lib/utils/platform.dart b/refilc/lib/utils/platform.dart
similarity index 96%
rename from filcnaplo/lib/utils/platform.dart
rename to refilc/lib/utils/platform.dart
index 2a9fd56..0594ad3 100644
--- a/filcnaplo/lib/utils/platform.dart
+++ b/refilc/lib/utils/platform.dart
@@ -1,6 +1,6 @@
-import 'dart:io';
-
-class PlatformUtils {
-  static bool get isDesktop => Platform.isWindows || Platform.isMacOS || Platform.isLinux;
-  static bool get isMobile => !isDesktop;
-}
+import 'dart:io';
+
+class PlatformUtils {
+  static bool get isDesktop => Platform.isWindows || Platform.isMacOS || Platform.isLinux;
+  static bool get isMobile => !isDesktop;
+}
diff --git a/refilc/lib/utils/reverse_search.dart b/refilc/lib/utils/reverse_search.dart
new file mode 100644
index 0000000..35e3425
--- /dev/null
+++ b/refilc/lib/utils/reverse_search.dart
@@ -0,0 +1,44 @@
+import 'dart:developer';
+
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:provider/provider.dart';
+
+class ReverseSearch {
+  static Future<Lesson?> getLessonByAbsence(
+      Absence absence, BuildContext context) async {
+    final timetableProvider =
+        Provider.of<TimetableProvider>(context, listen: false);
+
+    List<Lesson> lessons = [];
+    final week = Week.fromDate(absence.date);
+    try {
+      await timetableProvider.fetch(week: week);
+    } catch (e) {
+      log("[ERROR] getLessonByAbsence: $e");
+    }
+    lessons = timetableProvider.getWeek(week) ?? [];
+
+    // Find absence lesson in timetable
+    Lesson lesson = lessons.firstWhere(
+      (l) =>
+          _sameDate(l.date, absence.date) &&
+          l.subject.id == absence.subject.id &&
+          l.lessonIndex == absence.lessonIndex.toString(),
+      orElse: () => Lesson.fromJson({'isEmpty': true}),
+    );
+
+    if (lesson.isEmpty) {
+      return null;
+    } else {
+      return lesson;
+    }
+  }
+
+  // difference.inDays is not reliable
+  static bool _sameDate(DateTime a, DateTime b) =>
+      (a.year == b.year && a.month == b.month && a.day == b.day);
+}
diff --git a/filcnaplo/linux/filcnaplo.desktop b/refilc/linux/filcnaplo.desktop
old mode 100755
new mode 100644
similarity index 76%
rename from filcnaplo/linux/filcnaplo.desktop
rename to refilc/linux/filcnaplo.desktop
index deaa024..d558654
--- a/filcnaplo/linux/filcnaplo.desktop
+++ b/refilc/linux/filcnaplo.desktop
@@ -1,8 +1,8 @@
-  [Desktop Entry]
-  Name=reFilc
-  Comment=Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez
-  Exec=filcnaplo
-  Icon=icon.png
-  Terminal=false
-  Type=Application
+  [Desktop Entry]
+  Name=reFilc
+  Comment=Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez
+  Exec=refilc
+  Icon=icon.png
+  Terminal=false
+  Type=Application
   Categories=Education;
\ No newline at end of file
diff --git a/refilc/linux/flutter/generated_plugin_registrant.cc b/refilc/linux/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..0fcfb27
--- /dev/null
+++ b/refilc/linux/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,27 @@
+//
+//  Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+#include <dynamic_color/dynamic_color_plugin.h>
+#include <file_selector_linux/file_selector_plugin.h>
+#include <flutter_acrylic/flutter_acrylic_plugin.h>
+#include <url_launcher_linux/url_launcher_plugin.h>
+
+void fl_register_plugins(FlPluginRegistry* registry) {
+  g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
+      fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
+  dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
+  g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
+      fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
+  file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
+  g_autoptr(FlPluginRegistrar) flutter_acrylic_registrar =
+      fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterAcrylicPlugin");
+  flutter_acrylic_plugin_register_with_registrar(flutter_acrylic_registrar);
+  g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
+      fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
+  url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
+}
diff --git a/refilc/linux/flutter/generated_plugin_registrant.h b/refilc/linux/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..e0f0a47
--- /dev/null
+++ b/refilc/linux/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+//  Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter_linux/flutter_linux.h>
+
+// Registers Flutter plugins.
+void fl_register_plugins(FlPluginRegistry* registry);
+
+#endif  // GENERATED_PLUGIN_REGISTRANT_
diff --git a/refilc/linux/flutter/generated_plugins.cmake b/refilc/linux/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..c5541e6
--- /dev/null
+++ b/refilc/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,27 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+  dynamic_color
+  file_selector_linux
+  flutter_acrylic
+  url_launcher_linux
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/filcnaplo/linux/icon.png b/refilc/linux/icon.png
similarity index 100%
rename from filcnaplo/linux/icon.png
rename to refilc/linux/icon.png
diff --git a/filcnaplo/linux/main.cc b/refilc/linux/main.cc
similarity index 96%
rename from filcnaplo/linux/main.cc
rename to refilc/linux/main.cc
index 4340ffc..e7c5c54 100644
--- a/filcnaplo/linux/main.cc
+++ b/refilc/linux/main.cc
@@ -1,6 +1,6 @@
-#include "my_application.h"
-
-int main(int argc, char** argv) {
-  g_autoptr(MyApplication) app = my_application_new();
-  return g_application_run(G_APPLICATION(app), argc, argv);
-}
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+  g_autoptr(MyApplication) app = my_application_new();
+  return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/filcnaplo/linux/my_application.cc b/refilc/linux/my_application.cc
similarity index 97%
rename from filcnaplo/linux/my_application.cc
rename to refilc/linux/my_application.cc
index 05d121f..71d1af1 100644
--- a/filcnaplo/linux/my_application.cc
+++ b/refilc/linux/my_application.cc
@@ -1,104 +1,104 @@
-#include "my_application.h"
-
-#include <flutter_linux/flutter_linux.h>
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#endif
-
-#include "flutter/generated_plugin_registrant.h"
-
-struct _MyApplication {
-  GtkApplication parent_instance;
-  char** dart_entrypoint_arguments;
-};
-
-G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
-
-// Implements GApplication::activate.
-static void my_application_activate(GApplication* application) {
-  MyApplication* self = MY_APPLICATION(application);
-  GtkWindow* window =
-      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
-
-  // Use a header bar when running in GNOME as this is the common style used
-  // by applications and is the setup most users will be using (e.g. Ubuntu
-  // desktop).
-  // If running on X and not using GNOME then just use a traditional title bar
-  // in case the window manager does more exotic layout, e.g. tiling.
-  // If running on Wayland assume the header bar will work (may need changing
-  // if future cases occur).
-  gboolean use_header_bar = TRUE;
-#ifdef GDK_WINDOWING_X11
-  GdkScreen* screen = gtk_window_get_screen(window);
-  if (GDK_IS_X11_SCREEN(screen)) {
-    const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
-    if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
-      use_header_bar = FALSE;
-    }
-  }
-#endif
-  if (use_header_bar) {
-    GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
-    gtk_widget_show(GTK_WIDGET(header_bar));
-    gtk_header_bar_set_title(header_bar, "Filc Napló");
-    gtk_header_bar_set_show_close_button(header_bar, TRUE);
-    gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
-  } else {
-    gtk_window_set_title(window, "Filc Napló");
-  }
-
-  gtk_window_set_default_size(window, 1280, 720);
-  gtk_widget_show(GTK_WIDGET(window));
-
-  g_autoptr(FlDartProject) project = fl_dart_project_new();
-  fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
-
-  FlView* view = fl_view_new(project);
-  gtk_widget_show(GTK_WIDGET(view));
-  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
-
-  fl_register_plugins(FL_PLUGIN_REGISTRY(view));
-
-  gtk_widget_grab_focus(GTK_WIDGET(view));
-}
-
-// Implements GApplication::local_command_line.
-static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
-  MyApplication* self = MY_APPLICATION(application);
-  // Strip out the first argument as it is the binary name.
-  self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
-
-  g_autoptr(GError) error = nullptr;
-  if (!g_application_register(application, nullptr, &error)) {
-     g_warning("Failed to register: %s", error->message);
-     *exit_status = 1;
-     return TRUE;
-  }
-
-  g_application_activate(application);
-  *exit_status = 0;
-
-  return TRUE;
-}
-
-// Implements GObject::dispose.
-static void my_application_dispose(GObject* object) {
-  MyApplication* self = MY_APPLICATION(object);
-  g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
-  G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
-}
-
-static void my_application_class_init(MyApplicationClass* klass) {
-  G_APPLICATION_CLASS(klass)->activate = my_application_activate;
-  G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
-  G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
-}
-
-static void my_application_init(MyApplication* self) {}
-
-MyApplication* my_application_new() {
-  return MY_APPLICATION(g_object_new(my_application_get_type(),
-                                     "application-id", APPLICATION_ID,
-                                     "flags", G_APPLICATION_NON_UNIQUE,
-                                     nullptr));
-}
+#include "my_application.h"
+
+#include <flutter_linux/flutter_linux.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+  GtkApplication parent_instance;
+  char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+  MyApplication* self = MY_APPLICATION(application);
+  GtkWindow* window =
+      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+  // Use a header bar when running in GNOME as this is the common style used
+  // by applications and is the setup most users will be using (e.g. Ubuntu
+  // desktop).
+  // If running on X and not using GNOME then just use a traditional title bar
+  // in case the window manager does more exotic layout, e.g. tiling.
+  // If running on Wayland assume the header bar will work (may need changing
+  // if future cases occur).
+  gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+  GdkScreen* screen = gtk_window_get_screen(window);
+  if (GDK_IS_X11_SCREEN(screen)) {
+    const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+    if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+      use_header_bar = FALSE;
+    }
+  }
+#endif
+  if (use_header_bar) {
+    GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+    gtk_widget_show(GTK_WIDGET(header_bar));
+    gtk_header_bar_set_title(header_bar, "Filc Napló");
+    gtk_header_bar_set_show_close_button(header_bar, TRUE);
+    gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+  } else {
+    gtk_window_set_title(window, "Filc Napló");
+  }
+
+  gtk_window_set_default_size(window, 1280, 720);
+  gtk_widget_show(GTK_WIDGET(window));
+
+  g_autoptr(FlDartProject) project = fl_dart_project_new();
+  fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
+
+  FlView* view = fl_view_new(project);
+  gtk_widget_show(GTK_WIDGET(view));
+  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+  fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+  gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
+  MyApplication* self = MY_APPLICATION(application);
+  // Strip out the first argument as it is the binary name.
+  self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+  g_autoptr(GError) error = nullptr;
+  if (!g_application_register(application, nullptr, &error)) {
+     g_warning("Failed to register: %s", error->message);
+     *exit_status = 1;
+     return TRUE;
+  }
+
+  g_application_activate(application);
+  *exit_status = 0;
+
+  return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject* object) {
+  MyApplication* self = MY_APPLICATION(object);
+  g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+  G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+  G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+  G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
+  G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+  return MY_APPLICATION(g_object_new(my_application_get_type(),
+                                     "application-id", APPLICATION_ID,
+                                     "flags", G_APPLICATION_NON_UNIQUE,
+                                     nullptr));
+}
diff --git a/filcnaplo/linux/my_application.h b/refilc/linux/my_application.h
similarity index 95%
rename from filcnaplo/linux/my_application.h
rename to refilc/linux/my_application.h
index 8f20fb5..72271d5 100644
--- a/filcnaplo/linux/my_application.h
+++ b/refilc/linux/my_application.h
@@ -1,18 +1,18 @@
-#ifndef FLUTTER_MY_APPLICATION_H_
-#define FLUTTER_MY_APPLICATION_H_
-
-#include <gtk/gtk.h>
-
-G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
-                     GtkApplication)
-
-/**
- * my_application_new:
- *
- * Creates a new Flutter-based application.
- *
- * Returns: a new #MyApplication.
- */
-MyApplication* my_application_new();
-
-#endif  // FLUTTER_MY_APPLICATION_H_
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include <gtk/gtk.h>
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+                     GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif  // FLUTTER_MY_APPLICATION_H_
diff --git a/filcnaplo/macos/Flutter/Flutter-Debug.xcconfig b/refilc/macos/Flutter/Flutter-Debug.xcconfig
similarity index 98%
rename from filcnaplo/macos/Flutter/Flutter-Debug.xcconfig
rename to refilc/macos/Flutter/Flutter-Debug.xcconfig
index 63eaa61..4b81f9b 100644
--- a/filcnaplo/macos/Flutter/Flutter-Debug.xcconfig
+++ b/refilc/macos/Flutter/Flutter-Debug.xcconfig
@@ -1,2 +1,2 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
-#include "ephemeral/Flutter-Generated.xcconfig"
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/filcnaplo/macos/Flutter/Flutter-Release.xcconfig b/refilc/macos/Flutter/Flutter-Release.xcconfig
similarity index 98%
rename from filcnaplo/macos/Flutter/Flutter-Release.xcconfig
rename to refilc/macos/Flutter/Flutter-Release.xcconfig
index 88d14e0..5caa9d1 100644
--- a/filcnaplo/macos/Flutter/Flutter-Release.xcconfig
+++ b/refilc/macos/Flutter/Flutter-Release.xcconfig
@@ -1,2 +1,2 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
-#include "ephemeral/Flutter-Generated.xcconfig"
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/refilc/macos/Flutter/GeneratedPluginRegistrant.swift b/refilc/macos/Flutter/GeneratedPluginRegistrant.swift
new file mode 100644
index 0000000..a878503
--- /dev/null
+++ b/refilc/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -0,0 +1,32 @@
+//
+//  Generated file. Do not edit.
+//
+
+import FlutterMacOS
+import Foundation
+
+import connectivity_plus
+import dynamic_color
+import file_selector_macos
+import flutter_local_notifications
+import macos_window_utils
+import open_file
+import package_info_plus
+import path_provider_foundation
+import share_plus
+import sqflite
+import url_launcher_macos
+
+func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+  ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
+  DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
+  FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
+  FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
+  MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin"))
+  OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin"))
+  FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
+  PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
+  SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
+  SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
+  UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
+}
diff --git a/filcnaplo/macos/Podfile b/refilc/macos/Podfile
similarity index 100%
rename from filcnaplo/macos/Podfile
rename to refilc/macos/Podfile
diff --git a/filcnaplo/macos/Runner.xcodeproj/project.pbxproj b/refilc/macos/Runner.xcodeproj/project.pbxproj
similarity index 99%
rename from filcnaplo/macos/Runner.xcodeproj/project.pbxproj
rename to refilc/macos/Runner.xcodeproj/project.pbxproj
index 61c33df..b40331f 100644
--- a/filcnaplo/macos/Runner.xcodeproj/project.pbxproj
+++ b/refilc/macos/Runner.xcodeproj/project.pbxproj
@@ -434,7 +434,7 @@
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				NEW_SETTING = "";
-				PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
+				PRODUCT_BUNDLE_IDENTIFIER = hu.filc.refilc;
 				PRODUCT_NAME = "Felt Diary";
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_VERSION = 5.0;
@@ -574,7 +574,7 @@
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				NEW_SETTING = "";
-				PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
+				PRODUCT_BUNDLE_IDENTIFIER = hu.filc.refilc;
 				PRODUCT_NAME = "Felt Diary";
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -604,7 +604,7 @@
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				NEW_SETTING = "";
-				PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
+				PRODUCT_BUNDLE_IDENTIFIER = hu.filc.refilc;
 				PRODUCT_NAME = "Felt Diary";
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_VERSION = 5.0;
diff --git a/filcnaplo/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/refilc/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 96%
rename from filcnaplo/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to refilc/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index fc6bf80..18d9810 100644
--- a/filcnaplo/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/refilc/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>IDEDidComputeMac32BitWarning</key>
-	<true/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/filcnaplo/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/refilc/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
similarity index 100%
rename from filcnaplo/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
rename to refilc/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
diff --git a/filcnaplo/ios/Runner.xcworkspace/contents.xcworkspacedata b/refilc/macos/Runner.xcworkspace/contents.xcworkspacedata
similarity index 95%
rename from filcnaplo/ios/Runner.xcworkspace/contents.xcworkspacedata
rename to refilc/macos/Runner.xcworkspace/contents.xcworkspacedata
index 17ccc03..21a3cc1 100644
--- a/filcnaplo/ios/Runner.xcworkspace/contents.xcworkspacedata
+++ b/refilc/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
-   version = "1.0">
-   <FileRef
-      location = "group:Runner.xcodeproj">
-   </FileRef>
-   <FileRef
-      location = "group:Pods/Pods.xcodeproj">
-   </FileRef>
-</Workspace>
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:Runner.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/filcnaplo/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/refilc/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 96%
rename from filcnaplo/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to refilc/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index fc6bf80..18d9810 100644
--- a/filcnaplo/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/refilc/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>IDEDidComputeMac32BitWarning</key>
-	<true/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/filcnaplo/macos/Runner/AppDelegate.swift b/refilc/macos/Runner/AppDelegate.swift
similarity index 95%
rename from filcnaplo/macos/Runner/AppDelegate.swift
rename to refilc/macos/Runner/AppDelegate.swift
index 553a135..d53ef64 100644
--- a/filcnaplo/macos/Runner/AppDelegate.swift
+++ b/refilc/macos/Runner/AppDelegate.swift
@@ -1,9 +1,9 @@
-import Cocoa
-import FlutterMacOS
-
-@NSApplicationMain
-class AppDelegate: FlutterAppDelegate {
-  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
-    return true
-  }
-}
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+    return true
+  }
+}
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 94%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
index 8d4e7cb..a2ec33f 100644
--- a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,68 +1,68 @@
-{
-  "images" : [
-    {
-      "size" : "16x16",
-      "idiom" : "mac",
-      "filename" : "app_icon_16.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "16x16",
-      "idiom" : "mac",
-      "filename" : "app_icon_32.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "32x32",
-      "idiom" : "mac",
-      "filename" : "app_icon_32.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "32x32",
-      "idiom" : "mac",
-      "filename" : "app_icon_64.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "128x128",
-      "idiom" : "mac",
-      "filename" : "app_icon_128.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "128x128",
-      "idiom" : "mac",
-      "filename" : "app_icon_256.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "256x256",
-      "idiom" : "mac",
-      "filename" : "app_icon_256.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "256x256",
-      "idiom" : "mac",
-      "filename" : "app_icon_512.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "512x512",
-      "idiom" : "mac",
-      "filename" : "app_icon_512.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "512x512",
-      "idiom" : "mac",
-      "filename" : "app_icon_1024.png",
-      "scale" : "2x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
+{
+  "images" : [
+    {
+      "size" : "16x16",
+      "idiom" : "mac",
+      "filename" : "app_icon_16.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "16x16",
+      "idiom" : "mac",
+      "filename" : "app_icon_32.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "32x32",
+      "idiom" : "mac",
+      "filename" : "app_icon_32.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "32x32",
+      "idiom" : "mac",
+      "filename" : "app_icon_64.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "128x128",
+      "idiom" : "mac",
+      "filename" : "app_icon_128.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "128x128",
+      "idiom" : "mac",
+      "filename" : "app_icon_256.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "256x256",
+      "idiom" : "mac",
+      "filename" : "app_icon_256.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "256x256",
+      "idiom" : "mac",
+      "filename" : "app_icon_512.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "512x512",
+      "idiom" : "mac",
+      "filename" : "app_icon_512.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "512x512",
+      "idiom" : "mac",
+      "filename" : "app_icon_1024.png",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
diff --git a/filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
similarity index 100%
rename from filcnaplo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
rename to refilc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
diff --git a/filcnaplo/macos/Runner/Base.lproj/MainMenu.xib b/refilc/macos/Runner/Base.lproj/MainMenu.xib
similarity index 98%
rename from filcnaplo/macos/Runner/Base.lproj/MainMenu.xib
rename to refilc/macos/Runner/Base.lproj/MainMenu.xib
index 3f655e3..bbf5e2d 100644
--- a/filcnaplo/macos/Runner/Base.lproj/MainMenu.xib
+++ b/refilc/macos/Runner/Base.lproj/MainMenu.xib
@@ -1,348 +1,348 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21179.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
-    <dependencies>
-        <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21179.7"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
-            <connections>
-                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
-            </connections>
-        </customObject>
-        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
-        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
-        <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Felt_Diary" customModuleProvider="target">
-            <connections>
-                <outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
-                <outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
-            </connections>
-        </customObject>
-        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
-        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
-            <items>
-                <menuItem title="APP_NAME" id="1Xt-HY-uBw">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
-                        <items>
-                            <menuItem title="About APP_NAME" id="5kV-Vb-QxS">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
-                            <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
-                            <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
-                            <menuItem title="Services" id="NMo-om-nkz">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
-                            <menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
-                                <connections>
-                                    <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                                <connections>
-                                    <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Show All" id="Kd2-mp-pUS">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
-                            <menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
-                                <connections>
-                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
-                                </connections>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="Edit" id="5QF-Oa-p0T">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="Edit" id="W48-6f-4Dl">
-                        <items>
-                            <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
-                                <connections>
-                                    <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
-                                <connections>
-                                    <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
-                            <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
-                                <connections>
-                                    <action selector="cut:" target="-1" id="YJe-68-I9s"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
-                                <connections>
-                                    <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
-                                <connections>
-                                    <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                                <connections>
-                                    <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Delete" id="pa3-QI-u2k">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
-                                <connections>
-                                    <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
-                            <menuItem title="Find" id="4EN-yA-p0u">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Find" id="1b7-l0-nxx">
-                                    <items>
-                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
-                                            <connections>
-                                                <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
-                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                                            <connections>
-                                                <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
-                                            <connections>
-                                                <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
-                                            <connections>
-                                                <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
-                                            <connections>
-                                                <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
-                                            <connections>
-                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
-                                            </connections>
-                                        </menuItem>
-                                    </items>
-                                </menu>
-                            </menuItem>
-                            <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
-                                    <items>
-                                        <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
-                                            <connections>
-                                                <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
-                                            <connections>
-                                                <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
-                                        <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
-                                            </connections>
-                                        </menuItem>
-                                    </items>
-                                </menu>
-                            </menuItem>
-                            <menuItem title="Substitutions" id="9ic-FL-obx">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
-                                    <items>
-                                        <menuItem title="Show Substitutions" id="z6F-FW-3nz">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
-                                        <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Smart Quotes" id="hQb-2v-fYv">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Smart Dashes" id="rgM-f4-ycn">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Smart Links" id="cwL-P1-jid">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Data Detectors" id="tRr-pd-1PS">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Text Replacement" id="HFQ-gK-NFA">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
-                                            </connections>
-                                        </menuItem>
-                                    </items>
-                                </menu>
-                            </menuItem>
-                            <menuItem title="Transformations" id="2oI-Rn-ZJC">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
-                                    <items>
-                                        <menuItem title="Make Upper Case" id="vmV-6d-7jI">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Make Lower Case" id="d9M-CD-aMd">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Capitalize" id="UEZ-Bs-lqG">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
-                                            </connections>
-                                        </menuItem>
-                                    </items>
-                                </menu>
-                            </menuItem>
-                            <menuItem title="Speech" id="xrE-MZ-jX0">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
-                                    <items>
-                                        <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
-                                            </connections>
-                                        </menuItem>
-                                        <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
-                                            <modifierMask key="keyEquivalentModifierMask"/>
-                                            <connections>
-                                                <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
-                                            </connections>
-                                        </menuItem>
-                                    </items>
-                                </menu>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="View" id="H8h-7b-M4v">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="View" id="HyV-fh-RgO">
-                        <items>
-                            <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
-                                <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
-                                <connections>
-                                    <action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
-                                </connections>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="Window" id="aUF-d1-5bR">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
-                        <items>
-                            <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
-                                <connections>
-                                    <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Zoom" id="R4o-n2-Eq4">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
-                            <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
-                                </connections>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="Help" id="EPT-qC-fAb">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="Help" systemMenu="help" id="rJ0-wn-3NY"/>
-                </menuItem>
-            </items>
-            <point key="canvasLocation" x="142" y="-258"/>
-        </menu>
-        <window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" titlebarAppearsTransparent="YES" toolbarStyle="unified" titleVisibility="hidden" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Felt_Diary" customModuleProvider="target">
-            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
-            <rect key="contentRect" x="335" y="390" width="800" height="600"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1440" height="875"/>
-            <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
-                <rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
-                <autoresizingMask key="autoresizingMask"/>
-            </view>
-            <toolbar key="toolbar" implicitIdentifier="76215EDB-EEE8-458B-9EB5-96D223607AF7" autosavesConfiguration="NO" displayMode="iconAndLabel" sizeMode="regular" id="HrH-7k-XRf">
-                <allowedToolbarItems/>
-                <defaultToolbarItems/>
-            </toolbar>
-            <point key="canvasLocation" x="139" y="143"/>
-        </window>
-    </objects>
-</document>
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21179.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21179.7"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+            <connections>
+                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Felt_Diary" customModuleProvider="target">
+            <connections>
+                <outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
+                <outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
+        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+            <items>
+                <menuItem title="APP_NAME" id="1Xt-HY-uBw">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
+                        <items>
+                            <menuItem title="About APP_NAME" id="5kV-Vb-QxS">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+                            <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
+                            <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
+                            <menuItem title="Services" id="NMo-om-nkz">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
+                            <menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
+                                <connections>
+                                    <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                <connections>
+                                    <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Show All" id="Kd2-mp-pUS">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+                            <menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
+                                <connections>
+                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Edit" id="5QF-Oa-p0T">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="Edit" id="W48-6f-4Dl">
+                        <items>
+                            <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
+                                <connections>
+                                    <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
+                                <connections>
+                                    <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
+                            <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
+                                <connections>
+                                    <action selector="cut:" target="-1" id="YJe-68-I9s"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
+                                <connections>
+                                    <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
+                                <connections>
+                                    <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                <connections>
+                                    <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Delete" id="pa3-QI-u2k">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
+                                <connections>
+                                    <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
+                            <menuItem title="Find" id="4EN-yA-p0u">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Find" id="1b7-l0-nxx">
+                                    <items>
+                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
+                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
+                                            <connections>
+                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                            <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
+                                    <items>
+                                        <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
+                                            <connections>
+                                                <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
+                                            <connections>
+                                                <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
+                                        <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                            <menuItem title="Substitutions" id="9ic-FL-obx">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
+                                    <items>
+                                        <menuItem title="Show Substitutions" id="z6F-FW-3nz">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
+                                        <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Smart Quotes" id="hQb-2v-fYv">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Smart Dashes" id="rgM-f4-ycn">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Smart Links" id="cwL-P1-jid">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Data Detectors" id="tRr-pd-1PS">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Text Replacement" id="HFQ-gK-NFA">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                            <menuItem title="Transformations" id="2oI-Rn-ZJC">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
+                                    <items>
+                                        <menuItem title="Make Upper Case" id="vmV-6d-7jI">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Make Lower Case" id="d9M-CD-aMd">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Capitalize" id="UEZ-Bs-lqG">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                            <menuItem title="Speech" id="xrE-MZ-jX0">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
+                                    <items>
+                                        <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="View" id="H8h-7b-M4v">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="View" id="HyV-fh-RgO">
+                        <items>
+                            <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
+                                <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
+                                <connections>
+                                    <action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Window" id="aUF-d1-5bR">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+                        <items>
+                            <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+                                <connections>
+                                    <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Zoom" id="R4o-n2-Eq4">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
+                            <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Help" id="EPT-qC-fAb">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="Help" systemMenu="help" id="rJ0-wn-3NY"/>
+                </menuItem>
+            </items>
+            <point key="canvasLocation" x="142" y="-258"/>
+        </menu>
+        <window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" titlebarAppearsTransparent="YES" toolbarStyle="unified" titleVisibility="hidden" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Felt_Diary" customModuleProvider="target">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
+            <rect key="contentRect" x="335" y="390" width="800" height="600"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1440" height="875"/>
+            <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
+                <rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
+                <autoresizingMask key="autoresizingMask"/>
+            </view>
+            <toolbar key="toolbar" implicitIdentifier="76215EDB-EEE8-458B-9EB5-96D223607AF7" autosavesConfiguration="NO" displayMode="iconAndLabel" sizeMode="regular" id="HrH-7k-XRf">
+                <allowedToolbarItems/>
+                <defaultToolbarItems/>
+            </toolbar>
+            <point key="canvasLocation" x="139" y="143"/>
+        </window>
+    </objects>
+</document>
diff --git a/filcnaplo/macos/Runner/Configs/AppInfo.xcconfig b/refilc/macos/Runner/Configs/AppInfo.xcconfig
similarity index 97%
rename from filcnaplo/macos/Runner/Configs/AppInfo.xcconfig
rename to refilc/macos/Runner/Configs/AppInfo.xcconfig
index 1027f1d..b86f95b 100644
--- a/filcnaplo/macos/Runner/Configs/AppInfo.xcconfig
+++ b/refilc/macos/Runner/Configs/AppInfo.xcconfig
@@ -1,14 +1,14 @@
-// Application-level settings for the Runner target.
-//
-// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
-// future. If not, the values below would default to using the project name when this becomes a
-// 'flutter create' template.
-
-// The application's name. By default this is also the title of the Flutter window.
-PRODUCT_NAME = reFilc
-
-// The application's bundle identifier
-PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo
-
-// The copyright displayed in application information
-PRODUCT_COPYRIGHT = reFilc
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = reFilc
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = reFilc
diff --git a/filcnaplo/macos/Runner/Configs/Debug.xcconfig b/refilc/macos/Runner/Configs/Debug.xcconfig
similarity index 97%
rename from filcnaplo/macos/Runner/Configs/Debug.xcconfig
rename to refilc/macos/Runner/Configs/Debug.xcconfig
index b398823..36b0fd9 100644
--- a/filcnaplo/macos/Runner/Configs/Debug.xcconfig
+++ b/refilc/macos/Runner/Configs/Debug.xcconfig
@@ -1,2 +1,2 @@
-#include "../../Flutter/Flutter-Debug.xcconfig"
-#include "Warnings.xcconfig"
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/filcnaplo/macos/Runner/Configs/Release.xcconfig b/refilc/macos/Runner/Configs/Release.xcconfig
similarity index 97%
rename from filcnaplo/macos/Runner/Configs/Release.xcconfig
rename to refilc/macos/Runner/Configs/Release.xcconfig
index d93e5dc..dff4f49 100644
--- a/filcnaplo/macos/Runner/Configs/Release.xcconfig
+++ b/refilc/macos/Runner/Configs/Release.xcconfig
@@ -1,2 +1,2 @@
-#include "../../Flutter/Flutter-Release.xcconfig"
-#include "Warnings.xcconfig"
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/filcnaplo/macos/Runner/Configs/Warnings.xcconfig b/refilc/macos/Runner/Configs/Warnings.xcconfig
similarity index 97%
rename from filcnaplo/macos/Runner/Configs/Warnings.xcconfig
rename to refilc/macos/Runner/Configs/Warnings.xcconfig
index fb4d7d3..42bcbf4 100644
--- a/filcnaplo/macos/Runner/Configs/Warnings.xcconfig
+++ b/refilc/macos/Runner/Configs/Warnings.xcconfig
@@ -1,13 +1,13 @@
-WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
-GCC_WARN_UNDECLARED_SELECTOR = YES
-CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
-CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
-CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
-CLANG_WARN_PRAGMA_PACK = YES
-CLANG_WARN_STRICT_PROTOTYPES = YES
-CLANG_WARN_COMMA = YES
-GCC_WARN_STRICT_SELECTOR_MATCH = YES
-CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
-CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
-GCC_WARN_SHADOW = YES
-CLANG_WARN_UNREACHABLE_CODE = YES
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/filcnaplo/macos/Runner/DebugProfile.entitlements b/refilc/macos/Runner/DebugProfile.entitlements
similarity index 96%
rename from filcnaplo/macos/Runner/DebugProfile.entitlements
rename to refilc/macos/Runner/DebugProfile.entitlements
index acb5c4c..9f5b50b 100644
--- a/filcnaplo/macos/Runner/DebugProfile.entitlements
+++ b/refilc/macos/Runner/DebugProfile.entitlements
@@ -1,16 +1,16 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.security.app-sandbox</key>
-	<true/>
-	<key>com.apple.security.cs.allow-jit</key>
-	<true/>
-	<key>com.apple.security.files.downloads.read-write</key>
-	<true/>
-	<key>com.apple.security.network.client</key>
-	<true/>
-	<key>com.apple.security.network.server</key>
-	<true/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.app-sandbox</key>
+	<true/>
+	<key>com.apple.security.cs.allow-jit</key>
+	<true/>
+	<key>com.apple.security.files.downloads.read-write</key>
+	<true/>
+	<key>com.apple.security.network.client</key>
+	<true/>
+	<key>com.apple.security.network.server</key>
+	<true/>
+</dict>
+</plist>
diff --git a/filcnaplo/macos/Runner/Info.plist b/refilc/macos/Runner/Info.plist
similarity index 97%
rename from filcnaplo/macos/Runner/Info.plist
rename to refilc/macos/Runner/Info.plist
index 0e53e66..91dd316 100644
--- a/filcnaplo/macos/Runner/Info.plist
+++ b/refilc/macos/Runner/Info.plist
@@ -1,32 +1,32 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>$(DEVELOPMENT_LANGUAGE)</string>
-	<key>CFBundleExecutable</key>
-	<string>${EXECUTABLE_NAME}</string>
-	<key>CFBundleIconFile</key>
-	<string></string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>$(FLUTTER_BUILD_NAME)</string>
-	<key>CFBundleVersion</key>
-	<string>$(FLUTTER_BUILD_NUMBER)</string>
-	<key>LSMinimumSystemVersion</key>
-	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
-	<key>NSHumanReadableCopyright</key>
-	<string>$(PRODUCT_COPYRIGHT)</string>
-	<key>NSMainNibFile</key>
-	<string>MainMenu</string>
-	<key>NSPrincipalClass</key>
-	<string>NSApplication</string>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(FLUTTER_BUILD_NAME)</string>
+	<key>CFBundleVersion</key>
+	<string>$(FLUTTER_BUILD_NUMBER)</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>$(PRODUCT_COPYRIGHT)</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/filcnaplo/macos/Runner/MainFlutterWindow.swift b/refilc/macos/Runner/MainFlutterWindow.swift
similarity index 96%
rename from filcnaplo/macos/Runner/MainFlutterWindow.swift
rename to refilc/macos/Runner/MainFlutterWindow.swift
index 59fb24d..4b4fe9b 100644
--- a/filcnaplo/macos/Runner/MainFlutterWindow.swift
+++ b/refilc/macos/Runner/MainFlutterWindow.swift
@@ -1,19 +1,19 @@
-import Cocoa
-import FlutterMacOS
-import flutter_acrylic
-
-class MainFlutterWindow: NSWindow {
-  override func awakeFromNib() {
-      let blurryContainerViewController = BlurryContainerViewController()
-    let windowFrame = self.frame
-    self.contentViewController = blurryContainerViewController
-    self.setFrame(windowFrame, display: true)
-
-    /* Initialize the flutter_acrylic plugin */
-    MainFlutterWindowManipulator.start(mainFlutterWindow: self)
-
-    RegisterGeneratedPlugins(registry: blurryContainerViewController.flutterViewController)
-
-    super.awakeFromNib()
-  }
-}
+import Cocoa
+import FlutterMacOS
+import flutter_acrylic
+
+class MainFlutterWindow: NSWindow {
+  override func awakeFromNib() {
+      let blurryContainerViewController = BlurryContainerViewController()
+    let windowFrame = self.frame
+    self.contentViewController = blurryContainerViewController
+    self.setFrame(windowFrame, display: true)
+
+    /* Initialize the flutter_acrylic plugin */
+    MainFlutterWindowManipulator.start(mainFlutterWindow: self)
+
+    RegisterGeneratedPlugins(registry: blurryContainerViewController.flutterViewController)
+
+    super.awakeFromNib()
+  }
+}
diff --git a/filcnaplo/macos/Runner/Release.entitlements b/refilc/macos/Runner/Release.entitlements
similarity index 96%
rename from filcnaplo/macos/Runner/Release.entitlements
rename to refilc/macos/Runner/Release.entitlements
index 0da2e44..8dc5725 100644
--- a/filcnaplo/macos/Runner/Release.entitlements
+++ b/refilc/macos/Runner/Release.entitlements
@@ -1,12 +1,12 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.security.app-sandbox</key>
-	<true/>
-	<key>com.apple.security.files.downloads.read-write</key>
-	<true/>
-	<key>com.apple.security.network.client</key>
-	<true/>
-</dict>
-</plist>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.app-sandbox</key>
+	<true/>
+	<key>com.apple.security.files.downloads.read-write</key>
+	<true/>
+	<key>com.apple.security.network.client</key>
+	<true/>
+</dict>
+</plist>
diff --git a/filcnaplo/pubspec.yaml b/refilc/pubspec.yaml
similarity index 90%
rename from filcnaplo/pubspec.yaml
rename to refilc/pubspec.yaml
index f56bc27..0c54ffd 100644
--- a/filcnaplo/pubspec.yaml
+++ b/refilc/pubspec.yaml
@@ -1,171 +1,171 @@
-name: filcnaplo
-description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
-homepage: https://refilc.hu
-publish_to: "none"
-
-version: 4.2.3+223
-
-environment:
-  sdk: ">=2.17.0 <3.0.0"
-
-dependencies:
-  flutter:
-    sdk: flutter
-  cupertino_icons: ^1.0.2
-
-  # Local filcnaplo packages
-  filcnaplo_mobile_ui:
-    path: "../filcnaplo_mobile_ui/"
-  filcnaplo_desktop_ui:
-    path: "../filcnaplo_desktop_ui/"
-  filcnaplo_kreta_api:
-    path: "../filcnaplo_kreta_api/"
-  filcnaplo_premium:
-    path: "../filcnaplo_premium/"
-
-  flutter_localizations:
-    sdk: flutter
-  i18n_extension: ^9.0.0
-  sqflite: ^2.2.0+2
-  intl: ^0.18.0
-  provider: ^5.0.0
-  http: ^0.13.3
-  uuid: ^3.0.4
-  html: ^0.15.0
-  open_file:
-    git:
-      url: https://github.com/crazecoder/open_file
-      ref: master
-  path_provider: ^2.0.2
-  permission_handler: ^10.2.0
-  share_plus: ^7.0.2
-  connectivity_plus: ^4.0.1
-  flutter_displaymode: ^0.6.0
-  quick_actions: ^1.0.1
-  animated_list_plus: ^0.5.0
-  dynamic_color: ^1.2.2
-  material_color_utilities: ^0.5.0
-  crypto: ^3.0.2
-  elegant_notification: ^1.6.1
-  flutter_feather_icons: ^2.0.0+1
-  live_activities: ^1.7.4
-  animated_flip_counter: ^0.2.5
-  lottie: ^1.4.3
-  rive: ^0.9.1
-  animated_background: ^2.0.0
-  dropdown_button2: ^1.8.9
-  home_widget: ^0.1.6
-  flutter_expandable_fab: ^1.8.1
-  uni_links: ^0.5.1
-  url_launcher: ^6.1.6
-  workmanager: ^0.5.1
-  flutter_svg: ^1.1.6
-  image_picker: ^0.8.6
-  animations: ^2.0.1
-  background_fetch: ^1.1.5
-  flutter_local_notifications: ^14.1.0
-  package_info_plus: ^4.0.2
-  screenshot: ^2.1.0
-  flutter_staggered_grid_view: ^0.7.0
-  sqflite_common_ffi_web: ^0.4.0
-  image_crop:
-    git:
-      url: https://github.com/kimaah/image_crop.git
-
-dev_dependencies:
-  flutter_lints: ^2.0.1
-  flutter_launcher_icons: "^0.13.1"
-  flutter_native_splash: "^2.3.0"
-  sqflite_common_ffi: ^2.0.0+3
-
-flutter:
-  uses-material-design: true
-
-  assets:
-    - assets/icons/ic_launcher.png
-    - assets/icons/ic_splash.png
-    - assets/animations/
-    - assets/images/
-    - assets/images/subject_covers/
-
-  fonts:
-    - family: FilcIcons
-      fonts:
-        - asset: assets/fonts/FilcIcons.ttf
-    - family: Montserrat
-      fonts:
-        - asset: assets/fonts/Montserrat/Montserrat-Black.ttf
-          weight: 900
-        - asset: assets/fonts/Montserrat/Montserrat-BlackItalic.ttf
-          weight: 900
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-ExtraBold.ttf
-          weight: 800
-        - asset: assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf
-          weight: 800
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-Bold.ttf
-          weight: 700
-        - asset: assets/fonts/Montserrat/Montserrat-BoldItalic.ttf
-          weight: 700
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-SemiBold.ttf
-          weight: 600
-        - asset: assets/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf
-          weight: 600
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-Medium.ttf
-          weight: 500
-        - asset: assets/fonts/Montserrat/Montserrat-MediumItalic.ttf
-          weight: 500
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-Regular.ttf
-          weight: 400
-        - asset: assets/fonts/Montserrat/Montserrat-Italic.ttf
-          weight: 400
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-Light.ttf
-          weight: 300
-        - asset: assets/fonts/Montserrat/Montserrat-LightItalic.ttf
-          weight: 300
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-ExtraLight.ttf
-          weight: 200
-        - asset: assets/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf
-          weight: 200
-          style: italic
-        - asset: assets/fonts/Montserrat/Montserrat-Thin.ttf
-          weight: 100
-        - asset: assets/fonts/Montserrat/Montserrat-ThinItalic.ttf
-          weight: 100
-          style: italic
-
-    - family: SpaceMono
-      fonts:
-        - asset: assets/fonts/SpaceMono/SpaceMono-Regular.ttf
-        - asset: assets/fonts/SpaceMono/SpaceMono-Bold.ttf
-          weight: 700
-        - asset: assets/fonts/SpaceMono/SpaceMono-Italic.ttf
-          style: italic
-        - asset: assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf
-          weight: 700
-          style: italic
-
-flutter_launcher_icons:
-  image_path: assets/icons/ic_android.png
-  android: true
-  adaptive_icon_background: "#3D7BF4"
-  adaptive_icon_foreground: assets/icons/ic_android.png
-  ios: false
-  remove_alpha_ios: false
-
-flutter_native_splash:
-  color: "#3D7BF4"
-  image: assets/icons/ic_splash.png
-  android_12:
-    image: assets/icons/ic_splash.png
-  android: true
-  android_gravity: center
-  ios: true
-  ios_content_mode: center
-  web: false
+name: refilc
+description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
+homepage: https://refilc.hu
+publish_to: "none"
+
+version: 4.2.3+223
+
+environment:
+  sdk: ">=2.17.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  cupertino_icons: ^1.0.2
+
+  # Local refilc packages
+  refilc_mobile_ui:
+    path: "../refilc_mobile_ui/"
+  refilc_desktop_ui:
+    path: "../refilc_desktop_ui/"
+  refilc_kreta_api:
+    path: "../refilc_kreta_api/"
+  refilc_premium:
+    path: "../refilc_premium/"
+
+  flutter_localizations:
+    sdk: flutter
+  i18n_extension: ^9.0.0
+  sqflite: ^2.2.0+2
+  intl: ^0.18.0
+  provider: ^5.0.0
+  http: ^0.13.3
+  uuid: ^3.0.4
+  html: ^0.15.0
+  open_file:
+    git:
+      url: https://github.com/crazecoder/open_file
+      ref: master
+  path_provider: ^2.0.2
+  permission_handler: ^10.2.0
+  share_plus: ^7.0.2
+  connectivity_plus: ^4.0.1
+  flutter_displaymode: ^0.6.0
+  quick_actions: ^1.0.1
+  animated_list_plus: ^0.5.0
+  dynamic_color: ^1.2.2
+  material_color_utilities: ^0.5.0
+  crypto: ^3.0.2
+  elegant_notification: ^1.6.1
+  flutter_feather_icons: ^2.0.0+1
+  live_activities: ^1.7.4
+  animated_flip_counter: ^0.2.5
+  lottie: ^1.4.3
+  rive: ^0.9.1
+  animated_background: ^2.0.0
+  dropdown_button2: ^1.8.9
+  home_widget: ^0.1.6
+  flutter_expandable_fab: ^1.8.1
+  uni_links: ^0.5.1
+  url_launcher: ^6.1.6
+  workmanager: ^0.5.1
+  flutter_svg: ^1.1.6
+  image_picker: ^0.8.6
+  animations: ^2.0.1
+  background_fetch: ^1.1.5
+  flutter_local_notifications: ^14.1.0
+  package_info_plus: ^4.0.2
+  screenshot: ^2.1.0
+  flutter_staggered_grid_view: ^0.7.0
+  sqflite_common_ffi_web: ^0.4.0
+  image_crop:
+    git:
+      url: https://github.com/kimaah/image_crop.git
+
+dev_dependencies:
+  flutter_lints: ^2.0.1
+  flutter_launcher_icons: "^0.13.1"
+  flutter_native_splash: "^2.3.0"
+  sqflite_common_ffi: ^2.0.0+3
+
+flutter:
+  uses-material-design: true
+
+  assets:
+    - assets/icons/ic_launcher.png
+    - assets/icons/ic_splash.png
+    - assets/animations/
+    - assets/images/
+    - assets/images/subject_covers/
+
+  fonts:
+    - family: FilcIcons
+      fonts:
+        - asset: assets/fonts/FilcIcons.ttf
+    - family: Montserrat
+      fonts:
+        - asset: assets/fonts/Montserrat/Montserrat-Black.ttf
+          weight: 900
+        - asset: assets/fonts/Montserrat/Montserrat-BlackItalic.ttf
+          weight: 900
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-ExtraBold.ttf
+          weight: 800
+        - asset: assets/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf
+          weight: 800
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-Bold.ttf
+          weight: 700
+        - asset: assets/fonts/Montserrat/Montserrat-BoldItalic.ttf
+          weight: 700
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-SemiBold.ttf
+          weight: 600
+        - asset: assets/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf
+          weight: 600
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-Medium.ttf
+          weight: 500
+        - asset: assets/fonts/Montserrat/Montserrat-MediumItalic.ttf
+          weight: 500
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-Regular.ttf
+          weight: 400
+        - asset: assets/fonts/Montserrat/Montserrat-Italic.ttf
+          weight: 400
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-Light.ttf
+          weight: 300
+        - asset: assets/fonts/Montserrat/Montserrat-LightItalic.ttf
+          weight: 300
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-ExtraLight.ttf
+          weight: 200
+        - asset: assets/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf
+          weight: 200
+          style: italic
+        - asset: assets/fonts/Montserrat/Montserrat-Thin.ttf
+          weight: 100
+        - asset: assets/fonts/Montserrat/Montserrat-ThinItalic.ttf
+          weight: 100
+          style: italic
+
+    - family: SpaceMono
+      fonts:
+        - asset: assets/fonts/SpaceMono/SpaceMono-Regular.ttf
+        - asset: assets/fonts/SpaceMono/SpaceMono-Bold.ttf
+          weight: 700
+        - asset: assets/fonts/SpaceMono/SpaceMono-Italic.ttf
+          style: italic
+        - asset: assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf
+          weight: 700
+          style: italic
+
+flutter_launcher_icons:
+  image_path: assets/icons/ic_android.png
+  android: true
+  adaptive_icon_background: "#3D7BF4"
+  adaptive_icon_foreground: assets/icons/ic_android.png
+  ios: false
+  remove_alpha_ios: false
+
+flutter_native_splash:
+  color: "#3D7BF4"
+  image: assets/icons/ic_splash.png
+  android_12:
+    image: assets/icons/ic_splash.png
+  android: true
+  android_gravity: center
+  ios: true
+  ios_content_mode: center
+  web: false
diff --git a/filcnaplo/run.sh b/refilc/run.sh
similarity index 95%
rename from filcnaplo/run.sh
rename to refilc/run.sh
index 1a09367..495e44e 100644
--- a/filcnaplo/run.sh
+++ b/refilc/run.sh
@@ -1,12 +1,12 @@
-#!/bin/fish
-
-function get_version
-  cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
-end
-
-
-if test -e /mnt/enc/keys/filc3.properties
-  set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties 
-end
-
-flutter run --debug --dart-define=APPVER=(get_version)
+#!/bin/fish
+
+function get_version
+  cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
+end
+
+
+if test -e /mnt/enc/keys/filc3.properties
+  set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties 
+end
+
+flutter run --debug --dart-define=APPVER=(get_version)
diff --git a/filcnaplo/run_release.sh b/refilc/run_release.sh
similarity index 95%
rename from filcnaplo/run_release.sh
rename to refilc/run_release.sh
index dbaaa92..35c1037 100644
--- a/filcnaplo/run_release.sh
+++ b/refilc/run_release.sh
@@ -1,12 +1,12 @@
-#!/bin/fish
-
-function get_version
-  cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
-end
-
-
-if test -e /mnt/enc/keys/filc3.properties
-  set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties 
-end
-
-flutter run --release --dart-define=APPVER=(get_version)
+#!/bin/fish
+
+function get_version
+  cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
+end
+
+
+if test -e /mnt/enc/keys/filc3.properties
+  set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties 
+end
+
+flutter run --release --dart-define=APPVER=(get_version)
diff --git a/filcnaplo/test/widget_test.dart b/refilc/test/widget_test.dart
similarity index 96%
rename from filcnaplo/test/widget_test.dart
rename to refilc/test/widget_test.dart
index 1b85968..adccc85 100644
--- a/filcnaplo/test/widget_test.dart
+++ b/refilc/test/widget_test.dart
@@ -8,7 +8,7 @@
 // import 'package:flutter/material.dart';
 // import 'package:flutter_test/flutter_test.dart';
 
-// import 'package:filcnaplo/main.dart';
+// import 'package:refilc/main.dart';
 
 // void main() {
 //   testWidgets('Counter increments smoke test', (WidgetTester tester) async {
diff --git a/filcnaplo/web/favicon.png b/refilc/web/favicon.png
similarity index 100%
rename from filcnaplo/web/favicon.png
rename to refilc/web/favicon.png
diff --git a/filcnaplo/web/icons/Icon-192.png b/refilc/web/icons/Icon-192.png
similarity index 100%
rename from filcnaplo/web/icons/Icon-192.png
rename to refilc/web/icons/Icon-192.png
diff --git a/filcnaplo/web/icons/Icon-512.png b/refilc/web/icons/Icon-512.png
similarity index 100%
rename from filcnaplo/web/icons/Icon-512.png
rename to refilc/web/icons/Icon-512.png
diff --git a/filcnaplo/web/icons/Icon-maskable-192.png b/refilc/web/icons/Icon-maskable-192.png
similarity index 100%
rename from filcnaplo/web/icons/Icon-maskable-192.png
rename to refilc/web/icons/Icon-maskable-192.png
diff --git a/filcnaplo/web/icons/Icon-maskable-512.png b/refilc/web/icons/Icon-maskable-512.png
similarity index 100%
rename from filcnaplo/web/icons/Icon-maskable-512.png
rename to refilc/web/icons/Icon-maskable-512.png
diff --git a/filcnaplo/web/index.html b/refilc/web/index.html
similarity index 95%
rename from filcnaplo/web/index.html
rename to refilc/web/index.html
index d806e3c..c5beab9 100644
--- a/filcnaplo/web/index.html
+++ b/refilc/web/index.html
@@ -23,13 +23,13 @@
   <!-- iOS meta tags & icons -->
   <meta name="apple-mobile-web-app-capable" content="yes">
   <meta name="apple-mobile-web-app-status-bar-style" content="black">
-  <meta name="apple-mobile-web-app-title" content="filcnaplo">
+  <meta name="apple-mobile-web-app-title" content="refilc">
   <link rel="apple-touch-icon" href="icons/Icon-192.png">
 
   <!-- Favicon -->
   <link rel="icon" type="image/png" href="favicon.png"/>
 
-  <title>filcnaplo</title>
+  <title>refilc</title>
   <link rel="manifest" href="manifest.json">
 
   <script>
diff --git a/filcnaplo/web/manifest.json b/refilc/web/manifest.json
similarity index 93%
rename from filcnaplo/web/manifest.json
rename to refilc/web/manifest.json
index d43c553..3b15c41 100644
--- a/filcnaplo/web/manifest.json
+++ b/refilc/web/manifest.json
@@ -1,6 +1,6 @@
 {
-    "name": "filcnaplo",
-    "short_name": "filcnaplo",
+    "name": "refilc",
+    "short_name": "refilc",
     "start_url": ".",
     "display": "standalone",
     "background_color": "#0175C2",
diff --git a/filcnaplo/windows/runner/Runner.rc b/refilc/windows/runner/Runner.rc
similarity index 92%
rename from filcnaplo/windows/runner/Runner.rc
rename to refilc/windows/runner/Runner.rc
index 51b3032..9926483 100644
--- a/filcnaplo/windows/runner/Runner.rc
+++ b/refilc/windows/runner/Runner.rc
@@ -90,12 +90,12 @@ BEGIN
         BLOCK "040904e4"
         BEGIN
             VALUE "CompanyName", "hu.refilc" "\0"
-            VALUE "FileDescription", "filcnaplo" "\0"
+            VALUE "FileDescription", "refilc" "\0"
             VALUE "FileVersion", VERSION_AS_STRING "\0"
-            VALUE "InternalName", "filcnaplo" "\0"
+            VALUE "InternalName", "refilc" "\0"
             VALUE "LegalCopyright", "Copyright (C) 2023 hu.refilc. All rights reserved." "\0"
-            VALUE "OriginalFilename", "filcnaplo.exe" "\0"
-            VALUE "ProductName", "filcnaplo" "\0"
+            VALUE "OriginalFilename", "refilc.exe" "\0"
+            VALUE "ProductName", "refilc" "\0"
             VALUE "ProductVersion", VERSION_AS_STRING "\0"
         END
     END
diff --git a/filcnaplo/windows/runner/flutter_window.cpp b/refilc/windows/runner/flutter_window.cpp
similarity index 100%
rename from filcnaplo/windows/runner/flutter_window.cpp
rename to refilc/windows/runner/flutter_window.cpp
diff --git a/filcnaplo/windows/runner/flutter_window.h b/refilc/windows/runner/flutter_window.h
similarity index 100%
rename from filcnaplo/windows/runner/flutter_window.h
rename to refilc/windows/runner/flutter_window.h
diff --git a/filcnaplo/windows/runner/main.cpp b/refilc/windows/runner/main.cpp
similarity index 100%
rename from filcnaplo/windows/runner/main.cpp
rename to refilc/windows/runner/main.cpp
diff --git a/filcnaplo/windows/runner/resource.h b/refilc/windows/runner/resource.h
similarity index 100%
rename from filcnaplo/windows/runner/resource.h
rename to refilc/windows/runner/resource.h
diff --git a/filcnaplo/windows/runner/resources/app_icon.ico b/refilc/windows/runner/resources/app_icon.ico
similarity index 100%
rename from filcnaplo/windows/runner/resources/app_icon.ico
rename to refilc/windows/runner/resources/app_icon.ico
diff --git a/filcnaplo/windows/runner/runner.exe.manifest b/refilc/windows/runner/runner.exe.manifest
similarity index 100%
rename from filcnaplo/windows/runner/runner.exe.manifest
rename to refilc/windows/runner/runner.exe.manifest
diff --git a/filcnaplo/windows/runner/utils.cpp b/refilc/windows/runner/utils.cpp
similarity index 100%
rename from filcnaplo/windows/runner/utils.cpp
rename to refilc/windows/runner/utils.cpp
diff --git a/filcnaplo/windows/runner/utils.h b/refilc/windows/runner/utils.h
similarity index 100%
rename from filcnaplo/windows/runner/utils.h
rename to refilc/windows/runner/utils.h
diff --git a/filcnaplo/windows/runner/win32_window.cpp b/refilc/windows/runner/win32_window.cpp
similarity index 100%
rename from filcnaplo/windows/runner/win32_window.cpp
rename to refilc/windows/runner/win32_window.cpp
diff --git a/filcnaplo/windows/runner/win32_window.h b/refilc/windows/runner/win32_window.h
similarity index 100%
rename from filcnaplo/windows/runner/win32_window.h
rename to refilc/windows/runner/win32_window.h
diff --git a/filcnaplo_desktop_ui/LICENSE b/refilc_desktop_ui/LICENSE
similarity index 98%
rename from filcnaplo_desktop_ui/LICENSE
rename to refilc_desktop_ui/LICENSE
index 3877ae0..f288702 100644
--- a/filcnaplo_desktop_ui/LICENSE
+++ b/refilc_desktop_ui/LICENSE
@@ -1,674 +1,674 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<https://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<https://www.gnu.org/licenses/why-not-lgpl.html>.
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/filcnaplo_desktop_ui/README.md b/refilc_desktop_ui/README.md
similarity index 100%
rename from filcnaplo_desktop_ui/README.md
rename to refilc_desktop_ui/README.md
diff --git a/filcnaplo_desktop_ui/analysis_options.yaml b/refilc_desktop_ui/analysis_options.yaml
similarity index 98%
rename from filcnaplo_desktop_ui/analysis_options.yaml
rename to refilc_desktop_ui/analysis_options.yaml
index 16f5f56..fd16f92 100644
--- a/filcnaplo_desktop_ui/analysis_options.yaml
+++ b/refilc_desktop_ui/analysis_options.yaml
@@ -1,28 +1,28 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
-  # The lint rules applied to this project can be customized in the
-  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
-  # included above or to enable additional rules. A list of all available lints
-  # and their documentation is published at
-  # https://dart-lang.github.io/linter/lints/index.html.
-  #
-  # Instead of disabling a lint rule for the entire project in the
-  # section below, it can also be suppressed for a single line of code
-  # or a specific dart file by using the `// ignore: name_of_lint` and
-  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
-  # producing the lint.
-  rules:
-    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
-    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/filcnaplo_desktop_ui/lib/common/filter_bar.dart b/refilc_desktop_ui/lib/common/filter_bar.dart
similarity index 71%
rename from filcnaplo_desktop_ui/lib/common/filter_bar.dart
rename to refilc_desktop_ui/lib/common/filter_bar.dart
index 12dbf84..51efc63 100644
--- a/filcnaplo_desktop_ui/lib/common/filter_bar.dart
+++ b/refilc_desktop_ui/lib/common/filter_bar.dart
@@ -1,85 +1,92 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class FilterBar extends StatelessWidget implements PreferredSizeWidget {
-  const FilterBar({
-    Key? key,
-    required this.items,
-    required this.controller,
-    this.onTap,
-    this.padding = const EdgeInsets.symmetric(horizontal: 24.0),
-    this.disableFading = false,
-    this.scrollable = true,
-  })  : assert(items.length == controller.length),
-        super(key: key);
-
-  final List<Widget> items;
-  final TabController controller;
-  final EdgeInsetsGeometry padding;
-  final Function(int)? onTap;
-  @override
-  final Size preferredSize = const Size.fromHeight(42.0);
-  final bool disableFading;
-  final bool scrollable;
-
-  @override
-  Widget build(BuildContext context) {
-    final tabbar = TabBar(
-      controller: controller,
-      isScrollable: scrollable,
-      physics: const BouncingScrollPhysics(),
-      // Label
-      labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(
-            fontWeight: FontWeight.w600,
-            fontSize: 15.0,
-          ),
-      labelPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
-      labelColor: Theme.of(context).colorScheme.secondary,
-      unselectedLabelColor: AppColors.of(context).text.withOpacity(0.65),
-      // Indicator
-      indicatorPadding: const EdgeInsets.symmetric(vertical: 8),
-      indicator: BoxDecoration(
-        color: Theme.of(context).colorScheme.secondary.withOpacity(0.25),
-        borderRadius: BorderRadius.circular(45.0),
-      ),
-      overlayColor: MaterialStateProperty.all(const Color(0x00000000)),
-      // Tabs
-      padding: EdgeInsets.zero,
-      tabs: items,
-      onTap: onTap,
-    );
-
-    return Container(
-      width: MediaQuery.of(context).size.width,
-      height: 48.0,
-      padding: padding,
-      child: disableFading
-          ? tabbar
-          : AnimatedBuilder(
-              animation: controller.animation!,
-              builder: (ctx, child) {
-                // avoid fading over selected tab
-                return ShaderMask(
-                    shaderCallback: (Rect bounds) {
-                      final Color bg = Theme.of(context).scaffoldBackgroundColor;
-                      final double index = controller.animation!.value;
-                      return LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [
-                        index < 0.2 ? Colors.transparent : bg,
-                        Colors.transparent,
-                        Colors.transparent,
-                        index > controller.length - 1.2 ? Colors.transparent : bg
-                      ], stops: const [
-                        0,
-                        0.1,
-                        0.9,
-                        1
-                      ]).createShader(bounds);
-                    },
-                    blendMode: BlendMode.dstOut,
-                    child: child);
-              },
-              child: tabbar,
-            ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class FilterBar extends StatelessWidget implements PreferredSizeWidget {
+  const FilterBar({
+    Key? key,
+    required this.items,
+    required this.controller,
+    this.onTap,
+    this.padding = const EdgeInsets.symmetric(horizontal: 24.0),
+    this.disableFading = false,
+    this.scrollable = true,
+  })  : assert(items.length == controller.length),
+        super(key: key);
+
+  final List<Widget> items;
+  final TabController controller;
+  final EdgeInsetsGeometry padding;
+  final Function(int)? onTap;
+  @override
+  final Size preferredSize = const Size.fromHeight(42.0);
+  final bool disableFading;
+  final bool scrollable;
+
+  @override
+  Widget build(BuildContext context) {
+    final tabbar = TabBar(
+      controller: controller,
+      isScrollable: scrollable,
+      physics: const BouncingScrollPhysics(),
+      // Label
+      labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(
+            fontWeight: FontWeight.w600,
+            fontSize: 15.0,
+          ),
+      labelPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+      labelColor: Theme.of(context).colorScheme.secondary,
+      unselectedLabelColor: AppColors.of(context).text.withOpacity(0.65),
+      // Indicator
+      indicatorPadding: const EdgeInsets.symmetric(vertical: 8),
+      indicator: BoxDecoration(
+        color: Theme.of(context).colorScheme.secondary.withOpacity(0.25),
+        borderRadius: BorderRadius.circular(45.0),
+      ),
+      overlayColor: MaterialStateProperty.all(const Color(0x00000000)),
+      // Tabs
+      padding: EdgeInsets.zero,
+      tabs: items,
+      onTap: onTap,
+    );
+
+    return Container(
+      width: MediaQuery.of(context).size.width,
+      height: 48.0,
+      padding: padding,
+      child: disableFading
+          ? tabbar
+          : AnimatedBuilder(
+              animation: controller.animation!,
+              builder: (ctx, child) {
+                // avoid fading over selected tab
+                return ShaderMask(
+                    shaderCallback: (Rect bounds) {
+                      final Color bg =
+                          Theme.of(context).scaffoldBackgroundColor;
+                      final double index = controller.animation!.value;
+                      return LinearGradient(
+                          begin: Alignment.topLeft,
+                          end: Alignment.bottomRight,
+                          colors: [
+                            index < 0.2 ? Colors.transparent : bg,
+                            Colors.transparent,
+                            Colors.transparent,
+                            index > controller.length - 1.2
+                                ? Colors.transparent
+                                : bg
+                          ],
+                          stops: const [
+                            0,
+                            0.1,
+                            0.9,
+                            1
+                          ]).createShader(bounds);
+                    },
+                    blendMode: BlendMode.dstOut,
+                    child: child);
+              },
+              child: tabbar,
+            ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/common/panel_button.dart b/refilc_desktop_ui/lib/common/panel_button.dart
similarity index 77%
rename from filcnaplo_desktop_ui/lib/common/panel_button.dart
rename to refilc_desktop_ui/lib/common/panel_button.dart
index daa5ea6..93adf9b 100644
--- a/filcnaplo_desktop_ui/lib/common/panel_button.dart
+++ b/refilc_desktop_ui/lib/common/panel_button.dart
@@ -1,66 +1,72 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class PanelButton extends StatelessWidget {
-  const PanelButton({
-    Key? key,
-    this.onPressed,
-    this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
-    this.leading,
-    this.title,
-    this.trailing,
-    this.trailingDivider = false,
-  }) : super(key: key);
-
-  final void Function()? onPressed;
-  final EdgeInsetsGeometry padding;
-  final Widget? leading;
-  final Widget? title;
-  final Widget? trailing;
-  final bool trailingDivider;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(horizontal: 12.0),
-      child: RawMaterialButton(
-        onPressed: onPressed,
-        padding: padding,
-        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
-        child: ListTile(
-          leading: leading != null
-              ? Theme(
-                  data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Theme.of(context).colorScheme.secondary)),
-                  child: leading!,
-                )
-              : null,
-          trailing: trailingDivider
-              ? Row(
-                  mainAxisSize: MainAxisSize.min,
-                  children: [
-                    Container(
-                      margin: const EdgeInsets.only(right: 6.0),
-                      width: 2.0,
-                      height: 32.0,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.15),
-                        borderRadius: BorderRadius.circular(45.0),
-                      ),
-                    ),
-                    if (trailing != null) trailing!,
-                  ],
-                )
-              : trailing,
-          title: title != null
-              ? DefaultTextStyle(
-                  style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w600, fontSize: 14.0),
-                  child: title!,
-                )
-              : null,
-          contentPadding: EdgeInsets.zero,
-          visualDensity: VisualDensity.compact,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class PanelButton extends StatelessWidget {
+  const PanelButton({
+    Key? key,
+    this.onPressed,
+    this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
+    this.leading,
+    this.title,
+    this.trailing,
+    this.trailingDivider = false,
+  }) : super(key: key);
+
+  final void Function()? onPressed;
+  final EdgeInsetsGeometry padding;
+  final Widget? leading;
+  final Widget? title;
+  final Widget? trailing;
+  final bool trailingDivider;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 12.0),
+      child: RawMaterialButton(
+        onPressed: onPressed,
+        padding: padding,
+        shape:
+            RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
+        child: ListTile(
+          leading: leading != null
+              ? Theme(
+                  data: Theme.of(context).copyWith(
+                      iconTheme: IconThemeData(
+                          color: Theme.of(context).colorScheme.secondary)),
+                  child: leading!,
+                )
+              : null,
+          trailing: trailingDivider
+              ? Row(
+                  mainAxisSize: MainAxisSize.min,
+                  children: [
+                    Container(
+                      margin: const EdgeInsets.only(right: 6.0),
+                      width: 2.0,
+                      height: 32.0,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.15),
+                        borderRadius: BorderRadius.circular(45.0),
+                      ),
+                    ),
+                    if (trailing != null) trailing!,
+                  ],
+                )
+              : trailing,
+          title: title != null
+              ? DefaultTextStyle(
+                  style: Theme.of(context)
+                      .textTheme
+                      .titleMedium!
+                      .copyWith(fontWeight: FontWeight.w600, fontSize: 14.0),
+                  child: title!,
+                )
+              : null,
+          contentPadding: EdgeInsets.zero,
+          visualDensity: VisualDensity.compact,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/common/profile_image.dart b/refilc_desktop_ui/lib/common/profile_image.dart
similarity index 82%
rename from filcnaplo_desktop_ui/lib/common/profile_image.dart
rename to refilc_desktop_ui/lib/common/profile_image.dart
index 8fc1221..3dfb0db 100644
--- a/filcnaplo_desktop_ui/lib/common/profile_image.dart
+++ b/refilc_desktop_ui/lib/common/profile_image.dart
@@ -1,75 +1,78 @@
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-
-class ProfileImage extends StatelessWidget {
-  const ProfileImage({
-    Key? key,
-    this.name,
-    this.radius = 20.0,
-    this.role = Role.student,
-    this.backgroundColor,
-  }) : super(key: key);
-
-  final String? name;
-  final double radius;
-  final Role? role;
-  final Color? backgroundColor;
-
-  @override
-  Widget build(BuildContext context) {
-    Color color = ColorUtils.foregroundColor(backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
-    Color roleColor;
-
-    if (Theme.of(context).brightness == Brightness.light) {
-      roleColor = const Color(0xFF444444);
-    } else {
-      roleColor = const Color(0xFF555555);
-    }
-
-    return Stack(
-      alignment: Alignment.center,
-      children: [
-        Material(
-          clipBehavior: Clip.hardEdge,
-          shape: const CircleBorder(),
-          color: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
-          child: InkWell(
-            child: AnimatedContainer(
-              duration: const Duration(milliseconds: 200),
-              height: radius * 2,
-              width: radius * 2,
-              decoration: const BoxDecoration(
-                shape: BoxShape.circle,
-              ),
-              child: name != null && (name?.trim().length ?? 0) > 0
-                  ? Center(
-                      child: Text(
-                        (name?.trim().length ?? 0) > 0 ? (name ?? "?").trim()[0] : "?",
-                        style: TextStyle(
-                          color: color,
-                          fontWeight: FontWeight.w600,
-                          fontSize: 18.0 * (radius / 20.0),
-                        ),
-                      ),
-                    )
-                  : Container(),
-            ),
-          ),
-        ),
-
-        // Role indicator
-        if (role == Role.parent)
-          SizedBox(
-            height: radius * 2,
-            width: radius * 2,
-            child: Container(
-              alignment: Alignment.bottomRight,
-              child: Icon(Icons.shield, color: roleColor, size: radius / 1.3),
-            ),
-          ),
-      ],
-    );
-  }
-}
+import 'package:refilc/models/user.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/theme/colors/colors.dart';
+
+class ProfileImage extends StatelessWidget {
+  const ProfileImage({
+    Key? key,
+    this.name,
+    this.radius = 20.0,
+    this.role = Role.student,
+    this.backgroundColor,
+  }) : super(key: key);
+
+  final String? name;
+  final double radius;
+  final Role? role;
+  final Color? backgroundColor;
+
+  @override
+  Widget build(BuildContext context) {
+    Color color = ColorUtils.foregroundColor(
+        backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
+    Color roleColor;
+
+    if (Theme.of(context).brightness == Brightness.light) {
+      roleColor = const Color(0xFF444444);
+    } else {
+      roleColor = const Color(0xFF555555);
+    }
+
+    return Stack(
+      alignment: Alignment.center,
+      children: [
+        Material(
+          clipBehavior: Clip.hardEdge,
+          shape: const CircleBorder(),
+          color: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
+          child: InkWell(
+            child: AnimatedContainer(
+              duration: const Duration(milliseconds: 200),
+              height: radius * 2,
+              width: radius * 2,
+              decoration: const BoxDecoration(
+                shape: BoxShape.circle,
+              ),
+              child: name != null && (name?.trim().length ?? 0) > 0
+                  ? Center(
+                      child: Text(
+                        (name?.trim().length ?? 0) > 0
+                            ? (name ?? "?").trim()[0]
+                            : "?",
+                        style: TextStyle(
+                          color: color,
+                          fontWeight: FontWeight.w600,
+                          fontSize: 18.0 * (radius / 20.0),
+                        ),
+                      ),
+                    )
+                  : Container(),
+            ),
+          ),
+        ),
+
+        // Role indicator
+        if (role == Role.parent)
+          SizedBox(
+            height: radius * 2,
+            width: radius * 2,
+            child: Container(
+              alignment: Alignment.bottomRight,
+              child: Icon(Icons.shield, color: roleColor, size: radius / 1.3),
+            ),
+          ),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/common/widgets/grade/grade_viewable.dart b/refilc_desktop_ui/lib/common/widgets/grade/grade_viewable.dart
similarity index 66%
rename from filcnaplo_desktop_ui/lib/common/widgets/grade/grade_viewable.dart
rename to refilc_desktop_ui/lib/common/widgets/grade/grade_viewable.dart
index f3f1ffa..d8b71ac 100644
--- a/filcnaplo_desktop_ui/lib/common/widgets/grade/grade_viewable.dart
+++ b/refilc_desktop_ui/lib/common/widgets/grade/grade_viewable.dart
@@ -1,14 +1,14 @@
-import 'package:flutter/material.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-
-class GradeViewable extends StatelessWidget {
-  const GradeViewable(this.grade, {Key? key}) : super(key: key);
-
-  final Grade grade;
-
-  @override
-  Widget build(BuildContext context) {
-    return GradeTile(grade);
-  }
-}
\ No newline at end of file
+import 'package:flutter/material.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+
+class GradeViewable extends StatelessWidget {
+  const GradeViewable(this.grade, {Key? key}) : super(key: key);
+
+  final Grade grade;
+
+  @override
+  Widget build(BuildContext context) {
+    return GradeTile(grade);
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/common/widgets/lesson/lesson_viewable.dart b/refilc_desktop_ui/lib/common/widgets/lesson/lesson_viewable.dart
similarity index 70%
rename from filcnaplo_desktop_ui/lib/common/widgets/lesson/lesson_viewable.dart
rename to refilc_desktop_ui/lib/common/widgets/lesson/lesson_viewable.dart
index 3fe931b..18f9a14 100644
--- a/filcnaplo_desktop_ui/lib/common/widgets/lesson/lesson_viewable.dart
+++ b/refilc_desktop_ui/lib/common/widgets/lesson/lesson_viewable.dart
@@ -1,19 +1,20 @@
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo/ui/widgets/lesson/lesson_tile.dart';
-import 'package:flutter/material.dart';
-
-class LessonViewable extends StatelessWidget {
-  const LessonViewable(this.lesson, {Key? key, this.swapDesc = false}) : super(key: key);
-
-  final Lesson lesson;
-  final bool swapDesc;
-
-  @override
-  Widget build(BuildContext context) {
-    final tile = LessonTile(lesson, swapDesc: swapDesc);
-
-    if (lesson.subject.id == '' || tile.lesson.isEmpty) return tile;
-
-    return tile;
-  }
-}
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
+import 'package:flutter/material.dart';
+
+class LessonViewable extends StatelessWidget {
+  const LessonViewable(this.lesson, {Key? key, this.swapDesc = false})
+      : super(key: key);
+
+  final Lesson lesson;
+  final bool swapDesc;
+
+  @override
+  Widget build(BuildContext context) {
+    final tile = LessonTile(lesson, swapDesc: swapDesc);
+
+    if (lesson.subject.id == '' || tile.lesson.isEmpty) return tile;
+
+    return tile;
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/absences/absences_page.dart b/refilc_desktop_ui/lib/pages/absences/absences_page.dart
similarity index 88%
rename from filcnaplo_desktop_ui/lib/pages/absences/absences_page.dart
rename to refilc_desktop_ui/lib/pages/absences/absences_page.dart
index f9270b5..f18db5d 100644
--- a/filcnaplo_desktop_ui/lib/pages/absences/absences_page.dart
+++ b/refilc_desktop_ui/lib/pages/absences/absences_page.dart
@@ -1,405 +1,405 @@
-import 'dart:math';
-
-import 'package:animations/animations.dart';
-import 'package:auto_size_text/auto_size_text.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/action_button.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.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/absence/absence_subject_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/statistics_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/miss_tile.dart';
-import 'package:filcnaplo_mobile_ui/pages/absences/absence_subject_view.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'absences_page.i18n.dart';
-
-enum AbsenceFilter { absences, delays, misses }
-
-class SubjectAbsence {
-  Subject subject;
-  List<Absence> absences;
-  double percentage;
-
-  SubjectAbsence(
-      {required this.subject, this.absences = const [], this.percentage = 0.0});
-}
-
-class AbsencesPage extends StatefulWidget {
-  const AbsencesPage({Key? key}) : super(key: key);
-
-  @override
-  _AbsencesPageState createState() => _AbsencesPageState();
-}
-
-class _AbsencesPageState extends State<AbsencesPage>
-    with TickerProviderStateMixin {
-  late UserProvider user;
-  late AbsenceProvider absenceProvider;
-  late TimetableProvider timetableProvider;
-  late NoteProvider noteProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late TabController _tabController;
-  late List<SubjectAbsence> absences = [];
-  final Map<Subject, Lesson> _lessonCount = {};
-
-  @override
-  void initState() {
-    super.initState();
-
-    _tabController = TabController(length: 3, vsync: this);
-    timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
-
-    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
-      for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
-        if (!lesson.isEmpty &&
-            lesson.subject.id != '' &&
-            lesson.lessonYearIndex != null) {
-          _lessonCount.update(
-            lesson.subject,
-            (value) {
-              if (lesson.lessonYearIndex! > value.lessonYearIndex!) {
-                return lesson;
-              } else {
-                return value;
-              }
-            },
-            ifAbsent: () => lesson,
-          );
-        }
-      }
-    });
-  }
-
-  void buildSubjectAbsences() {
-    Map<Subject, SubjectAbsence> _absences = {};
-
-    for (final absence in absenceProvider.absences) {
-      if (absence.delay != 0) continue;
-
-      if (!_absences.containsKey(absence.subject)) {
-        _absences[absence.subject] =
-            SubjectAbsence(subject: absence.subject, absences: [absence]);
-      } else {
-        _absences[absence.subject]?.absences.add(absence);
-      }
-    }
-
-    _absences.forEach((subject, absence) {
-      final absentLessonsOfSubject = absenceProvider.absences
-          .where((e) => e.subject == subject && e.delay == 0)
-          .length;
-      final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
-
-      double absentLessonsOfSubjectPercentage;
-
-      if (absentLessonsOfSubject <= totalLessonsOfSubject) {
-        absentLessonsOfSubjectPercentage =
-            absentLessonsOfSubject / totalLessonsOfSubject * 100;
-      } else {
-        absentLessonsOfSubjectPercentage = -1;
-      }
-
-      _absences[subject]?.percentage =
-          absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
-    });
-
-    absences = _absences.values.toList();
-    absences.sort((a, b) => -a.percentage.compareTo(b.percentage));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    absenceProvider = Provider.of<AbsenceProvider>(context);
-    noteProvider = Provider.of<NoteProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-    timetableProvider = Provider.of<TimetableProvider>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    buildSubjectAbsences();
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 12.0),
-        child: NestedScrollView(
-          physics: const BouncingScrollPhysics(
-              parent: AlwaysScrollableScrollPhysics()),
-          headerSliverBuilder: (context, _) => [
-            SliverAppBar(
-              pinned: true,
-              floating: false,
-              snap: false,
-              centerTitle: false,
-              automaticallyImplyLeading: false,
-              shadowColor: Theme.of(context).shadowColor,
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-              title: Padding(
-                padding: const EdgeInsets.only(left: 8.0),
-                child: Text(
-                  "Absences".i18n,
-                  style: TextStyle(
-                      color: AppColors.of(context).text,
-                      fontSize: 32.0,
-                      fontWeight: FontWeight.bold),
-                ),
-              ),
-              bottom: FilterBar(items: [
-                Tab(text: "Absences".i18n),
-                Tab(text: "Delays".i18n),
-                Tab(text: "Misses".i18n),
-              ], controller: _tabController, disableFading: true),
-            ),
-          ],
-          body: TabBarView(
-              physics: const BouncingScrollPhysics(),
-              controller: _tabController,
-              children: List.generate(
-                  3, (index) => filterViewBuilder(context, index))),
-        ),
-      ),
-    );
-  }
-
-  List<DateWidget> getFilterWidgets(AbsenceFilter activeData) {
-    List<DateWidget> items = [];
-    switch (activeData) {
-      case AbsenceFilter.absences:
-        for (var a in absences) {
-          items.add(DateWidget(
-            date: DateTime.fromMillisecondsSinceEpoch(0),
-            widget: AbsenceSubjectTile(
-              a.subject,
-              percentage: a.percentage,
-              excused: a.absences
-                  .where((a) => a.state == Justification.excused)
-                  .length,
-              unexcused: a.absences
-                  .where((a) => a.state == Justification.unexcused)
-                  .length,
-              pending: a.absences
-                  .where((a) => a.state == Justification.pending)
-                  .length,
-              onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
-                  context: context),
-            ),
-          ));
-        }
-        break;
-      case AbsenceFilter.delays:
-        for (var absence in absenceProvider.absences) {
-          if (absence.delay != 0) {
-            items.add(DateWidget(
-                date: absence.date,
-                widget: AbsenceViewable(
-                  absence,
-                  padding: EdgeInsets.zero,
-                )));
-          }
-        }
-        break;
-      case AbsenceFilter.misses:
-        for (var note in noteProvider.notes) {
-          if (note.type?.name == "HaziFeladatHiany" ||
-              note.type?.name == "Felszereleshiany") {
-            items.add(DateWidget(
-              date: note.date,
-              widget: MissTile(note),
-            ));
-          }
-        }
-        break;
-    }
-    return items;
-  }
-
-  Widget filterViewBuilder(context, int activeData) {
-    List<Widget> filterWidgets = [];
-
-    if (activeData > 0) {
-      filterWidgets = sortDateWidgets(
-        context,
-        dateWidgets: getFilterWidgets(AbsenceFilter.values[activeData]),
-        padding: EdgeInsets.zero,
-        hasShadow: true,
-      );
-    } else {
-      filterWidgets = [
-        Padding(
-          padding: const EdgeInsets.only(bottom: 24.0),
-          child: Panel(
-            title: Row(
-              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-              children: [
-                Text("Subjects".i18n),
-                Padding(
-                  padding: const EdgeInsets.only(right: 4.0),
-                  child: IconButton(
-                    onPressed: () {
-                      showDialog(
-                        context: context,
-                        builder: (context) => AlertDialog(
-                          shape: RoundedRectangleBorder(
-                              borderRadius: BorderRadius.circular(12.0)),
-                          title: Text("attention".i18n),
-                          content: Text("attention_body".i18n),
-                          actions: [
-                            ActionButton(
-                                label: "Ok",
-                                onTap: () => Navigator.of(context).pop())
-                          ],
-                        ),
-                      );
-                    },
-                    padding: EdgeInsets.zero,
-                    splashRadius: 24.0,
-                    visualDensity: VisualDensity.compact,
-                    constraints: BoxConstraints.tight(const Size(42.0, 42.0)),
-                    icon: const Icon(FeatherIcons.info),
-                  ),
-                ),
-              ],
-            ),
-            child: PageTransitionSwitcher(
-              transitionBuilder: (
-                Widget child,
-                Animation<double> primaryAnimation,
-                Animation<double> secondaryAnimation,
-              ) {
-                return FadeThroughTransition(
-                  child: child,
-                  animation: primaryAnimation,
-                  secondaryAnimation: secondaryAnimation,
-                  fillColor: Theme.of(context).colorScheme.background,
-                );
-              },
-              child: Column(
-                children: getFilterWidgets(AbsenceFilter.values[activeData])
-                    .map((e) => e.widget)
-                    .cast<Widget>()
-                    .toList(),
-              ),
-            ),
-          ),
-        )
-      ];
-    }
-
-    return Padding(
-      padding: const EdgeInsets.only(top: 12.0),
-      child: RefreshIndicator(
-        color: Theme.of(context).colorScheme.secondary,
-        onRefresh: () async {
-          await absenceProvider.fetch();
-          await noteProvider.fetch();
-        },
-        child: ListView.builder(
-          padding: EdgeInsets.zero,
-          physics: const BouncingScrollPhysics(),
-          itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
-          itemBuilder: (context, index) {
-            if (filterWidgets.isNotEmpty) {
-              if ((index == 0 && activeData == 1) ||
-                  (index == 0 && activeData == 0)) {
-                int value1 = 0;
-                int value2 = 0;
-                String title1 = "";
-                String title2 = "";
-                String suffix = "";
-
-                if (activeData == AbsenceFilter.absences.index) {
-                  value1 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay == 0 && e.state == Justification.excused)
-                      .length;
-                  value2 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay == 0 && e.state == Justification.unexcused)
-                      .length;
-                  title1 = "stat_1".i18n;
-                  title2 = "stat_2".i18n;
-                  suffix = " " + "hr".i18n;
-                } else if (activeData == AbsenceFilter.delays.index) {
-                  value1 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay != 0 && e.state == Justification.excused)
-                      .map((e) => e.delay)
-                      .fold(0, (a, b) => a + b);
-                  value2 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay != 0 && e.state == Justification.unexcused)
-                      .map((e) => e.delay)
-                      .fold(0, (a, b) => a + b);
-                  title1 = "stat_3".i18n;
-                  title2 = "stat_4".i18n;
-                  suffix = " " + "min".i18n;
-                }
-
-                return Padding(
-                  padding: const EdgeInsets.only(
-                      bottom: 24.0, left: 24.0, right: 24.0),
-                  child: Row(children: [
-                    Expanded(
-                      child: StatisticsTile(
-                        title: AutoSizeText(
-                          title1,
-                          textAlign: TextAlign.center,
-                          maxLines: 2,
-                          overflow: TextOverflow.ellipsis,
-                        ),
-                        valueSuffix: suffix,
-                        value: value1.toDouble(),
-                        decimal: false,
-                        color: AppColors.of(context).green,
-                      ),
-                    ),
-                    const SizedBox(width: 24.0),
-                    Expanded(
-                      child: StatisticsTile(
-                        title: AutoSizeText(
-                          title2,
-                          textAlign: TextAlign.center,
-                          maxLines: 2,
-                          overflow: TextOverflow.ellipsis,
-                        ),
-                        valueSuffix: suffix,
-                        value: value2.toDouble(),
-                        decimal: false,
-                        color: AppColors.of(context).red,
-                      ),
-                    ),
-                  ]),
-                );
-              }
-
-              return Padding(
-                padding:
-                    const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
-                child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
-              );
-            } else {
-              return Empty(subtitle: "empty".i18n);
-            }
-          },
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:animations/animations.dart';
+import 'package:auto_size_text/auto_size_text.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/action_button.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_subject_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/statistics_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/miss_tile.dart';
+import 'package:refilc_mobile_ui/pages/absences/absence_subject_view.dart';
+import 'package:refilc/ui/filter/sort.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'absences_page.i18n.dart';
+
+enum AbsenceFilter { absences, delays, misses }
+
+class SubjectAbsence {
+  Subject subject;
+  List<Absence> absences;
+  double percentage;
+
+  SubjectAbsence(
+      {required this.subject, this.absences = const [], this.percentage = 0.0});
+}
+
+class AbsencesPage extends StatefulWidget {
+  const AbsencesPage({Key? key}) : super(key: key);
+
+  @override
+  _AbsencesPageState createState() => _AbsencesPageState();
+}
+
+class _AbsencesPageState extends State<AbsencesPage>
+    with TickerProviderStateMixin {
+  late UserProvider user;
+  late AbsenceProvider absenceProvider;
+  late TimetableProvider timetableProvider;
+  late NoteProvider noteProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late TabController _tabController;
+  late List<SubjectAbsence> absences = [];
+  final Map<Subject, Lesson> _lessonCount = {};
+
+  @override
+  void initState() {
+    super.initState();
+
+    _tabController = TabController(length: 3, vsync: this);
+    timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
+
+    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
+      for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
+        if (!lesson.isEmpty &&
+            lesson.subject.id != '' &&
+            lesson.lessonYearIndex != null) {
+          _lessonCount.update(
+            lesson.subject,
+            (value) {
+              if (lesson.lessonYearIndex! > value.lessonYearIndex!) {
+                return lesson;
+              } else {
+                return value;
+              }
+            },
+            ifAbsent: () => lesson,
+          );
+        }
+      }
+    });
+  }
+
+  void buildSubjectAbsences() {
+    Map<Subject, SubjectAbsence> _absences = {};
+
+    for (final absence in absenceProvider.absences) {
+      if (absence.delay != 0) continue;
+
+      if (!_absences.containsKey(absence.subject)) {
+        _absences[absence.subject] =
+            SubjectAbsence(subject: absence.subject, absences: [absence]);
+      } else {
+        _absences[absence.subject]?.absences.add(absence);
+      }
+    }
+
+    _absences.forEach((subject, absence) {
+      final absentLessonsOfSubject = absenceProvider.absences
+          .where((e) => e.subject == subject && e.delay == 0)
+          .length;
+      final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
+
+      double absentLessonsOfSubjectPercentage;
+
+      if (absentLessonsOfSubject <= totalLessonsOfSubject) {
+        absentLessonsOfSubjectPercentage =
+            absentLessonsOfSubject / totalLessonsOfSubject * 100;
+      } else {
+        absentLessonsOfSubjectPercentage = -1;
+      }
+
+      _absences[subject]?.percentage =
+          absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
+    });
+
+    absences = _absences.values.toList();
+    absences.sort((a, b) => -a.percentage.compareTo(b.percentage));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    absenceProvider = Provider.of<AbsenceProvider>(context);
+    noteProvider = Provider.of<NoteProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+    timetableProvider = Provider.of<TimetableProvider>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    buildSubjectAbsences();
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 12.0),
+        child: NestedScrollView(
+          physics: const BouncingScrollPhysics(
+              parent: AlwaysScrollableScrollPhysics()),
+          headerSliverBuilder: (context, _) => [
+            SliverAppBar(
+              pinned: true,
+              floating: false,
+              snap: false,
+              centerTitle: false,
+              automaticallyImplyLeading: false,
+              shadowColor: Theme.of(context).shadowColor,
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+              title: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  "Absences".i18n,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontSize: 32.0,
+                      fontWeight: FontWeight.bold),
+                ),
+              ),
+              bottom: FilterBar(items: [
+                Tab(text: "Absences".i18n),
+                Tab(text: "Delays".i18n),
+                Tab(text: "Misses".i18n),
+              ], controller: _tabController, disableFading: true),
+            ),
+          ],
+          body: TabBarView(
+              physics: const BouncingScrollPhysics(),
+              controller: _tabController,
+              children: List.generate(
+                  3, (index) => filterViewBuilder(context, index))),
+        ),
+      ),
+    );
+  }
+
+  List<DateWidget> getFilterWidgets(AbsenceFilter activeData) {
+    List<DateWidget> items = [];
+    switch (activeData) {
+      case AbsenceFilter.absences:
+        for (var a in absences) {
+          items.add(DateWidget(
+            date: DateTime.fromMillisecondsSinceEpoch(0),
+            widget: AbsenceSubjectTile(
+              a.subject,
+              percentage: a.percentage,
+              excused: a.absences
+                  .where((a) => a.state == Justification.excused)
+                  .length,
+              unexcused: a.absences
+                  .where((a) => a.state == Justification.unexcused)
+                  .length,
+              pending: a.absences
+                  .where((a) => a.state == Justification.pending)
+                  .length,
+              onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
+                  context: context),
+            ),
+          ));
+        }
+        break;
+      case AbsenceFilter.delays:
+        for (var absence in absenceProvider.absences) {
+          if (absence.delay != 0) {
+            items.add(DateWidget(
+                date: absence.date,
+                widget: AbsenceViewable(
+                  absence,
+                  padding: EdgeInsets.zero,
+                )));
+          }
+        }
+        break;
+      case AbsenceFilter.misses:
+        for (var note in noteProvider.notes) {
+          if (note.type?.name == "HaziFeladatHiany" ||
+              note.type?.name == "Felszereleshiany") {
+            items.add(DateWidget(
+              date: note.date,
+              widget: MissTile(note),
+            ));
+          }
+        }
+        break;
+    }
+    return items;
+  }
+
+  Widget filterViewBuilder(context, int activeData) {
+    List<Widget> filterWidgets = [];
+
+    if (activeData > 0) {
+      filterWidgets = sortDateWidgets(
+        context,
+        dateWidgets: getFilterWidgets(AbsenceFilter.values[activeData]),
+        padding: EdgeInsets.zero,
+        hasShadow: true,
+      );
+    } else {
+      filterWidgets = [
+        Padding(
+          padding: const EdgeInsets.only(bottom: 24.0),
+          child: Panel(
+            title: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Text("Subjects".i18n),
+                Padding(
+                  padding: const EdgeInsets.only(right: 4.0),
+                  child: IconButton(
+                    onPressed: () {
+                      showDialog(
+                        context: context,
+                        builder: (context) => AlertDialog(
+                          shape: RoundedRectangleBorder(
+                              borderRadius: BorderRadius.circular(12.0)),
+                          title: Text("attention".i18n),
+                          content: Text("attention_body".i18n),
+                          actions: [
+                            ActionButton(
+                                label: "Ok",
+                                onTap: () => Navigator.of(context).pop())
+                          ],
+                        ),
+                      );
+                    },
+                    padding: EdgeInsets.zero,
+                    splashRadius: 24.0,
+                    visualDensity: VisualDensity.compact,
+                    constraints: BoxConstraints.tight(const Size(42.0, 42.0)),
+                    icon: const Icon(FeatherIcons.info),
+                  ),
+                ),
+              ],
+            ),
+            child: PageTransitionSwitcher(
+              transitionBuilder: (
+                Widget child,
+                Animation<double> primaryAnimation,
+                Animation<double> secondaryAnimation,
+              ) {
+                return FadeThroughTransition(
+                  child: child,
+                  animation: primaryAnimation,
+                  secondaryAnimation: secondaryAnimation,
+                  fillColor: Theme.of(context).colorScheme.background,
+                );
+              },
+              child: Column(
+                children: getFilterWidgets(AbsenceFilter.values[activeData])
+                    .map((e) => e.widget)
+                    .cast<Widget>()
+                    .toList(),
+              ),
+            ),
+          ),
+        )
+      ];
+    }
+
+    return Padding(
+      padding: const EdgeInsets.only(top: 12.0),
+      child: RefreshIndicator(
+        color: Theme.of(context).colorScheme.secondary,
+        onRefresh: () async {
+          await absenceProvider.fetch();
+          await noteProvider.fetch();
+        },
+        child: ListView.builder(
+          padding: EdgeInsets.zero,
+          physics: const BouncingScrollPhysics(),
+          itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
+          itemBuilder: (context, index) {
+            if (filterWidgets.isNotEmpty) {
+              if ((index == 0 && activeData == 1) ||
+                  (index == 0 && activeData == 0)) {
+                int value1 = 0;
+                int value2 = 0;
+                String title1 = "";
+                String title2 = "";
+                String suffix = "";
+
+                if (activeData == AbsenceFilter.absences.index) {
+                  value1 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay == 0 && e.state == Justification.excused)
+                      .length;
+                  value2 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay == 0 && e.state == Justification.unexcused)
+                      .length;
+                  title1 = "stat_1".i18n;
+                  title2 = "stat_2".i18n;
+                  suffix = " " + "hr".i18n;
+                } else if (activeData == AbsenceFilter.delays.index) {
+                  value1 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay != 0 && e.state == Justification.excused)
+                      .map((e) => e.delay)
+                      .fold(0, (a, b) => a + b);
+                  value2 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay != 0 && e.state == Justification.unexcused)
+                      .map((e) => e.delay)
+                      .fold(0, (a, b) => a + b);
+                  title1 = "stat_3".i18n;
+                  title2 = "stat_4".i18n;
+                  suffix = " " + "min".i18n;
+                }
+
+                return Padding(
+                  padding: const EdgeInsets.only(
+                      bottom: 24.0, left: 24.0, right: 24.0),
+                  child: Row(children: [
+                    Expanded(
+                      child: StatisticsTile(
+                        title: AutoSizeText(
+                          title1,
+                          textAlign: TextAlign.center,
+                          maxLines: 2,
+                          overflow: TextOverflow.ellipsis,
+                        ),
+                        valueSuffix: suffix,
+                        value: value1.toDouble(),
+                        decimal: false,
+                        color: AppColors.of(context).green,
+                      ),
+                    ),
+                    const SizedBox(width: 24.0),
+                    Expanded(
+                      child: StatisticsTile(
+                        title: AutoSizeText(
+                          title2,
+                          textAlign: TextAlign.center,
+                          maxLines: 2,
+                          overflow: TextOverflow.ellipsis,
+                        ),
+                        valueSuffix: suffix,
+                        value: value2.toDouble(),
+                        decimal: false,
+                        color: AppColors.of(context).red,
+                      ),
+                    ),
+                  ]),
+                );
+              }
+
+              return Padding(
+                padding:
+                    const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
+                child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
+              );
+            } else {
+              return Empty(subtitle: "empty".i18n);
+            }
+          },
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/absences/absences_page.i18n.dart b/refilc_desktop_ui/lib/pages/absences/absences_page.i18n.dart
similarity index 97%
rename from filcnaplo_desktop_ui/lib/pages/absences/absences_page.i18n.dart
rename to refilc_desktop_ui/lib/pages/absences/absences_page.i18n.dart
index 91b7621..2b37c00 100644
--- a/filcnaplo_desktop_ui/lib/pages/absences/absences_page.i18n.dart
+++ b/refilc_desktop_ui/lib/pages/absences/absences_page.i18n.dart
@@ -1,57 +1,57 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension ScreensLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Absences": "Absences",
-          "Delays": "Delays",
-          "Misses": "Misses",
-          "empty": "You have no absences.",
-          "stat_1": "Excused Absences",
-          "stat_2": "Unexcused Absences",
-          "stat_3": "Excused Delay",
-          "stat_4": "Unexcused Delay",
-          "min": "min",
-          "hr": "hrs",
-          "Subjects": "Subjects",
-          "attention": "Attention!",
-          "attention_body": "Percentage calculations are only an approximation so they may not be accurate.",
-        },
-        "hu_hu": {
-          "Absences": "Hiányzások",
-          "Delays": "Késések",
-          "Misses": "Hiányok",
-          "empty": "Nincsenek hiányaid.",
-          "stat_1": "Igazolt hiányzások",
-          "stat_2": "Igazolatlan hiányzások",
-          "stat_3": "Igazolt Késés",
-          "stat_4": "Igazolatlan Késés",
-          "min": "perc",
-          "hr": "óra",
-          "Subjects": "Tantárgyak",
-          "attention": "Figyelem!",
-          "attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.",
-        },
-        "de_de": {
-          "Absences": "Fehlen",
-          "Delays": "Verspätung",
-          "Misses": "Fehlt",
-          "empty": "Sie haben keine Fehlen.",
-          "stat_1": "Entschuldigte Fehlen",
-          "stat_2": "Unentschuldigte Fehlen",
-          "stat_3": "Entschuldigte Verspätung",
-          "stat_4": "Unentschuldigte Verspätung",
-          "min": "min",
-          "hr": "hrs",
-          "Subjects": "Fächer",
-          "attention": "Achtung!",
-          "attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension ScreensLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Absences": "Absences",
+          "Delays": "Delays",
+          "Misses": "Misses",
+          "empty": "You have no absences.",
+          "stat_1": "Excused Absences",
+          "stat_2": "Unexcused Absences",
+          "stat_3": "Excused Delay",
+          "stat_4": "Unexcused Delay",
+          "min": "min",
+          "hr": "hrs",
+          "Subjects": "Subjects",
+          "attention": "Attention!",
+          "attention_body": "Percentage calculations are only an approximation so they may not be accurate.",
+        },
+        "hu_hu": {
+          "Absences": "Hiányzások",
+          "Delays": "Késések",
+          "Misses": "Hiányok",
+          "empty": "Nincsenek hiányaid.",
+          "stat_1": "Igazolt hiányzások",
+          "stat_2": "Igazolatlan hiányzások",
+          "stat_3": "Igazolt Késés",
+          "stat_4": "Igazolatlan Késés",
+          "min": "perc",
+          "hr": "óra",
+          "Subjects": "Tantárgyak",
+          "attention": "Figyelem!",
+          "attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.",
+        },
+        "de_de": {
+          "Absences": "Fehlen",
+          "Delays": "Verspätung",
+          "Misses": "Fehlt",
+          "empty": "Sie haben keine Fehlen.",
+          "stat_1": "Entschuldigte Fehlen",
+          "stat_2": "Unentschuldigte Fehlen",
+          "stat_3": "Entschuldigte Verspätung",
+          "stat_4": "Unentschuldigte Verspätung",
+          "min": "min",
+          "hr": "hrs",
+          "Subjects": "Fächer",
+          "attention": "Achtung!",
+          "attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/grades/grade_subject_view.dart b/refilc_desktop_ui/lib/pages/grades/grade_subject_view.dart
similarity index 84%
rename from filcnaplo_desktop_ui/lib/pages/grades/grade_subject_view.dart
rename to refilc_desktop_ui/lib/pages/grades/grade_subject_view.dart
index 95571f1..be978ef 100644
--- a/filcnaplo_desktop_ui/lib/pages/grades/grade_subject_view.dart
+++ b/refilc_desktop_ui/lib/pages/grades/grade_subject_view.dart
@@ -1,291 +1,291 @@
-import 'dart:math';
-
-import 'package:animations/animations.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/trend_display.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_tile.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/hero_scrollview.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
-import 'package:filcnaplo_desktop_ui/pages/grades/grades_count.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'grades_page.i18n.dart';
-//import 'package:filcnaplo_premium/ui/mobile/goal_planner/new_goal.dart';
-
-class GradeSubjectView extends StatefulWidget {
-  const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
-      : super(key: key);
-
-  final Subject subject;
-  final double groupAverage;
-
-  void push(BuildContext context, {bool root = false}) {
-    Navigator.of(context, rootNavigator: root)
-        .push(CupertinoPageRoute(builder: (context) => this));
-  }
-
-  @override
-  State<GradeSubjectView> createState() => _GradeSubjectViewState();
-}
-
-class _GradeSubjectViewState extends State<GradeSubjectView> {
-  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
-
-  // Controllers
-  PersistentBottomSheetController? _sheetController;
-  final ScrollController _scrollController = ScrollController();
-
-  List<Widget> gradeTiles = [];
-
-  // Providers
-  late GradeProvider gradeProvider;
-  late GradeCalculatorProvider calculatorProvider;
-
-  late double average;
-  late Widget gradeGraph;
-
-  bool gradeCalcMode = false;
-
-  List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
-      ? gradeProvider.grades.where((e) => e.subject == subject).toList()
-      : calculatorProvider.grades.where((e) => e.subject == subject).toList();
-
-  bool showGraph(List<Grade> subjectGrades) {
-    if (gradeCalcMode) return true;
-
-    final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
-    final maxGradeDate = gradeDates.fold(0, max);
-    final minGradeDate = gradeDates.fold(0, min);
-    if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
-      return false; // naplo/#78
-    }
-
-    return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
-  }
-
-  void buildTiles(List<Grade> subjectGrades) {
-    List<Widget> tiles = [];
-
-    if (showGraph(subjectGrades)) {
-      tiles.add(gradeGraph);
-    } else {
-      tiles.add(Container(height: 24.0));
-    }
-
-    List<Widget> _gradeTiles = [];
-
-    if (!gradeCalcMode) {
-      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
-      for (var grade in subjectGrades) {
-        if (grade.type == GradeType.midYear) {
-          _gradeTiles.add(GradeViewable(grade));
-        } else {
-          _gradeTiles.add(CertificationTile(grade, padding: EdgeInsets.zero));
-        }
-      }
-    } else if (subjectGrades.isNotEmpty) {
-      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
-      for (var grade in subjectGrades) {
-        _gradeTiles.add(GradeTile(grade));
-      }
-    }
-    tiles.add(
-      PageTransitionSwitcher(
-        transitionBuilder: (
-          Widget child,
-          Animation<double> primaryAnimation,
-          Animation<double> secondaryAnimation,
-        ) {
-          return SharedAxisTransition(
-            animation: primaryAnimation,
-            secondaryAnimation: secondaryAnimation,
-            transitionType: SharedAxisTransitionType.vertical,
-            child: child,
-            fillColor: Colors.transparent,
-          );
-        },
-        child: _gradeTiles.isNotEmpty
-            ? Panel(
-                key: ValueKey(gradeCalcMode),
-                title: Text(
-                  gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
-                ),
-                child: Column(
-                  children: _gradeTiles,
-                ))
-            : const SizedBox(),
-      ),
-    );
-
-    tiles.add(Padding(
-        padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
-    gradeTiles = List.castFrom(tiles);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    gradeProvider = Provider.of<GradeProvider>(context);
-    calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
-
-    List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
-    average = AverageHelper.averageEvals(subjectGrades);
-    final prevAvg = subjectGrades.isNotEmpty
-        ? AverageHelper.averageEvals(subjectGrades
-            .where((e) => e.date.isBefore(subjectGrades
-                .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
-                .date
-                .subtract(const Duration(days: 30))))
-            .toList())
-        : 0.0;
-
-    gradeGraph = Padding(
-      padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
-      child: Panel(
-        title: Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: [
-            Text("annual_average".i18n),
-            if (average != prevAvg)
-              TrendDisplay(current: average, previous: prevAvg),
-          ],
-        ),
-        child: Container(
-          padding: const EdgeInsets.only(top: 12.0, right: 12.0),
-          child: Row(
-            children: [
-              Expanded(
-                  child: GradeGraph(subjectGrades,
-                      dayThreshold: 5, classAvg: widget.groupAverage)),
-              Padding(
-                padding: const EdgeInsets.only(bottom: 24.0),
-                child: GradesCount(grades: subjectGrades),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-
-    if (!gradeCalcMode) {
-      buildTiles(subjectGrades);
-    } else {
-      List<Grade> ghostGrades = calculatorProvider.ghosts
-          .where((e) => e.subject == widget.subject)
-          .toList();
-      buildTiles(ghostGrades);
-    }
-
-    return Scaffold(
-        key: _scaffoldKey,
-        floatingActionButtonLocation: ExpandableFab.location,
-        floatingActionButton: Visibility(
-          visible: !gradeCalcMode &&
-              subjectGrades
-                  .where((e) => e.type == GradeType.midYear)
-                  .isNotEmpty,
-          child: ExpandableFab(
-            type: ExpandableFabType.up,
-            distance: 50,
-            children: [
-              FloatingActionButton.small(
-                child: const Icon(FeatherIcons.plus),
-                onPressed: () {
-                  gradeCalc(context);
-                },
-              ),
-              // FloatingActionButton.small(
-              //   child: const Icon(FeatherIcons.flag, size: 20.0),
-              //   onPressed: () {
-              //     Navigator.of(context).push(CupertinoPageRoute(builder: (context) => PremiumGoalplannerNewGoalScreen(subject: widget.subject)));
-              //   },
-              // ),
-            ],
-          ),
-        ),
-        body: RefreshIndicator(
-          onRefresh: () async {},
-          color: Theme.of(context).colorScheme.secondary,
-          child: HeroScrollView(
-              onClose: () {
-                if (_sheetController != null && gradeCalcMode) {
-                  _sheetController!.close();
-                } else {
-                  Navigator.of(context).pop();
-                }
-              },
-              navBarItems: [
-                const SizedBox(width: 6.0),
-                if (widget.groupAverage != 0)
-                  Center(
-                      child: AverageDisplay(
-                          average: widget.groupAverage, border: true)),
-                const SizedBox(width: 6.0),
-                if (average != 0)
-                  Center(child: AverageDisplay(average: average)),
-                const SizedBox(width: 12.0),
-              ],
-              icon: SubjectIcon.resolveVariant(
-                  subject: widget.subject, context: context),
-              scrollController: _scrollController,
-              title: widget.subject.renamedTo ?? widget.subject.name.capital(),
-              italic: widget.subject.isRenamed,
-              child: SubjectGradesContainer(
-                child: CupertinoScrollbar(
-                  child: ListView.builder(
-                    physics: const BouncingScrollPhysics(),
-                    padding: const EdgeInsets.symmetric(horizontal: 24.0),
-                    shrinkWrap: true,
-                    itemBuilder: (context, index) => gradeTiles[index],
-                    itemCount: gradeTiles.length,
-                  ),
-                ),
-              )),
-        ));
-  }
-
-  void gradeCalc(BuildContext context) {
-    // Scroll to the top of the page
-    _scrollController.animateTo(75,
-        duration: const Duration(milliseconds: 500), curve: Curves.ease);
-
-    calculatorProvider.clear();
-    calculatorProvider.addAllGrades(gradeProvider.grades);
-
-    _sheetController = _scaffoldKey.currentState?.showBottomSheet(
-      (context) => RoundedBottomSheet(
-          child: GradeCalculator(widget.subject), borderRadius: 14.0),
-      backgroundColor: const Color(0x00000000),
-      elevation: 12.0,
-    );
-
-    // Hide the fab and grades
-    setState(() {
-      gradeCalcMode = true;
-    });
-
-    _sheetController!.closed.then((value) {
-      // Show fab and grades
-      if (mounted) {
-        setState(() {
-          gradeCalcMode = false;
-        });
-      }
-    });
-  }
-}
+import 'dart:math';
+
+import 'package:animations/animations.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/trend_display.dart';
+import 'package:refilc_mobile_ui/common/widgets/cretification/certification_tile.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart';
+import 'package:refilc_mobile_ui/common/hero_scrollview.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
+import 'package:refilc_desktop_ui/pages/grades/grades_count.dart';
+import 'package:refilc_mobile_ui/pages/grades/graph.dart';
+import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'grades_page.i18n.dart';
+//import 'package:refilc_premium/ui/mobile/goal_planner/new_goal.dart';
+
+class GradeSubjectView extends StatefulWidget {
+  const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
+      : super(key: key);
+
+  final Subject subject;
+  final double groupAverage;
+
+  void push(BuildContext context, {bool root = false}) {
+    Navigator.of(context, rootNavigator: root)
+        .push(CupertinoPageRoute(builder: (context) => this));
+  }
+
+  @override
+  State<GradeSubjectView> createState() => _GradeSubjectViewState();
+}
+
+class _GradeSubjectViewState extends State<GradeSubjectView> {
+  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+
+  // Controllers
+  PersistentBottomSheetController? _sheetController;
+  final ScrollController _scrollController = ScrollController();
+
+  List<Widget> gradeTiles = [];
+
+  // Providers
+  late GradeProvider gradeProvider;
+  late GradeCalculatorProvider calculatorProvider;
+
+  late double average;
+  late Widget gradeGraph;
+
+  bool gradeCalcMode = false;
+
+  List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
+      ? gradeProvider.grades.where((e) => e.subject == subject).toList()
+      : calculatorProvider.grades.where((e) => e.subject == subject).toList();
+
+  bool showGraph(List<Grade> subjectGrades) {
+    if (gradeCalcMode) return true;
+
+    final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
+    final maxGradeDate = gradeDates.fold(0, max);
+    final minGradeDate = gradeDates.fold(0, min);
+    if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
+      return false; // naplo/#78
+    }
+
+    return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
+  }
+
+  void buildTiles(List<Grade> subjectGrades) {
+    List<Widget> tiles = [];
+
+    if (showGraph(subjectGrades)) {
+      tiles.add(gradeGraph);
+    } else {
+      tiles.add(Container(height: 24.0));
+    }
+
+    List<Widget> _gradeTiles = [];
+
+    if (!gradeCalcMode) {
+      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
+      for (var grade in subjectGrades) {
+        if (grade.type == GradeType.midYear) {
+          _gradeTiles.add(GradeViewable(grade));
+        } else {
+          _gradeTiles.add(CertificationTile(grade, padding: EdgeInsets.zero));
+        }
+      }
+    } else if (subjectGrades.isNotEmpty) {
+      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
+      for (var grade in subjectGrades) {
+        _gradeTiles.add(GradeTile(grade));
+      }
+    }
+    tiles.add(
+      PageTransitionSwitcher(
+        transitionBuilder: (
+          Widget child,
+          Animation<double> primaryAnimation,
+          Animation<double> secondaryAnimation,
+        ) {
+          return SharedAxisTransition(
+            animation: primaryAnimation,
+            secondaryAnimation: secondaryAnimation,
+            transitionType: SharedAxisTransitionType.vertical,
+            child: child,
+            fillColor: Colors.transparent,
+          );
+        },
+        child: _gradeTiles.isNotEmpty
+            ? Panel(
+                key: ValueKey(gradeCalcMode),
+                title: Text(
+                  gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
+                ),
+                child: Column(
+                  children: _gradeTiles,
+                ))
+            : const SizedBox(),
+      ),
+    );
+
+    tiles.add(Padding(
+        padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
+    gradeTiles = List.castFrom(tiles);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    gradeProvider = Provider.of<GradeProvider>(context);
+    calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
+
+    List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
+    average = AverageHelper.averageEvals(subjectGrades);
+    final prevAvg = subjectGrades.isNotEmpty
+        ? AverageHelper.averageEvals(subjectGrades
+            .where((e) => e.date.isBefore(subjectGrades
+                .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
+                .date
+                .subtract(const Duration(days: 30))))
+            .toList())
+        : 0.0;
+
+    gradeGraph = Padding(
+      padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
+      child: Panel(
+        title: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text("annual_average".i18n),
+            if (average != prevAvg)
+              TrendDisplay(current: average, previous: prevAvg),
+          ],
+        ),
+        child: Container(
+          padding: const EdgeInsets.only(top: 12.0, right: 12.0),
+          child: Row(
+            children: [
+              Expanded(
+                  child: GradeGraph(subjectGrades,
+                      dayThreshold: 5, classAvg: widget.groupAverage)),
+              Padding(
+                padding: const EdgeInsets.only(bottom: 24.0),
+                child: GradesCount(grades: subjectGrades),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+
+    if (!gradeCalcMode) {
+      buildTiles(subjectGrades);
+    } else {
+      List<Grade> ghostGrades = calculatorProvider.ghosts
+          .where((e) => e.subject == widget.subject)
+          .toList();
+      buildTiles(ghostGrades);
+    }
+
+    return Scaffold(
+        key: _scaffoldKey,
+        floatingActionButtonLocation: ExpandableFab.location,
+        floatingActionButton: Visibility(
+          visible: !gradeCalcMode &&
+              subjectGrades
+                  .where((e) => e.type == GradeType.midYear)
+                  .isNotEmpty,
+          child: ExpandableFab(
+            type: ExpandableFabType.up,
+            distance: 50,
+            children: [
+              FloatingActionButton.small(
+                child: const Icon(FeatherIcons.plus),
+                onPressed: () {
+                  gradeCalc(context);
+                },
+              ),
+              // FloatingActionButton.small(
+              //   child: const Icon(FeatherIcons.flag, size: 20.0),
+              //   onPressed: () {
+              //     Navigator.of(context).push(CupertinoPageRoute(builder: (context) => PremiumGoalplannerNewGoalScreen(subject: widget.subject)));
+              //   },
+              // ),
+            ],
+          ),
+        ),
+        body: RefreshIndicator(
+          onRefresh: () async {},
+          color: Theme.of(context).colorScheme.secondary,
+          child: HeroScrollView(
+              onClose: () {
+                if (_sheetController != null && gradeCalcMode) {
+                  _sheetController!.close();
+                } else {
+                  Navigator.of(context).pop();
+                }
+              },
+              navBarItems: [
+                const SizedBox(width: 6.0),
+                if (widget.groupAverage != 0)
+                  Center(
+                      child: AverageDisplay(
+                          average: widget.groupAverage, border: true)),
+                const SizedBox(width: 6.0),
+                if (average != 0)
+                  Center(child: AverageDisplay(average: average)),
+                const SizedBox(width: 12.0),
+              ],
+              icon: SubjectIcon.resolveVariant(
+                  subject: widget.subject, context: context),
+              scrollController: _scrollController,
+              title: widget.subject.renamedTo ?? widget.subject.name.capital(),
+              italic: widget.subject.isRenamed,
+              child: SubjectGradesContainer(
+                child: CupertinoScrollbar(
+                  child: ListView.builder(
+                    physics: const BouncingScrollPhysics(),
+                    padding: const EdgeInsets.symmetric(horizontal: 24.0),
+                    shrinkWrap: true,
+                    itemBuilder: (context, index) => gradeTiles[index],
+                    itemCount: gradeTiles.length,
+                  ),
+                ),
+              )),
+        ));
+  }
+
+  void gradeCalc(BuildContext context) {
+    // Scroll to the top of the page
+    _scrollController.animateTo(75,
+        duration: const Duration(milliseconds: 500), curve: Curves.ease);
+
+    calculatorProvider.clear();
+    calculatorProvider.addAllGrades(gradeProvider.grades);
+
+    _sheetController = _scaffoldKey.currentState?.showBottomSheet(
+      (context) => RoundedBottomSheet(
+          child: GradeCalculator(widget.subject), borderRadius: 14.0),
+      backgroundColor: const Color(0x00000000),
+      elevation: 12.0,
+    );
+
+    // Hide the fab and grades
+    setState(() {
+      gradeCalcMode = true;
+    });
+
+    _sheetController!.closed.then((value) {
+      // Show fab and grades
+      if (mounted) {
+        setState(() {
+          gradeCalcMode = false;
+        });
+      }
+    });
+  }
+}
diff --git a/refilc_desktop_ui/lib/pages/grades/grades_count.dart b/refilc_desktop_ui/lib/pages/grades/grades_count.dart
new file mode 100644
index 0000000..07b141f
--- /dev/null
+++ b/refilc_desktop_ui/lib/pages/grades/grades_count.dart
@@ -0,0 +1,30 @@
+import 'package:flutter/material.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_desktop_ui/pages/grades/grades_count_item.dart';
+import 'package:collection/collection.dart';
+
+class GradesCount extends StatelessWidget {
+  const GradesCount({Key? key, required this.grades}) : super(key: key);
+
+  final List<Grade> grades;
+
+  @override
+  Widget build(BuildContext context) {
+    List<int> gradesCount = List.generate(5,
+        (int index) => grades.where((e) => e.value.value == index + 1).length);
+
+    return Container(
+      width: 75,
+      padding:
+          const EdgeInsets.only(bottom: 6.0, top: 6.0, left: 12.0, right: 0.0),
+      margin: const EdgeInsets.symmetric(horizontal: 12.0),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.spaceAround,
+        children: gradesCount
+            .mapIndexed(
+                (index, e) => GradesCountItem(count: e, value: index + 1))
+            .toList(),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/grades/grades_count_item.dart b/refilc_desktop_ui/lib/pages/grades/grades_count_item.dart
similarity index 80%
rename from filcnaplo_desktop_ui/lib/pages/grades/grades_count_item.dart
rename to refilc_desktop_ui/lib/pages/grades/grades_count_item.dart
index 0030cac..1d12a60 100644
--- a/filcnaplo_desktop_ui/lib/pages/grades/grades_count_item.dart
+++ b/refilc_desktop_ui/lib/pages/grades/grades_count_item.dart
@@ -1,37 +1,39 @@
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:flutter/material.dart';
-
-class GradesCountItem extends StatelessWidget {
-  const GradesCountItem({Key? key, required this.count, required this.value}) : super(key: key);
-
-  final int count;
-  final int value;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 2.0),
-      child: Row(
-        mainAxisAlignment: MainAxisAlignment.spaceBetween,
-        children: [
-          Text.rich(
-            TextSpan(children: [
-              TextSpan(
-                text: count.toString(),
-                style: const TextStyle(fontWeight: FontWeight.w600),
-              ),
-              const TextSpan(
-                text: "x",
-                style: TextStyle(fontSize: 13.0),
-              ),
-            ]),
-            style: const TextStyle(fontSize: 15.0),
-          ),
-          const SizedBox(width: 5.0),
-          GradeValueWidget(GradeValue(value, "Value", "Value", 100), size: 19.0, fill: true, shadow: false),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:flutter/material.dart';
+
+class GradesCountItem extends StatelessWidget {
+  const GradesCountItem({Key? key, required this.count, required this.value})
+      : super(key: key);
+
+  final int count;
+  final int value;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 2.0),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: [
+          Text.rich(
+            TextSpan(children: [
+              TextSpan(
+                text: count.toString(),
+                style: const TextStyle(fontWeight: FontWeight.w600),
+              ),
+              const TextSpan(
+                text: "x",
+                style: TextStyle(fontSize: 13.0),
+              ),
+            ]),
+            style: const TextStyle(fontSize: 15.0),
+          ),
+          const SizedBox(width: 5.0),
+          GradeValueWidget(GradeValue(value, "Value", "Value", 100),
+              size: 19.0, fill: true, shadow: false),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/grades/grades_page.dart b/refilc_desktop_ui/lib/pages/grades/grades_page.dart
similarity index 86%
rename from filcnaplo_desktop_ui/lib/pages/grades/grades_page.dart
rename to refilc_desktop_ui/lib/pages/grades/grades_page.dart
index 619756a..43172d0 100644
--- a/filcnaplo_desktop_ui/lib/pages/grades/grades_page.dart
+++ b/refilc_desktop_ui/lib/pages/grades/grades_page.dart
@@ -1,312 +1,312 @@
-import 'dart:math';
-
-import 'package:auto_size_text/auto_size_text.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/group_average.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/statistics_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_subject_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/trend_display.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/fail_warning.dart';
-import 'package:filcnaplo_desktop_ui/pages/grades/grades_count.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
-import 'package:filcnaplo_desktop_ui/pages/grades/grade_subject_view.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo_premium/ui/mobile/grades/average_selector.dart';
-import 'grades_page.i18n.dart';
-
-class GradesPage extends StatefulWidget {
-  const GradesPage({Key? key}) : super(key: key);
-
-  @override
-  _GradesPageState createState() => _GradesPageState();
-}
-
-class _GradesPageState extends State<GradesPage> {
-  late UserProvider user;
-  late GradeProvider gradeProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late Widget yearlyGraph;
-  List<Widget> subjectTiles = [];
-
-  int avgDropValue = 0;
-
-  List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
-      .grades
-      .where((e) =>
-          e.subject == subject &&
-          e.type == GradeType.midYear &&
-          (days == 0 ||
-              e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
-      .toList();
-
-  void generateTiles() {
-    List<Subject> subjects = gradeProvider.grades
-        .map((e) => e.subject)
-        .toSet()
-        .toList()
-      ..sort((a, b) => a.name.compareTo(b.name));
-    List<Widget> tiles = [];
-
-    Map<Subject, double> subjectAvgs = {};
-
-    tiles.addAll(subjects.map((subject) {
-      List<Grade> subjectGrades = getSubjectGrades(subject);
-
-      double avg = AverageHelper.averageEvals(subjectGrades);
-      double averageBefore = 0.0;
-
-      if (avgDropValue != 0) {
-        List<Grade> gradesBefore =
-            getSubjectGrades(subject, days: avgDropValue);
-        averageBefore =
-            avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore);
-      }
-      var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0");
-      double groupAverage = gradeProvider.groupAverages
-          .firstWhere((e) => e.subject == subject, orElse: () => nullavg)
-          .average;
-
-      if (avg != 0) subjectAvgs[subject] = avg;
-
-      return GradeSubjectTile(
-        subject,
-        averageBefore: averageBefore,
-        average: avg,
-        groupAverage: avgDropValue == 0 ? groupAverage : 0.0,
-        onTap: () {
-          GradeSubjectView(subject, groupAverage: groupAverage)
-              .push(context, root: true);
-        },
-      );
-    }));
-
-    if (tiles.isNotEmpty) {
-      tiles.insert(0, yearlyGraph);
-      tiles.insert(1, FailWarning(subjectAvgs: subjectAvgs));
-      tiles.insert(
-          2,
-          PanelTitle(
-              title: Text(avgDropValue == 0
-                  ? "Subjects".i18n
-                  : "Subjects_changes".i18n)));
-      tiles.insert(3, const PanelHeader(padding: EdgeInsets.only(top: 12.0)));
-      tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0)));
-      tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0)));
-    } else {
-      tiles.insert(
-        0,
-        Padding(
-          padding: const EdgeInsets.only(top: 24.0),
-          child: Empty(subtitle: "empty".i18n),
-        ),
-      );
-    }
-
-    double subjectAvg = subjectAvgs.isNotEmpty
-        ? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
-            subjectAvgs.length
-        : 0.0;
-    final double classAvg = gradeProvider.groupAverages.isNotEmpty
-        ? gradeProvider.groupAverages
-                .map((e) => e.average)
-                .fold(0.0, (double a, double b) => a + b) /
-            gradeProvider.groupAverages.length
-        : 0.0;
-
-    if (subjectAvg > 0) {
-      tiles.add(Row(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Expanded(
-            child: StatisticsTile(
-              fill: true,
-              title: AutoSizeText(
-                "subjectavg".i18n,
-                textAlign: TextAlign.center,
-                maxLines: 2,
-                overflow: TextOverflow.ellipsis,
-              ),
-              value: subjectAvg,
-            ),
-          ),
-          const SizedBox(width: 24.0),
-          Expanded(
-            child: StatisticsTile(
-              outline: true,
-              title: AutoSizeText(
-                "classavg".i18n,
-                textAlign: TextAlign.center,
-                maxLines: 2,
-                wrapWords: false,
-                overflow: TextOverflow.ellipsis,
-              ),
-              value: classAvg,
-            ),
-          ),
-        ],
-      ));
-    }
-
-    // padding
-    tiles.add(const SizedBox(height: 32.0));
-
-    subjectTiles = List.castFrom(tiles);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    gradeProvider = Provider.of<GradeProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    final double totalClassAvg = gradeProvider.groupAverages.isEmpty
-        ? 0.0
-        : gradeProvider.groupAverages
-                .map((e) => e.average)
-                .fold(0.0, (double a, double b) => a + b) /
-            gradeProvider.groupAverages.length;
-
-    final now = gradeProvider.grades.isNotEmpty
-        ? gradeProvider.grades
-            .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
-            .date
-        : DateTime.now();
-
-    final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
-        .where((e) => e.type == GradeType.midYear)
-        .toList());
-    final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
-        .where((e) => e.type == GradeType.midYear)
-        .where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
-        .toList());
-
-    List<Grade> graphGrades = gradeProvider.grades
-        .where((e) =>
-            e.type == GradeType.midYear &&
-            (avgDropValue == 0 ||
-                e.date.isAfter(
-                    DateTime.now().subtract(Duration(days: avgDropValue)))))
-        .toList();
-
-    yearlyGraph = Padding(
-      padding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
-      child: Panel(
-        title: Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: [
-            PremiumAverageSelector(
-              value: avgDropValue,
-              onChanged: (value) {
-                setState(() {
-                  avgDropValue = value!;
-                });
-              },
-            ),
-            Row(
-              children: [
-                // if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true),
-                // const SizedBox(width: 4.0),
-                TrendDisplay(
-                    previous: prevStudentAvg, current: currentStudentAvg),
-                if (gradeProvider.grades
-                    .where((e) => e.type == GradeType.midYear)
-                    .isNotEmpty)
-                  AverageDisplay(average: currentStudentAvg),
-              ],
-            )
-          ],
-        ),
-        child: Container(
-          padding: const EdgeInsets.only(top: 12.0, right: 12.0),
-          child: Row(
-            children: [
-              Expanded(
-                  child: GradeGraph(graphGrades,
-                      dayThreshold: 2, classAvg: totalClassAvg)),
-              Padding(
-                padding: const EdgeInsets.only(bottom: 24.0),
-                child: GradesCount(grades: graphGrades),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-
-    generateTiles();
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 9.0),
-        child: NestedScrollView(
-          physics: const BouncingScrollPhysics(
-              parent: AlwaysScrollableScrollPhysics()),
-          headerSliverBuilder: (context, _) => [
-            SliverAppBar(
-              centerTitle: false,
-              pinned: true,
-              floating: false,
-              snap: false,
-              automaticallyImplyLeading: false,
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-              title: Padding(
-                padding: const EdgeInsets.only(left: 8.0),
-                child: Text(
-                  "Grades".i18n,
-                  style: TextStyle(
-                      color: AppColors.of(context).text,
-                      fontSize: 32.0,
-                      fontWeight: FontWeight.bold),
-                ),
-              ),
-              shadowColor: Theme.of(context).shadowColor,
-            ),
-          ],
-          body: RefreshIndicator(
-            onRefresh: () => gradeProvider.fetch(),
-            color: Theme.of(context).colorScheme.secondary,
-            child: ListView.builder(
-              padding: EdgeInsets.zero,
-              physics: const BouncingScrollPhysics(),
-              itemCount: max(subjectTiles.length, 1),
-              itemBuilder: (context, index) {
-                if (subjectTiles.isNotEmpty) {
-                  EdgeInsetsGeometry panelPadding =
-                      const EdgeInsets.symmetric(horizontal: 24.0);
-
-                  if (subjectTiles[index].runtimeType == GradeSubjectTile) {
-                    return Padding(
-                        padding: panelPadding,
-                        child: PanelBody(
-                          child: subjectTiles[index],
-                          padding: const EdgeInsets.symmetric(horizontal: 8.0),
-                        ));
-                  } else {
-                    return Padding(
-                        padding: panelPadding, child: subjectTiles[index]);
-                  }
-                } else {
-                  return Container();
-                }
-              },
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:auto_size_text/auto_size_text.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/group_average.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/widgets/statistics_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/grade_subject_tile.dart';
+import 'package:refilc_mobile_ui/common/trend_display.dart';
+import 'package:refilc_mobile_ui/pages/grades/fail_warning.dart';
+import 'package:refilc_desktop_ui/pages/grades/grades_count.dart';
+import 'package:refilc_mobile_ui/pages/grades/graph.dart';
+import 'package:refilc_desktop_ui/pages/grades/grade_subject_view.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc_premium/ui/mobile/grades/average_selector.dart';
+import 'grades_page.i18n.dart';
+
+class GradesPage extends StatefulWidget {
+  const GradesPage({Key? key}) : super(key: key);
+
+  @override
+  _GradesPageState createState() => _GradesPageState();
+}
+
+class _GradesPageState extends State<GradesPage> {
+  late UserProvider user;
+  late GradeProvider gradeProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late Widget yearlyGraph;
+  List<Widget> subjectTiles = [];
+
+  int avgDropValue = 0;
+
+  List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
+      .grades
+      .where((e) =>
+          e.subject == subject &&
+          e.type == GradeType.midYear &&
+          (days == 0 ||
+              e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
+      .toList();
+
+  void generateTiles() {
+    List<Subject> subjects = gradeProvider.grades
+        .map((e) => e.subject)
+        .toSet()
+        .toList()
+      ..sort((a, b) => a.name.compareTo(b.name));
+    List<Widget> tiles = [];
+
+    Map<Subject, double> subjectAvgs = {};
+
+    tiles.addAll(subjects.map((subject) {
+      List<Grade> subjectGrades = getSubjectGrades(subject);
+
+      double avg = AverageHelper.averageEvals(subjectGrades);
+      double averageBefore = 0.0;
+
+      if (avgDropValue != 0) {
+        List<Grade> gradesBefore =
+            getSubjectGrades(subject, days: avgDropValue);
+        averageBefore =
+            avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore);
+      }
+      var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0");
+      double groupAverage = gradeProvider.groupAverages
+          .firstWhere((e) => e.subject == subject, orElse: () => nullavg)
+          .average;
+
+      if (avg != 0) subjectAvgs[subject] = avg;
+
+      return GradeSubjectTile(
+        subject,
+        averageBefore: averageBefore,
+        average: avg,
+        groupAverage: avgDropValue == 0 ? groupAverage : 0.0,
+        onTap: () {
+          GradeSubjectView(subject, groupAverage: groupAverage)
+              .push(context, root: true);
+        },
+      );
+    }));
+
+    if (tiles.isNotEmpty) {
+      tiles.insert(0, yearlyGraph);
+      tiles.insert(1, FailWarning(subjectAvgs: subjectAvgs));
+      tiles.insert(
+          2,
+          PanelTitle(
+              title: Text(avgDropValue == 0
+                  ? "Subjects".i18n
+                  : "Subjects_changes".i18n)));
+      tiles.insert(3, const PanelHeader(padding: EdgeInsets.only(top: 12.0)));
+      tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0)));
+      tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0)));
+    } else {
+      tiles.insert(
+        0,
+        Padding(
+          padding: const EdgeInsets.only(top: 24.0),
+          child: Empty(subtitle: "empty".i18n),
+        ),
+      );
+    }
+
+    double subjectAvg = subjectAvgs.isNotEmpty
+        ? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
+            subjectAvgs.length
+        : 0.0;
+    final double classAvg = gradeProvider.groupAverages.isNotEmpty
+        ? gradeProvider.groupAverages
+                .map((e) => e.average)
+                .fold(0.0, (double a, double b) => a + b) /
+            gradeProvider.groupAverages.length
+        : 0.0;
+
+    if (subjectAvg > 0) {
+      tiles.add(Row(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Expanded(
+            child: StatisticsTile(
+              fill: true,
+              title: AutoSizeText(
+                "subjectavg".i18n,
+                textAlign: TextAlign.center,
+                maxLines: 2,
+                overflow: TextOverflow.ellipsis,
+              ),
+              value: subjectAvg,
+            ),
+          ),
+          const SizedBox(width: 24.0),
+          Expanded(
+            child: StatisticsTile(
+              outline: true,
+              title: AutoSizeText(
+                "classavg".i18n,
+                textAlign: TextAlign.center,
+                maxLines: 2,
+                wrapWords: false,
+                overflow: TextOverflow.ellipsis,
+              ),
+              value: classAvg,
+            ),
+          ),
+        ],
+      ));
+    }
+
+    // padding
+    tiles.add(const SizedBox(height: 32.0));
+
+    subjectTiles = List.castFrom(tiles);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    gradeProvider = Provider.of<GradeProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    final double totalClassAvg = gradeProvider.groupAverages.isEmpty
+        ? 0.0
+        : gradeProvider.groupAverages
+                .map((e) => e.average)
+                .fold(0.0, (double a, double b) => a + b) /
+            gradeProvider.groupAverages.length;
+
+    final now = gradeProvider.grades.isNotEmpty
+        ? gradeProvider.grades
+            .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
+            .date
+        : DateTime.now();
+
+    final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
+        .where((e) => e.type == GradeType.midYear)
+        .toList());
+    final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
+        .where((e) => e.type == GradeType.midYear)
+        .where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
+        .toList());
+
+    List<Grade> graphGrades = gradeProvider.grades
+        .where((e) =>
+            e.type == GradeType.midYear &&
+            (avgDropValue == 0 ||
+                e.date.isAfter(
+                    DateTime.now().subtract(Duration(days: avgDropValue)))))
+        .toList();
+
+    yearlyGraph = Padding(
+      padding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
+      child: Panel(
+        title: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            PremiumAverageSelector(
+              value: avgDropValue,
+              onChanged: (value) {
+                setState(() {
+                  avgDropValue = value!;
+                });
+              },
+            ),
+            Row(
+              children: [
+                // if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true),
+                // const SizedBox(width: 4.0),
+                TrendDisplay(
+                    previous: prevStudentAvg, current: currentStudentAvg),
+                if (gradeProvider.grades
+                    .where((e) => e.type == GradeType.midYear)
+                    .isNotEmpty)
+                  AverageDisplay(average: currentStudentAvg),
+              ],
+            )
+          ],
+        ),
+        child: Container(
+          padding: const EdgeInsets.only(top: 12.0, right: 12.0),
+          child: Row(
+            children: [
+              Expanded(
+                  child: GradeGraph(graphGrades,
+                      dayThreshold: 2, classAvg: totalClassAvg)),
+              Padding(
+                padding: const EdgeInsets.only(bottom: 24.0),
+                child: GradesCount(grades: graphGrades),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+
+    generateTiles();
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 9.0),
+        child: NestedScrollView(
+          physics: const BouncingScrollPhysics(
+              parent: AlwaysScrollableScrollPhysics()),
+          headerSliverBuilder: (context, _) => [
+            SliverAppBar(
+              centerTitle: false,
+              pinned: true,
+              floating: false,
+              snap: false,
+              automaticallyImplyLeading: false,
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+              title: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  "Grades".i18n,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontSize: 32.0,
+                      fontWeight: FontWeight.bold),
+                ),
+              ),
+              shadowColor: Theme.of(context).shadowColor,
+            ),
+          ],
+          body: RefreshIndicator(
+            onRefresh: () => gradeProvider.fetch(),
+            color: Theme.of(context).colorScheme.secondary,
+            child: ListView.builder(
+              padding: EdgeInsets.zero,
+              physics: const BouncingScrollPhysics(),
+              itemCount: max(subjectTiles.length, 1),
+              itemBuilder: (context, index) {
+                if (subjectTiles.isNotEmpty) {
+                  EdgeInsetsGeometry panelPadding =
+                      const EdgeInsets.symmetric(horizontal: 24.0);
+
+                  if (subjectTiles[index].runtimeType == GradeSubjectTile) {
+                    return Padding(
+                        padding: panelPadding,
+                        child: PanelBody(
+                          child: subjectTiles[index],
+                          padding: const EdgeInsets.symmetric(horizontal: 8.0),
+                        ));
+                  } else {
+                    return Padding(
+                        padding: panelPadding, child: subjectTiles[index]);
+                  }
+                } else {
+                  return Container();
+                }
+              },
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/grades_page.i18n.dart b/refilc_desktop_ui/lib/pages/grades/grades_page.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/grades/grades_page.i18n.dart
rename to refilc_desktop_ui/lib/pages/grades/grades_page.i18n.dart
index 11d7fbb..41d0d03
--- a/filcnaplo_mobile_ui/lib/pages/grades/grades_page.i18n.dart
+++ b/refilc_desktop_ui/lib/pages/grades/grades_page.i18n.dart
@@ -1,60 +1,60 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Grades": "Grades",
-          "Ghost Grades": "Grades",
-          "Subjects": "Subjects",
-          "Subjects_changes": "Subject Differences",
-          "empty": "You don't have any subjects.",
-          "annual_average": "Annual average",
-          "3_months_average": "3 Monthly Average",
-          "30_days_average": "Monthly Average",
-          "14_days_average": "2 Weekly Average",
-          "7_days_average": "Weekly Average",
-          "subjectavg": "Subject Average",
-          "classavg": "Class Average",
-          "fail_warning": "Faliure warning",
-          "fail_warning_description": "You are failing %d subject(s)",
-        },
-        "hu_hu": {
-          "Grades": "Jegyek",
-          "Ghost Grades": "Szellem jegyek",
-          "Subjects": "Tantárgyak",
-          "Subjects_changes": "Tantárgyi változások",
-          "empty": "Még nincs egy tárgyad sem.",
-          "annual_average": "Éves átlag",
-          "3_months_average": "Háromhavi átlag",
-          "30_days_average": "Havi átlag",
-          "14_days_average": "Kétheti átlag",
-          "7_days_average": "Heti átlag",
-          "subjectavg": "Tantárgyi átlag",
-          "classavg": "Osztályátlag",
-          "fail_warning": "Bukás figyelmeztető",
-          "fail_warning_description": "Bukásra állsz %d tantárgyból",
-        },
-        "de_de": {
-          "Grades": "Noten",
-          "Ghost Grades": "Geist Noten",
-          "Subjects": "Fächer",
-          "Subjects_changes": "Betreff Änderungen",
-          "empty": "Sie haben keine Fächer.",
-          "annual_average": "Jahresdurchschnitt",
-          "3_months_average": "Drei-Monats-Durchschnitt",
-          "30_days_average": "Monatsdurchschnitt",
-          "14_days_average": "Vierzehntägiger Durchschnitt",
-          "7_days_average": "Wöchentlicher Durchschnitt",
-          "subjectavg": "Fächer Durchschnitt",
-          "classavg": "Klassendurchschnitt",
-          "fail_warning": "Ausfallwarnung",
-          "fail_warning_description": "Sie werden in %d des Fachs durchfallen",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Grades": "Grades",
+          "Ghost Grades": "Grades",
+          "Subjects": "Subjects",
+          "Subjects_changes": "Subject Differences",
+          "empty": "You don't have any subjects.",
+          "annual_average": "Annual average",
+          "3_months_average": "3 Monthly Average",
+          "30_days_average": "Monthly Average",
+          "14_days_average": "2 Weekly Average",
+          "7_days_average": "Weekly Average",
+          "subjectavg": "Subject Average",
+          "classavg": "Class Average",
+          "fail_warning": "Faliure warning",
+          "fail_warning_description": "You are failing %d subject(s)",
+        },
+        "hu_hu": {
+          "Grades": "Jegyek",
+          "Ghost Grades": "Szellem jegyek",
+          "Subjects": "Tantárgyak",
+          "Subjects_changes": "Tantárgyi változások",
+          "empty": "Még nincs egy tárgyad sem.",
+          "annual_average": "Éves átlag",
+          "3_months_average": "Háromhavi átlag",
+          "30_days_average": "Havi átlag",
+          "14_days_average": "Kétheti átlag",
+          "7_days_average": "Heti átlag",
+          "subjectavg": "Tantárgyi átlag",
+          "classavg": "Osztályátlag",
+          "fail_warning": "Bukás figyelmeztető",
+          "fail_warning_description": "Bukásra állsz %d tantárgyból",
+        },
+        "de_de": {
+          "Grades": "Noten",
+          "Ghost Grades": "Geist Noten",
+          "Subjects": "Fächer",
+          "Subjects_changes": "Betreff Änderungen",
+          "empty": "Sie haben keine Fächer.",
+          "annual_average": "Jahresdurchschnitt",
+          "3_months_average": "Drei-Monats-Durchschnitt",
+          "30_days_average": "Monatsdurchschnitt",
+          "14_days_average": "Vierzehntägiger Durchschnitt",
+          "7_days_average": "Wöchentlicher Durchschnitt",
+          "subjectavg": "Fächer Durchschnitt",
+          "classavg": "Klassendurchschnitt",
+          "fail_warning": "Ausfallwarnung",
+          "fail_warning_description": "Sie werden in %d des Fachs durchfallen",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/home/home_page.dart b/refilc_desktop_ui/lib/pages/home/home_page.dart
similarity index 92%
rename from filcnaplo_desktop_ui/lib/pages/home/home_page.dart
rename to refilc_desktop_ui/lib/pages/home/home_page.dart
index edfc433..e75476e 100644
--- a/filcnaplo_desktop_ui/lib/pages/home/home_page.dart
+++ b/refilc_desktop_ui/lib/pages/home/home_page.dart
@@ -1,180 +1,180 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
-import 'package:flutter/material.dart';
-import 'package:animated_list_plus/animated_list_plus.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/ui/filter/widgets.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-import 'home_page.i18n.dart';
-
-class HomePage extends StatefulWidget {
-  const HomePage({Key? key}) : super(key: key);
-
-  @override
-  State<HomePage> createState() => _HomePageState();
-}
-
-class _HomePageState extends State<HomePage>
-    with SingleTickerProviderStateMixin {
-  late UserProvider user;
-  late SettingsProvider settings;
-
-  late TabController _tabController;
-  late PageController _pageController;
-
-  late String greeting;
-  late String firstName;
-
-  late List<String> listOrder;
-  static const pageCount = 4;
-
-  @override
-  void initState() {
-    super.initState();
-
-    _tabController = TabController(length: pageCount, vsync: this);
-    _pageController = PageController();
-
-    listOrder = List.generate(pageCount, (index) => "$index");
-
-    user = Provider.of<UserProvider>(context, listen: false);
-
-    DateTime now = DateTime.now();
-    if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
-        now.isAfter(DateTime(now.year, DateTime.june, 14))) {
-      greeting = "goodrest";
-    } else if (now.month == user.student?.birth.month &&
-        now.day == user.student?.birth.day) {
-      greeting = "happybirthday";
-    } else if (now.month == DateTime.december &&
-        now.day >= 24 &&
-        now.day <= 26) {
-      greeting = "merryxmas";
-    } else if (now.month == DateTime.january && now.day == 1) {
-      greeting = "happynewyear";
-    } else if (now.hour >= 18) {
-      greeting = "goodevening";
-    } else if (now.hour >= 10) {
-      greeting = "goodafternoon";
-    } else if (now.hour >= 4) {
-      greeting = "goodmorning";
-    } else {
-      greeting = "goodevening";
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    settings = Provider.of<SettingsProvider>(context);
-
-    List<String> nameParts = user.name?.split(" ") ?? ["?"];
-    if (!settings.presentationMode) {
-      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-    } else {
-      firstName = "Béla";
-    }
-
-    return SafeArea(
-      child: Row(
-        children: [
-          Expanded(
-            child: Column(
-              crossAxisAlignment: CrossAxisAlignment.start,
-              children: [
-                // Greeting
-                Padding(
-                  padding: const EdgeInsets.only(
-                      left: 32.0, top: 24.0, bottom: 12.0),
-                  child: Text(
-                    greeting.i18n.fill([firstName]),
-                    overflow: TextOverflow.fade,
-                    style: TextStyle(
-                      fontWeight: FontWeight.bold,
-                      fontSize: 24.0,
-                      color: Theme.of(context).textTheme.bodyMedium?.color,
-                    ),
-                  ),
-                ),
-
-                Padding(
-                  padding: const EdgeInsets.only(bottom: 12.0),
-                  child: FilterBar(
-                    items: [
-                      Tab(text: "All".i18n),
-                      Tab(text: "Grades".i18n),
-                      Tab(text: "Messages".i18n),
-                      Tab(text: "Absences".i18n),
-                    ],
-                    controller: _tabController,
-                    onTap: (i) async {
-                      int selectedPage = _pageController.page!.round();
-
-                      if (i == selectedPage) return;
-                      if (_pageController.page?.roundToDouble() !=
-                          _pageController.page) {
-                        _pageController.animateToPage(i,
-                            curve: Curves.easeIn, duration: kTabScrollDuration);
-                        return;
-                      }
-
-                      // swap current page with target page
-                      setState(() {
-                        _pageController.jumpToPage(i);
-                        String currentList = listOrder[selectedPage];
-                        listOrder[selectedPage] = listOrder[i];
-                        listOrder[i] = currentList;
-                      });
-                    },
-                    disableFading: true,
-                  ),
-                ),
-
-                // Data filters
-                Expanded(
-                  child: PageView.custom(
-                    controller: _pageController,
-                    childrenDelegate: SliverChildBuilderDelegate(
-                      (BuildContext context, int index) {
-                        return FutureBuilder<List<DateWidget>>(
-                          key: ValueKey<String>(listOrder[index]),
-                          future: getFilterWidgets(homeFilters[index],
-                              context: context),
-                          builder: (context, dateWidgets) => dateWidgets.data !=
-                                  null
-                              ? ImplicitlyAnimatedList<Widget>(
-                                  items: sortDateWidgets(context,
-                                      dateWidgets: dateWidgets.data!),
-                                  itemBuilder: filterItemBuilder,
-                                  spawnIsolate: false,
-                                  areItemsTheSame: (a, b) => a.key == b.key,
-                                  physics: const BouncingScrollPhysics(
-                                      parent: AlwaysScrollableScrollPhysics()),
-                                  padding: const EdgeInsets.symmetric(
-                                      horizontal: 24.0),
-                                )
-                              : Container(),
-                        );
-                      },
-                      childCount: 4,
-                      findChildIndexCallback: (Key key) {
-                        final ValueKey<String> valueKey =
-                            key as ValueKey<String>;
-                        final String data = valueKey.value;
-                        return listOrder.indexOf(data);
-                      },
-                    ),
-                    physics: const PageScrollPhysics()
-                        .applyTo(const BouncingScrollPhysics()),
-                  ),
-                ),
-              ],
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:flutter/material.dart';
+import 'package:animated_list_plus/animated_list_plus.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/ui/filter/widgets.dart';
+import 'package:refilc/ui/filter/sort.dart';
+import 'home_page.i18n.dart';
+
+class HomePage extends StatefulWidget {
+  const HomePage({Key? key}) : super(key: key);
+
+  @override
+  State<HomePage> createState() => _HomePageState();
+}
+
+class _HomePageState extends State<HomePage>
+    with SingleTickerProviderStateMixin {
+  late UserProvider user;
+  late SettingsProvider settings;
+
+  late TabController _tabController;
+  late PageController _pageController;
+
+  late String greeting;
+  late String firstName;
+
+  late List<String> listOrder;
+  static const pageCount = 4;
+
+  @override
+  void initState() {
+    super.initState();
+
+    _tabController = TabController(length: pageCount, vsync: this);
+    _pageController = PageController();
+
+    listOrder = List.generate(pageCount, (index) => "$index");
+
+    user = Provider.of<UserProvider>(context, listen: false);
+
+    DateTime now = DateTime.now();
+    if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
+        now.isAfter(DateTime(now.year, DateTime.june, 14))) {
+      greeting = "goodrest";
+    } else if (now.month == user.student?.birth.month &&
+        now.day == user.student?.birth.day) {
+      greeting = "happybirthday";
+    } else if (now.month == DateTime.december &&
+        now.day >= 24 &&
+        now.day <= 26) {
+      greeting = "merryxmas";
+    } else if (now.month == DateTime.january && now.day == 1) {
+      greeting = "happynewyear";
+    } else if (now.hour >= 18) {
+      greeting = "goodevening";
+    } else if (now.hour >= 10) {
+      greeting = "goodafternoon";
+    } else if (now.hour >= 4) {
+      greeting = "goodmorning";
+    } else {
+      greeting = "goodevening";
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    settings = Provider.of<SettingsProvider>(context);
+
+    List<String> nameParts = user.name?.split(" ") ?? ["?"];
+    if (!settings.presentationMode) {
+      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+    } else {
+      firstName = "Béla";
+    }
+
+    return SafeArea(
+      child: Row(
+        children: [
+          Expanded(
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                // Greeting
+                Padding(
+                  padding: const EdgeInsets.only(
+                      left: 32.0, top: 24.0, bottom: 12.0),
+                  child: Text(
+                    greeting.i18n.fill([firstName]),
+                    overflow: TextOverflow.fade,
+                    style: TextStyle(
+                      fontWeight: FontWeight.bold,
+                      fontSize: 24.0,
+                      color: Theme.of(context).textTheme.bodyMedium?.color,
+                    ),
+                  ),
+                ),
+
+                Padding(
+                  padding: const EdgeInsets.only(bottom: 12.0),
+                  child: FilterBar(
+                    items: [
+                      Tab(text: "All".i18n),
+                      Tab(text: "Grades".i18n),
+                      Tab(text: "Messages".i18n),
+                      Tab(text: "Absences".i18n),
+                    ],
+                    controller: _tabController,
+                    onTap: (i) async {
+                      int selectedPage = _pageController.page!.round();
+
+                      if (i == selectedPage) return;
+                      if (_pageController.page?.roundToDouble() !=
+                          _pageController.page) {
+                        _pageController.animateToPage(i,
+                            curve: Curves.easeIn, duration: kTabScrollDuration);
+                        return;
+                      }
+
+                      // swap current page with target page
+                      setState(() {
+                        _pageController.jumpToPage(i);
+                        String currentList = listOrder[selectedPage];
+                        listOrder[selectedPage] = listOrder[i];
+                        listOrder[i] = currentList;
+                      });
+                    },
+                    disableFading: true,
+                  ),
+                ),
+
+                // Data filters
+                Expanded(
+                  child: PageView.custom(
+                    controller: _pageController,
+                    childrenDelegate: SliverChildBuilderDelegate(
+                      (BuildContext context, int index) {
+                        return FutureBuilder<List<DateWidget>>(
+                          key: ValueKey<String>(listOrder[index]),
+                          future: getFilterWidgets(homeFilters[index],
+                              context: context),
+                          builder: (context, dateWidgets) => dateWidgets.data !=
+                                  null
+                              ? ImplicitlyAnimatedList<Widget>(
+                                  items: sortDateWidgets(context,
+                                      dateWidgets: dateWidgets.data!),
+                                  itemBuilder: filterItemBuilder,
+                                  spawnIsolate: false,
+                                  areItemsTheSame: (a, b) => a.key == b.key,
+                                  physics: const BouncingScrollPhysics(
+                                      parent: AlwaysScrollableScrollPhysics()),
+                                  padding: const EdgeInsets.symmetric(
+                                      horizontal: 24.0),
+                                )
+                              : Container(),
+                        );
+                      },
+                      childCount: 4,
+                      findChildIndexCallback: (Key key) {
+                        final ValueKey<String> valueKey =
+                            key as ValueKey<String>;
+                        final String data = valueKey.value;
+                        return listOrder.indexOf(data);
+                      },
+                    ),
+                    physics: const PageScrollPhysics()
+                        .applyTo(const BouncingScrollPhysics()),
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/home/home_page.i18n.dart b/refilc_desktop_ui/lib/pages/home/home_page.i18n.dart
similarity index 97%
rename from filcnaplo_desktop_ui/lib/pages/home/home_page.i18n.dart
rename to refilc_desktop_ui/lib/pages/home/home_page.i18n.dart
index 47ed140..2362b96 100644
--- a/filcnaplo_desktop_ui/lib/pages/home/home_page.i18n.dart
+++ b/refilc_desktop_ui/lib/pages/home/home_page.i18n.dart
@@ -1,63 +1,63 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "goodmorning": "Good morning, %s!",
-          "goodafternoon": "Good afternoon, %s!",
-          "goodevening": "Good evening, %s!",
-          "goodrest": "⛱️ Have a nice holiday, %s!",
-          "happybirthday": "🎂 Happy birthday, %s!",
-          "merryxmas": "🎄 Merry Christmas, %s!",
-          "happynewyear": "🎉 Happy New Year, %s!",
-          "empty": "Nothing to see here.",
-          "All": "All",
-          "Grades": "Grades",
-          "Messages": "Messages",
-          "Absences": "Absences",
-          "update_available": "Update Available",
-          "missed_exams": "You missed %s exams this week.".one("You missed an exam this week."),
-          "missed_exam_contact": "Contact %s, to resolve it!",
-        },
-        "hu_hu": {
-          "goodmorning": "Jó reggelt, %s!",
-          "goodafternoon": "Szép napot, %s!",
-          "goodevening": "Szép estét, %s!",
-          "goodrest": "⛱️ Jó szünetet, %s!",
-          "happybirthday": "🎂 Boldog születésnapot, %s!",
-          "merryxmas": "🎄 Boldog Karácsonyt, %s!",
-          "happynewyear": "🎉 Boldog új évet, %s!",
-          "empty": "Nincs itt semmi látnivaló.",
-          "All": "Összes",
-          "Grades": "Jegyek",
-          "Messages": "Üzenetek",
-          "Absences": "Hiányok",
-          "update_available": "Frissítés elérhető",
-          "missed_exams": "Ezen a héten hiányoztál %s dolgozatról.".one("Ezen a héten hiányoztál egy dolgozatról."),
-          "missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
-        },
-        "de_de": {
-          "goodmorning": "Guten morgen, %s!",
-          "goodafternoon": "Guten Tag, %s!",
-          "goodevening": "Guten Abend, %s!",
-          "goodrest": "⛱️ Schöne Ferien, %s!",
-          "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
-          "merryxmas": "🎄 Frohe Weihnachten, %s!",
-          "happynewyear": "🎉 Frohes neues Jahr, %s!",
-          "empty": "Hier gibt es nichts zu sehen.",
-          "All": "Alles",
-          "Grades": "Noten",
-          "Messages": "Nachrichten",
-          "Absences": "Fehlen",
-          "update_available": "Update verfügbar",
-          "missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.".one("Diese Woche haben Sie eine Prüfung verpasst."),
-          "missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "goodmorning": "Good morning, %s!",
+          "goodafternoon": "Good afternoon, %s!",
+          "goodevening": "Good evening, %s!",
+          "goodrest": "⛱️ Have a nice holiday, %s!",
+          "happybirthday": "🎂 Happy birthday, %s!",
+          "merryxmas": "🎄 Merry Christmas, %s!",
+          "happynewyear": "🎉 Happy New Year, %s!",
+          "empty": "Nothing to see here.",
+          "All": "All",
+          "Grades": "Grades",
+          "Messages": "Messages",
+          "Absences": "Absences",
+          "update_available": "Update Available",
+          "missed_exams": "You missed %s exams this week.".one("You missed an exam this week."),
+          "missed_exam_contact": "Contact %s, to resolve it!",
+        },
+        "hu_hu": {
+          "goodmorning": "Jó reggelt, %s!",
+          "goodafternoon": "Szép napot, %s!",
+          "goodevening": "Szép estét, %s!",
+          "goodrest": "⛱️ Jó szünetet, %s!",
+          "happybirthday": "🎂 Boldog születésnapot, %s!",
+          "merryxmas": "🎄 Boldog Karácsonyt, %s!",
+          "happynewyear": "🎉 Boldog új évet, %s!",
+          "empty": "Nincs itt semmi látnivaló.",
+          "All": "Összes",
+          "Grades": "Jegyek",
+          "Messages": "Üzenetek",
+          "Absences": "Hiányok",
+          "update_available": "Frissítés elérhető",
+          "missed_exams": "Ezen a héten hiányoztál %s dolgozatról.".one("Ezen a héten hiányoztál egy dolgozatról."),
+          "missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
+        },
+        "de_de": {
+          "goodmorning": "Guten morgen, %s!",
+          "goodafternoon": "Guten Tag, %s!",
+          "goodevening": "Guten Abend, %s!",
+          "goodrest": "⛱️ Schöne Ferien, %s!",
+          "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
+          "merryxmas": "🎄 Frohe Weihnachten, %s!",
+          "happynewyear": "🎉 Frohes neues Jahr, %s!",
+          "empty": "Hier gibt es nichts zu sehen.",
+          "All": "Alles",
+          "Grades": "Noten",
+          "Messages": "Nachrichten",
+          "Absences": "Fehlen",
+          "update_available": "Update verfügbar",
+          "missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.".one("Diese Woche haben Sie eine Prüfung verpasst."),
+          "missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/messages/messages_page.dart b/refilc_desktop_ui/lib/pages/messages/messages_page.dart
similarity index 77%
rename from filcnaplo_desktop_ui/lib/pages/messages/messages_page.dart
rename to refilc_desktop_ui/lib/pages/messages/messages_page.dart
index 815c421..87f85d1 100644
--- a/filcnaplo_desktop_ui/lib/pages/messages/messages_page.dart
+++ b/refilc_desktop_ui/lib/pages/messages/messages_page.dart
@@ -1,164 +1,173 @@
-import 'dart:math';
-
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/message_viewable.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'messages_page.i18n.dart';
-
-class MessagesPage extends StatefulWidget {
-  const MessagesPage({Key? key}) : super(key: key);
-
-  @override
-  _MessagesPageState createState() => _MessagesPageState();
-}
-
-class _MessagesPageState extends State<MessagesPage> with TickerProviderStateMixin {
-  late UserProvider user;
-  late MessageProvider messageProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late TabController tabController;
-
-  @override
-  void initState() {
-    super.initState();
-
-    tabController = TabController(length: 4, vsync: this);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    messageProvider = Provider.of<MessageProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 12.0),
-        child: NestedScrollView(
-          physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
-          headerSliverBuilder: (context, _) => [
-            SliverAppBar(
-              pinned: true,
-              floating: false,
-              snap: false,
-              centerTitle: false,
-              automaticallyImplyLeading: false,
-              shadowColor: Theme.of(context).shadowColor,
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-              title: Padding(
-                padding: const EdgeInsets.only(left: 8.0),
-                child: Text(
-                  "Messages".i18n,
-                  style: TextStyle(color: AppColors.of(context).text, fontSize: 32.0, fontWeight: FontWeight.bold),
-                ),
-              ),
-              bottom: FilterBar(
-                items: [
-                  Tab(text: "Inbox".i18n),
-                  Tab(text: "Sent".i18n),
-                  Tab(text: "Trash".i18n),
-                  Tab(text: "Draft".i18n),
-                ],
-                controller: tabController,
-                disableFading: true,
-              ),
-            ),
-          ],
-          body: TabBarView(
-              physics: const BouncingScrollPhysics(),
-              controller: tabController,
-              children: List.generate(4, (index) => filterViewBuilder(context, index))),
-        ),
-      ),
-    );
-  }
-
-  List<DateWidget> getFilterWidgets(MessageType activeData) {
-    List<DateWidget> items = [];
-    switch (activeData) {
-      case MessageType.inbox:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.inbox) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-      case MessageType.sent:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.sent) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-      case MessageType.trash:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.trash) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-      case MessageType.draft:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.draft) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-    }
-    return items;
-  }
-
-  Widget filterViewBuilder(context, int activeData) {
-    List<Widget> filterWidgets = sortDateWidgets(context, dateWidgets: getFilterWidgets(MessageType.values[activeData]), hasShadow: true);
-
-    return Padding(
-      padding: const EdgeInsets.only(top: 12.0),
-      child: RefreshIndicator(
-        color: Theme.of(context).colorScheme.secondary,
-        onRefresh: () {
-          return Future.wait([
-            messageProvider.fetch(type: MessageType.inbox),
-            messageProvider.fetch(type: MessageType.sent),
-            messageProvider.fetch(type: MessageType.trash),
-          ]);
-        },
-        child: ListView.builder(
-          padding: EdgeInsets.zero,
-          physics: const BouncingScrollPhysics(),
-          itemBuilder: (context, index) => filterWidgets.isNotEmpty
-              ? Padding(
-                  padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
-                  child: filterWidgets[index],
-                )
-              : Empty(subtitle: "empty".i18n),
-          itemCount: max(filterWidgets.length, 1),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc/ui/filter/sort.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/message_viewable.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'messages_page.i18n.dart';
+
+class MessagesPage extends StatefulWidget {
+  const MessagesPage({Key? key}) : super(key: key);
+
+  @override
+  _MessagesPageState createState() => _MessagesPageState();
+}
+
+class _MessagesPageState extends State<MessagesPage>
+    with TickerProviderStateMixin {
+  late UserProvider user;
+  late MessageProvider messageProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late TabController tabController;
+
+  @override
+  void initState() {
+    super.initState();
+
+    tabController = TabController(length: 4, vsync: this);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    messageProvider = Provider.of<MessageProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 12.0),
+        child: NestedScrollView(
+          physics: const BouncingScrollPhysics(
+              parent: AlwaysScrollableScrollPhysics()),
+          headerSliverBuilder: (context, _) => [
+            SliverAppBar(
+              pinned: true,
+              floating: false,
+              snap: false,
+              centerTitle: false,
+              automaticallyImplyLeading: false,
+              shadowColor: Theme.of(context).shadowColor,
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+              title: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  "Messages".i18n,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontSize: 32.0,
+                      fontWeight: FontWeight.bold),
+                ),
+              ),
+              bottom: FilterBar(
+                items: [
+                  Tab(text: "Inbox".i18n),
+                  Tab(text: "Sent".i18n),
+                  Tab(text: "Trash".i18n),
+                  Tab(text: "Draft".i18n),
+                ],
+                controller: tabController,
+                disableFading: true,
+              ),
+            ),
+          ],
+          body: TabBarView(
+              physics: const BouncingScrollPhysics(),
+              controller: tabController,
+              children: List.generate(
+                  4, (index) => filterViewBuilder(context, index))),
+        ),
+      ),
+    );
+  }
+
+  List<DateWidget> getFilterWidgets(MessageType activeData) {
+    List<DateWidget> items = [];
+    switch (activeData) {
+      case MessageType.inbox:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.inbox) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+      case MessageType.sent:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.sent) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+      case MessageType.trash:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.trash) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+      case MessageType.draft:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.draft) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+    }
+    return items;
+  }
+
+  Widget filterViewBuilder(context, int activeData) {
+    List<Widget> filterWidgets = sortDateWidgets(context,
+        dateWidgets: getFilterWidgets(MessageType.values[activeData]),
+        hasShadow: true);
+
+    return Padding(
+      padding: const EdgeInsets.only(top: 12.0),
+      child: RefreshIndicator(
+        color: Theme.of(context).colorScheme.secondary,
+        onRefresh: () {
+          return Future.wait([
+            messageProvider.fetch(type: MessageType.inbox),
+            messageProvider.fetch(type: MessageType.sent),
+            messageProvider.fetch(type: MessageType.trash),
+          ]);
+        },
+        child: ListView.builder(
+          padding: EdgeInsets.zero,
+          physics: const BouncingScrollPhysics(),
+          itemBuilder: (context, index) => filterWidgets.isNotEmpty
+              ? Padding(
+                  padding: const EdgeInsets.symmetric(
+                      horizontal: 24.0, vertical: 6.0),
+                  child: filterWidgets[index],
+                )
+              : Empty(subtitle: "empty".i18n),
+          itemCount: max(filterWidgets.length, 1),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/messages/messages_page.i18n.dart b/refilc_desktop_ui/lib/pages/messages/messages_page.i18n.dart
similarity index 96%
rename from filcnaplo_desktop_ui/lib/pages/messages/messages_page.i18n.dart
rename to refilc_desktop_ui/lib/pages/messages/messages_page.i18n.dart
index e584436..b1665e1 100644
--- a/filcnaplo_desktop_ui/lib/pages/messages/messages_page.i18n.dart
+++ b/refilc_desktop_ui/lib/pages/messages/messages_page.i18n.dart
@@ -1,36 +1,36 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Messages": "Messages",
-          "Inbox": "Inbox",
-          "Sent": "Sent",
-          "Trash": "Trash",
-          "Draft": "Draft",
-          "empty": "You have no messages.",
-        },
-        "hu_hu": {
-          "Messages": "Üzenetek",
-          "Inbox": "Beérkezett",
-          "Sent": "Elküldött",
-          "Trash": "Kuka",
-          "Draft": "Piszkozat",
-          "empty": "Nincsenek üzeneteid.",
-        },
-        "de_de": {
-          "Messages": "Nachrichten",
-          "Inbox": "Posteingang",
-          "Sent": "Gesendet",
-          "Trash": "Müll",
-          "Draft": "Entwurf",
-          "empty": "Sie haben keine Nachrichten.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Messages": "Messages",
+          "Inbox": "Inbox",
+          "Sent": "Sent",
+          "Trash": "Trash",
+          "Draft": "Draft",
+          "empty": "You have no messages.",
+        },
+        "hu_hu": {
+          "Messages": "Üzenetek",
+          "Inbox": "Beérkezett",
+          "Sent": "Elküldött",
+          "Trash": "Kuka",
+          "Draft": "Piszkozat",
+          "empty": "Nincsenek üzeneteid.",
+        },
+        "de_de": {
+          "Messages": "Nachrichten",
+          "Inbox": "Posteingang",
+          "Sent": "Gesendet",
+          "Trash": "Müll",
+          "Draft": "Entwurf",
+          "empty": "Sie haben keine Nachrichten.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart b/refilc_desktop_ui/lib/pages/timetable/timetable_page.dart
similarity index 93%
rename from filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart
rename to refilc_desktop_ui/lib/pages/timetable/timetable_page.dart
index 8d6e5fb..52f7846 100644
--- a/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart
+++ b/refilc_desktop_ui/lib/pages/timetable/timetable_page.dart
@@ -1,390 +1,390 @@
-import 'dart:math';
-import 'package:animations/animations.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
-import 'package:filcnaplo_desktop_ui/common/widgets/lesson/lesson_viewable.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:intl/intl.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'timetable_page.i18n.dart';
-
-// todo: "fix" overflow (priority: -1)
-
-class TimetablePage extends StatefulWidget {
-  const TimetablePage({Key? key, this.initialDay, this.initialWeek})
-      : super(key: key);
-
-  final DateTime? initialDay;
-  final Week? initialWeek;
-
-  static void jump(BuildContext context,
-      {Week? week, DateTime? day, Lesson? lesson}) {
-    // Go to timetable page with arguments
-    // NavigationScreen.of(context)?.customRoute(navigationPageRoute((context) => TimetablePage(
-    //       initialDay: lesson?.date ?? day,
-    //       initialWeek: lesson?.date != null
-    //           ? Week.fromDate(lesson!.date)
-    //           : day != null
-    //               ? Week.fromDate(day)
-    //               : week,
-    //     )));
-
-    // NavigationScreen.of(context)?.setPage("timetable");
-
-    // Show initial Lesson
-    // if (lesson != null) LessonView.show(lesson, context: context);
-  }
-
-  @override
-  _TimetablePageState createState() => _TimetablePageState();
-}
-
-class _TimetablePageState extends State<TimetablePage>
-    with TickerProviderStateMixin {
-  late UserProvider user;
-  late TimetableProvider timetableProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late TimetableController _controller;
-  late TabController _tabController;
-  late Widget empty;
-
-  int _getDayIndex(DateTime date) {
-    int index = 0;
-    if (_controller.days == null || (_controller.days?.isEmpty ?? true)) {
-      return index;
-    }
-
-    // find the first day with upcoming lessons
-    index = _controller.days!.indexWhere((day) => day.last.end.isAfter(date));
-    if (index == -1) index = 0; // fallback
-
-    return index;
-  }
-
-  // Update timetable on user change
-  Future<void> _userListener() async {
-    await Provider.of<KretaClient>(context, listen: false).refreshLogin();
-    if (mounted) _controller.jump(_controller.currentWeek, context: context);
-  }
-
-  @override
-  void initState() {
-    super.initState();
-
-    // Initalize controllers
-    _controller = TimetableController();
-    _tabController = TabController(length: 0, vsync: this, initialIndex: 0);
-
-    empty = Empty(subtitle: "empty".i18n);
-
-    bool initial = true;
-
-    // Only update the TabController on week changes
-    _controller.addListener(() {
-      if (_controller.days == null) return;
-      setState(() {
-        _tabController = TabController(
-          length: _controller.days!.length,
-          vsync: this,
-          initialIndex:
-              min(_tabController.index, max(_controller.days!.length - 1, 0)),
-        );
-
-        if (initial ||
-            _controller.previousWeekId != _controller.currentWeekId) {
-          _tabController
-              .animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
-        }
-        initial = false;
-
-        // Empty is updated once every week change
-        empty = Empty(subtitle: "empty".i18n);
-      });
-    });
-
-    if (mounted) {
-      if (widget.initialWeek != null) {
-        _controller.jump(widget.initialWeek!, context: context, initial: true);
-      } else {
-        _controller.jump(_controller.currentWeek,
-            context: context, initial: true, skip: true);
-      }
-    }
-    // Listen for user changes
-    user = Provider.of<UserProvider>(context, listen: false);
-    user.addListener(_userListener);
-  }
-
-  @override
-  void dispose() {
-    _tabController.dispose();
-    _controller.dispose();
-    user.removeListener(_userListener);
-    super.dispose();
-  }
-
-  String dayTitle(int index) {
-    // Sometimes when changing weeks really fast,
-    // controller.days might be null or won't include index
-    try {
-      return DateFormat("EEEE", I18n.of(context).locale.languageCode)
-          .format(_controller.days![index].first.date);
-    } catch (e) {
-      return "timetable".i18n;
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    timetableProvider = Provider.of<TimetableProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-
-    // First name
-    List<String> nameParts = user.name?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 18.0),
-        child: Column(
-          children: [
-            Expanded(
-              child: PageTransitionSwitcher(
-                transitionBuilder: (
-                  Widget child,
-                  Animation<double> primaryAnimation,
-                  Animation<double> secondaryAnimation,
-                ) {
-                  return FadeThroughTransition(
-                    child: child,
-                    animation: primaryAnimation,
-                    secondaryAnimation: secondaryAnimation,
-                    fillColor: Theme.of(context).scaffoldBackgroundColor,
-                  );
-                },
-                child: _controller.days != null
-                    ?
-                    // Week view
-                    _tabController.length > 0
-                        ? CupertinoScrollbar(
-                            child: ListView.builder(
-                              scrollDirection: Axis.horizontal,
-                              itemCount: _controller.days!.length,
-                              itemBuilder: (context, tab) => SizedBox(
-                                width: 400,
-                                child: Column(
-                                  crossAxisAlignment: CrossAxisAlignment.start,
-                                  children: [
-                                    // Day Title
-                                    Padding(
-                                      padding: const EdgeInsets.only(
-                                          left: 24.0,
-                                          right: 28.0,
-                                          top: 18.0,
-                                          bottom: 8.0),
-                                      child: Row(
-                                        mainAxisAlignment:
-                                            MainAxisAlignment.spaceBetween,
-                                        children: [
-                                          Text(
-                                            dayTitle(tab).capital(),
-                                            style: const TextStyle(
-                                              fontSize: 32.0,
-                                              fontWeight: FontWeight.w600,
-                                            ),
-                                          ),
-                                          Text(
-                                            "${_controller.days![tab].first.date.day}"
-                                                    .padLeft(2, '0') +
-                                                ".",
-                                            style: TextStyle(
-                                              color: AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(.5),
-                                              fontWeight: FontWeight.w500,
-                                            ),
-                                          ),
-                                        ],
-                                      ),
-                                    ),
-
-                                    // Lessons
-                                    Expanded(
-                                      child: ListView.builder(
-                                        padding: EdgeInsets.zero,
-                                        physics: const BouncingScrollPhysics(),
-                                        itemCount:
-                                            _controller.days![tab].length + 2,
-                                        itemBuilder: (context, index) {
-                                          if (_controller.days == null) {
-                                            return Container();
-                                          }
-
-                                          // Header
-                                          if (index == 0) {
-                                            return const Padding(
-                                              padding: EdgeInsets.only(
-                                                  top: 8.0,
-                                                  left: 24.0,
-                                                  right: 24.0),
-                                              child: PanelHeader(
-                                                  padding: EdgeInsets.only(
-                                                      top: 12.0)),
-                                            );
-                                          }
-
-                                          // Footer
-                                          if (index ==
-                                              _controller.days![tab].length +
-                                                  1) {
-                                            return const Padding(
-                                              padding: EdgeInsets.only(
-                                                  bottom: 8.0,
-                                                  left: 24.0,
-                                                  right: 24.0),
-                                              child: PanelFooter(
-                                                  padding: EdgeInsets.only(
-                                                      top: 12.0)),
-                                            );
-                                          }
-
-                                          // Body
-                                          final Lesson lesson =
-                                              _controller.days![tab][index - 1];
-                                          final bool swapDescDay = _controller
-                                                  .days![tab]
-                                                  .map(
-                                                      (l) => l.swapDesc ? 1 : 0)
-                                                  .reduce((a, b) => a + b) >=
-                                              _controller.days![tab].length *
-                                                  .5;
-
-                                          return Padding(
-                                            padding: const EdgeInsets.symmetric(
-                                                horizontal: 24.0),
-                                            child: PanelBody(
-                                              padding:
-                                                  const EdgeInsets.symmetric(
-                                                      horizontal: 10.0),
-                                              child: LessonViewable(
-                                                lesson,
-                                                swapDesc: swapDescDay,
-                                              ),
-                                            ),
-                                          );
-                                        },
-                                      ),
-                                    ),
-                                  ],
-                                ),
-                              ),
-                            ),
-                          )
-
-                        // Empty week
-                        : Expanded(
-                            child: Center(child: empty),
-                          )
-                    : Center(
-                        child: CircularProgressIndicator(
-                          color: Theme.of(context).colorScheme.secondary,
-                        ),
-                      ),
-              ),
-            ),
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
-              child: Row(
-                mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                children: [
-                  // Previous week
-                  IconButton(
-                      onPressed: _controller.currentWeekId == 0
-                          ? null
-                          : () => setState(() {
-                                _controller.previous(context);
-                              }),
-                      splashRadius: 24.0,
-                      icon: const Icon(FeatherIcons.chevronLeft),
-                      color: Theme.of(context).colorScheme.secondary),
-
-                  // Week selector
-                  InkWell(
-                    borderRadius: BorderRadius.circular(6.0),
-                    onTap: () => setState(() {
-                      _controller.current();
-                      if (mounted) {
-                        _controller.jump(_controller.currentWeek,
-                            context: context,
-                            loader: _controller.currentWeekId !=
-                                _controller.previousWeekId);
-                      }
-                    }),
-                    child: Padding(
-                      padding: const EdgeInsets.all(8.0),
-                      child: Text(
-                        "${_controller.currentWeekId + 1}. " +
-                            "week".i18n +
-                            " (" +
-                            // Week start
-                            DateFormat(
-                                    (_controller.currentWeek.start.year !=
-                                                DateTime.now().year
-                                            ? "yy. "
-                                            : "") +
-                                        "MMM d.",
-                                    I18n.of(context).locale.languageCode)
-                                .format(_controller.currentWeek.start) +
-                            " - " +
-                            // Week end
-                            DateFormat(
-                                    (_controller.currentWeek.start.year !=
-                                                DateTime.now().year
-                                            ? "yy. "
-                                            : "") +
-                                        "MMM d.",
-                                    I18n.of(context).locale.languageCode)
-                                .format(_controller.currentWeek.end) +
-                            ")",
-                        style: const TextStyle(
-                          fontWeight: FontWeight.w500,
-                          fontSize: 14.0,
-                        ),
-                      ),
-                    ),
-                  ),
-
-                  // Next week
-                  IconButton(
-                      onPressed: _controller.currentWeekId == 51
-                          ? null
-                          : () => setState(() {
-                                _controller.next(context);
-                              }),
-                      splashRadius: 24.0,
-                      icon: const Icon(FeatherIcons.chevronRight),
-                      color: Theme.of(context).colorScheme.secondary),
-                ],
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+import 'package:animations/animations.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
+import 'package:refilc_desktop_ui/common/widgets/lesson/lesson_viewable.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:intl/intl.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'timetable_page.i18n.dart';
+
+// todo: "fix" overflow (priority: -1)
+
+class TimetablePage extends StatefulWidget {
+  const TimetablePage({Key? key, this.initialDay, this.initialWeek})
+      : super(key: key);
+
+  final DateTime? initialDay;
+  final Week? initialWeek;
+
+  static void jump(BuildContext context,
+      {Week? week, DateTime? day, Lesson? lesson}) {
+    // Go to timetable page with arguments
+    // NavigationScreen.of(context)?.customRoute(navigationPageRoute((context) => TimetablePage(
+    //       initialDay: lesson?.date ?? day,
+    //       initialWeek: lesson?.date != null
+    //           ? Week.fromDate(lesson!.date)
+    //           : day != null
+    //               ? Week.fromDate(day)
+    //               : week,
+    //     )));
+
+    // NavigationScreen.of(context)?.setPage("timetable");
+
+    // Show initial Lesson
+    // if (lesson != null) LessonView.show(lesson, context: context);
+  }
+
+  @override
+  _TimetablePageState createState() => _TimetablePageState();
+}
+
+class _TimetablePageState extends State<TimetablePage>
+    with TickerProviderStateMixin {
+  late UserProvider user;
+  late TimetableProvider timetableProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late TimetableController _controller;
+  late TabController _tabController;
+  late Widget empty;
+
+  int _getDayIndex(DateTime date) {
+    int index = 0;
+    if (_controller.days == null || (_controller.days?.isEmpty ?? true)) {
+      return index;
+    }
+
+    // find the first day with upcoming lessons
+    index = _controller.days!.indexWhere((day) => day.last.end.isAfter(date));
+    if (index == -1) index = 0; // fallback
+
+    return index;
+  }
+
+  // Update timetable on user change
+  Future<void> _userListener() async {
+    await Provider.of<KretaClient>(context, listen: false).refreshLogin();
+    if (mounted) _controller.jump(_controller.currentWeek, context: context);
+  }
+
+  @override
+  void initState() {
+    super.initState();
+
+    // Initalize controllers
+    _controller = TimetableController();
+    _tabController = TabController(length: 0, vsync: this, initialIndex: 0);
+
+    empty = Empty(subtitle: "empty".i18n);
+
+    bool initial = true;
+
+    // Only update the TabController on week changes
+    _controller.addListener(() {
+      if (_controller.days == null) return;
+      setState(() {
+        _tabController = TabController(
+          length: _controller.days!.length,
+          vsync: this,
+          initialIndex:
+              min(_tabController.index, max(_controller.days!.length - 1, 0)),
+        );
+
+        if (initial ||
+            _controller.previousWeekId != _controller.currentWeekId) {
+          _tabController
+              .animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
+        }
+        initial = false;
+
+        // Empty is updated once every week change
+        empty = Empty(subtitle: "empty".i18n);
+      });
+    });
+
+    if (mounted) {
+      if (widget.initialWeek != null) {
+        _controller.jump(widget.initialWeek!, context: context, initial: true);
+      } else {
+        _controller.jump(_controller.currentWeek,
+            context: context, initial: true, skip: true);
+      }
+    }
+    // Listen for user changes
+    user = Provider.of<UserProvider>(context, listen: false);
+    user.addListener(_userListener);
+  }
+
+  @override
+  void dispose() {
+    _tabController.dispose();
+    _controller.dispose();
+    user.removeListener(_userListener);
+    super.dispose();
+  }
+
+  String dayTitle(int index) {
+    // Sometimes when changing weeks really fast,
+    // controller.days might be null or won't include index
+    try {
+      return DateFormat("EEEE", I18n.of(context).locale.languageCode)
+          .format(_controller.days![index].first.date);
+    } catch (e) {
+      return "timetable".i18n;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    timetableProvider = Provider.of<TimetableProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+
+    // First name
+    List<String> nameParts = user.name?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 18.0),
+        child: Column(
+          children: [
+            Expanded(
+              child: PageTransitionSwitcher(
+                transitionBuilder: (
+                  Widget child,
+                  Animation<double> primaryAnimation,
+                  Animation<double> secondaryAnimation,
+                ) {
+                  return FadeThroughTransition(
+                    child: child,
+                    animation: primaryAnimation,
+                    secondaryAnimation: secondaryAnimation,
+                    fillColor: Theme.of(context).scaffoldBackgroundColor,
+                  );
+                },
+                child: _controller.days != null
+                    ?
+                    // Week view
+                    _tabController.length > 0
+                        ? CupertinoScrollbar(
+                            child: ListView.builder(
+                              scrollDirection: Axis.horizontal,
+                              itemCount: _controller.days!.length,
+                              itemBuilder: (context, tab) => SizedBox(
+                                width: 400,
+                                child: Column(
+                                  crossAxisAlignment: CrossAxisAlignment.start,
+                                  children: [
+                                    // Day Title
+                                    Padding(
+                                      padding: const EdgeInsets.only(
+                                          left: 24.0,
+                                          right: 28.0,
+                                          top: 18.0,
+                                          bottom: 8.0),
+                                      child: Row(
+                                        mainAxisAlignment:
+                                            MainAxisAlignment.spaceBetween,
+                                        children: [
+                                          Text(
+                                            dayTitle(tab).capital(),
+                                            style: const TextStyle(
+                                              fontSize: 32.0,
+                                              fontWeight: FontWeight.w600,
+                                            ),
+                                          ),
+                                          Text(
+                                            "${_controller.days![tab].first.date.day}"
+                                                    .padLeft(2, '0') +
+                                                ".",
+                                            style: TextStyle(
+                                              color: AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.5),
+                                              fontWeight: FontWeight.w500,
+                                            ),
+                                          ),
+                                        ],
+                                      ),
+                                    ),
+
+                                    // Lessons
+                                    Expanded(
+                                      child: ListView.builder(
+                                        padding: EdgeInsets.zero,
+                                        physics: const BouncingScrollPhysics(),
+                                        itemCount:
+                                            _controller.days![tab].length + 2,
+                                        itemBuilder: (context, index) {
+                                          if (_controller.days == null) {
+                                            return Container();
+                                          }
+
+                                          // Header
+                                          if (index == 0) {
+                                            return const Padding(
+                                              padding: EdgeInsets.only(
+                                                  top: 8.0,
+                                                  left: 24.0,
+                                                  right: 24.0),
+                                              child: PanelHeader(
+                                                  padding: EdgeInsets.only(
+                                                      top: 12.0)),
+                                            );
+                                          }
+
+                                          // Footer
+                                          if (index ==
+                                              _controller.days![tab].length +
+                                                  1) {
+                                            return const Padding(
+                                              padding: EdgeInsets.only(
+                                                  bottom: 8.0,
+                                                  left: 24.0,
+                                                  right: 24.0),
+                                              child: PanelFooter(
+                                                  padding: EdgeInsets.only(
+                                                      top: 12.0)),
+                                            );
+                                          }
+
+                                          // Body
+                                          final Lesson lesson =
+                                              _controller.days![tab][index - 1];
+                                          final bool swapDescDay = _controller
+                                                  .days![tab]
+                                                  .map(
+                                                      (l) => l.swapDesc ? 1 : 0)
+                                                  .reduce((a, b) => a + b) >=
+                                              _controller.days![tab].length *
+                                                  .5;
+
+                                          return Padding(
+                                            padding: const EdgeInsets.symmetric(
+                                                horizontal: 24.0),
+                                            child: PanelBody(
+                                              padding:
+                                                  const EdgeInsets.symmetric(
+                                                      horizontal: 10.0),
+                                              child: LessonViewable(
+                                                lesson,
+                                                swapDesc: swapDescDay,
+                                              ),
+                                            ),
+                                          );
+                                        },
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            ),
+                          )
+
+                        // Empty week
+                        : Expanded(
+                            child: Center(child: empty),
+                          )
+                    : Center(
+                        child: CircularProgressIndicator(
+                          color: Theme.of(context).colorScheme.secondary,
+                        ),
+                      ),
+              ),
+            ),
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  // Previous week
+                  IconButton(
+                      onPressed: _controller.currentWeekId == 0
+                          ? null
+                          : () => setState(() {
+                                _controller.previous(context);
+                              }),
+                      splashRadius: 24.0,
+                      icon: const Icon(FeatherIcons.chevronLeft),
+                      color: Theme.of(context).colorScheme.secondary),
+
+                  // Week selector
+                  InkWell(
+                    borderRadius: BorderRadius.circular(6.0),
+                    onTap: () => setState(() {
+                      _controller.current();
+                      if (mounted) {
+                        _controller.jump(_controller.currentWeek,
+                            context: context,
+                            loader: _controller.currentWeekId !=
+                                _controller.previousWeekId);
+                      }
+                    }),
+                    child: Padding(
+                      padding: const EdgeInsets.all(8.0),
+                      child: Text(
+                        "${_controller.currentWeekId + 1}. " +
+                            "week".i18n +
+                            " (" +
+                            // Week start
+                            DateFormat(
+                                    (_controller.currentWeek.start.year !=
+                                                DateTime.now().year
+                                            ? "yy. "
+                                            : "") +
+                                        "MMM d.",
+                                    I18n.of(context).locale.languageCode)
+                                .format(_controller.currentWeek.start) +
+                            " - " +
+                            // Week end
+                            DateFormat(
+                                    (_controller.currentWeek.start.year !=
+                                                DateTime.now().year
+                                            ? "yy. "
+                                            : "") +
+                                        "MMM d.",
+                                    I18n.of(context).locale.languageCode)
+                                .format(_controller.currentWeek.end) +
+                            ")",
+                        style: const TextStyle(
+                          fontWeight: FontWeight.w500,
+                          fontSize: 14.0,
+                        ),
+                      ),
+                    ),
+                  ),
+
+                  // Next week
+                  IconButton(
+                      onPressed: _controller.currentWeekId == 51
+                          ? null
+                          : () => setState(() {
+                                _controller.next(context);
+                              }),
+                      splashRadius: 24.0,
+                      icon: const Icon(FeatherIcons.chevronRight),
+                      color: Theme.of(context).colorScheme.secondary),
+                ],
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.i18n.dart b/refilc_desktop_ui/lib/pages/timetable/timetable_page.i18n.dart
similarity index 97%
rename from filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.i18n.dart
rename to refilc_desktop_ui/lib/pages/timetable/timetable_page.i18n.dart
index 21eaa51..75d3bd0 100644
--- a/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.i18n.dart
+++ b/refilc_desktop_ui/lib/pages/timetable/timetable_page.i18n.dart
@@ -1,30 +1,30 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "timetable": "Timetable",
-          "empty": "No school this week!",
-          "week": "Week",
-          "error": "Failed to fetch timetable!",
-        },
-        "hu_hu": {
-          "timetable": "Órarend",
-          "empty": "Ezen a héten nincs iskola.",
-          "week": "Hét",
-          "error": "Nem sikerült lekérni az órarendet!",
-        },
-        "de_de": {
-          "timetable": "Zeitplan",
-          "empty": "Keine Schule diese Woche.",
-          "week": "Woche",
-          "error": "Der Fahrplan konnte nicht abgerufen werden!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "timetable": "Timetable",
+          "empty": "No school this week!",
+          "week": "Week",
+          "error": "Failed to fetch timetable!",
+        },
+        "hu_hu": {
+          "timetable": "Órarend",
+          "empty": "Ezen a héten nincs iskola.",
+          "week": "Hét",
+          "error": "Nem sikerült lekérni az órarendet!",
+        },
+        "de_de": {
+          "timetable": "Zeitplan",
+          "empty": "Keine Schule diese Woche.",
+          "week": "Woche",
+          "error": "Der Fahrplan konnte nicht abgerufen werden!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/login/login_route.dart b/refilc_desktop_ui/lib/screens/login/login_route.dart
similarity index 96%
rename from filcnaplo_desktop_ui/lib/screens/login/login_route.dart
rename to refilc_desktop_ui/lib/screens/login/login_route.dart
index 9ef1ea6..f6f5452 100644
--- a/filcnaplo_desktop_ui/lib/screens/login/login_route.dart
+++ b/refilc_desktop_ui/lib/screens/login/login_route.dart
@@ -1,17 +1,17 @@
-import 'package:animations/animations.dart';
-import 'package:flutter/material.dart';
-
-Route loginRoute(Widget widget) {
-  return PageRouteBuilder(
-    pageBuilder: (context, animation, secondaryAnimation) => widget,
-    transitionDuration: const Duration(milliseconds: 650),
-    transitionsBuilder: (context, animation, secondaryAnimation, child) {
-      return FadeThroughTransition(
-        fillColor: Colors.transparent,
-        animation: animation,
-        secondaryAnimation: secondaryAnimation,
-        child: child,
-      );
-    },
-  );
-}
+import 'package:animations/animations.dart';
+import 'package:flutter/material.dart';
+
+Route loginRoute(Widget widget) {
+  return PageRouteBuilder(
+    pageBuilder: (context, animation, secondaryAnimation) => widget,
+    transitionDuration: const Duration(milliseconds: 650),
+    transitionsBuilder: (context, animation, secondaryAnimation, child) {
+      return FadeThroughTransition(
+        fillColor: Colors.transparent,
+        animation: animation,
+        secondaryAnimation: secondaryAnimation,
+        child: child,
+      );
+    },
+  );
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/login/login_screen.dart b/refilc_desktop_ui/lib/screens/login/login_screen.dart
similarity index 95%
rename from filcnaplo_desktop_ui/lib/screens/login/login_screen.dart
rename to refilc_desktop_ui/lib/screens/login/login_screen.dart
index ad398be..5762c5c 100644
--- a/filcnaplo_desktop_ui/lib/screens/login/login_screen.dart
+++ b/refilc_desktop_ui/lib/screens/login/login_screen.dart
@@ -1,358 +1,358 @@
-import 'dart:io';
-import 'dart:ui';
-
-import 'package:elegant_notification/elegant_notification.dart';
-import 'package:elegant_notification/resources/arrays.dart';
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/api/login.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/login_button.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_acrylic/flutter_acrylic.dart';
-import 'login_screen.i18n.dart';
-
-const LinearGradient _backgroundGradient = LinearGradient(
-  colors: [
-    Color.fromARGB(255, 61, 122, 244),
-    Color.fromARGB(255, 23, 77, 185),
-    Color.fromARGB(255, 7, 42, 112),
-  ],
-  begin: Alignment(-0.8, -2.0),
-  end: Alignment(0.8, 1.0),
-  stops: [-1.0, 0.0, 1.0],
-);
-
-class LoginScreen extends StatefulWidget {
-  const LoginScreen({Key? key, this.back = false}) : super(key: key);
-
-  final bool back;
-
-  @override
-  _LoginScreenState createState() => _LoginScreenState();
-}
-
-class _LoginScreenState extends State<LoginScreen> {
-  final usernameController = TextEditingController();
-  final passwordController = TextEditingController();
-  final schoolController = SchoolInputController();
-  final _scrollController = ScrollController();
-
-  LoginState _loginState = LoginState.normal;
-  bool showBack = false;
-  double topInset = 12.0;
-
-  @override
-  void initState() {
-    super.initState();
-    showBack = widget.back;
-
-    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
-      statusBarColor: Colors.transparent,
-      statusBarIconBrightness: Brightness.light,
-      systemNavigationBarColor: Colors.white,
-      systemNavigationBarIconBrightness: Brightness.dark,
-    ));
-
-    FilcAPI.getSchools().then((schools) {
-      if (schools != null) {
-        schoolController.update(() {
-          schoolController.schools = schools;
-        });
-      } else {
-        ElegantNotification.error(
-          background: Colors.white,
-          description: Text(
-            "schools_error".i18n,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(color: Colors.red),
-          ),
-          onActionPressed: () {},
-          onCloseButtonPressed: () {},
-          onDismiss: () {},
-          onProgressFinished: () {},
-          displayCloseButton: false,
-          showProgressIndicator: false,
-          autoDismiss: true,
-          animation: AnimationType.fromTop,
-        ).show(context);
-      }
-    });
-
-    if (Platform.isMacOS) {
-      Window.getTitlebarHeight()
-          .then((value) => setState(() => topInset = value));
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Container(
-        decoration: const BoxDecoration(
-          gradient: _backgroundGradient,
-        ),
-        child: SafeArea(
-          child: Stack(
-            children: [
-              Row(
-                children: [
-                  Expanded(
-                    child: Column(
-                      mainAxisAlignment: MainAxisAlignment.center,
-                      children: [
-                        // App logo
-                        Padding(
-                          padding: const EdgeInsets.only(bottom: 24.0),
-                          child: ClipRect(
-                            child: Padding(
-                              padding: const EdgeInsets.only(
-                                  left: 12.0, right: 12.0, bottom: 32.0),
-                              child: SizedBox(
-                                width: 100.0,
-                                height: 100.0,
-                                // Png shadow *hack*
-                                child: Stack(
-                                  children: [
-                                    Padding(
-                                      padding: const EdgeInsets.only(top: 8.0),
-                                      child: Opacity(
-                                          child: Image.asset(
-                                              "assets/icons/ic_splash.png",
-                                              color: Colors.black),
-                                          opacity: 0.3),
-                                    ),
-                                    BackdropFilter(
-                                      filter: ImageFilter.blur(
-                                          sigmaX: 6.0, sigmaY: 6.0),
-                                      child: Image.asset(
-                                          "assets/icons/ic_splash.png"),
-                                    )
-                                  ],
-                                ),
-                              ),
-                            ),
-                          ),
-                        ),
-
-                        // Inputs
-                        SizedBox(
-                          width: 400.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: const TextStyle(
-                                            color: Colors.white,
-                                            fontWeight: FontWeight.w600,
-                                            fontSize: 14.0,
-                                          ),
-                                        ),
-                                      ),
-                                      Expanded(
-                                        child: Text(
-                                          "usernameHint".i18n,
-                                          maxLines: 1,
-                                          textAlign: TextAlign.right,
-                                          style: const TextStyle(
-                                            color: Colors.white54,
-                                            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: const TextStyle(
-                                            color: Colors.white,
-                                            fontWeight: FontWeight.w600,
-                                            fontSize: 14.0,
-                                          ),
-                                        ),
-                                      ),
-                                      Expanded(
-                                        child: Text(
-                                          "passwordHint".i18n,
-                                          maxLines: 1,
-                                          textAlign: TextAlign.right,
-                                          style: const TextStyle(
-                                            color: Colors.white54,
-                                            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: const TextStyle(
-                                      color: Colors.white,
-                                      fontWeight: FontWeight.w600,
-                                      fontSize: 14.0,
-                                    ),
-                                  ),
-                                ),
-                                SchoolInput(
-                                  scroll: _scrollController,
-                                  controller: schoolController,
-                                ),
-                              ],
-                            ),
-                          ),
-                        ),
-
-                        // Log in button
-                        SizedBox(
-                          width: 400.0,
-                          child: Padding(
-                            padding: const EdgeInsets.only(top: 42.0),
-                            child: Visibility(
-                              child: LoginButton(
-                                child: Text("login".i18n,
-                                    maxLines: 1,
-                                    style: const TextStyle(
-                                      fontWeight: FontWeight.w600,
-                                      fontSize: 15.0,
-                                    )),
-                                onPressed: () => _loginAPI(context: context),
-                              ),
-                              visible: _loginState != LoginState.inProgress,
-                              replacement: const Padding(
-                                padding: EdgeInsets.symmetric(vertical: 6.0),
-                                child: Center(
-                                  child: CircularProgressIndicator(
-                                    valueColor: AlwaysStoppedAnimation<Color>(
-                                        Colors.white),
-                                  ),
-                                ),
-                              ),
-                            ),
-                          ),
-                        ),
-                        if (_loginState == LoginState.missingFields ||
-                            _loginState == LoginState.invalidGrant ||
-                            _loginState == LoginState.failed)
-                          Padding(
-                            padding: const EdgeInsets.only(top: 8.0),
-                            child: Text(
-                              [
-                                "missing_fields",
-                                "invalid_grant",
-                                "error"
-                              ][_loginState.index]
-                                  .i18n,
-                              style: const TextStyle(
-                                  color: Colors.red,
-                                  fontWeight: FontWeight.w500),
-                            ),
-                          ),
-                      ],
-                    ),
-                  ),
-                ],
-              ),
-              if (showBack)
-                Container(
-                  alignment: Alignment.topLeft,
-                  padding: EdgeInsets.only(left: 16.0, top: topInset),
-                  child: const ClipOval(
-                    child: Material(
-                      type: MaterialType.transparency,
-                      child: BackButton(color: Colors.white),
-                    ),
-                  ),
-                ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-
-  void _loginAPI({required BuildContext context}) {
-    String username = usernameController.text;
-    String password = passwordController.text;
-
-    if (username == "" ||
-        password == "" ||
-        schoolController.selectedSchool == null) {
-      return setState(() => _loginState = LoginState.missingFields);
-    }
-
-    setState(() => _loginState = LoginState.inProgress);
-
-    loginAPI(
-        username: username,
-        password: password,
-        instituteCode: schoolController.selectedSchool!.instituteCode,
-        context: context,
-        onLogin: (user) {
-          ElegantNotification.success(
-            background: Colors.white,
-            description: Text(
-              "welcome".i18n.fill([user.name]),
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(color: Colors.black),
-            ),
-            onActionPressed: () {},
-            onCloseButtonPressed: () {},
-            onDismiss: () {},
-            onProgressFinished: () {},
-            displayCloseButton: false,
-            showProgressIndicator: false,
-            autoDismiss: true,
-            animation: AnimationType.fromTop,
-          ).show(context);
-        },
-        onSuccess: () {
-          Navigator.of(context)
-              .pushNamedAndRemoveUntil("login_to_navigation", (_) => false);
-        }).then((res) => setState(() => _loginState = res));
-  }
-}
+import 'dart:io';
+import 'dart:ui';
+
+import 'package:elegant_notification/elegant_notification.dart';
+import 'package:elegant_notification/resources/arrays.dart';
+import 'package:refilc/api/client.dart';
+import 'package:refilc/api/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:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_acrylic/flutter_acrylic.dart';
+import 'login_screen.i18n.dart';
+
+const LinearGradient _backgroundGradient = LinearGradient(
+  colors: [
+    Color.fromARGB(255, 61, 122, 244),
+    Color.fromARGB(255, 23, 77, 185),
+    Color.fromARGB(255, 7, 42, 112),
+  ],
+  begin: Alignment(-0.8, -2.0),
+  end: Alignment(0.8, 1.0),
+  stops: [-1.0, 0.0, 1.0],
+);
+
+class LoginScreen extends StatefulWidget {
+  const LoginScreen({Key? key, this.back = false}) : super(key: key);
+
+  final bool back;
+
+  @override
+  _LoginScreenState createState() => _LoginScreenState();
+}
+
+class _LoginScreenState extends State<LoginScreen> {
+  final usernameController = TextEditingController();
+  final passwordController = TextEditingController();
+  final schoolController = SchoolInputController();
+  final _scrollController = ScrollController();
+
+  LoginState _loginState = LoginState.normal;
+  bool showBack = false;
+  double topInset = 12.0;
+
+  @override
+  void initState() {
+    super.initState();
+    showBack = widget.back;
+
+    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
+      statusBarColor: Colors.transparent,
+      statusBarIconBrightness: Brightness.light,
+      systemNavigationBarColor: Colors.white,
+      systemNavigationBarIconBrightness: Brightness.dark,
+    ));
+
+    FilcAPI.getSchools().then((schools) {
+      if (schools != null) {
+        schoolController.update(() {
+          schoolController.schools = schools;
+        });
+      } else {
+        ElegantNotification.error(
+          background: Colors.white,
+          description: Text(
+            "schools_error".i18n,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(color: Colors.red),
+          ),
+          onActionPressed: () {},
+          onCloseButtonPressed: () {},
+          onDismiss: () {},
+          onProgressFinished: () {},
+          displayCloseButton: false,
+          showProgressIndicator: false,
+          autoDismiss: true,
+          animation: AnimationType.fromTop,
+        ).show(context);
+      }
+    });
+
+    if (Platform.isMacOS) {
+      Window.getTitlebarHeight()
+          .then((value) => setState(() => topInset = value));
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      body: Container(
+        decoration: const BoxDecoration(
+          gradient: _backgroundGradient,
+        ),
+        child: SafeArea(
+          child: Stack(
+            children: [
+              Row(
+                children: [
+                  Expanded(
+                    child: Column(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: [
+                        // App logo
+                        Padding(
+                          padding: const EdgeInsets.only(bottom: 24.0),
+                          child: ClipRect(
+                            child: Padding(
+                              padding: const EdgeInsets.only(
+                                  left: 12.0, right: 12.0, bottom: 32.0),
+                              child: SizedBox(
+                                width: 100.0,
+                                height: 100.0,
+                                // Png shadow *hack*
+                                child: Stack(
+                                  children: [
+                                    Padding(
+                                      padding: const EdgeInsets.only(top: 8.0),
+                                      child: Opacity(
+                                          child: Image.asset(
+                                              "assets/icons/ic_splash.png",
+                                              color: Colors.black),
+                                          opacity: 0.3),
+                                    ),
+                                    BackdropFilter(
+                                      filter: ImageFilter.blur(
+                                          sigmaX: 6.0, sigmaY: 6.0),
+                                      child: Image.asset(
+                                          "assets/icons/ic_splash.png"),
+                                    )
+                                  ],
+                                ),
+                              ),
+                            ),
+                          ),
+                        ),
+
+                        // Inputs
+                        SizedBox(
+                          width: 400.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: const TextStyle(
+                                            color: Colors.white,
+                                            fontWeight: FontWeight.w600,
+                                            fontSize: 14.0,
+                                          ),
+                                        ),
+                                      ),
+                                      Expanded(
+                                        child: Text(
+                                          "usernameHint".i18n,
+                                          maxLines: 1,
+                                          textAlign: TextAlign.right,
+                                          style: const TextStyle(
+                                            color: Colors.white54,
+                                            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: const TextStyle(
+                                            color: Colors.white,
+                                            fontWeight: FontWeight.w600,
+                                            fontSize: 14.0,
+                                          ),
+                                        ),
+                                      ),
+                                      Expanded(
+                                        child: Text(
+                                          "passwordHint".i18n,
+                                          maxLines: 1,
+                                          textAlign: TextAlign.right,
+                                          style: const TextStyle(
+                                            color: Colors.white54,
+                                            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: const TextStyle(
+                                      color: Colors.white,
+                                      fontWeight: FontWeight.w600,
+                                      fontSize: 14.0,
+                                    ),
+                                  ),
+                                ),
+                                SchoolInput(
+                                  scroll: _scrollController,
+                                  controller: schoolController,
+                                ),
+                              ],
+                            ),
+                          ),
+                        ),
+
+                        // Log in button
+                        SizedBox(
+                          width: 400.0,
+                          child: Padding(
+                            padding: const EdgeInsets.only(top: 42.0),
+                            child: Visibility(
+                              child: LoginButton(
+                                child: Text("login".i18n,
+                                    maxLines: 1,
+                                    style: const TextStyle(
+                                      fontWeight: FontWeight.w600,
+                                      fontSize: 15.0,
+                                    )),
+                                onPressed: () => _loginAPI(context: context),
+                              ),
+                              visible: _loginState != LoginState.inProgress,
+                              replacement: const Padding(
+                                padding: EdgeInsets.symmetric(vertical: 6.0),
+                                child: Center(
+                                  child: CircularProgressIndicator(
+                                    valueColor: AlwaysStoppedAnimation<Color>(
+                                        Colors.white),
+                                  ),
+                                ),
+                              ),
+                            ),
+                          ),
+                        ),
+                        if (_loginState == LoginState.missingFields ||
+                            _loginState == LoginState.invalidGrant ||
+                            _loginState == LoginState.failed)
+                          Padding(
+                            padding: const EdgeInsets.only(top: 8.0),
+                            child: Text(
+                              [
+                                "missing_fields",
+                                "invalid_grant",
+                                "error"
+                              ][_loginState.index]
+                                  .i18n,
+                              style: const TextStyle(
+                                  color: Colors.red,
+                                  fontWeight: FontWeight.w500),
+                            ),
+                          ),
+                      ],
+                    ),
+                  ),
+                ],
+              ),
+              if (showBack)
+                Container(
+                  alignment: Alignment.topLeft,
+                  padding: EdgeInsets.only(left: 16.0, top: topInset),
+                  child: const ClipOval(
+                    child: Material(
+                      type: MaterialType.transparency,
+                      child: BackButton(color: Colors.white),
+                    ),
+                  ),
+                ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  void _loginAPI({required BuildContext context}) {
+    String username = usernameController.text;
+    String password = passwordController.text;
+
+    if (username == "" ||
+        password == "" ||
+        schoolController.selectedSchool == null) {
+      return setState(() => _loginState = LoginState.missingFields);
+    }
+
+    setState(() => _loginState = LoginState.inProgress);
+
+    loginAPI(
+        username: username,
+        password: password,
+        instituteCode: schoolController.selectedSchool!.instituteCode,
+        context: context,
+        onLogin: (user) {
+          ElegantNotification.success(
+            background: Colors.white,
+            description: Text(
+              "welcome".i18n.fill([user.name]),
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(color: Colors.black),
+            ),
+            onActionPressed: () {},
+            onCloseButtonPressed: () {},
+            onDismiss: () {},
+            onProgressFinished: () {},
+            displayCloseButton: false,
+            showProgressIndicator: false,
+            autoDismiss: true,
+            animation: AnimationType.fromTop,
+          ).show(context);
+        },
+        onSuccess: () {
+          Navigator.of(context)
+              .pushNamedAndRemoveUntil("login_to_navigation", (_) => false);
+        }).then((res) => setState(() => _loginState = res));
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/login/login_screen.i18n.dart b/refilc_desktop_ui/lib/screens/login/login_screen.i18n.dart
similarity index 97%
rename from filcnaplo_desktop_ui/lib/screens/login/login_screen.i18n.dart
rename to refilc_desktop_ui/lib/screens/login/login_screen.i18n.dart
index bcbeace..f463081 100644
--- a/filcnaplo_desktop_ui/lib/screens/login/login_screen.i18n.dart
+++ b/refilc_desktop_ui/lib/screens/login/login_screen.i18n.dart
@@ -1,51 +1,51 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "username": "Username",
-          "usernameHint": "Student ID number",
-          "password": "Password",
-          "passwordHint": "Date of birth",
-          "school": "School",
-          "login": "Log in",
-          "welcome": "Welcome, %s!",
-          "missing_fields": "Missing Fields!",
-          "invalid_grant": "Invalid Username/Password!",
-          "error": "Failed to log in.",
-          "schools_error": "Failed to get schools."
-        },
-        "hu_hu": {
-          "username": "Felhasználónév",
-          "usernameHint": "Oktatási azonosító",
-          "password": "Jelszó",
-          "passwordHint": "Születési dátum",
-          "school": "Iskola",
-          "login": "Belépés",
-          "welcome": "Üdv, %s!",
-          "missing_fields": "Hiányzó adatok!",
-          "invalid_grant": "Helytelen Felhasználónév/Jelszó!",
-          "error": "Sikertelen bejelentkezés.",
-          "schools_error": "Nem sikerült lekérni az iskolákat."
-        },
-        "de_de": {
-          "username": "Benutzername",
-          "usernameHint": "Ausbildung ID",
-          "password": "Passwort",
-          "passwordHint": "Geburtsdatum",
-          "school": "Schule",
-          "login": "Einloggen",
-          "welcome": "Wilkommen, %s!",
-          "missing_fields": "Fehlende Felder!",
-          "invalid_grant": "Ungültiger Benutzername/Passwort!",
-          "error": "Anmeldung fehlgeschlagen.",
-          "schools_error": "Keine Schulen gefunden."
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "username": "Username",
+          "usernameHint": "Student ID number",
+          "password": "Password",
+          "passwordHint": "Date of birth",
+          "school": "School",
+          "login": "Log in",
+          "welcome": "Welcome, %s!",
+          "missing_fields": "Missing Fields!",
+          "invalid_grant": "Invalid Username/Password!",
+          "error": "Failed to log in.",
+          "schools_error": "Failed to get schools."
+        },
+        "hu_hu": {
+          "username": "Felhasználónév",
+          "usernameHint": "Oktatási azonosító",
+          "password": "Jelszó",
+          "passwordHint": "Születési dátum",
+          "school": "Iskola",
+          "login": "Belépés",
+          "welcome": "Üdv, %s!",
+          "missing_fields": "Hiányzó adatok!",
+          "invalid_grant": "Helytelen Felhasználónév/Jelszó!",
+          "error": "Sikertelen bejelentkezés.",
+          "schools_error": "Nem sikerült lekérni az iskolákat."
+        },
+        "de_de": {
+          "username": "Benutzername",
+          "usernameHint": "Ausbildung ID",
+          "password": "Passwort",
+          "passwordHint": "Geburtsdatum",
+          "school": "Schule",
+          "login": "Einloggen",
+          "welcome": "Wilkommen, %s!",
+          "missing_fields": "Fehlende Felder!",
+          "invalid_grant": "Ungültiger Benutzername/Passwort!",
+          "error": "Anmeldung fehlgeschlagen.",
+          "schools_error": "Keine Schulen gefunden."
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/navigation_route.dart b/refilc_desktop_ui/lib/screens/navigation/navigation_route.dart
old mode 100755
new mode 100644
similarity index 94%
rename from filcnaplo_mobile_ui/lib/screens/navigation/navigation_route.dart
rename to refilc_desktop_ui/lib/screens/navigation/navigation_route.dart
index fc3d87f..79778aa
--- a/filcnaplo_mobile_ui/lib/screens/navigation/navigation_route.dart
+++ b/refilc_desktop_ui/lib/screens/navigation/navigation_route.dart
@@ -1,25 +1,25 @@
-class NavigationRoute {
-  late String _name;
-  late int _index;
-
-  final List<String> _internalPageMap = [
-    "home",
-    "grades",
-    "timetable",
-    "messages",
-    "absences",
-  ];
-
-  String get name => _name;
-  int get index => _index;
-
-  set name(String n) {
-    _name = n;
-    _index = _internalPageMap.indexOf(n);
-  }
-
-  set index(int i) {
-    _index = i;
-    _name = _internalPageMap.elementAt(i);
-  }
-}
+class NavigationRoute {
+  late String _name;
+  late int _index;
+
+  final List<String> _internalPageMap = [
+    "home",
+    "grades",
+    "timetable",
+    "messages",
+    "absences",
+  ];
+
+  String get name => _name;
+  int get index => _index;
+
+  set name(String n) {
+    _name = n;
+    _index = _internalPageMap.indexOf(n);
+  }
+
+  set index(int i) {
+    _index = i;
+    _name = _internalPageMap.elementAt(i);
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/navigation_route_handler.dart b/refilc_desktop_ui/lib/screens/navigation/navigation_route_handler.dart
similarity index 73%
rename from filcnaplo_desktop_ui/lib/screens/navigation/navigation_route_handler.dart
rename to refilc_desktop_ui/lib/screens/navigation/navigation_route_handler.dart
index 7193ffb..f7766d7 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/navigation_route_handler.dart
+++ b/refilc_desktop_ui/lib/screens/navigation/navigation_route_handler.dart
@@ -1,37 +1,37 @@
-import 'package:animations/animations.dart';
-import 'package:filcnaplo_desktop_ui/pages/absences/absences_page.dart';
-import 'package:filcnaplo_desktop_ui/pages/grades/grades_page.dart';
-import 'package:filcnaplo_desktop_ui/pages/home/home_page.dart';
-import 'package:filcnaplo_desktop_ui/pages/messages/messages_page.dart';
-import 'package:filcnaplo_desktop_ui/pages/timetable/timetable_page.dart';
-import 'package:flutter/material.dart';
-
-Route navigationRouteHandler(RouteSettings settings) {
-  switch (settings.name) {
-    case "grades":
-      return navigationPageRoute((context) => const GradesPage());
-    case "timetable":
-      return navigationPageRoute((context) => const TimetablePage());
-    case "messages":
-      return navigationPageRoute((context) => const MessagesPage());
-    case "absences":
-      return navigationPageRoute((context) => const AbsencesPage());
-    case "home":
-    default:
-      return navigationPageRoute((context) => const HomePage());
-  }
-}
-
-Route navigationPageRoute(Widget Function(BuildContext) builder) {
-  return PageRouteBuilder(
-    pageBuilder: (context, _, __) => builder(context),
-    transitionsBuilder: (context, animation, secondaryAnimation, child) {
-      return FadeThroughTransition(
-        fillColor: Theme.of(context).scaffoldBackgroundColor,
-        animation: animation,
-        secondaryAnimation: secondaryAnimation,
-        child: child,
-      );
-    },
-  );
-}
+import 'package:animations/animations.dart';
+import 'package:refilc_desktop_ui/pages/absences/absences_page.dart';
+import 'package:refilc_desktop_ui/pages/grades/grades_page.dart';
+import 'package:refilc_desktop_ui/pages/home/home_page.dart';
+import 'package:refilc_desktop_ui/pages/messages/messages_page.dart';
+import 'package:refilc_desktop_ui/pages/timetable/timetable_page.dart';
+import 'package:flutter/material.dart';
+
+Route navigationRouteHandler(RouteSettings settings) {
+  switch (settings.name) {
+    case "grades":
+      return navigationPageRoute((context) => const GradesPage());
+    case "timetable":
+      return navigationPageRoute((context) => const TimetablePage());
+    case "messages":
+      return navigationPageRoute((context) => const MessagesPage());
+    case "absences":
+      return navigationPageRoute((context) => const AbsencesPage());
+    case "home":
+    default:
+      return navigationPageRoute((context) => const HomePage());
+  }
+}
+
+Route navigationPageRoute(Widget Function(BuildContext) builder) {
+  return PageRouteBuilder(
+    pageBuilder: (context, _, __) => builder(context),
+    transitionsBuilder: (context, animation, secondaryAnimation, child) {
+      return FadeThroughTransition(
+        fillColor: Theme.of(context).scaffoldBackgroundColor,
+        animation: animation,
+        secondaryAnimation: secondaryAnimation,
+        child: child,
+      );
+    },
+  );
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/navigation_screen.dart b/refilc_desktop_ui/lib/screens/navigation/navigation_screen.dart
similarity index 85%
rename from filcnaplo_desktop_ui/lib/screens/navigation/navigation_screen.dart
rename to refilc_desktop_ui/lib/screens/navigation/navigation_screen.dart
index 58bd949..4eb248d 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/navigation_screen.dart
+++ b/refilc_desktop_ui/lib/screens/navigation/navigation_screen.dart
@@ -1,163 +1,163 @@
-import 'dart:io';
-
-import 'package:filcnaplo/api/providers/news_provider.dart';
-import 'package:filcnaplo/api/providers/sync.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/theme/observer.dart';
-import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_route.dart';
-import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_route_handler.dart';
-import 'package:filcnaplo_desktop_ui/screens/navigation/sidebar.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_acrylic/flutter_acrylic.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_premium/providers/goal_provider.dart';
-
-class NavigationScreen extends StatefulWidget {
-  const NavigationScreen({Key? key}) : super(key: key);
-
-  static NavigationScreenState? of(BuildContext context) =>
-      context.findAncestorStateOfType<NavigationScreenState>();
-
-  @override
-  State<NavigationScreen> createState() => NavigationScreenState();
-}
-
-class NavigationScreenState extends State<NavigationScreen>
-    with WidgetsBindingObserver {
-  final _navigatorState = GlobalKey<NavigatorState>();
-  late NavigationRoute selected;
-  late SettingsProvider settings;
-  late NewsProvider newsProvider;
-  late GoalProvider goalProvider;
-  double topInset = 0.0;
-
-  @override
-  void initState() {
-    super.initState();
-    settings = Provider.of<SettingsProvider>(context, listen: false);
-    selected = NavigationRoute();
-    selected.index = 0;
-
-    // add brightness observer
-    WidgetsBinding.instance.addObserver(this);
-
-    // set client User-Agent
-    Provider.of<KretaClient>(context, listen: false).userAgent =
-        settings.config.userAgent;
-
-    // get news
-    newsProvider = Provider.of<NewsProvider>(context, listen: false);
-    newsProvider.restore().then((value) => newsProvider.fetch());
-
-    // get goals
-    // goalProvider = Provider.of<GoalProvider>(context, listen: false);
-    // goalProvider.fetchDone();
-
-    // Initial sync
-    syncAll(context);
-
-    () async {
-      try {
-        await Window.initialize();
-      } catch (_) {}
-      // Transparent sidebar
-      await Window.setEffect(
-          effect: WindowEffect.acrylic,
-          color: Platform.isMacOS
-              ? Colors.transparent
-              : const Color.fromARGB(27, 27, 27, 27));
-
-      // todo: do for windows
-      if (Platform.isMacOS) {
-        topInset = await Window.getTitlebarHeight();
-        await Window.enableFullSizeContentView();
-        await Window.hideTitle();
-        await Window.makeTitlebarTransparent();
-      }
-    }();
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  @override
-  void didChangePlatformBrightness() {
-    if (settings.theme == ThemeMode.system) {
-      // ignore: deprecated_member_use
-      Brightness? brightness =
-          // ignore: deprecated_member_use
-          WidgetsBinding.instance.window.platformBrightness;
-      Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(
-          brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark);
-    }
-    super.didChangePlatformBrightness();
-  }
-
-  void setPage(String page) => setState(() => selected.name = page);
-
-  @override
-  Widget build(BuildContext context) {
-    settings = Provider.of<SettingsProvider>(context);
-    newsProvider = Provider.of<NewsProvider>(context);
-    goalProvider = Provider.of<GoalProvider>(context);
-
-    // show news / complete goals
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      if (newsProvider.show) {
-        newsProvider.lock();
-        // NewsView.show(newsProvider.news[newsProvider.state], context: context).then((value) => newsProvider.release());
-      }
-      if (goalProvider.hasDoneGoals) {
-        // to-do
-      }
-    });
-
-    return Scaffold(
-      backgroundColor: Colors.transparent,
-      body: Row(
-        children: [
-          if (_navigatorState.currentState != null)
-            Container(
-              decoration: BoxDecoration(
-                color:
-                    Theme.of(context).scaffoldBackgroundColor.withOpacity(.5),
-                border: Border(
-                    right: BorderSide(
-                        color: AppColors.of(context).shadow.withOpacity(.7),
-                        width: 1.0)),
-              ),
-              child: Padding(
-                padding: EdgeInsets.only(top: topInset),
-                child: Sidebar(
-                  navigator: _navigatorState.currentState!,
-                  selected: selected.name,
-                  onRouteChange: (name) => setPage(name),
-                ),
-              ),
-            ),
-          Expanded(
-            child: Container(
-              color: Theme.of(context).scaffoldBackgroundColor,
-              child: MediaQuery(
-                data: MediaQuery.of(context).copyWith(
-                  padding: EdgeInsets.only(top: topInset),
-                ),
-                child: Navigator(
-                  key: _navigatorState,
-                  initialRoute: selected.name,
-                  onGenerateRoute: (settings) =>
-                      navigationRouteHandler(settings),
-                ),
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'dart:io';
+
+import 'package:refilc/api/providers/news_provider.dart';
+import 'package:refilc/api/providers/sync.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/theme/observer.dart';
+import 'package:refilc_desktop_ui/screens/navigation/navigation_route.dart';
+import 'package:refilc_desktop_ui/screens/navigation/navigation_route_handler.dart';
+import 'package:refilc_desktop_ui/screens/navigation/sidebar.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_acrylic/flutter_acrylic.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_premium/providers/goal_provider.dart';
+
+class NavigationScreen extends StatefulWidget {
+  const NavigationScreen({Key? key}) : super(key: key);
+
+  static NavigationScreenState? of(BuildContext context) =>
+      context.findAncestorStateOfType<NavigationScreenState>();
+
+  @override
+  State<NavigationScreen> createState() => NavigationScreenState();
+}
+
+class NavigationScreenState extends State<NavigationScreen>
+    with WidgetsBindingObserver {
+  final _navigatorState = GlobalKey<NavigatorState>();
+  late NavigationRoute selected;
+  late SettingsProvider settings;
+  late NewsProvider newsProvider;
+  late GoalProvider goalProvider;
+  double topInset = 0.0;
+
+  @override
+  void initState() {
+    super.initState();
+    settings = Provider.of<SettingsProvider>(context, listen: false);
+    selected = NavigationRoute();
+    selected.index = 0;
+
+    // add brightness observer
+    WidgetsBinding.instance.addObserver(this);
+
+    // set client User-Agent
+    Provider.of<KretaClient>(context, listen: false).userAgent =
+        settings.config.userAgent;
+
+    // get news
+    newsProvider = Provider.of<NewsProvider>(context, listen: false);
+    newsProvider.restore().then((value) => newsProvider.fetch());
+
+    // get goals
+    // goalProvider = Provider.of<GoalProvider>(context, listen: false);
+    // goalProvider.fetchDone();
+
+    // Initial sync
+    syncAll(context);
+
+    () async {
+      try {
+        await Window.initialize();
+      } catch (_) {}
+      // Transparent sidebar
+      await Window.setEffect(
+          effect: WindowEffect.acrylic,
+          color: Platform.isMacOS
+              ? Colors.transparent
+              : const Color.fromARGB(27, 27, 27, 27));
+
+      // todo: do for windows
+      if (Platform.isMacOS) {
+        topInset = await Window.getTitlebarHeight();
+        await Window.enableFullSizeContentView();
+        await Window.hideTitle();
+        await Window.makeTitlebarTransparent();
+      }
+    }();
+  }
+
+  @override
+  void dispose() {
+    WidgetsBinding.instance.removeObserver(this);
+    super.dispose();
+  }
+
+  @override
+  void didChangePlatformBrightness() {
+    if (settings.theme == ThemeMode.system) {
+      // ignore: deprecated_member_use
+      Brightness? brightness =
+          // ignore: deprecated_member_use
+          WidgetsBinding.instance.window.platformBrightness;
+      Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(
+          brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark);
+    }
+    super.didChangePlatformBrightness();
+  }
+
+  void setPage(String page) => setState(() => selected.name = page);
+
+  @override
+  Widget build(BuildContext context) {
+    settings = Provider.of<SettingsProvider>(context);
+    newsProvider = Provider.of<NewsProvider>(context);
+    goalProvider = Provider.of<GoalProvider>(context);
+
+    // show news / complete goals
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      if (newsProvider.show) {
+        newsProvider.lock();
+        // NewsView.show(newsProvider.news[newsProvider.state], context: context).then((value) => newsProvider.release());
+      }
+      if (goalProvider.hasDoneGoals) {
+        // to-do
+      }
+    });
+
+    return Scaffold(
+      backgroundColor: Colors.transparent,
+      body: Row(
+        children: [
+          if (_navigatorState.currentState != null)
+            Container(
+              decoration: BoxDecoration(
+                color:
+                    Theme.of(context).scaffoldBackgroundColor.withOpacity(.5),
+                border: Border(
+                    right: BorderSide(
+                        color: AppColors.of(context).shadow.withOpacity(.7),
+                        width: 1.0)),
+              ),
+              child: Padding(
+                padding: EdgeInsets.only(top: topInset),
+                child: Sidebar(
+                  navigator: _navigatorState.currentState!,
+                  selected: selected.name,
+                  onRouteChange: (name) => setPage(name),
+                ),
+              ),
+            ),
+          Expanded(
+            child: Container(
+              color: Theme.of(context).scaffoldBackgroundColor,
+              child: MediaQuery(
+                data: MediaQuery.of(context).copyWith(
+                  padding: EdgeInsets.only(top: topInset),
+                ),
+                child: Navigator(
+                  key: _navigatorState,
+                  initialRoute: selected.name,
+                  onGenerateRoute: (settings) =>
+                      navigationRouteHandler(settings),
+                ),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart b/refilc_desktop_ui/lib/screens/navigation/sidebar.dart
similarity index 86%
rename from filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
rename to refilc_desktop_ui/lib/screens/navigation/sidebar.dart
index 1c0f5fa..639254f 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
+++ b/refilc_desktop_ui/lib/screens/navigation/sidebar.dart
@@ -1,348 +1,348 @@
-import 'package:animations/animations.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:filcnaplo_desktop_ui/common/panel_button.dart';
-import 'package:filcnaplo_desktop_ui/common/profile_image.dart';
-import 'package:filcnaplo_desktop_ui/screens/navigation/sidebar.i18n.dart';
-import 'package:filcnaplo_desktop_ui/screens/navigation/sidebar_action.dart';
-import 'package:filcnaplo_desktop_ui/screens/settings/settings_screen.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_tile.dart';
-import 'package:filcnaplo_kreta_api/client/client.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-
-class Sidebar extends StatefulWidget {
-  const Sidebar(
-      {Key? key,
-      required this.navigator,
-      required this.onRouteChange,
-      this.selected = "home"})
-      : super(key: key);
-
-  final NavigatorState navigator;
-  final String selected;
-  final Function(String) onRouteChange;
-
-  @override
-  State<Sidebar> createState() => _SidebarState();
-}
-
-class _SidebarState extends State<Sidebar> {
-  late UserProvider user;
-  late SettingsProvider settings;
-  late String firstName;
-
-  String topNav = "";
-  bool expandAccount = false;
-  List<Widget> accountTiles = [];
-
-  @override
-  void initState() {
-    super.initState();
-    user = Provider.of<UserProvider>(context, listen: false);
-  }
-
-  Future<void> restore() => Future.wait([
-        Provider.of<GradeProvider>(context, listen: false).restore(),
-        Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
-        Provider.of<ExamProvider>(context, listen: false).restore(),
-        Provider.of<HomeworkProvider>(context, listen: false).restore(),
-        Provider.of<MessageProvider>(context, listen: false).restore(),
-        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(),
-      ]);
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    settings = Provider.of<SettingsProvider>(context);
-
-    List<String> nameParts = user.name?.split(" ") ?? ["?"];
-    if (!settings.presentationMode) {
-      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-    } else {
-      firstName = "János";
-    }
-
-    List<Widget> pageWidgets = [
-      SidebarAction(
-        title: Text("Home".i18n),
-        icon: const Icon(FilcIcons.home),
-        selected: widget.selected == "home",
-        onTap: () {
-          if (widget.selected != "home") {
-            widget.navigator.pushReplacementNamed("home");
-            widget.onRouteChange("home");
-          }
-        },
-      ),
-      SidebarAction(
-        title: Text("Grades".i18n),
-        icon: const Icon(FeatherIcons.bookmark),
-        selected: widget.selected == "grades",
-        onTap: () {
-          if (widget.selected != "grades") {
-            widget.navigator.pushReplacementNamed("grades");
-            widget.onRouteChange("grades");
-          }
-        },
-      ),
-      SidebarAction(
-        title: Text("Timetable".i18n),
-        icon: const Icon(FeatherIcons.calendar),
-        selected: widget.selected == "timetable",
-        onTap: () {
-          if (widget.selected != "timetable") {
-            widget.navigator.pushReplacementNamed("timetable");
-            widget.onRouteChange("timetable");
-          }
-        },
-      ),
-      SidebarAction(
-        title: Text("Messages".i18n),
-        icon: const Icon(FeatherIcons.messageSquare),
-        selected: widget.selected == "messages",
-        onTap: () {
-          if (widget.selected != "messages") {
-            widget.navigator.pushReplacementNamed("messages");
-            widget.onRouteChange("messages");
-          }
-        },
-      ),
-      SidebarAction(
-        title: Text("Absences".i18n),
-        icon: const Icon(FeatherIcons.clock),
-        selected: widget.selected == "absences",
-        onTap: () {
-          if (widget.selected != "absences") {
-            widget.navigator.pushReplacementNamed("absences");
-            widget.onRouteChange("absences");
-          }
-        },
-      ),
-    ];
-
-    List<Widget> bottomActions = [
-      SidebarAction(
-        title: Text("Settings".i18n),
-        selected: true,
-        icon: const Icon(FeatherIcons.settings),
-        onTap: () {
-          if (topNav != "settings") {
-            widget.navigator
-                .push(CupertinoPageRoute(
-                    builder: (context) => const SettingsScreen()))
-                .then((value) => topNav = "");
-            topNav = "settings";
-          }
-        },
-      ),
-    ];
-
-    buildAccountTiles();
-
-    List<Widget> accountWidgets = [
-      Padding(
-        padding: const EdgeInsets.symmetric(horizontal: 12.0),
-        child: Column(children: accountTiles),
-      ),
-
-      // Account settings
-      PanelButton(
-        onPressed: () {
-          Navigator.of(context).pushNamed("login_back");
-        },
-        title: Text("adduser".i18n),
-        leading: const Icon(FeatherIcons.userPlus),
-      ),
-      PanelButton(
-        onPressed: () 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 other Users left, go back to LoginScreen
-          if (user.getUsers().isNotEmpty) {
-            user.setUser(user.getUsers().first.id);
-            restore().then((_) => user.setUser(user.getUsers().first.id));
-          } else {
-            Navigator.of(context)
-                .pushNamedAndRemoveUntil("login", (_) => false);
-          }
-        },
-        title: Text("logout".i18n),
-        leading: Icon(FeatherIcons.logOut, color: AppColors.of(context).red),
-      ),
-    ];
-
-    return SizedBox(
-      height: double.infinity,
-      width: 250.0,
-      child: Column(
-        children: [
-          Padding(
-            padding: const EdgeInsets.only(
-              left: 12.0,
-              top: 18.0,
-              bottom: 24.0,
-              right: 12.0,
-            ),
-            child: InkWell(
-              customBorder: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(10)),
-              onTap: () {
-                setState(() {
-                  expandAccount = !expandAccount;
-                });
-              },
-              child: Row(
-                children: [
-                  Padding(
-                    padding: const EdgeInsets.only(
-                      right: 12.0,
-                      left: 5.0,
-                      top: 5.0,
-                      bottom: 5.0,
-                    ),
-                    child: ProfileImage(
-                      name: firstName,
-                      radius: 18.0,
-                      backgroundColor: Theme.of(context)
-                          .colorScheme
-                          .primary, //!settings.presentationMode
-                      //     ? ColorUtils.stringToColor(user.name ?? "?")
-                      //     : Theme.of(context).colorScheme.secondary,
-                    ),
-                  ),
-                  Expanded(
-                    child: Text(
-                      firstName,
-                      style: const TextStyle(
-                        fontSize: 16.0,
-                        fontWeight: FontWeight.w600,
-                      ),
-                    ),
-                  ),
-                  PageTransitionSwitcher(
-                    transitionBuilder:
-                        (child, primaryAnimation, secondaryAnimation) {
-                      return FadeThroughTransition(
-                        fillColor: Colors.transparent,
-                        animation: primaryAnimation,
-                        secondaryAnimation: secondaryAnimation,
-                        child: child,
-                      );
-                    },
-                    child: IconButton(
-                      key: Key(expandAccount ? "accounts" : "pages"),
-                      icon: Icon(expandAccount
-                          ? FeatherIcons.chevronDown
-                          : FeatherIcons.chevronRight),
-                      padding: EdgeInsets.zero,
-                      onPressed: () {
-                        setState(() {
-                          expandAccount = !expandAccount;
-                        });
-                      },
-                      splashColor: const Color(0x00000000),
-                      focusColor: const Color(0x00000000),
-                      hoverColor: const Color(0x00000000),
-                      highlightColor: const Color(0x00000000),
-                    ),
-                  ),
-                ],
-              ),
-            ),
-          ),
-
-          // Pages
-          Expanded(
-            child: PageTransitionSwitcher(
-              duration: const Duration(milliseconds: 500),
-              transitionBuilder: (child, primaryAnimation, secondaryAnimation) {
-                return SharedAxisTransition(
-                  fillColor: Colors.transparent,
-                  animation: primaryAnimation,
-                  secondaryAnimation: secondaryAnimation,
-                  transitionType: SharedAxisTransitionType.scaled,
-                  child: child,
-                );
-              },
-              child: !expandAccount
-                  ? Column(
-                      key: const Key("pages"),
-                      children: pageWidgets,
-                    )
-                  : Column(
-                      key: const Key("accounts"),
-                      children: accountWidgets,
-                    ),
-            ),
-          ),
-
-          // Settings
-          ...bottomActions,
-
-          // Bottom padding
-          const SizedBox(height: 12.0),
-        ],
-      ),
-    );
-  }
-
-  void buildAccountTiles() {
-    accountTiles = [];
-    user.getUsers().forEach((account) {
-      if (account.id == user.id) return;
-
-      String _firstName;
-
-      List<String> _nameParts = user.name?.split(" ") ?? ["?"];
-      if (!settings.presentationMode) {
-        _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
-      } else {
-        _firstName = "János";
-      }
-
-      accountTiles.add(AccountTile(
-        name: Text(!settings.presentationMode ? account.name : "János",
-            style: const TextStyle(fontWeight: FontWeight.w500)),
-        username:
-            Text(!settings.presentationMode ? account.username : "72469696969"),
-        profileImage: ProfileImage(
-          name: _firstName,
-          backgroundColor: !settings.presentationMode
-              ? ColorUtils.stringToColor(account.name)
-              : Theme.of(context).colorScheme.secondary,
-          role: account.role,
-        ),
-        onTap: () {
-          user.setUser(account.id);
-          restore().then((_) => user.setUser(account.id));
-        },
-        // onTapMenu: () => _showBottomSheet(account),
-      ));
-    });
-  }
-}
+import 'package:animations/animations.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:refilc_desktop_ui/common/panel_button.dart';
+import 'package:refilc_desktop_ui/common/profile_image.dart';
+import 'package:refilc_desktop_ui/screens/navigation/sidebar.i18n.dart';
+import 'package:refilc_desktop_ui/screens/navigation/sidebar_action.dart';
+import 'package:refilc_desktop_ui/screens/settings/settings_screen.dart';
+import 'package:refilc_mobile_ui/screens/settings/accounts/account_tile.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+
+class Sidebar extends StatefulWidget {
+  const Sidebar(
+      {Key? key,
+      required this.navigator,
+      required this.onRouteChange,
+      this.selected = "home"})
+      : super(key: key);
+
+  final NavigatorState navigator;
+  final String selected;
+  final Function(String) onRouteChange;
+
+  @override
+  State<Sidebar> createState() => _SidebarState();
+}
+
+class _SidebarState extends State<Sidebar> {
+  late UserProvider user;
+  late SettingsProvider settings;
+  late String firstName;
+
+  String topNav = "";
+  bool expandAccount = false;
+  List<Widget> accountTiles = [];
+
+  @override
+  void initState() {
+    super.initState();
+    user = Provider.of<UserProvider>(context, listen: false);
+  }
+
+  Future<void> restore() => Future.wait([
+        Provider.of<GradeProvider>(context, listen: false).restore(),
+        Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
+        Provider.of<ExamProvider>(context, listen: false).restore(),
+        Provider.of<HomeworkProvider>(context, listen: false).restore(),
+        Provider.of<MessageProvider>(context, listen: false).restore(),
+        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(),
+      ]);
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    settings = Provider.of<SettingsProvider>(context);
+
+    List<String> nameParts = user.name?.split(" ") ?? ["?"];
+    if (!settings.presentationMode) {
+      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+    } else {
+      firstName = "János";
+    }
+
+    List<Widget> pageWidgets = [
+      SidebarAction(
+        title: Text("Home".i18n),
+        icon: const Icon(FilcIcons.home),
+        selected: widget.selected == "home",
+        onTap: () {
+          if (widget.selected != "home") {
+            widget.navigator.pushReplacementNamed("home");
+            widget.onRouteChange("home");
+          }
+        },
+      ),
+      SidebarAction(
+        title: Text("Grades".i18n),
+        icon: const Icon(FeatherIcons.bookmark),
+        selected: widget.selected == "grades",
+        onTap: () {
+          if (widget.selected != "grades") {
+            widget.navigator.pushReplacementNamed("grades");
+            widget.onRouteChange("grades");
+          }
+        },
+      ),
+      SidebarAction(
+        title: Text("Timetable".i18n),
+        icon: const Icon(FeatherIcons.calendar),
+        selected: widget.selected == "timetable",
+        onTap: () {
+          if (widget.selected != "timetable") {
+            widget.navigator.pushReplacementNamed("timetable");
+            widget.onRouteChange("timetable");
+          }
+        },
+      ),
+      SidebarAction(
+        title: Text("Messages".i18n),
+        icon: const Icon(FeatherIcons.messageSquare),
+        selected: widget.selected == "messages",
+        onTap: () {
+          if (widget.selected != "messages") {
+            widget.navigator.pushReplacementNamed("messages");
+            widget.onRouteChange("messages");
+          }
+        },
+      ),
+      SidebarAction(
+        title: Text("Absences".i18n),
+        icon: const Icon(FeatherIcons.clock),
+        selected: widget.selected == "absences",
+        onTap: () {
+          if (widget.selected != "absences") {
+            widget.navigator.pushReplacementNamed("absences");
+            widget.onRouteChange("absences");
+          }
+        },
+      ),
+    ];
+
+    List<Widget> bottomActions = [
+      SidebarAction(
+        title: Text("Settings".i18n),
+        selected: true,
+        icon: const Icon(FeatherIcons.settings),
+        onTap: () {
+          if (topNav != "settings") {
+            widget.navigator
+                .push(CupertinoPageRoute(
+                    builder: (context) => const SettingsScreen()))
+                .then((value) => topNav = "");
+            topNav = "settings";
+          }
+        },
+      ),
+    ];
+
+    buildAccountTiles();
+
+    List<Widget> accountWidgets = [
+      Padding(
+        padding: const EdgeInsets.symmetric(horizontal: 12.0),
+        child: Column(children: accountTiles),
+      ),
+
+      // Account settings
+      PanelButton(
+        onPressed: () {
+          Navigator.of(context).pushNamed("login_back");
+        },
+        title: Text("adduser".i18n),
+        leading: const Icon(FeatherIcons.userPlus),
+      ),
+      PanelButton(
+        onPressed: () 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 other Users left, go back to LoginScreen
+          if (user.getUsers().isNotEmpty) {
+            user.setUser(user.getUsers().first.id);
+            restore().then((_) => user.setUser(user.getUsers().first.id));
+          } else {
+            Navigator.of(context)
+                .pushNamedAndRemoveUntil("login", (_) => false);
+          }
+        },
+        title: Text("logout".i18n),
+        leading: Icon(FeatherIcons.logOut, color: AppColors.of(context).red),
+      ),
+    ];
+
+    return SizedBox(
+      height: double.infinity,
+      width: 250.0,
+      child: Column(
+        children: [
+          Padding(
+            padding: const EdgeInsets.only(
+              left: 12.0,
+              top: 18.0,
+              bottom: 24.0,
+              right: 12.0,
+            ),
+            child: InkWell(
+              customBorder: RoundedRectangleBorder(
+                  borderRadius: BorderRadius.circular(10)),
+              onTap: () {
+                setState(() {
+                  expandAccount = !expandAccount;
+                });
+              },
+              child: Row(
+                children: [
+                  Padding(
+                    padding: const EdgeInsets.only(
+                      right: 12.0,
+                      left: 5.0,
+                      top: 5.0,
+                      bottom: 5.0,
+                    ),
+                    child: ProfileImage(
+                      name: firstName,
+                      radius: 18.0,
+                      backgroundColor: Theme.of(context)
+                          .colorScheme
+                          .primary, //!settings.presentationMode
+                      //     ? ColorUtils.stringToColor(user.name ?? "?")
+                      //     : Theme.of(context).colorScheme.secondary,
+                    ),
+                  ),
+                  Expanded(
+                    child: Text(
+                      firstName,
+                      style: const TextStyle(
+                        fontSize: 16.0,
+                        fontWeight: FontWeight.w600,
+                      ),
+                    ),
+                  ),
+                  PageTransitionSwitcher(
+                    transitionBuilder:
+                        (child, primaryAnimation, secondaryAnimation) {
+                      return FadeThroughTransition(
+                        fillColor: Colors.transparent,
+                        animation: primaryAnimation,
+                        secondaryAnimation: secondaryAnimation,
+                        child: child,
+                      );
+                    },
+                    child: IconButton(
+                      key: Key(expandAccount ? "accounts" : "pages"),
+                      icon: Icon(expandAccount
+                          ? FeatherIcons.chevronDown
+                          : FeatherIcons.chevronRight),
+                      padding: EdgeInsets.zero,
+                      onPressed: () {
+                        setState(() {
+                          expandAccount = !expandAccount;
+                        });
+                      },
+                      splashColor: const Color(0x00000000),
+                      focusColor: const Color(0x00000000),
+                      hoverColor: const Color(0x00000000),
+                      highlightColor: const Color(0x00000000),
+                    ),
+                  ),
+                ],
+              ),
+            ),
+          ),
+
+          // Pages
+          Expanded(
+            child: PageTransitionSwitcher(
+              duration: const Duration(milliseconds: 500),
+              transitionBuilder: (child, primaryAnimation, secondaryAnimation) {
+                return SharedAxisTransition(
+                  fillColor: Colors.transparent,
+                  animation: primaryAnimation,
+                  secondaryAnimation: secondaryAnimation,
+                  transitionType: SharedAxisTransitionType.scaled,
+                  child: child,
+                );
+              },
+              child: !expandAccount
+                  ? Column(
+                      key: const Key("pages"),
+                      children: pageWidgets,
+                    )
+                  : Column(
+                      key: const Key("accounts"),
+                      children: accountWidgets,
+                    ),
+            ),
+          ),
+
+          // Settings
+          ...bottomActions,
+
+          // Bottom padding
+          const SizedBox(height: 12.0),
+        ],
+      ),
+    );
+  }
+
+  void buildAccountTiles() {
+    accountTiles = [];
+    user.getUsers().forEach((account) {
+      if (account.id == user.id) return;
+
+      String _firstName;
+
+      List<String> _nameParts = user.name?.split(" ") ?? ["?"];
+      if (!settings.presentationMode) {
+        _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
+      } else {
+        _firstName = "János";
+      }
+
+      accountTiles.add(AccountTile(
+        name: Text(!settings.presentationMode ? account.name : "János",
+            style: const TextStyle(fontWeight: FontWeight.w500)),
+        username:
+            Text(!settings.presentationMode ? account.username : "72469696969"),
+        profileImage: ProfileImage(
+          name: _firstName,
+          backgroundColor: !settings.presentationMode
+              ? ColorUtils.stringToColor(account.name)
+              : Theme.of(context).colorScheme.secondary,
+          role: account.role,
+        ),
+        onTap: () {
+          user.setUser(account.id);
+          restore().then((_) => user.setUser(account.id));
+        },
+        // onTapMenu: () => _showBottomSheet(account),
+      ));
+    });
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.i18n.dart b/refilc_desktop_ui/lib/screens/navigation/sidebar.i18n.dart
similarity index 100%
rename from filcnaplo_desktop_ui/lib/screens/navigation/sidebar.i18n.dart
rename to refilc_desktop_ui/lib/screens/navigation/sidebar.i18n.dart
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar_action.dart b/refilc_desktop_ui/lib/screens/navigation/sidebar_action.dart
similarity index 73%
rename from filcnaplo_desktop_ui/lib/screens/navigation/sidebar_action.dart
rename to refilc_desktop_ui/lib/screens/navigation/sidebar_action.dart
index 6f71f26..e13610f 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar_action.dart
+++ b/refilc_desktop_ui/lib/screens/navigation/sidebar_action.dart
@@ -1,49 +1,55 @@
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-
-class SidebarAction extends StatelessWidget {
-  const SidebarAction({Key? key, this.title, this.icon, this.onTap, this.selected = false}) : super(key: key);
-
-  final bool selected;
-  final Widget? icon;
-  final Widget? title;
-  final Function()? onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 12.0),
-      child: InkWell(
-        onTap: onTap,
-        borderRadius: BorderRadius.circular(12.0),
-        child: Padding(
-          padding: const EdgeInsets.all(8.0),
-          child: Row(
-            children: [
-              if (icon != null)
-                IconTheme(
-                  data: IconThemeData(
-                    color: AppColors.of(context).text.withOpacity(selected ? 1.0 : .3),
-                  ),
-                  child: icon!,
-                ),
-              if (title != null)
-                Padding(
-                  padding: const EdgeInsets.only(left: 24.0),
-                  child: AnimatedDefaultTextStyle(
-                    duration: const Duration(milliseconds: 500),
-                    style: TextStyle(
-                      color: AppColors.of(context).text.withOpacity(selected ? 1.0 : .8),
-                      fontWeight: FontWeight.w500,
-                      fontFamily: "Montserrat",
-                    ),
-                    child: title!,
-                  ),
-                ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:refilc/theme/colors/colors.dart';
+
+class SidebarAction extends StatelessWidget {
+  const SidebarAction(
+      {Key? key, this.title, this.icon, this.onTap, this.selected = false})
+      : super(key: key);
+
+  final bool selected;
+  final Widget? icon;
+  final Widget? title;
+  final Function()? onTap;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 12.0),
+      child: InkWell(
+        onTap: onTap,
+        borderRadius: BorderRadius.circular(12.0),
+        child: Padding(
+          padding: const EdgeInsets.all(8.0),
+          child: Row(
+            children: [
+              if (icon != null)
+                IconTheme(
+                  data: IconThemeData(
+                    color: AppColors.of(context)
+                        .text
+                        .withOpacity(selected ? 1.0 : .3),
+                  ),
+                  child: icon!,
+                ),
+              if (title != null)
+                Padding(
+                  padding: const EdgeInsets.only(left: 24.0),
+                  child: AnimatedDefaultTextStyle(
+                    duration: const Duration(milliseconds: 500),
+                    style: TextStyle(
+                      color: AppColors.of(context)
+                          .text
+                          .withOpacity(selected ? 1.0 : .8),
+                      fontWeight: FontWeight.w500,
+                      fontFamily: "Montserrat",
+                    ),
+                    child: title!,
+                  ),
+                ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/news/news_view.dart b/refilc_desktop_ui/lib/screens/news/news_view.dart
similarity index 95%
rename from filcnaplo_desktop_ui/lib/screens/news/news_view.dart
rename to refilc_desktop_ui/lib/screens/news/news_view.dart
index cc9609c..9b6c307 100644
--- a/filcnaplo_desktop_ui/lib/screens/news/news_view.dart
+++ b/refilc_desktop_ui/lib/screens/news/news_view.dart
@@ -1,10 +1,10 @@
-import 'package:flutter/material.dart';
-
-class NewsView extends StatelessWidget {
-  const NewsView({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Container();
-  }
-}
+import 'package:flutter/material.dart';
+
+class NewsView extends StatelessWidget {
+  const NewsView({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.dart b/refilc_desktop_ui/lib/screens/settings/settings_screen.dart
similarity index 93%
rename from filcnaplo_desktop_ui/lib/screens/settings/settings_screen.dart
rename to refilc_desktop_ui/lib/screens/settings/settings_screen.dart
index 90a3213..8f08e7b 100644
--- a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.dart
+++ b/refilc_desktop_ui/lib/screens/settings/settings_screen.dart
@@ -1,956 +1,955 @@
-import 'package:filcnaplo/api/providers/update_provider.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_mobile_ui/common/action_button.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/update/updates_view.dart';
-import 'package:filcnaplo_mobile_ui/premium/premium_button.dart';
-import 'package:filcnaplo_mobile_ui/screens/news/news_screen.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_tile.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/debug/subject_icon_gallery.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/privacy_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_helper.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as tabs;
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
-import 'package:provider/provider.dart';
-import 'package:url_launcher/url_launcher.dart';
-import 'settings_screen.i18n.dart';
-import 'package:flutter/services.dart';
-import 'package:filcnaplo_premium/ui/mobile/settings/nickname.dart';
-import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
-
-class SettingsScreen extends StatefulWidget {
-  const SettingsScreen({Key? key}) : super(key: key);
-
-  @override
-  _SettingsScreenState createState() => _SettingsScreenState();
-}
-
-class _SettingsScreenState extends State<SettingsScreen>
-    with SingleTickerProviderStateMixin {
-  int devmodeCountdown = 3;
-  final bool __ss = false; // secret settings
-
-  late UserProvider user;
-  late UpdateProvider updateProvider;
-  late SettingsProvider settings;
-  late KretaClient kretaClient;
-  late String firstName;
-  List<Widget> accountTiles = [];
-
-  late AnimationController _hideContainersController;
-
-  Future<void> restore() => Future.wait([
-        Provider.of<GradeProvider>(context, listen: false).restore(),
-        Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
-        Provider.of<ExamProvider>(context, listen: false).restore(),
-        Provider.of<HomeworkProvider>(context, listen: false).restore(),
-        Provider.of<MessageProvider>(context, listen: false).restore(),
-        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(),
-      ]);
-
-  void buildAccountTiles() {
-    accountTiles = [];
-    user.getUsers().forEach((account) {
-      if (account.id == user.id) return;
-
-      String _firstName;
-
-      List<String> _nameParts = user.displayName?.split(" ") ?? ["?"];
-      if (!settings.presentationMode) {
-        _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
-      } else {
-        _firstName = "János";
-      }
-
-      accountTiles.add(AccountTile(
-        name: Text(!settings.presentationMode ? account.name : "János",
-            style: const TextStyle(fontWeight: FontWeight.w500)),
-        username:
-            Text(!settings.presentationMode ? account.username : "72469696969"),
-        profileImage: ProfileImage(
-          name: _firstName,
-          backgroundColor: Theme.of(context)
-              .colorScheme
-              .primary, //!settings.presentationMode
-          //? ColorUtils.stringToColor(account.name)
-          //: Theme.of(context).colorScheme.secondary,
-          role: account.role,
-        ),
-        onTap: () {
-          user.setUser(account.id);
-          restore().then((_) => user.setUser(account.id));
-          Navigator.of(context).pop();
-        },
-        onTapMenu: () => _showBottomSheet(account),
-      ));
-    });
-  }
-
-  void _showBottomSheet(User u) {
-    showBottomSheetMenu(context, items: [
-      BottomSheetMenuItem(
-        onPressed: () => AccountView.show(u, context: context),
-        icon: const Icon(FeatherIcons.user),
-        title: Text("personal_details".i18n),
-      ),
-      BottomSheetMenuItem(
-        onPressed: () => _openDKT(u),
-        icon: Icon(FeatherIcons.grid, color: AppColors.of(context).teal),
-        title: Text("open_dkt".i18n),
-      ),
-      UserMenuNickname(u),
-      // BottomSheetMenuItem(
-      //   onPressed: () {},
-      //   icon: Icon(FeatherIcons.camera),
-      //   title: Text("edit_profile_picture".i18n),
-      // ),
-      // BottomSheetMenuItem(
-      //   onPressed: () {},
-      //   icon: Icon(FeatherIcons.trash2, color: AppColors.of(context).red),
-      //   title: Text("remove_profile_picture".i18n),
-      // ),
-    ]);
-  }
-
-  void _openDKT(User u) => tabs.launch(
-      "https://dkttanulo.e-kreta.hu/sso?id_token=${kretaClient.idToken}",
-      customTabsOption: tabs.CustomTabsOption(
-        toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-        showPageTitle: true,
-      ));
-
-  @override
-  void initState() {
-    super.initState();
-    _hideContainersController = AnimationController(
-        vsync: this, duration: const Duration(milliseconds: 200));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    settings = Provider.of<SettingsProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-    kretaClient = Provider.of<KretaClient>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    if (!settings.presentationMode) {
-      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-    } else {
-      firstName = "János";
-    }
-
-    String startPageTitle =
-        SettingsHelper.localizedPageTitles()[settings.startPage] ?? "?";
-    String themeModeText = {
-          ThemeMode.light: "light".i18n,
-          ThemeMode.dark: "dark".i18n,
-          ThemeMode.system: "system".i18n
-        }[settings.theme] ??
-        "?";
-    String languageText = SettingsHelper.langMap[settings.language] ?? "?";
-    String vibrateTitle = {
-          VibrationStrength.off: "voff".i18n,
-          VibrationStrength.light: "vlight".i18n,
-          VibrationStrength.medium: "vmedium".i18n,
-          VibrationStrength.strong: "vstrong".i18n,
-        }[settings.vibrate] ??
-        "?";
-
-    buildAccountTiles();
-
-    if (settings.developerMode) devmodeCountdown = -1;
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 11.5),
-        child: CustomScrollView(
-          slivers: [
-            SliverAppBar(
-              pinned: true,
-              floating: true,
-              snap: false,
-              centerTitle: false,
-              title: const Text("Settings"),
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-            ),
-            SliverToBoxAdapter(
-              child: AnimatedBuilder(
-                animation: _hideContainersController,
-                builder: (context, child) => Opacity(
-                  opacity: 1 - _hideContainersController.value,
-                  child: Column(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      StaggeredGrid.extent(
-                        // direction: Axis.horizontal,
-                        // crossAxisCount: 3,
-                        maxCrossAxisExtent: 600,
-                        children: [
-                          const SizedBox(height: 32.0),
-
-                          // Updates
-                          if (updateProvider.available)
-                            Container(
-                              constraints: const BoxConstraints(maxWidth: 500),
-                              child: Padding(
-                                padding: const EdgeInsets.symmetric(
-                                    vertical: 12.0, horizontal: 24.0),
-                                child: Panel(
-                                  child: PanelButton(
-                                    onPressed: () => _openUpdates(context),
-                                    title: Text("update_available".i18n),
-                                    leading: const Icon(FeatherIcons.download),
-                                    trailing: Text(
-                                      updateProvider.releases.first.tag,
-                                      style: TextStyle(
-                                        fontWeight: FontWeight.w500,
-                                        color: Theme.of(context)
-                                            .colorScheme
-                                            .secondary,
-                                      ),
-                                    ),
-                                  ),
-                                ),
-                              ),
-                            ),
-
-                          // const Padding(
-                          //   padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-                          //   child: PremiumBannerButton(),
-                          // ),
-                          if (!Provider.of<PremiumProvider>(context).hasPremium)
-                            const ClipRect(
-                              child: Padding(
-                                padding: EdgeInsets.symmetric(vertical: 12.0),
-                                child: PremiumButton(),
-                              ),
-                            ),
-
-                          // General Settings
-                          Container(
-                            constraints: const BoxConstraints(maxWidth: 500),
-                            child: Padding(
-                              padding: const EdgeInsets.symmetric(
-                                  vertical: 12.0, horizontal: 24.0),
-                              child: Panel(
-                                title: Text("general".i18n),
-                                child: Column(
-                                  children: [
-                                    PanelButton(
-                                      onPressed: () {
-                                        SettingsHelper.language(context);
-                                        setState(() {});
-                                      },
-                                      title: Text("language".i18n),
-                                      leading: const Icon(FeatherIcons.globe),
-                                      trailing: Text(languageText),
-                                    ),
-                                    PanelButton(
-                                      onPressed: () {
-                                        SettingsHelper.startPage(context);
-                                        setState(() {});
-                                      },
-                                      title: Text("startpage".i18n),
-                                      leading: const Icon(FeatherIcons.play),
-                                      trailing: Text(startPageTitle.capital()),
-                                    ),
-                                    PanelButton(
-                                      onPressed: () {
-                                        SettingsHelper.rounding(context);
-                                        setState(() {});
-                                      },
-                                      title: Text("rounding".i18n),
-                                      leading:
-                                          const Icon(FeatherIcons.gitCommit),
-                                      trailing: Text((settings.rounding / 10)
-                                          .toStringAsFixed(1)),
-                                    ),
-                                    PanelButton(
-                                      onPressed: () {
-                                        SettingsHelper.vibrate(context);
-                                        setState(() {});
-                                      },
-                                      title: Text("vibrate".i18n),
-                                      leading: const Icon(FeatherIcons.radio),
-                                      trailing: Text(vibrateTitle),
-                                    ),
-                                    PanelButton(
-                                      padding:
-                                          const EdgeInsets.only(left: 14.0),
-                                      onPressed: () {
-                                        SettingsHelper.bellDelay(context);
-                                        setState(() {});
-                                      },
-                                      title: Text(
-                                        "bell_delay".i18n,
-                                        style: TextStyle(
-                                            color: AppColors.of(context)
-                                                .text
-                                                .withOpacity(
-                                                    settings.bellDelayEnabled
-                                                        ? 1.0
-                                                        : .5)),
-                                      ),
-                                      leading: settings.bellDelayEnabled
-                                          ? const Icon(FeatherIcons.bell)
-                                          : Icon(FeatherIcons.bellOff,
-                                              color: AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(.25)),
-                                      trailingDivider: true,
-                                      trailing: Switch(
-                                        onChanged: (v) => settings.update(
-                                            bellDelayEnabled: v),
-                                        value: settings.bellDelayEnabled,
-                                        activeColor: Theme.of(context)
-                                            .colorScheme
-                                            .secondary,
-                                      ),
-                                    ),
-                                  ],
-                                ),
-                              ),
-                            ),
-                          ),
-
-                          if (kDebugMode)
-                            Container(
-                              constraints: const BoxConstraints(maxWidth: 500),
-                              child: Padding(
-                                padding: const EdgeInsets.symmetric(
-                                    vertical: 12.0, horizontal: 24.0),
-                                child: Panel(
-                                  title: const Text("Debug"),
-                                  child: Column(
-                                    children: [
-                                      PanelButton(
-                                        title:
-                                            const Text("Subject Icon Gallery"),
-                                        leading: const Icon(CupertinoIcons
-                                            .rectangle_3_offgrid_fill),
-                                        trailing:
-                                            const Icon(Icons.arrow_forward),
-                                        onPressed: () {
-                                          Navigator.of(context,
-                                                  rootNavigator: true)
-                                              .push(
-                                            CupertinoPageRoute(
-                                                builder: (context) =>
-                                                    const SubjectIconGallery()),
-                                          );
-                                        },
-                                      )
-                                    ],
-                                  ),
-                                ),
-                              ),
-                            ),
-
-                          // Secret Settings
-                          if (__ss)
-                            Container(
-                              constraints: const BoxConstraints(maxWidth: 500),
-                              child: Padding(
-                                padding: const EdgeInsets.symmetric(
-                                    vertical: 12.0, horizontal: 24.0),
-                                child: Panel(
-                                  title: Text("secret".i18n),
-                                  child: Column(
-                                    children: [
-                                      // Good student mode
-                                      Material(
-                                        type: MaterialType.transparency,
-                                        child: SwitchListTile(
-                                          contentPadding:
-                                              const EdgeInsets.only(left: 12.0),
-                                          shape: RoundedRectangleBorder(
-                                              borderRadius:
-                                                  BorderRadius.circular(12.0)),
-                                          title: Text("goodstudent".i18n,
-                                              style: const TextStyle(
-                                                  fontWeight: FontWeight.w500)),
-                                          onChanged: (v) {
-                                            if (v) {
-                                              showDialog(
-                                                context: context,
-                                                builder: (context) =>
-                                                    WillPopScope(
-                                                  onWillPop: () async => false,
-                                                  child: AlertDialog(
-                                                    shape:
-                                                        RoundedRectangleBorder(
-                                                            borderRadius:
-                                                                BorderRadius
-                                                                    .circular(
-                                                                        12.0)),
-                                                    title:
-                                                        Text("attention".i18n),
-                                                    content: Text(
-                                                        "goodstudent_disclaimer"
-                                                            .i18n),
-                                                    actions: [
-                                                      ActionButton(
-                                                          label:
-                                                              "understand".i18n,
-                                                          onTap: () {
-                                                            Navigator.of(
-                                                                    context)
-                                                                .pop();
-                                                            settings.update(
-                                                                goodStudent: v);
-                                                            Provider.of<GradeProvider>(
-                                                                    context,
-                                                                    listen:
-                                                                        false)
-                                                                .fetch();
-                                                          })
-                                                    ],
-                                                  ),
-                                                ),
-                                              );
-                                            } else {
-                                              settings.update(goodStudent: v);
-                                              Provider.of<GradeProvider>(
-                                                      context,
-                                                      listen: false)
-                                                  .fetch();
-                                            }
-                                          },
-                                          value: settings.goodStudent,
-                                          activeColor: Theme.of(context)
-                                              .colorScheme
-                                              .secondary,
-                                        ),
-                                      ),
-
-                                      // Presentation mode
-                                      Material(
-                                        type: MaterialType.transparency,
-                                        child: SwitchListTile(
-                                          contentPadding:
-                                              const EdgeInsets.only(left: 12.0),
-                                          shape: RoundedRectangleBorder(
-                                              borderRadius:
-                                                  BorderRadius.circular(12.0)),
-                                          title: const Text("Presentation Mode",
-                                              style: TextStyle(
-                                                  fontWeight: FontWeight.w500)),
-                                          onChanged: (v) => settings.update(
-                                              presentationMode: v),
-                                          value: settings.presentationMode,
-                                          activeColor: Theme.of(context)
-                                              .colorScheme
-                                              .secondary,
-                                        ),
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              ),
-                            ),
-
-                          // Theme Settings
-                          Container(
-                            constraints: const BoxConstraints(maxWidth: 500),
-                            child: Padding(
-                              padding: const EdgeInsets.symmetric(
-                                  vertical: 12.0, horizontal: 24.0),
-                              child: Panel(
-                                title: Text("appearance".i18n),
-                                child: Column(
-                                  children: [
-                                    PanelButton(
-                                      onPressed: () {
-                                        SettingsHelper.theme(context);
-                                        setState(() {});
-                                      },
-                                      title: Text("theme".i18n),
-                                      leading: const Icon(FeatherIcons.sun),
-                                      trailing: Text(themeModeText),
-                                    ),
-                                    PanelButton(
-                                      onPressed: () async {
-                                        await _hideContainersController
-                                            .forward();
-                                        SettingsHelper.accentColor(context);
-                                        setState(() {});
-                                        _hideContainersController.reset();
-                                      },
-                                      title: Text("color".i18n),
-                                      leading: const Icon(FeatherIcons.droplet),
-                                      trailing: Container(
-                                        width: 12.0,
-                                        height: 12.0,
-                                        decoration: BoxDecoration(
-                                          color: Theme.of(context)
-                                              .colorScheme
-                                              .secondary,
-                                          shape: BoxShape.circle,
-                                        ),
-                                      ),
-                                    ),
-                                    PanelButton(
-                                      onPressed: () {
-                                        SettingsHelper.gradeColors(context);
-                                        setState(() {});
-                                      },
-                                      title: Text("grade_colors".i18n),
-                                      leading: const Icon(FeatherIcons.star),
-                                      trailing: Row(
-                                        mainAxisSize: MainAxisSize.min,
-                                        children: List.generate(
-                                          5,
-                                          (i) => Container(
-                                            margin: const EdgeInsets.only(
-                                                left: 2.0),
-                                            width: 12.0,
-                                            height: 12.0,
-                                            decoration: BoxDecoration(
-                                              shape: BoxShape.circle,
-                                              color: settings.gradeColors[i],
-                                            ),
-                                          ),
-                                        ),
-                                      ),
-                                    ),
-                                    Material(
-                                      type: MaterialType.transparency,
-                                      child: SwitchListTile(
-                                        contentPadding:
-                                            const EdgeInsets.only(left: 12.0),
-                                        shape: RoundedRectangleBorder(
-                                            borderRadius:
-                                                BorderRadius.circular(12.0)),
-                                        title: Row(
-                                          children: [
-                                            Icon(
-                                              FeatherIcons.barChart,
-                                              color: settings.graphClassAvg
-                                                  ? Theme.of(context)
-                                                      .colorScheme
-                                                      .secondary
-                                                  : AppColors.of(context)
-                                                      .text
-                                                      .withOpacity(.25),
-                                            ),
-                                            const SizedBox(width: 24.0),
-                                            Expanded(
-                                              child: Text(
-                                                "graph_class_avg".i18n,
-                                                style: TextStyle(
-                                                  fontWeight: FontWeight.w600,
-                                                  fontSize: 16.0,
-                                                  color: AppColors.of(context)
-                                                      .text
-                                                      .withOpacity(
-                                                          settings.graphClassAvg
-                                                              ? 1.0
-                                                              : .5),
-                                                ),
-                                              ),
-                                            ),
-                                          ],
-                                        ),
-                                        onChanged: (v) =>
-                                            settings.update(graphClassAvg: v),
-                                        value: settings.graphClassAvg,
-                                        activeColor: Theme.of(context)
-                                            .colorScheme
-                                            .secondary,
-                                      ),
-                                    ),
-                                    const PremiumIconPackSelector(),
-                                  ],
-                                ),
-                              ),
-                            ),
-                          ),
-
-                          // Notifications
-                          Container(
-                            constraints: const BoxConstraints(maxWidth: 500),
-                            child: Padding(
-                              padding: const EdgeInsets.symmetric(
-                                  vertical: 12.0, horizontal: 24.0),
-                              child: Panel(
-                                title: Text("notifications".i18n),
-                                child: Material(
-                                  type: MaterialType.transparency,
-                                  child: SwitchListTile(
-                                    contentPadding:
-                                        const EdgeInsets.only(left: 12.0),
-                                    shape: RoundedRectangleBorder(
-                                        borderRadius:
-                                            BorderRadius.circular(12.0)),
-                                    title: Row(
-                                      children: [
-                                        Icon(
-                                          Icons.newspaper_outlined,
-                                          color: settings.newsEnabled
-                                              ? Theme.of(context)
-                                                  .colorScheme
-                                                  .secondary
-                                              : AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(.25),
-                                        ),
-                                        const SizedBox(width: 24.0),
-                                        Expanded(
-                                          child: Text(
-                                            "news".i18n,
-                                            style: TextStyle(
-                                              fontWeight: FontWeight.w600,
-                                              fontSize: 16.0,
-                                              color: AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(
-                                                      settings.newsEnabled
-                                                          ? 1.0
-                                                          : .5),
-                                            ),
-                                          ),
-                                        ),
-                                      ],
-                                    ),
-                                    onChanged: (v) =>
-                                        settings.update(newsEnabled: v),
-                                    value: settings.newsEnabled,
-                                    activeColor:
-                                        Theme.of(context).colorScheme.secondary,
-                                  ),
-                                ),
-                              ),
-                            ),
-                          ),
-
-                          // Extras
-                          Container(
-                            constraints: const BoxConstraints(maxWidth: 500),
-                            child: Padding(
-                              padding: const EdgeInsets.symmetric(
-                                  vertical: 12.0, horizontal: 24.0),
-                              child: Panel(
-                                title: Text("extras".i18n),
-                                child: Column(children: [
-                                  Material(
-                                    type: MaterialType.transparency,
-                                    child: SwitchListTile(
-                                      contentPadding:
-                                          const EdgeInsets.only(left: 12.0),
-                                      shape: RoundedRectangleBorder(
-                                          borderRadius:
-                                              BorderRadius.circular(12.0)),
-                                      title: Row(
-                                        children: [
-                                          Icon(
-                                            FeatherIcons.gift,
-                                            color: settings.gradeOpeningFun
-                                                ? Theme.of(context)
-                                                    .colorScheme
-                                                    .secondary
-                                                : AppColors.of(context)
-                                                    .text
-                                                    .withOpacity(.25),
-                                          ),
-                                          const SizedBox(width: 24.0),
-                                          Expanded(
-                                            child: Text(
-                                              "surprise_grades".i18n,
-                                              style: TextStyle(
-                                                fontWeight: FontWeight.w600,
-                                                fontSize: 16.0,
-                                                color: AppColors.of(context)
-                                                    .text
-                                                    .withOpacity(
-                                                        settings.gradeOpeningFun
-                                                            ? 1.0
-                                                            : .5),
-                                              ),
-                                            ),
-                                          ),
-                                        ],
-                                      ),
-                                      onChanged: (v) =>
-                                          settings.update(gradeOpeningFun: v),
-                                      value: settings.gradeOpeningFun,
-                                      activeColor: Theme.of(context)
-                                          .colorScheme
-                                          .secondary,
-                                    ),
-                                  ),
-                                ]),
-                              ),
-                            ),
-                          ),
-
-                          // About
-                          Container(
-                            constraints: const BoxConstraints(maxWidth: 500),
-                            child: Padding(
-                              padding: const EdgeInsets.symmetric(
-                                  vertical: 12.0, horizontal: 24.0),
-                              child: Panel(
-                                title: Text("about".i18n),
-                                child: Column(children: [
-                                  PanelButton(
-                                    leading: const Icon(FeatherIcons.atSign),
-                                    title: const Text("Discord"),
-                                    onPressed: () => launchUrl(
-                                        Uri.parse(
-                                            "https://filcnaplo.hu/discord"),
-                                        mode: LaunchMode.externalApplication),
-                                  ),
-                                  PanelButton(
-                                    leading: const Icon(FeatherIcons.globe),
-                                    title: const Text("www.filcnaplo.hu"),
-                                    onPressed: () => launchUrl(
-                                        Uri.parse("https://filcnaplo.hu"),
-                                        mode: LaunchMode.externalApplication),
-                                  ),
-                                  PanelButton(
-                                    leading: const Icon(FeatherIcons.github),
-                                    title: const Text("Github"),
-                                    onPressed: () => launchUrl(
-                                        Uri.parse("https://github.com/filc"),
-                                        mode: LaunchMode.externalApplication),
-                                  ),
-                                  PanelButton(
-                                    leading: const Icon(FeatherIcons.mail),
-                                    title: Text("news".i18n),
-                                    onPressed: () => _openNews(context),
-                                  ),
-                                  PanelButton(
-                                    leading: const Icon(FeatherIcons.lock),
-                                    title: Text("privacy".i18n),
-                                    onPressed: () => _openPrivacy(context),
-                                  ),
-                                  PanelButton(
-                                    leading: const Icon(FeatherIcons.award),
-                                    title: Text("licenses".i18n),
-                                    onPressed: () =>
-                                        showLicensePage(context: context),
-                                  ),
-                                  Tooltip(
-                                    message: "data_collected".i18n,
-                                    padding: const EdgeInsets.all(4.0),
-                                    textStyle: TextStyle(
-                                        fontWeight: FontWeight.w500,
-                                        color: AppColors.of(context).text),
-                                    decoration: BoxDecoration(
-                                        color: Theme.of(context)
-                                            .colorScheme
-                                            .background),
-                                    child: Material(
-                                      type: MaterialType.transparency,
-                                      child: SwitchListTile(
-                                        contentPadding:
-                                            const EdgeInsets.only(left: 12.0),
-                                        shape: RoundedRectangleBorder(
-                                            borderRadius:
-                                                BorderRadius.circular(12.0)),
-                                        secondary: Icon(
-                                          FeatherIcons.barChart2,
-                                          color: settings.xFilcId != "none"
-                                              ? Theme.of(context)
-                                                  .colorScheme
-                                                  .secondary
-                                              : AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(.25),
-                                        ),
-                                        title: Text(
-                                          "Analytics".i18n,
-                                          style: TextStyle(
-                                            fontWeight: FontWeight.w600,
-                                            fontSize: 16.0,
-                                            color: AppColors.of(context)
-                                                .text
-                                                .withOpacity(
-                                                    settings.xFilcId != "none"
-                                                        ? 1.0
-                                                        : .5),
-                                          ),
-                                        ),
-                                        subtitle: Text(
-                                          "Anonymous Usage Analytics".i18n,
-                                          style: TextStyle(
-                                            color: AppColors.of(context)
-                                                .text
-                                                .withOpacity(
-                                                    settings.xFilcId != "none"
-                                                        ? .5
-                                                        : .2),
-                                          ),
-                                        ),
-                                        onChanged: (v) {
-                                          String newId;
-                                          if (v == false) {
-                                            newId = "none";
-                                          } else if (settings.xFilcId ==
-                                              "none") {
-                                            newId = SettingsProvider
-                                                    .defaultSettings()
-                                                .xFilcId;
-                                          } else {
-                                            newId = settings.xFilcId;
-                                          }
-                                          settings.update(xFilcId: newId);
-                                        },
-                                        value: settings.xFilcId != "none",
-                                        activeColor: Theme.of(context)
-                                            .colorScheme
-                                            .secondary,
-                                      ),
-                                    ),
-                                  ),
-                                ]),
-                              ),
-                            ),
-                          ),
-                          if (settings.developerMode)
-                            Container(
-                              constraints: const BoxConstraints(maxWidth: 500),
-                              child: Padding(
-                                padding: const EdgeInsets.symmetric(
-                                    vertical: 12.0, horizontal: 24.0),
-                                child: Panel(
-                                  title: const Text("Developer Settings"),
-                                  child: Column(
-                                    children: [
-                                      Material(
-                                        type: MaterialType.transparency,
-                                        child: SwitchListTile(
-                                          contentPadding:
-                                              const EdgeInsets.only(left: 12.0),
-                                          shape: RoundedRectangleBorder(
-                                              borderRadius:
-                                                  BorderRadius.circular(12.0)),
-                                          title: const Text("Developer Mode",
-                                              style: TextStyle(
-                                                  fontWeight: FontWeight.w500)),
-                                          onChanged: (v) => settings.update(
-                                              developerMode: false),
-                                          value: settings.developerMode,
-                                          activeColor: Theme.of(context)
-                                              .colorScheme
-                                              .secondary,
-                                        ),
-                                      ),
-                                      PanelButton(
-                                        leading: const Icon(FeatherIcons.copy),
-                                        title: const Text("Copy JWT"),
-                                        onPressed: () => Clipboard.setData(
-                                            ClipboardData(
-                                                text: Provider.of<KretaClient>(
-                                                        context,
-                                                        listen: false)
-                                                    .accessToken!)),
-                                      ),
-                                      // if (Provider.of<PremiumProvider>(context,
-                                      //         listen: false)
-                                      //     .hasPremium)
-                                      //   PanelButton(
-                                      //     leading: const Icon(FeatherIcons.key),
-                                      //     title: const Text("Remove Premium"),
-                                      //     onPressed: () {
-                                      //       Provider.of<PremiumProvider>(
-                                      //               context,
-                                      //               listen: false)
-                                      //           .activate(removePremium: true);
-                                      //       settings.update(
-                                      //           accentColor: AccentColor.filc,
-                                      //           store: true);
-                                      //       Provider.of<ThemeModeObserver>(
-                                      //               context,
-                                      //               listen: false)
-                                      //           .changeTheme(settings.theme);
-                                      //     },
-                                      //   ),
-                                    ],
-                                  ),
-                                ),
-                              ),
-                            ),
-                        ],
-                      ),
-                      const SizedBox(
-                        height: 40,
-                      ),
-                      SafeArea(
-                        top: false,
-                        child: Center(
-                          child: GestureDetector(
-                            child: const Panel(
-                                title: Text("v" +
-                                    String.fromEnvironment("APPVER",
-                                        defaultValue: "?"))),
-                            onTap: () {
-                              if (devmodeCountdown > 0) {
-                                ScaffoldMessenger.of(context)
-                                    .showSnackBar(SnackBar(
-                                  duration: const Duration(milliseconds: 200),
-                                  content: Text(
-                                      "You are $devmodeCountdown taps away from Developer Mode."),
-                                ));
-
-                                setState(() => devmodeCountdown--);
-                              } else if (devmodeCountdown == 0) {
-                                ScaffoldMessenger.of(context)
-                                    .showSnackBar(const SnackBar(
-                                  content: Text(
-                                      "Developer Mode successfully activated."),
-                                ));
-
-                                settings.update(developerMode: true);
-
-                                setState(() => devmodeCountdown--);
-                              }
-                            },
-                          ),
-                        ),
-                      ),
-                    ],
-                  ),
-                ),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-
-  void _openNews(BuildContext context) =>
-      Navigator.of(context, rootNavigator: true)
-          .push(CupertinoPageRoute(builder: (context) => const NewsScreen()));
-  void _openUpdates(BuildContext context) =>
-      UpdateView.show(updateProvider.releases.first, context: context);
-  void _openPrivacy(BuildContext context) => PrivacyView.show(context);
-}
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_mobile_ui/common/action_button.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/common/widgets/update/updates_view.dart';
+import 'package:refilc_mobile_ui/premium/premium_button.dart';
+import 'package:refilc_mobile_ui/screens/news/news_screen.dart';
+import 'package:refilc_mobile_ui/screens/settings/accounts/account_tile.dart';
+import 'package:refilc_mobile_ui/screens/settings/accounts/account_view.dart';
+import 'package:refilc_mobile_ui/screens/settings/debug/subject_icon_gallery.dart';
+import 'package:refilc_mobile_ui/screens/settings/privacy_view.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_helper.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as tabs;
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
+import 'package:provider/provider.dart';
+import 'package:url_launcher/url_launcher.dart';
+import 'settings_screen.i18n.dart';
+import 'package:flutter/services.dart';
+import 'package:refilc_premium/ui/mobile/settings/nickname.dart';
+import 'package:refilc_premium/ui/mobile/settings/icon_pack.dart';
+
+class SettingsScreen extends StatefulWidget {
+  const SettingsScreen({Key? key}) : super(key: key);
+
+  @override
+  _SettingsScreenState createState() => _SettingsScreenState();
+}
+
+class _SettingsScreenState extends State<SettingsScreen>
+    with SingleTickerProviderStateMixin {
+  int devmodeCountdown = 3;
+  final bool __ss = false; // secret settings
+
+  late UserProvider user;
+  late UpdateProvider updateProvider;
+  late SettingsProvider settings;
+  late KretaClient kretaClient;
+  late String firstName;
+  List<Widget> accountTiles = [];
+
+  late AnimationController _hideContainersController;
+
+  Future<void> restore() => Future.wait([
+        Provider.of<GradeProvider>(context, listen: false).restore(),
+        Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
+        Provider.of<ExamProvider>(context, listen: false).restore(),
+        Provider.of<HomeworkProvider>(context, listen: false).restore(),
+        Provider.of<MessageProvider>(context, listen: false).restore(),
+        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(),
+      ]);
+
+  void buildAccountTiles() {
+    accountTiles = [];
+    user.getUsers().forEach((account) {
+      if (account.id == user.id) return;
+
+      String _firstName;
+
+      List<String> _nameParts = user.displayName?.split(" ") ?? ["?"];
+      if (!settings.presentationMode) {
+        _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
+      } else {
+        _firstName = "János";
+      }
+
+      accountTiles.add(AccountTile(
+        name: Text(!settings.presentationMode ? account.name : "János",
+            style: const TextStyle(fontWeight: FontWeight.w500)),
+        username:
+            Text(!settings.presentationMode ? account.username : "72469696969"),
+        profileImage: ProfileImage(
+          name: _firstName,
+          backgroundColor: Theme.of(context)
+              .colorScheme
+              .primary, //!settings.presentationMode
+          //? ColorUtils.stringToColor(account.name)
+          //: Theme.of(context).colorScheme.secondary,
+          role: account.role,
+        ),
+        onTap: () {
+          user.setUser(account.id);
+          restore().then((_) => user.setUser(account.id));
+          Navigator.of(context).pop();
+        },
+        onTapMenu: () => _showBottomSheet(account),
+      ));
+    });
+  }
+
+  void _showBottomSheet(User u) {
+    showBottomSheetMenu(context, items: [
+      BottomSheetMenuItem(
+        onPressed: () => AccountView.show(u, context: context),
+        icon: const Icon(FeatherIcons.user),
+        title: Text("personal_details".i18n),
+      ),
+      BottomSheetMenuItem(
+        onPressed: () => _openDKT(u),
+        icon: Icon(FeatherIcons.grid, color: AppColors.of(context).teal),
+        title: Text("open_dkt".i18n),
+      ),
+      UserMenuNickname(u),
+      // BottomSheetMenuItem(
+      //   onPressed: () {},
+      //   icon: Icon(FeatherIcons.camera),
+      //   title: Text("edit_profile_picture".i18n),
+      // ),
+      // BottomSheetMenuItem(
+      //   onPressed: () {},
+      //   icon: Icon(FeatherIcons.trash2, color: AppColors.of(context).red),
+      //   title: Text("remove_profile_picture".i18n),
+      // ),
+    ]);
+  }
+
+  void _openDKT(User u) => tabs.launch(
+      "https://dkttanulo.e-kreta.hu/sso?id_token=${kretaClient.idToken}",
+      customTabsOption: tabs.CustomTabsOption(
+        toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+        showPageTitle: true,
+      ));
+
+  @override
+  void initState() {
+    super.initState();
+    _hideContainersController = AnimationController(
+        vsync: this, duration: const Duration(milliseconds: 200));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    settings = Provider.of<SettingsProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+    kretaClient = Provider.of<KretaClient>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    if (!settings.presentationMode) {
+      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+    } else {
+      firstName = "János";
+    }
+
+    String startPageTitle =
+        SettingsHelper.localizedPageTitles()[settings.startPage] ?? "?";
+    String themeModeText = {
+          ThemeMode.light: "light".i18n,
+          ThemeMode.dark: "dark".i18n,
+          ThemeMode.system: "system".i18n
+        }[settings.theme] ??
+        "?";
+    String languageText = SettingsHelper.langMap[settings.language] ?? "?";
+    String vibrateTitle = {
+          VibrationStrength.off: "voff".i18n,
+          VibrationStrength.light: "vlight".i18n,
+          VibrationStrength.medium: "vmedium".i18n,
+          VibrationStrength.strong: "vstrong".i18n,
+        }[settings.vibrate] ??
+        "?";
+
+    buildAccountTiles();
+
+    if (settings.developerMode) devmodeCountdown = -1;
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 11.5),
+        child: CustomScrollView(
+          slivers: [
+            SliverAppBar(
+              pinned: true,
+              floating: true,
+              snap: false,
+              centerTitle: false,
+              title: const Text("Settings"),
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+            ),
+            SliverToBoxAdapter(
+              child: AnimatedBuilder(
+                animation: _hideContainersController,
+                builder: (context, child) => Opacity(
+                  opacity: 1 - _hideContainersController.value,
+                  child: Column(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: [
+                      StaggeredGrid.extent(
+                        // direction: Axis.horizontal,
+                        // crossAxisCount: 3,
+                        maxCrossAxisExtent: 600,
+                        children: [
+                          const SizedBox(height: 32.0),
+
+                          // Updates
+                          if (updateProvider.available)
+                            Container(
+                              constraints: const BoxConstraints(maxWidth: 500),
+                              child: Padding(
+                                padding: const EdgeInsets.symmetric(
+                                    vertical: 12.0, horizontal: 24.0),
+                                child: Panel(
+                                  child: PanelButton(
+                                    onPressed: () => _openUpdates(context),
+                                    title: Text("update_available".i18n),
+                                    leading: const Icon(FeatherIcons.download),
+                                    trailing: Text(
+                                      updateProvider.releases.first.tag,
+                                      style: TextStyle(
+                                        fontWeight: FontWeight.w500,
+                                        color: Theme.of(context)
+                                            .colorScheme
+                                            .secondary,
+                                      ),
+                                    ),
+                                  ),
+                                ),
+                              ),
+                            ),
+
+                          // const Padding(
+                          //   padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+                          //   child: PremiumBannerButton(),
+                          // ),
+                          if (!Provider.of<PremiumProvider>(context).hasPremium)
+                            const ClipRect(
+                              child: Padding(
+                                padding: EdgeInsets.symmetric(vertical: 12.0),
+                                child: PremiumButton(),
+                              ),
+                            ),
+
+                          // General Settings
+                          Container(
+                            constraints: const BoxConstraints(maxWidth: 500),
+                            child: Padding(
+                              padding: const EdgeInsets.symmetric(
+                                  vertical: 12.0, horizontal: 24.0),
+                              child: Panel(
+                                title: Text("general".i18n),
+                                child: Column(
+                                  children: [
+                                    PanelButton(
+                                      onPressed: () {
+                                        SettingsHelper.language(context);
+                                        setState(() {});
+                                      },
+                                      title: Text("language".i18n),
+                                      leading: const Icon(FeatherIcons.globe),
+                                      trailing: Text(languageText),
+                                    ),
+                                    PanelButton(
+                                      onPressed: () {
+                                        SettingsHelper.startPage(context);
+                                        setState(() {});
+                                      },
+                                      title: Text("startpage".i18n),
+                                      leading: const Icon(FeatherIcons.play),
+                                      trailing: Text(startPageTitle.capital()),
+                                    ),
+                                    PanelButton(
+                                      onPressed: () {
+                                        SettingsHelper.rounding(context);
+                                        setState(() {});
+                                      },
+                                      title: Text("rounding".i18n),
+                                      leading:
+                                          const Icon(FeatherIcons.gitCommit),
+                                      trailing: Text((settings.rounding / 10)
+                                          .toStringAsFixed(1)),
+                                    ),
+                                    PanelButton(
+                                      onPressed: () {
+                                        SettingsHelper.vibrate(context);
+                                        setState(() {});
+                                      },
+                                      title: Text("vibrate".i18n),
+                                      leading: const Icon(FeatherIcons.radio),
+                                      trailing: Text(vibrateTitle),
+                                    ),
+                                    PanelButton(
+                                      padding:
+                                          const EdgeInsets.only(left: 14.0),
+                                      onPressed: () {
+                                        SettingsHelper.bellDelay(context);
+                                        setState(() {});
+                                      },
+                                      title: Text(
+                                        "bell_delay".i18n,
+                                        style: TextStyle(
+                                            color: AppColors.of(context)
+                                                .text
+                                                .withOpacity(
+                                                    settings.bellDelayEnabled
+                                                        ? 1.0
+                                                        : .5)),
+                                      ),
+                                      leading: settings.bellDelayEnabled
+                                          ? const Icon(FeatherIcons.bell)
+                                          : Icon(FeatherIcons.bellOff,
+                                              color: AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.25)),
+                                      trailingDivider: true,
+                                      trailing: Switch(
+                                        onChanged: (v) => settings.update(
+                                            bellDelayEnabled: v),
+                                        value: settings.bellDelayEnabled,
+                                        activeColor: Theme.of(context)
+                                            .colorScheme
+                                            .secondary,
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            ),
+                          ),
+
+                          if (kDebugMode)
+                            Container(
+                              constraints: const BoxConstraints(maxWidth: 500),
+                              child: Padding(
+                                padding: const EdgeInsets.symmetric(
+                                    vertical: 12.0, horizontal: 24.0),
+                                child: Panel(
+                                  title: const Text("Debug"),
+                                  child: Column(
+                                    children: [
+                                      PanelButton(
+                                        title:
+                                            const Text("Subject Icon Gallery"),
+                                        leading: const Icon(CupertinoIcons
+                                            .rectangle_3_offgrid_fill),
+                                        trailing:
+                                            const Icon(Icons.arrow_forward),
+                                        onPressed: () {
+                                          Navigator.of(context,
+                                                  rootNavigator: true)
+                                              .push(
+                                            CupertinoPageRoute(
+                                                builder: (context) =>
+                                                    const SubjectIconGallery()),
+                                          );
+                                        },
+                                      )
+                                    ],
+                                  ),
+                                ),
+                              ),
+                            ),
+
+                          // Secret Settings
+                          if (__ss)
+                            Container(
+                              constraints: const BoxConstraints(maxWidth: 500),
+                              child: Padding(
+                                padding: const EdgeInsets.symmetric(
+                                    vertical: 12.0, horizontal: 24.0),
+                                child: Panel(
+                                  title: Text("secret".i18n),
+                                  child: Column(
+                                    children: [
+                                      // Good student mode
+                                      Material(
+                                        type: MaterialType.transparency,
+                                        child: SwitchListTile(
+                                          contentPadding:
+                                              const EdgeInsets.only(left: 12.0),
+                                          shape: RoundedRectangleBorder(
+                                              borderRadius:
+                                                  BorderRadius.circular(12.0)),
+                                          title: Text("goodstudent".i18n,
+                                              style: const TextStyle(
+                                                  fontWeight: FontWeight.w500)),
+                                          onChanged: (v) {
+                                            if (v) {
+                                              showDialog(
+                                                context: context,
+                                                builder: (context) =>
+                                                    WillPopScope(
+                                                  onWillPop: () async => false,
+                                                  child: AlertDialog(
+                                                    shape:
+                                                        RoundedRectangleBorder(
+                                                            borderRadius:
+                                                                BorderRadius
+                                                                    .circular(
+                                                                        12.0)),
+                                                    title:
+                                                        Text("attention".i18n),
+                                                    content: Text(
+                                                        "goodstudent_disclaimer"
+                                                            .i18n),
+                                                    actions: [
+                                                      ActionButton(
+                                                          label:
+                                                              "understand".i18n,
+                                                          onTap: () {
+                                                            Navigator.of(
+                                                                    context)
+                                                                .pop();
+                                                            settings.update(
+                                                                goodStudent: v);
+                                                            Provider.of<GradeProvider>(
+                                                                    context,
+                                                                    listen:
+                                                                        false)
+                                                                .fetch();
+                                                          })
+                                                    ],
+                                                  ),
+                                                ),
+                                              );
+                                            } else {
+                                              settings.update(goodStudent: v);
+                                              Provider.of<GradeProvider>(
+                                                      context,
+                                                      listen: false)
+                                                  .fetch();
+                                            }
+                                          },
+                                          value: settings.goodStudent,
+                                          activeColor: Theme.of(context)
+                                              .colorScheme
+                                              .secondary,
+                                        ),
+                                      ),
+
+                                      // Presentation mode
+                                      Material(
+                                        type: MaterialType.transparency,
+                                        child: SwitchListTile(
+                                          contentPadding:
+                                              const EdgeInsets.only(left: 12.0),
+                                          shape: RoundedRectangleBorder(
+                                              borderRadius:
+                                                  BorderRadius.circular(12.0)),
+                                          title: const Text("Presentation Mode",
+                                              style: TextStyle(
+                                                  fontWeight: FontWeight.w500)),
+                                          onChanged: (v) => settings.update(
+                                              presentationMode: v),
+                                          value: settings.presentationMode,
+                                          activeColor: Theme.of(context)
+                                              .colorScheme
+                                              .secondary,
+                                        ),
+                                      ),
+                                    ],
+                                  ),
+                                ),
+                              ),
+                            ),
+
+                          // Theme Settings
+                          Container(
+                            constraints: const BoxConstraints(maxWidth: 500),
+                            child: Padding(
+                              padding: const EdgeInsets.symmetric(
+                                  vertical: 12.0, horizontal: 24.0),
+                              child: Panel(
+                                title: Text("appearance".i18n),
+                                child: Column(
+                                  children: [
+                                    PanelButton(
+                                      onPressed: () {
+                                        SettingsHelper.theme(context);
+                                        setState(() {});
+                                      },
+                                      title: Text("theme".i18n),
+                                      leading: const Icon(FeatherIcons.sun),
+                                      trailing: Text(themeModeText),
+                                    ),
+                                    PanelButton(
+                                      onPressed: () async {
+                                        await _hideContainersController
+                                            .forward();
+                                        SettingsHelper.accentColor(context);
+                                        setState(() {});
+                                        _hideContainersController.reset();
+                                      },
+                                      title: Text("color".i18n),
+                                      leading: const Icon(FeatherIcons.droplet),
+                                      trailing: Container(
+                                        width: 12.0,
+                                        height: 12.0,
+                                        decoration: BoxDecoration(
+                                          color: Theme.of(context)
+                                              .colorScheme
+                                              .secondary,
+                                          shape: BoxShape.circle,
+                                        ),
+                                      ),
+                                    ),
+                                    PanelButton(
+                                      onPressed: () {
+                                        SettingsHelper.gradeColors(context);
+                                        setState(() {});
+                                      },
+                                      title: Text("grade_colors".i18n),
+                                      leading: const Icon(FeatherIcons.star),
+                                      trailing: Row(
+                                        mainAxisSize: MainAxisSize.min,
+                                        children: List.generate(
+                                          5,
+                                          (i) => Container(
+                                            margin: const EdgeInsets.only(
+                                                left: 2.0),
+                                            width: 12.0,
+                                            height: 12.0,
+                                            decoration: BoxDecoration(
+                                              shape: BoxShape.circle,
+                                              color: settings.gradeColors[i],
+                                            ),
+                                          ),
+                                        ),
+                                      ),
+                                    ),
+                                    Material(
+                                      type: MaterialType.transparency,
+                                      child: SwitchListTile(
+                                        contentPadding:
+                                            const EdgeInsets.only(left: 12.0),
+                                        shape: RoundedRectangleBorder(
+                                            borderRadius:
+                                                BorderRadius.circular(12.0)),
+                                        title: Row(
+                                          children: [
+                                            Icon(
+                                              FeatherIcons.barChart,
+                                              color: settings.graphClassAvg
+                                                  ? Theme.of(context)
+                                                      .colorScheme
+                                                      .secondary
+                                                  : AppColors.of(context)
+                                                      .text
+                                                      .withOpacity(.25),
+                                            ),
+                                            const SizedBox(width: 24.0),
+                                            Expanded(
+                                              child: Text(
+                                                "graph_class_avg".i18n,
+                                                style: TextStyle(
+                                                  fontWeight: FontWeight.w600,
+                                                  fontSize: 16.0,
+                                                  color: AppColors.of(context)
+                                                      .text
+                                                      .withOpacity(
+                                                          settings.graphClassAvg
+                                                              ? 1.0
+                                                              : .5),
+                                                ),
+                                              ),
+                                            ),
+                                          ],
+                                        ),
+                                        onChanged: (v) =>
+                                            settings.update(graphClassAvg: v),
+                                        value: settings.graphClassAvg,
+                                        activeColor: Theme.of(context)
+                                            .colorScheme
+                                            .secondary,
+                                      ),
+                                    ),
+                                    const PremiumIconPackSelector(),
+                                  ],
+                                ),
+                              ),
+                            ),
+                          ),
+
+                          // Notifications
+                          Container(
+                            constraints: const BoxConstraints(maxWidth: 500),
+                            child: Padding(
+                              padding: const EdgeInsets.symmetric(
+                                  vertical: 12.0, horizontal: 24.0),
+                              child: Panel(
+                                title: Text("notifications".i18n),
+                                child: Material(
+                                  type: MaterialType.transparency,
+                                  child: SwitchListTile(
+                                    contentPadding:
+                                        const EdgeInsets.only(left: 12.0),
+                                    shape: RoundedRectangleBorder(
+                                        borderRadius:
+                                            BorderRadius.circular(12.0)),
+                                    title: Row(
+                                      children: [
+                                        Icon(
+                                          Icons.newspaper_outlined,
+                                          color: settings.newsEnabled
+                                              ? Theme.of(context)
+                                                  .colorScheme
+                                                  .secondary
+                                              : AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.25),
+                                        ),
+                                        const SizedBox(width: 24.0),
+                                        Expanded(
+                                          child: Text(
+                                            "news".i18n,
+                                            style: TextStyle(
+                                              fontWeight: FontWeight.w600,
+                                              fontSize: 16.0,
+                                              color: AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(
+                                                      settings.newsEnabled
+                                                          ? 1.0
+                                                          : .5),
+                                            ),
+                                          ),
+                                        ),
+                                      ],
+                                    ),
+                                    onChanged: (v) =>
+                                        settings.update(newsEnabled: v),
+                                    value: settings.newsEnabled,
+                                    activeColor:
+                                        Theme.of(context).colorScheme.secondary,
+                                  ),
+                                ),
+                              ),
+                            ),
+                          ),
+
+                          // Extras
+                          Container(
+                            constraints: const BoxConstraints(maxWidth: 500),
+                            child: Padding(
+                              padding: const EdgeInsets.symmetric(
+                                  vertical: 12.0, horizontal: 24.0),
+                              child: Panel(
+                                title: Text("extras".i18n),
+                                child: Column(children: [
+                                  Material(
+                                    type: MaterialType.transparency,
+                                    child: SwitchListTile(
+                                      contentPadding:
+                                          const EdgeInsets.only(left: 12.0),
+                                      shape: RoundedRectangleBorder(
+                                          borderRadius:
+                                              BorderRadius.circular(12.0)),
+                                      title: Row(
+                                        children: [
+                                          Icon(
+                                            FeatherIcons.gift,
+                                            color: settings.gradeOpeningFun
+                                                ? Theme.of(context)
+                                                    .colorScheme
+                                                    .secondary
+                                                : AppColors.of(context)
+                                                    .text
+                                                    .withOpacity(.25),
+                                          ),
+                                          const SizedBox(width: 24.0),
+                                          Expanded(
+                                            child: Text(
+                                              "surprise_grades".i18n,
+                                              style: TextStyle(
+                                                fontWeight: FontWeight.w600,
+                                                fontSize: 16.0,
+                                                color: AppColors.of(context)
+                                                    .text
+                                                    .withOpacity(
+                                                        settings.gradeOpeningFun
+                                                            ? 1.0
+                                                            : .5),
+                                              ),
+                                            ),
+                                          ),
+                                        ],
+                                      ),
+                                      onChanged: (v) =>
+                                          settings.update(gradeOpeningFun: v),
+                                      value: settings.gradeOpeningFun,
+                                      activeColor: Theme.of(context)
+                                          .colorScheme
+                                          .secondary,
+                                    ),
+                                  ),
+                                ]),
+                              ),
+                            ),
+                          ),
+
+                          // About
+                          Container(
+                            constraints: const BoxConstraints(maxWidth: 500),
+                            child: Padding(
+                              padding: const EdgeInsets.symmetric(
+                                  vertical: 12.0, horizontal: 24.0),
+                              child: Panel(
+                                title: Text("about".i18n),
+                                child: Column(children: [
+                                  PanelButton(
+                                    leading: const Icon(FeatherIcons.atSign),
+                                    title: const Text("Discord"),
+                                    onPressed: () => launchUrl(
+                                        Uri.parse("https://refilc.hu/discord"),
+                                        mode: LaunchMode.externalApplication),
+                                  ),
+                                  PanelButton(
+                                    leading: const Icon(FeatherIcons.globe),
+                                    title: const Text("www.refilc.hu"),
+                                    onPressed: () => launchUrl(
+                                        Uri.parse("https://refilc.hu"),
+                                        mode: LaunchMode.externalApplication),
+                                  ),
+                                  PanelButton(
+                                    leading: const Icon(FeatherIcons.github),
+                                    title: const Text("Github"),
+                                    onPressed: () => launchUrl(
+                                        Uri.parse("https://github.com/filc"),
+                                        mode: LaunchMode.externalApplication),
+                                  ),
+                                  PanelButton(
+                                    leading: const Icon(FeatherIcons.mail),
+                                    title: Text("news".i18n),
+                                    onPressed: () => _openNews(context),
+                                  ),
+                                  PanelButton(
+                                    leading: const Icon(FeatherIcons.lock),
+                                    title: Text("privacy".i18n),
+                                    onPressed: () => _openPrivacy(context),
+                                  ),
+                                  PanelButton(
+                                    leading: const Icon(FeatherIcons.award),
+                                    title: Text("licenses".i18n),
+                                    onPressed: () =>
+                                        showLicensePage(context: context),
+                                  ),
+                                  Tooltip(
+                                    message: "data_collected".i18n,
+                                    padding: const EdgeInsets.all(4.0),
+                                    textStyle: TextStyle(
+                                        fontWeight: FontWeight.w500,
+                                        color: AppColors.of(context).text),
+                                    decoration: BoxDecoration(
+                                        color: Theme.of(context)
+                                            .colorScheme
+                                            .background),
+                                    child: Material(
+                                      type: MaterialType.transparency,
+                                      child: SwitchListTile(
+                                        contentPadding:
+                                            const EdgeInsets.only(left: 12.0),
+                                        shape: RoundedRectangleBorder(
+                                            borderRadius:
+                                                BorderRadius.circular(12.0)),
+                                        secondary: Icon(
+                                          FeatherIcons.barChart2,
+                                          color: settings.xFilcId != "none"
+                                              ? Theme.of(context)
+                                                  .colorScheme
+                                                  .secondary
+                                              : AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.25),
+                                        ),
+                                        title: Text(
+                                          "Analytics".i18n,
+                                          style: TextStyle(
+                                            fontWeight: FontWeight.w600,
+                                            fontSize: 16.0,
+                                            color: AppColors.of(context)
+                                                .text
+                                                .withOpacity(
+                                                    settings.xFilcId != "none"
+                                                        ? 1.0
+                                                        : .5),
+                                          ),
+                                        ),
+                                        subtitle: Text(
+                                          "Anonymous Usage Analytics".i18n,
+                                          style: TextStyle(
+                                            color: AppColors.of(context)
+                                                .text
+                                                .withOpacity(
+                                                    settings.xFilcId != "none"
+                                                        ? .5
+                                                        : .2),
+                                          ),
+                                        ),
+                                        onChanged: (v) {
+                                          String newId;
+                                          if (v == false) {
+                                            newId = "none";
+                                          } else if (settings.xFilcId ==
+                                              "none") {
+                                            newId = SettingsProvider
+                                                    .defaultSettings()
+                                                .xFilcId;
+                                          } else {
+                                            newId = settings.xFilcId;
+                                          }
+                                          settings.update(xFilcId: newId);
+                                        },
+                                        value: settings.xFilcId != "none",
+                                        activeColor: Theme.of(context)
+                                            .colorScheme
+                                            .secondary,
+                                      ),
+                                    ),
+                                  ),
+                                ]),
+                              ),
+                            ),
+                          ),
+                          if (settings.developerMode)
+                            Container(
+                              constraints: const BoxConstraints(maxWidth: 500),
+                              child: Padding(
+                                padding: const EdgeInsets.symmetric(
+                                    vertical: 12.0, horizontal: 24.0),
+                                child: Panel(
+                                  title: const Text("Developer Settings"),
+                                  child: Column(
+                                    children: [
+                                      Material(
+                                        type: MaterialType.transparency,
+                                        child: SwitchListTile(
+                                          contentPadding:
+                                              const EdgeInsets.only(left: 12.0),
+                                          shape: RoundedRectangleBorder(
+                                              borderRadius:
+                                                  BorderRadius.circular(12.0)),
+                                          title: const Text("Developer Mode",
+                                              style: TextStyle(
+                                                  fontWeight: FontWeight.w500)),
+                                          onChanged: (v) => settings.update(
+                                              developerMode: false),
+                                          value: settings.developerMode,
+                                          activeColor: Theme.of(context)
+                                              .colorScheme
+                                              .secondary,
+                                        ),
+                                      ),
+                                      PanelButton(
+                                        leading: const Icon(FeatherIcons.copy),
+                                        title: const Text("Copy JWT"),
+                                        onPressed: () => Clipboard.setData(
+                                            ClipboardData(
+                                                text: Provider.of<KretaClient>(
+                                                        context,
+                                                        listen: false)
+                                                    .accessToken!)),
+                                      ),
+                                      // if (Provider.of<PremiumProvider>(context,
+                                      //         listen: false)
+                                      //     .hasPremium)
+                                      //   PanelButton(
+                                      //     leading: const Icon(FeatherIcons.key),
+                                      //     title: const Text("Remove Premium"),
+                                      //     onPressed: () {
+                                      //       Provider.of<PremiumProvider>(
+                                      //               context,
+                                      //               listen: false)
+                                      //           .activate(removePremium: true);
+                                      //       settings.update(
+                                      //           accentColor: AccentColor.filc,
+                                      //           store: true);
+                                      //       Provider.of<ThemeModeObserver>(
+                                      //               context,
+                                      //               listen: false)
+                                      //           .changeTheme(settings.theme);
+                                      //     },
+                                      //   ),
+                                    ],
+                                  ),
+                                ),
+                              ),
+                            ),
+                        ],
+                      ),
+                      const SizedBox(
+                        height: 40,
+                      ),
+                      SafeArea(
+                        top: false,
+                        child: Center(
+                          child: GestureDetector(
+                            child: const Panel(
+                                title: Text("v" +
+                                    String.fromEnvironment("APPVER",
+                                        defaultValue: "?"))),
+                            onTap: () {
+                              if (devmodeCountdown > 0) {
+                                ScaffoldMessenger.of(context)
+                                    .showSnackBar(SnackBar(
+                                  duration: const Duration(milliseconds: 200),
+                                  content: Text(
+                                      "You are $devmodeCountdown taps away from Developer Mode."),
+                                ));
+
+                                setState(() => devmodeCountdown--);
+                              } else if (devmodeCountdown == 0) {
+                                ScaffoldMessenger.of(context)
+                                    .showSnackBar(const SnackBar(
+                                  content: Text(
+                                      "Developer Mode successfully activated."),
+                                ));
+
+                                settings.update(developerMode: true);
+
+                                setState(() => devmodeCountdown--);
+                              }
+                            },
+                          ),
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  void _openNews(BuildContext context) =>
+      Navigator.of(context, rootNavigator: true)
+          .push(CupertinoPageRoute(builder: (context) => const NewsScreen()));
+  void _openUpdates(BuildContext context) =>
+      UpdateView.show(updateProvider.releases.first, context: context);
+  void _openPrivacy(BuildContext context) => PrivacyView.show(context);
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart b/refilc_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
similarity index 97%
rename from filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
rename to refilc_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
index 530a2bf..9dd52f1 100644
--- a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
+++ b/refilc_desktop_ui/lib/screens/settings/settings_screen.i18n.dart
@@ -1,188 +1,188 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension SettingsLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "personal_details": "Personal Details",
-          "open_dkt": "Open DKT",
-          "edit_nickname": "Edit Nickname",
-          "edit_profile_picture": "Edit Profile Picture",
-          "remove_profile_picture": "Remove Profile Picture",
-          "light": "Light",
-          "dark": "Dark",
-          "system": "System",
-          "add_user": "Add User",
-          "log_out": "Log Out",
-          "update_available": "Update Available",
-          "general": "General",
-          "language": "Language",
-          "startpage": "Startpage",
-          "rounding": "Rounding",
-          "appearance": "Appearance",
-          "theme": "Theme",
-          "color": "Color",
-          "grade_colors": "Grade Colors",
-          "notifications": "Notifications",
-          "news": "News",
-          "extras": "Extras",
-          "about": "About",
-          "supporters": "Supporters",
-          "privacy": "Privacy Policy",
-          "licenses": "Licenses",
-          "vibrate": "Vibration",
-          "voff": "Off",
-          "vlight": "Light",
-          "vmedium": "Medium",
-          "vstrong": "Strong",
-          "cancel": "Cancel",
-          "done": "Done",
-          "reset": "Reset",
-          "open": "Open",
-          "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",
-          "goodstudent": "Good student mode",
-          "attention": "Attention!",
-          "goodstudent_disclaimer":
-              "reFilc can not be held liable for the usage of this feature.\n\n(if your mother beats you up because you showed her fake grades, you can only blame yourself for it)",
-          "understand": "I understand",
-          "secret": "Secret Settings",
-          "bell_delay": "Bell Delay",
-          "delay": "Delay",
-          "hurry": "Hurry",
-          "sync": "Synchronize",
-          "sync_help": "Press the Synchronize button when the bell rings.",
-          "surprise_grades": "Surprise Grades",
-          "icon_pack": "Icon Pack",
-          "change_username": "Set a nickname",
-          "Accent Color": "Accent Color",
-          "Background Color": "Background Color",
-          "Highlight Color": "Highlight Color",
-          "Adaptive Theme": "Adaptive Theme",
-        },
-        "hu_hu": {
-          "personal_details": "Személyes információk",
-          "open_dkt": "DKT megnyitása",
-          "edit_nickname": "Becenév szerkesztése",
-          "edit_profile_picture": "Profil-kép szerkesztése",
-          "remove_profile_picture": "Profil-kép törlése",
-          "light": "Világos",
-          "dark": "Sötét",
-          "system": "Rendszer",
-          "add_user": "Felhasználó hozzáadása",
-          "log_out": "Kijelentkezés",
-          "update_available": "Frissítés elérhető",
-          "general": "Általános",
-          "language": "Nyelv",
-          "startpage": "Kezdőlap",
-          "rounding": "Kerekítés",
-          "appearance": "Kinézet",
-          "theme": "Téma",
-          "color": "Színek",
-          "grade_colors": "Jegyek színei",
-          "notifications": "Értesítések",
-          "news": "Hírek",
-          "extras": "Extrák",
-          "about": "Névjegy",
-          "supporters": "Támogatók",
-          "privacy": "Adatvédelmi irányelvek",
-          "licenses": "Licenszek",
-          "vibrate": "Rezgés",
-          "voff": "Kikapcsolás",
-          "vlight": "Alacsony",
-          "vmedium": "Közepes",
-          "vstrong": "Erős",
-          "cancel": "Mégsem",
-          "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ó",
-          "Analytics": "Analitika",
-          "Anonymous Usage Analytics": "Névtelen használati analitika",
-          "graph_class_avg": "Osztályátlag a grafikonon",
-          "goodstudent": "Jó tanuló mód",
-          "attention": "Figyelem!",
-          "goodstudent_disclaimer":
-              "A reFilc minden felelősséget elhárít a funkció használatával kapcsolatban.\n\n(Értsd: ha az anyád megver, mert megtévesztő ábrákat mutattál neki, azért csakis magadadat hibáztathatod.)",
-          "understand": "Értem",
-          "secret": "Titkos Beállítások",
-          "bell_delay": "Csengő eltolódása",
-          "delay": "Késleltetés",
-          "hurry": "Siettetés",
-          "sync": "Szinkronizálás",
-          "sync_help": "Csengetéskor nyomd meg a Szinkronizálás gombot.",
-          "surprise_grades": "Meglepetés jegyek",
-          "icon_pack": "Ikon séma",
-          "change_username": "Becenév beállítása",
-          "Accent Color": "Egyedi szín",
-          "Background Color": "Háttér színe",
-          "Highlight Color": "Panelek színe",
-          "Adaptive Theme": "Adaptív téma",
-        },
-        "de_de": {
-          "personal_details": "Persönliche Angaben",
-          "open_dkt": "Öffnen DKT",
-          "edit_nickname": "Spitznamen bearbeiten",
-          "edit_profile_picture": "Profilbild bearbeiten",
-          "remove_profile_picture": "Profilbild entfernen",
-          "light": "Licht",
-          "dark": "Dunkel",
-          "system": "System",
-          "add_user": "Benutzer hinzufügen",
-          "log_out": "Abmelden",
-          "update_available": "Update verfügbar",
-          "general": "Allgemein",
-          "language": "Sprache",
-          "startpage": "Startseite",
-          "rounding": "Rundung",
-          "appearance": "Erscheinungsbild",
-          "theme": "Thema",
-          "color": "Farbe",
-          "grade_colors": "Grad Farben",
-          "notifications": "Benachrichtigungen",
-          "news": "Nachrichten",
-          "extras": "Extras",
-          "about": "Informationen",
-          "supporters": "Unterstützer",
-          "privacy": "Datenschutzbestimmungen",
-          "licenses": "Lizenzen",
-          "vibrate": "Vibration",
-          "voff": "Aus",
-          "vlight": "Leicht",
-          "vmedium": "Mittel",
-          "vstrong": "Stark",
-          "cancel": "Abbrechen",
-          "done": "Fertig",
-          "reset": "Zurücksetzen",
-          "open": "Öffnen",
-          "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",
-          "goodstudent": "Guter Student Modus",
-          "attention": "Achtung!",
-          "goodstudent_disclaimer": "Same in English.",
-          "understand": "Ich verstehe",
-          "secret": "Geheime Einstellungen",
-          "bell_delay": "Klingelverzögerung",
-          "delay": "Verzögern",
-          "hurry": "Eile",
-          "sync": "Synchronisieren",
-          "sync_help": "Drücken Sie die Sync-Taste, wenn die Glocke läutet.",
-          "surprise_grades": "Überraschungsnoten",
-          "icon_pack": "Icon-Pack",
-          "change_username": "Einen Spitznamen festlegen",
-          "Accent Color": "Accent Color",
-          "Background Color": "Background Color",
-          "Highlight Color": "Highlight Color",
-          "Adaptive Theme": "Adaptive Theme",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension SettingsLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "personal_details": "Personal Details",
+          "open_dkt": "Open DKT",
+          "edit_nickname": "Edit Nickname",
+          "edit_profile_picture": "Edit Profile Picture",
+          "remove_profile_picture": "Remove Profile Picture",
+          "light": "Light",
+          "dark": "Dark",
+          "system": "System",
+          "add_user": "Add User",
+          "log_out": "Log Out",
+          "update_available": "Update Available",
+          "general": "General",
+          "language": "Language",
+          "startpage": "Startpage",
+          "rounding": "Rounding",
+          "appearance": "Appearance",
+          "theme": "Theme",
+          "color": "Color",
+          "grade_colors": "Grade Colors",
+          "notifications": "Notifications",
+          "news": "News",
+          "extras": "Extras",
+          "about": "About",
+          "supporters": "Supporters",
+          "privacy": "Privacy Policy",
+          "licenses": "Licenses",
+          "vibrate": "Vibration",
+          "voff": "Off",
+          "vlight": "Light",
+          "vmedium": "Medium",
+          "vstrong": "Strong",
+          "cancel": "Cancel",
+          "done": "Done",
+          "reset": "Reset",
+          "open": "Open",
+          "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",
+          "goodstudent": "Good student mode",
+          "attention": "Attention!",
+          "goodstudent_disclaimer":
+              "reFilc can not be held liable for the usage of this feature.\n\n(if your mother beats you up because you showed her fake grades, you can only blame yourself for it)",
+          "understand": "I understand",
+          "secret": "Secret Settings",
+          "bell_delay": "Bell Delay",
+          "delay": "Delay",
+          "hurry": "Hurry",
+          "sync": "Synchronize",
+          "sync_help": "Press the Synchronize button when the bell rings.",
+          "surprise_grades": "Surprise Grades",
+          "icon_pack": "Icon Pack",
+          "change_username": "Set a nickname",
+          "Accent Color": "Accent Color",
+          "Background Color": "Background Color",
+          "Highlight Color": "Highlight Color",
+          "Adaptive Theme": "Adaptive Theme",
+        },
+        "hu_hu": {
+          "personal_details": "Személyes információk",
+          "open_dkt": "DKT megnyitása",
+          "edit_nickname": "Becenév szerkesztése",
+          "edit_profile_picture": "Profil-kép szerkesztése",
+          "remove_profile_picture": "Profil-kép törlése",
+          "light": "Világos",
+          "dark": "Sötét",
+          "system": "Rendszer",
+          "add_user": "Felhasználó hozzáadása",
+          "log_out": "Kijelentkezés",
+          "update_available": "Frissítés elérhető",
+          "general": "Általános",
+          "language": "Nyelv",
+          "startpage": "Kezdőlap",
+          "rounding": "Kerekítés",
+          "appearance": "Kinézet",
+          "theme": "Téma",
+          "color": "Színek",
+          "grade_colors": "Jegyek színei",
+          "notifications": "Értesítések",
+          "news": "Hírek",
+          "extras": "Extrák",
+          "about": "Névjegy",
+          "supporters": "Támogatók",
+          "privacy": "Adatvédelmi irányelvek",
+          "licenses": "Licenszek",
+          "vibrate": "Rezgés",
+          "voff": "Kikapcsolás",
+          "vlight": "Alacsony",
+          "vmedium": "Közepes",
+          "vstrong": "Erős",
+          "cancel": "Mégsem",
+          "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ó",
+          "Analytics": "Analitika",
+          "Anonymous Usage Analytics": "Névtelen használati analitika",
+          "graph_class_avg": "Osztályátlag a grafikonon",
+          "goodstudent": "Jó tanuló mód",
+          "attention": "Figyelem!",
+          "goodstudent_disclaimer":
+              "A reFilc minden felelősséget elhárít a funkció használatával kapcsolatban.\n\n(Értsd: ha az anyád megver, mert megtévesztő ábrákat mutattál neki, azért csakis magadadat hibáztathatod.)",
+          "understand": "Értem",
+          "secret": "Titkos Beállítások",
+          "bell_delay": "Csengő eltolódása",
+          "delay": "Késleltetés",
+          "hurry": "Siettetés",
+          "sync": "Szinkronizálás",
+          "sync_help": "Csengetéskor nyomd meg a Szinkronizálás gombot.",
+          "surprise_grades": "Meglepetés jegyek",
+          "icon_pack": "Ikon séma",
+          "change_username": "Becenév beállítása",
+          "Accent Color": "Egyedi szín",
+          "Background Color": "Háttér színe",
+          "Highlight Color": "Panelek színe",
+          "Adaptive Theme": "Adaptív téma",
+        },
+        "de_de": {
+          "personal_details": "Persönliche Angaben",
+          "open_dkt": "Öffnen DKT",
+          "edit_nickname": "Spitznamen bearbeiten",
+          "edit_profile_picture": "Profilbild bearbeiten",
+          "remove_profile_picture": "Profilbild entfernen",
+          "light": "Licht",
+          "dark": "Dunkel",
+          "system": "System",
+          "add_user": "Benutzer hinzufügen",
+          "log_out": "Abmelden",
+          "update_available": "Update verfügbar",
+          "general": "Allgemein",
+          "language": "Sprache",
+          "startpage": "Startseite",
+          "rounding": "Rundung",
+          "appearance": "Erscheinungsbild",
+          "theme": "Thema",
+          "color": "Farbe",
+          "grade_colors": "Grad Farben",
+          "notifications": "Benachrichtigungen",
+          "news": "Nachrichten",
+          "extras": "Extras",
+          "about": "Informationen",
+          "supporters": "Unterstützer",
+          "privacy": "Datenschutzbestimmungen",
+          "licenses": "Lizenzen",
+          "vibrate": "Vibration",
+          "voff": "Aus",
+          "vlight": "Leicht",
+          "vmedium": "Mittel",
+          "vstrong": "Stark",
+          "cancel": "Abbrechen",
+          "done": "Fertig",
+          "reset": "Zurücksetzen",
+          "open": "Öffnen",
+          "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",
+          "goodstudent": "Guter Student Modus",
+          "attention": "Achtung!",
+          "goodstudent_disclaimer": "Same in English.",
+          "understand": "Ich verstehe",
+          "secret": "Geheime Einstellungen",
+          "bell_delay": "Klingelverzögerung",
+          "delay": "Verzögern",
+          "hurry": "Eile",
+          "sync": "Synchronisieren",
+          "sync_help": "Drücken Sie die Sync-Taste, wenn die Glocke läutet.",
+          "surprise_grades": "Überraschungsnoten",
+          "icon_pack": "Icon-Pack",
+          "change_username": "Einen Spitznamen festlegen",
+          "Accent Color": "Accent Color",
+          "Background Color": "Background Color",
+          "Highlight Color": "Highlight Color",
+          "Adaptive Theme": "Adaptive Theme",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_desktop_ui/pubspec.yaml b/refilc_desktop_ui/pubspec.yaml
similarity index 73%
rename from filcnaplo_desktop_ui/pubspec.yaml
rename to refilc_desktop_ui/pubspec.yaml
index 2a1645a..ced7b9a 100644
--- a/filcnaplo_desktop_ui/pubspec.yaml
+++ b/refilc_desktop_ui/pubspec.yaml
@@ -1,34 +1,34 @@
-name: filcnaplo_desktop_ui
-publish_to: "none"
-
-environment:
-  sdk: ">=2.17.0 <3.0.0"
-
-dependencies:
-  flutter:
-    sdk: flutter
-
-  # Filcnaplo main dep
-  filcnaplo:
-    path: ../filcnaplo/
-  filcnaplo_kreta_api:
-    path: ../filcnaplo_kreta_api/
-
-  cupertino_icons: ^1.0.2
-  flutter_feather_icons: ^2.0.0+1
-  provider: ^5.0.0
-  url_launcher: ^6.0.9
-  flutter_linkify: ^5.0.2
-  flutter_markdown: ^0.6.5
-  animations: ^2.0.1
-  confetti: ^0.6.0
-  auto_size_text: ^3.0.0
-  flutter_acrylic: ^1.1.3
-  elegant_notification: ^1.6.1
-  flutter_staggered_grid_view: ^0.7.0
-
-dev_dependencies:
-  flutter_lints: ^1.0.0
-
-flutter:
-  uses-material-design: true
+name: refilc_desktop_ui
+publish_to: "none"
+
+environment:
+  sdk: ">=2.17.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+
+  # refilc main dep
+  refilc:
+    path: ../refilc/
+  refilc_kreta_api:
+    path: ../refilc_kreta_api/
+
+  cupertino_icons: ^1.0.2
+  flutter_feather_icons: ^2.0.0+1
+  provider: ^5.0.0
+  url_launcher: ^6.0.9
+  flutter_linkify: ^5.0.2
+  flutter_markdown: ^0.6.5
+  animations: ^2.0.1
+  confetti: ^0.6.0
+  auto_size_text: ^3.0.0
+  flutter_acrylic: ^1.1.3
+  elegant_notification: ^1.6.1
+  flutter_staggered_grid_view: ^0.7.0
+
+dev_dependencies:
+  flutter_lints: ^1.0.0
+
+flutter:
+  uses-material-design: true
diff --git a/filcnaplo_kreta_api/.github/dependabot.yml b/refilc_kreta_api/.github/dependabot.yml
similarity index 97%
rename from filcnaplo_kreta_api/.github/dependabot.yml
rename to refilc_kreta_api/.github/dependabot.yml
index 9fc48a7..8702968 100644
--- a/filcnaplo_kreta_api/.github/dependabot.yml
+++ b/refilc_kreta_api/.github/dependabot.yml
@@ -1,11 +1,11 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
-
-version: 2
-updates:
-  - package-ecosystem: "pub" # See documentation for possible values
-    directory: "/" # Location of package manifests
-    schedule:
-      interval: "daily"
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+  - package-ecosystem: "pub" # See documentation for possible values
+    directory: "/" # Location of package manifests
+    schedule:
+      interval: "daily"
diff --git a/filcnaplo_kreta_api/LICENSE b/refilc_kreta_api/LICENSE
similarity index 98%
rename from filcnaplo_kreta_api/LICENSE
rename to refilc_kreta_api/LICENSE
index 1024750..21b1553 100644
--- a/filcnaplo_kreta_api/LICENSE
+++ b/refilc_kreta_api/LICENSE
@@ -1,29 +1,29 @@
-BSD 3-Clause License
-
-Copyright (c) 2023, reFilc
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+BSD 3-Clause License
+
+Copyright (c) 2023, reFilc
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/filcnaplo_kreta_api/README.md b/refilc_kreta_api/README.md
similarity index 100%
rename from filcnaplo_kreta_api/README.md
rename to refilc_kreta_api/README.md
diff --git a/filcnaplo_premium/analysis_options.yaml b/refilc_kreta_api/analysis_options.yaml
similarity index 98%
rename from filcnaplo_premium/analysis_options.yaml
rename to refilc_kreta_api/analysis_options.yaml
index 16f5f56..fd16f92 100644
--- a/filcnaplo_premium/analysis_options.yaml
+++ b/refilc_kreta_api/analysis_options.yaml
@@ -1,28 +1,28 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
-  # The lint rules applied to this project can be customized in the
-  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
-  # included above or to enable additional rules. A list of all available lints
-  # and their documentation is published at
-  # https://dart-lang.github.io/linter/lints/index.html.
-  #
-  # Instead of disabling a lint rule for the entire project in the
-  # section below, it can also be suppressed for a single line of code
-  # or a specific dart file by using the `// ignore: name_of_lint` and
-  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
-  # producing the lint.
-  rules:
-    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
-    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/filcnaplo_kreta_api/lib/client/api.dart b/refilc_kreta_api/lib/client/api.dart
similarity index 97%
rename from filcnaplo_kreta_api/lib/client/api.dart
rename to refilc_kreta_api/lib/client/api.dart
index f3c18d0..33537e3 100644
--- a/filcnaplo_kreta_api/lib/client/api.dart
+++ b/refilc_kreta_api/lib/client/api.dart
@@ -1,125 +1,125 @@
-import 'package:intl/intl.dart';
-
-class KretaAPI {
-  // IDP API
-  static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
-  static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
-  static const clientId = "kreta-ellenorzo-mobile-android";
-
-  // ELLENORZO API
-  static String notes(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.notes;
-  static String events(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.events;
-  static String student(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.student;
-  static String grades(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.grades;
-  static String absences(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.absences;
-  static String groups(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
-  static String groupAverages(String iss, String uid) =>
-      BaseKreta.kreta(iss) +
-      KretaApiEndpoints.groupAverages +
-      "?oktatasiNevelesiFeladatUid=" +
-      uid;
-  static String averages(String iss, String uid) =>
-      BaseKreta.kreta(iss) +
-      KretaApiEndpoints.averages +
-      "?oktatasiNevelesiFeladatUid=" +
-      uid;
-  static String timetable(String iss, {DateTime? start, DateTime? end}) =>
-      BaseKreta.kreta(iss) +
-      KretaApiEndpoints.timetable +
-      (start != null && end != null
-          ? "?datumTol=" +
-              start.toUtc().toIso8601String() +
-              "&datumIg=" +
-              end.toUtc().toIso8601String()
-          : "");
-  static String exams(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
-  static String homework(String iss, {DateTime? start, String? id}) =>
-      BaseKreta.kreta(iss) +
-      KretaApiEndpoints.homework +
-      (id != null ? "/$id" : "") +
-      (id == null && start != null
-          ? "?datumTol=" + DateFormat('yyyy-MM-dd').format(start)
-          : "");
-  static String capabilities(String iss) =>
-      BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
-  static String downloadHomeworkAttachments(
-          String iss, String uid, String type) =>
-      BaseKreta.kreta(iss) +
-      KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
-
-  // ADMIN API
-  static const sendMessage =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.sendMessage;
-  static String messages(String endpoint) =>
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.messages(endpoint);
-  static String message(String id) =>
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.message(id);
-  static const recipientCategories =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
-  static const availableCategories =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
-  static const recipientsTeacher =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientsTeacher;
-  static const uploadAttachment =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
-  static String downloadAttachment(String id) =>
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.downloadAttachment(id);
-  static const trashMessage =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.trashMessage;
-  static const deleteMessage =
-      BaseKreta.kretaAdmin + KretaAdminEndpoints.deleteMessage;
-}
-
-class BaseKreta {
-  static String kreta(String iss) => "https://$iss.e-kreta.hu";
-  static const kretaIdp = "https://idp.e-kreta.hu";
-  static const kretaAdmin = "https://eugyintezes.e-kreta.hu";
-  static const kretaFiles = "https://files.e-kreta.hu";
-}
-
-class KretaApiEndpoints {
-  static const token = "/connect/token";
-  static const nonce = "/nonce";
-  static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
-  static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
-  static const student = "/ellenorzo/V3/Sajat/TanuloAdatlap";
-  static const grades = "/ellenorzo/V3/Sajat/Ertekelesek";
-  static const absences = "/ellenorzo/V3/Sajat/Mulasztasok";
-  static const groups = "/ellenorzo/V3/Sajat/OsztalyCsoportok";
-  static const groupAverages =
-      "/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/OsztalyAtlagok";
-  static const averages = "/ellenorzo/V3/idk";
-  static const timetable = "/ellenorzo/V3/Sajat/OrarendElemek";
-  static const exams = "/ellenorzo/V3/Sajat/BejelentettSzamonkeresek";
-  static const homework = "/ellenorzo/V3/Sajat/HaziFeladatok";
-  // static const homeworkDone = "/ellenorzo/V3/Sajat/HaziFeladatok/Megoldva"; // Removed from the API
-  static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
-  static String downloadHomeworkAttachments(String uid, String type) =>
-      "/ellenorzo/V3/Sajat/Csatolmany/$uid";
-}
-
-class KretaAdminEndpoints {
-  //static const messages = "/api/v1/kommunikacio/postaladaelemek/sajat";
-  static const sendMessage = "/api/v1/kommunikacio/uzenetek";
-  static String messages(String endpoint) =>
-      "/api/v1/kommunikacio/postaladaelemek/$endpoint";
-  static String message(String id) =>
-      "/api/v1/kommunikacio/postaladaelemek/$id";
-  static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
-  static const availableCategories = "/api/v1/kommunikacio/cimezhetotipusok";
-  static const recipientsTeacher = "/api/v1/kreta/alkalmazottak/tanar";
-  static const uploadAttachment = "/ideiglenesfajlok";
-  static String downloadAttachment(String id) =>
-      "/api/v1/dokumentumok/uzenetek/$id";
-  static const trashMessage = "/api/v1/kommunikacio/postaladaelemek/kuka";
-  static const deleteMessage = "/api/v1/kommunikacio/postaladaelemek/torles";
-  // profile management
-  static const editProfile = "/api/profilapi/saveprofildata";
-}
+import 'package:intl/intl.dart';
+
+class KretaAPI {
+  // IDP API
+  static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
+  static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
+  static const clientId = "kreta-ellenorzo-mobile-android";
+
+  // ELLENORZO API
+  static String notes(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.notes;
+  static String events(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.events;
+  static String student(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.student;
+  static String grades(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.grades;
+  static String absences(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.absences;
+  static String groups(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
+  static String groupAverages(String iss, String uid) =>
+      BaseKreta.kreta(iss) +
+      KretaApiEndpoints.groupAverages +
+      "?oktatasiNevelesiFeladatUid=" +
+      uid;
+  static String averages(String iss, String uid) =>
+      BaseKreta.kreta(iss) +
+      KretaApiEndpoints.averages +
+      "?oktatasiNevelesiFeladatUid=" +
+      uid;
+  static String timetable(String iss, {DateTime? start, DateTime? end}) =>
+      BaseKreta.kreta(iss) +
+      KretaApiEndpoints.timetable +
+      (start != null && end != null
+          ? "?datumTol=" +
+              start.toUtc().toIso8601String() +
+              "&datumIg=" +
+              end.toUtc().toIso8601String()
+          : "");
+  static String exams(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
+  static String homework(String iss, {DateTime? start, String? id}) =>
+      BaseKreta.kreta(iss) +
+      KretaApiEndpoints.homework +
+      (id != null ? "/$id" : "") +
+      (id == null && start != null
+          ? "?datumTol=" + DateFormat('yyyy-MM-dd').format(start)
+          : "");
+  static String capabilities(String iss) =>
+      BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
+  static String downloadHomeworkAttachments(
+          String iss, String uid, String type) =>
+      BaseKreta.kreta(iss) +
+      KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
+
+  // ADMIN API
+  static const sendMessage =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.sendMessage;
+  static String messages(String endpoint) =>
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.messages(endpoint);
+  static String message(String id) =>
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.message(id);
+  static const recipientCategories =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
+  static const availableCategories =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
+  static const recipientsTeacher =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientsTeacher;
+  static const uploadAttachment =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
+  static String downloadAttachment(String id) =>
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.downloadAttachment(id);
+  static const trashMessage =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.trashMessage;
+  static const deleteMessage =
+      BaseKreta.kretaAdmin + KretaAdminEndpoints.deleteMessage;
+}
+
+class BaseKreta {
+  static String kreta(String iss) => "https://$iss.e-kreta.hu";
+  static const kretaIdp = "https://idp.e-kreta.hu";
+  static const kretaAdmin = "https://eugyintezes.e-kreta.hu";
+  static const kretaFiles = "https://files.e-kreta.hu";
+}
+
+class KretaApiEndpoints {
+  static const token = "/connect/token";
+  static const nonce = "/nonce";
+  static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
+  static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
+  static const student = "/ellenorzo/V3/Sajat/TanuloAdatlap";
+  static const grades = "/ellenorzo/V3/Sajat/Ertekelesek";
+  static const absences = "/ellenorzo/V3/Sajat/Mulasztasok";
+  static const groups = "/ellenorzo/V3/Sajat/OsztalyCsoportok";
+  static const groupAverages =
+      "/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/OsztalyAtlagok";
+  static const averages = "/ellenorzo/V3/idk";
+  static const timetable = "/ellenorzo/V3/Sajat/OrarendElemek";
+  static const exams = "/ellenorzo/V3/Sajat/BejelentettSzamonkeresek";
+  static const homework = "/ellenorzo/V3/Sajat/HaziFeladatok";
+  // static const homeworkDone = "/ellenorzo/V3/Sajat/HaziFeladatok/Megoldva"; // Removed from the API
+  static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
+  static String downloadHomeworkAttachments(String uid, String type) =>
+      "/ellenorzo/V3/Sajat/Csatolmany/$uid";
+}
+
+class KretaAdminEndpoints {
+  //static const messages = "/api/v1/kommunikacio/postaladaelemek/sajat";
+  static const sendMessage = "/api/v1/kommunikacio/uzenetek";
+  static String messages(String endpoint) =>
+      "/api/v1/kommunikacio/postaladaelemek/$endpoint";
+  static String message(String id) =>
+      "/api/v1/kommunikacio/postaladaelemek/$id";
+  static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
+  static const availableCategories = "/api/v1/kommunikacio/cimezhetotipusok";
+  static const recipientsTeacher = "/api/v1/kreta/alkalmazottak/tanar";
+  static const uploadAttachment = "/ideiglenesfajlok";
+  static String downloadAttachment(String id) =>
+      "/api/v1/dokumentumok/uzenetek/$id";
+  static const trashMessage = "/api/v1/kommunikacio/postaladaelemek/kuka";
+  static const deleteMessage = "/api/v1/kommunikacio/postaladaelemek/torles";
+  // profile management
+  static const editProfile = "/api/profilapi/saveprofildata";
+}
diff --git a/filcnaplo_kreta_api/lib/client/client.dart b/refilc_kreta_api/lib/client/client.dart
similarity index 90%
rename from filcnaplo_kreta_api/lib/client/client.dart
rename to refilc_kreta_api/lib/client/client.dart
index f150e3b..eff5a4c 100644
--- a/filcnaplo_kreta_api/lib/client/client.dart
+++ b/refilc_kreta_api/lib/client/client.dart
@@ -1,219 +1,219 @@
-// ignore_for_file: avoid_print
-
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:filcnaplo/api/login.dart';
-import 'package:filcnaplo/api/nonce.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo/utils/jwt.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/io_client.dart' as http;
-import 'dart:async';
-
-class KretaClient {
-  String? accessToken;
-  String? refreshToken;
-  String? idToken;
-  String? userAgent;
-  late http.Client client;
-
-  late final SettingsProvider _settings;
-  late final UserProvider _user;
-  late final StatusProvider _status;
-
-  KretaClient({
-    this.accessToken,
-    required SettingsProvider settings,
-    required UserProvider user,
-    required StatusProvider status,
-  })  : _settings = settings,
-        _user = user,
-        _status = status,
-        userAgent = settings.config.userAgent {
-    var ioclient = HttpClient();
-    ioclient.badCertificateCallback = _checkCerts;
-    client = http.IOClient(ioclient);
-  }
-
-  bool _checkCerts(X509Certificate cert, String host, int port) {
-    return _settings.developerMode;
-  }
-
-  Future<dynamic> getAPI(
-    String url, {
-    Map<String, String>? headers,
-    bool autoHeader = true,
-    bool json = true,
-    bool rawResponse = false,
-  }) async {
-    Map<String, String> headerMap;
-
-    if (rawResponse) json = false;
-
-    if (headers != null) {
-      headerMap = headers;
-    } else {
-      headerMap = {};
-    }
-
-    try {
-      http.Response? res;
-
-      for (int i = 0; i < 3; i++) {
-        if (autoHeader) {
-          if (!headerMap.containsKey("authorization") && accessToken != null) {
-            headerMap["authorization"] = "Bearer $accessToken";
-          }
-          if (!headerMap.containsKey("user-agent") && userAgent != null) {
-            headerMap["user-agent"] = "$userAgent";
-          }
-        }
-
-        res = await client.get(Uri.parse(url), headers: headerMap);
-        _status.triggerRequest(res);
-
-        if (res.statusCode == 401) {
-          await refreshLogin();
-          headerMap.remove("authorization");
-        } else {
-          break;
-        }
-
-        // Wait before retrying
-        await Future.delayed(const Duration(milliseconds: 500));
-      }
-
-      if (res == null) throw "Login error";
-      if (res.body == 'invalid_grant' || res.body.replaceAll(' ', '') == '') {
-        throw "Auth error";
-      }
-
-      if (json) {
-        return jsonDecode(res.body);
-      } else if (rawResponse) {
-        return res.bodyBytes;
-      } else {
-        return res.body;
-      }
-    } on http.ClientException catch (error) {
-      print(
-          "ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
-    } catch (error) {
-      print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
-    }
-  }
-
-  Future<dynamic> postAPI(
-    String url, {
-    Map<String, String>? headers,
-    bool autoHeader = true,
-    bool json = true,
-    Object? body,
-  }) async {
-    Map<String, String> headerMap;
-
-    if (headers != null) {
-      headerMap = headers;
-    } else {
-      headerMap = {};
-    }
-
-    try {
-      http.Response? res;
-
-      for (int i = 0; i < 3; i++) {
-        if (autoHeader) {
-          if (!headerMap.containsKey("authorization") && accessToken != null) {
-            headerMap["authorization"] = "Bearer $accessToken";
-          }
-          if (!headerMap.containsKey("user-agent") && userAgent != null) {
-            headerMap["user-agent"] = "$userAgent";
-          }
-          if (!headerMap.containsKey("content-type")) {
-            headerMap["content-type"] = "application/json";
-          }
-        }
-
-        res = await client.post(Uri.parse(url), headers: headerMap, body: body);
-        if (res.statusCode == 401) {
-          await refreshLogin();
-          headerMap.remove("authorization");
-        } else {
-          break;
-        }
-      }
-
-      if (res == null) throw "Login error";
-
-      if (json) {
-        return jsonDecode(res.body);
-      } else {
-        return res.body;
-      }
-    } on http.ClientException catch (error) {
-      print(
-          "ERROR: KretaClient.postAPI ($url) ClientException: ${error.message}");
-    } catch (error) {
-      print("ERROR: KretaClient.postAPI ($url) ${error.runtimeType}: $error");
-    }
-  }
-
-  Future<void> refreshLogin() async {
-    User? loginUser = _user.user;
-    if (loginUser == null) return;
-
-    Map<String, String> headers = {
-      "content-type": "application/x-www-form-urlencoded",
-    };
-
-    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,
-        ));
-
-    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;
-    }
-
-    if (refreshToken != null) {
-      Map? refreshRes = 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"];
-        }
-      }
-    }
-  }
-}
+// ignore_for_file: avoid_print
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:refilc/api/login.dart';
+import 'package:refilc/api/nonce.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_kreta_api/client/api.dart';
+import 'package:http/http.dart' as http;
+import 'package:http/io_client.dart' as http;
+import 'dart:async';
+
+class KretaClient {
+  String? accessToken;
+  String? refreshToken;
+  String? idToken;
+  String? userAgent;
+  late http.Client client;
+
+  late final SettingsProvider _settings;
+  late final UserProvider _user;
+  late final StatusProvider _status;
+
+  KretaClient({
+    this.accessToken,
+    required SettingsProvider settings,
+    required UserProvider user,
+    required StatusProvider status,
+  })  : _settings = settings,
+        _user = user,
+        _status = status,
+        userAgent = settings.config.userAgent {
+    var ioclient = HttpClient();
+    ioclient.badCertificateCallback = _checkCerts;
+    client = http.IOClient(ioclient);
+  }
+
+  bool _checkCerts(X509Certificate cert, String host, int port) {
+    return _settings.developerMode;
+  }
+
+  Future<dynamic> getAPI(
+    String url, {
+    Map<String, String>? headers,
+    bool autoHeader = true,
+    bool json = true,
+    bool rawResponse = false,
+  }) async {
+    Map<String, String> headerMap;
+
+    if (rawResponse) json = false;
+
+    if (headers != null) {
+      headerMap = headers;
+    } else {
+      headerMap = {};
+    }
+
+    try {
+      http.Response? res;
+
+      for (int i = 0; i < 3; i++) {
+        if (autoHeader) {
+          if (!headerMap.containsKey("authorization") && accessToken != null) {
+            headerMap["authorization"] = "Bearer $accessToken";
+          }
+          if (!headerMap.containsKey("user-agent") && userAgent != null) {
+            headerMap["user-agent"] = "$userAgent";
+          }
+        }
+
+        res = await client.get(Uri.parse(url), headers: headerMap);
+        _status.triggerRequest(res);
+
+        if (res.statusCode == 401) {
+          await refreshLogin();
+          headerMap.remove("authorization");
+        } else {
+          break;
+        }
+
+        // Wait before retrying
+        await Future.delayed(const Duration(milliseconds: 500));
+      }
+
+      if (res == null) throw "Login error";
+      if (res.body == 'invalid_grant' || res.body.replaceAll(' ', '') == '') {
+        throw "Auth error";
+      }
+
+      if (json) {
+        return jsonDecode(res.body);
+      } else if (rawResponse) {
+        return res.bodyBytes;
+      } else {
+        return res.body;
+      }
+    } on http.ClientException catch (error) {
+      print(
+          "ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
+    } catch (error) {
+      print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
+    }
+  }
+
+  Future<dynamic> postAPI(
+    String url, {
+    Map<String, String>? headers,
+    bool autoHeader = true,
+    bool json = true,
+    Object? body,
+  }) async {
+    Map<String, String> headerMap;
+
+    if (headers != null) {
+      headerMap = headers;
+    } else {
+      headerMap = {};
+    }
+
+    try {
+      http.Response? res;
+
+      for (int i = 0; i < 3; i++) {
+        if (autoHeader) {
+          if (!headerMap.containsKey("authorization") && accessToken != null) {
+            headerMap["authorization"] = "Bearer $accessToken";
+          }
+          if (!headerMap.containsKey("user-agent") && userAgent != null) {
+            headerMap["user-agent"] = "$userAgent";
+          }
+          if (!headerMap.containsKey("content-type")) {
+            headerMap["content-type"] = "application/json";
+          }
+        }
+
+        res = await client.post(Uri.parse(url), headers: headerMap, body: body);
+        if (res.statusCode == 401) {
+          await refreshLogin();
+          headerMap.remove("authorization");
+        } else {
+          break;
+        }
+      }
+
+      if (res == null) throw "Login error";
+
+      if (json) {
+        return jsonDecode(res.body);
+      } else {
+        return res.body;
+      }
+    } on http.ClientException catch (error) {
+      print(
+          "ERROR: KretaClient.postAPI ($url) ClientException: ${error.message}");
+    } catch (error) {
+      print("ERROR: KretaClient.postAPI ($url) ${error.runtimeType}: $error");
+    }
+  }
+
+  Future<void> refreshLogin() async {
+    User? loginUser = _user.user;
+    if (loginUser == null) return;
+
+    Map<String, String> headers = {
+      "content-type": "application/x-www-form-urlencoded",
+    };
+
+    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,
+        ));
+
+    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;
+    }
+
+    if (refreshToken != null) {
+      Map? refreshRes = 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"];
+        }
+      }
+    }
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/controllers/profile_controller.dart b/refilc_kreta_api/lib/controllers/profile_controller.dart
similarity index 100%
rename from filcnaplo_kreta_api/lib/controllers/profile_controller.dart
rename to refilc_kreta_api/lib/controllers/profile_controller.dart
diff --git a/filcnaplo_kreta_api/lib/controllers/timetable_controller.dart b/refilc_kreta_api/lib/controllers/timetable_controller.dart
similarity index 92%
rename from filcnaplo_kreta_api/lib/controllers/timetable_controller.dart
rename to refilc_kreta_api/lib/controllers/timetable_controller.dart
index f552062..9fe2924 100644
--- a/filcnaplo_kreta_api/lib/controllers/timetable_controller.dart
+++ b/refilc_kreta_api/lib/controllers/timetable_controller.dart
@@ -1,241 +1,241 @@
-// ignore_for_file: avoid_print
-
-import 'dart:async';
-import 'dart:developer';
-import 'dart:math' as math;
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.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/widgets.dart';
-import 'package:provider/provider.dart';
-
-enum LoadType { initial, offline, loading, online }
-
-class TimetableController extends ChangeNotifier {
-  late Week currentWeek;
-  int currentWeekId = -1;
-  late int previousWeekId;
-  List<List<Lesson>>? days;
-  LoadType loadType = LoadType.initial;
-
-  TimetableController() {
-    current();
-  }
-
-  static int getWeekId(Week week) =>
-      (week.start.difference(getSchoolYearStart()).inDays /
-              DateTime.daysPerWeek)
-          .ceil();
-
-  static DateTime getSchoolYearStart() {
-    DateTime now = DateTime.now();
-    DateTime nowStart = _getYearStart(now.year);
-
-    if (nowStart.isBefore(now)) {
-      return nowStart;
-    } else {
-      return _getYearStart(now.year - 1);
-    }
-  }
-
-  static DateTime _getYearStart(int year) {
-    var s1 = DateTime(year, DateTime.september, 1);
-    if (s1.weekday == 6) {
-      s1.add(const Duration(days: 2));
-    } else if (s1.weekday == 7) {
-      s1.add(const Duration(days: 1));
-    }
-    return s1;
-  }
-
-  // Jump shortcuts
-  Future<void> next(BuildContext context) =>
-      jump(Week.fromId(currentWeekId + 1), context: context);
-  Future<void> previous(BuildContext context) =>
-      jump(Week.fromId(currentWeekId - 1), context: context);
-  void current() {
-    Week week = Week.current();
-    int id = getWeekId(week);
-
-    if (id > 51) id = 51;
-    if (id < 0) id = 0;
-
-    _setWeek(Week.fromId(id));
-  }
-
-  Future<void> jump(Week week,
-      {required BuildContext context,
-      bool initial = false,
-      bool skip = false,
-      bool loader = true}) async {
-    if (_setWeek(week)) return;
-
-    loadType = LoadType.initial;
-
-    if (loader) {
-      days = null;
-
-      // Don't start loading on init
-      if (!initial) notifyListeners();
-    }
-
-    days = _sortDays(week, context: context);
-
-    if (week != currentWeek) return;
-
-    loadType = LoadType.loading;
-
-    notifyListeners();
-
-    try {
-      await _fetchWeek(week, context: context).timeout(
-          const Duration(seconds: 5),
-          onTimeout: (() => throw "timeout"));
-      loadType = LoadType.online;
-    } catch (error, stack) {
-      print("ERROR: TimetableController.jump: $error\n$stack");
-      loadType = LoadType.offline;
-    }
-
-    if (week != currentWeek) return;
-
-    days = _sortDays(week, context: context);
-
-    if (week != currentWeek) return;
-
-    // Jump to next week on weekends
-    if (skip &&
-        (days?.length ?? 0) > 0 &&
-        days!.last.last.end.isBefore(DateTime.now())) return next(context);
-
-    notifyListeners();
-  }
-
-  bool _setWeek(Week week) {
-    int id = getWeekId(week);
-    if (id > 51) return true; // Max 52.
-    if (id < 0) return true; // Min 1.
-
-    // Set week start to Sept. 1 of first week
-    if (!_differentDate(week.start, Week.fromId(0).start)) {
-      week.start = TimetableController.getSchoolYearStart();
-    }
-
-    currentWeek = week;
-    previousWeekId = currentWeekId;
-    currentWeekId = id;
-    return false;
-  }
-
-  Future<void> _fetchWeek(Week week, {required BuildContext context}) async {
-    await Future.wait([
-      context.read<TimetableProvider>().fetch(week: week),
-      context.read<HomeworkProvider>().fetch(from: week.start, db: false),
-    ]);
-  }
-
-  List<List<Lesson>> _sortDays(Week week, {required BuildContext context}) {
-    List<List<Lesson>> days = [];
-
-    try {
-      final timetableProvider = context.read<TimetableProvider>();
-
-      List<Lesson> lessons = timetableProvider.getWeek(week) ?? [];
-
-      if (lessons.isNotEmpty) {
-        days.add([]);
-        lessons.sort((a, b) => a.date.compareTo(b.date));
-        for (var lesson in lessons) {
-          if (days.last.isNotEmpty &&
-              _differentDate(lesson.date, days.last.last.date)) days.add([]);
-          days.last.add(lesson);
-        }
-
-        for (int i = 0; i < days.length; i++) {
-          List<Lesson> _day = List.castFrom(days[i]);
-
-          List<int> lessonIndexes = _getIndexes(_day);
-          int minIndex = 0, maxIndex = 0;
-
-          if (lessonIndexes.isNotEmpty) {
-            minIndex = lessonIndexes.reduce(math.min);
-            maxIndex = lessonIndexes.reduce(math.max);
-          }
-
-          List<Lesson> day = [];
-
-          if (lessonIndexes.isNotEmpty) {
-            // Fill missing indexes with empty spaces
-            for (var i in List<int>.generate(
-                maxIndex - minIndex + 1, (int i) => minIndex + i)) {
-              List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
-
-              // Empty lesson
-              if (indexLessons.isEmpty) {
-                // Get start date by previous lesson
-                List<Lesson> prevLesson = _getLessonsByIndex(day, i - 1);
-                try {
-                  DateTime startDate =
-                      prevLesson.last.start.add(const Duration(seconds: 1));
-                  indexLessons.add(Lesson.fromJson({
-                    'isEmpty': true,
-                    'Oraszam': i,
-                    'KezdetIdopont': startDate.toIso8601String()
-                  }));
-                  // ignore: empty_catches
-                } catch (e) {}
-              }
-
-              day.addAll(indexLessons);
-            }
-          }
-
-          // Additional lessons
-          day.addAll(_day.where((l) =>
-              int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
-
-          day.sort((a, b) => a.start.compareTo(b.start));
-
-          // Special Dates
-          for (var l in _day) {
-            l.subject.id == '' ? day.insert(0, l) : null;
-          }
-
-          days[i] = day;
-        }
-      }
-    } catch (e) {
-      log("_sortDays error: $e");
-    }
-
-    return days;
-  }
-
-  List<Lesson> _getLessonsByIndex(List<Lesson> lessons, int index) {
-    List<Lesson> ret = [];
-
-    for (var lesson in lessons) {
-      int? lessonIndex = int.tryParse(lesson.lessonIndex);
-
-      if (lessonIndex != null && lessonIndex == index) {
-        ret.add(lesson);
-      }
-    }
-
-    return ret;
-  }
-
-  List<int> _getIndexes(List<Lesson> lessons) {
-    List<int> indexes = [];
-    for (var l in lessons) {
-      int? index = int.tryParse(l.lessonIndex);
-      if (index != null) indexes.add(index);
-    }
-    return indexes;
-  }
-
-  bool _differentDate(DateTime a, DateTime b) =>
-      !(a.year == b.year && a.month == b.month && a.day == b.day);
-}
+// ignore_for_file: avoid_print
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:math' as math;
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:provider/provider.dart';
+
+enum LoadType { initial, offline, loading, online }
+
+class TimetableController extends ChangeNotifier {
+  late Week currentWeek;
+  int currentWeekId = -1;
+  late int previousWeekId;
+  List<List<Lesson>>? days;
+  LoadType loadType = LoadType.initial;
+
+  TimetableController() {
+    current();
+  }
+
+  static int getWeekId(Week week) =>
+      (week.start.difference(getSchoolYearStart()).inDays /
+              DateTime.daysPerWeek)
+          .ceil();
+
+  static DateTime getSchoolYearStart() {
+    DateTime now = DateTime.now();
+    DateTime nowStart = _getYearStart(now.year);
+
+    if (nowStart.isBefore(now)) {
+      return nowStart;
+    } else {
+      return _getYearStart(now.year - 1);
+    }
+  }
+
+  static DateTime _getYearStart(int year) {
+    var s1 = DateTime(year, DateTime.september, 1);
+    if (s1.weekday == 6) {
+      s1.add(const Duration(days: 2));
+    } else if (s1.weekday == 7) {
+      s1.add(const Duration(days: 1));
+    }
+    return s1;
+  }
+
+  // Jump shortcuts
+  Future<void> next(BuildContext context) =>
+      jump(Week.fromId(currentWeekId + 1), context: context);
+  Future<void> previous(BuildContext context) =>
+      jump(Week.fromId(currentWeekId - 1), context: context);
+  void current() {
+    Week week = Week.current();
+    int id = getWeekId(week);
+
+    if (id > 51) id = 51;
+    if (id < 0) id = 0;
+
+    _setWeek(Week.fromId(id));
+  }
+
+  Future<void> jump(Week week,
+      {required BuildContext context,
+      bool initial = false,
+      bool skip = false,
+      bool loader = true}) async {
+    if (_setWeek(week)) return;
+
+    loadType = LoadType.initial;
+
+    if (loader) {
+      days = null;
+
+      // Don't start loading on init
+      if (!initial) notifyListeners();
+    }
+
+    days = _sortDays(week, context: context);
+
+    if (week != currentWeek) return;
+
+    loadType = LoadType.loading;
+
+    notifyListeners();
+
+    try {
+      await _fetchWeek(week, context: context).timeout(
+          const Duration(seconds: 5),
+          onTimeout: (() => throw "timeout"));
+      loadType = LoadType.online;
+    } catch (error, stack) {
+      print("ERROR: TimetableController.jump: $error\n$stack");
+      loadType = LoadType.offline;
+    }
+
+    if (week != currentWeek) return;
+
+    days = _sortDays(week, context: context);
+
+    if (week != currentWeek) return;
+
+    // Jump to next week on weekends
+    if (skip &&
+        (days?.length ?? 0) > 0 &&
+        days!.last.last.end.isBefore(DateTime.now())) return next(context);
+
+    notifyListeners();
+  }
+
+  bool _setWeek(Week week) {
+    int id = getWeekId(week);
+    if (id > 51) return true; // Max 52.
+    if (id < 0) return true; // Min 1.
+
+    // Set week start to Sept. 1 of first week
+    if (!_differentDate(week.start, Week.fromId(0).start)) {
+      week.start = TimetableController.getSchoolYearStart();
+    }
+
+    currentWeek = week;
+    previousWeekId = currentWeekId;
+    currentWeekId = id;
+    return false;
+  }
+
+  Future<void> _fetchWeek(Week week, {required BuildContext context}) async {
+    await Future.wait([
+      context.read<TimetableProvider>().fetch(week: week),
+      context.read<HomeworkProvider>().fetch(from: week.start, db: false),
+    ]);
+  }
+
+  List<List<Lesson>> _sortDays(Week week, {required BuildContext context}) {
+    List<List<Lesson>> days = [];
+
+    try {
+      final timetableProvider = context.read<TimetableProvider>();
+
+      List<Lesson> lessons = timetableProvider.getWeek(week) ?? [];
+
+      if (lessons.isNotEmpty) {
+        days.add([]);
+        lessons.sort((a, b) => a.date.compareTo(b.date));
+        for (var lesson in lessons) {
+          if (days.last.isNotEmpty &&
+              _differentDate(lesson.date, days.last.last.date)) days.add([]);
+          days.last.add(lesson);
+        }
+
+        for (int i = 0; i < days.length; i++) {
+          List<Lesson> _day = List.castFrom(days[i]);
+
+          List<int> lessonIndexes = _getIndexes(_day);
+          int minIndex = 0, maxIndex = 0;
+
+          if (lessonIndexes.isNotEmpty) {
+            minIndex = lessonIndexes.reduce(math.min);
+            maxIndex = lessonIndexes.reduce(math.max);
+          }
+
+          List<Lesson> day = [];
+
+          if (lessonIndexes.isNotEmpty) {
+            // Fill missing indexes with empty spaces
+            for (var i in List<int>.generate(
+                maxIndex - minIndex + 1, (int i) => minIndex + i)) {
+              List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
+
+              // Empty lesson
+              if (indexLessons.isEmpty) {
+                // Get start date by previous lesson
+                List<Lesson> prevLesson = _getLessonsByIndex(day, i - 1);
+                try {
+                  DateTime startDate =
+                      prevLesson.last.start.add(const Duration(seconds: 1));
+                  indexLessons.add(Lesson.fromJson({
+                    'isEmpty': true,
+                    'Oraszam': i,
+                    'KezdetIdopont': startDate.toIso8601String()
+                  }));
+                  // ignore: empty_catches
+                } catch (e) {}
+              }
+
+              day.addAll(indexLessons);
+            }
+          }
+
+          // Additional lessons
+          day.addAll(_day.where((l) =>
+              int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
+
+          day.sort((a, b) => a.start.compareTo(b.start));
+
+          // Special Dates
+          for (var l in _day) {
+            l.subject.id == '' ? day.insert(0, l) : null;
+          }
+
+          days[i] = day;
+        }
+      }
+    } catch (e) {
+      log("_sortDays error: $e");
+    }
+
+    return days;
+  }
+
+  List<Lesson> _getLessonsByIndex(List<Lesson> lessons, int index) {
+    List<Lesson> ret = [];
+
+    for (var lesson in lessons) {
+      int? lessonIndex = int.tryParse(lesson.lessonIndex);
+
+      if (lessonIndex != null && lessonIndex == index) {
+        ret.add(lesson);
+      }
+    }
+
+    return ret;
+  }
+
+  List<int> _getIndexes(List<Lesson> lessons) {
+    List<int> indexes = [];
+    for (var l in lessons) {
+      int? index = int.tryParse(l.lessonIndex);
+      if (index != null) indexes.add(index);
+    }
+    return indexes;
+  }
+
+  bool _differentDate(DateTime a, DateTime b) =>
+      !(a.year == b.year && a.month == b.month && a.day == b.day);
+}
diff --git a/filcnaplo_kreta_api/lib/models/absence.dart b/refilc_kreta_api/lib/models/absence.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/absence.dart
rename to refilc_kreta_api/lib/models/absence.dart
index 9997351..fb1638d 100644
--- a/filcnaplo_kreta_api/lib/models/absence.dart
+++ b/refilc_kreta_api/lib/models/absence.dart
@@ -1,98 +1,98 @@
-import "category.dart";
-import "subject.dart";
-import "teacher.dart";
-
-class Absence {
-  Map? json;
-  String id;
-  DateTime date;
-  int delay;
-  DateTime submitDate;
-  Teacher teacher;
-  Justification state;
-  Category? justification;
-  Category? type;
-  Category? mode;
-  Subject subject;
-  DateTime lessonStart;
-  DateTime lessonEnd;
-  int? lessonIndex;
-  String group;
-  bool isSeen;
-  @override
-  bool operator ==(Object other) =>
-      identical(this, other) ||
-      other is Absence && runtimeType == other.runtimeType && id == other.id;
-
-  @override
-  int get hashCode => id.hashCode;
-
-  Absence({
-    required this.id,
-    required this.date,
-    required this.delay,
-    required this.submitDate,
-    required this.teacher,
-    required this.state,
-    this.justification,
-    this.type,
-    this.mode,
-    required this.subject,
-    required this.lessonStart,
-    required this.lessonEnd,
-    this.lessonIndex,
-    required this.group,
-    this.json,
-    this.isSeen = false,
-  });
-
-  factory Absence.fromJson(Map json) {
-    DateTime lessonStart;
-    DateTime lessonEnd;
-    int? lessonIndex;
-    if (json["Ora"] != null) {
-      lessonStart = json["Ora"]["KezdoDatum"] != null
-          ? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal()
-          : DateTime(0);
-      lessonEnd = json["Ora"]["VegDatum"] != null
-          ? DateTime.parse(json["Ora"]["VegDatum"]).toLocal()
-          : DateTime(0);
-      lessonIndex = json["Ora"]["Oraszam"];
-    } else {
-      lessonStart = DateTime(0);
-      lessonEnd = DateTime(0);
-    }
-
-    return Absence(
-      id: json["Uid"],
-      date: json["Datum"] != null
-          ? DateTime.parse(json["Datum"]).toLocal()
-          : DateTime(0),
-      delay: json["KesesPercben"] ?? 0,
-      submitDate: json["KeszitesDatuma"] != null
-          ? DateTime.parse(json["KeszitesDatuma"]).toLocal()
-          : DateTime(0),
-      teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
-      state: json["IgazolasAllapota"] == "Igazolt"
-          ? Justification.excused
-          : json["IgazolasAllapota"] == "Igazolando"
-              ? Justification.pending
-              : Justification.unexcused,
-      justification: json["IgazolasTipusa"] != null
-          ? Category.fromJson(json["IgazolasTipusa"])
-          : null,
-      type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
-      mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
-      subject: Subject.fromJson(json["Tantargy"] ?? {}),
-      lessonStart: lessonStart,
-      lessonEnd: lessonEnd,
-      lessonIndex: lessonIndex,
-      group:
-          json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
-      isSeen: false,
-      json: json,
-    );
-  }
-}
-
-enum Justification { excused, unexcused, pending }
+import "category.dart";
+import "subject.dart";
+import "teacher.dart";
+
+class Absence {
+  Map? json;
+  String id;
+  DateTime date;
+  int delay;
+  DateTime submitDate;
+  Teacher teacher;
+  Justification state;
+  Category? justification;
+  Category? type;
+  Category? mode;
+  Subject subject;
+  DateTime lessonStart;
+  DateTime lessonEnd;
+  int? lessonIndex;
+  String group;
+  bool isSeen;
+  @override
+  bool operator ==(Object other) =>
+      identical(this, other) ||
+      other is Absence && runtimeType == other.runtimeType && id == other.id;
+
+  @override
+  int get hashCode => id.hashCode;
+
+  Absence({
+    required this.id,
+    required this.date,
+    required this.delay,
+    required this.submitDate,
+    required this.teacher,
+    required this.state,
+    this.justification,
+    this.type,
+    this.mode,
+    required this.subject,
+    required this.lessonStart,
+    required this.lessonEnd,
+    this.lessonIndex,
+    required this.group,
+    this.json,
+    this.isSeen = false,
+  });
+
+  factory Absence.fromJson(Map json) {
+    DateTime lessonStart;
+    DateTime lessonEnd;
+    int? lessonIndex;
+    if (json["Ora"] != null) {
+      lessonStart = json["Ora"]["KezdoDatum"] != null
+          ? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal()
+          : DateTime(0);
+      lessonEnd = json["Ora"]["VegDatum"] != null
+          ? DateTime.parse(json["Ora"]["VegDatum"]).toLocal()
+          : DateTime(0);
+      lessonIndex = json["Ora"]["Oraszam"];
+    } else {
+      lessonStart = DateTime(0);
+      lessonEnd = DateTime(0);
+    }
+
+    return Absence(
+      id: json["Uid"],
+      date: json["Datum"] != null
+          ? DateTime.parse(json["Datum"]).toLocal()
+          : DateTime(0),
+      delay: json["KesesPercben"] ?? 0,
+      submitDate: json["KeszitesDatuma"] != null
+          ? DateTime.parse(json["KeszitesDatuma"]).toLocal()
+          : DateTime(0),
+      teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
+      state: json["IgazolasAllapota"] == "Igazolt"
+          ? Justification.excused
+          : json["IgazolasAllapota"] == "Igazolando"
+              ? Justification.pending
+              : Justification.unexcused,
+      justification: json["IgazolasTipusa"] != null
+          ? Category.fromJson(json["IgazolasTipusa"])
+          : null,
+      type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
+      mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
+      subject: Subject.fromJson(json["Tantargy"] ?? {}),
+      lessonStart: lessonStart,
+      lessonEnd: lessonEnd,
+      lessonIndex: lessonIndex,
+      group:
+          json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
+      isSeen: false,
+      json: json,
+    );
+  }
+}
+
+enum Justification { excused, unexcused, pending }
diff --git a/filcnaplo_kreta_api/lib/models/attachment.dart b/refilc_kreta_api/lib/models/attachment.dart
similarity index 77%
rename from filcnaplo_kreta_api/lib/models/attachment.dart
rename to refilc_kreta_api/lib/models/attachment.dart
index 6fe76ea..fd3028d 100644
--- a/filcnaplo_kreta_api/lib/models/attachment.dart
+++ b/refilc_kreta_api/lib/models/attachment.dart
@@ -1,32 +1,33 @@
-import 'package:file_picker/file_picker.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-
-class Attachment {
-  Map? json;
-  int id;
-  PlatformFile? file;
-  String name;
-  String? fileId;
-  String kretaFilePath;
-
-  Attachment({
-    required this.id,
-    this.file,
-    required this.name,
-    this.fileId,
-    required this.kretaFilePath,
-    this.json,
-  });
-
-  factory Attachment.fromJson(Map json) {
-    return Attachment(
-      id: json["azonosito"],
-      name: (json["fajlNev"] ?? "attachment").trim(),
-      kretaFilePath: json["utvonal"] ?? "",
-      json: json,
-    );
-  }
-
-  String get downloadUrl => KretaAPI.downloadAttachment(id.toString());
-  bool get isImage => name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
-}
+import 'package:file_picker/file_picker.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+
+class Attachment {
+  Map? json;
+  int id;
+  PlatformFile? file;
+  String name;
+  String? fileId;
+  String kretaFilePath;
+
+  Attachment({
+    required this.id,
+    this.file,
+    required this.name,
+    this.fileId,
+    required this.kretaFilePath,
+    this.json,
+  });
+
+  factory Attachment.fromJson(Map json) {
+    return Attachment(
+      id: json["azonosito"],
+      name: (json["fajlNev"] ?? "attachment").trim(),
+      kretaFilePath: json["utvonal"] ?? "",
+      json: json,
+    );
+  }
+
+  String get downloadUrl => KretaAPI.downloadAttachment(id.toString());
+  bool get isImage =>
+      name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
+}
diff --git a/filcnaplo_kreta_api/lib/models/category.dart b/refilc_kreta_api/lib/models/category.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/category.dart
rename to refilc_kreta_api/lib/models/category.dart
index 7709a51..144e1e9 100644
--- a/filcnaplo_kreta_api/lib/models/category.dart
+++ b/refilc_kreta_api/lib/models/category.dart
@@ -1,44 +1,44 @@
-import 'grade.dart';
-
-class Category {
-  String id;
-  String description;
-  String name;
-
-  Category({
-    required this.id,
-    this.description = "",
-    this.name = "",
-  });
-
-  factory Category.fromJson(Map json) {
-    return Category(
-      id: json["Uid"] ?? "",
-      description: json["Leiras"] != "Na" ? json["Leiras"] ?? "" : "",
-      name: json["Nev"] != "Na" ? json["Nev"] ?? "" : "",
-    );
-  }
-
-  static GradeType getGradeType(String string) {
-    switch (string) {
-      case "evkozi_jegy_ertekeles":
-        return GradeType.midYear;
-      case "I_ne_jegy_ertekeles":
-        return GradeType.firstQ;
-      case "II_ne_jegy_ertekeles":
-        return GradeType.secondQ;
-      case "felevi_jegy_ertekeles":
-        return GradeType.halfYear;
-      case "III_ne_jegy_ertekeles":
-        return GradeType.thirdQ;
-      case "IV_ne_jegy_ertekeles":
-        return GradeType.fourthQ;
-      case "evvegi_jegy_ertekeles":
-        return GradeType.endYear;
-      case "osztalyozo_vizsga":
-        return GradeType.levelExam;
-      default:
-        return GradeType.unknown;
-    }
-  }
-}
+import 'grade.dart';
+
+class Category {
+  String id;
+  String description;
+  String name;
+
+  Category({
+    required this.id,
+    this.description = "",
+    this.name = "",
+  });
+
+  factory Category.fromJson(Map json) {
+    return Category(
+      id: json["Uid"] ?? "",
+      description: json["Leiras"] != "Na" ? json["Leiras"] ?? "" : "",
+      name: json["Nev"] != "Na" ? json["Nev"] ?? "" : "",
+    );
+  }
+
+  static GradeType getGradeType(String string) {
+    switch (string) {
+      case "evkozi_jegy_ertekeles":
+        return GradeType.midYear;
+      case "I_ne_jegy_ertekeles":
+        return GradeType.firstQ;
+      case "II_ne_jegy_ertekeles":
+        return GradeType.secondQ;
+      case "felevi_jegy_ertekeles":
+        return GradeType.halfYear;
+      case "III_ne_jegy_ertekeles":
+        return GradeType.thirdQ;
+      case "IV_ne_jegy_ertekeles":
+        return GradeType.fourthQ;
+      case "evvegi_jegy_ertekeles":
+        return GradeType.endYear;
+      case "osztalyozo_vizsga":
+        return GradeType.levelExam;
+      default:
+        return GradeType.unknown;
+    }
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/event.dart b/refilc_kreta_api/lib/models/event.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/event.dart
rename to refilc_kreta_api/lib/models/event.dart
index 2099d6b..26aa057 100644
--- a/filcnaplo_kreta_api/lib/models/event.dart
+++ b/refilc_kreta_api/lib/models/event.dart
@@ -1,28 +1,28 @@
-class Event {
-  Map? json;
-  String id;
-  DateTime start;
-  DateTime end;
-  String title;
-  String content;
-
-  Event({
-    required this.id,
-    required this.start,
-    required this.end,
-    this.title = "",
-    this.content = "",
-    this.json,
-  });
-
-  factory Event.fromJson(Map json) {
-    return Event(
-      id: json["Uid"] ?? "",
-      start: json["ErvenyessegKezdete"] != null ? DateTime.parse(json["ErvenyessegKezdete"]).toLocal() : DateTime(0),
-      end: json["ErvenyessegVege"] != null ? DateTime.parse(json["ErvenyessegVege"]).toLocal() : DateTime(0),
-      title: json["Cim"] ?? "",
-      content: json["Tartalom"] != null ? json["Tartalom"].replaceAll("\r", "") : "",
-      json: json,
-    );
-  }
-}
+class Event {
+  Map? json;
+  String id;
+  DateTime start;
+  DateTime end;
+  String title;
+  String content;
+
+  Event({
+    required this.id,
+    required this.start,
+    required this.end,
+    this.title = "",
+    this.content = "",
+    this.json,
+  });
+
+  factory Event.fromJson(Map json) {
+    return Event(
+      id: json["Uid"] ?? "",
+      start: json["ErvenyessegKezdete"] != null ? DateTime.parse(json["ErvenyessegKezdete"]).toLocal() : DateTime(0),
+      end: json["ErvenyessegVege"] != null ? DateTime.parse(json["ErvenyessegVege"]).toLocal() : DateTime(0),
+      title: json["Cim"] ?? "",
+      content: json["Tartalom"] != null ? json["Tartalom"].replaceAll("\r", "") : "",
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/exam.dart b/refilc_kreta_api/lib/models/exam.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/exam.dart
rename to refilc_kreta_api/lib/models/exam.dart
index 5f7689b..3894135 100644
--- a/filcnaplo_kreta_api/lib/models/exam.dart
+++ b/refilc_kreta_api/lib/models/exam.dart
@@ -1,49 +1,49 @@
-import 'category.dart';
-import 'teacher.dart';
-
-class Exam {
-  Map? json;
-  DateTime date;
-  DateTime writeDate;
-  Category? mode;
-  int? subjectIndex;
-  String subjectName;
-  Teacher teacher;
-  String description;
-  String group;
-  String id;
-
-  Exam({
-    required this.id,
-    required this.date,
-    required this.writeDate,
-    this.mode,
-    this.subjectIndex,
-    required this.subjectName,
-    required this.teacher,
-    required this.description,
-    required this.group,
-    this.json,
-  });
-
-  factory Exam.fromJson(Map json) {
-    return Exam(
-      id: json["Uid"] ?? "",
-      date: json["BejelentesDatuma"] != null
-          ? DateTime.parse(json["BejelentesDatuma"]).toLocal()
-          : DateTime(0),
-      writeDate: json["Datum"] != null
-          ? DateTime.parse(json["Datum"]).toLocal()
-          : DateTime(0),
-      mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
-      subjectIndex: json["OrarendiOraOraszama"],
-      subjectName: json["TantargyNeve"] ?? "",
-      teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
-      description: (json["Temaja"] ?? "").trim(),
-      group: json["OsztalyCsoport"] != null
-          ? json["OsztalyCsoport"]["Uid"] ?? ""
-          : "",
-      json: json,
-    );
-  }
-}
+import 'category.dart';
+import 'teacher.dart';
+
+class Exam {
+  Map? json;
+  DateTime date;
+  DateTime writeDate;
+  Category? mode;
+  int? subjectIndex;
+  String subjectName;
+  Teacher teacher;
+  String description;
+  String group;
+  String id;
+
+  Exam({
+    required this.id,
+    required this.date,
+    required this.writeDate,
+    this.mode,
+    this.subjectIndex,
+    required this.subjectName,
+    required this.teacher,
+    required this.description,
+    required this.group,
+    this.json,
+  });
+
+  factory Exam.fromJson(Map json) {
+    return Exam(
+      id: json["Uid"] ?? "",
+      date: json["BejelentesDatuma"] != null
+          ? DateTime.parse(json["BejelentesDatuma"]).toLocal()
+          : DateTime(0),
+      writeDate: json["Datum"] != null
+          ? DateTime.parse(json["Datum"]).toLocal()
+          : DateTime(0),
+      mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
+      subjectIndex: json["OrarendiOraOraszama"],
+      subjectName: json["TantargyNeve"] ?? "",
+      teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
+      description: (json["Temaja"] ?? "").trim(),
+      group: json["OsztalyCsoport"] != null
+          ? json["OsztalyCsoport"]["Uid"] ?? ""
+          : "",
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/grade.dart b/refilc_kreta_api/lib/models/grade.dart
similarity index 95%
rename from filcnaplo_kreta_api/lib/models/grade.dart
rename to refilc_kreta_api/lib/models/grade.dart
index 80c7db7..4b26eb1 100644
--- a/filcnaplo_kreta_api/lib/models/grade.dart
+++ b/refilc_kreta_api/lib/models/grade.dart
@@ -1,156 +1,156 @@
-import 'package:filcnaplo/utils/format.dart';
-import 'category.dart';
-import 'subject.dart';
-import 'teacher.dart';
-
-class Grade {
-  Map? json;
-  String id;
-  DateTime date;
-  GradeValue value;
-  Teacher teacher;
-  String description;
-  GradeType type;
-  String groupId;
-  Subject subject;
-  Category? gradeType;
-  Category mode;
-  DateTime writeDate;
-  DateTime seenDate;
-  String form;
-
-  Grade({
-    required this.id,
-    required this.date,
-    required this.value,
-    required this.teacher,
-    required this.description,
-    required this.type,
-    required this.groupId,
-    required this.subject,
-    this.gradeType,
-    required this.mode,
-    required this.writeDate,
-    required this.seenDate,
-    required this.form,
-    this.json,
-  });
-
-  factory Grade.fromJson(Map json) {
-    return Grade(
-      id: json["Uid"] ?? "",
-      date: json["KeszitesDatuma"] != null
-          ? DateTime.parse(json["KeszitesDatuma"]).toLocal()
-          : DateTime(0),
-      value: GradeValue(
-        json["SzamErtek"] ?? 0,
-        json["SzovegesErtek"] ?? "",
-        json["SzovegesErtekelesRovidNev"] ?? "",
-        json["SulySzazalekErteke"] ?? 0,
-        percentage: json["ErtekFajta"] != null
-            ? json["ErtekFajta"]["Uid"] == "3,Szazalekos"
-            : false,
-      ),
-      teacher: Teacher.fromString((json["ErtekeloTanarNeve"] ?? "").trim()),
-      description: json["Tema"] ?? "",
-      type: json["Tipus"] != null
-          ? Category.getGradeType(json["Tipus"]["Nev"])
-          : GradeType.unknown,
-      groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
-      subject: Subject.fromJson(json["Tantargy"] ?? {}),
-      gradeType: json["ErtekFajta"] != null
-          ? Category.fromJson(json["ErtekFajta"])
-          : null,
-      mode: Category.fromJson(json["Mod"] ?? {}),
-      writeDate: json["RogzitesDatuma"] != null
-          ? DateTime.parse(json["RogzitesDatuma"]).toLocal()
-          : DateTime(0),
-      seenDate: json["LattamozasDatuma"] != null
-          ? DateTime.parse(json["LattamozasDatuma"]).toLocal()
-          : DateTime(0),
-      form: (json["Jelleg"] ?? "Na") != "Na" ? json["Jelleg"] : "",
-      json: json,
-    );
-  }
-
-  bool compareTo(dynamic other) {
-    if (runtimeType != other.runtimeType) return false;
-
-    if (id == other.id && seenDate == other.seenDate) {
-      return true;
-    }
-
-    return false;
-  }
-}
-
-class GradeValue {
-  int _value;
-  set value(int v) => _value = v;
-  int get value {
-    String _valueName = valueName.toLowerCase().specialChars();
-    if (_value == 0 &&
-        ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
-      switch (_valueName) {
-        case "peldas":
-          return 5;
-        case "jo":
-          return 4;
-        case "valtozo":
-          return 3;
-        case "rossz":
-          return 2;
-        case "hanyag":
-          return 1;
-        // other
-        case "jeles":
-          return 5;
-        case "kozepes":
-          return 3;
-        case "elegseges":
-          return 2;
-        case "elegtelen":
-          return 1;
-      }
-    }
-    return _value;
-  }
-
-  String _valueName;
-  set valueName(String v) => _valueName = v;
-  String get valueName => _valueName.split("(")[0];
-  String shortName;
-  int _weight;
-  set weight(int v) => _weight = v;
-  int get weight {
-    String _valueName = valueName.toLowerCase().specialChars();
-    if (_value == 0 &&
-        ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
-      return 0;
-    }
-    return _weight;
-  }
-
-  final bool _percentage;
-  bool get percentage => _percentage;
-
-  GradeValue(int value, String valueName, this.shortName, int weight,
-      {bool percentage = false})
-      : _value = value,
-        _valueName = valueName,
-        _weight = weight,
-        _percentage = percentage;
-}
-
-enum GradeType {
-  midYear,
-  firstQ,
-  secondQ,
-  halfYear,
-  thirdQ,
-  fourthQ,
-  endYear,
-  levelExam,
-  ghost,
-  unknown
-}
+import 'package:refilc/utils/format.dart';
+import 'category.dart';
+import 'subject.dart';
+import 'teacher.dart';
+
+class Grade {
+  Map? json;
+  String id;
+  DateTime date;
+  GradeValue value;
+  Teacher teacher;
+  String description;
+  GradeType type;
+  String groupId;
+  Subject subject;
+  Category? gradeType;
+  Category mode;
+  DateTime writeDate;
+  DateTime seenDate;
+  String form;
+
+  Grade({
+    required this.id,
+    required this.date,
+    required this.value,
+    required this.teacher,
+    required this.description,
+    required this.type,
+    required this.groupId,
+    required this.subject,
+    this.gradeType,
+    required this.mode,
+    required this.writeDate,
+    required this.seenDate,
+    required this.form,
+    this.json,
+  });
+
+  factory Grade.fromJson(Map json) {
+    return Grade(
+      id: json["Uid"] ?? "",
+      date: json["KeszitesDatuma"] != null
+          ? DateTime.parse(json["KeszitesDatuma"]).toLocal()
+          : DateTime(0),
+      value: GradeValue(
+        json["SzamErtek"] ?? 0,
+        json["SzovegesErtek"] ?? "",
+        json["SzovegesErtekelesRovidNev"] ?? "",
+        json["SulySzazalekErteke"] ?? 0,
+        percentage: json["ErtekFajta"] != null
+            ? json["ErtekFajta"]["Uid"] == "3,Szazalekos"
+            : false,
+      ),
+      teacher: Teacher.fromString((json["ErtekeloTanarNeve"] ?? "").trim()),
+      description: json["Tema"] ?? "",
+      type: json["Tipus"] != null
+          ? Category.getGradeType(json["Tipus"]["Nev"])
+          : GradeType.unknown,
+      groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
+      subject: Subject.fromJson(json["Tantargy"] ?? {}),
+      gradeType: json["ErtekFajta"] != null
+          ? Category.fromJson(json["ErtekFajta"])
+          : null,
+      mode: Category.fromJson(json["Mod"] ?? {}),
+      writeDate: json["RogzitesDatuma"] != null
+          ? DateTime.parse(json["RogzitesDatuma"]).toLocal()
+          : DateTime(0),
+      seenDate: json["LattamozasDatuma"] != null
+          ? DateTime.parse(json["LattamozasDatuma"]).toLocal()
+          : DateTime(0),
+      form: (json["Jelleg"] ?? "Na") != "Na" ? json["Jelleg"] : "",
+      json: json,
+    );
+  }
+
+  bool compareTo(dynamic other) {
+    if (runtimeType != other.runtimeType) return false;
+
+    if (id == other.id && seenDate == other.seenDate) {
+      return true;
+    }
+
+    return false;
+  }
+}
+
+class GradeValue {
+  int _value;
+  set value(int v) => _value = v;
+  int get value {
+    String _valueName = valueName.toLowerCase().specialChars();
+    if (_value == 0 &&
+        ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
+      switch (_valueName) {
+        case "peldas":
+          return 5;
+        case "jo":
+          return 4;
+        case "valtozo":
+          return 3;
+        case "rossz":
+          return 2;
+        case "hanyag":
+          return 1;
+        // other
+        case "jeles":
+          return 5;
+        case "kozepes":
+          return 3;
+        case "elegseges":
+          return 2;
+        case "elegtelen":
+          return 1;
+      }
+    }
+    return _value;
+  }
+
+  String _valueName;
+  set valueName(String v) => _valueName = v;
+  String get valueName => _valueName.split("(")[0];
+  String shortName;
+  int _weight;
+  set weight(int v) => _weight = v;
+  int get weight {
+    String _valueName = valueName.toLowerCase().specialChars();
+    if (_value == 0 &&
+        ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
+      return 0;
+    }
+    return _weight;
+  }
+
+  final bool _percentage;
+  bool get percentage => _percentage;
+
+  GradeValue(int value, String valueName, this.shortName, int weight,
+      {bool percentage = false})
+      : _value = value,
+        _valueName = valueName,
+        _weight = weight,
+        _percentage = percentage;
+}
+
+enum GradeType {
+  midYear,
+  firstQ,
+  secondQ,
+  halfYear,
+  thirdQ,
+  fourthQ,
+  endYear,
+  levelExam,
+  ghost,
+  unknown
+}
diff --git a/filcnaplo_kreta_api/lib/models/group_average.dart b/refilc_kreta_api/lib/models/group_average.dart
similarity index 63%
rename from filcnaplo_kreta_api/lib/models/group_average.dart
rename to refilc_kreta_api/lib/models/group_average.dart
index e95f730..8104e30 100644
--- a/filcnaplo_kreta_api/lib/models/group_average.dart
+++ b/refilc_kreta_api/lib/models/group_average.dart
@@ -1,19 +1,23 @@
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-
-class GroupAverage {
-  String uid;
-  double average;
-  Subject subject;
-  Map json;
-
-  GroupAverage({required this.uid, required this.average, required this.subject, this.json = const {}});
-
-  factory GroupAverage.fromJson(Map json) {
-    return GroupAverage(
-      uid: json["Uid"] ?? "",
-      average: json["OsztalyCsoportAtlag"] ?? 0,
-      subject: Subject.fromJson(json["Tantargy"] ?? {}),
-      json: json,
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/subject.dart';
+
+class GroupAverage {
+  String uid;
+  double average;
+  Subject subject;
+  Map json;
+
+  GroupAverage(
+      {required this.uid,
+      required this.average,
+      required this.subject,
+      this.json = const {}});
+
+  factory GroupAverage.fromJson(Map json) {
+    return GroupAverage(
+      uid: json["Uid"] ?? "",
+      average: json["OsztalyCsoportAtlag"] ?? 0,
+      subject: Subject.fromJson(json["Tantargy"] ?? {}),
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/homework.dart b/refilc_kreta_api/lib/models/homework.dart
similarity index 94%
rename from filcnaplo_kreta_api/lib/models/homework.dart
rename to refilc_kreta_api/lib/models/homework.dart
index bd4ab39..5ae358d 100644
--- a/filcnaplo_kreta_api/lib/models/homework.dart
+++ b/refilc_kreta_api/lib/models/homework.dart
@@ -1,86 +1,86 @@
-import 'package:filcnaplo_kreta_api/client/api.dart';
-
-import 'subject.dart';
-import 'teacher.dart';
-
-class Homework {
-  Map? json;
-  DateTime date;
-  DateTime lessonDate;
-  DateTime deadline;
-  bool byTeacher;
-  bool homeworkEnabled;
-  Teacher teacher;
-  String content;
-  Subject subject;
-  String group;
-  List<HomeworkAttachment> attachments;
-  String id;
-
-  Homework({
-    required this.date,
-    required this.lessonDate,
-    required this.deadline,
-    required this.byTeacher,
-    required this.homeworkEnabled,
-    required this.teacher,
-    required this.content,
-    required this.subject,
-    required this.group,
-    required this.attachments,
-    required this.id,
-    this.json,
-  });
-
-  factory Homework.fromJson(Map json) {
-    return Homework(
-      id: json["Uid"] ?? "",
-      date: json["RogzitesIdopontja"] != null
-          ? DateTime.parse(json["RogzitesIdopontja"]).toLocal()
-          : DateTime(0),
-      lessonDate: json["FeladasDatuma"] != null
-          ? DateTime.parse(json["FeladasDatuma"]).toLocal()
-          : DateTime(0),
-      deadline: json["HataridoDatuma"] != null
-          ? DateTime.parse(json["HataridoDatuma"]).toLocal()
-          : DateTime(0),
-      byTeacher: json["IsTanarRogzitette"] ?? true,
-      homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
-      teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
-      content: (json["Szoveg"] ?? "").trim(),
-      subject: Subject.fromJson(json["Tantargy"] ?? {}),
-      group: json["OsztalyCsoport"] != null
-          ? json["OsztalyCsoport"]["Uid"] ?? ""
-          : "",
-      attachments: ((json["Csatolmanyok"] ?? []) as List)
-          .cast<Map>()
-          .map((Map json) => HomeworkAttachment.fromJson(json))
-          .toList(),
-      json: json,
-    );
-  }
-}
-
-class HomeworkAttachment {
-  Map? json;
-  String id;
-  String name;
-  String type;
-
-  HomeworkAttachment(
-      {required this.id, this.name = "", this.type = "", this.json});
-
-  factory HomeworkAttachment.fromJson(Map json) {
-    return HomeworkAttachment(
-      id: json["Uid"] ?? "",
-      name: json["Nev"] ?? "",
-      type: json["Tipus"] ?? "",
-      json: json,
-    );
-  }
-
-  String downloadUrl(String iss) =>
-      KretaAPI.downloadHomeworkAttachments(iss, id, type);
-  bool get isImage =>
-      name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
-}
+import 'package:refilc_kreta_api/client/api.dart';
+
+import 'subject.dart';
+import 'teacher.dart';
+
+class Homework {
+  Map? json;
+  DateTime date;
+  DateTime lessonDate;
+  DateTime deadline;
+  bool byTeacher;
+  bool homeworkEnabled;
+  Teacher teacher;
+  String content;
+  Subject subject;
+  String group;
+  List<HomeworkAttachment> attachments;
+  String id;
+
+  Homework({
+    required this.date,
+    required this.lessonDate,
+    required this.deadline,
+    required this.byTeacher,
+    required this.homeworkEnabled,
+    required this.teacher,
+    required this.content,
+    required this.subject,
+    required this.group,
+    required this.attachments,
+    required this.id,
+    this.json,
+  });
+
+  factory Homework.fromJson(Map json) {
+    return Homework(
+      id: json["Uid"] ?? "",
+      date: json["RogzitesIdopontja"] != null
+          ? DateTime.parse(json["RogzitesIdopontja"]).toLocal()
+          : DateTime(0),
+      lessonDate: json["FeladasDatuma"] != null
+          ? DateTime.parse(json["FeladasDatuma"]).toLocal()
+          : DateTime(0),
+      deadline: json["HataridoDatuma"] != null
+          ? DateTime.parse(json["HataridoDatuma"]).toLocal()
+          : DateTime(0),
+      byTeacher: json["IsTanarRogzitette"] ?? true,
+      homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
+      teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
+      content: (json["Szoveg"] ?? "").trim(),
+      subject: Subject.fromJson(json["Tantargy"] ?? {}),
+      group: json["OsztalyCsoport"] != null
+          ? json["OsztalyCsoport"]["Uid"] ?? ""
+          : "",
+      attachments: ((json["Csatolmanyok"] ?? []) as List)
+          .cast<Map>()
+          .map((Map json) => HomeworkAttachment.fromJson(json))
+          .toList(),
+      json: json,
+    );
+  }
+}
+
+class HomeworkAttachment {
+  Map? json;
+  String id;
+  String name;
+  String type;
+
+  HomeworkAttachment(
+      {required this.id, this.name = "", this.type = "", this.json});
+
+  factory HomeworkAttachment.fromJson(Map json) {
+    return HomeworkAttachment(
+      id: json["Uid"] ?? "",
+      name: json["Nev"] ?? "",
+      type: json["Tipus"] ?? "",
+      json: json,
+    );
+  }
+
+  String downloadUrl(String iss) =>
+      KretaAPI.downloadHomeworkAttachments(iss, id, type);
+  bool get isImage =>
+      name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
+}
diff --git a/filcnaplo_kreta_api/lib/models/lesson.dart b/refilc_kreta_api/lib/models/lesson.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/lesson.dart
rename to refilc_kreta_api/lib/models/lesson.dart
index afa7d7c..3e30c49 100644
--- a/filcnaplo_kreta_api/lib/models/lesson.dart
+++ b/refilc_kreta_api/lib/models/lesson.dart
@@ -1,119 +1,119 @@
-import 'subject.dart';
-import 'category.dart';
-import 'teacher.dart';
-
-class Lesson {
-  Map? json;
-  Category? status;
-  DateTime date;
-  Subject subject;
-  String lessonIndex;
-  int? lessonYearIndex;
-  Teacher? substituteTeacher;
-  Teacher teacher;
-  bool homeworkEnabled;
-  DateTime start;
-  DateTime end;
-  bool studentPresence;
-  String homeworkId;
-  String exam;
-  String id;
-  Category? type;
-  String description;
-  String room;
-  String groupName;
-  String name;
-  bool online;
-  bool isEmpty;
-  bool isSeen;
-
-  Lesson({
-    this.status,
-    required this.date,
-    required this.subject,
-    required this.lessonIndex,
-    this.lessonYearIndex,
-    this.substituteTeacher,
-    required this.teacher,
-    this.homeworkEnabled = false,
-    required this.start,
-    required this.end,
-    this.studentPresence = true,
-    required this.homeworkId,
-    this.exam = "",
-    required this.id,
-    this.type,
-    required this.description,
-    required this.room,
-    required this.groupName,
-    required this.name,
-    this.online = false,
-    this.isEmpty = false,
-    this.json,
-    this.isSeen = false,
-  });
-  @override
-  bool operator ==(Object other) =>
-      identical(this, other) ||
-      other is Lesson && runtimeType == other.runtimeType && id == other.id;
-
-  @override
-  int get hashCode => id.hashCode;
-
-  factory Lesson.fromJson(Map json) {
-    return Lesson(
-        id: json["Uid"] ?? "",
-        status:
-            json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
-        date: json["Datum"] != null
-            ? DateTime.parse(json["Datum"]).toLocal()
-            : DateTime(0),
-        subject: Subject.fromJson(json["Tantargy"] ?? {}),
-        lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
-        lessonYearIndex: json["OraEvesSorszama"],
-        substituteTeacher: json["HelyettesTanarNeve"] != null
-            ? Teacher.fromString((json["HelyettesTanarNeve"]).trim())
-            : null,
-        teacher: Teacher.fromString((json["TanarNeve"] ?? "").trim()),
-        homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
-        start: json["KezdetIdopont"] != null
-            ? DateTime.parse(json["KezdetIdopont"]).toLocal()
-            : DateTime(0),
-        studentPresence: json["TanuloJelenlet"] != null
-            ? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
-                ? false
-                : true
-            : true,
-        end: json["VegIdopont"] != null
-            ? DateTime.parse(json["VegIdopont"]).toLocal()
-            : DateTime(0),
-        homeworkId: json["HaziFeladatUid"] ?? "",
-        exam: json["BejelentettSzamonkeresUid"] ?? "",
-        type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
-        description: json["Tema"] ?? "",
-        room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String)
-            .replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
-        groupName: json["OsztalyCsoport"] != null
-            ? json["OsztalyCsoport"]["Nev"] ?? ""
-            : "",
-        name: json["Nev"] ?? "",
-        online: json["IsDigitalisOra"] ?? false,
-        isEmpty: json['isEmpty'] ?? false,
-        json: json,
-        isSeen: false);
-  }
-
-  int? getFloor() {
-    final match = RegExp(r"(\d{3})").firstMatch(room);
-    if (match != null) {
-      final floorNumber = int.tryParse(match[0] ?? "");
-      if (floorNumber != null) {
-        return (floorNumber / 100).floor();
-      }
-    }
-    return null;
-  }
-
-  bool get isChanged => status?.name == "Elmaradt" || substituteTeacher != null;
-  bool get swapDesc => room.length > 8;
-}
+import 'subject.dart';
+import 'category.dart';
+import 'teacher.dart';
+
+class Lesson {
+  Map? json;
+  Category? status;
+  DateTime date;
+  Subject subject;
+  String lessonIndex;
+  int? lessonYearIndex;
+  Teacher? substituteTeacher;
+  Teacher teacher;
+  bool homeworkEnabled;
+  DateTime start;
+  DateTime end;
+  bool studentPresence;
+  String homeworkId;
+  String exam;
+  String id;
+  Category? type;
+  String description;
+  String room;
+  String groupName;
+  String name;
+  bool online;
+  bool isEmpty;
+  bool isSeen;
+
+  Lesson({
+    this.status,
+    required this.date,
+    required this.subject,
+    required this.lessonIndex,
+    this.lessonYearIndex,
+    this.substituteTeacher,
+    required this.teacher,
+    this.homeworkEnabled = false,
+    required this.start,
+    required this.end,
+    this.studentPresence = true,
+    required this.homeworkId,
+    this.exam = "",
+    required this.id,
+    this.type,
+    required this.description,
+    required this.room,
+    required this.groupName,
+    required this.name,
+    this.online = false,
+    this.isEmpty = false,
+    this.json,
+    this.isSeen = false,
+  });
+  @override
+  bool operator ==(Object other) =>
+      identical(this, other) ||
+      other is Lesson && runtimeType == other.runtimeType && id == other.id;
+
+  @override
+  int get hashCode => id.hashCode;
+
+  factory Lesson.fromJson(Map json) {
+    return Lesson(
+        id: json["Uid"] ?? "",
+        status:
+            json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
+        date: json["Datum"] != null
+            ? DateTime.parse(json["Datum"]).toLocal()
+            : DateTime(0),
+        subject: Subject.fromJson(json["Tantargy"] ?? {}),
+        lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
+        lessonYearIndex: json["OraEvesSorszama"],
+        substituteTeacher: json["HelyettesTanarNeve"] != null
+            ? Teacher.fromString((json["HelyettesTanarNeve"]).trim())
+            : null,
+        teacher: Teacher.fromString((json["TanarNeve"] ?? "").trim()),
+        homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
+        start: json["KezdetIdopont"] != null
+            ? DateTime.parse(json["KezdetIdopont"]).toLocal()
+            : DateTime(0),
+        studentPresence: json["TanuloJelenlet"] != null
+            ? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
+                ? false
+                : true
+            : true,
+        end: json["VegIdopont"] != null
+            ? DateTime.parse(json["VegIdopont"]).toLocal()
+            : DateTime(0),
+        homeworkId: json["HaziFeladatUid"] ?? "",
+        exam: json["BejelentettSzamonkeresUid"] ?? "",
+        type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
+        description: json["Tema"] ?? "",
+        room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String)
+            .replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
+        groupName: json["OsztalyCsoport"] != null
+            ? json["OsztalyCsoport"]["Nev"] ?? ""
+            : "",
+        name: json["Nev"] ?? "",
+        online: json["IsDigitalisOra"] ?? false,
+        isEmpty: json['isEmpty'] ?? false,
+        json: json,
+        isSeen: false);
+  }
+
+  int? getFloor() {
+    final match = RegExp(r"(\d{3})").firstMatch(room);
+    if (match != null) {
+      final floorNumber = int.tryParse(match[0] ?? "");
+      if (floorNumber != null) {
+        return (floorNumber / 100).floor();
+      }
+    }
+    return null;
+  }
+
+  bool get isChanged => status?.name == "Elmaradt" || substituteTeacher != null;
+  bool get swapDesc => room.length > 8;
+}
diff --git a/filcnaplo_kreta_api/lib/models/message.dart b/refilc_kreta_api/lib/models/message.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/message.dart
rename to refilc_kreta_api/lib/models/message.dart
index 97cd5f3..de52d85 100644
--- a/filcnaplo_kreta_api/lib/models/message.dart
+++ b/refilc_kreta_api/lib/models/message.dart
@@ -1,107 +1,107 @@
-import 'recipient.dart';
-import 'attachment.dart';
-
-class Message {
-  Map? json;
-  int id;
-  int? replyId;
-  int messageId;
-  int? conversationId;
-  bool seen;
-  bool deleted;
-  DateTime date;
-  String author;
-  String content;
-  String subject;
-  MessageType? type;
-  List<Recipient> recipients;
-  List<Attachment> attachments;
-  bool isSeen;
-
-  Message({
-    required this.id,
-    required this.messageId,
-    required this.seen,
-    required this.deleted,
-    required this.date,
-    required this.author,
-    required this.content,
-    required this.subject,
-    this.type,
-    required this.recipients,
-    required this.attachments,
-    this.replyId,
-    this.conversationId,
-    this.json,
-    this.isSeen = false,
-  });
-  @override
-  bool operator ==(Object other) =>
-      identical(this, other) ||
-      other is Message && runtimeType == other.runtimeType && id == other.id;
-
-  @override
-  int get hashCode => id.hashCode;
-
-  factory Message.fromJson(Map json, {MessageType? forceType}) {
-    Map message = json["uzenet"];
-
-    MessageType? type = forceType;
-    if (type == null) {
-      switch (json["tipus"]["kod"]) {
-        case "BEERKEZETT":
-          type = MessageType.inbox;
-          break;
-        case "ELKULDOTT":
-          type = MessageType.sent;
-          break;
-        case "PISZKOZAT":
-          type = MessageType.draft;
-          break;
-      }
-
-      if (json["isToroltElem"] == true) type = MessageType.trash;
-    }
-
-    return Message(
-      id: json["azonosito"],
-      messageId: message["azonosito"],
-      seen: json["isElolvasva"] ?? false,
-      deleted: json["isToroltElem"] ?? false,
-      date: message["kuldesDatum"] != null ? DateTime.parse(message["kuldesDatum"]).toLocal() : DateTime(0),
-      author: (message["feladoNev"] ?? "").trim(),
-      content: message["szoveg"].replaceAll("\r", "") ?? "",
-      subject: message["targy"] ?? "",
-      type: type,
-      recipients: (message["cimzettLista"] as List).cast<Map>().map((Map recipient) => Recipient.fromJson(recipient)).toList(),
-      attachments: (message["csatolmanyok"] as List).cast<Map>().map((Map attachment) => Attachment.fromJson(attachment)).toList(),
-      replyId: message["elozoUzenetAzonosito"],
-      conversationId: message["beszelgetesAzonosito"],
-      json: json,
-      isSeen: false,
-    );
-  }
-
-  bool compareTo(dynamic other) {
-    if (runtimeType != other.runtimeType) return false;
-
-    return id == other.id && seen == other.seen && deleted == other.deleted;
-  }
-}
-
-enum MessageType { inbox, sent, trash, draft }
-
-class Conversation {
-  int id;
-  late List<Message> _messages;
-  List<Message> get messages => _messages;
-
-  Conversation({required this.id, List<Message> messages = const []}) {
-    _messages = List.from(messages);
-  }
-
-  void sort() => _messages.sort((a, b) => -a.date.compareTo(b.date));
-  void add(Message message) => _messages.add(message);
-
-  Message get newest => _messages.first;
-}
+import 'recipient.dart';
+import 'attachment.dart';
+
+class Message {
+  Map? json;
+  int id;
+  int? replyId;
+  int messageId;
+  int? conversationId;
+  bool seen;
+  bool deleted;
+  DateTime date;
+  String author;
+  String content;
+  String subject;
+  MessageType? type;
+  List<Recipient> recipients;
+  List<Attachment> attachments;
+  bool isSeen;
+
+  Message({
+    required this.id,
+    required this.messageId,
+    required this.seen,
+    required this.deleted,
+    required this.date,
+    required this.author,
+    required this.content,
+    required this.subject,
+    this.type,
+    required this.recipients,
+    required this.attachments,
+    this.replyId,
+    this.conversationId,
+    this.json,
+    this.isSeen = false,
+  });
+  @override
+  bool operator ==(Object other) =>
+      identical(this, other) ||
+      other is Message && runtimeType == other.runtimeType && id == other.id;
+
+  @override
+  int get hashCode => id.hashCode;
+
+  factory Message.fromJson(Map json, {MessageType? forceType}) {
+    Map message = json["uzenet"];
+
+    MessageType? type = forceType;
+    if (type == null) {
+      switch (json["tipus"]["kod"]) {
+        case "BEERKEZETT":
+          type = MessageType.inbox;
+          break;
+        case "ELKULDOTT":
+          type = MessageType.sent;
+          break;
+        case "PISZKOZAT":
+          type = MessageType.draft;
+          break;
+      }
+
+      if (json["isToroltElem"] == true) type = MessageType.trash;
+    }
+
+    return Message(
+      id: json["azonosito"],
+      messageId: message["azonosito"],
+      seen: json["isElolvasva"] ?? false,
+      deleted: json["isToroltElem"] ?? false,
+      date: message["kuldesDatum"] != null ? DateTime.parse(message["kuldesDatum"]).toLocal() : DateTime(0),
+      author: (message["feladoNev"] ?? "").trim(),
+      content: message["szoveg"].replaceAll("\r", "") ?? "",
+      subject: message["targy"] ?? "",
+      type: type,
+      recipients: (message["cimzettLista"] as List).cast<Map>().map((Map recipient) => Recipient.fromJson(recipient)).toList(),
+      attachments: (message["csatolmanyok"] as List).cast<Map>().map((Map attachment) => Attachment.fromJson(attachment)).toList(),
+      replyId: message["elozoUzenetAzonosito"],
+      conversationId: message["beszelgetesAzonosito"],
+      json: json,
+      isSeen: false,
+    );
+  }
+
+  bool compareTo(dynamic other) {
+    if (runtimeType != other.runtimeType) return false;
+
+    return id == other.id && seen == other.seen && deleted == other.deleted;
+  }
+}
+
+enum MessageType { inbox, sent, trash, draft }
+
+class Conversation {
+  int id;
+  late List<Message> _messages;
+  List<Message> get messages => _messages;
+
+  Conversation({required this.id, List<Message> messages = const []}) {
+    _messages = List.from(messages);
+  }
+
+  void sort() => _messages.sort((a, b) => -a.date.compareTo(b.date));
+  void add(Message message) => _messages.add(message);
+
+  Message get newest => _messages.first;
+}
diff --git a/filcnaplo_kreta_api/lib/models/note.dart b/refilc_kreta_api/lib/models/note.dart
similarity index 96%
rename from filcnaplo_kreta_api/lib/models/note.dart
rename to refilc_kreta_api/lib/models/note.dart
index ba94fa5..18e6e15 100644
--- a/filcnaplo_kreta_api/lib/models/note.dart
+++ b/refilc_kreta_api/lib/models/note.dart
@@ -1,51 +1,51 @@
-import 'category.dart';
-import 'teacher.dart';
-
-class Note {
-  Map? json;
-  String id;
-  String title;
-  DateTime date;
-  DateTime submitDate;
-  Teacher teacher;
-  DateTime seenDate;
-  String groupId;
-  String content;
-  Category? type;
-
-  Note({
-    required this.id,
-    required this.title,
-    required this.date,
-    required this.submitDate,
-    required this.teacher,
-    required this.seenDate,
-    required this.groupId,
-    required this.content,
-    this.type,
-    this.json,
-  });
-
-  factory Note.fromJson(Map json) {
-    return Note(
-      id: json["Uid"] ?? "",
-      title: json["Cim"] ?? "",
-      date: json["Datum"] != null
-          ? DateTime.parse(json["Datum"]).toLocal()
-          : DateTime(0),
-      submitDate: json["KeszitesDatuma"] != null
-          ? DateTime.parse(json["KeszitesDatuma"]).toLocal()
-          : DateTime(0),
-      teacher: Teacher.fromString((json["KeszitoTanarNeve"] ?? "").trim()),
-      seenDate: json["LattamozasDatuma"] != null
-          ? DateTime.parse(json["LattamozasDatuma"]).toLocal()
-          : DateTime(0),
-      groupId: json["OsztalyCsoport"] != null
-          ? json["OsztalyCsoport"]["Uid"] ?? ""
-          : "",
-      content: json["Tartalom"].replaceAll("\r", "") ?? "",
-      type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
-      json: json,
-    );
-  }
-}
+import 'category.dart';
+import 'teacher.dart';
+
+class Note {
+  Map? json;
+  String id;
+  String title;
+  DateTime date;
+  DateTime submitDate;
+  Teacher teacher;
+  DateTime seenDate;
+  String groupId;
+  String content;
+  Category? type;
+
+  Note({
+    required this.id,
+    required this.title,
+    required this.date,
+    required this.submitDate,
+    required this.teacher,
+    required this.seenDate,
+    required this.groupId,
+    required this.content,
+    this.type,
+    this.json,
+  });
+
+  factory Note.fromJson(Map json) {
+    return Note(
+      id: json["Uid"] ?? "",
+      title: json["Cim"] ?? "",
+      date: json["Datum"] != null
+          ? DateTime.parse(json["Datum"]).toLocal()
+          : DateTime(0),
+      submitDate: json["KeszitesDatuma"] != null
+          ? DateTime.parse(json["KeszitesDatuma"]).toLocal()
+          : DateTime(0),
+      teacher: Teacher.fromString((json["KeszitoTanarNeve"] ?? "").trim()),
+      seenDate: json["LattamozasDatuma"] != null
+          ? DateTime.parse(json["LattamozasDatuma"]).toLocal()
+          : DateTime(0),
+      groupId: json["OsztalyCsoport"] != null
+          ? json["OsztalyCsoport"]["Uid"] ?? ""
+          : "",
+      content: json["Tartalom"].replaceAll("\r", "") ?? "",
+      type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/recipient.dart b/refilc_kreta_api/lib/models/recipient.dart
similarity index 95%
rename from filcnaplo_kreta_api/lib/models/recipient.dart
rename to refilc_kreta_api/lib/models/recipient.dart
index e04d63c..cc7805c 100644
--- a/filcnaplo_kreta_api/lib/models/recipient.dart
+++ b/refilc_kreta_api/lib/models/recipient.dart
@@ -1,56 +1,56 @@
-class Recipient {
-  Map? json;
-  int id;
-  String? studentId; // oktatasi azonosito
-  int kretaId;
-  String name;
-  RecipientCategory? category;
-
-  Recipient({
-    required this.id,
-    this.studentId,
-    required this.name,
-    required this.kretaId,
-    this.category,
-    this.json,
-  });
-
-  factory Recipient.fromJson(Map json) {
-    return Recipient(
-      id: json["azonosito"],
-      name: json["nev"] ?? "",
-      kretaId: json["kretaAzonosito"],
-      category: json["tipus"] != null ? RecipientCategory.fromJson(json["tipus"]) : null,
-      json: json,
-    );
-  }
-}
-
-class RecipientCategory {
-  Map? json;
-  int id;
-  String code;
-  String shortName;
-  String name;
-  String description;
-
-  RecipientCategory({
-    required this.id,
-    required this.code,
-    required this.shortName,
-    required this.name,
-    required this.description,
-    this.json,
-  });
-
-  factory RecipientCategory.fromJson(Map json) {
-    return RecipientCategory(
-      id: json["azonosito"],
-      code: json["kod"] ?? "",
-      shortName: json["rovidNev"] ?? "",
-      name: json["nev"] ?? "",
-      description: json["leiras"] ?? "",
-      json: json,
-    );
-  }
-}
+class Recipient {
+  Map? json;
+  int id;
+  String? studentId; // oktatasi azonosito
+  int kretaId;
+  String name;
+  RecipientCategory? category;
+
+  Recipient({
+    required this.id,
+    this.studentId,
+    required this.name,
+    required this.kretaId,
+    this.category,
+    this.json,
+  });
+
+  factory Recipient.fromJson(Map json) {
+    return Recipient(
+      id: json["azonosito"],
+      name: json["nev"] ?? "",
+      kretaId: json["kretaAzonosito"],
+      category: json["tipus"] != null ? RecipientCategory.fromJson(json["tipus"]) : null,
+      json: json,
+    );
+  }
+}
+
+class RecipientCategory {
+  Map? json;
+  int id;
+  String code;
+  String shortName;
+  String name;
+  String description;
+
+  RecipientCategory({
+    required this.id,
+    required this.code,
+    required this.shortName,
+    required this.name,
+    required this.description,
+    this.json,
+  });
+
+  factory RecipientCategory.fromJson(Map json) {
+    return RecipientCategory(
+      id: json["azonosito"],
+      code: json["kod"] ?? "",
+      shortName: json["rovidNev"] ?? "",
+      name: json["nev"] ?? "",
+      description: json["leiras"] ?? "",
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/school.dart b/refilc_kreta_api/lib/models/school.dart
similarity index 95%
rename from filcnaplo_kreta_api/lib/models/school.dart
rename to refilc_kreta_api/lib/models/school.dart
index b55aea6..999b302 100644
--- a/filcnaplo_kreta_api/lib/models/school.dart
+++ b/refilc_kreta_api/lib/models/school.dart
@@ -1,19 +1,19 @@
-class School {
-  String instituteCode;
-  String name;
-  String city;
-
-  School({
-    required this.instituteCode,
-    required this.name,
-    required this.city,
-  });
-
-  factory School.fromJson(Map json) {
-    return School(
-      instituteCode: json["instituteCode"] ?? "",
-      name: (json["name"] ?? "").trim(),
-      city: json["city"] ?? "",
-    );
-  }
-}
+class School {
+  String instituteCode;
+  String name;
+  String city;
+
+  School({
+    required this.instituteCode,
+    required this.name,
+    required this.city,
+  });
+
+  factory School.fromJson(Map json) {
+    return School(
+      instituteCode: json["instituteCode"] ?? "",
+      name: (json["name"] ?? "").trim(),
+      city: json["city"] ?? "",
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/student.dart b/refilc_kreta_api/lib/models/student.dart
similarity index 78%
rename from filcnaplo_kreta_api/lib/models/student.dart
rename to refilc_kreta_api/lib/models/student.dart
index 046ddaa..a364731 100644
--- a/filcnaplo_kreta_api/lib/models/student.dart
+++ b/refilc_kreta_api/lib/models/student.dart
@@ -1,55 +1,61 @@
-import 'school.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-class Student {
-  Map? json;
-  String id;
-  String name;
-  School school;
-  DateTime birth;
-  String yearId;
-  String? address;
-  String? groupId;
-  List<String> parents;
-  String? className;
-
-  Student({
-    required this.id,
-    required this.name,
-    required this.school,
-    required this.birth,
-    required this.yearId,
-    this.address,
-    required this.parents,
-    this.json,
-  });
-
-  factory Student.fromJson(Map json) {
-    List<String> parents = [];
-
-    parents = ((json["Gondviselok"] ?? []) as List).cast<Map>().map((e) => e["Nev"] ?? "").toList().cast<String>();
-    if (json["AnyjaNeve"] != null) parents.insert(0, json["AnyjaNeve"]);
-
-    parents = parents.map((e) => e.capitalize()).toList(); // fix name casing
-    parents = parents.toSet().toList(); // remove duplicates
-
-    return Student(
-      id: json["Uid"] ?? "",
-      name: (json["Nev"] ?? json["SzuletesiNev"] ?? "").trim(),
-      school: School(
-        instituteCode: json["IntezmenyAzonosito"] ?? "",
-        name: json["IntezmenyNev"] ?? "",
-        city: "",
-      ),
-      birth: json["SzuletesiDatum"] != null ? DateTime.parse(json["SzuletesiDatum"]).toLocal() : DateTime(0),
-      yearId: json["TanevUid"] ?? "",
-      address: json["Cimek"] != null
-          ? json["Cimek"].length > 0
-              ? json["Cimek"][0]
-              : null
-          : null,
-      parents: parents,
-      json: json,
-    );
-  }
-}
+import 'school.dart';
+import 'package:refilc/utils/format.dart';
+
+class Student {
+  Map? json;
+  String id;
+  String name;
+  School school;
+  DateTime birth;
+  String yearId;
+  String? address;
+  String? groupId;
+  List<String> parents;
+  String? className;
+
+  Student({
+    required this.id,
+    required this.name,
+    required this.school,
+    required this.birth,
+    required this.yearId,
+    this.address,
+    required this.parents,
+    this.json,
+  });
+
+  factory Student.fromJson(Map json) {
+    List<String> parents = [];
+
+    parents = ((json["Gondviselok"] ?? []) as List)
+        .cast<Map>()
+        .map((e) => e["Nev"] ?? "")
+        .toList()
+        .cast<String>();
+    if (json["AnyjaNeve"] != null) parents.insert(0, json["AnyjaNeve"]);
+
+    parents = parents.map((e) => e.capitalize()).toList(); // fix name casing
+    parents = parents.toSet().toList(); // remove duplicates
+
+    return Student(
+      id: json["Uid"] ?? "",
+      name: (json["Nev"] ?? json["SzuletesiNev"] ?? "").trim(),
+      school: School(
+        instituteCode: json["IntezmenyAzonosito"] ?? "",
+        name: json["IntezmenyNev"] ?? "",
+        city: "",
+      ),
+      birth: json["SzuletesiDatum"] != null
+          ? DateTime.parse(json["SzuletesiDatum"]).toLocal()
+          : DateTime(0),
+      yearId: json["TanevUid"] ?? "",
+      address: json["Cimek"] != null
+          ? json["Cimek"].length > 0
+              ? json["Cimek"][0]
+              : null
+          : null,
+      parents: parents,
+      json: json,
+    );
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/models/subject.dart b/refilc_kreta_api/lib/models/subject.dart
similarity index 95%
rename from filcnaplo_kreta_api/lib/models/subject.dart
rename to refilc_kreta_api/lib/models/subject.dart
index ec36d32..6adc113 100644
--- a/filcnaplo_kreta_api/lib/models/subject.dart
+++ b/refilc_kreta_api/lib/models/subject.dart
@@ -1,30 +1,30 @@
-import 'category.dart';
-
-class Subject {
-  String id;
-  Category category;
-  String name;
-  String? renamedTo;
-
-  bool get isRenamed => renamedTo != null;
-
-  Subject({required this.id, required this.category, required this.name, this.renamedTo});
-
-  factory Subject.fromJson(Map json) {
-    final id = json["Uid"] ?? "";
-    return Subject(
-      id: id,
-      category: Category.fromJson(json["Kategoria"] ?? {}),
-      name: (json["Nev"] ?? "").trim(),
-    );
-  }
-
-  @override
-  bool operator ==(other) {
-    if (other is! Subject) return false;
-    return id == other.id;
-  }
-
-  @override
-  int get hashCode => id.hashCode;
-}
+import 'category.dart';
+
+class Subject {
+  String id;
+  Category category;
+  String name;
+  String? renamedTo;
+
+  bool get isRenamed => renamedTo != null;
+
+  Subject({required this.id, required this.category, required this.name, this.renamedTo});
+
+  factory Subject.fromJson(Map json) {
+    final id = json["Uid"] ?? "";
+    return Subject(
+      id: id,
+      category: Category.fromJson(json["Kategoria"] ?? {}),
+      name: (json["Nev"] ?? "").trim(),
+    );
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is! Subject) return false;
+    return id == other.id;
+  }
+
+  @override
+  int get hashCode => id.hashCode;
+}
diff --git a/filcnaplo_kreta_api/lib/models/teacher.dart b/refilc_kreta_api/lib/models/teacher.dart
similarity index 93%
rename from filcnaplo_kreta_api/lib/models/teacher.dart
rename to refilc_kreta_api/lib/models/teacher.dart
index 2ad20c0..43a8b35 100644
--- a/filcnaplo_kreta_api/lib/models/teacher.dart
+++ b/refilc_kreta_api/lib/models/teacher.dart
@@ -1,4 +1,4 @@
-import 'package:filcnaplo/utils/format.dart';
+import 'package:refilc/utils/format.dart';
 
 class Teacher {
   String id;
diff --git a/filcnaplo_kreta_api/lib/models/week.dart b/refilc_kreta_api/lib/models/week.dart
similarity index 73%
rename from filcnaplo_kreta_api/lib/models/week.dart
rename to refilc_kreta_api/lib/models/week.dart
index 03cc048..69a5c34 100644
--- a/filcnaplo_kreta_api/lib/models/week.dart
+++ b/refilc_kreta_api/lib/models/week.dart
@@ -1,41 +1,45 @@
-import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
-
-class Week {
-  DateTime start;
-  DateTime end;
-
-  Week({required this.start, required this.end});
-
-  factory Week.current() => Week.fromDate(DateTime.now());
-
-  factory Week.fromId(int id) {
-    DateTime _now = TimetableController.getSchoolYearStart().add(Duration(days: id * DateTime.daysPerWeek));
-    DateTime now = DateTime(_now.year, _now.month, _now.day);
-    return Week(
-      start: now.subtract(Duration(days: now.weekday - 1)),
-      end: now.add(Duration(days: DateTime.daysPerWeek - now.weekday)),
-    );
-  }
-
-  factory Week.fromDate(DateTime date) {
-    // fix #32
-    DateTime _date = DateTime(date.year, date.month, date.day);
-    return Week(
-      start: _date.subtract(Duration(days: _date.weekday - 1)),
-      end: _date.add(Duration(days: DateTime.daysPerWeek - _date.weekday)),
-    );
-  }
-
-  Week next() => Week.fromDate(start.add(const Duration(days: 8)));
-
-  int get id => -(TimetableController.getSchoolYearStart().difference(start).inDays / DateTime.daysPerWeek).floor();
-
-  @override
-  String toString() => "Week(start: $start, end: $end)";
-
-  @override
-  bool operator ==(Object other) => other is Week && id == other.id;
-
-  @override
-  int get hashCode => id;
-}
+import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
+
+class Week {
+  DateTime start;
+  DateTime end;
+
+  Week({required this.start, required this.end});
+
+  factory Week.current() => Week.fromDate(DateTime.now());
+
+  factory Week.fromId(int id) {
+    DateTime _now = TimetableController.getSchoolYearStart()
+        .add(Duration(days: id * DateTime.daysPerWeek));
+    DateTime now = DateTime(_now.year, _now.month, _now.day);
+    return Week(
+      start: now.subtract(Duration(days: now.weekday - 1)),
+      end: now.add(Duration(days: DateTime.daysPerWeek - now.weekday)),
+    );
+  }
+
+  factory Week.fromDate(DateTime date) {
+    // fix #32
+    DateTime _date = DateTime(date.year, date.month, date.day);
+    return Week(
+      start: _date.subtract(Duration(days: _date.weekday - 1)),
+      end: _date.add(Duration(days: DateTime.daysPerWeek - _date.weekday)),
+    );
+  }
+
+  Week next() => Week.fromDate(start.add(const Duration(days: 8)));
+
+  int get id =>
+      -(TimetableController.getSchoolYearStart().difference(start).inDays /
+              DateTime.daysPerWeek)
+          .floor();
+
+  @override
+  String toString() => "Week(start: $start, end: $end)";
+
+  @override
+  bool operator ==(Object other) => other is Week && id == other.id;
+
+  @override
+  int get hashCode => id;
+}
diff --git a/filcnaplo_kreta_api/lib/providers/absence_provider.dart b/refilc_kreta_api/lib/providers/absence_provider.dart
similarity index 87%
rename from filcnaplo_kreta_api/lib/providers/absence_provider.dart
rename to refilc_kreta_api/lib/providers/absence_provider.dart
index 6450953..f7286c1 100644
--- a/filcnaplo_kreta_api/lib/providers/absence_provider.dart
+++ b/refilc_kreta_api/lib/providers/absence_provider.dart
@@ -1,94 +1,94 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class AbsenceProvider with ChangeNotifier {
-  late List<Absence> _absences;
-  late BuildContext _context;
-  List<Absence> get absences => _absences;
-
-  AbsenceProvider({
-    List<Absence> initialAbsences = const [],
-    required BuildContext context,
-  }) {
-    _absences = List.castFrom(initialAbsences);
-    _context = context;
-
-    if (_absences.isEmpty) restore();
-  }
-
-  Future<void> restore() async {
-    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
-
-    // Load absences from the database
-    if (userId != null) {
-      var dbAbsences =
-          await Provider.of<DatabaseProvider>(_context, listen: false)
-              .userQuery
-              .getAbsences(userId: userId);
-      _absences = dbAbsences;
-      await convertBySettings();
-    }
-  }
-
-  // for renamed subjects
-  Future<void> convertBySettings() async {
-    final _database = Provider.of<DatabaseProvider>(_context, listen: false);
-    Map<String, String> renamedSubjects =
-        (await _database.query.getSettings(_database)).renamedSubjectsEnabled
-            ? await _database.userQuery.renamedSubjects(
-                userId:
-                    Provider.of<UserProvider>(_context, listen: false).user!.id)
-            : {};
-    Map<String, String> renamedTeachers =
-        (await _database.query.getSettings(_database)).renamedTeachersEnabled
-            ? await _database.userQuery.renamedTeachers(
-                userId:
-                    Provider.of<UserProvider>(_context, listen: false).user!.id)
-            : {};
-
-    for (Absence absence in _absences) {
-      absence.subject.renamedTo = renamedSubjects.isNotEmpty
-          ? renamedSubjects[absence.subject.id]
-          : null;
-      absence.teacher.renamedTo = renamedTeachers.isNotEmpty
-          ? renamedTeachers[absence.teacher.id]
-          : null;
-    }
-
-    notifyListeners();
-  }
-
-  // Fetches Absences from the Kreta API then stores them in the database
-  Future<void> fetch() async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot fetch Absences for User null";
-    String iss = user.instituteCode;
-
-    List? absencesJson = await Provider.of<KretaClient>(_context, listen: false)
-        .getAPI(KretaAPI.absences(iss));
-    if (absencesJson == null) throw "Cannot fetch Absences for User ${user.id}";
-    List<Absence> absences =
-        absencesJson.map((e) => Absence.fromJson(e)).toList();
-
-    if (absences.isNotEmpty || _absences.isNotEmpty) await store(absences);
-  }
-
-  // Stores Absences in the database
-  Future<void> store(List<Absence> absences) async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot store Absences for User null";
-    String userId = user.id;
-
-    await Provider.of<DatabaseProvider>(_context, listen: false)
-        .userStore
-        .storeAbsences(absences, userId: userId);
-    _absences = absences;
-    await convertBySettings();
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class AbsenceProvider with ChangeNotifier {
+  late List<Absence> _absences;
+  late BuildContext _context;
+  List<Absence> get absences => _absences;
+
+  AbsenceProvider({
+    List<Absence> initialAbsences = const [],
+    required BuildContext context,
+  }) {
+    _absences = List.castFrom(initialAbsences);
+    _context = context;
+
+    if (_absences.isEmpty) restore();
+  }
+
+  Future<void> restore() async {
+    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
+
+    // Load absences from the database
+    if (userId != null) {
+      var dbAbsences =
+          await Provider.of<DatabaseProvider>(_context, listen: false)
+              .userQuery
+              .getAbsences(userId: userId);
+      _absences = dbAbsences;
+      await convertBySettings();
+    }
+  }
+
+  // for renamed subjects
+  Future<void> convertBySettings() async {
+    final _database = Provider.of<DatabaseProvider>(_context, listen: false);
+    Map<String, String> renamedSubjects =
+        (await _database.query.getSettings(_database)).renamedSubjectsEnabled
+            ? await _database.userQuery.renamedSubjects(
+                userId:
+                    Provider.of<UserProvider>(_context, listen: false).user!.id)
+            : {};
+    Map<String, String> renamedTeachers =
+        (await _database.query.getSettings(_database)).renamedTeachersEnabled
+            ? await _database.userQuery.renamedTeachers(
+                userId:
+                    Provider.of<UserProvider>(_context, listen: false).user!.id)
+            : {};
+
+    for (Absence absence in _absences) {
+      absence.subject.renamedTo = renamedSubjects.isNotEmpty
+          ? renamedSubjects[absence.subject.id]
+          : null;
+      absence.teacher.renamedTo = renamedTeachers.isNotEmpty
+          ? renamedTeachers[absence.teacher.id]
+          : null;
+    }
+
+    notifyListeners();
+  }
+
+  // Fetches Absences from the Kreta API then stores them in the database
+  Future<void> fetch() async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot fetch Absences for User null";
+    String iss = user.instituteCode;
+
+    List? absencesJson = await Provider.of<KretaClient>(_context, listen: false)
+        .getAPI(KretaAPI.absences(iss));
+    if (absencesJson == null) throw "Cannot fetch Absences for User ${user.id}";
+    List<Absence> absences =
+        absencesJson.map((e) => Absence.fromJson(e)).toList();
+
+    if (absences.isNotEmpty || _absences.isNotEmpty) await store(absences);
+  }
+
+  // Stores Absences in the database
+  Future<void> store(List<Absence> absences) async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot store Absences for User null";
+    String userId = user.id;
+
+    await Provider.of<DatabaseProvider>(_context, listen: false)
+        .userStore
+        .storeAbsences(absences, userId: userId);
+    _absences = absences;
+    await convertBySettings();
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/event_provider.dart b/refilc_kreta_api/lib/providers/event_provider.dart
similarity index 72%
rename from filcnaplo_kreta_api/lib/providers/event_provider.dart
rename to refilc_kreta_api/lib/providers/event_provider.dart
index c70a609..63836be 100644
--- a/filcnaplo_kreta_api/lib/providers/event_provider.dart
+++ b/refilc_kreta_api/lib/providers/event_provider.dart
@@ -1,59 +1,65 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class EventProvider with ChangeNotifier {
-  late List<Event> _events;
-  late BuildContext _context;
-  List<Event> get events => _events;
-
-  EventProvider({
-    List<Event> initialEvents = const [],
-    required BuildContext context,
-  }) {
-    _events = List.castFrom(initialEvents);
-    _context = context;
-
-    if (_events.isEmpty) restore();
-  }
-
-  Future<void> restore() async {
-    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
-
-    // Load events from the database
-    if (userId != null) {
-      var dbEvents = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getEvents(userId: userId);
-      _events = dbEvents;
-      notifyListeners();
-    }
-  }
-
-  // Fetches Events from the Kreta API then stores them in the database
-  Future<void> fetch() async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot fetch Events for User null";
-    String iss = user.instituteCode;
-    
-    List? eventsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.events(iss));
-    if (eventsJson == null) throw "Cannot fetch Events for User ${user.id}";
-    List<Event> events = eventsJson.map((e) => Event.fromJson(e)).toList();
-
-    if (events.isNotEmpty || _events.isNotEmpty) await store(events);
-  }
-
-  // Stores Events in the database
-  Future<void> store(List<Event> events) async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot store Events for User null";
-    String userId = user.id;
-
-    await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeEvents(events, userId: userId);
-    _events = events;
-    notifyListeners();
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class EventProvider with ChangeNotifier {
+  late List<Event> _events;
+  late BuildContext _context;
+  List<Event> get events => _events;
+
+  EventProvider({
+    List<Event> initialEvents = const [],
+    required BuildContext context,
+  }) {
+    _events = List.castFrom(initialEvents);
+    _context = context;
+
+    if (_events.isEmpty) restore();
+  }
+
+  Future<void> restore() async {
+    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
+
+    // Load events from the database
+    if (userId != null) {
+      var dbEvents =
+          await Provider.of<DatabaseProvider>(_context, listen: false)
+              .userQuery
+              .getEvents(userId: userId);
+      _events = dbEvents;
+      notifyListeners();
+    }
+  }
+
+  // Fetches Events from the Kreta API then stores them in the database
+  Future<void> fetch() async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot fetch Events for User null";
+    String iss = user.instituteCode;
+
+    List? eventsJson = await Provider.of<KretaClient>(_context, listen: false)
+        .getAPI(KretaAPI.events(iss));
+    if (eventsJson == null) throw "Cannot fetch Events for User ${user.id}";
+    List<Event> events = eventsJson.map((e) => Event.fromJson(e)).toList();
+
+    if (events.isNotEmpty || _events.isNotEmpty) await store(events);
+  }
+
+  // Stores Events in the database
+  Future<void> store(List<Event> events) async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot store Events for User null";
+    String userId = user.id;
+
+    await Provider.of<DatabaseProvider>(_context, listen: false)
+        .userStore
+        .storeEvents(events, userId: userId);
+    _events = events;
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/exam_provider.dart b/refilc_kreta_api/lib/providers/exam_provider.dart
similarity index 75%
rename from filcnaplo_kreta_api/lib/providers/exam_provider.dart
rename to refilc_kreta_api/lib/providers/exam_provider.dart
index 6f69f47..57f0943 100644
--- a/filcnaplo_kreta_api/lib/providers/exam_provider.dart
+++ b/refilc_kreta_api/lib/providers/exam_provider.dart
@@ -1,59 +1,64 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class ExamProvider with ChangeNotifier {
-  late List<Exam> _exams;
-  late BuildContext _context;
-  List<Exam> get exams => _exams;
-
-  ExamProvider({
-    List<Exam> initialExams = const [],
-    required BuildContext context,
-  }) {
-    _exams = List.castFrom(initialExams);
-    _context = context;
-
-    if (_exams.isEmpty) restore();
-  }
-
-  Future<void> restore() async {
-    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
-
-    // Load exams from the database
-    if (userId != null) {
-      var dbExams = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getExams(userId: userId);
-      _exams = dbExams;
-      notifyListeners();
-    }
-  }
-
-  // Fetches Exams from the Kreta API then stores them in the database
-  Future<void> fetch() async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot fetch Exams for User null";
-    String iss = user.instituteCode;
-
-    List? examsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.exams(iss));
-    if (examsJson == null) throw "Cannot fetch Exams for User ${user.id}";
-    List<Exam> exams = examsJson.map((e) => Exam.fromJson(e)).toList();
-
-    if (exams.isNotEmpty || _exams.isNotEmpty) await store(exams);
-  }
-
-  // Stores Exams in the database
-  Future<void> store(List<Exam> exams) async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot store Exams for User null";
-    String userId = user.id;
-
-    await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeExams(exams, userId: userId);
-    _exams = exams;
-    notifyListeners();
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class ExamProvider with ChangeNotifier {
+  late List<Exam> _exams;
+  late BuildContext _context;
+  List<Exam> get exams => _exams;
+
+  ExamProvider({
+    List<Exam> initialExams = const [],
+    required BuildContext context,
+  }) {
+    _exams = List.castFrom(initialExams);
+    _context = context;
+
+    if (_exams.isEmpty) restore();
+  }
+
+  Future<void> restore() async {
+    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
+
+    // Load exams from the database
+    if (userId != null) {
+      var dbExams = await Provider.of<DatabaseProvider>(_context, listen: false)
+          .userQuery
+          .getExams(userId: userId);
+      _exams = dbExams;
+      notifyListeners();
+    }
+  }
+
+  // Fetches Exams from the Kreta API then stores them in the database
+  Future<void> fetch() async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot fetch Exams for User null";
+    String iss = user.instituteCode;
+
+    List? examsJson = await Provider.of<KretaClient>(_context, listen: false)
+        .getAPI(KretaAPI.exams(iss));
+    if (examsJson == null) throw "Cannot fetch Exams for User ${user.id}";
+    List<Exam> exams = examsJson.map((e) => Exam.fromJson(e)).toList();
+
+    if (exams.isNotEmpty || _exams.isNotEmpty) await store(exams);
+  }
+
+  // Stores Exams in the database
+  Future<void> store(List<Exam> exams) async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot store Exams for User null";
+    String userId = user.id;
+
+    await Provider.of<DatabaseProvider>(_context, listen: false)
+        .userStore
+        .storeExams(exams, userId: userId);
+    _exams = exams;
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/grade_provider.dart b/refilc_kreta_api/lib/providers/grade_provider.dart
similarity index 88%
rename from filcnaplo_kreta_api/lib/providers/grade_provider.dart
rename to refilc_kreta_api/lib/providers/grade_provider.dart
index de33a64..d8b2092 100644
--- a/filcnaplo_kreta_api/lib/providers/grade_provider.dart
+++ b/refilc_kreta_api/lib/providers/grade_provider.dart
@@ -1,165 +1,165 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/group_average.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.i18n.dart';
-import 'package:flutter/material.dart';
-
-class GradeProvider with ChangeNotifier {
-  // Private
-  late List<Grade> _grades;
-  late DateTime _lastSeen;
-  late String _groups;
-  List<GroupAverage> _groupAvg = [];
-  late final SettingsProvider _settings;
-  late final UserProvider _user;
-  late final DatabaseProvider _database;
-  late final KretaClient _kreta;
-
-  // Public
-  List<Grade> get grades => _grades;
-  DateTime get lastSeenDate =>
-      _settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
-  String get groups => _groups;
-  List<GroupAverage> get groupAverages => _groupAvg;
-
-  GradeProvider({
-    List<Grade> initialGrades = const [],
-    required SettingsProvider settings,
-    required UserProvider user,
-    required DatabaseProvider database,
-    required KretaClient kreta,
-  }) {
-    _settings = settings;
-    _user = user;
-    _database = database;
-    _kreta = kreta;
-
-    _grades = List.castFrom(initialGrades);
-    _lastSeen = DateTime.now();
-
-    if (_grades.isEmpty) restore();
-  }
-
-  Future<void> seenAll() async {
-    String? userId = _user.id;
-    if (userId != null) {
-      final userStore = _database.userStore;
-      userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
-      _lastSeen = DateTime.now();
-    }
-  }
-
-  Future<void> restore() async {
-    String? userId = _user.id;
-
-    // Load grades from the database
-    if (userId != null) {
-      final userQuery = _database.userQuery;
-
-      _grades = await userQuery.getGrades(userId: userId);
-      await convertBySettings();
-      _groupAvg = await userQuery.getGroupAverages(userId: userId);
-      notifyListeners();
-      DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
-      if (lastSeenDB.millisecondsSinceEpoch == 0 ||
-          lastSeenDB.year == 0 ||
-          !_settings.gradeOpeningFun) {
-        _lastSeen = DateTime.now();
-        await seenAll();
-      } else {
-        _lastSeen = lastSeenDB;
-      }
-      notifyListeners();
-    }
-  }
-
-  // good student mode, renamed subjects
-  Future<void> convertBySettings() async {
-    Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
-        ? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
-        : {};
-    Map<String, String> renamedTeachers = _settings.renamedTeachersEnabled
-        ? await _database.userQuery.renamedTeachers(userId: _user.user!.id)
-        : {};
-
-    for (Grade grade in _grades) {
-      grade.subject.renamedTo =
-          renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
-      grade.teacher.renamedTo =
-          renamedTeachers.isNotEmpty ? renamedTeachers[grade.teacher.id] : null;
-
-      grade.value.value =
-          _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
-      grade.value.valueName = _settings.goodStudent
-          ? "Jeles".i18n
-          : '${grade.json!["SzovegesErtek"]}'
-              .replaceAll(RegExp(r'[(]+[12345]?[)]'), '')
-              .i18n;
-      grade.value.shortName = _settings.goodStudent
-          ? "Jeles".i18n
-          : '${grade.json!["SzovegesErtekelesRovidNev"]}' != "null" &&
-                  '${grade.json!["SzovegesErtekelesRovidNev"]}' != "-" &&
-                  '${grade.json!["SzovegesErtekelesRovidNev"]}'
-                          .replaceAll(RegExp(r'[0123456789]+[%]?'), '') !=
-                      ""
-              ? '${grade.json!["SzovegesErtekelesRovidNev"]}'.i18n
-              : grade.value.valueName;
-    }
-
-    notifyListeners();
-  }
-
-  // Fetches Grades from the Kreta API then stores them in the database
-  Future<void> fetch() async {
-    User? user = _user.user;
-    if (user == null) throw "Cannot fetch Grades for User null";
-    String iss = user.instituteCode;
-
-    List? gradesJson = await _kreta.getAPI(KretaAPI.grades(iss));
-    if (gradesJson == null) throw "Cannot fetch Grades for User ${user.id}";
-    List<Grade> grades = gradesJson.map((e) => Grade.fromJson(e)).toList();
-
-    if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
-
-    List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
-    if (groupsJson == null || groupsJson.isEmpty) {
-      throw "Cannot fetch Groups for User ${user.id}";
-    }
-    _groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
-
-    List? groupAvgJson =
-        await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
-    if (groupAvgJson == null) {
-      throw "Cannot fetch Class Averages for User ${user.id}";
-    }
-    final groupAvgs =
-        groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
-    await storeGroupAvg(groupAvgs);
-  }
-
-  // Stores Grades in the database
-  Future<void> store(List<Grade> grades) async {
-    User? user = _user.user;
-    if (user == null) throw "Cannot store Grades for User null";
-    String userId = user.id;
-
-    await _database.userStore.storeGrades(grades, userId: userId);
-    _grades = grades;
-    await convertBySettings();
-  }
-
-  Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
-    _groupAvg = groupAvgs;
-
-    User? user = _user.user;
-    if (user == null) throw "Cannot store Grades for User null";
-    String userId = user.id;
-    await _database.userStore.storeGroupAverages(groupAvgs, userId: userId);
-    notifyListeners();
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/group_average.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.i18n.dart';
+import 'package:flutter/material.dart';
+
+class GradeProvider with ChangeNotifier {
+  // Private
+  late List<Grade> _grades;
+  late DateTime _lastSeen;
+  late String _groups;
+  List<GroupAverage> _groupAvg = [];
+  late final SettingsProvider _settings;
+  late final UserProvider _user;
+  late final DatabaseProvider _database;
+  late final KretaClient _kreta;
+
+  // Public
+  List<Grade> get grades => _grades;
+  DateTime get lastSeenDate =>
+      _settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
+  String get groups => _groups;
+  List<GroupAverage> get groupAverages => _groupAvg;
+
+  GradeProvider({
+    List<Grade> initialGrades = const [],
+    required SettingsProvider settings,
+    required UserProvider user,
+    required DatabaseProvider database,
+    required KretaClient kreta,
+  }) {
+    _settings = settings;
+    _user = user;
+    _database = database;
+    _kreta = kreta;
+
+    _grades = List.castFrom(initialGrades);
+    _lastSeen = DateTime.now();
+
+    if (_grades.isEmpty) restore();
+  }
+
+  Future<void> seenAll() async {
+    String? userId = _user.id;
+    if (userId != null) {
+      final userStore = _database.userStore;
+      userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
+      _lastSeen = DateTime.now();
+    }
+  }
+
+  Future<void> restore() async {
+    String? userId = _user.id;
+
+    // Load grades from the database
+    if (userId != null) {
+      final userQuery = _database.userQuery;
+
+      _grades = await userQuery.getGrades(userId: userId);
+      await convertBySettings();
+      _groupAvg = await userQuery.getGroupAverages(userId: userId);
+      notifyListeners();
+      DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
+      if (lastSeenDB.millisecondsSinceEpoch == 0 ||
+          lastSeenDB.year == 0 ||
+          !_settings.gradeOpeningFun) {
+        _lastSeen = DateTime.now();
+        await seenAll();
+      } else {
+        _lastSeen = lastSeenDB;
+      }
+      notifyListeners();
+    }
+  }
+
+  // good student mode, renamed subjects
+  Future<void> convertBySettings() async {
+    Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
+        ? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
+        : {};
+    Map<String, String> renamedTeachers = _settings.renamedTeachersEnabled
+        ? await _database.userQuery.renamedTeachers(userId: _user.user!.id)
+        : {};
+
+    for (Grade grade in _grades) {
+      grade.subject.renamedTo =
+          renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
+      grade.teacher.renamedTo =
+          renamedTeachers.isNotEmpty ? renamedTeachers[grade.teacher.id] : null;
+
+      grade.value.value =
+          _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
+      grade.value.valueName = _settings.goodStudent
+          ? "Jeles".i18n
+          : '${grade.json!["SzovegesErtek"]}'
+              .replaceAll(RegExp(r'[(]+[12345]?[)]'), '')
+              .i18n;
+      grade.value.shortName = _settings.goodStudent
+          ? "Jeles".i18n
+          : '${grade.json!["SzovegesErtekelesRovidNev"]}' != "null" &&
+                  '${grade.json!["SzovegesErtekelesRovidNev"]}' != "-" &&
+                  '${grade.json!["SzovegesErtekelesRovidNev"]}'
+                          .replaceAll(RegExp(r'[0123456789]+[%]?'), '') !=
+                      ""
+              ? '${grade.json!["SzovegesErtekelesRovidNev"]}'.i18n
+              : grade.value.valueName;
+    }
+
+    notifyListeners();
+  }
+
+  // Fetches Grades from the Kreta API then stores them in the database
+  Future<void> fetch() async {
+    User? user = _user.user;
+    if (user == null) throw "Cannot fetch Grades for User null";
+    String iss = user.instituteCode;
+
+    List? gradesJson = await _kreta.getAPI(KretaAPI.grades(iss));
+    if (gradesJson == null) throw "Cannot fetch Grades for User ${user.id}";
+    List<Grade> grades = gradesJson.map((e) => Grade.fromJson(e)).toList();
+
+    if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
+
+    List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
+    if (groupsJson == null || groupsJson.isEmpty) {
+      throw "Cannot fetch Groups for User ${user.id}";
+    }
+    _groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
+
+    List? groupAvgJson =
+        await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
+    if (groupAvgJson == null) {
+      throw "Cannot fetch Class Averages for User ${user.id}";
+    }
+    final groupAvgs =
+        groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
+    await storeGroupAvg(groupAvgs);
+  }
+
+  // Stores Grades in the database
+  Future<void> store(List<Grade> grades) async {
+    User? user = _user.user;
+    if (user == null) throw "Cannot store Grades for User null";
+    String userId = user.id;
+
+    await _database.userStore.storeGrades(grades, userId: userId);
+    _grades = grades;
+    await convertBySettings();
+  }
+
+  Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
+    _groupAvg = groupAvgs;
+
+    User? user = _user.user;
+    if (user == null) throw "Cannot store Grades for User null";
+    String userId = user.id;
+    await _database.userStore.storeGroupAverages(groupAvgs, userId: userId);
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/grade_provider.i18n.dart b/refilc_kreta_api/lib/providers/grade_provider.i18n.dart
similarity index 100%
rename from filcnaplo_kreta_api/lib/providers/grade_provider.i18n.dart
rename to refilc_kreta_api/lib/providers/grade_provider.i18n.dart
diff --git a/filcnaplo_kreta_api/lib/providers/homework_provider.dart b/refilc_kreta_api/lib/providers/homework_provider.dart
similarity index 88%
rename from filcnaplo_kreta_api/lib/providers/homework_provider.dart
rename to refilc_kreta_api/lib/providers/homework_provider.dart
index 6985330..ebca1a8 100644
--- a/filcnaplo_kreta_api/lib/providers/homework_provider.dart
+++ b/refilc_kreta_api/lib/providers/homework_provider.dart
@@ -1,124 +1,124 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class HomeworkProvider with ChangeNotifier {
-  // Private
-  late final SettingsProvider _settings;
-  late final UserProvider _user;
-  late final DatabaseProvider _database;
-
-  // Public
-  late List<Homework> _homework;
-  late BuildContext _context;
-  List<Homework> get homework => _homework;
-
-  HomeworkProvider({
-    List<Homework> initialHomework = const [],
-    required BuildContext context,
-    required DatabaseProvider database,
-  }) {
-    _homework = List.castFrom(initialHomework);
-    _context = context;
-    _database = database;
-
-    if (_homework.isEmpty) restore();
-  }
-
-  Future<void> restore() async {
-    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
-
-    // Load homework from the database
-    if (userId != null) {
-      var dbHomework =
-          await Provider.of<DatabaseProvider>(_context, listen: false)
-              .userQuery
-              .getHomework(userId: userId);
-      _homework = dbHomework;
-      await convertBySettings();
-    }
-  }
-
-  Future<void> convertBySettings() async {
-    Map<String, String> renamedSubjects =
-        (await _database.query.getSettings(_database)).renamedSubjectsEnabled
-            ? await _database.userQuery.renamedSubjects(userId: _user.id!)
-            : {};
-    Map<String, String> renamedTeachers =
-        (await _database.query.getSettings(_database)).renamedTeachersEnabled
-            ? await _database.userQuery.renamedTeachers(userId: _user.id!)
-            : {};
-
-    for (Homework homework in _homework) {
-      homework.subject.renamedTo = renamedSubjects.isNotEmpty
-          ? renamedSubjects[homework.subject.id]
-          : null;
-      homework.teacher.renamedTo = renamedTeachers.isNotEmpty
-          ? renamedTeachers[homework.teacher.id]
-          : null;
-    }
-
-    notifyListeners();
-  }
-
-  // Fetches Homework from the Kreta API then stores them in the database
-  Future<void> fetch({DateTime? from, bool db = true}) async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot fetch Homework for User null";
-
-    String iss = user.instituteCode;
-
-    List? homeworkJson = [];
-
-    try {
-      homeworkJson = await Provider.of<KretaClient>(_context, listen: false)
-          .getAPI(KretaAPI.homework(iss, start: from));
-    } catch (e) {
-      // error fetcing homework (unknown error)
-    }
-
-    if (homeworkJson == null) {
-      if (kDebugMode) print("Cannot fetch Homework for User ${user.id}");
-      return;
-    }
-
-    List<Homework> homework = [];
-    await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
-      Map? e = await Provider.of<KretaClient>(_context, listen: false)
-          .getAPI(KretaAPI.homework(iss, id: hw["Uid"]));
-      Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
-          ? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
-          : {};
-
-      if (e != null) {
-        Homework hw = Homework.fromJson(e);
-        hw.subject.renamedTo =
-            renamedSubjects.isNotEmpty ? renamedSubjects[hw.subject.id] : null;
-        homework.add(hw);
-      }
-    });
-
-    if (homework.isEmpty && _homework.isEmpty) return;
-
-    if (db) await store(homework);
-    _homework = homework;
-    notifyListeners();
-  }
-
-  // Stores Homework in the database
-  Future<void> store(List<Homework> homework) async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot store Homework for User null";
-    String userId = user.id;
-    await Provider.of<DatabaseProvider>(_context, listen: false)
-        .userStore
-        .storeHomework(homework, userId: userId);
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class HomeworkProvider with ChangeNotifier {
+  // Private
+  late final SettingsProvider _settings;
+  late final UserProvider _user;
+  late final DatabaseProvider _database;
+
+  // Public
+  late List<Homework> _homework;
+  late BuildContext _context;
+  List<Homework> get homework => _homework;
+
+  HomeworkProvider({
+    List<Homework> initialHomework = const [],
+    required BuildContext context,
+    required DatabaseProvider database,
+  }) {
+    _homework = List.castFrom(initialHomework);
+    _context = context;
+    _database = database;
+
+    if (_homework.isEmpty) restore();
+  }
+
+  Future<void> restore() async {
+    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
+
+    // Load homework from the database
+    if (userId != null) {
+      var dbHomework =
+          await Provider.of<DatabaseProvider>(_context, listen: false)
+              .userQuery
+              .getHomework(userId: userId);
+      _homework = dbHomework;
+      await convertBySettings();
+    }
+  }
+
+  Future<void> convertBySettings() async {
+    Map<String, String> renamedSubjects =
+        (await _database.query.getSettings(_database)).renamedSubjectsEnabled
+            ? await _database.userQuery.renamedSubjects(userId: _user.id!)
+            : {};
+    Map<String, String> renamedTeachers =
+        (await _database.query.getSettings(_database)).renamedTeachersEnabled
+            ? await _database.userQuery.renamedTeachers(userId: _user.id!)
+            : {};
+
+    for (Homework homework in _homework) {
+      homework.subject.renamedTo = renamedSubjects.isNotEmpty
+          ? renamedSubjects[homework.subject.id]
+          : null;
+      homework.teacher.renamedTo = renamedTeachers.isNotEmpty
+          ? renamedTeachers[homework.teacher.id]
+          : null;
+    }
+
+    notifyListeners();
+  }
+
+  // Fetches Homework from the Kreta API then stores them in the database
+  Future<void> fetch({DateTime? from, bool db = true}) async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot fetch Homework for User null";
+
+    String iss = user.instituteCode;
+
+    List? homeworkJson = [];
+
+    try {
+      homeworkJson = await Provider.of<KretaClient>(_context, listen: false)
+          .getAPI(KretaAPI.homework(iss, start: from));
+    } catch (e) {
+      // error fetcing homework (unknown error)
+    }
+
+    if (homeworkJson == null) {
+      if (kDebugMode) print("Cannot fetch Homework for User ${user.id}");
+      return;
+    }
+
+    List<Homework> homework = [];
+    await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
+      Map? e = await Provider.of<KretaClient>(_context, listen: false)
+          .getAPI(KretaAPI.homework(iss, id: hw["Uid"]));
+      Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
+          ? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
+          : {};
+
+      if (e != null) {
+        Homework hw = Homework.fromJson(e);
+        hw.subject.renamedTo =
+            renamedSubjects.isNotEmpty ? renamedSubjects[hw.subject.id] : null;
+        homework.add(hw);
+      }
+    });
+
+    if (homework.isEmpty && _homework.isEmpty) return;
+
+    if (db) await store(homework);
+    _homework = homework;
+    notifyListeners();
+  }
+
+  // Stores Homework in the database
+  Future<void> store(List<Homework> homework) async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot store Homework for User null";
+    String userId = user.id;
+    await Provider.of<DatabaseProvider>(_context, listen: false)
+        .userStore
+        .storeHomework(homework, userId: userId);
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/message_provider.dart b/refilc_kreta_api/lib/providers/message_provider.dart
similarity index 64%
rename from filcnaplo_kreta_api/lib/providers/message_provider.dart
rename to refilc_kreta_api/lib/providers/message_provider.dart
index 8499b85..11ee531 100644
--- a/filcnaplo_kreta_api/lib/providers/message_provider.dart
+++ b/refilc_kreta_api/lib/providers/message_provider.dart
@@ -1,80 +1,91 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class MessageProvider with ChangeNotifier {
-  late List<Message> _messages;
-  late BuildContext _context;
-  List<Message> get messages => _messages;
-
-  MessageProvider({
-    List<Message> initialMessages = const [],
-    required BuildContext context,
-  }) {
-    _messages = List.castFrom(initialMessages);
-    _context = context;
-
-    if (_messages.isEmpty) restore();
-  }
-
-  Future<void> restore() async {
-    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
-
-    // Load messages from the database
-    if (userId != null) {
-      var dbMessages = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getMessages(userId: userId);
-      _messages = dbMessages;
-      notifyListeners();
-    }
-  }
-
-  // Fetches all types of Messages
-  Future<void> fetchAll() => Future.forEach(MessageType.values, (MessageType v) => fetch(type: v));
-
-  // Fetches Messages from the Kreta API then stores them in the database
-  Future<void> fetch({MessageType type = MessageType.inbox}) async {
-    // Check Message Type
-    if (type == MessageType.draft) return;
-    String messageType = ["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
-
-    // Check User
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot fetch Messages for User null";
-
-    // Get messages
-    List? messagesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.messages(messageType));
-    if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}";
-
-    // Parse messages
-    List<Message> messages = [];
-    await Future.wait(List.generate(messagesJson.length, (index) {
-      return () async {
-        Map message = messagesJson.cast<Map>()[index];
-        Map? messageJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.message(message["azonosito"].toString()));
-        if (messageJson != null) messages.add(Message.fromJson(messageJson, forceType: type));
-      }();
-    }));
-
-    await store(messages, type);
-  }
-
-  // Stores Messages in the database
-  Future<void> store(List<Message> messages, MessageType type) async {
-    // Only store the specified type
-    _messages.removeWhere((m) => m.type == type);
-    _messages.addAll(messages);
-
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot store Messages for User null";
-
-    String userId = user.id;
-    await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeMessages(_messages, userId: userId);
-
-    notifyListeners();
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class MessageProvider with ChangeNotifier {
+  late List<Message> _messages;
+  late BuildContext _context;
+  List<Message> get messages => _messages;
+
+  MessageProvider({
+    List<Message> initialMessages = const [],
+    required BuildContext context,
+  }) {
+    _messages = List.castFrom(initialMessages);
+    _context = context;
+
+    if (_messages.isEmpty) restore();
+  }
+
+  Future<void> restore() async {
+    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
+
+    // Load messages from the database
+    if (userId != null) {
+      var dbMessages =
+          await Provider.of<DatabaseProvider>(_context, listen: false)
+              .userQuery
+              .getMessages(userId: userId);
+      _messages = dbMessages;
+      notifyListeners();
+    }
+  }
+
+  // Fetches all types of Messages
+  Future<void> fetchAll() =>
+      Future.forEach(MessageType.values, (MessageType v) => fetch(type: v));
+
+  // Fetches Messages from the Kreta API then stores them in the database
+  Future<void> fetch({MessageType type = MessageType.inbox}) async {
+    // Check Message Type
+    if (type == MessageType.draft) return;
+    String messageType =
+        ["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
+
+    // Check User
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot fetch Messages for User null";
+
+    // Get messages
+    List? messagesJson = await Provider.of<KretaClient>(_context, listen: false)
+        .getAPI(KretaAPI.messages(messageType));
+    if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}";
+
+    // Parse messages
+    List<Message> messages = [];
+    await Future.wait(List.generate(messagesJson.length, (index) {
+      return () async {
+        Map message = messagesJson.cast<Map>()[index];
+        Map? messageJson =
+            await Provider.of<KretaClient>(_context, listen: false)
+                .getAPI(KretaAPI.message(message["azonosito"].toString()));
+        if (messageJson != null)
+          messages.add(Message.fromJson(messageJson, forceType: type));
+      }();
+    }));
+
+    await store(messages, type);
+  }
+
+  // Stores Messages in the database
+  Future<void> store(List<Message> messages, MessageType type) async {
+    // Only store the specified type
+    _messages.removeWhere((m) => m.type == type);
+    _messages.addAll(messages);
+
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot store Messages for User null";
+
+    String userId = user.id;
+    await Provider.of<DatabaseProvider>(_context, listen: false)
+        .userStore
+        .storeMessages(_messages, userId: userId);
+
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/note_provider.dart b/refilc_kreta_api/lib/providers/note_provider.dart
similarity index 75%
rename from filcnaplo_kreta_api/lib/providers/note_provider.dart
rename to refilc_kreta_api/lib/providers/note_provider.dart
index f43a48a..42a232b 100644
--- a/filcnaplo_kreta_api/lib/providers/note_provider.dart
+++ b/refilc_kreta_api/lib/providers/note_provider.dart
@@ -1,59 +1,64 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/api.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class NoteProvider with ChangeNotifier {
-  late List<Note> _notes;
-  late BuildContext _context;
-  List<Note> get notes => _notes;
-
-  NoteProvider({
-    List<Note> initialNotes = const [],
-    required BuildContext context,
-  }) {
-    _notes = List.castFrom(initialNotes);
-    _context = context;
-
-    if (_notes.isEmpty) restore();
-  }
-
-  Future<void> restore() async {
-    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
-
-    // Load notes from the database
-    if (userId != null) {
-      var dbNotes = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getNotes(userId: userId);
-      _notes = dbNotes;
-      notifyListeners();
-    }
-  }
-
-  // Fetches Notes from the Kreta API then stores them in the database
-  Future<void> fetch() async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot fetch Notes for User null";
-    String iss = user.instituteCode;
-
-    List? notesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.notes(iss));
-    if (notesJson == null) throw "Cannot fetch Notes for User ${user.id}";
-    List<Note> notes = notesJson.map((e) => Note.fromJson(e)).toList();
-
-    if (notes.isNotEmpty || _notes.isNotEmpty) await store(notes);
-  }
-
-  // Stores Notes in the database
-  Future<void> store(List<Note> notes) async {
-    User? user = Provider.of<UserProvider>(_context, listen: false).user;
-    if (user == null) throw "Cannot store Notes for User null";
-    String userId = user.id;
-
-    await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeNotes(notes, userId: userId);
-    _notes = notes;
-    notifyListeners();
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class NoteProvider with ChangeNotifier {
+  late List<Note> _notes;
+  late BuildContext _context;
+  List<Note> get notes => _notes;
+
+  NoteProvider({
+    List<Note> initialNotes = const [],
+    required BuildContext context,
+  }) {
+    _notes = List.castFrom(initialNotes);
+    _context = context;
+
+    if (_notes.isEmpty) restore();
+  }
+
+  Future<void> restore() async {
+    String? userId = Provider.of<UserProvider>(_context, listen: false).id;
+
+    // Load notes from the database
+    if (userId != null) {
+      var dbNotes = await Provider.of<DatabaseProvider>(_context, listen: false)
+          .userQuery
+          .getNotes(userId: userId);
+      _notes = dbNotes;
+      notifyListeners();
+    }
+  }
+
+  // Fetches Notes from the Kreta API then stores them in the database
+  Future<void> fetch() async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot fetch Notes for User null";
+    String iss = user.instituteCode;
+
+    List? notesJson = await Provider.of<KretaClient>(_context, listen: false)
+        .getAPI(KretaAPI.notes(iss));
+    if (notesJson == null) throw "Cannot fetch Notes for User ${user.id}";
+    List<Note> notes = notesJson.map((e) => Note.fromJson(e)).toList();
+
+    if (notes.isNotEmpty || _notes.isNotEmpty) await store(notes);
+  }
+
+  // Stores Notes in the database
+  Future<void> store(List<Note> notes) async {
+    User? user = Provider.of<UserProvider>(_context, listen: false).user;
+    if (user == null) throw "Cannot store Notes for User null";
+    String userId = user.id;
+
+    await Provider.of<DatabaseProvider>(_context, listen: false)
+        .userStore
+        .storeNotes(notes, userId: userId);
+    _notes = notes;
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart b/refilc_kreta_api/lib/providers/timetable_provider.dart
similarity index 86%
rename from filcnaplo_kreta_api/lib/providers/timetable_provider.dart
rename to refilc_kreta_api/lib/providers/timetable_provider.dart
index 1b9a3ef..0e63132 100644
--- a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
+++ b/refilc_kreta_api/lib/providers/timetable_provider.dart
@@ -1,110 +1,110 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-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';
-
-class TimetableProvider with ChangeNotifier {
-  Map<Week, List<Lesson>> lessons = {};
-  late final UserProvider _user;
-  late final DatabaseProvider _database;
-  late final KretaClient _kreta;
-
-  TimetableProvider({
-    required UserProvider user,
-    required DatabaseProvider database,
-    required KretaClient kreta,
-  })  : _user = user,
-        _database = database,
-        _kreta = kreta {
-    restoreUser();
-  }
-
-  Future<void> restoreUser() async {
-    String? userId = _user.id;
-
-    // Load lessons from the database
-    if (userId != null) {
-      var dbLessons = await _database.userQuery.getLessons(userId: userId);
-      lessons = dbLessons;
-      await convertBySettings();
-    }
-  }
-
-  // for renamed subjects
-  Future<void> convertBySettings() async {
-    Map<String, String> renamedSubjects =
-        (await _database.query.getSettings(_database)).renamedSubjectsEnabled
-            ? await _database.userQuery.renamedSubjects(userId: _user.id!)
-            : {};
-    Map<String, String> renamedTeachers =
-        (await _database.query.getSettings(_database)).renamedTeachersEnabled
-            ? await _database.userQuery.renamedTeachers(userId: _user.id!)
-            : {};
-
-    for (Lesson lesson in lessons.values.expand((e) => e)) {
-      lesson.subject.renamedTo = renamedSubjects.isNotEmpty
-          ? renamedSubjects[lesson.subject.id]
-          : null;
-      lesson.teacher.renamedTo = renamedTeachers.isNotEmpty
-          ? renamedTeachers[lesson.teacher.id]
-          : null;
-    }
-
-    notifyListeners();
-  }
-
-  List<Lesson>? getWeek(Week week) => lessons[week];
-
-  // Fetches Lessons from the Kreta API then stores them in the database
-  Future<void> fetch({Week? week}) async {
-    if (week == null) return;
-    User? user = _user.user;
-    if (user == null) throw "Cannot fetch Lessons for User null";
-    String iss = user.instituteCode;
-    List? lessonsJson = await _kreta
-        .getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
-
-    if (lessonsJson == null) {
-      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();
-      await convertBySettings();
-    }
-  }
-
-  // Stores Lessons in the database
-  Future<void> store() async {
-    User? user = _user.user;
-    if (user == null) throw "Cannot store Lessons for User null";
-    String userId = user.id;
-
-    // -TODO: clear indexes with weeks outside of the current school year
-    await _database.userStore.storeLessons(lessons, userId: userId);
-  }
-
-  // Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
-  //   _subjectLessonCount = lessonCount;
-
-  //   if (store) {
-  //     User? user = Provider.of<UserProvider>(_context, listen: false).user;
-  //     if (user == null) throw "Cannot store Lesson Count for User null";
-  //     String userId = user.id;
-
-  //     await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeSubjectLessonCount(lessonCount, userId: userId);
-  //   }
-
-  //   notifyListeners();
-  // }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/api.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:flutter/material.dart';
+
+class TimetableProvider with ChangeNotifier {
+  Map<Week, List<Lesson>> lessons = {};
+  late final UserProvider _user;
+  late final DatabaseProvider _database;
+  late final KretaClient _kreta;
+
+  TimetableProvider({
+    required UserProvider user,
+    required DatabaseProvider database,
+    required KretaClient kreta,
+  })  : _user = user,
+        _database = database,
+        _kreta = kreta {
+    restoreUser();
+  }
+
+  Future<void> restoreUser() async {
+    String? userId = _user.id;
+
+    // Load lessons from the database
+    if (userId != null) {
+      var dbLessons = await _database.userQuery.getLessons(userId: userId);
+      lessons = dbLessons;
+      await convertBySettings();
+    }
+  }
+
+  // for renamed subjects
+  Future<void> convertBySettings() async {
+    Map<String, String> renamedSubjects =
+        (await _database.query.getSettings(_database)).renamedSubjectsEnabled
+            ? await _database.userQuery.renamedSubjects(userId: _user.id!)
+            : {};
+    Map<String, String> renamedTeachers =
+        (await _database.query.getSettings(_database)).renamedTeachersEnabled
+            ? await _database.userQuery.renamedTeachers(userId: _user.id!)
+            : {};
+
+    for (Lesson lesson in lessons.values.expand((e) => e)) {
+      lesson.subject.renamedTo = renamedSubjects.isNotEmpty
+          ? renamedSubjects[lesson.subject.id]
+          : null;
+      lesson.teacher.renamedTo = renamedTeachers.isNotEmpty
+          ? renamedTeachers[lesson.teacher.id]
+          : null;
+    }
+
+    notifyListeners();
+  }
+
+  List<Lesson>? getWeek(Week week) => lessons[week];
+
+  // Fetches Lessons from the Kreta API then stores them in the database
+  Future<void> fetch({Week? week}) async {
+    if (week == null) return;
+    User? user = _user.user;
+    if (user == null) throw "Cannot fetch Lessons for User null";
+    String iss = user.instituteCode;
+    List? lessonsJson = await _kreta
+        .getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
+
+    if (lessonsJson == null) {
+      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();
+      await convertBySettings();
+    }
+  }
+
+  // Stores Lessons in the database
+  Future<void> store() async {
+    User? user = _user.user;
+    if (user == null) throw "Cannot store Lessons for User null";
+    String userId = user.id;
+
+    // -TODO: clear indexes with weeks outside of the current school year
+    await _database.userStore.storeLessons(lessons, userId: userId);
+  }
+
+  // Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
+  //   _subjectLessonCount = lessonCount;
+
+  //   if (store) {
+  //     User? user = Provider.of<UserProvider>(_context, listen: false).user;
+  //     if (user == null) throw "Cannot store Lesson Count for User null";
+  //     String userId = user.id;
+
+  //     await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeSubjectLessonCount(lessonCount, userId: userId);
+  //   }
+
+  //   notifyListeners();
+  // }
+}
diff --git a/filcnaplo_kreta_api/pubspec.yaml b/refilc_kreta_api/pubspec.yaml
similarity index 71%
rename from filcnaplo_kreta_api/pubspec.yaml
rename to refilc_kreta_api/pubspec.yaml
index e9375a9..74da970 100644
--- a/filcnaplo_kreta_api/pubspec.yaml
+++ b/refilc_kreta_api/pubspec.yaml
@@ -1,17 +1,17 @@
-name: filcnaplo_kreta_api
-publish_to: "none"
-
-environment:
-  sdk: ">=2.17.0 <3.0.0"
-
-dependencies:
-  flutter:
-    sdk: flutter
-  filcnaplo:
-    path: ../filcnaplo/
-  http: ^0.13.3
-  provider: ^5.0.0
-  file_picker: ^5.3.2
-
-dev_dependencies:
-  flutter_lints: ^1.0.0
+name: refilc_kreta_api
+publish_to: "none"
+
+environment:
+  sdk: ">=2.17.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  refilc:
+    path: ../refilc/
+  http: ^0.13.3
+  provider: ^5.0.0
+  file_picker: ^5.3.2
+
+dev_dependencies:
+  flutter_lints: ^1.0.0
diff --git a/filcnaplo_mobile_ui/.github/dependabot.yml b/refilc_mobile_ui/.github/dependabot.yml
similarity index 97%
rename from filcnaplo_mobile_ui/.github/dependabot.yml
rename to refilc_mobile_ui/.github/dependabot.yml
index 9fc48a7..8702968 100644
--- a/filcnaplo_mobile_ui/.github/dependabot.yml
+++ b/refilc_mobile_ui/.github/dependabot.yml
@@ -1,11 +1,11 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
-
-version: 2
-updates:
-  - package-ecosystem: "pub" # See documentation for possible values
-    directory: "/" # Location of package manifests
-    schedule:
-      interval: "daily"
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+  - package-ecosystem: "pub" # See documentation for possible values
+    directory: "/" # Location of package manifests
+    schedule:
+      interval: "daily"
diff --git a/filcnaplo_mobile_ui/LICENSE b/refilc_mobile_ui/LICENSE
old mode 100755
new mode 100644
similarity index 98%
rename from filcnaplo_mobile_ui/LICENSE
rename to refilc_mobile_ui/LICENSE
index 1024750..21b1553
--- a/filcnaplo_mobile_ui/LICENSE
+++ b/refilc_mobile_ui/LICENSE
@@ -1,29 +1,29 @@
-BSD 3-Clause License
-
-Copyright (c) 2023, reFilc
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+BSD 3-Clause License
+
+Copyright (c) 2023, reFilc
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/filcnaplo_mobile_ui/README.md b/refilc_mobile_ui/README.md
old mode 100755
new mode 100644
similarity index 100%
rename from filcnaplo_mobile_ui/README.md
rename to refilc_mobile_ui/README.md
diff --git a/filcnaplo_kreta_api/analysis_options.yaml b/refilc_mobile_ui/analysis_options.yaml
similarity index 98%
rename from filcnaplo_kreta_api/analysis_options.yaml
rename to refilc_mobile_ui/analysis_options.yaml
index 16f5f56..fd16f92 100644
--- a/filcnaplo_kreta_api/analysis_options.yaml
+++ b/refilc_mobile_ui/analysis_options.yaml
@@ -1,28 +1,28 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
-  # The lint rules applied to this project can be customized in the
-  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
-  # included above or to enable additional rules. A list of all available lints
-  # and their documentation is published at
-  # https://dart-lang.github.io/linter/lints/index.html.
-  #
-  # Instead of disabling a lint rule for the entire project in the
-  # section below, it can also be suppressed for a single line of code
-  # or a specific dart file by using the `// ignore: name_of_lint` and
-  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
-  # producing the lint.
-  rules:
-    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
-    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/filcnaplo_mobile_ui/lib/common/action_button.dart b/refilc_mobile_ui/lib/common/action_button.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/action_button.dart
rename to refilc_mobile_ui/lib/common/action_button.dart
index fc316a1..80c6aa9
--- a/filcnaplo_mobile_ui/lib/common/action_button.dart
+++ b/refilc_mobile_ui/lib/common/action_button.dart
@@ -1,36 +1,36 @@
-import 'package:flutter/material.dart';
-
-class ActionButton extends StatelessWidget {
-  const ActionButton({Key? key, required this.label, this.activeColor, this.onTap}) : super(key: key);
-
-  final Color? activeColor;
-  final void Function()? onTap;
-  final String label;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(top: 6.0, bottom: 6.0, right: 3.0),
-      child: InkWell(
-        onTap: onTap,
-        borderRadius: BorderRadius.circular(6.0),
-        child: AnimatedContainer(
-          duration: const Duration(milliseconds: 200),
-          curve: Curves.easeInOut,
-          height: 32.0,
-          decoration: BoxDecoration(
-            color: (activeColor ?? Theme.of(context).colorScheme.secondary).withOpacity(0.25),
-            borderRadius: BorderRadius.circular(6.0),
-          ),
-          padding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 12.0),
-          child: Center(
-              child: Text(label,
-                  maxLines: 1,
-                  softWrap: false,
-                  overflow: TextOverflow.ellipsis,
-                  style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.w600, color: activeColor ?? Theme.of(context).colorScheme.secondary))),
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class ActionButton extends StatelessWidget {
+  const ActionButton({Key? key, required this.label, this.activeColor, this.onTap}) : super(key: key);
+
+  final Color? activeColor;
+  final void Function()? onTap;
+  final String label;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(top: 6.0, bottom: 6.0, right: 3.0),
+      child: InkWell(
+        onTap: onTap,
+        borderRadius: BorderRadius.circular(6.0),
+        child: AnimatedContainer(
+          duration: const Duration(milliseconds: 200),
+          curve: Curves.easeInOut,
+          height: 32.0,
+          decoration: BoxDecoration(
+            color: (activeColor ?? Theme.of(context).colorScheme.secondary).withOpacity(0.25),
+            borderRadius: BorderRadius.circular(6.0),
+          ),
+          padding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 12.0),
+          child: Center(
+              child: Text(label,
+                  maxLines: 1,
+                  softWrap: false,
+                  overflow: TextOverflow.ellipsis,
+                  style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.w600, color: activeColor ?? Theme.of(context).colorScheme.secondary))),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/average_display.dart b/refilc_mobile_ui/lib/common/average_display.dart
old mode 100755
new mode 100644
similarity index 89%
rename from filcnaplo_mobile_ui/lib/common/average_display.dart
rename to refilc_mobile_ui/lib/common/average_display.dart
index 735497e..e88987e
--- a/filcnaplo_mobile_ui/lib/common/average_display.dart
+++ b/refilc_mobile_ui/lib/common/average_display.dart
@@ -1,45 +1,45 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-
-class AverageDisplay extends StatelessWidget {
-  const AverageDisplay({Key? key, this.average = 0.0, this.border = false})
-      : super(key: key);
-
-  final double average;
-  final bool border;
-
-  @override
-  Widget build(BuildContext context) {
-    Color color = average == 0.0
-        ? AppColors.of(context).text.withOpacity(.8)
-        : gradeColor(context: context, value: average);
-
-    String averageText = average.toStringAsFixed(2);
-    if (I18n.of(context).locale.languageCode != "en") {
-      averageText = averageText.replaceAll(".", ",");
-    }
-
-    return Container(
-      width: border ? 57.0 : 54.0,
-      padding: EdgeInsets.symmetric(
-          horizontal: 8.0 - (border ? 2 : 0), vertical: 6.0 - (border ? 2 : 0)),
-      decoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(45.0),
-        border: border
-            ? Border.fromBorderSide(
-                BorderSide(color: color.withOpacity(.5), width: 3.0))
-            : null,
-        color: !border ? color.withOpacity(average == 0.0 ? .15 : .25) : null,
-      ),
-      child: Text(
-        average == 0.0 ? "-" : averageText,
-        textAlign: TextAlign.center,
-        style: TextStyle(
-            color: color, fontWeight: FontWeight.w600, fontSize: 14.0),
-        maxLines: 1,
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+
+class AverageDisplay extends StatelessWidget {
+  const AverageDisplay({Key? key, this.average = 0.0, this.border = false})
+      : super(key: key);
+
+  final double average;
+  final bool border;
+
+  @override
+  Widget build(BuildContext context) {
+    Color color = average == 0.0
+        ? AppColors.of(context).text.withOpacity(.8)
+        : gradeColor(context: context, value: average);
+
+    String averageText = average.toStringAsFixed(2);
+    if (I18n.of(context).locale.languageCode != "en") {
+      averageText = averageText.replaceAll(".", ",");
+    }
+
+    return Container(
+      width: border ? 57.0 : 54.0,
+      padding: EdgeInsets.symmetric(
+          horizontal: 8.0 - (border ? 2 : 0), vertical: 6.0 - (border ? 2 : 0)),
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(45.0),
+        border: border
+            ? Border.fromBorderSide(
+                BorderSide(color: color.withOpacity(.5), width: 3.0))
+            : null,
+        color: !border ? color.withOpacity(average == 0.0 ? .15 : .25) : null,
+      ),
+      child: Text(
+        average == 0.0 ? "-" : averageText,
+        textAlign: TextAlign.center,
+        style: TextStyle(
+            color: color, fontWeight: FontWeight.w600, fontSize: 14.0),
+        maxLines: 1,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/beta_chip.dart b/refilc_mobile_ui/lib/common/beta_chip.dart
similarity index 95%
rename from filcnaplo_mobile_ui/lib/common/beta_chip.dart
rename to refilc_mobile_ui/lib/common/beta_chip.dart
index 9b4c0e8..0695b75 100644
--- a/filcnaplo_mobile_ui/lib/common/beta_chip.dart
+++ b/refilc_mobile_ui/lib/common/beta_chip.dart
@@ -1,4 +1,4 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
+import 'package:refilc/theme/colors/colors.dart';
 import 'package:flutter/material.dart';
 
 class BetaChip extends StatelessWidget {
diff --git a/filcnaplo_mobile_ui/lib/common/bottom_card.dart b/refilc_mobile_ui/lib/common/bottom_card.dart
old mode 100755
new mode 100644
similarity index 93%
rename from filcnaplo_mobile_ui/lib/common/bottom_card.dart
rename to refilc_mobile_ui/lib/common/bottom_card.dart
index 82c4c86..b2f40b9
--- a/filcnaplo_mobile_ui/lib/common/bottom_card.dart
+++ b/refilc_mobile_ui/lib/common/bottom_card.dart
@@ -1,51 +1,51 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class BottomCard extends StatelessWidget {
-  const BottomCard({Key? key, this.child}) : super(key: key);
-
-  final Widget? child;
-
-  @override
-  Widget build(BuildContext context) {
-    return SafeArea(
-      child: Padding(
-        padding: const EdgeInsets.all(12.0),
-        child: Container(
-          decoration: BoxDecoration(
-            borderRadius: BorderRadius.circular(14.0),
-            color: Theme.of(context).colorScheme.background,
-          ),
-          child: Column(
-            mainAxisSize: MainAxisSize.min,
-            children: [
-              Container(
-                width: 42.0,
-                height: 4.0,
-                margin: const EdgeInsets.only(top: 12.0, bottom: 4.0),
-                decoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(45.0),
-                  color: AppColors.of(context).text.withOpacity(0.10),
-                ),
-              ),
-              if (child != null) child!,
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-Future<void> showBottomCard({
-  required BuildContext context,
-  Widget? child,
-  bool rootNavigator = true,
-}) async =>
-    await showModalBottomSheet(
-        backgroundColor: const Color(0x00000000),
-        useRootNavigator: rootNavigator,
-        elevation: 0,
-        isDismissible: true,
-        context: context,
-        builder: (context) => BottomCard(child: child));
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class BottomCard extends StatelessWidget {
+  const BottomCard({Key? key, this.child}) : super(key: key);
+
+  final Widget? child;
+
+  @override
+  Widget build(BuildContext context) {
+    return SafeArea(
+      child: Padding(
+        padding: const EdgeInsets.all(12.0),
+        child: Container(
+          decoration: BoxDecoration(
+            borderRadius: BorderRadius.circular(14.0),
+            color: Theme.of(context).colorScheme.background,
+          ),
+          child: Column(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              Container(
+                width: 42.0,
+                height: 4.0,
+                margin: const EdgeInsets.only(top: 12.0, bottom: 4.0),
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(45.0),
+                  color: AppColors.of(context).text.withOpacity(0.10),
+                ),
+              ),
+              if (child != null) child!,
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+Future<void> showBottomCard({
+  required BuildContext context,
+  Widget? child,
+  bool rootNavigator = true,
+}) async =>
+    await showModalBottomSheet(
+        backgroundColor: const Color(0x00000000),
+        useRootNavigator: rootNavigator,
+        elevation: 0,
+        isDismissible: true,
+        context: context,
+        builder: (context) => BottomCard(child: child));
diff --git a/filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu.dart b/refilc_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu.dart
old mode 100755
new mode 100644
similarity index 72%
rename from filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu.dart
rename to refilc_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu.dart
index c447ee7..0200d7f
--- a/filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu.dart
+++ b/refilc_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu.dart
@@ -1,22 +1,23 @@
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
-import 'package:flutter/material.dart';
-
-class BottomSheetMenu extends StatelessWidget {
-  const BottomSheetMenu({Key? key, this.items = const []}) : super(key: key);
-
-  final List<Widget> items;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.all(12.0),
-      child: Column(
-        mainAxisSize: MainAxisSize.min,
-        children: items,
-      ),
-    );
-  }
-}
-
-void showBottomSheetMenu(BuildContext context, {List<Widget> items = const []}) =>
-    showRoundedModalBottomSheet(context, child: BottomSheetMenu(items: items));
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
+import 'package:flutter/material.dart';
+
+class BottomSheetMenu extends StatelessWidget {
+  const BottomSheetMenu({Key? key, this.items = const []}) : super(key: key);
+
+  final List<Widget> items;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.all(12.0),
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: items,
+      ),
+    );
+  }
+}
+
+void showBottomSheetMenu(BuildContext context,
+        {List<Widget> items = const []}) =>
+    showRoundedModalBottomSheet(context, child: BottomSheetMenu(items: items));
diff --git a/filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu_item.dart b/refilc_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu_item.dart
old mode 100755
new mode 100644
similarity index 62%
rename from filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu_item.dart
rename to refilc_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu_item.dart
index 525feea..9497969
--- a/filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu_item.dart
+++ b/refilc_mobile_ui/lib/common/bottom_sheet_menu/bottom_sheet_menu_item.dart
@@ -1,19 +1,21 @@
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:flutter/material.dart';
-
-class BottomSheetMenuItem extends StatelessWidget {
-  const BottomSheetMenuItem({Key? key, required this.onPressed, required this.title, this.icon}) : super(key: key);
-
-  final void Function()? onPressed;
-  final Widget? title;
-  final Widget? icon;
-
-  @override
-  Widget build(BuildContext context) {
-    return PanelButton(
-      onPressed: onPressed,
-      leading: icon,
-      title: title,
-    );
-  }
-}
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:flutter/material.dart';
+
+class BottomSheetMenuItem extends StatelessWidget {
+  const BottomSheetMenuItem(
+      {Key? key, required this.onPressed, required this.title, this.icon})
+      : super(key: key);
+
+  final void Function()? onPressed;
+  final Widget? title;
+  final Widget? icon;
+
+  @override
+  Widget build(BuildContext context) {
+    return PanelButton(
+      onPressed: onPressed,
+      leading: icon,
+      title: title,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/rounded_bottom_sheet.dart b/refilc_mobile_ui/lib/common/bottom_sheet_menu/rounded_bottom_sheet.dart
old mode 100755
new mode 100644
similarity index 88%
rename from filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/rounded_bottom_sheet.dart
rename to refilc_mobile_ui/lib/common/bottom_sheet_menu/rounded_bottom_sheet.dart
index e0d5689..a384d52
--- a/filcnaplo_mobile_ui/lib/common/bottom_sheet_menu/rounded_bottom_sheet.dart
+++ b/refilc_mobile_ui/lib/common/bottom_sheet_menu/rounded_bottom_sheet.dart
@@ -1,70 +1,76 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class RoundedBottomSheet extends StatelessWidget {
-  const RoundedBottomSheet({Key? key, this.child, this.borderRadius = 12.0, this.shrink = true, this.showHandle = true}) : super(key: key);
-
-  final Widget? child;
-  final double borderRadius;
-  final bool shrink;
-  final bool showHandle;
-
-  @override
-  Widget build(BuildContext context) {
-    return AnimatedContainer(
-      duration: const Duration(milliseconds: 500),
-      decoration: BoxDecoration(
-        color: Theme.of(context).colorScheme.background,
-        borderRadius: BorderRadius.only(
-          topLeft: Radius.circular(borderRadius),
-          topRight: Radius.circular(borderRadius),
-        ),
-      ),
-      child: SafeArea(
-        child: Column(
-          mainAxisSize: shrink ? MainAxisSize.min : MainAxisSize.max,
-          children: [
-            if (showHandle)
-              Container(
-                width: 42.0,
-                height: 4.0,
-                margin: const EdgeInsets.only(top: 12.0, bottom: 4.0),
-                decoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(45.0),
-                  color: AppColors.of(context).text.withOpacity(0.10),
-                ),
-              ),
-            if (child != null) child!,
-            SizedBox(height: MediaQuery.of(context).padding.bottom),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-Future<T?> showRoundedModalBottomSheet<T>(
-  BuildContext context, {
-  required Widget child,
-  bool rootNavigator = true,
-}) async {
-  return await showModalBottomSheet<T>(
-      context: context,
-      backgroundColor: const Color(0x00000000),
-      elevation: 0,
-      isDismissible: true,
-      useRootNavigator: rootNavigator,
-      builder: (context) => RoundedBottomSheet(child: child));
-}
-
-PersistentBottomSheetController<T> showRoundedBottomSheet<T>(
-  BuildContext context, {
-  required Widget child,
-}) {
-  return showBottomSheet<T>(
-    context: context,
-    backgroundColor: const Color(0x00000000),
-    elevation: 12.0,
-    builder: (context) => RoundedBottomSheet(child: child),
-  );
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class RoundedBottomSheet extends StatelessWidget {
+  const RoundedBottomSheet(
+      {Key? key,
+      this.child,
+      this.borderRadius = 12.0,
+      this.shrink = true,
+      this.showHandle = true})
+      : super(key: key);
+
+  final Widget? child;
+  final double borderRadius;
+  final bool shrink;
+  final bool showHandle;
+
+  @override
+  Widget build(BuildContext context) {
+    return AnimatedContainer(
+      duration: const Duration(milliseconds: 500),
+      decoration: BoxDecoration(
+        color: Theme.of(context).colorScheme.background,
+        borderRadius: BorderRadius.only(
+          topLeft: Radius.circular(borderRadius),
+          topRight: Radius.circular(borderRadius),
+        ),
+      ),
+      child: SafeArea(
+        child: Column(
+          mainAxisSize: shrink ? MainAxisSize.min : MainAxisSize.max,
+          children: [
+            if (showHandle)
+              Container(
+                width: 42.0,
+                height: 4.0,
+                margin: const EdgeInsets.only(top: 12.0, bottom: 4.0),
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(45.0),
+                  color: AppColors.of(context).text.withOpacity(0.10),
+                ),
+              ),
+            if (child != null) child!,
+            SizedBox(height: MediaQuery.of(context).padding.bottom),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+Future<T?> showRoundedModalBottomSheet<T>(
+  BuildContext context, {
+  required Widget child,
+  bool rootNavigator = true,
+}) async {
+  return await showModalBottomSheet<T>(
+      context: context,
+      backgroundColor: const Color(0x00000000),
+      elevation: 0,
+      isDismissible: true,
+      useRootNavigator: rootNavigator,
+      builder: (context) => RoundedBottomSheet(child: child));
+}
+
+PersistentBottomSheetController<T> showRoundedBottomSheet<T>(
+  BuildContext context, {
+  required Widget child,
+}) {
+  return showBottomSheet<T>(
+    context: context,
+    backgroundColor: const Color(0x00000000),
+    elevation: 12.0,
+    builder: (context) => RoundedBottomSheet(child: child),
+  );
+}
diff --git a/filcnaplo_mobile_ui/lib/common/custom_snack_bar.dart b/refilc_mobile_ui/lib/common/custom_snack_bar.dart
old mode 100755
new mode 100644
similarity index 58%
rename from filcnaplo_mobile_ui/lib/common/custom_snack_bar.dart
rename to refilc_mobile_ui/lib/common/custom_snack_bar.dart
index 2f56809..121a6bf
--- a/filcnaplo_mobile_ui/lib/common/custom_snack_bar.dart
+++ b/refilc_mobile_ui/lib/common/custom_snack_bar.dart
@@ -1,34 +1,42 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-// ignore: non_constant_identifier_names
-SnackBar CustomSnackBar({
-  required Widget content,
-  required BuildContext context,
-  Brightness? brightness,
-  Color? backgroundColor,
-  Duration? duration,
-}) {
-  // backgroundColor > Brightness > Theme Background
-  Color _backgroundColor = backgroundColor ?? (AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).highlight);
-  Color textColor = AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).text;
-
-  return SnackBar(
-    duration: duration ?? const Duration(seconds: 4),
-    content: Container(
-      decoration: BoxDecoration(
-        color: _backgroundColor,
-        borderRadius: BorderRadius.circular(6.0),
-        boxShadow: [BoxShadow(color: Colors.black.withOpacity(.15), blurRadius: 4.0)],
-      ),
-      padding: const EdgeInsets.all(12.0),
-      child: DefaultTextStyle(
-        style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: textColor, fontWeight: FontWeight.w500),
-        child: content,
-      ),
-    ),
-    backgroundColor: const Color(0x00000000),
-    elevation: 0,
-    padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
-  );
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+// ignore: non_constant_identifier_names
+SnackBar CustomSnackBar({
+  required Widget content,
+  required BuildContext context,
+  Brightness? brightness,
+  Color? backgroundColor,
+  Duration? duration,
+}) {
+  // backgroundColor > Brightness > Theme Background
+  Color _backgroundColor = backgroundColor ??
+      (AppColors.fromBrightness(brightness ?? Theme.of(context).brightness)
+          .highlight);
+  Color textColor =
+      AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).text;
+
+  return SnackBar(
+    duration: duration ?? const Duration(seconds: 4),
+    content: Container(
+      decoration: BoxDecoration(
+        color: _backgroundColor,
+        borderRadius: BorderRadius.circular(6.0),
+        boxShadow: [
+          BoxShadow(color: Colors.black.withOpacity(.15), blurRadius: 4.0)
+        ],
+      ),
+      padding: const EdgeInsets.all(12.0),
+      child: DefaultTextStyle(
+        style: Theme.of(context)
+            .textTheme
+            .bodyMedium!
+            .copyWith(color: textColor, fontWeight: FontWeight.w500),
+        child: content,
+      ),
+    ),
+    backgroundColor: const Color(0x00000000),
+    elevation: 0,
+    padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
+  );
+}
diff --git a/filcnaplo_mobile_ui/lib/common/detail.dart b/refilc_mobile_ui/lib/common/detail.dart
old mode 100755
new mode 100644
similarity index 55%
rename from filcnaplo_mobile_ui/lib/common/detail.dart
rename to refilc_mobile_ui/lib/common/detail.dart
index cb70b7e..50fdc6f
--- a/filcnaplo_mobile_ui/lib/common/detail.dart
+++ b/refilc_mobile_ui/lib/common/detail.dart
@@ -1,31 +1,39 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class Detail extends StatelessWidget {
-  const Detail({Key? key, required this.title, required this.description, this.maxLines = 3}) : super(key: key);
-
-  final String title;
-  final String description;
-  final int? maxLines;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 18.0),
-      child: SelectableText.rich(
-        TextSpan(
-          text: "$title: ",
-          style: TextStyle(fontWeight: FontWeight.w600, color: AppColors.of(context).text),
-          children: [
-            TextSpan(
-              text: description,
-              style: TextStyle(fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(0.85)),
-            ),
-          ],
-        ),
-        minLines: 1,
-        maxLines: maxLines,
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class Detail extends StatelessWidget {
+  const Detail(
+      {Key? key,
+      required this.title,
+      required this.description,
+      this.maxLines = 3})
+      : super(key: key);
+
+  final String title;
+  final String description;
+  final int? maxLines;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 18.0),
+      child: SelectableText.rich(
+        TextSpan(
+          text: "$title: ",
+          style: TextStyle(
+              fontWeight: FontWeight.w600, color: AppColors.of(context).text),
+          children: [
+            TextSpan(
+              text: description,
+              style: TextStyle(
+                  fontWeight: FontWeight.w500,
+                  color: AppColors.of(context).text.withOpacity(0.85)),
+            ),
+          ],
+        ),
+        minLines: 1,
+        maxLines: maxLines,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/dialog_button.dart b/refilc_mobile_ui/lib/common/dialog_button.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/dialog_button.dart
rename to refilc_mobile_ui/lib/common/dialog_button.dart
index 17bf422..57f0a8c
--- a/filcnaplo_mobile_ui/lib/common/dialog_button.dart
+++ b/refilc_mobile_ui/lib/common/dialog_button.dart
@@ -1,23 +1,23 @@
-import 'package:flutter/material.dart';
-
-class DialogButton extends StatelessWidget {
-  const DialogButton({Key? key, required this.label, this.onTap}) : super(key: key);
-
-  final String label;
-  final Function()? onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    return RawMaterialButton(
-      onPressed: onTap,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-      child: Text(
-        label.toUpperCase(),
-        style: TextStyle(
-          fontWeight: FontWeight.w600,
-          color: Theme.of(context).colorScheme.secondary,
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class DialogButton extends StatelessWidget {
+  const DialogButton({Key? key, required this.label, this.onTap}) : super(key: key);
+
+  final String label;
+  final Function()? onTap;
+
+  @override
+  Widget build(BuildContext context) {
+    return RawMaterialButton(
+      onPressed: onTap,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+      child: Text(
+        label.toUpperCase(),
+        style: TextStyle(
+          fontWeight: FontWeight.w600,
+          color: Theme.of(context).colorScheme.secondary,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/dot.dart b/refilc_mobile_ui/lib/common/dot.dart
old mode 100755
new mode 100644
similarity index 95%
rename from filcnaplo_mobile_ui/lib/common/dot.dart
rename to refilc_mobile_ui/lib/common/dot.dart
index 2d827a2..17daa3e
--- a/filcnaplo_mobile_ui/lib/common/dot.dart
+++ b/refilc_mobile_ui/lib/common/dot.dart
@@ -1,20 +1,20 @@
-import 'package:flutter/material.dart';
-
-class Dot extends StatelessWidget {
-  final Color color;
-  final double size;
-
-  const Dot({Key? key, this.color = Colors.grey, this.size = 16.0}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      decoration: BoxDecoration(
-        color: color,
-        shape: BoxShape.circle,
-      ),
-      width: size,
-      height: size,
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class Dot extends StatelessWidget {
+  final Color color;
+  final double size;
+
+  const Dot({Key? key, this.color = Colors.grey, this.size = 16.0}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      decoration: BoxDecoration(
+        color: color,
+        shape: BoxShape.circle,
+      ),
+      width: size,
+      height: size,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/empty.dart b/refilc_mobile_ui/lib/common/empty.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/common/empty.dart
rename to refilc_mobile_ui/lib/common/empty.dart
index ea0a06c..3f88798
--- a/filcnaplo_mobile_ui/lib/common/empty.dart
+++ b/refilc_mobile_ui/lib/common/empty.dart
@@ -1,54 +1,54 @@
-import 'dart:math';
-
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-List<String> faces = [
-  "(·.·)",
-  "(≥o≤)",
-  "(·_·)",
-  "(˚Δ˚)b",
-  "(^-^*)",
-  "(='X'=)",
-  "(>_<)",
-  "(;-;)",
-  "\\(^Д^)/",
-  "\\(o_o)/",
-];
-
-class Empty extends StatelessWidget {
-  const Empty({Key? key, this.subtitle}) : super(key: key);
-
-  final String? subtitle;
-
-  @override
-  Widget build(BuildContext context) {
-    int index = Random(DateTime.now().minute).nextInt(faces.length);
-
-    return Center(
-      child: Padding(
-        padding: const EdgeInsets.all(12.0),
-        child: Text.rich(
-          TextSpan(
-            text: faces[index],
-            style: TextStyle(
-                fontSize: 32.0,
-                fontWeight: FontWeight.w500,
-                color: AppColors.of(context).text.withOpacity(.75)),
-            children: subtitle != null
-                ? [
-                    TextSpan(
-                        text: "\n" + subtitle!,
-                        style: TextStyle(
-                            fontSize: 18.0,
-                            height: 2.0,
-                            color: AppColors.of(context).text.withOpacity(.5)))
-                  ]
-                : [],
-          ),
-          textAlign: TextAlign.center,
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+List<String> faces = [
+  "(·.·)",
+  "(≥o≤)",
+  "(·_·)",
+  "(˚Δ˚)b",
+  "(^-^*)",
+  "(='X'=)",
+  "(>_<)",
+  "(;-;)",
+  "\\(^Д^)/",
+  "\\(o_o)/",
+];
+
+class Empty extends StatelessWidget {
+  const Empty({Key? key, this.subtitle}) : super(key: key);
+
+  final String? subtitle;
+
+  @override
+  Widget build(BuildContext context) {
+    int index = Random(DateTime.now().minute).nextInt(faces.length);
+
+    return Center(
+      child: Padding(
+        padding: const EdgeInsets.all(12.0),
+        child: Text.rich(
+          TextSpan(
+            text: faces[index],
+            style: TextStyle(
+                fontSize: 32.0,
+                fontWeight: FontWeight.w500,
+                color: AppColors.of(context).text.withOpacity(.75)),
+            children: subtitle != null
+                ? [
+                    TextSpan(
+                        text: "\n" + subtitle!,
+                        style: TextStyle(
+                            fontSize: 18.0,
+                            height: 2.0,
+                            color: AppColors.of(context).text.withOpacity(.5)))
+                  ]
+                : [],
+          ),
+          textAlign: TextAlign.center,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/filter_bar.dart b/refilc_mobile_ui/lib/common/filter_bar.dart
old mode 100755
new mode 100644
similarity index 74%
rename from filcnaplo_mobile_ui/lib/common/filter_bar.dart
rename to refilc_mobile_ui/lib/common/filter_bar.dart
index c95e1a7..edededc
--- a/filcnaplo_mobile_ui/lib/common/filter_bar.dart
+++ b/refilc_mobile_ui/lib/common/filter_bar.dart
@@ -1,117 +1,126 @@
-import 'dart:math';
-
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class FilterBar extends StatefulWidget implements PreferredSizeWidget {
-  const FilterBar({
-    Key? key,
-    required this.items,
-    required this.controller,
-    this.onTap,
-    this.padding = const EdgeInsets.symmetric(horizontal: 24.0),
-    this.disableFading = false,
-    this.scrollable = true,
-    this.censored = false,
-  })  : assert(items.length == controller.length),
-        super(key: key);
-
-  final List<Widget> items;
-  final TabController controller;
-  final EdgeInsetsGeometry padding;
-  final Function(int)? onTap;
-  final bool disableFading;
-  final bool scrollable;
-  final bool censored;
-
-  @override
-  final Size preferredSize = const Size.fromHeight(42.0);
-
-  @override
-  State<FilterBar> createState() => _FilterBarState();
-}
-
-class _FilterBarState extends State<FilterBar> {
-  List<double> censoredItemsWidth = [];
-  @override
-  void initState() {
-    super.initState();
-
-    censoredItemsWidth = List.generate(widget.items.length, (index) => 25 + Random().nextDouble() * 50).toList();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final tabbar = TabBar(
-      controller: widget.controller,
-      isScrollable: widget.scrollable,
-      physics: const BouncingScrollPhysics(),
-      // Label
-      labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(
-            fontWeight: FontWeight.w600,
-            fontSize: 15.0,
-          ),
-      labelPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
-      labelColor: Theme.of(context).colorScheme.secondary,
-      unselectedLabelColor: AppColors.of(context).text.withOpacity(0.65),
-      // Indicator
-      indicatorSize: TabBarIndicatorSize.tab,
-      indicatorPadding: const EdgeInsets.symmetric(vertical: 8.0),
-      indicator: BoxDecoration(
-        color: Theme.of(context).colorScheme.secondary.withOpacity(0.25),
-        borderRadius: BorderRadius.circular(45.0),
-      ),
-      overlayColor: MaterialStateProperty.all(const Color(0x00000000)),
-      // Tabs
-      padding: EdgeInsets.zero,
-      tabs: widget.censored
-          ? censoredItemsWidth
-              .map(
-                (e) => Container(
-                  width: e,
-                  height: 15,
-                  decoration: BoxDecoration(
-                    color: AppColors.of(context).text.withOpacity(.45),
-                    borderRadius: BorderRadius.circular(8.0),
-                  ),
-                ),
-              )
-              .toList()
-          : widget.items,
-      onTap: widget.onTap,
-    );
-
-    return Container(
-      width: MediaQuery.of(context).size.width,
-      height: 48.0,
-      padding: widget.padding,
-      child: widget.disableFading
-          ? tabbar
-          : AnimatedBuilder(
-              animation: widget.controller.animation!,
-              builder: (ctx, child) {
-                // avoid fading over selected tab
-                return ShaderMask(
-                    shaderCallback: (Rect bounds) {
-                      final Color bg = Theme.of(context).scaffoldBackgroundColor;
-                      final double index = widget.controller.animation!.value;
-                      return LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [
-                        index < 0.2 ? Colors.transparent : bg,
-                        Colors.transparent,
-                        Colors.transparent,
-                        index > widget.controller.length - 1.2 ? Colors.transparent : bg
-                      ], stops: const [
-                        0,
-                        0.1,
-                        0.9,
-                        1
-                      ]).createShader(bounds);
-                    },
-                    blendMode: BlendMode.dstOut,
-                    child: child);
-              },
-              child: tabbar,
-            ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class FilterBar extends StatefulWidget implements PreferredSizeWidget {
+  const FilterBar({
+    Key? key,
+    required this.items,
+    required this.controller,
+    this.onTap,
+    this.padding = const EdgeInsets.symmetric(horizontal: 24.0),
+    this.disableFading = false,
+    this.scrollable = true,
+    this.censored = false,
+  })  : assert(items.length == controller.length),
+        super(key: key);
+
+  final List<Widget> items;
+  final TabController controller;
+  final EdgeInsetsGeometry padding;
+  final Function(int)? onTap;
+  final bool disableFading;
+  final bool scrollable;
+  final bool censored;
+
+  @override
+  final Size preferredSize = const Size.fromHeight(42.0);
+
+  @override
+  State<FilterBar> createState() => _FilterBarState();
+}
+
+class _FilterBarState extends State<FilterBar> {
+  List<double> censoredItemsWidth = [];
+  @override
+  void initState() {
+    super.initState();
+
+    censoredItemsWidth = List.generate(
+            widget.items.length, (index) => 25 + Random().nextDouble() * 50)
+        .toList();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final tabbar = TabBar(
+      controller: widget.controller,
+      isScrollable: widget.scrollable,
+      physics: const BouncingScrollPhysics(),
+      // Label
+      labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(
+            fontWeight: FontWeight.w600,
+            fontSize: 15.0,
+          ),
+      labelPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+      labelColor: Theme.of(context).colorScheme.secondary,
+      unselectedLabelColor: AppColors.of(context).text.withOpacity(0.65),
+      // Indicator
+      indicatorSize: TabBarIndicatorSize.tab,
+      indicatorPadding: const EdgeInsets.symmetric(vertical: 8.0),
+      indicator: BoxDecoration(
+        color: Theme.of(context).colorScheme.secondary.withOpacity(0.25),
+        borderRadius: BorderRadius.circular(45.0),
+      ),
+      overlayColor: MaterialStateProperty.all(const Color(0x00000000)),
+      // Tabs
+      padding: EdgeInsets.zero,
+      tabs: widget.censored
+          ? censoredItemsWidth
+              .map(
+                (e) => Container(
+                  width: e,
+                  height: 15,
+                  decoration: BoxDecoration(
+                    color: AppColors.of(context).text.withOpacity(.45),
+                    borderRadius: BorderRadius.circular(8.0),
+                  ),
+                ),
+              )
+              .toList()
+          : widget.items,
+      onTap: widget.onTap,
+    );
+
+    return Container(
+      width: MediaQuery.of(context).size.width,
+      height: 48.0,
+      padding: widget.padding,
+      child: widget.disableFading
+          ? tabbar
+          : AnimatedBuilder(
+              animation: widget.controller.animation!,
+              builder: (ctx, child) {
+                // avoid fading over selected tab
+                return ShaderMask(
+                    shaderCallback: (Rect bounds) {
+                      final Color bg =
+                          Theme.of(context).scaffoldBackgroundColor;
+                      final double index = widget.controller.animation!.value;
+                      return LinearGradient(
+                          begin: Alignment.topLeft,
+                          end: Alignment.bottomRight,
+                          colors: [
+                            index < 0.2 ? Colors.transparent : bg,
+                            Colors.transparent,
+                            Colors.transparent,
+                            index > widget.controller.length - 1.2
+                                ? Colors.transparent
+                                : bg
+                          ],
+                          stops: const [
+                            0,
+                            0.1,
+                            0.9,
+                            1
+                          ]).createShader(bounds);
+                    },
+                    blendMode: BlendMode.dstOut,
+                    child: child);
+              },
+              child: tabbar,
+            ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/hero_dialog_route.dart b/refilc_mobile_ui/lib/common/hero_dialog_route.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/hero_dialog_route.dart
rename to refilc_mobile_ui/lib/common/hero_dialog_route.dart
index 745e77e..99789ec
--- a/filcnaplo_mobile_ui/lib/common/hero_dialog_route.dart
+++ b/refilc_mobile_ui/lib/common/hero_dialog_route.dart
@@ -1,35 +1,35 @@
-import 'package:flutter/material.dart';
-
-class HeroDialogRoute<T> extends PageRoute<T> {
-  HeroDialogRoute({required this.builder}) : super();
-
-  final WidgetBuilder builder;
-
-  @override
-  bool get opaque => false;
-
-  @override
-  bool get barrierDismissible => true;
-
-  @override
-  String? get barrierLabel => "livecard";
-
-  @override
-  Duration get transitionDuration => const Duration(milliseconds: 250);
-
-  @override
-  bool get maintainState => true;
-
-  @override
-  Color get barrierColor => Colors.black38;
-
-  @override
-  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
-    return FadeTransition(opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut), child: child);
-  }
-
-  @override
-  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
-    return builder(context);
-  }
-}
+import 'package:flutter/material.dart';
+
+class HeroDialogRoute<T> extends PageRoute<T> {
+  HeroDialogRoute({required this.builder}) : super();
+
+  final WidgetBuilder builder;
+
+  @override
+  bool get opaque => false;
+
+  @override
+  bool get barrierDismissible => true;
+
+  @override
+  String? get barrierLabel => "livecard";
+
+  @override
+  Duration get transitionDuration => const Duration(milliseconds: 250);
+
+  @override
+  bool get maintainState => true;
+
+  @override
+  Color get barrierColor => Colors.black38;
+
+  @override
+  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
+    return FadeTransition(opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut), child: child);
+  }
+
+  @override
+  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
+    return builder(context);
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/hero_scrollview.dart b/refilc_mobile_ui/lib/common/hero_scrollview.dart
old mode 100755
new mode 100644
similarity index 94%
rename from filcnaplo_mobile_ui/lib/common/hero_scrollview.dart
rename to refilc_mobile_ui/lib/common/hero_scrollview.dart
index 91872a2..8a92dad
--- a/filcnaplo_mobile_ui/lib/common/hero_scrollview.dart
+++ b/refilc_mobile_ui/lib/common/hero_scrollview.dart
@@ -1,137 +1,137 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-class HeroScrollView extends StatefulWidget {
-  const HeroScrollView(
-      {Key? key,
-      required this.child,
-      required this.title,
-      required this.icon,
-      this.italic = false,
-      this.navBarItems = const [],
-      this.onClose,
-      this.iconSize = 64.0,
-      this.scrollController})
-      : super(key: key);
-
-  final Widget child;
-  final String title;
-  final IconData? icon;
-  final List<Widget> navBarItems;
-  final VoidCallback? onClose;
-  final double iconSize;
-  final ScrollController? scrollController;
-  final bool italic;
-
-  @override
-  _HeroScrollViewState createState() => _HeroScrollViewState();
-}
-
-class _HeroScrollViewState extends State<HeroScrollView> {
-  late ScrollController _scrollController;
-
-  bool showBarTitle = false;
-
-  @override
-  void initState() {
-    super.initState();
-    _scrollController = widget.scrollController ?? ScrollController();
-
-    _scrollController.addListener(() {
-      if (_scrollController.offset > 42.0) {
-        if (showBarTitle == false) setState(() => showBarTitle = true);
-      } else {
-        if (showBarTitle == true) setState(() => showBarTitle = false);
-      }
-    });
-  }
-
-  @override
-  void dispose() {
-    super.dispose();
-    _scrollController.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return NestedScrollView(
-      controller: _scrollController,
-      physics:
-          const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
-      headerSliverBuilder: (context, _) => [
-        SliverAppBar(
-          pinned: true,
-          floating: false,
-          snap: false,
-          centerTitle: false,
-          titleSpacing: 0,
-          surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-          title: AnimatedOpacity(
-              opacity: showBarTitle ? 1.0 : 0.0,
-              child: Row(
-                children: [
-                  Icon(widget.icon,
-                      color: AppColors.of(context).text.withOpacity(.8)),
-                  const SizedBox(width: 8.0),
-                  Expanded(
-                    child: Text(
-                      widget.title.capital(),
-                      overflow: TextOverflow.ellipsis,
-                      maxLines: 2,
-                      style: TextStyle(
-                          color: AppColors.of(context).text,
-                          fontWeight: FontWeight.w500,
-                          fontStyle: widget.italic ? FontStyle.italic : null),
-                    ),
-                  ),
-                ],
-              ),
-              duration: const Duration(milliseconds: 200)),
-          leading: BackButton(
-              color: AppColors.of(context).text,
-              onPressed: () {
-                if (widget.onClose != null) {
-                  widget.onClose!();
-                } else {
-                  Navigator.of(context).pop();
-                }
-              }),
-          actions: widget.navBarItems,
-          expandedHeight: 145.69,
-          stretch: true,
-          flexibleSpace: FlexibleSpaceBar(
-            background: Stack(
-              children: [
-                Center(
-                  child: Icon(
-                    widget.icon,
-                    size: widget.iconSize,
-                    color: AppColors.of(context).text.withOpacity(.15),
-                  ),
-                ),
-                Container(
-                  alignment: Alignment.center,
-                  margin: const EdgeInsets.only(top: 82),
-                  padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                  child: Text(
-                    widget.title.capital(),
-                    maxLines: 2,
-                    overflow: TextOverflow.ellipsis,
-                    textAlign: TextAlign.center,
-                    style: TextStyle(
-                        fontSize: 36.0,
-                        color: AppColors.of(context).text.withOpacity(.9),
-                        fontStyle: widget.italic ? FontStyle.italic : null,
-                        fontWeight: FontWeight.bold),
-                  ),
-                ),
-              ],
-            ),
-          ),
-        ),
-      ],
-      body: widget.child,
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+
+class HeroScrollView extends StatefulWidget {
+  const HeroScrollView(
+      {Key? key,
+      required this.child,
+      required this.title,
+      required this.icon,
+      this.italic = false,
+      this.navBarItems = const [],
+      this.onClose,
+      this.iconSize = 64.0,
+      this.scrollController})
+      : super(key: key);
+
+  final Widget child;
+  final String title;
+  final IconData? icon;
+  final List<Widget> navBarItems;
+  final VoidCallback? onClose;
+  final double iconSize;
+  final ScrollController? scrollController;
+  final bool italic;
+
+  @override
+  _HeroScrollViewState createState() => _HeroScrollViewState();
+}
+
+class _HeroScrollViewState extends State<HeroScrollView> {
+  late ScrollController _scrollController;
+
+  bool showBarTitle = false;
+
+  @override
+  void initState() {
+    super.initState();
+    _scrollController = widget.scrollController ?? ScrollController();
+
+    _scrollController.addListener(() {
+      if (_scrollController.offset > 42.0) {
+        if (showBarTitle == false) setState(() => showBarTitle = true);
+      } else {
+        if (showBarTitle == true) setState(() => showBarTitle = false);
+      }
+    });
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    _scrollController.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return NestedScrollView(
+      controller: _scrollController,
+      physics:
+          const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
+      headerSliverBuilder: (context, _) => [
+        SliverAppBar(
+          pinned: true,
+          floating: false,
+          snap: false,
+          centerTitle: false,
+          titleSpacing: 0,
+          surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+          title: AnimatedOpacity(
+              opacity: showBarTitle ? 1.0 : 0.0,
+              child: Row(
+                children: [
+                  Icon(widget.icon,
+                      color: AppColors.of(context).text.withOpacity(.8)),
+                  const SizedBox(width: 8.0),
+                  Expanded(
+                    child: Text(
+                      widget.title.capital(),
+                      overflow: TextOverflow.ellipsis,
+                      maxLines: 2,
+                      style: TextStyle(
+                          color: AppColors.of(context).text,
+                          fontWeight: FontWeight.w500,
+                          fontStyle: widget.italic ? FontStyle.italic : null),
+                    ),
+                  ),
+                ],
+              ),
+              duration: const Duration(milliseconds: 200)),
+          leading: BackButton(
+              color: AppColors.of(context).text,
+              onPressed: () {
+                if (widget.onClose != null) {
+                  widget.onClose!();
+                } else {
+                  Navigator.of(context).pop();
+                }
+              }),
+          actions: widget.navBarItems,
+          expandedHeight: 145.69,
+          stretch: true,
+          flexibleSpace: FlexibleSpaceBar(
+            background: Stack(
+              children: [
+                Center(
+                  child: Icon(
+                    widget.icon,
+                    size: widget.iconSize,
+                    color: AppColors.of(context).text.withOpacity(.15),
+                  ),
+                ),
+                Container(
+                  alignment: Alignment.center,
+                  margin: const EdgeInsets.only(top: 82),
+                  padding: const EdgeInsets.symmetric(horizontal: 12.0),
+                  child: Text(
+                    widget.title.capital(),
+                    maxLines: 2,
+                    overflow: TextOverflow.ellipsis,
+                    textAlign: TextAlign.center,
+                    style: TextStyle(
+                        fontSize: 36.0,
+                        color: AppColors.of(context).text.withOpacity(.9),
+                        fontStyle: widget.italic ? FontStyle.italic : null,
+                        fontWeight: FontWeight.bold),
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ),
+      ],
+      body: widget.child,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/material_action_button.dart b/refilc_mobile_ui/lib/common/material_action_button.dart
old mode 100755
new mode 100644
similarity index 78%
rename from filcnaplo_mobile_ui/lib/common/material_action_button.dart
rename to refilc_mobile_ui/lib/common/material_action_button.dart
index eaf1f96..067abe1
--- a/filcnaplo_mobile_ui/lib/common/material_action_button.dart
+++ b/refilc_mobile_ui/lib/common/material_action_button.dart
@@ -1,35 +1,37 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:flutter/material.dart';
-
-class MaterialActionButton extends StatelessWidget {
-  const MaterialActionButton({
-    Key? key,
-    required this.child,
-    this.onPressed,
-    this.backgroundColor,
-  }) : super(key: key);
-
-  final Widget child;
-  final Function()? onPressed;
-  final Color? backgroundColor;
-
-  @override
-  Widget build(BuildContext context) {
-    return RawMaterialButton(
-      padding: const EdgeInsets.symmetric(horizontal: 16.0),
-      shape: const StadiumBorder(),
-      child: DefaultTextStyle(
-        child: child,
-        style: Theme.of(context).textTheme.bodyMedium!.copyWith(
-              fontWeight: FontWeight.w600,
-              color: backgroundColor != null ? ColorUtils.foregroundColor(backgroundColor!) : null,
-            ),
-      ),
-      fillColor: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
-      elevation: 0,
-      highlightElevation: 0,
-      onPressed: onPressed,
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:flutter/material.dart';
+
+class MaterialActionButton extends StatelessWidget {
+  const MaterialActionButton({
+    Key? key,
+    required this.child,
+    this.onPressed,
+    this.backgroundColor,
+  }) : super(key: key);
+
+  final Widget child;
+  final Function()? onPressed;
+  final Color? backgroundColor;
+
+  @override
+  Widget build(BuildContext context) {
+    return RawMaterialButton(
+      padding: const EdgeInsets.symmetric(horizontal: 16.0),
+      shape: const StadiumBorder(),
+      child: DefaultTextStyle(
+        child: child,
+        style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+              fontWeight: FontWeight.w600,
+              color: backgroundColor != null
+                  ? ColorUtils.foregroundColor(backgroundColor!)
+                  : null,
+            ),
+      ),
+      fillColor: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
+      elevation: 0,
+      highlightElevation: 0,
+      onPressed: onPressed,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/new_content_indicator.dart b/refilc_mobile_ui/lib/common/new_content_indicator.dart
old mode 100755
new mode 100644
similarity index 82%
rename from filcnaplo_mobile_ui/lib/common/new_content_indicator.dart
rename to refilc_mobile_ui/lib/common/new_content_indicator.dart
index 3287848..cea0250
--- a/filcnaplo_mobile_ui/lib/common/new_content_indicator.dart
+++ b/refilc_mobile_ui/lib/common/new_content_indicator.dart
@@ -1,34 +1,36 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class NewContentIndicator extends StatelessWidget {
-  const NewContentIndicator({Key? key, this.size = 64.0}) : super(key: key);
-
-  final double size;
-
-  @override
-  Widget build(BuildContext context) {
-    return AnimatedContainer(
-      duration: const Duration(milliseconds: 200),
-      alignment: Alignment.topRight,
-      width: size,
-      height: size,
-      child: AnimatedContainer(
-        duration: const Duration(milliseconds: 200),
-        height: size / 3.0,
-        width: size / 3.0,
-        decoration: BoxDecoration(
-          shape: BoxShape.circle,
-          border: Border.all(color: Theme.of(context).scaffoldBackgroundColor, width: size / 20.0),
-        ),
-        child: AnimatedContainer(
-          duration: const Duration(milliseconds: 200),
-          decoration: BoxDecoration(
-            color: AppColors.of(context).red,
-            shape: BoxShape.circle,
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class NewContentIndicator extends StatelessWidget {
+  const NewContentIndicator({Key? key, this.size = 64.0}) : super(key: key);
+
+  final double size;
+
+  @override
+  Widget build(BuildContext context) {
+    return AnimatedContainer(
+      duration: const Duration(milliseconds: 200),
+      alignment: Alignment.topRight,
+      width: size,
+      height: size,
+      child: AnimatedContainer(
+        duration: const Duration(milliseconds: 200),
+        height: size / 3.0,
+        width: size / 3.0,
+        decoration: BoxDecoration(
+          shape: BoxShape.circle,
+          border: Border.all(
+              color: Theme.of(context).scaffoldBackgroundColor,
+              width: size / 20.0),
+        ),
+        child: AnimatedContainer(
+          duration: const Duration(milliseconds: 200),
+          decoration: BoxDecoration(
+            color: AppColors.of(context).red,
+            shape: BoxShape.circle,
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/panel/panel.dart b/refilc_mobile_ui/lib/common/panel/panel.dart
old mode 100755
new mode 100644
similarity index 84%
rename from filcnaplo_mobile_ui/lib/common/panel/panel.dart
rename to refilc_mobile_ui/lib/common/panel/panel.dart
index cc82c53..201ec67
--- a/filcnaplo_mobile_ui/lib/common/panel/panel.dart
+++ b/refilc_mobile_ui/lib/common/panel/panel.dart
@@ -1,135 +1,142 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class Panel extends StatelessWidget {
-  const Panel({Key? key, this.child, this.title, this.padding, this.hasShadow = true}) : super(key: key);
-
-  final Widget? child;
-  final Widget? title;
-  final EdgeInsetsGeometry? padding;
-  final bool hasShadow;
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        // Panel Title
-        if (title != null) PanelTitle(title: title!),
-
-        // Panel Body
-        if (child != null)
-          Container(
-            width: double.infinity,
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(16.0),
-              color: Theme.of(context).colorScheme.background,
-              boxShadow: [
-                if (hasShadow)
-                  BoxShadow(
-                    offset: const Offset(0, 21),
-                    blurRadius: 23.0,
-                    color: Theme.of(context).shadowColor,
-                  )
-              ],
-            ),
-            padding: padding ?? const EdgeInsets.all(8.0),
-            child: child,
-          ),
-      ],
-    );
-  }
-}
-
-class PanelTitle extends StatelessWidget {
-  const PanelTitle({Key? key, required this.title}) : super(key: key);
-
-  final Widget title;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(left: 14.0, bottom: 8.0),
-      child: DefaultTextStyle(
-        style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w600, color: AppColors.of(context).text.withOpacity(0.65)),
-        child: title,
-      ),
-    );
-  }
-}
-
-class PanelHeader extends StatelessWidget {
-  const PanelHeader({Key? key, required this.padding}) : super(key: key);
-
-  final EdgeInsetsGeometry padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      width: double.infinity,
-      padding: padding,
-      decoration: BoxDecoration(
-        borderRadius: const BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0)),
-        color: Theme.of(context).colorScheme.background,
-        boxShadow: [
-          BoxShadow(
-            offset: const Offset(0, 21),
-            blurRadius: 23.0,
-            color: Theme.of(context).shadowColor,
-          )
-        ],
-      ),
-    );
-  }
-}
-
-class PanelBody extends StatelessWidget {
-  const PanelBody({Key? key, this.child, this.padding}) : super(key: key);
-
-  final Widget? child;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      width: double.infinity,
-      decoration: BoxDecoration(
-        color: Theme.of(context).colorScheme.background,
-        boxShadow: [
-          BoxShadow(
-            offset: const Offset(0, 21),
-            blurRadius: 23.0,
-            color: Theme.of(context).shadowColor,
-          )
-        ],
-      ),
-      padding: padding,
-      child: child,
-    );
-  }
-}
-
-class PanelFooter extends StatelessWidget {
-  const PanelFooter({Key? key, required this.padding}) : super(key: key);
-
-  final EdgeInsetsGeometry padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      width: double.infinity,
-      padding: padding,
-      decoration: BoxDecoration(
-        borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(16.0), bottomRight: Radius.circular(16.0)),
-        color: Theme.of(context).colorScheme.background,
-        boxShadow: [
-          BoxShadow(
-            offset: const Offset(0, 21),
-            blurRadius: 23.0,
-            color: Theme.of(context).shadowColor,
-          )
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class Panel extends StatelessWidget {
+  const Panel(
+      {Key? key, this.child, this.title, this.padding, this.hasShadow = true})
+      : super(key: key);
+
+  final Widget? child;
+  final Widget? title;
+  final EdgeInsetsGeometry? padding;
+  final bool hasShadow;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        // Panel Title
+        if (title != null) PanelTitle(title: title!),
+
+        // Panel Body
+        if (child != null)
+          Container(
+            width: double.infinity,
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.circular(16.0),
+              color: Theme.of(context).colorScheme.background,
+              boxShadow: [
+                if (hasShadow)
+                  BoxShadow(
+                    offset: const Offset(0, 21),
+                    blurRadius: 23.0,
+                    color: Theme.of(context).shadowColor,
+                  )
+              ],
+            ),
+            padding: padding ?? const EdgeInsets.all(8.0),
+            child: child,
+          ),
+      ],
+    );
+  }
+}
+
+class PanelTitle extends StatelessWidget {
+  const PanelTitle({Key? key, required this.title}) : super(key: key);
+
+  final Widget title;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(left: 14.0, bottom: 8.0),
+      child: DefaultTextStyle(
+        style: Theme.of(context).textTheme.titleMedium!.copyWith(
+            fontWeight: FontWeight.w600,
+            color: AppColors.of(context).text.withOpacity(0.65)),
+        child: title,
+      ),
+    );
+  }
+}
+
+class PanelHeader extends StatelessWidget {
+  const PanelHeader({Key? key, required this.padding}) : super(key: key);
+
+  final EdgeInsetsGeometry padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      padding: padding,
+      decoration: BoxDecoration(
+        borderRadius: const BorderRadius.only(
+            topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0)),
+        color: Theme.of(context).colorScheme.background,
+        boxShadow: [
+          BoxShadow(
+            offset: const Offset(0, 21),
+            blurRadius: 23.0,
+            color: Theme.of(context).shadowColor,
+          )
+        ],
+      ),
+    );
+  }
+}
+
+class PanelBody extends StatelessWidget {
+  const PanelBody({Key? key, this.child, this.padding}) : super(key: key);
+
+  final Widget? child;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      decoration: BoxDecoration(
+        color: Theme.of(context).colorScheme.background,
+        boxShadow: [
+          BoxShadow(
+            offset: const Offset(0, 21),
+            blurRadius: 23.0,
+            color: Theme.of(context).shadowColor,
+          )
+        ],
+      ),
+      padding: padding,
+      child: child,
+    );
+  }
+}
+
+class PanelFooter extends StatelessWidget {
+  const PanelFooter({Key? key, required this.padding}) : super(key: key);
+
+  final EdgeInsetsGeometry padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      padding: padding,
+      decoration: BoxDecoration(
+        borderRadius: const BorderRadius.only(
+            bottomLeft: Radius.circular(16.0),
+            bottomRight: Radius.circular(16.0)),
+        color: Theme.of(context).colorScheme.background,
+        boxShadow: [
+          BoxShadow(
+            offset: const Offset(0, 21),
+            blurRadius: 23.0,
+            color: Theme.of(context).shadowColor,
+          )
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/panel/panel_action_button.dart b/refilc_mobile_ui/lib/common/panel/panel_action_button.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/panel/panel_action_button.dart
rename to refilc_mobile_ui/lib/common/panel/panel_action_button.dart
index 3bf62cf..131e235
--- a/filcnaplo_mobile_ui/lib/common/panel/panel_action_button.dart
+++ b/refilc_mobile_ui/lib/common/panel/panel_action_button.dart
@@ -1,44 +1,44 @@
-import 'package:flutter/material.dart';
-
-class PanelActionButton extends StatelessWidget {
-  const PanelActionButton({
-    Key? key,
-    this.onPressed,
-    this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
-    this.leading,
-    this.title,
-    this.trailing,
-  }) : super(key: key);
-
-  final void Function()? onPressed;
-  final EdgeInsetsGeometry padding;
-  final Widget? leading;
-  final Widget? title;
-  final Widget? trailing;
-
-  @override
-  Widget build(BuildContext context) {
-    return RawMaterialButton(
-      onPressed: onPressed,
-      padding: padding,
-      shape: RoundedRectangleBorder(
-        borderRadius: BorderRadius.circular(8.0),
-        side: BorderSide(color: Theme.of(context).colorScheme.secondary.withOpacity(.6), width: 2),
-      ),
-      child: ListTile(
-        leading: leading != null
-            ? Theme(
-                data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Theme.of(context).colorScheme.secondary)),
-                child: leading!,
-              )
-            : null,
-        trailing: trailing,
-        title: title != null
-            ? DefaultTextStyle(style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, fontSize: 15.0), child: title!)
-            : null,
-        contentPadding: EdgeInsets.zero,
-        visualDensity: VisualDensity.compact,
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class PanelActionButton extends StatelessWidget {
+  const PanelActionButton({
+    Key? key,
+    this.onPressed,
+    this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
+    this.leading,
+    this.title,
+    this.trailing,
+  }) : super(key: key);
+
+  final void Function()? onPressed;
+  final EdgeInsetsGeometry padding;
+  final Widget? leading;
+  final Widget? title;
+  final Widget? trailing;
+
+  @override
+  Widget build(BuildContext context) {
+    return RawMaterialButton(
+      onPressed: onPressed,
+      padding: padding,
+      shape: RoundedRectangleBorder(
+        borderRadius: BorderRadius.circular(8.0),
+        side: BorderSide(color: Theme.of(context).colorScheme.secondary.withOpacity(.6), width: 2),
+      ),
+      child: ListTile(
+        leading: leading != null
+            ? Theme(
+                data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Theme.of(context).colorScheme.secondary)),
+                child: leading!,
+              )
+            : null,
+        trailing: trailing,
+        title: title != null
+            ? DefaultTextStyle(style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, fontSize: 15.0), child: title!)
+            : null,
+        contentPadding: EdgeInsets.zero,
+        visualDensity: VisualDensity.compact,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/panel/panel_button.dart b/refilc_mobile_ui/lib/common/panel/panel_button.dart
old mode 100755
new mode 100644
similarity index 75%
rename from filcnaplo_mobile_ui/lib/common/panel/panel_button.dart
rename to refilc_mobile_ui/lib/common/panel/panel_button.dart
index d1f3b64..f4190eb
--- a/filcnaplo_mobile_ui/lib/common/panel/panel_button.dart
+++ b/refilc_mobile_ui/lib/common/panel/panel_button.dart
@@ -1,74 +1,84 @@
-import 'dart:ui';
-
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class PanelButton extends StatelessWidget {
-  const PanelButton({
-    Key? key,
-    this.onPressed,
-    this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
-    this.leading,
-    this.title,
-    this.trailing,
-    this.background = false,
-    this.trailingDivider = false,
-  }) : super(key: key);
-
-  final void Function()? onPressed;
-  final EdgeInsetsGeometry padding;
-  final Widget? leading;
-  final Widget? title;
-  final Widget? trailing;
-  final bool background;
-  final bool trailingDivider;
-
-  @override
-  Widget build(BuildContext context) {
-    final button = RawMaterialButton(
-      onPressed: onPressed,
-      padding: padding,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
-      fillColor: background ? Colors.white.withOpacity(Theme.of(context).brightness == Brightness.light ? .35 : .2) : null,
-      child: ListTile(
-        leading: leading != null
-            ? Theme(
-                data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Theme.of(context).colorScheme.secondary)),
-                child: leading!,
-              )
-            : null,
-        trailing: trailingDivider
-            ? Row(
-                mainAxisSize: MainAxisSize.min,
-                children: [
-                  Container(
-                    margin: const EdgeInsets.only(right: 6.0),
-                    width: 2.0,
-                    height: 32.0,
-                    decoration: BoxDecoration(
-                      color: AppColors.of(context).text.withOpacity(.15),
-                      borderRadius: BorderRadius.circular(45.0),
-                    ),
-                  ),
-                  if (trailing != null) trailing!,
-                ],
-              )
-            : trailing,
-        title: title != null
-            ? DefaultTextStyle(style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w600, fontSize: 16.0), child: title!)
-            : null,
-        contentPadding: EdgeInsets.zero,
-        visualDensity: VisualDensity.compact,
-      ),
-    );
-
-    if (!background) return button;
-
-    return BackdropFilter(
-        filter: ImageFilter.blur(
-          sigmaX: 12.0,
-          sigmaY: 12.0,
-        ),
-        child: button);
-  }
-}
+import 'dart:ui';
+
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class PanelButton extends StatelessWidget {
+  const PanelButton({
+    Key? key,
+    this.onPressed,
+    this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
+    this.leading,
+    this.title,
+    this.trailing,
+    this.background = false,
+    this.trailingDivider = false,
+  }) : super(key: key);
+
+  final void Function()? onPressed;
+  final EdgeInsetsGeometry padding;
+  final Widget? leading;
+  final Widget? title;
+  final Widget? trailing;
+  final bool background;
+  final bool trailingDivider;
+
+  @override
+  Widget build(BuildContext context) {
+    final button = RawMaterialButton(
+      onPressed: onPressed,
+      padding: padding,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
+      fillColor: background
+          ? Colors.white.withOpacity(
+              Theme.of(context).brightness == Brightness.light ? .35 : .2)
+          : null,
+      child: ListTile(
+        leading: leading != null
+            ? Theme(
+                data: Theme.of(context).copyWith(
+                    iconTheme: IconThemeData(
+                        color: Theme.of(context).colorScheme.secondary)),
+                child: leading!,
+              )
+            : null,
+        trailing: trailingDivider
+            ? Row(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  Container(
+                    margin: const EdgeInsets.only(right: 6.0),
+                    width: 2.0,
+                    height: 32.0,
+                    decoration: BoxDecoration(
+                      color: AppColors.of(context).text.withOpacity(.15),
+                      borderRadius: BorderRadius.circular(45.0),
+                    ),
+                  ),
+                  if (trailing != null) trailing!,
+                ],
+              )
+            : trailing,
+        title: title != null
+            ? DefaultTextStyle(
+                style: Theme.of(context)
+                    .textTheme
+                    .titleMedium!
+                    .copyWith(fontWeight: FontWeight.w600, fontSize: 16.0),
+                child: title!)
+            : null,
+        contentPadding: EdgeInsets.zero,
+        visualDensity: VisualDensity.compact,
+      ),
+    );
+
+    if (!background) return button;
+
+    return BackdropFilter(
+        filter: ImageFilter.blur(
+          sigmaX: 12.0,
+          sigmaY: 12.0,
+        ),
+        child: button);
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/personality_card/empty_card.dart b/refilc_mobile_ui/lib/common/personality_card/empty_card.dart
similarity index 100%
rename from filcnaplo_mobile_ui/lib/common/personality_card/empty_card.dart
rename to refilc_mobile_ui/lib/common/personality_card/empty_card.dart
diff --git a/filcnaplo_mobile_ui/lib/common/personality_card/personality_card.dart b/refilc_mobile_ui/lib/common/personality_card/personality_card.dart
similarity index 93%
rename from filcnaplo_mobile_ui/lib/common/personality_card/personality_card.dart
rename to refilc_mobile_ui/lib/common/personality_card/personality_card.dart
index a6dec8e..e5aae1e 100644
--- a/filcnaplo_mobile_ui/lib/common/personality_card/personality_card.dart
+++ b/refilc_mobile_ui/lib/common/personality_card/personality_card.dart
@@ -1,16 +1,16 @@
 import 'package:dotted_border/dotted_border.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/personality.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/personality.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
diff --git a/filcnaplo_mobile_ui/lib/common/personality_card/personality_card.i18n.dart b/refilc_mobile_ui/lib/common/personality_card/personality_card.i18n.dart
similarity index 100%
rename from filcnaplo_mobile_ui/lib/common/personality_card/personality_card.i18n.dart
rename to refilc_mobile_ui/lib/common/personality_card/personality_card.i18n.dart
diff --git a/filcnaplo_mobile_ui/lib/common/profile_image/profile_button.dart b/refilc_mobile_ui/lib/common/profile_image/profile_button.dart
old mode 100755
new mode 100644
similarity index 74%
rename from filcnaplo_mobile_ui/lib/common/profile_image/profile_button.dart
rename to refilc_mobile_ui/lib/common/profile_image/profile_button.dart
index 03714ad..94263c8
--- a/filcnaplo_mobile_ui/lib/common/profile_image/profile_button.dart
+++ b/refilc_mobile_ui/lib/common/profile_image/profile_button.dart
@@ -1,98 +1,98 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_kreta_api/client/client.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
-
-class ProfileButton extends StatelessWidget {
-  const ProfileButton({Key? key, required this.child}) : super(key: key);
-
-  final ProfileImage child;
-
-  @override
-  Widget build(BuildContext context) {
-    final bool pMode =
-        Provider.of<SettingsProvider>(context, listen: false).presentationMode;
-
-    late UserProvider user;
-    late User? account;
-
-    Future<void> restore() => Future.wait([
-          Provider.of<GradeProvider>(context, listen: false).restore(),
-          Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
-          Provider.of<ExamProvider>(context, listen: false).restore(),
-          Provider.of<HomeworkProvider>(context, listen: false).restore(),
-          Provider.of<MessageProvider>(context, listen: false).restore(),
-          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(),
-        ]);
-
-    user = Provider.of<UserProvider>(context);
-    try {
-      user.getUsers().forEach((acc) {
-        if (user.name!.toLowerCase().replaceAll(' ', '') !=
-            acc.name.toLowerCase().replaceAll(' ', '')) {
-          account = acc;
-        }
-      });
-    } catch (err) {
-      account = null;
-    }
-
-    return ProfileImage(
-      backgroundColor: !pMode
-          ? child.backgroundColor
-          : Theme.of(context).colorScheme.secondary,
-      heroTag: child.heroTag,
-      key: child.key,
-      name: !pMode ? child.name : "János",
-      radius: child.radius,
-      badge: child.badge,
-      role: child.role,
-      profilePictureString: child.profilePictureString,
-      onTap: () {
-        showSlidingBottomSheet(
-          context,
-          useRootNavigator: true,
-          builder: (context) => SlidingSheetDialog(
-            color: Theme.of(context).scaffoldBackgroundColor,
-            duration: const Duration(milliseconds: 400),
-            scrollSpec: const ScrollSpec.bouncingScroll(),
-            snapSpec: const SnapSpec(
-              snap: true,
-              snappings: [1.0],
-              initialSnap: 1.0,
-              positioning: SnapPositioning.relativeToSheetHeight,
-            ),
-            cornerRadius: 16,
-            cornerRadiusOnFullscreen: 0,
-            builder: (context, state) => Material(
-              color: Theme.of(context).scaffoldBackgroundColor,
-              child: const SettingsScreen(),
-            ),
-          ),
-        );
-      },
-      onLongPress: () {
-        if (account != null) {
-          user.setUser(account!.id);
-          restore().then((_) => user.setUser(account!.id));
-        }
-      },
-    );
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
+
+class ProfileButton extends StatelessWidget {
+  const ProfileButton({Key? key, required this.child}) : super(key: key);
+
+  final ProfileImage child;
+
+  @override
+  Widget build(BuildContext context) {
+    final bool pMode =
+        Provider.of<SettingsProvider>(context, listen: false).presentationMode;
+
+    late UserProvider user;
+    late User? account;
+
+    Future<void> restore() => Future.wait([
+          Provider.of<GradeProvider>(context, listen: false).restore(),
+          Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
+          Provider.of<ExamProvider>(context, listen: false).restore(),
+          Provider.of<HomeworkProvider>(context, listen: false).restore(),
+          Provider.of<MessageProvider>(context, listen: false).restore(),
+          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(),
+        ]);
+
+    user = Provider.of<UserProvider>(context);
+    try {
+      user.getUsers().forEach((acc) {
+        if (user.name!.toLowerCase().replaceAll(' ', '') !=
+            acc.name.toLowerCase().replaceAll(' ', '')) {
+          account = acc;
+        }
+      });
+    } catch (err) {
+      account = null;
+    }
+
+    return ProfileImage(
+      backgroundColor: !pMode
+          ? child.backgroundColor
+          : Theme.of(context).colorScheme.secondary,
+      heroTag: child.heroTag,
+      key: child.key,
+      name: !pMode ? child.name : "János",
+      radius: child.radius,
+      badge: child.badge,
+      role: child.role,
+      profilePictureString: child.profilePictureString,
+      onTap: () {
+        showSlidingBottomSheet(
+          context,
+          useRootNavigator: true,
+          builder: (context) => SlidingSheetDialog(
+            color: Theme.of(context).scaffoldBackgroundColor,
+            duration: const Duration(milliseconds: 400),
+            scrollSpec: const ScrollSpec.bouncingScroll(),
+            snapSpec: const SnapSpec(
+              snap: true,
+              snappings: [1.0],
+              initialSnap: 1.0,
+              positioning: SnapPositioning.relativeToSheetHeight,
+            ),
+            cornerRadius: 16,
+            cornerRadiusOnFullscreen: 0,
+            builder: (context, state) => Material(
+              color: Theme.of(context).scaffoldBackgroundColor,
+              child: const SettingsScreen(),
+            ),
+          ),
+        );
+      },
+      onLongPress: () {
+        if (account != null) {
+          user.setUser(account!.id);
+          restore().then((_) => user.setUser(account!.id));
+        }
+      },
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/profile_image/profile_image.dart b/refilc_mobile_ui/lib/common/profile_image/profile_image.dart
old mode 100755
new mode 100644
similarity index 94%
rename from filcnaplo_mobile_ui/lib/common/profile_image/profile_image.dart
rename to refilc_mobile_ui/lib/common/profile_image/profile_image.dart
index 9c75d95..b189067
--- a/filcnaplo_mobile_ui/lib/common/profile_image/profile_image.dart
+++ b/refilc_mobile_ui/lib/common/profile_image/profile_image.dart
@@ -1,253 +1,253 @@
-import 'dart:convert';
-
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/common/new_content_indicator.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/color.dart';
-
-class ProfileImage extends StatefulWidget {
-  const ProfileImage({
-    Key? key,
-    this.onTap,
-    this.onDoubleTap,
-    this.onLongPress,
-    this.name,
-    this.backgroundColor,
-    this.radius = 20.0,
-    this.heroTag,
-    this.badge = false,
-    this.role = Role.student,
-    this.censored = false,
-    this.profilePictureString = "",
-  }) : super(key: key);
-
-  final void Function()? onTap;
-  final void Function()? onDoubleTap;
-  final void Function()? onLongPress;
-  final String? name;
-  final Color? backgroundColor;
-  final double radius;
-  final String? heroTag;
-  final bool badge;
-  final Role? role;
-  final bool censored;
-  final String profilePictureString;
-
-  @override
-  State<ProfileImage> createState() => _ProfileImageState();
-}
-
-class _ProfileImageState extends State<ProfileImage> {
-  Image? profilePicture;
-  String? profPicSaved;
-
-  @override
-  void initState() {
-    super.initState();
-    updatePic();
-  }
-
-  void updatePic() {
-    profilePicture = widget.profilePictureString != ""
-        ? Image.memory(
-            const Base64Decoder().convert(widget.profilePictureString),
-            fit: BoxFit.scaleDown,
-            gaplessPlayback: true)
-        : null;
-    profPicSaved = widget.profilePictureString;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (profPicSaved != widget.profilePictureString) updatePic();
-
-    if (widget.heroTag == null) {
-      return buildWithoutHero(context);
-    } else {
-      return buildWithHero(context);
-    }
-  }
-
-  Widget buildWithoutHero(BuildContext context) {
-    Color color = ColorUtils.foregroundColor(
-        widget.backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
-    Color roleColor;
-
-    if (Theme.of(context).brightness == Brightness.light) {
-      roleColor = const Color(0xFF444444);
-    } else {
-      roleColor = const Color(0xFF555555);
-    }
-
-    return Stack(
-      alignment: Alignment.center,
-      children: [
-        Material(
-          clipBehavior: Clip.hardEdge,
-          shape: const CircleBorder(),
-          color: widget.backgroundColor ??
-              AppColors.of(context).text.withOpacity(.15),
-          child: InkWell(
-            onTap: widget.onTap,
-            onDoubleTap: widget.onDoubleTap,
-            onLongPress: widget.onLongPress,
-            child: AnimatedContainer(
-              duration: const Duration(milliseconds: 200),
-              height: widget.radius * 2,
-              width: widget.radius * 2,
-              decoration: const BoxDecoration(
-                shape: BoxShape.circle,
-              ),
-              child:
-                  widget.name != null && (widget.name?.trim().length ?? 0) > 0
-                      ? Center(
-                          child: widget.censored
-                              ? Container(
-                                  width: 15,
-                                  height: 15,
-                                  decoration: BoxDecoration(
-                                    color: color.withOpacity(.5),
-                                    borderRadius: BorderRadius.circular(8.0),
-                                  ),
-                                )
-                              : profilePicture ??
-                                  Text(
-                                    (widget.name?.trim().length ?? 0) > 0
-                                        ? (widget.name ?? "?").trim()[0]
-                                        : "?",
-                                    style: TextStyle(
-                                      color: color,
-                                      fontWeight: FontWeight.w600,
-                                      fontSize: 18.0 * (widget.radius / 20.0),
-                                    ),
-                                  ),
-                        )
-                      : Container(),
-            ),
-          ),
-        ),
-
-        // Role indicator
-        if (widget.role == Role.parent)
-          SizedBox(
-            height: widget.radius * 2,
-            width: widget.radius * 2,
-            child: Container(
-              alignment: Alignment.bottomRight,
-              child: Icon(Icons.shield,
-                  color: roleColor, size: widget.radius / 1.3),
-            ),
-          ),
-      ],
-    );
-  }
-
-  Widget buildWithHero(BuildContext context) {
-    Color color = ColorUtils.foregroundColor(
-        widget.backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
-    Color roleColor;
-
-    if (Theme.of(context).brightness == Brightness.light) {
-      roleColor = const Color(0xFF444444);
-    } else {
-      roleColor = const Color(0xFF555555);
-    }
-
-    Widget child = FittedBox(
-      fit: BoxFit.fitHeight,
-      child: Text(
-        (widget.name?.trim().length ?? 0) > 0
-            ? (widget.name ?? "?").trim()[0]
-            : "?",
-        style: TextStyle(
-          color: color,
-          fontWeight: FontWeight.w600,
-          fontSize: 18.0 * (widget.radius / 20.0),
-        ),
-      ),
-    );
-
-    return SizedBox(
-      height: widget.radius * 2,
-      width: widget.radius * 2,
-      child: Stack(
-        alignment: Alignment.center,
-        children: [
-          if (widget.name != null && (widget.name?.trim().length ?? 0) > 0)
-            Hero(
-              tag: widget.heroTag! + "background",
-              transitionOnUserGestures: true,
-              child: Material(
-                clipBehavior: Clip.hardEdge,
-                shape: const CircleBorder(),
-                color: profilePicture != null
-                    ? Colors.transparent
-                    : widget.backgroundColor ??
-                        AppColors.of(context).text.withOpacity(.15),
-                child: AnimatedContainer(
-                  duration: const Duration(milliseconds: 200),
-                  height: widget.radius * 2,
-                  width: widget.radius * 2,
-                  decoration: const BoxDecoration(
-                    shape: BoxShape.circle,
-                  ),
-                  child: profilePicture,
-                ),
-              ),
-            ),
-          Hero(
-            tag: widget.heroTag! + "child",
-            transitionOnUserGestures: true,
-            child: Material(
-              clipBehavior: Clip.hardEdge,
-              shape: profilePicture != null ? const CircleBorder() : null,
-              child: profilePicture ?? child,
-              type: MaterialType.transparency,
-            ),
-          ),
-
-          // Badge
-          if (widget.badge)
-            Hero(
-              tag: widget.heroTag! + "new_content_indicator",
-              child: NewContentIndicator(size: widget.radius * 2),
-            ),
-
-          // Role indicator
-          if (widget.role == Role.parent)
-            Hero(
-              tag: widget.heroTag! + "role_indicator",
-              child: FittedBox(
-                fit: BoxFit.fitHeight,
-                child: SizedBox(
-                  height: widget.radius * 2,
-                  width: widget.radius * 2,
-                  child: Container(
-                    alignment: Alignment.bottomRight,
-                    child: Icon(Icons.shield,
-                        color: roleColor, size: widget.radius / 1.3),
-                  ),
-                ),
-              ),
-            ),
-
-          Material(
-            color: Colors.transparent,
-            clipBehavior: Clip.hardEdge,
-            shape: const CircleBorder(),
-            child: InkWell(
-              onTap: widget.onTap,
-              onDoubleTap: widget.onDoubleTap,
-              onLongPress: widget.onLongPress,
-              child: SizedBox(
-                height: widget.radius * 2,
-                width: widget.radius * 2,
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'dart:convert';
+
+import 'package:refilc/models/user.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_mobile_ui/common/new_content_indicator.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/color.dart';
+
+class ProfileImage extends StatefulWidget {
+  const ProfileImage({
+    Key? key,
+    this.onTap,
+    this.onDoubleTap,
+    this.onLongPress,
+    this.name,
+    this.backgroundColor,
+    this.radius = 20.0,
+    this.heroTag,
+    this.badge = false,
+    this.role = Role.student,
+    this.censored = false,
+    this.profilePictureString = "",
+  }) : super(key: key);
+
+  final void Function()? onTap;
+  final void Function()? onDoubleTap;
+  final void Function()? onLongPress;
+  final String? name;
+  final Color? backgroundColor;
+  final double radius;
+  final String? heroTag;
+  final bool badge;
+  final Role? role;
+  final bool censored;
+  final String profilePictureString;
+
+  @override
+  State<ProfileImage> createState() => _ProfileImageState();
+}
+
+class _ProfileImageState extends State<ProfileImage> {
+  Image? profilePicture;
+  String? profPicSaved;
+
+  @override
+  void initState() {
+    super.initState();
+    updatePic();
+  }
+
+  void updatePic() {
+    profilePicture = widget.profilePictureString != ""
+        ? Image.memory(
+            const Base64Decoder().convert(widget.profilePictureString),
+            fit: BoxFit.scaleDown,
+            gaplessPlayback: true)
+        : null;
+    profPicSaved = widget.profilePictureString;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (profPicSaved != widget.profilePictureString) updatePic();
+
+    if (widget.heroTag == null) {
+      return buildWithoutHero(context);
+    } else {
+      return buildWithHero(context);
+    }
+  }
+
+  Widget buildWithoutHero(BuildContext context) {
+    Color color = ColorUtils.foregroundColor(
+        widget.backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
+    Color roleColor;
+
+    if (Theme.of(context).brightness == Brightness.light) {
+      roleColor = const Color(0xFF444444);
+    } else {
+      roleColor = const Color(0xFF555555);
+    }
+
+    return Stack(
+      alignment: Alignment.center,
+      children: [
+        Material(
+          clipBehavior: Clip.hardEdge,
+          shape: const CircleBorder(),
+          color: widget.backgroundColor ??
+              AppColors.of(context).text.withOpacity(.15),
+          child: InkWell(
+            onTap: widget.onTap,
+            onDoubleTap: widget.onDoubleTap,
+            onLongPress: widget.onLongPress,
+            child: AnimatedContainer(
+              duration: const Duration(milliseconds: 200),
+              height: widget.radius * 2,
+              width: widget.radius * 2,
+              decoration: const BoxDecoration(
+                shape: BoxShape.circle,
+              ),
+              child:
+                  widget.name != null && (widget.name?.trim().length ?? 0) > 0
+                      ? Center(
+                          child: widget.censored
+                              ? Container(
+                                  width: 15,
+                                  height: 15,
+                                  decoration: BoxDecoration(
+                                    color: color.withOpacity(.5),
+                                    borderRadius: BorderRadius.circular(8.0),
+                                  ),
+                                )
+                              : profilePicture ??
+                                  Text(
+                                    (widget.name?.trim().length ?? 0) > 0
+                                        ? (widget.name ?? "?").trim()[0]
+                                        : "?",
+                                    style: TextStyle(
+                                      color: color,
+                                      fontWeight: FontWeight.w600,
+                                      fontSize: 18.0 * (widget.radius / 20.0),
+                                    ),
+                                  ),
+                        )
+                      : Container(),
+            ),
+          ),
+        ),
+
+        // Role indicator
+        if (widget.role == Role.parent)
+          SizedBox(
+            height: widget.radius * 2,
+            width: widget.radius * 2,
+            child: Container(
+              alignment: Alignment.bottomRight,
+              child: Icon(Icons.shield,
+                  color: roleColor, size: widget.radius / 1.3),
+            ),
+          ),
+      ],
+    );
+  }
+
+  Widget buildWithHero(BuildContext context) {
+    Color color = ColorUtils.foregroundColor(
+        widget.backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
+    Color roleColor;
+
+    if (Theme.of(context).brightness == Brightness.light) {
+      roleColor = const Color(0xFF444444);
+    } else {
+      roleColor = const Color(0xFF555555);
+    }
+
+    Widget child = FittedBox(
+      fit: BoxFit.fitHeight,
+      child: Text(
+        (widget.name?.trim().length ?? 0) > 0
+            ? (widget.name ?? "?").trim()[0]
+            : "?",
+        style: TextStyle(
+          color: color,
+          fontWeight: FontWeight.w600,
+          fontSize: 18.0 * (widget.radius / 20.0),
+        ),
+      ),
+    );
+
+    return SizedBox(
+      height: widget.radius * 2,
+      width: widget.radius * 2,
+      child: Stack(
+        alignment: Alignment.center,
+        children: [
+          if (widget.name != null && (widget.name?.trim().length ?? 0) > 0)
+            Hero(
+              tag: widget.heroTag! + "background",
+              transitionOnUserGestures: true,
+              child: Material(
+                clipBehavior: Clip.hardEdge,
+                shape: const CircleBorder(),
+                color: profilePicture != null
+                    ? Colors.transparent
+                    : widget.backgroundColor ??
+                        AppColors.of(context).text.withOpacity(.15),
+                child: AnimatedContainer(
+                  duration: const Duration(milliseconds: 200),
+                  height: widget.radius * 2,
+                  width: widget.radius * 2,
+                  decoration: const BoxDecoration(
+                    shape: BoxShape.circle,
+                  ),
+                  child: profilePicture,
+                ),
+              ),
+            ),
+          Hero(
+            tag: widget.heroTag! + "child",
+            transitionOnUserGestures: true,
+            child: Material(
+              clipBehavior: Clip.hardEdge,
+              shape: profilePicture != null ? const CircleBorder() : null,
+              child: profilePicture ?? child,
+              type: MaterialType.transparency,
+            ),
+          ),
+
+          // Badge
+          if (widget.badge)
+            Hero(
+              tag: widget.heroTag! + "new_content_indicator",
+              child: NewContentIndicator(size: widget.radius * 2),
+            ),
+
+          // Role indicator
+          if (widget.role == Role.parent)
+            Hero(
+              tag: widget.heroTag! + "role_indicator",
+              child: FittedBox(
+                fit: BoxFit.fitHeight,
+                child: SizedBox(
+                  height: widget.radius * 2,
+                  width: widget.radius * 2,
+                  child: Container(
+                    alignment: Alignment.bottomRight,
+                    child: Icon(Icons.shield,
+                        color: roleColor, size: widget.radius / 1.3),
+                  ),
+                ),
+              ),
+            ),
+
+          Material(
+            color: Colors.transparent,
+            clipBehavior: Clip.hardEdge,
+            shape: const CircleBorder(),
+            child: InkWell(
+              onTap: widget.onTap,
+              onDoubleTap: widget.onDoubleTap,
+              onLongPress: widget.onLongPress,
+              child: SizedBox(
+                height: widget.radius * 2,
+                width: widget.radius * 2,
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/progress_bar.dart b/refilc_mobile_ui/lib/common/progress_bar.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/progress_bar.dart
rename to refilc_mobile_ui/lib/common/progress_bar.dart
index ffffa00..d6028db
--- a/filcnaplo_mobile_ui/lib/common/progress_bar.dart
+++ b/refilc_mobile_ui/lib/common/progress_bar.dart
@@ -1,80 +1,80 @@
-import 'package:flutter/material.dart';
-
-class ProgressBar extends StatelessWidget {
-  const ProgressBar(
-      {Key? key, required this.value, this.backgroundColor, this.height = 8.0})
-      : super(key: key);
-
-  final double value;
-  final Color? backgroundColor;
-  final double height;
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        // Background
-        Container(
-          decoration: BoxDecoration(
-            color: Theme.of(context).brightness == Brightness.light
-                ? Colors.black.withOpacity(0.1)
-                : Colors.white.withOpacity(0.1),
-            borderRadius: BorderRadius.circular(45.0),
-          ),
-          width: double.infinity,
-          height: height,
-        ),
-
-        // Slider
-        AnimatedContainer(
-          duration: const Duration(milliseconds: 500),
-          width: double.infinity,
-          child: CustomPaint(
-            painter: ProgressPainter(
-              backgroundColor:
-                  backgroundColor ?? Theme.of(context).colorScheme.secondary,
-              height: height,
-              value: value.clamp(0, 1),
-            ),
-          ),
-        )
-      ],
-    );
-  }
-}
-
-class ProgressPainter extends CustomPainter {
-  ProgressPainter(
-      {required this.height,
-      required this.value,
-      required this.backgroundColor});
-
-  final double height;
-  final double value;
-  final Color backgroundColor;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    double width = size.width * value;
-
-    if (width <= 0) return;
-
-    // Slider
-    canvas.drawRRect(
-      RRect.fromRectAndRadius(
-        Rect.fromLTWH(0, 0, width, height),
-        const Radius.circular(45.0),
-      ),
-      Paint()
-        ..color = backgroundColor
-        ..style = PaintingStyle.fill,
-    );
-  }
-
-  @override
-  bool shouldRepaint(ProgressPainter oldDelegate) {
-    return value != oldDelegate.value ||
-        height != oldDelegate.height ||
-        backgroundColor != oldDelegate.backgroundColor;
-  }
-}
+import 'package:flutter/material.dart';
+
+class ProgressBar extends StatelessWidget {
+  const ProgressBar(
+      {Key? key, required this.value, this.backgroundColor, this.height = 8.0})
+      : super(key: key);
+
+  final double value;
+  final Color? backgroundColor;
+  final double height;
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: [
+        // Background
+        Container(
+          decoration: BoxDecoration(
+            color: Theme.of(context).brightness == Brightness.light
+                ? Colors.black.withOpacity(0.1)
+                : Colors.white.withOpacity(0.1),
+            borderRadius: BorderRadius.circular(45.0),
+          ),
+          width: double.infinity,
+          height: height,
+        ),
+
+        // Slider
+        AnimatedContainer(
+          duration: const Duration(milliseconds: 500),
+          width: double.infinity,
+          child: CustomPaint(
+            painter: ProgressPainter(
+              backgroundColor:
+                  backgroundColor ?? Theme.of(context).colorScheme.secondary,
+              height: height,
+              value: value.clamp(0, 1),
+            ),
+          ),
+        )
+      ],
+    );
+  }
+}
+
+class ProgressPainter extends CustomPainter {
+  ProgressPainter(
+      {required this.height,
+      required this.value,
+      required this.backgroundColor});
+
+  final double height;
+  final double value;
+  final Color backgroundColor;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    double width = size.width * value;
+
+    if (width <= 0) return;
+
+    // Slider
+    canvas.drawRRect(
+      RRect.fromRectAndRadius(
+        Rect.fromLTWH(0, 0, width, height),
+        const Radius.circular(45.0),
+      ),
+      Paint()
+        ..color = backgroundColor
+        ..style = PaintingStyle.fill,
+    );
+  }
+
+  @override
+  bool shouldRepaint(ProgressPainter oldDelegate) {
+    return value != oldDelegate.value ||
+        height != oldDelegate.height ||
+        backgroundColor != oldDelegate.backgroundColor;
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/round_border_icon.dart b/refilc_mobile_ui/lib/common/round_border_icon.dart
similarity index 100%
rename from filcnaplo_mobile_ui/lib/common/round_border_icon.dart
rename to refilc_mobile_ui/lib/common/round_border_icon.dart
diff --git a/filcnaplo_mobile_ui/lib/common/screens.i18n.dart b/refilc_mobile_ui/lib/common/screens.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/screens.i18n.dart
rename to refilc_mobile_ui/lib/common/screens.i18n.dart
index 9094eb1..3145432
--- a/filcnaplo_mobile_ui/lib/common/screens.i18n.dart
+++ b/refilc_mobile_ui/lib/common/screens.i18n.dart
@@ -1,33 +1,33 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension ScreensLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "home": "Home",
-          "grades": "Grades",
-          "timetable": "Timetable",
-          "messages": "Messages",
-          "absences": "Absences",
-        },
-        "hu_hu": {
-          "home": "Kezdőlap",
-          "grades": "Jegyek",
-          "timetable": "Órarend",
-          "messages": "Üzenetek",
-          "absences": "Hiányok",
-        },
-        "de_de": {
-          "home": "Zuhause",
-          "grades": "Noten",
-          "timetable": "Zeitplan",
-          "messages": "Mitteilungen",
-          "absences": "Fehlen",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension ScreensLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "home": "Home",
+          "grades": "Grades",
+          "timetable": "Timetable",
+          "messages": "Messages",
+          "absences": "Absences",
+        },
+        "hu_hu": {
+          "home": "Kezdőlap",
+          "grades": "Jegyek",
+          "timetable": "Órarend",
+          "messages": "Üzenetek",
+          "absences": "Hiányok",
+        },
+        "de_de": {
+          "home": "Zuhause",
+          "grades": "Noten",
+          "timetable": "Zeitplan",
+          "messages": "Mitteilungen",
+          "absences": "Fehlen",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/sliding_bottom_sheet.dart b/refilc_mobile_ui/lib/common/sliding_bottom_sheet.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/sliding_bottom_sheet.dart
rename to refilc_mobile_ui/lib/common/sliding_bottom_sheet.dart
index 0932f62..daf2302
--- a/filcnaplo_mobile_ui/lib/common/sliding_bottom_sheet.dart
+++ b/refilc_mobile_ui/lib/common/sliding_bottom_sheet.dart
@@ -1,46 +1,46 @@
-import 'package:flutter/material.dart';
-import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart' as ss;
-
-void showSlidingBottomSheet(
-        {required Widget child, required BuildContext context}) =>
-    ss.showSlidingBottomSheet(context,
-        useRootNavigator: true,
-        builder: (context) => ss.SlidingSheetDialog(
-              cornerRadius: 16,
-              cornerRadiusOnFullscreen: 0,
-              avoidStatusBar: true,
-              color: Theme.of(context).colorScheme.background,
-              duration: const Duration(milliseconds: 400),
-              snapSpec: const ss.SnapSpec(
-                snap: true,
-                snappings: [0.5, 1.0],
-                positioning: ss.SnapPositioning.relativeToAvailableSpace,
-              ),
-              headerBuilder: (context, state) {
-                return Material(
-                  color: Theme.of(context).colorScheme.background,
-                  child: Column(
-                    mainAxisSize: MainAxisSize.min,
-                    children: [
-                      Container(
-                        decoration: BoxDecoration(
-                          color: Colors.grey,
-                          borderRadius: BorderRadius.circular(12.0),
-                        ),
-                        height: 4.0,
-                        width: 60.0,
-                        margin: const EdgeInsets.all(12.0),
-                      ),
-                    ],
-                  ),
-                );
-              },
-              builder: (context, state) {
-                return Material(
-                  color: Theme.of(context).colorScheme.background,
-                  child: Padding(
-                      padding: const EdgeInsets.fromLTRB(12.0, 0, 12.0, 8.0),
-                      child: child),
-                );
-              },
-            ));
+import 'package:flutter/material.dart';
+import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart' as ss;
+
+void showSlidingBottomSheet(
+        {required Widget child, required BuildContext context}) =>
+    ss.showSlidingBottomSheet(context,
+        useRootNavigator: true,
+        builder: (context) => ss.SlidingSheetDialog(
+              cornerRadius: 16,
+              cornerRadiusOnFullscreen: 0,
+              avoidStatusBar: true,
+              color: Theme.of(context).colorScheme.background,
+              duration: const Duration(milliseconds: 400),
+              snapSpec: const ss.SnapSpec(
+                snap: true,
+                snappings: [0.5, 1.0],
+                positioning: ss.SnapPositioning.relativeToAvailableSpace,
+              ),
+              headerBuilder: (context, state) {
+                return Material(
+                  color: Theme.of(context).colorScheme.background,
+                  child: Column(
+                    mainAxisSize: MainAxisSize.min,
+                    children: [
+                      Container(
+                        decoration: BoxDecoration(
+                          color: Colors.grey,
+                          borderRadius: BorderRadius.circular(12.0),
+                        ),
+                        height: 4.0,
+                        width: 60.0,
+                        margin: const EdgeInsets.all(12.0),
+                      ),
+                    ],
+                  ),
+                );
+              },
+              builder: (context, state) {
+                return Material(
+                  color: Theme.of(context).colorScheme.background,
+                  child: Padding(
+                      padding: const EdgeInsets.fromLTRB(12.0, 0, 12.0, 8.0),
+                      child: child),
+                );
+              },
+            ));
diff --git a/filcnaplo_mobile_ui/lib/common/system_chrome.dart b/refilc_mobile_ui/lib/common/system_chrome.dart
old mode 100755
new mode 100644
similarity index 98%
rename from filcnaplo_mobile_ui/lib/common/system_chrome.dart
rename to refilc_mobile_ui/lib/common/system_chrome.dart
index 0b27f55..725b44c
--- a/filcnaplo_mobile_ui/lib/common/system_chrome.dart
+++ b/refilc_mobile_ui/lib/common/system_chrome.dart
@@ -1,15 +1,15 @@
-import 'dart:io';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-
-void setSystemChrome(BuildContext context) {
-  SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
-  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
-    statusBarColor: Colors.transparent,
-    statusBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light,
-    systemNavigationBarColor: Theme.of(context).bottomNavigationBarTheme.backgroundColor,
-    systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light,
-    statusBarBrightness: Platform.isIOS ? Theme.of(context).brightness : null,
-  ));
-}
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+void setSystemChrome(BuildContext context) {
+  SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
+  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
+    statusBarColor: Colors.transparent,
+    statusBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light,
+    systemNavigationBarColor: Theme.of(context).bottomNavigationBarTheme.backgroundColor,
+    systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light,
+    statusBarBrightness: Platform.isIOS ? Theme.of(context).brightness : null,
+  ));
+}
diff --git a/filcnaplo_mobile_ui/lib/common/trend_display.dart b/refilc_mobile_ui/lib/common/trend_display.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/trend_display.dart
rename to refilc_mobile_ui/lib/common/trend_display.dart
index 0631056..c2697e1
--- a/filcnaplo_mobile_ui/lib/common/trend_display.dart
+++ b/refilc_mobile_ui/lib/common/trend_display.dart
@@ -1,59 +1,59 @@
-import 'package:flutter/material.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-
-class TrendDisplay<T extends num> extends StatelessWidget {
-  const TrendDisplay({Key? key, required this.current, required this.previous, this.padding}) : super(key: key);
-
-  final T current;
-  final T previous;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    const upIcon = "▲";
-    const downIcon = "▼";
-    final upColor = Colors.lightGreenAccent.shade700;
-    const downColor = Colors.redAccent;
-
-    Color color;
-    String icon;
-
-    double percentage;
-
-    if (previous > 0) {
-      percentage = (current - previous) * 100.0;
-    } else {
-      percentage = 0.0;
-    }
-
-    final String percentageText = percentage.abs().toStringAsFixed(1).replaceAll('.', I18n.of(context).locale.languageCode != 'en' ? ',' : '.');
-
-    if (!percentage.isNegative) {
-      color = upColor;
-      icon = upIcon;
-    } else {
-      color = downColor;
-      icon = downIcon;
-    }
-
-    if (percentage == 0) {
-      return const SizedBox();
-    }
-
-    return Padding(
-      padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-      child: Row(
-        children: [
-          Padding(
-            padding: const EdgeInsets.only(right: 2.0),
-            child: Text(
-              icon,
-              style: TextStyle(fontSize: 18.0, color: color),
-            ),
-          ),
-          Text("$percentageText%", style: TextStyle(color: color)),
-        ],
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+
+class TrendDisplay<T extends num> extends StatelessWidget {
+  const TrendDisplay({Key? key, required this.current, required this.previous, this.padding}) : super(key: key);
+
+  final T current;
+  final T previous;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    const upIcon = "▲";
+    const downIcon = "▼";
+    final upColor = Colors.lightGreenAccent.shade700;
+    const downColor = Colors.redAccent;
+
+    Color color;
+    String icon;
+
+    double percentage;
+
+    if (previous > 0) {
+      percentage = (current - previous) * 100.0;
+    } else {
+      percentage = 0.0;
+    }
+
+    final String percentageText = percentage.abs().toStringAsFixed(1).replaceAll('.', I18n.of(context).locale.languageCode != 'en' ? ',' : '.');
+
+    if (!percentage.isNegative) {
+      color = upColor;
+      icon = upIcon;
+    } else {
+      color = downColor;
+      icon = downIcon;
+    }
+
+    if (percentage == 0) {
+      return const SizedBox();
+    }
+
+    return Padding(
+      padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+      child: Row(
+        children: [
+          Padding(
+            padding: const EdgeInsets.only(right: 2.0),
+            child: Text(
+              icon,
+              style: TextStyle(fontSize: 18.0, color: color),
+            ),
+          ),
+          Text("$percentageText%", style: TextStyle(color: color)),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/viewable.dart b/refilc_mobile_ui/lib/common/viewable.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/viewable.dart
rename to refilc_mobile_ui/lib/common/viewable.dart
index eb73a47..37a2d28
--- a/filcnaplo_mobile_ui/lib/common/viewable.dart
+++ b/refilc_mobile_ui/lib/common/viewable.dart
@@ -1,979 +1,979 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:math' as math;
-import 'dart:ui' as ui;
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/gestures.dart' show kMinFlingVelocity;
-import 'package:flutter/material.dart';
-import 'package:flutter/scheduler.dart';
-import 'package:flutter/services.dart';
-
-double valueFromPercentageInRange({required final double min, max, percentage}) {
-  return percentage * (max - min) + min;
-}
-
-double percentageFromValueInRange({required final double min, max, value}) {
-  return (value - min) / (max - min);
-}
-
-const double _kOpenScale = 1.025;
-
-const Color _borderColor = CupertinoDynamicColor.withBrightness(
-  color: Color(0xFFA9A9AF),
-  darkColor: Color(0xFF57585A),
-);
-
-typedef _DismissCallback = void Function(
-  BuildContext context,
-  double scale,
-  double opacity,
-);
-
-typedef ViewablePreviewBuilder = Widget Function(
-  BuildContext context,
-  Animation<double> animation,
-  Widget child,
-);
-
-typedef _ViewablePreviewBuilderChildless = Widget Function(
-  BuildContext context,
-  Animation<double> animation,
-);
-
-Rect _getRect(GlobalKey globalKey) {
-  assert(globalKey.currentContext != null);
-  final RenderBox renderBoxContainer = globalKey.currentContext!.findRenderObject()! as RenderBox;
-  final Offset containerOffset = renderBoxContainer.localToGlobal(
-    renderBoxContainer.paintBounds.topLeft,
-  );
-  return containerOffset & renderBoxContainer.paintBounds.size;
-}
-
-enum _ViewableLocation {
-  center,
-  left,
-  right,
-}
-
-class Viewable extends StatefulWidget {
-  const Viewable({
-    Key? key,
-    required this.view,
-    required this.tile,
-    this.actions = const [],
-    this.previewBuilder,
-  }) : super(key: key);
-
-  final Widget tile;
-  final Widget view;
-
-  final List<Widget> actions;
-
-  final ViewablePreviewBuilder? previewBuilder;
-
-  @override
-  State<Viewable> createState() => _ViewableState();
-}
-
-class _ViewableState extends State<Viewable> with TickerProviderStateMixin {
-  final GlobalKey _childGlobalKey = GlobalKey();
-  bool _childHidden = false;
-
-  late AnimationController _openController;
-  Rect? _decoyChildEndRect;
-  OverlayEntry? _lastOverlayEntry;
-  _ViewableRoute<void>? _route;
-
-  @override
-  void initState() {
-    super.initState();
-    _openController = AnimationController(
-      duration: const Duration(milliseconds: 100),
-      vsync: this,
-    );
-    _openController.addStatusListener(_onDecoyAnimationStatusChange);
-  }
-
-  _ViewableLocation get _contextMenuLocation {
-    final Rect childRect = _getRect(_childGlobalKey);
-    final double screenWidth = MediaQuery.of(context).size.width;
-
-    final double center = screenWidth / 2;
-    final bool centerDividesChild = childRect.left < center && childRect.right > center;
-    final double distanceFromCenter = (center - childRect.center.dx).abs();
-    if (centerDividesChild && distanceFromCenter <= childRect.width / 4) {
-      return _ViewableLocation.center;
-    }
-
-    if (childRect.center.dx > center) {
-      return _ViewableLocation.right;
-    }
-
-    return _ViewableLocation.left;
-  }
-
-  void _openContextMenu() {
-    setState(() {
-      _childHidden = true;
-    });
-
-    _route = _ViewableRoute<void>(
-      actions: widget.actions,
-      barrierLabel: 'Dismiss',
-      filter: ui.ImageFilter.blur(
-        sigmaX: 5.0,
-        sigmaY: 5.0,
-      ),
-      contextMenuLocation: _contextMenuLocation,
-      previousChildRect: _decoyChildEndRect!,
-      builder: (BuildContext context, Animation<double> animation) {
-        return ClipRRect(
-          borderRadius: BorderRadius.circular(16.0),
-          child: Material(
-            color: Theme.of(context).colorScheme.background,
-            borderRadius: BorderRadius.circular(16.0),
-            child: Stack(
-              children: [
-                Opacity(
-                  opacity: animation.status == AnimationStatus.forward
-                      ? Curves.easeOutCirc.transform(animation.value)
-                      : Curves.easeInCirc.transform(animation.value),
-                  child: widget.view,
-                ),
-                Opacity(
-                  opacity: 1 -
-                      (animation.status == AnimationStatus.forward
-                          ? Curves.easeOutCirc.transform(animation.value)
-                          : Curves.easeInCirc.transform(animation.value)),
-                  child: widget.tile,
-                ),
-              ],
-            ),
-          ),
-        );
-      },
-    );
-    Navigator.of(context, rootNavigator: true).push<void>(_route!);
-    _route!.animation!.addStatusListener(_routeAnimationStatusListener);
-  }
-
-  void _onDecoyAnimationStatusChange(AnimationStatus animationStatus) {
-    switch (animationStatus) {
-      case AnimationStatus.dismissed:
-        if (_route == null) {
-          setState(() {
-            _childHidden = false;
-          });
-        }
-        _lastOverlayEntry?.remove();
-        _lastOverlayEntry = null;
-        break;
-
-      case AnimationStatus.completed:
-        setState(() {
-          _childHidden = true;
-        });
-        _openContextMenu();
-
-        SchedulerBinding.instance.addPostFrameCallback((Duration _) {
-          _lastOverlayEntry?.remove();
-          _lastOverlayEntry = null;
-          _openController.reset();
-        });
-        break;
-
-      case AnimationStatus.forward:
-      case AnimationStatus.reverse:
-        return;
-    }
-  }
-
-  void _routeAnimationStatusListener(AnimationStatus status) {
-    if (status != AnimationStatus.dismissed) {
-      return;
-    }
-    setState(() {
-      _childHidden = false;
-    });
-    _route!.animation!.removeStatusListener(_routeAnimationStatusListener);
-    _route = null;
-  }
-
-  void _onTap() {
-    _onTapDown(TapDownDetails(), anim: false);
-  }
-
-  void _onTapDown(TapDownDetails details, {anim = true}) {
-    setState(() {
-      _childHidden = true;
-    });
-
-    final Rect childRect = _getRect(_childGlobalKey);
-    _decoyChildEndRect = Rect.fromCenter(
-      center: childRect.center,
-      width: childRect.width * _kOpenScale,
-      height: childRect.height * _kOpenScale,
-    );
-
-    _lastOverlayEntry = OverlayEntry(
-      builder: (BuildContext context) {
-        return _DecoyChild(
-          beginRect: childRect,
-          controller: _openController,
-          endRect: _decoyChildEndRect,
-          child: widget.tile,
-        );
-      },
-    );
-    Overlay.of(context, rootOverlay: true).insert(_lastOverlayEntry!);
-    _openController.forward(from: anim ? 0.0 : 1.0);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return GestureDetector(
-      onTap: _onTap,
-      child: TickerMode(
-        enabled: !_childHidden,
-        child: Opacity(
-          key: _childGlobalKey,
-          opacity: _childHidden ? 0.0 : 1.0,
-          child: widget.tile,
-        ),
-      ),
-    );
-  }
-
-  @override
-  void dispose() {
-    _openController.dispose();
-    super.dispose();
-  }
-}
-
-class _DecoyChild extends StatefulWidget {
-  const _DecoyChild({
-    Key? key,
-    this.beginRect,
-    required this.controller,
-    this.endRect,
-    this.child,
-  }) : super(key: key);
-
-  final Rect? beginRect;
-  final AnimationController controller;
-  final Rect? endRect;
-  final Widget? child;
-
-  @override
-  _DecoyChildState createState() => _DecoyChildState();
-}
-
-class _DecoyChildState extends State<_DecoyChild> with TickerProviderStateMixin {
-  static const Color _lightModeMaskColor = Color(0xFF888888);
-  static const Color _masklessColor = Color(0xFFFFFFFF);
-
-  final GlobalKey _childGlobalKey = GlobalKey();
-  late Animation<Color> _mask;
-  late Animation<Rect?> _rect;
-
-  @override
-  void initState() {
-    super.initState();
-
-    _mask = _OnOffAnimation<Color>(
-      controller: widget.controller,
-      onValue: _lightModeMaskColor,
-      offValue: _masklessColor,
-      intervalOn: 0.0,
-      intervalOff: 0.5,
-    );
-
-    final Rect midRect = widget.beginRect!.deflate(
-      widget.beginRect!.width * (_kOpenScale - 1.0) / 2,
-    );
-    _rect = TweenSequence<Rect?>(<TweenSequenceItem<Rect?>>[
-      TweenSequenceItem<Rect?>(
-        tween: RectTween(
-          begin: widget.beginRect,
-          end: midRect,
-        ).chain(CurveTween(curve: Curves.easeInOutCubic)),
-        weight: 1.0,
-      ),
-      TweenSequenceItem<Rect?>(
-        tween: RectTween(
-          begin: midRect,
-          end: widget.endRect,
-        ).chain(CurveTween(curve: Curves.easeOutCubic)),
-        weight: 1.0,
-      ),
-    ]).animate(widget.controller);
-    _rect.addListener(_rectListener);
-  }
-
-  void _rectListener() {
-    if (widget.controller.value < 0.5) {
-      return;
-    }
-    HapticFeedback.selectionClick();
-    _rect.removeListener(_rectListener);
-  }
-
-  @override
-  void dispose() {
-    _rect.removeListener(_rectListener);
-    super.dispose();
-  }
-
-  Widget _buildAnimation(BuildContext context, Widget? child) {
-    final Color color = widget.controller.status == AnimationStatus.reverse ? _masklessColor : _mask.value;
-    return Positioned.fromRect(
-      rect: _rect.value!,
-      child: ShaderMask(
-        key: _childGlobalKey,
-        shaderCallback: (Rect bounds) {
-          return LinearGradient(
-            begin: Alignment.topLeft,
-            end: Alignment.bottomRight,
-            colors: <Color>[color, color],
-          ).createShader(bounds);
-        },
-        child: widget.child,
-      ),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: <Widget>[
-        AnimatedBuilder(
-          builder: _buildAnimation,
-          animation: widget.controller,
-        ),
-      ],
-    );
-  }
-}
-
-class _ViewableRoute<T> extends PopupRoute<T> {
-  _ViewableRoute({
-    required List<Widget> actions,
-    required _ViewableLocation contextMenuLocation,
-    this.barrierLabel,
-    _ViewablePreviewBuilderChildless? builder,
-    ui.ImageFilter? filter,
-    required Rect previousChildRect,
-    RouteSettings? settings,
-  })  : _actions = actions,
-        _builder = builder,
-        _contextMenuLocation = contextMenuLocation,
-        _previousChildRect = previousChildRect,
-        super(
-          filter: filter,
-          settings: settings,
-        );
-
-  static const Color _kModalBarrierColor = Color(0x6604040F);
-
-  static const Duration _kModalPopupTransitionDuration = Duration(milliseconds: 335);
-
-  final List<Widget> _actions;
-  final _ViewablePreviewBuilderChildless? _builder;
-  final GlobalKey _childGlobalKey = GlobalKey();
-  final _ViewableLocation _contextMenuLocation;
-  bool _externalOffstage = false;
-  bool _internalOffstage = false;
-  Orientation? _lastOrientation;
-
-  final Rect _previousChildRect;
-  double? _scale = 1.0;
-  final GlobalKey _sheetGlobalKey = GlobalKey();
-
-  static final CurveTween _curve = CurveTween(
-    curve: Curves.easeOutBack,
-  );
-  static final CurveTween _curveReverse = CurveTween(
-    curve: Curves.easeInBack,
-  );
-  static final RectTween _rectTween = RectTween();
-  static final Animatable<Rect?> _rectAnimatable = _rectTween.chain(_curve);
-  static final RectTween _rectTweenReverse = RectTween();
-  static final Animatable<Rect?> _rectAnimatableReverse = _rectTweenReverse.chain(
-    _curveReverse,
-  );
-  static final RectTween _sheetRectTween = RectTween();
-  final Animatable<Rect?> _sheetRectAnimatable = _sheetRectTween.chain(
-    _curve,
-  );
-  final Animatable<Rect?> _sheetRectAnimatableReverse = _sheetRectTween.chain(
-    _curveReverse,
-  );
-  static final Tween<double> _sheetScaleTween = Tween<double>();
-  static final Animatable<double> _sheetScaleAnimatable = _sheetScaleTween.chain(
-    _curve,
-  );
-  static final Animatable<double> _sheetScaleAnimatableReverse = _sheetScaleTween.chain(
-    _curveReverse,
-  );
-  final Tween<double> _opacityTween = Tween<double>(begin: 0.0, end: 1.0);
-  late Animation<double> _sheetOpacity;
-
-  @override
-  final String? barrierLabel;
-
-  @override
-  Color get barrierColor => _kModalBarrierColor;
-
-  @override
-  bool get barrierDismissible => true;
-
-  @override
-  bool get semanticsDismissible => false;
-
-  @override
-  Duration get transitionDuration => _kModalPopupTransitionDuration;
-
-  static Rect _getScaledRect(GlobalKey globalKey, double scale) {
-    final Rect childRect = _getRect(globalKey);
-    final Size sizeScaled = childRect.size * scale;
-    final Offset offsetScaled = Offset(
-      childRect.left + (childRect.size.width - sizeScaled.width) / 2,
-      childRect.top + (childRect.size.height - sizeScaled.height) / 2,
-    );
-    return offsetScaled & sizeScaled;
-  }
-
-  static AlignmentDirectional getSheetAlignment(_ViewableLocation contextMenuLocation) {
-    switch (contextMenuLocation) {
-      case _ViewableLocation.center:
-        return AlignmentDirectional.topCenter;
-      case _ViewableLocation.right:
-        return AlignmentDirectional.topEnd;
-      case _ViewableLocation.left:
-        return AlignmentDirectional.topStart;
-    }
-  }
-
-  static Rect _getSheetRectBegin(Orientation? orientation, _ViewableLocation contextMenuLocation, Rect childRect, Rect sheetRect) {
-    switch (contextMenuLocation) {
-      case _ViewableLocation.center:
-        final Offset target = orientation == Orientation.portrait ? childRect.bottomCenter : childRect.topCenter;
-        final Offset centered = target - Offset(sheetRect.width / 2, 0.0);
-        return centered & sheetRect.size;
-      case _ViewableLocation.right:
-        final Offset target = orientation == Orientation.portrait ? childRect.bottomRight : childRect.topRight;
-        return (target - Offset(sheetRect.width, 0.0)) & sheetRect.size;
-      case _ViewableLocation.left:
-        final Offset target = orientation == Orientation.portrait ? childRect.bottomLeft : childRect.topLeft;
-        return target & sheetRect.size;
-    }
-  }
-
-  void _onDismiss(BuildContext context, double scale, double opacity) {
-    _scale = scale;
-    _opacityTween.end = opacity;
-    _sheetOpacity = _opacityTween.animate(CurvedAnimation(
-      parent: animation!,
-      curve: const Interval(0.9, 1.0),
-    ));
-    Navigator.of(context).pop();
-  }
-
-  void _updateTweenRects() {
-    final Rect childRect = _scale == null ? _getRect(_childGlobalKey) : _getScaledRect(_childGlobalKey, _scale!);
-    _rectTween.begin = _previousChildRect;
-    _rectTween.end = childRect;
-
-    final Rect childRectOriginal = Rect.fromCenter(
-      center: _previousChildRect.center,
-      width: _previousChildRect.width / _kOpenScale,
-      height: _previousChildRect.height / _kOpenScale,
-    );
-
-    final Rect sheetRect = _getRect(_sheetGlobalKey);
-    final Rect sheetRectBegin = _getSheetRectBegin(
-      _lastOrientation,
-      _contextMenuLocation,
-      childRectOriginal,
-      sheetRect,
-    );
-    _sheetRectTween.begin = sheetRectBegin;
-    _sheetRectTween.end = sheetRect;
-    _sheetScaleTween.begin = 0.0;
-    _sheetScaleTween.end = _scale;
-
-    _rectTweenReverse.begin = childRectOriginal;
-    _rectTweenReverse.end = childRect;
-  }
-
-  void _setOffstageInternally() {
-    super.offstage = _externalOffstage || _internalOffstage;
-
-    changedInternalState();
-  }
-
-  @override
-  bool didPop(T? result) {
-    _updateTweenRects();
-    return super.didPop(result);
-  }
-
-  @override
-  set offstage(bool value) {
-    _externalOffstage = value;
-    _setOffstageInternally();
-  }
-
-  @override
-  TickerFuture didPush() {
-    _internalOffstage = true;
-    _setOffstageInternally();
-
-    SchedulerBinding.instance.addPostFrameCallback((Duration _) {
-      _updateTweenRects();
-      _internalOffstage = false;
-      _setOffstageInternally();
-    });
-    return super.didPush();
-  }
-
-  @override
-  Animation<double> createAnimation() {
-    final Animation<double> animation = super.createAnimation();
-    _sheetOpacity = _opacityTween.animate(CurvedAnimation(
-      parent: animation,
-      curve: Curves.linear,
-    ));
-    return animation;
-  }
-
-  @override
-  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
-    return Container();
-  }
-
-  @override
-  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
-    return OrientationBuilder(
-      builder: (BuildContext context, Orientation orientation) {
-        _lastOrientation = orientation;
-
-        if (!animation.isCompleted) {
-          final bool reverse = animation.status == AnimationStatus.reverse;
-          final Rect rect = reverse ? _rectAnimatableReverse.evaluate(animation)! : _rectAnimatable.evaluate(animation)!;
-          final Rect sheetRect = reverse ? _sheetRectAnimatableReverse.evaluate(animation)! : _sheetRectAnimatable.evaluate(animation)!;
-          final double sheetScale = reverse ? _sheetScaleAnimatableReverse.evaluate(animation) : _sheetScaleAnimatable.evaluate(animation);
-          return Stack(
-            children: <Widget>[
-              Positioned.fromRect(
-                rect: sheetRect,
-                child: FadeTransition(
-                  opacity: _sheetOpacity,
-                  child: Transform.scale(
-                    alignment: getSheetAlignment(_contextMenuLocation),
-                    scale: sheetScale,
-                    child: _ViewableSheet(
-                      key: _sheetGlobalKey,
-                      actions: _actions,
-                    ),
-                  ),
-                ),
-              ),
-              Positioned.fromRect(
-                key: _childGlobalKey,
-                rect: rect,
-                child: _builder!(context, animation),
-              ),
-            ],
-          );
-        }
-
-        return _ContextMenuRouteStatic(
-          actions: _actions,
-          childGlobalKey: _childGlobalKey,
-          contextMenuLocation: _contextMenuLocation,
-          onDismiss: _onDismiss,
-          orientation: orientation,
-          sheetGlobalKey: _sheetGlobalKey,
-          child: _builder!(context, animation),
-        );
-      },
-    );
-  }
-}
-
-class _ContextMenuRouteStatic extends StatefulWidget {
-  const _ContextMenuRouteStatic({
-    Key? key,
-    this.actions,
-    required this.child,
-    this.childGlobalKey,
-    required this.contextMenuLocation,
-    this.onDismiss,
-    required this.orientation,
-    this.sheetGlobalKey,
-  }) : super(key: key);
-
-  final List<Widget>? actions;
-  final Widget child;
-  final GlobalKey? childGlobalKey;
-  final _ViewableLocation contextMenuLocation;
-  final _DismissCallback? onDismiss;
-  final Orientation orientation;
-  final GlobalKey? sheetGlobalKey;
-
-  @override
-  _ContextMenuRouteStaticState createState() => _ContextMenuRouteStaticState();
-}
-
-class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with TickerProviderStateMixin {
-  static const double _kMinScale = 0.8;
-
-  static const double _kSheetScaleThreshold = 0.9;
-  static const double _kPadding = 20.0;
-  static const double _kDamping = 400.0;
-  static const Duration _kMoveControllerDuration = Duration(milliseconds: 600);
-
-  late Offset _dragOffset;
-  double _lastScale = 1.0;
-  late AnimationController _moveController;
-  late AnimationController _sheetController;
-  late Animation<Offset> _moveAnimation;
-  late Animation<double> _sheetScaleAnimation;
-  late Animation<double> _sheetOpacityAnimation;
-
-  static double _getScale(Orientation orientation, double maxDragDistance, double dy) {
-    final double dyDirectional = dy <= 0.0 ? dy : -dy;
-    return math.max(
-      _kMinScale,
-      (maxDragDistance + dyDirectional) / maxDragDistance,
-    );
-  }
-
-  void _onPanStart(DragStartDetails details) {
-    _moveController.value = 1.0;
-    _setDragOffset(Offset.zero);
-  }
-
-  void _onPanUpdate(DragUpdateDetails details) {
-    _setDragOffset(_dragOffset + details.delta);
-  }
-
-  void _onPanEnd(DragEndDetails details) {
-    if (details.velocity.pixelsPerSecond.dy.abs() >= kMinFlingVelocity) {
-      final bool flingIsAway = details.velocity.pixelsPerSecond.dy > 0;
-      final double finalPosition = flingIsAway ? _moveAnimation.value.dy + 100.0 : 0.0;
-
-      if (flingIsAway && _sheetController.status != AnimationStatus.forward) {
-        _sheetController.forward();
-      } else if (!flingIsAway && _sheetController.status != AnimationStatus.reverse) {
-        _sheetController.reverse();
-      }
-
-      _moveAnimation = Tween<Offset>(
-        begin: Offset(0.0, _moveAnimation.value.dy),
-        end: Offset(0.0, finalPosition),
-      ).animate(_moveController);
-      _moveController.reset();
-      _moveController.duration = const Duration(
-        milliseconds: 64,
-      );
-      _moveController.forward();
-      _moveController.addStatusListener(_flingStatusListener);
-      return;
-    }
-
-    if (_lastScale == _kMinScale) {
-      widget.onDismiss!(context, _lastScale, _sheetOpacityAnimation.value);
-      return;
-    }
-
-    _moveController.addListener(_moveListener);
-    _moveController.reverse();
-  }
-
-  void _moveListener() {
-    if (_lastScale > _kSheetScaleThreshold) {
-      _moveController.removeListener(_moveListener);
-      if (_sheetController.status != AnimationStatus.dismissed) {
-        _sheetController.reverse();
-      }
-    }
-  }
-
-  void _flingStatusListener(AnimationStatus status) {
-    if (status != AnimationStatus.completed) {
-      return;
-    }
-
-    _moveController.duration = _kMoveControllerDuration;
-
-    _moveController.removeStatusListener(_flingStatusListener);
-
-    if (_moveAnimation.value.dy == 0.0) {
-      return;
-    }
-    widget.onDismiss!(context, _lastScale, _sheetOpacityAnimation.value);
-  }
-
-  Alignment _getChildAlignment(Orientation orientation, _ViewableLocation contextMenuLocation) {
-    switch (contextMenuLocation) {
-      case _ViewableLocation.center:
-        return orientation == Orientation.portrait ? Alignment.bottomCenter : Alignment.topRight;
-      case _ViewableLocation.right:
-        return orientation == Orientation.portrait ? Alignment.bottomCenter : Alignment.topLeft;
-      case _ViewableLocation.left:
-        return orientation == Orientation.portrait ? Alignment.bottomCenter : Alignment.topRight;
-    }
-  }
-
-  void _setDragOffset(Offset dragOffset) {
-    final double endX = _kPadding * dragOffset.dx / _kDamping;
-    final double endY = dragOffset.dy >= 0.0 ? dragOffset.dy : _kPadding * dragOffset.dy / _kDamping;
-    setState(() {
-      _dragOffset = dragOffset;
-      _moveAnimation = Tween<Offset>(
-        begin: Offset.zero,
-        end: Offset(
-          endX.clamp(-_kPadding, _kPadding),
-          endY,
-        ),
-      ).animate(
-        CurvedAnimation(
-          parent: _moveController,
-          curve: Curves.elasticIn,
-        ),
-      );
-
-      if (_lastScale <= _kSheetScaleThreshold && _sheetController.status != AnimationStatus.forward && _sheetScaleAnimation.value != 0.0) {
-        _sheetController.forward();
-      } else if (_lastScale > _kSheetScaleThreshold && _sheetController.status != AnimationStatus.reverse && _sheetScaleAnimation.value != 1.0) {
-        _sheetController.reverse();
-      }
-    });
-  }
-
-  List<Widget> _getChildren(Orientation orientation, _ViewableLocation contextMenuLocation) {
-    final Expanded child = Expanded(
-      child: Align(
-        alignment: _getChildAlignment(
-          widget.orientation,
-          widget.contextMenuLocation,
-        ),
-        child: AnimatedBuilder(
-          animation: _moveController,
-          builder: _buildChildAnimation,
-          child: widget.child,
-        ),
-      ),
-    );
-    const SizedBox spacer = SizedBox(
-      width: _kPadding,
-      height: _kPadding,
-    );
-    final sheet = AnimatedBuilder(
-      animation: _sheetController,
-      builder: _buildSheetAnimation,
-      child: _ViewableSheet(
-        key: widget.sheetGlobalKey,
-        actions: widget.actions!,
-      ),
-    );
-
-    switch (contextMenuLocation) {
-      case _ViewableLocation.center:
-        return <Widget>[child, spacer, sheet];
-      case _ViewableLocation.right:
-        return orientation == Orientation.portrait ? <Widget>[child, spacer, sheet] : <Widget>[sheet, spacer, child];
-      case _ViewableLocation.left:
-        return <Widget>[child, spacer, sheet];
-    }
-  }
-
-  Widget _buildSheetAnimation(BuildContext context, Widget? child) {
-    return Transform.scale(
-      alignment: _ViewableRoute.getSheetAlignment(widget.contextMenuLocation),
-      scale: _sheetScaleAnimation.value,
-      child: FadeTransition(
-        opacity: _sheetOpacityAnimation,
-        child: child,
-      ),
-    );
-  }
-
-  Widget _buildChildAnimation(BuildContext context, Widget? child) {
-    _lastScale = _getScale(
-      widget.orientation,
-      MediaQuery.of(context).size.height,
-      _moveAnimation.value.dy,
-    );
-    return Transform.scale(
-      key: widget.childGlobalKey,
-      scale: _lastScale,
-      child: child,
-    );
-  }
-
-  Widget _buildAnimation(BuildContext context, Widget? child) {
-    return Transform.translate(
-      offset: _moveAnimation.value,
-      child: child,
-    );
-  }
-
-  @override
-  void initState() {
-    super.initState();
-    _moveController = AnimationController(
-      duration: _kMoveControllerDuration,
-      value: 1.0,
-      vsync: this,
-    );
-    _sheetController = AnimationController(
-      duration: const Duration(milliseconds: 100),
-      reverseDuration: const Duration(milliseconds: 200),
-      vsync: this,
-    );
-    _sheetScaleAnimation = Tween<double>(
-      begin: 1.0,
-      end: 0.0,
-    ).animate(
-      CurvedAnimation(
-        parent: _sheetController,
-        curve: Curves.linear,
-        reverseCurve: Curves.easeInBack,
-      ),
-    );
-    _sheetOpacityAnimation = Tween<double>(
-      begin: 1.0,
-      end: 0.0,
-    ).animate(_sheetController);
-    _setDragOffset(Offset.zero);
-  }
-
-  @override
-  void dispose() {
-    _moveController.dispose();
-    _sheetController.dispose();
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final List<Widget> children = _getChildren(
-      widget.orientation,
-      widget.contextMenuLocation,
-    );
-
-    return SafeArea(
-      child: Padding(
-        padding: const EdgeInsets.all(_kPadding),
-        child: Align(
-          alignment: Alignment.topLeft,
-          child: GestureDetector(
-            onPanEnd: _onPanEnd,
-            onPanStart: _onPanStart,
-            onPanUpdate: _onPanUpdate,
-            child: AnimatedBuilder(
-              animation: _moveController,
-              builder: _buildAnimation,
-              child: widget.orientation == Orientation.portrait
-                  ? Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: children,
-                    )
-                  : Row(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: children,
-                    ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-class _ViewableSheet extends StatelessWidget {
-  const _ViewableSheet({
-    Key? key,
-    required this.actions,
-  }) : super(key: key);
-
-  final List<Widget> actions;
-
-  List<Widget> getChildren(BuildContext context) {
-    if (actions.isEmpty) return [];
-
-    final Widget menu = Expanded(
-      child: IntrinsicHeight(
-        child: ClipRRect(
-          borderRadius: const BorderRadius.all(Radius.circular(13.0)),
-          child: Column(
-            crossAxisAlignment: CrossAxisAlignment.stretch,
-            children: [
-              actions.first,
-              for (Widget action in actions.skip(1))
-                DecoratedBox(
-                  decoration: BoxDecoration(
-                    border: Border(
-                        top: BorderSide(
-                      color: CupertinoDynamicColor.resolve(_borderColor, context),
-                      width: 0.5,
-                    )),
-                  ),
-                  position: DecorationPosition.foreground,
-                  child: action,
-                ),
-            ],
-          ),
-        ),
-      ),
-    );
-
-    return [menu];
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: getChildren(context),
-    );
-  }
-}
-
-class _OnOffAnimation<T> extends CompoundAnimation<T> {
-  _OnOffAnimation({
-    required AnimationController controller,
-    required T onValue,
-    required T offValue,
-    required double intervalOn,
-    required double intervalOff,
-  })  : _offValue = offValue,
-        assert(intervalOn >= 0.0 && intervalOn <= 1.0),
-        assert(intervalOff >= 0.0 && intervalOff <= 1.0),
-        assert(intervalOn <= intervalOff),
-        super(
-          first: Tween<T>(begin: offValue, end: onValue).animate(
-            CurvedAnimation(
-              parent: controller,
-              curve: Interval(intervalOn, intervalOn),
-            ),
-          ),
-          next: Tween<T>(begin: onValue, end: offValue).animate(
-            CurvedAnimation(
-              parent: controller,
-              curve: Interval(intervalOff, intervalOff),
-            ),
-          ),
-        );
-
-  final T _offValue;
-
-  @override
-  T get value => next.value == _offValue ? next.value : first.value;
-}
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:math' as math;
+import 'dart:ui' as ui;
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/gestures.dart' show kMinFlingVelocity;
+import 'package:flutter/material.dart';
+import 'package:flutter/scheduler.dart';
+import 'package:flutter/services.dart';
+
+double valueFromPercentageInRange({required final double min, max, percentage}) {
+  return percentage * (max - min) + min;
+}
+
+double percentageFromValueInRange({required final double min, max, value}) {
+  return (value - min) / (max - min);
+}
+
+const double _kOpenScale = 1.025;
+
+const Color _borderColor = CupertinoDynamicColor.withBrightness(
+  color: Color(0xFFA9A9AF),
+  darkColor: Color(0xFF57585A),
+);
+
+typedef _DismissCallback = void Function(
+  BuildContext context,
+  double scale,
+  double opacity,
+);
+
+typedef ViewablePreviewBuilder = Widget Function(
+  BuildContext context,
+  Animation<double> animation,
+  Widget child,
+);
+
+typedef _ViewablePreviewBuilderChildless = Widget Function(
+  BuildContext context,
+  Animation<double> animation,
+);
+
+Rect _getRect(GlobalKey globalKey) {
+  assert(globalKey.currentContext != null);
+  final RenderBox renderBoxContainer = globalKey.currentContext!.findRenderObject()! as RenderBox;
+  final Offset containerOffset = renderBoxContainer.localToGlobal(
+    renderBoxContainer.paintBounds.topLeft,
+  );
+  return containerOffset & renderBoxContainer.paintBounds.size;
+}
+
+enum _ViewableLocation {
+  center,
+  left,
+  right,
+}
+
+class Viewable extends StatefulWidget {
+  const Viewable({
+    Key? key,
+    required this.view,
+    required this.tile,
+    this.actions = const [],
+    this.previewBuilder,
+  }) : super(key: key);
+
+  final Widget tile;
+  final Widget view;
+
+  final List<Widget> actions;
+
+  final ViewablePreviewBuilder? previewBuilder;
+
+  @override
+  State<Viewable> createState() => _ViewableState();
+}
+
+class _ViewableState extends State<Viewable> with TickerProviderStateMixin {
+  final GlobalKey _childGlobalKey = GlobalKey();
+  bool _childHidden = false;
+
+  late AnimationController _openController;
+  Rect? _decoyChildEndRect;
+  OverlayEntry? _lastOverlayEntry;
+  _ViewableRoute<void>? _route;
+
+  @override
+  void initState() {
+    super.initState();
+    _openController = AnimationController(
+      duration: const Duration(milliseconds: 100),
+      vsync: this,
+    );
+    _openController.addStatusListener(_onDecoyAnimationStatusChange);
+  }
+
+  _ViewableLocation get _contextMenuLocation {
+    final Rect childRect = _getRect(_childGlobalKey);
+    final double screenWidth = MediaQuery.of(context).size.width;
+
+    final double center = screenWidth / 2;
+    final bool centerDividesChild = childRect.left < center && childRect.right > center;
+    final double distanceFromCenter = (center - childRect.center.dx).abs();
+    if (centerDividesChild && distanceFromCenter <= childRect.width / 4) {
+      return _ViewableLocation.center;
+    }
+
+    if (childRect.center.dx > center) {
+      return _ViewableLocation.right;
+    }
+
+    return _ViewableLocation.left;
+  }
+
+  void _openContextMenu() {
+    setState(() {
+      _childHidden = true;
+    });
+
+    _route = _ViewableRoute<void>(
+      actions: widget.actions,
+      barrierLabel: 'Dismiss',
+      filter: ui.ImageFilter.blur(
+        sigmaX: 5.0,
+        sigmaY: 5.0,
+      ),
+      contextMenuLocation: _contextMenuLocation,
+      previousChildRect: _decoyChildEndRect!,
+      builder: (BuildContext context, Animation<double> animation) {
+        return ClipRRect(
+          borderRadius: BorderRadius.circular(16.0),
+          child: Material(
+            color: Theme.of(context).colorScheme.background,
+            borderRadius: BorderRadius.circular(16.0),
+            child: Stack(
+              children: [
+                Opacity(
+                  opacity: animation.status == AnimationStatus.forward
+                      ? Curves.easeOutCirc.transform(animation.value)
+                      : Curves.easeInCirc.transform(animation.value),
+                  child: widget.view,
+                ),
+                Opacity(
+                  opacity: 1 -
+                      (animation.status == AnimationStatus.forward
+                          ? Curves.easeOutCirc.transform(animation.value)
+                          : Curves.easeInCirc.transform(animation.value)),
+                  child: widget.tile,
+                ),
+              ],
+            ),
+          ),
+        );
+      },
+    );
+    Navigator.of(context, rootNavigator: true).push<void>(_route!);
+    _route!.animation!.addStatusListener(_routeAnimationStatusListener);
+  }
+
+  void _onDecoyAnimationStatusChange(AnimationStatus animationStatus) {
+    switch (animationStatus) {
+      case AnimationStatus.dismissed:
+        if (_route == null) {
+          setState(() {
+            _childHidden = false;
+          });
+        }
+        _lastOverlayEntry?.remove();
+        _lastOverlayEntry = null;
+        break;
+
+      case AnimationStatus.completed:
+        setState(() {
+          _childHidden = true;
+        });
+        _openContextMenu();
+
+        SchedulerBinding.instance.addPostFrameCallback((Duration _) {
+          _lastOverlayEntry?.remove();
+          _lastOverlayEntry = null;
+          _openController.reset();
+        });
+        break;
+
+      case AnimationStatus.forward:
+      case AnimationStatus.reverse:
+        return;
+    }
+  }
+
+  void _routeAnimationStatusListener(AnimationStatus status) {
+    if (status != AnimationStatus.dismissed) {
+      return;
+    }
+    setState(() {
+      _childHidden = false;
+    });
+    _route!.animation!.removeStatusListener(_routeAnimationStatusListener);
+    _route = null;
+  }
+
+  void _onTap() {
+    _onTapDown(TapDownDetails(), anim: false);
+  }
+
+  void _onTapDown(TapDownDetails details, {anim = true}) {
+    setState(() {
+      _childHidden = true;
+    });
+
+    final Rect childRect = _getRect(_childGlobalKey);
+    _decoyChildEndRect = Rect.fromCenter(
+      center: childRect.center,
+      width: childRect.width * _kOpenScale,
+      height: childRect.height * _kOpenScale,
+    );
+
+    _lastOverlayEntry = OverlayEntry(
+      builder: (BuildContext context) {
+        return _DecoyChild(
+          beginRect: childRect,
+          controller: _openController,
+          endRect: _decoyChildEndRect,
+          child: widget.tile,
+        );
+      },
+    );
+    Overlay.of(context, rootOverlay: true).insert(_lastOverlayEntry!);
+    _openController.forward(from: anim ? 0.0 : 1.0);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(
+      onTap: _onTap,
+      child: TickerMode(
+        enabled: !_childHidden,
+        child: Opacity(
+          key: _childGlobalKey,
+          opacity: _childHidden ? 0.0 : 1.0,
+          child: widget.tile,
+        ),
+      ),
+    );
+  }
+
+  @override
+  void dispose() {
+    _openController.dispose();
+    super.dispose();
+  }
+}
+
+class _DecoyChild extends StatefulWidget {
+  const _DecoyChild({
+    Key? key,
+    this.beginRect,
+    required this.controller,
+    this.endRect,
+    this.child,
+  }) : super(key: key);
+
+  final Rect? beginRect;
+  final AnimationController controller;
+  final Rect? endRect;
+  final Widget? child;
+
+  @override
+  _DecoyChildState createState() => _DecoyChildState();
+}
+
+class _DecoyChildState extends State<_DecoyChild> with TickerProviderStateMixin {
+  static const Color _lightModeMaskColor = Color(0xFF888888);
+  static const Color _masklessColor = Color(0xFFFFFFFF);
+
+  final GlobalKey _childGlobalKey = GlobalKey();
+  late Animation<Color> _mask;
+  late Animation<Rect?> _rect;
+
+  @override
+  void initState() {
+    super.initState();
+
+    _mask = _OnOffAnimation<Color>(
+      controller: widget.controller,
+      onValue: _lightModeMaskColor,
+      offValue: _masklessColor,
+      intervalOn: 0.0,
+      intervalOff: 0.5,
+    );
+
+    final Rect midRect = widget.beginRect!.deflate(
+      widget.beginRect!.width * (_kOpenScale - 1.0) / 2,
+    );
+    _rect = TweenSequence<Rect?>(<TweenSequenceItem<Rect?>>[
+      TweenSequenceItem<Rect?>(
+        tween: RectTween(
+          begin: widget.beginRect,
+          end: midRect,
+        ).chain(CurveTween(curve: Curves.easeInOutCubic)),
+        weight: 1.0,
+      ),
+      TweenSequenceItem<Rect?>(
+        tween: RectTween(
+          begin: midRect,
+          end: widget.endRect,
+        ).chain(CurveTween(curve: Curves.easeOutCubic)),
+        weight: 1.0,
+      ),
+    ]).animate(widget.controller);
+    _rect.addListener(_rectListener);
+  }
+
+  void _rectListener() {
+    if (widget.controller.value < 0.5) {
+      return;
+    }
+    HapticFeedback.selectionClick();
+    _rect.removeListener(_rectListener);
+  }
+
+  @override
+  void dispose() {
+    _rect.removeListener(_rectListener);
+    super.dispose();
+  }
+
+  Widget _buildAnimation(BuildContext context, Widget? child) {
+    final Color color = widget.controller.status == AnimationStatus.reverse ? _masklessColor : _mask.value;
+    return Positioned.fromRect(
+      rect: _rect.value!,
+      child: ShaderMask(
+        key: _childGlobalKey,
+        shaderCallback: (Rect bounds) {
+          return LinearGradient(
+            begin: Alignment.topLeft,
+            end: Alignment.bottomRight,
+            colors: <Color>[color, color],
+          ).createShader(bounds);
+        },
+        child: widget.child,
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: <Widget>[
+        AnimatedBuilder(
+          builder: _buildAnimation,
+          animation: widget.controller,
+        ),
+      ],
+    );
+  }
+}
+
+class _ViewableRoute<T> extends PopupRoute<T> {
+  _ViewableRoute({
+    required List<Widget> actions,
+    required _ViewableLocation contextMenuLocation,
+    this.barrierLabel,
+    _ViewablePreviewBuilderChildless? builder,
+    ui.ImageFilter? filter,
+    required Rect previousChildRect,
+    RouteSettings? settings,
+  })  : _actions = actions,
+        _builder = builder,
+        _contextMenuLocation = contextMenuLocation,
+        _previousChildRect = previousChildRect,
+        super(
+          filter: filter,
+          settings: settings,
+        );
+
+  static const Color _kModalBarrierColor = Color(0x6604040F);
+
+  static const Duration _kModalPopupTransitionDuration = Duration(milliseconds: 335);
+
+  final List<Widget> _actions;
+  final _ViewablePreviewBuilderChildless? _builder;
+  final GlobalKey _childGlobalKey = GlobalKey();
+  final _ViewableLocation _contextMenuLocation;
+  bool _externalOffstage = false;
+  bool _internalOffstage = false;
+  Orientation? _lastOrientation;
+
+  final Rect _previousChildRect;
+  double? _scale = 1.0;
+  final GlobalKey _sheetGlobalKey = GlobalKey();
+
+  static final CurveTween _curve = CurveTween(
+    curve: Curves.easeOutBack,
+  );
+  static final CurveTween _curveReverse = CurveTween(
+    curve: Curves.easeInBack,
+  );
+  static final RectTween _rectTween = RectTween();
+  static final Animatable<Rect?> _rectAnimatable = _rectTween.chain(_curve);
+  static final RectTween _rectTweenReverse = RectTween();
+  static final Animatable<Rect?> _rectAnimatableReverse = _rectTweenReverse.chain(
+    _curveReverse,
+  );
+  static final RectTween _sheetRectTween = RectTween();
+  final Animatable<Rect?> _sheetRectAnimatable = _sheetRectTween.chain(
+    _curve,
+  );
+  final Animatable<Rect?> _sheetRectAnimatableReverse = _sheetRectTween.chain(
+    _curveReverse,
+  );
+  static final Tween<double> _sheetScaleTween = Tween<double>();
+  static final Animatable<double> _sheetScaleAnimatable = _sheetScaleTween.chain(
+    _curve,
+  );
+  static final Animatable<double> _sheetScaleAnimatableReverse = _sheetScaleTween.chain(
+    _curveReverse,
+  );
+  final Tween<double> _opacityTween = Tween<double>(begin: 0.0, end: 1.0);
+  late Animation<double> _sheetOpacity;
+
+  @override
+  final String? barrierLabel;
+
+  @override
+  Color get barrierColor => _kModalBarrierColor;
+
+  @override
+  bool get barrierDismissible => true;
+
+  @override
+  bool get semanticsDismissible => false;
+
+  @override
+  Duration get transitionDuration => _kModalPopupTransitionDuration;
+
+  static Rect _getScaledRect(GlobalKey globalKey, double scale) {
+    final Rect childRect = _getRect(globalKey);
+    final Size sizeScaled = childRect.size * scale;
+    final Offset offsetScaled = Offset(
+      childRect.left + (childRect.size.width - sizeScaled.width) / 2,
+      childRect.top + (childRect.size.height - sizeScaled.height) / 2,
+    );
+    return offsetScaled & sizeScaled;
+  }
+
+  static AlignmentDirectional getSheetAlignment(_ViewableLocation contextMenuLocation) {
+    switch (contextMenuLocation) {
+      case _ViewableLocation.center:
+        return AlignmentDirectional.topCenter;
+      case _ViewableLocation.right:
+        return AlignmentDirectional.topEnd;
+      case _ViewableLocation.left:
+        return AlignmentDirectional.topStart;
+    }
+  }
+
+  static Rect _getSheetRectBegin(Orientation? orientation, _ViewableLocation contextMenuLocation, Rect childRect, Rect sheetRect) {
+    switch (contextMenuLocation) {
+      case _ViewableLocation.center:
+        final Offset target = orientation == Orientation.portrait ? childRect.bottomCenter : childRect.topCenter;
+        final Offset centered = target - Offset(sheetRect.width / 2, 0.0);
+        return centered & sheetRect.size;
+      case _ViewableLocation.right:
+        final Offset target = orientation == Orientation.portrait ? childRect.bottomRight : childRect.topRight;
+        return (target - Offset(sheetRect.width, 0.0)) & sheetRect.size;
+      case _ViewableLocation.left:
+        final Offset target = orientation == Orientation.portrait ? childRect.bottomLeft : childRect.topLeft;
+        return target & sheetRect.size;
+    }
+  }
+
+  void _onDismiss(BuildContext context, double scale, double opacity) {
+    _scale = scale;
+    _opacityTween.end = opacity;
+    _sheetOpacity = _opacityTween.animate(CurvedAnimation(
+      parent: animation!,
+      curve: const Interval(0.9, 1.0),
+    ));
+    Navigator.of(context).pop();
+  }
+
+  void _updateTweenRects() {
+    final Rect childRect = _scale == null ? _getRect(_childGlobalKey) : _getScaledRect(_childGlobalKey, _scale!);
+    _rectTween.begin = _previousChildRect;
+    _rectTween.end = childRect;
+
+    final Rect childRectOriginal = Rect.fromCenter(
+      center: _previousChildRect.center,
+      width: _previousChildRect.width / _kOpenScale,
+      height: _previousChildRect.height / _kOpenScale,
+    );
+
+    final Rect sheetRect = _getRect(_sheetGlobalKey);
+    final Rect sheetRectBegin = _getSheetRectBegin(
+      _lastOrientation,
+      _contextMenuLocation,
+      childRectOriginal,
+      sheetRect,
+    );
+    _sheetRectTween.begin = sheetRectBegin;
+    _sheetRectTween.end = sheetRect;
+    _sheetScaleTween.begin = 0.0;
+    _sheetScaleTween.end = _scale;
+
+    _rectTweenReverse.begin = childRectOriginal;
+    _rectTweenReverse.end = childRect;
+  }
+
+  void _setOffstageInternally() {
+    super.offstage = _externalOffstage || _internalOffstage;
+
+    changedInternalState();
+  }
+
+  @override
+  bool didPop(T? result) {
+    _updateTweenRects();
+    return super.didPop(result);
+  }
+
+  @override
+  set offstage(bool value) {
+    _externalOffstage = value;
+    _setOffstageInternally();
+  }
+
+  @override
+  TickerFuture didPush() {
+    _internalOffstage = true;
+    _setOffstageInternally();
+
+    SchedulerBinding.instance.addPostFrameCallback((Duration _) {
+      _updateTweenRects();
+      _internalOffstage = false;
+      _setOffstageInternally();
+    });
+    return super.didPush();
+  }
+
+  @override
+  Animation<double> createAnimation() {
+    final Animation<double> animation = super.createAnimation();
+    _sheetOpacity = _opacityTween.animate(CurvedAnimation(
+      parent: animation,
+      curve: Curves.linear,
+    ));
+    return animation;
+  }
+
+  @override
+  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
+    return Container();
+  }
+
+  @override
+  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
+    return OrientationBuilder(
+      builder: (BuildContext context, Orientation orientation) {
+        _lastOrientation = orientation;
+
+        if (!animation.isCompleted) {
+          final bool reverse = animation.status == AnimationStatus.reverse;
+          final Rect rect = reverse ? _rectAnimatableReverse.evaluate(animation)! : _rectAnimatable.evaluate(animation)!;
+          final Rect sheetRect = reverse ? _sheetRectAnimatableReverse.evaluate(animation)! : _sheetRectAnimatable.evaluate(animation)!;
+          final double sheetScale = reverse ? _sheetScaleAnimatableReverse.evaluate(animation) : _sheetScaleAnimatable.evaluate(animation);
+          return Stack(
+            children: <Widget>[
+              Positioned.fromRect(
+                rect: sheetRect,
+                child: FadeTransition(
+                  opacity: _sheetOpacity,
+                  child: Transform.scale(
+                    alignment: getSheetAlignment(_contextMenuLocation),
+                    scale: sheetScale,
+                    child: _ViewableSheet(
+                      key: _sheetGlobalKey,
+                      actions: _actions,
+                    ),
+                  ),
+                ),
+              ),
+              Positioned.fromRect(
+                key: _childGlobalKey,
+                rect: rect,
+                child: _builder!(context, animation),
+              ),
+            ],
+          );
+        }
+
+        return _ContextMenuRouteStatic(
+          actions: _actions,
+          childGlobalKey: _childGlobalKey,
+          contextMenuLocation: _contextMenuLocation,
+          onDismiss: _onDismiss,
+          orientation: orientation,
+          sheetGlobalKey: _sheetGlobalKey,
+          child: _builder!(context, animation),
+        );
+      },
+    );
+  }
+}
+
+class _ContextMenuRouteStatic extends StatefulWidget {
+  const _ContextMenuRouteStatic({
+    Key? key,
+    this.actions,
+    required this.child,
+    this.childGlobalKey,
+    required this.contextMenuLocation,
+    this.onDismiss,
+    required this.orientation,
+    this.sheetGlobalKey,
+  }) : super(key: key);
+
+  final List<Widget>? actions;
+  final Widget child;
+  final GlobalKey? childGlobalKey;
+  final _ViewableLocation contextMenuLocation;
+  final _DismissCallback? onDismiss;
+  final Orientation orientation;
+  final GlobalKey? sheetGlobalKey;
+
+  @override
+  _ContextMenuRouteStaticState createState() => _ContextMenuRouteStaticState();
+}
+
+class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with TickerProviderStateMixin {
+  static const double _kMinScale = 0.8;
+
+  static const double _kSheetScaleThreshold = 0.9;
+  static const double _kPadding = 20.0;
+  static const double _kDamping = 400.0;
+  static const Duration _kMoveControllerDuration = Duration(milliseconds: 600);
+
+  late Offset _dragOffset;
+  double _lastScale = 1.0;
+  late AnimationController _moveController;
+  late AnimationController _sheetController;
+  late Animation<Offset> _moveAnimation;
+  late Animation<double> _sheetScaleAnimation;
+  late Animation<double> _sheetOpacityAnimation;
+
+  static double _getScale(Orientation orientation, double maxDragDistance, double dy) {
+    final double dyDirectional = dy <= 0.0 ? dy : -dy;
+    return math.max(
+      _kMinScale,
+      (maxDragDistance + dyDirectional) / maxDragDistance,
+    );
+  }
+
+  void _onPanStart(DragStartDetails details) {
+    _moveController.value = 1.0;
+    _setDragOffset(Offset.zero);
+  }
+
+  void _onPanUpdate(DragUpdateDetails details) {
+    _setDragOffset(_dragOffset + details.delta);
+  }
+
+  void _onPanEnd(DragEndDetails details) {
+    if (details.velocity.pixelsPerSecond.dy.abs() >= kMinFlingVelocity) {
+      final bool flingIsAway = details.velocity.pixelsPerSecond.dy > 0;
+      final double finalPosition = flingIsAway ? _moveAnimation.value.dy + 100.0 : 0.0;
+
+      if (flingIsAway && _sheetController.status != AnimationStatus.forward) {
+        _sheetController.forward();
+      } else if (!flingIsAway && _sheetController.status != AnimationStatus.reverse) {
+        _sheetController.reverse();
+      }
+
+      _moveAnimation = Tween<Offset>(
+        begin: Offset(0.0, _moveAnimation.value.dy),
+        end: Offset(0.0, finalPosition),
+      ).animate(_moveController);
+      _moveController.reset();
+      _moveController.duration = const Duration(
+        milliseconds: 64,
+      );
+      _moveController.forward();
+      _moveController.addStatusListener(_flingStatusListener);
+      return;
+    }
+
+    if (_lastScale == _kMinScale) {
+      widget.onDismiss!(context, _lastScale, _sheetOpacityAnimation.value);
+      return;
+    }
+
+    _moveController.addListener(_moveListener);
+    _moveController.reverse();
+  }
+
+  void _moveListener() {
+    if (_lastScale > _kSheetScaleThreshold) {
+      _moveController.removeListener(_moveListener);
+      if (_sheetController.status != AnimationStatus.dismissed) {
+        _sheetController.reverse();
+      }
+    }
+  }
+
+  void _flingStatusListener(AnimationStatus status) {
+    if (status != AnimationStatus.completed) {
+      return;
+    }
+
+    _moveController.duration = _kMoveControllerDuration;
+
+    _moveController.removeStatusListener(_flingStatusListener);
+
+    if (_moveAnimation.value.dy == 0.0) {
+      return;
+    }
+    widget.onDismiss!(context, _lastScale, _sheetOpacityAnimation.value);
+  }
+
+  Alignment _getChildAlignment(Orientation orientation, _ViewableLocation contextMenuLocation) {
+    switch (contextMenuLocation) {
+      case _ViewableLocation.center:
+        return orientation == Orientation.portrait ? Alignment.bottomCenter : Alignment.topRight;
+      case _ViewableLocation.right:
+        return orientation == Orientation.portrait ? Alignment.bottomCenter : Alignment.topLeft;
+      case _ViewableLocation.left:
+        return orientation == Orientation.portrait ? Alignment.bottomCenter : Alignment.topRight;
+    }
+  }
+
+  void _setDragOffset(Offset dragOffset) {
+    final double endX = _kPadding * dragOffset.dx / _kDamping;
+    final double endY = dragOffset.dy >= 0.0 ? dragOffset.dy : _kPadding * dragOffset.dy / _kDamping;
+    setState(() {
+      _dragOffset = dragOffset;
+      _moveAnimation = Tween<Offset>(
+        begin: Offset.zero,
+        end: Offset(
+          endX.clamp(-_kPadding, _kPadding),
+          endY,
+        ),
+      ).animate(
+        CurvedAnimation(
+          parent: _moveController,
+          curve: Curves.elasticIn,
+        ),
+      );
+
+      if (_lastScale <= _kSheetScaleThreshold && _sheetController.status != AnimationStatus.forward && _sheetScaleAnimation.value != 0.0) {
+        _sheetController.forward();
+      } else if (_lastScale > _kSheetScaleThreshold && _sheetController.status != AnimationStatus.reverse && _sheetScaleAnimation.value != 1.0) {
+        _sheetController.reverse();
+      }
+    });
+  }
+
+  List<Widget> _getChildren(Orientation orientation, _ViewableLocation contextMenuLocation) {
+    final Expanded child = Expanded(
+      child: Align(
+        alignment: _getChildAlignment(
+          widget.orientation,
+          widget.contextMenuLocation,
+        ),
+        child: AnimatedBuilder(
+          animation: _moveController,
+          builder: _buildChildAnimation,
+          child: widget.child,
+        ),
+      ),
+    );
+    const SizedBox spacer = SizedBox(
+      width: _kPadding,
+      height: _kPadding,
+    );
+    final sheet = AnimatedBuilder(
+      animation: _sheetController,
+      builder: _buildSheetAnimation,
+      child: _ViewableSheet(
+        key: widget.sheetGlobalKey,
+        actions: widget.actions!,
+      ),
+    );
+
+    switch (contextMenuLocation) {
+      case _ViewableLocation.center:
+        return <Widget>[child, spacer, sheet];
+      case _ViewableLocation.right:
+        return orientation == Orientation.portrait ? <Widget>[child, spacer, sheet] : <Widget>[sheet, spacer, child];
+      case _ViewableLocation.left:
+        return <Widget>[child, spacer, sheet];
+    }
+  }
+
+  Widget _buildSheetAnimation(BuildContext context, Widget? child) {
+    return Transform.scale(
+      alignment: _ViewableRoute.getSheetAlignment(widget.contextMenuLocation),
+      scale: _sheetScaleAnimation.value,
+      child: FadeTransition(
+        opacity: _sheetOpacityAnimation,
+        child: child,
+      ),
+    );
+  }
+
+  Widget _buildChildAnimation(BuildContext context, Widget? child) {
+    _lastScale = _getScale(
+      widget.orientation,
+      MediaQuery.of(context).size.height,
+      _moveAnimation.value.dy,
+    );
+    return Transform.scale(
+      key: widget.childGlobalKey,
+      scale: _lastScale,
+      child: child,
+    );
+  }
+
+  Widget _buildAnimation(BuildContext context, Widget? child) {
+    return Transform.translate(
+      offset: _moveAnimation.value,
+      child: child,
+    );
+  }
+
+  @override
+  void initState() {
+    super.initState();
+    _moveController = AnimationController(
+      duration: _kMoveControllerDuration,
+      value: 1.0,
+      vsync: this,
+    );
+    _sheetController = AnimationController(
+      duration: const Duration(milliseconds: 100),
+      reverseDuration: const Duration(milliseconds: 200),
+      vsync: this,
+    );
+    _sheetScaleAnimation = Tween<double>(
+      begin: 1.0,
+      end: 0.0,
+    ).animate(
+      CurvedAnimation(
+        parent: _sheetController,
+        curve: Curves.linear,
+        reverseCurve: Curves.easeInBack,
+      ),
+    );
+    _sheetOpacityAnimation = Tween<double>(
+      begin: 1.0,
+      end: 0.0,
+    ).animate(_sheetController);
+    _setDragOffset(Offset.zero);
+  }
+
+  @override
+  void dispose() {
+    _moveController.dispose();
+    _sheetController.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> children = _getChildren(
+      widget.orientation,
+      widget.contextMenuLocation,
+    );
+
+    return SafeArea(
+      child: Padding(
+        padding: const EdgeInsets.all(_kPadding),
+        child: Align(
+          alignment: Alignment.topLeft,
+          child: GestureDetector(
+            onPanEnd: _onPanEnd,
+            onPanStart: _onPanStart,
+            onPanUpdate: _onPanUpdate,
+            child: AnimatedBuilder(
+              animation: _moveController,
+              builder: _buildAnimation,
+              child: widget.orientation == Orientation.portrait
+                  ? Column(
+                      crossAxisAlignment: CrossAxisAlignment.start,
+                      children: children,
+                    )
+                  : Row(
+                      crossAxisAlignment: CrossAxisAlignment.start,
+                      children: children,
+                    ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class _ViewableSheet extends StatelessWidget {
+  const _ViewableSheet({
+    Key? key,
+    required this.actions,
+  }) : super(key: key);
+
+  final List<Widget> actions;
+
+  List<Widget> getChildren(BuildContext context) {
+    if (actions.isEmpty) return [];
+
+    final Widget menu = Expanded(
+      child: IntrinsicHeight(
+        child: ClipRRect(
+          borderRadius: const BorderRadius.all(Radius.circular(13.0)),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.stretch,
+            children: [
+              actions.first,
+              for (Widget action in actions.skip(1))
+                DecoratedBox(
+                  decoration: BoxDecoration(
+                    border: Border(
+                        top: BorderSide(
+                      color: CupertinoDynamicColor.resolve(_borderColor, context),
+                      width: 0.5,
+                    )),
+                  ),
+                  position: DecorationPosition.foreground,
+                  child: action,
+                ),
+            ],
+          ),
+        ),
+      ),
+    );
+
+    return [menu];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: getChildren(context),
+    );
+  }
+}
+
+class _OnOffAnimation<T> extends CompoundAnimation<T> {
+  _OnOffAnimation({
+    required AnimationController controller,
+    required T onValue,
+    required T offValue,
+    required double intervalOn,
+    required double intervalOff,
+  })  : _offValue = offValue,
+        assert(intervalOn >= 0.0 && intervalOn <= 1.0),
+        assert(intervalOff >= 0.0 && intervalOff <= 1.0),
+        assert(intervalOn <= intervalOff),
+        super(
+          first: Tween<T>(begin: offValue, end: onValue).animate(
+            CurvedAnimation(
+              parent: controller,
+              curve: Interval(intervalOn, intervalOn),
+            ),
+          ),
+          next: Tween<T>(begin: onValue, end: offValue).animate(
+            CurvedAnimation(
+              parent: controller,
+              curve: Interval(intervalOff, intervalOff),
+            ),
+          ),
+        );
+
+  final T _offValue;
+
+  @override
+  T get value => next.value == _offValue ? next.value : first.value;
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_display.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_display.dart
old mode 100755
new mode 100644
similarity index 73%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_display.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_display.dart
index b0fd86d..2339145
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_display.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_display.dart
@@ -1,50 +1,57 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-class AbsenceDisplay extends StatelessWidget {
-  const AbsenceDisplay(this.excused, this.unexcused, this.pending, {Key? key}) : super(key: key);
-
-  final int excused;
-  final int unexcused;
-  final int pending;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      padding: const EdgeInsets.only(top: 5.0),
-      // padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0),
-      // decoration: BoxDecoration(
-      //   color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.2),
-      //   borderRadius: BorderRadius.circular(12.0),
-      // ),
-      child: Row(children: [
-        if (excused > 0)
-          Icon(
-            FeatherIcons.check,
-            size: 16.0,
-            color: AppColors.of(context).green,
-          ),
-        if (excused > 0) const SizedBox(width: 2.0),
-        if (excused > 0) Text(excused.toString(), style: const TextStyle(fontFamily: "monospace", fontSize: 14.0)),
-        if (excused > 0 && pending > 0) const SizedBox(width: 6.0),
-        if (pending > 0)
-          Icon(
-            FeatherIcons.slash,
-            size: 14.0,
-            color: AppColors.of(context).orange,
-          ),
-        if (pending > 0) const SizedBox(width: 3.0),
-        if (pending > 0) Text(pending.toString(), style: const TextStyle(fontFamily: "monospace", fontSize: 14.0)),
-        if (unexcused > 0 && pending > 0) const SizedBox(width: 3.0),
-        if (unexcused > 0)
-          Icon(
-            FeatherIcons.x,
-            size: 18.0,
-            color: AppColors.of(context).red,
-          ),
-        if (unexcused > 0) Text(unexcused.toString(), style: const TextStyle(fontFamily: "monospace", fontSize: 14.0)),
-      ]),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+class AbsenceDisplay extends StatelessWidget {
+  const AbsenceDisplay(this.excused, this.unexcused, this.pending, {Key? key})
+      : super(key: key);
+
+  final int excused;
+  final int unexcused;
+  final int pending;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.only(top: 5.0),
+      // padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0),
+      // decoration: BoxDecoration(
+      //   color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.2),
+      //   borderRadius: BorderRadius.circular(12.0),
+      // ),
+      child: Row(children: [
+        if (excused > 0)
+          Icon(
+            FeatherIcons.check,
+            size: 16.0,
+            color: AppColors.of(context).green,
+          ),
+        if (excused > 0) const SizedBox(width: 2.0),
+        if (excused > 0)
+          Text(excused.toString(),
+              style: const TextStyle(fontFamily: "monospace", fontSize: 14.0)),
+        if (excused > 0 && pending > 0) const SizedBox(width: 6.0),
+        if (pending > 0)
+          Icon(
+            FeatherIcons.slash,
+            size: 14.0,
+            color: AppColors.of(context).orange,
+          ),
+        if (pending > 0) const SizedBox(width: 3.0),
+        if (pending > 0)
+          Text(pending.toString(),
+              style: const TextStyle(fontFamily: "monospace", fontSize: 14.0)),
+        if (unexcused > 0 && pending > 0) const SizedBox(width: 3.0),
+        if (unexcused > 0)
+          Icon(
+            FeatherIcons.x,
+            size: 18.0,
+            color: AppColors.of(context).red,
+          ),
+        if (unexcused > 0)
+          Text(unexcused.toString(),
+              style: const TextStyle(fontFamily: "monospace", fontSize: 14.0)),
+      ]),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_subject_tile.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_subject_tile.dart
old mode 100755
new mode 100644
similarity index 66%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_subject_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_subject_tile.dart
index c8fc05d..ba567ce
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_subject_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_subject_tile.dart
@@ -1,83 +1,100 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_display.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class AbsenceSubjectTile extends StatelessWidget {
-  const AbsenceSubjectTile(this.subject, {Key? key, this.percentage = 0.0, this.excused = 0, this.unexcused = 0, this.pending = 0, this.onTap})
-      : super(key: key);
-
-  final Subject subject;
-  final void Function()? onTap;
-  final double percentage;
-
-  final int excused;
-  final int unexcused;
-  final int pending;
-
-  @override
-  Widget build(BuildContext context) {
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-    return Material(
-      type: MaterialType.transparency,
-      child: ListTile(
-        // minLeadingWidth: 32.0,
-        dense: true,
-        contentPadding: const EdgeInsets.only(left: 8.0, right: 6.0),
-        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-        visualDensity: VisualDensity.compact,
-        onTap: onTap,
-        leading: Icon(SubjectIcon.resolveVariant(subject: subject, context: context), size: 32.0),
-        title: Text(
-          subject.renamedTo ?? subject.name.capital(),
-          maxLines: 2,
-          overflow: TextOverflow.ellipsis,
-          style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15.0, fontStyle: subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
-        ),
-        subtitle: AbsenceDisplay(excused, unexcused, pending),
-        trailing: Row(
-          mainAxisSize: MainAxisSize.min,
-          children: [
-            const SizedBox(width: 8.0),
-            if (percentage >= 0)
-              Stack(
-                alignment: Alignment.centerRight,
-                children: [
-                  const Opacity(child: Text("100%", style: TextStyle(fontFamily: "monospace")), opacity: 0),
-                  Text(
-                    percentage.round().toString() + "%",
-                    style: TextStyle(
-                      // fontFamily: "monospace",
-                      color: getColorByPercentage(percentage, context: context),
-                      fontWeight: FontWeight.w700,
-                      fontSize: 24.0,
-                    ),
-                  ),
-                ],
-              ),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-Color getColorByPercentage(double percentage, {required BuildContext context}) {
-  Color color = AppColors.of(context).text;
-
-  percentage = percentage.round().toDouble();
-
-  if (percentage > 35) {
-    color = AppColors.of(context).red;
-  } else if (percentage > 25) {
-    color = AppColors.of(context).orange;
-  } else if (percentage > 15) {
-    color = AppColors.of(context).yellow;
-  }
-
-  return color.withOpacity(.8);
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_display.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class AbsenceSubjectTile extends StatelessWidget {
+  const AbsenceSubjectTile(this.subject,
+      {Key? key,
+      this.percentage = 0.0,
+      this.excused = 0,
+      this.unexcused = 0,
+      this.pending = 0,
+      this.onTap})
+      : super(key: key);
+
+  final Subject subject;
+  final void Function()? onTap;
+  final double percentage;
+
+  final int excused;
+  final int unexcused;
+  final int pending;
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+    return Material(
+      type: MaterialType.transparency,
+      child: ListTile(
+        // minLeadingWidth: 32.0,
+        dense: true,
+        contentPadding: const EdgeInsets.only(left: 8.0, right: 6.0),
+        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+        visualDensity: VisualDensity.compact,
+        onTap: onTap,
+        leading: Icon(
+            SubjectIcon.resolveVariant(subject: subject, context: context),
+            size: 32.0),
+        title: Text(
+          subject.renamedTo ?? subject.name.capital(),
+          maxLines: 2,
+          overflow: TextOverflow.ellipsis,
+          style: TextStyle(
+              fontWeight: FontWeight.w600,
+              fontSize: 15.0,
+              fontStyle:
+                  subject.isRenamed && settingsProvider.renamedSubjectsItalics
+                      ? FontStyle.italic
+                      : null),
+        ),
+        subtitle: AbsenceDisplay(excused, unexcused, pending),
+        trailing: Row(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            const SizedBox(width: 8.0),
+            if (percentage >= 0)
+              Stack(
+                alignment: Alignment.centerRight,
+                children: [
+                  const Opacity(
+                      child: Text("100%",
+                          style: TextStyle(fontFamily: "monospace")),
+                      opacity: 0),
+                  Text(
+                    percentage.round().toString() + "%",
+                    style: TextStyle(
+                      // fontFamily: "monospace",
+                      color: getColorByPercentage(percentage, context: context),
+                      fontWeight: FontWeight.w700,
+                      fontSize: 24.0,
+                    ),
+                  ),
+                ],
+              ),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+Color getColorByPercentage(double percentage, {required BuildContext context}) {
+  Color color = AppColors.of(context).text;
+
+  percentage = percentage.round().toDouble();
+
+  if (percentage > 35) {
+    color = AppColors.of(context).red;
+  } else if (percentage > 25) {
+    color = AppColors.of(context).orange;
+  } else if (percentage > 15) {
+    color = AppColors.of(context).yellow;
+  }
+
+  return color.withOpacity(.8);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_tile.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_tile.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_tile.dart
index b01e8e7..ec73860
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_tile.dart
@@ -1,151 +1,151 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_container.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'absence_tile.i18n.dart';
-
-class AbsenceTile extends StatelessWidget {
-  const AbsenceTile(this.absence,
-      {Key? key, this.onTap, this.elevation = 0.0, this.padding})
-      : super(key: key);
-
-  final Absence absence;
-  final void Function()? onTap;
-  final double elevation;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    Color color = justificationColor(absence.state, context: context);
-    bool group = AbsenceGroupContainer.of(context) != null;
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    return Container(
-      decoration: BoxDecoration(
-        boxShadow: [
-          if (elevation > 0)
-            BoxShadow(
-              offset: Offset(0, 21 * elevation),
-              blurRadius: 23.0 * elevation,
-              color: Theme.of(context).shadowColor,
-            )
-        ],
-        borderRadius: BorderRadius.circular(14.0),
-      ),
-      child: Material(
-        type: MaterialType.transparency,
-        child: Padding(
-          padding: padding ??
-              (group
-                  ? EdgeInsets.zero
-                  : const EdgeInsets.symmetric(
-                      horizontal: 8.0,
-                    )),
-          child: ListTile(
-            onTap: onTap,
-            visualDensity: VisualDensity.compact,
-            dense: group,
-            contentPadding: const EdgeInsets.only(
-                left: 14.0, right: 12.0, top: 2.0, bottom: 2.0),
-            shape: RoundedRectangleBorder(
-                borderRadius: BorderRadius.circular(!group ? 14.0 : 12.0)),
-            leading: Container(
-              width: 44.0,
-              decoration: BoxDecoration(
-                shape: BoxShape.circle,
-                color: !group ? color.withOpacity(.25) : null,
-              ),
-              child: Center(
-                  child: Icon(justificationIcon(absence.state), color: color)),
-            ),
-            title: !group
-                ? Text.rich(TextSpan(
-                    text: "${absence.delay == 0 ? "" : absence.delay}",
-                    style: const TextStyle(
-                        fontWeight: FontWeight.w700, fontSize: 15.5),
-                    children: [
-                      TextSpan(
-                        text: absence.delay == 0
-                            ? justificationName(absence.state)
-                                .fill(["absence".i18n]).capital()
-                            : 'minute'.plural(absence.delay) +
-                                justificationName(absence.state)
-                                    .fill(["delay".i18n]),
-                        style: const TextStyle(fontWeight: FontWeight.w600),
-                      ),
-                    ],
-                  ))
-                : Text(
-                    (absence.lessonIndex != null
-                            ? "${absence.lessonIndex}. "
-                            : "") +
-                        (absence.subject.renamedTo ??
-                            absence.subject.name.capital()),
-                    maxLines: 2,
-                    overflow: TextOverflow.ellipsis,
-                    style: TextStyle(
-                        fontWeight: FontWeight.w500,
-                        fontSize: 14.0,
-                        fontStyle: absence.subject.isRenamed &&
-                                settingsProvider.renamedSubjectsItalics
-                            ? FontStyle.italic
-                            : null),
-                  ),
-            subtitle: !group
-                ? Text(
-                    absence.subject.renamedTo ?? absence.subject.name.capital(),
-                    maxLines: 2,
-                    overflow: TextOverflow.ellipsis,
-                    // DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
-                    style: TextStyle(
-                        fontWeight: FontWeight.w500,
-                        fontStyle: absence.subject.isRenamed &&
-                                settingsProvider.renamedSubjectsItalics
-                            ? FontStyle.italic
-                            : null),
-                  )
-                : null,
-          ),
-        ),
-      ),
-    );
-  }
-
-  static String justificationName(Justification state) {
-    switch (state) {
-      case Justification.excused:
-        return "excused".i18n;
-      case Justification.pending:
-        return "pending".i18n;
-      case Justification.unexcused:
-        return "unexcused".i18n;
-    }
-  }
-
-  static Color justificationColor(Justification state,
-      {required BuildContext context}) {
-    switch (state) {
-      case Justification.excused:
-        return AppColors.of(context).green;
-      case Justification.pending:
-        return AppColors.of(context).orange;
-      case Justification.unexcused:
-        return AppColors.of(context).red;
-    }
-  }
-
-  static IconData justificationIcon(Justification state) {
-    switch (state) {
-      case Justification.excused:
-        return FeatherIcons.check;
-      case Justification.pending:
-        return FeatherIcons.slash;
-      case Justification.unexcused:
-        return FeatherIcons.x;
-    }
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence_group/absence_group_container.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'absence_tile.i18n.dart';
+
+class AbsenceTile extends StatelessWidget {
+  const AbsenceTile(this.absence,
+      {Key? key, this.onTap, this.elevation = 0.0, this.padding})
+      : super(key: key);
+
+  final Absence absence;
+  final void Function()? onTap;
+  final double elevation;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    Color color = justificationColor(absence.state, context: context);
+    bool group = AbsenceGroupContainer.of(context) != null;
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    return Container(
+      decoration: BoxDecoration(
+        boxShadow: [
+          if (elevation > 0)
+            BoxShadow(
+              offset: Offset(0, 21 * elevation),
+              blurRadius: 23.0 * elevation,
+              color: Theme.of(context).shadowColor,
+            )
+        ],
+        borderRadius: BorderRadius.circular(14.0),
+      ),
+      child: Material(
+        type: MaterialType.transparency,
+        child: Padding(
+          padding: padding ??
+              (group
+                  ? EdgeInsets.zero
+                  : const EdgeInsets.symmetric(
+                      horizontal: 8.0,
+                    )),
+          child: ListTile(
+            onTap: onTap,
+            visualDensity: VisualDensity.compact,
+            dense: group,
+            contentPadding: const EdgeInsets.only(
+                left: 14.0, right: 12.0, top: 2.0, bottom: 2.0),
+            shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(!group ? 14.0 : 12.0)),
+            leading: Container(
+              width: 44.0,
+              decoration: BoxDecoration(
+                shape: BoxShape.circle,
+                color: !group ? color.withOpacity(.25) : null,
+              ),
+              child: Center(
+                  child: Icon(justificationIcon(absence.state), color: color)),
+            ),
+            title: !group
+                ? Text.rich(TextSpan(
+                    text: "${absence.delay == 0 ? "" : absence.delay}",
+                    style: const TextStyle(
+                        fontWeight: FontWeight.w700, fontSize: 15.5),
+                    children: [
+                      TextSpan(
+                        text: absence.delay == 0
+                            ? justificationName(absence.state)
+                                .fill(["absence".i18n]).capital()
+                            : 'minute'.plural(absence.delay) +
+                                justificationName(absence.state)
+                                    .fill(["delay".i18n]),
+                        style: const TextStyle(fontWeight: FontWeight.w600),
+                      ),
+                    ],
+                  ))
+                : Text(
+                    (absence.lessonIndex != null
+                            ? "${absence.lessonIndex}. "
+                            : "") +
+                        (absence.subject.renamedTo ??
+                            absence.subject.name.capital()),
+                    maxLines: 2,
+                    overflow: TextOverflow.ellipsis,
+                    style: TextStyle(
+                        fontWeight: FontWeight.w500,
+                        fontSize: 14.0,
+                        fontStyle: absence.subject.isRenamed &&
+                                settingsProvider.renamedSubjectsItalics
+                            ? FontStyle.italic
+                            : null),
+                  ),
+            subtitle: !group
+                ? Text(
+                    absence.subject.renamedTo ?? absence.subject.name.capital(),
+                    maxLines: 2,
+                    overflow: TextOverflow.ellipsis,
+                    // DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
+                    style: TextStyle(
+                        fontWeight: FontWeight.w500,
+                        fontStyle: absence.subject.isRenamed &&
+                                settingsProvider.renamedSubjectsItalics
+                            ? FontStyle.italic
+                            : null),
+                  )
+                : null,
+          ),
+        ),
+      ),
+    );
+  }
+
+  static String justificationName(Justification state) {
+    switch (state) {
+      case Justification.excused:
+        return "excused".i18n;
+      case Justification.pending:
+        return "pending".i18n;
+      case Justification.unexcused:
+        return "unexcused".i18n;
+    }
+  }
+
+  static Color justificationColor(Justification state,
+      {required BuildContext context}) {
+    switch (state) {
+      case Justification.excused:
+        return AppColors.of(context).green;
+      case Justification.pending:
+        return AppColors.of(context).orange;
+      case Justification.unexcused:
+        return AppColors.of(context).red;
+    }
+  }
+
+  static IconData justificationIcon(Justification state) {
+    switch (state) {
+      case Justification.excused:
+        return FeatherIcons.check;
+      case Justification.pending:
+        return FeatherIcons.slash;
+      case Justification.unexcused:
+        return FeatherIcons.x;
+    }
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_tile.i18n.dart
index 2b0c105..515cda1
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_tile.i18n.dart
@@ -1,36 +1,36 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "excused": "excused %s",
-          "pending": "%s to be excused",
-          "unexcused": "unexcused %s",
-          "absence": "absence",
-          "delay": "delay",
-          "minute": " minutes of ".one(" minute of "),
-        },
-        "hu_hu": {
-          "excused": "igazolt %s",
-          "pending": "igazolandó %s",
-          "unexcused": "igazolatlan %s",
-          "absence": "hiányzás",
-          "delay": "késés",
-          "minute": " perc ",
-        },
-        "de_de": {
-          "excused": "anerkannt %s",
-          "pending": "%s zu anerkennen",
-          "unexcused": "unanerkannt %s",
-          "absence": "Abwesenheit",
-          "delay": "Verspätung",
-          "minute": " Minuten ".one(" Minute "),
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "excused": "excused %s",
+          "pending": "%s to be excused",
+          "unexcused": "unexcused %s",
+          "absence": "absence",
+          "delay": "delay",
+          "minute": " minutes of ".one(" minute of "),
+        },
+        "hu_hu": {
+          "excused": "igazolt %s",
+          "pending": "igazolandó %s",
+          "unexcused": "igazolatlan %s",
+          "absence": "hiányzás",
+          "delay": "késés",
+          "minute": " perc ",
+        },
+        "de_de": {
+          "excused": "anerkannt %s",
+          "pending": "%s zu anerkennen",
+          "unexcused": "unanerkannt %s",
+          "absence": "Abwesenheit",
+          "delay": "Verspätung",
+          "minute": " Minuten ".one(" Minute "),
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_view.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_view.dart
old mode 100755
new mode 100644
similarity index 86%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_view.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_view.dart
index 23ec169..a8925ff
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_view.dart
@@ -1,156 +1,156 @@
-// ignore_for_file: empty_catches
-
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_card.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/detail.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_action_button.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:filcnaplo/utils/reverse_search.dart';
-import 'package:provider/provider.dart';
-import 'absence_view.i18n.dart';
-
-class AbsenceView extends StatelessWidget {
-  const AbsenceView(this.absence,
-      {Key? key, this.outsideContext, this.viewable = false})
-      : super(key: key);
-
-  final Absence absence;
-  final BuildContext? outsideContext;
-  final bool viewable;
-
-  static show(Absence absence, {required BuildContext context}) {
-    showBottomCard(
-        context: context, child: AbsenceView(absence, outsideContext: context));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    Color color =
-        AbsenceTile.justificationColor(absence.state, context: context);
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          ListTile(
-            visualDensity: VisualDensity.compact,
-            contentPadding: const EdgeInsets.only(left: 16.0, right: 12.0),
-            shape: RoundedRectangleBorder(
-                borderRadius: BorderRadius.circular(8.0)),
-            leading: Container(
-              width: 44.0,
-              height: 44.0,
-              decoration: BoxDecoration(
-                shape: BoxShape.circle,
-                color: color.withOpacity(.25),
-              ),
-              child: Center(
-                child: Icon(
-                  AbsenceTile.justificationIcon(absence.state),
-                  color: color,
-                ),
-              ),
-            ),
-            title: Text(
-              absence.subject.renamedTo ?? absence.subject.name.capital(),
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: TextStyle(
-                  fontWeight: FontWeight.w700,
-                  fontStyle: absence.subject.isRenamed &&
-                          settingsProvider.renamedSubjectsItalics
-                      ? FontStyle.italic
-                      : null),
-            ),
-            subtitle: Text(
-              (absence.teacher.isRenamed
-                      ? absence.teacher.renamedTo
-                      : absence.teacher.name) ??
-                  '',
-              // DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-            trailing: Text(
-              absence.date.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Absence Details
-          if (absence.delay > 0)
-            Detail(
-              title: "delay".i18n,
-              description: absence.delay.toString() +
-                  " " +
-                  "minutes".i18n.plural(absence.delay),
-            ),
-          if (absence.lessonIndex != null)
-            Detail(
-              title: "Lesson".i18n,
-              description:
-                  "${absence.lessonIndex}. (${absence.lessonStart.format(context, timeOnly: true)}"
-                  " - "
-                  "${absence.lessonEnd.format(context, timeOnly: true)})",
-            ),
-          if (absence.justification != null)
-            Detail(
-              title: "Excuse".i18n,
-              description: absence.justification?.description ?? "",
-            ),
-          if (absence.mode != null)
-            Detail(
-                title: "Mode".i18n,
-                description: absence.mode?.description ?? ""),
-          Detail(
-              title: "Submit date".i18n,
-              description: absence.submitDate.format(context)),
-
-          // Show in timetable
-          if (!viewable)
-            Padding(
-              padding: const EdgeInsets.only(
-                  left: 16.0, right: 16.0, bottom: 6.0, top: 12.0),
-              child: PanelActionButton(
-                leading: const Icon(FeatherIcons.calendar),
-                title: Text(
-                  "show in timetable".i18n,
-                  maxLines: 2,
-                  overflow: TextOverflow.ellipsis,
-                ),
-                onPressed: () {
-                  Navigator.of(context).pop();
-
-                  if (outsideContext != null) {
-                    ReverseSearch.getLessonByAbsence(absence, context)
-                        .then((lesson) {
-                      if (lesson != null) {
-                        TimetablePage.jump(outsideContext!, lesson: lesson);
-                      } else {
-                        ScaffoldMessenger.of(context)
-                            .showSnackBar(CustomSnackBar(
-                          content: Text("Cannot find lesson".i18n,
-                              style: const TextStyle(color: Colors.white)),
-                          backgroundColor: AppColors.of(context).red,
-                          context: context,
-                        ));
-                      }
-                    });
-                  }
-                },
-              ),
-            ),
-        ],
-      ),
-    );
-  }
-}
+// ignore_for_file: empty_catches
+
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_mobile_ui/common/bottom_card.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_mobile_ui/common/detail.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_action_button.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_tile.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:refilc/utils/reverse_search.dart';
+import 'package:provider/provider.dart';
+import 'absence_view.i18n.dart';
+
+class AbsenceView extends StatelessWidget {
+  const AbsenceView(this.absence,
+      {Key? key, this.outsideContext, this.viewable = false})
+      : super(key: key);
+
+  final Absence absence;
+  final BuildContext? outsideContext;
+  final bool viewable;
+
+  static show(Absence absence, {required BuildContext context}) {
+    showBottomCard(
+        context: context, child: AbsenceView(absence, outsideContext: context));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Color color =
+        AbsenceTile.justificationColor(absence.state, context: context);
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          ListTile(
+            visualDensity: VisualDensity.compact,
+            contentPadding: const EdgeInsets.only(left: 16.0, right: 12.0),
+            shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(8.0)),
+            leading: Container(
+              width: 44.0,
+              height: 44.0,
+              decoration: BoxDecoration(
+                shape: BoxShape.circle,
+                color: color.withOpacity(.25),
+              ),
+              child: Center(
+                child: Icon(
+                  AbsenceTile.justificationIcon(absence.state),
+                  color: color,
+                ),
+              ),
+            ),
+            title: Text(
+              absence.subject.renamedTo ?? absence.subject.name.capital(),
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: TextStyle(
+                  fontWeight: FontWeight.w700,
+                  fontStyle: absence.subject.isRenamed &&
+                          settingsProvider.renamedSubjectsItalics
+                      ? FontStyle.italic
+                      : null),
+            ),
+            subtitle: Text(
+              (absence.teacher.isRenamed
+                      ? absence.teacher.renamedTo
+                      : absence.teacher.name) ??
+                  '',
+              // DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+            trailing: Text(
+              absence.date.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Absence Details
+          if (absence.delay > 0)
+            Detail(
+              title: "delay".i18n,
+              description: absence.delay.toString() +
+                  " " +
+                  "minutes".i18n.plural(absence.delay),
+            ),
+          if (absence.lessonIndex != null)
+            Detail(
+              title: "Lesson".i18n,
+              description:
+                  "${absence.lessonIndex}. (${absence.lessonStart.format(context, timeOnly: true)}"
+                  " - "
+                  "${absence.lessonEnd.format(context, timeOnly: true)})",
+            ),
+          if (absence.justification != null)
+            Detail(
+              title: "Excuse".i18n,
+              description: absence.justification?.description ?? "",
+            ),
+          if (absence.mode != null)
+            Detail(
+                title: "Mode".i18n,
+                description: absence.mode?.description ?? ""),
+          Detail(
+              title: "Submit date".i18n,
+              description: absence.submitDate.format(context)),
+
+          // Show in timetable
+          if (!viewable)
+            Padding(
+              padding: const EdgeInsets.only(
+                  left: 16.0, right: 16.0, bottom: 6.0, top: 12.0),
+              child: PanelActionButton(
+                leading: const Icon(FeatherIcons.calendar),
+                title: Text(
+                  "show in timetable".i18n,
+                  maxLines: 2,
+                  overflow: TextOverflow.ellipsis,
+                ),
+                onPressed: () {
+                  Navigator.of(context).pop();
+
+                  if (outsideContext != null) {
+                    ReverseSearch.getLessonByAbsence(absence, context)
+                        .then((lesson) {
+                      if (lesson != null) {
+                        TimetablePage.jump(outsideContext!, lesson: lesson);
+                      } else {
+                        ScaffoldMessenger.of(context)
+                            .showSnackBar(CustomSnackBar(
+                          content: Text("Cannot find lesson".i18n,
+                              style: const TextStyle(color: Colors.white)),
+                          backgroundColor: AppColors.of(context).red,
+                          context: context,
+                        ));
+                      }
+                    });
+                  }
+                },
+              ),
+            ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_view.i18n.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_view.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_view.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_view.i18n.dart
index 66e7eb7..3af7d33
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_view.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_view.i18n.dart
@@ -1,39 +1,39 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Lesson": "Lesson",
-          "Excuse": "Excuse",
-          "Mode": "Mode",
-          "Submit date": "Submit Date",
-          "show in timetable": "Show in timetable",
-          "minutes": "minutes".one("minute"),
-          "delay": "Delay",
-        },
-        "hu_hu": {
-          "Lesson": "Óra",
-          "Excuse": "Igazolás",
-          "Mode": "Típus",
-          "Submit date": "Rögzítés dátuma",
-          "show in timetable": "Megtekintés az órarendben",
-          "minutes": "perc",
-          "delay": "Késés",
-        },
-        "de_de": {
-          "Lesson": "Stunde",
-          "Excuse": "Anerkannt",
-          "Mode": "Typ",
-          "Submit date": "Datum einreichen",
-          "show in timetable": "im Stundenplan anzeigen",
-          "minutes": "Minuten".one("Minute"),
-          "delay": "Verspätung",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Lesson": "Lesson",
+          "Excuse": "Excuse",
+          "Mode": "Mode",
+          "Submit date": "Submit Date",
+          "show in timetable": "Show in timetable",
+          "minutes": "minutes".one("minute"),
+          "delay": "Delay",
+        },
+        "hu_hu": {
+          "Lesson": "Óra",
+          "Excuse": "Igazolás",
+          "Mode": "Típus",
+          "Submit date": "Rögzítés dátuma",
+          "show in timetable": "Megtekintés az órarendben",
+          "minutes": "perc",
+          "delay": "Késés",
+        },
+        "de_de": {
+          "Lesson": "Stunde",
+          "Excuse": "Anerkannt",
+          "Mode": "Typ",
+          "Submit date": "Datum einreichen",
+          "show in timetable": "im Stundenplan anzeigen",
+          "minutes": "Minuten".one("Minute"),
+          "delay": "Verspätung",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_viewable.dart b/refilc_mobile_ui/lib/common/widgets/absence/absence_viewable.dart
old mode 100755
new mode 100644
similarity index 60%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence/absence_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/absence/absence_viewable.dart
index 4eda2b4..fe75595
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence/absence_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence/absence_viewable.dart
@@ -1,68 +1,71 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:filcnaplo_mobile_ui/common/viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_view.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_container.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/card_handle.dart';
-import 'package:filcnaplo_mobile_ui/pages/absences/absence_subject_view_container.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/reverse_search.dart';
-
-import 'absence_view.i18n.dart';
-
-class AbsenceViewable extends StatelessWidget {
-  const AbsenceViewable(this.absence, {Key? key, this.padding}) : super(key: key);
-
-  final Absence absence;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    final subject = AbsenceSubjectViewContainer.of(context) != null;
-    final group = AbsenceGroupContainer.of(context) != null;
-    final tile = AbsenceTile(absence, padding: padding);
-
-    return Viewable(
-      tile: group ? AbsenceGroupContainer(child: tile) : tile,
-      view: CardHandle(child: AbsenceView(absence, viewable: true)),
-      actions: [
-        PanelButton(
-          background: true,
-          title: Text(
-            "show in timetable".i18n,
-            textAlign: TextAlign.center,
-            maxLines: 2,
-            overflow: TextOverflow.ellipsis,
-          ),
-          onPressed: () {
-            Navigator.of(context, rootNavigator: true).pop();
-
-            if (subject) {
-              Future.delayed(const Duration(milliseconds: 250)).then((_) {
-                Navigator.of(context, rootNavigator: true).pop(absence);
-              });
-            } else {
-              Future.delayed(const Duration(milliseconds: 250)).then((_) {
-                ReverseSearch.getLessonByAbsence(absence, context).then((lesson) {
-                  if (lesson != null) {
-                    TimetablePage.jump(context, lesson: lesson);
-                  } else {
-                    ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
-                      content: Text("Cannot find lesson".i18n, style: const TextStyle(color: Colors.white)),
-                      backgroundColor: AppColors.of(context).red,
-                      context: context,
-                    ));
-                  }
-                });
-              });
-            }
-          },
-        ),
-      ],
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_mobile_ui/common/viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_view.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence_group/absence_group_container.dart';
+import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
+import 'package:refilc_mobile_ui/pages/absences/absence_subject_view_container.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/reverse_search.dart';
+
+import 'absence_view.i18n.dart';
+
+class AbsenceViewable extends StatelessWidget {
+  const AbsenceViewable(this.absence, {Key? key, this.padding})
+      : super(key: key);
+
+  final Absence absence;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    final subject = AbsenceSubjectViewContainer.of(context) != null;
+    final group = AbsenceGroupContainer.of(context) != null;
+    final tile = AbsenceTile(absence, padding: padding);
+
+    return Viewable(
+      tile: group ? AbsenceGroupContainer(child: tile) : tile,
+      view: CardHandle(child: AbsenceView(absence, viewable: true)),
+      actions: [
+        PanelButton(
+          background: true,
+          title: Text(
+            "show in timetable".i18n,
+            textAlign: TextAlign.center,
+            maxLines: 2,
+            overflow: TextOverflow.ellipsis,
+          ),
+          onPressed: () {
+            Navigator.of(context, rootNavigator: true).pop();
+
+            if (subject) {
+              Future.delayed(const Duration(milliseconds: 250)).then((_) {
+                Navigator.of(context, rootNavigator: true).pop(absence);
+              });
+            } else {
+              Future.delayed(const Duration(milliseconds: 250)).then((_) {
+                ReverseSearch.getLessonByAbsence(absence, context)
+                    .then((lesson) {
+                  if (lesson != null) {
+                    TimetablePage.jump(context, lesson: lesson);
+                  } else {
+                    ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
+                      content: Text("Cannot find lesson".i18n,
+                          style: const TextStyle(color: Colors.white)),
+                      backgroundColor: AppColors.of(context).red,
+                      context: context,
+                    ));
+                  }
+                });
+              });
+            }
+          },
+        ),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_container.dart b/refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_container.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_container.dart
rename to refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_container.dart
index 1b225e1..6b42750
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_container.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_container.dart
@@ -1,10 +1,10 @@
-import 'package:flutter/material.dart';
-
-class AbsenceGroupContainer extends InheritedWidget {
-  const AbsenceGroupContainer({Key? key, required Widget child}) : super(key: key, child: child);
-
-  static AbsenceGroupContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<AbsenceGroupContainer>();
-
-  @override
-  bool updateShouldNotify(AbsenceGroupContainer oldWidget) => false;
-}
+import 'package:flutter/material.dart';
+
+class AbsenceGroupContainer extends InheritedWidget {
+  const AbsenceGroupContainer({Key? key, required Widget child}) : super(key: key, child: child);
+
+  static AbsenceGroupContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<AbsenceGroupContainer>();
+
+  @override
+  bool updateShouldNotify(AbsenceGroupContainer oldWidget) => false;
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart b/refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
old mode 100755
new mode 100644
similarity index 87%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
index 62e8b45..daf7cef
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
@@ -1,103 +1,103 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_container.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:rounded_expansion_tile/rounded_expansion_tile.dart';
-import 'absence_group_tile.i18n.dart';
-
-class AbsenceGroupTile extends StatelessWidget {
-  const AbsenceGroupTile(this.absences,
-      {Key? key, this.showDate = false, this.padding})
-      : super(key: key);
-
-  final List<AbsenceViewable> absences;
-  final bool showDate;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    Justification state =
-        getState(absences.map((e) => e.absence.state).toList());
-    Color color = AbsenceTile.justificationColor(state, context: context);
-
-    absences.sort((a, b) =>
-        a.absence.lessonIndex?.compareTo(b.absence.lessonIndex ?? 0) ?? -1);
-
-    return ClipRRect(
-      borderRadius: BorderRadius.circular(14.0),
-      child: Material(
-        type: MaterialType.transparency,
-        child: Padding(
-          padding: padding ??
-              const EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0),
-          child: AbsenceGroupContainer(
-            child: RoundedExpansionTile(
-              shape: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(10)),
-              childrenPadding: const EdgeInsets.symmetric(horizontal: 8.0),
-              tileColor: Colors.transparent,
-              duration: const Duration(milliseconds: 250),
-              trailingDuration: 0.5,
-              trailing: const Icon(FeatherIcons.chevronDown),
-              leading: Container(
-                width: 44.0,
-                height: 44.0,
-                decoration: BoxDecoration(
-                  shape: BoxShape.circle,
-                  color: color.withOpacity(.25),
-                ),
-                child: Center(
-                    child: Icon(AbsenceTile.justificationIcon(state),
-                        color: color)),
-              ),
-              title: Text.rich(TextSpan(
-                text:
-                    "${absences.where((a) => a.absence.state == state).length} ",
-                style: TextStyle(
-                    fontWeight: FontWeight.w700,
-                    color: AppColors.of(context).text),
-                children: [
-                  TextSpan(
-                    text: AbsenceTile.justificationName(state)
-                        .fill(["absence".i18n]),
-                    style: TextStyle(
-                        fontWeight: FontWeight.w600,
-                        color: AppColors.of(context).text),
-                  ),
-                ],
-              )),
-              subtitle: showDate
-                  ? Text(
-                      absences.first.absence.date
-                          .format(context, weekday: true),
-                      style: TextStyle(
-                          fontWeight: FontWeight.w500,
-                          color: AppColors.of(context).text.withOpacity(0.8)),
-                    )
-                  : null,
-              children: absences,
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  static Justification getState(List<Justification> states) {
-    Justification state;
-
-    if (states.any((element) => element == Justification.unexcused)) {
-      state = Justification.unexcused;
-    } else if (states.any((element) => element == Justification.pending)) {
-      state = Justification.pending;
-    } else {
-      state = Justification.excused;
-    }
-
-    return state;
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence_group/absence_group_container.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_tile.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:rounded_expansion_tile/rounded_expansion_tile.dart';
+import 'absence_group_tile.i18n.dart';
+
+class AbsenceGroupTile extends StatelessWidget {
+  const AbsenceGroupTile(this.absences,
+      {Key? key, this.showDate = false, this.padding})
+      : super(key: key);
+
+  final List<AbsenceViewable> absences;
+  final bool showDate;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    Justification state =
+        getState(absences.map((e) => e.absence.state).toList());
+    Color color = AbsenceTile.justificationColor(state, context: context);
+
+    absences.sort((a, b) =>
+        a.absence.lessonIndex?.compareTo(b.absence.lessonIndex ?? 0) ?? -1);
+
+    return ClipRRect(
+      borderRadius: BorderRadius.circular(14.0),
+      child: Material(
+        type: MaterialType.transparency,
+        child: Padding(
+          padding: padding ??
+              const EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0),
+          child: AbsenceGroupContainer(
+            child: RoundedExpansionTile(
+              shape: RoundedRectangleBorder(
+                  borderRadius: BorderRadius.circular(10)),
+              childrenPadding: const EdgeInsets.symmetric(horizontal: 8.0),
+              tileColor: Colors.transparent,
+              duration: const Duration(milliseconds: 250),
+              trailingDuration: 0.5,
+              trailing: const Icon(FeatherIcons.chevronDown),
+              leading: Container(
+                width: 44.0,
+                height: 44.0,
+                decoration: BoxDecoration(
+                  shape: BoxShape.circle,
+                  color: color.withOpacity(.25),
+                ),
+                child: Center(
+                    child: Icon(AbsenceTile.justificationIcon(state),
+                        color: color)),
+              ),
+              title: Text.rich(TextSpan(
+                text:
+                    "${absences.where((a) => a.absence.state == state).length} ",
+                style: TextStyle(
+                    fontWeight: FontWeight.w700,
+                    color: AppColors.of(context).text),
+                children: [
+                  TextSpan(
+                    text: AbsenceTile.justificationName(state)
+                        .fill(["absence".i18n]),
+                    style: TextStyle(
+                        fontWeight: FontWeight.w600,
+                        color: AppColors.of(context).text),
+                  ),
+                ],
+              )),
+              subtitle: showDate
+                  ? Text(
+                      absences.first.absence.date
+                          .format(context, weekday: true),
+                      style: TextStyle(
+                          fontWeight: FontWeight.w500,
+                          color: AppColors.of(context).text.withOpacity(0.8)),
+                    )
+                  : null,
+              children: absences,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  static Justification getState(List<Justification> states) {
+    Justification state;
+
+    if (states.any((element) => element == Justification.unexcused)) {
+      state = Justification.unexcused;
+    } else if (states.any((element) => element == Justification.pending)) {
+      state = Justification.pending;
+    } else {
+      state = Justification.excused;
+    }
+
+    return state;
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.i18n.dart
index 16d29e2..0b121f6
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.i18n.dart
@@ -1,21 +1,21 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "absence": "absences",
-        },
-        "hu_hu": {
-          "absence": "hiányzás",
-        },
-        "de_de": {
-          "absence": "Fehlen",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "absence": "absences",
+        },
+        "hu_hu": {
+          "absence": "hiányzás",
+        },
+        "de_de": {
+          "absence": "Fehlen",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart b/refilc_mobile_ui/lib/common/widgets/ad/ad_tile.dart
similarity index 89%
rename from filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/ad/ad_tile.dart
index 12add1b..d796a68 100644
--- a/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/ad/ad_tile.dart
@@ -1,7 +1,7 @@
-import 'package:filcnaplo/models/ad.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
+import 'package:refilc/models/ad.dart';
+import 'package:refilc/theme/colors/colors.dart';
 import 'package:flutter/material.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
 
 class AdTile extends StatelessWidget {
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_viewable.dart b/refilc_mobile_ui/lib/common/widgets/ad/ad_viewable.dart
similarity index 90%
rename from filcnaplo_mobile_ui/lib/common/widgets/ad/ad_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/ad/ad_viewable.dart
index fa7ed4a..6aa27f7 100644
--- a/filcnaplo_mobile_ui/lib/common/widgets/ad/ad_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/ad/ad_viewable.dart
@@ -1,4 +1,4 @@
-import 'package:filcnaplo/models/ad.dart';
+import 'package:refilc/models/ad.dart';
 import 'package:flutter/material.dart';
 import 'package:url_launcher/url_launcher.dart';
 
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/card_handle.dart b/refilc_mobile_ui/lib/common/widgets/card_handle.dart
old mode 100755
new mode 100644
similarity index 89%
rename from filcnaplo_mobile_ui/lib/common/widgets/card_handle.dart
rename to refilc_mobile_ui/lib/common/widgets/card_handle.dart
index fb4fb5f..ad02d04
--- a/filcnaplo_mobile_ui/lib/common/widgets/card_handle.dart
+++ b/refilc_mobile_ui/lib/common/widgets/card_handle.dart
@@ -1,27 +1,27 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class CardHandle extends StatelessWidget {
-  const CardHandle({Key? key, this.child}) : super(key: key);
-
-  final Widget? child;
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      children: [
-        Container(
-          width: 42.0,
-          height: 4.0,
-          margin: const EdgeInsets.only(top: 12.0),
-          decoration: BoxDecoration(
-            borderRadius: BorderRadius.circular(45.0),
-            color: AppColors.of(context).text.withOpacity(0.10),
-          ),
-        ),
-        if (child != null) child!,
-      ],
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class CardHandle extends StatelessWidget {
+  const CardHandle({Key? key, this.child}) : super(key: key);
+
+  final Widget? child;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        Container(
+          width: 42.0,
+          height: 4.0,
+          margin: const EdgeInsets.only(top: 12.0),
+          decoration: BoxDecoration(
+            borderRadius: BorderRadius.circular(45.0),
+            color: AppColors.of(context).text.withOpacity(0.10),
+          ),
+        ),
+        if (child != null) child!,
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_card.dart b/refilc_mobile_ui/lib/common/widgets/cretification/certification_card.dart
old mode 100755
new mode 100644
similarity index 73%
rename from filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_card.dart
rename to refilc_mobile_ui/lib/common/widgets/cretification/certification_card.dart
index c9bedd8..d9a0673
--- a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_card.dart
+++ b/refilc_mobile_ui/lib/common/widgets/cretification/certification_card.dart
@@ -1,108 +1,115 @@
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_view.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'certification_card.i18n.dart';
-
-class CertificationCard extends StatelessWidget {
-  const CertificationCard(this.grades, {Key? key, required this.gradeType, this.padding}) : super(key: key);
-
-  final List<Grade> grades;
-  final GradeType gradeType;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    String title = getGradeTypeTitle(gradeType);
-    double average = AverageHelper.averageEvals(grades, finalAvg: true);
-    String averageText = average.toStringAsFixed(1);
-    if (I18n.of(context).locale.languageCode != "en") averageText = averageText.replaceAll(".", ",");
-    Color color = gradeColor(context: context, value: average);
-    Color textColor;
-
-    if (color.computeLuminance() >= .5) {
-      textColor = Colors.black;
-    } else {
-      textColor = Colors.white;
-    }
-
-    return Padding(
-      padding: padding ?? const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0),
-      child: Container(
-        decoration: BoxDecoration(
-          borderRadius: BorderRadius.circular(12.0),
-          gradient: LinearGradient(
-            colors: [color, color.withOpacity(.75)],
-          ),
-        ),
-        child: Material(
-          type: MaterialType.transparency,
-          borderRadius: BorderRadius.circular(12.0),
-          child: ListTile(
-            contentPadding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 16.0),
-            shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
-            leading: Text(
-              averageText,
-              style: TextStyle(
-                color: textColor,
-                fontWeight: FontWeight.bold,
-                fontSize: 24.0,
-              ),
-            ),
-            title: Text.rich(
-              TextSpan(
-                text: title,
-                children: [
-                  TextSpan(
-                    text: " • ${grades.length}",
-                    style: TextStyle(
-                      color: textColor.withOpacity(.75),
-                      fontWeight: FontWeight.w600,
-                      fontSize: 16.0,
-                    ),
-                  ),
-                ],
-              ),
-              style: TextStyle(
-                color: textColor,
-                fontWeight: FontWeight.w700,
-                fontSize: 18.0,
-              ),
-            ),
-            trailing: Icon(FeatherIcons.arrowRight, color: textColor),
-            onTap: () => CertificationView.show(grades, context: context, gradeType: gradeType),
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-String getGradeTypeTitle(GradeType gradeType) {
-  String title;
-
-  switch (gradeType) {
-    case GradeType.halfYear:
-      title = "mid".i18n;
-      break;
-    case GradeType.firstQ:
-      title = "1q".i18n;
-      break;
-    case GradeType.secondQ:
-      title = "2q".i18n;
-      break;
-    case GradeType.thirdQ:
-      title = "3q".i18n;
-      break;
-    case GradeType.fourthQ:
-      title = "4q".i18n;
-      break;
-    default:
-      title = "final".i18n;
-  }
-
-  return title;
-}
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/common/widgets/cretification/certification_view.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'certification_card.i18n.dart';
+
+class CertificationCard extends StatelessWidget {
+  const CertificationCard(this.grades,
+      {Key? key, required this.gradeType, this.padding})
+      : super(key: key);
+
+  final List<Grade> grades;
+  final GradeType gradeType;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    String title = getGradeTypeTitle(gradeType);
+    double average = AverageHelper.averageEvals(grades, finalAvg: true);
+    String averageText = average.toStringAsFixed(1);
+    if (I18n.of(context).locale.languageCode != "en")
+      averageText = averageText.replaceAll(".", ",");
+    Color color = gradeColor(context: context, value: average);
+    Color textColor;
+
+    if (color.computeLuminance() >= .5) {
+      textColor = Colors.black;
+    } else {
+      textColor = Colors.white;
+    }
+
+    return Padding(
+      padding:
+          padding ?? const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0),
+      child: Container(
+        decoration: BoxDecoration(
+          borderRadius: BorderRadius.circular(12.0),
+          gradient: LinearGradient(
+            colors: [color, color.withOpacity(.75)],
+          ),
+        ),
+        child: Material(
+          type: MaterialType.transparency,
+          borderRadius: BorderRadius.circular(12.0),
+          child: ListTile(
+            contentPadding:
+                const EdgeInsets.symmetric(vertical: 4.0, horizontal: 16.0),
+            shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(12.0)),
+            leading: Text(
+              averageText,
+              style: TextStyle(
+                color: textColor,
+                fontWeight: FontWeight.bold,
+                fontSize: 24.0,
+              ),
+            ),
+            title: Text.rich(
+              TextSpan(
+                text: title,
+                children: [
+                  TextSpan(
+                    text: " • ${grades.length}",
+                    style: TextStyle(
+                      color: textColor.withOpacity(.75),
+                      fontWeight: FontWeight.w600,
+                      fontSize: 16.0,
+                    ),
+                  ),
+                ],
+              ),
+              style: TextStyle(
+                color: textColor,
+                fontWeight: FontWeight.w700,
+                fontSize: 18.0,
+              ),
+            ),
+            trailing: Icon(FeatherIcons.arrowRight, color: textColor),
+            onTap: () => CertificationView.show(grades,
+                context: context, gradeType: gradeType),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+String getGradeTypeTitle(GradeType gradeType) {
+  String title;
+
+  switch (gradeType) {
+    case GradeType.halfYear:
+      title = "mid".i18n;
+      break;
+    case GradeType.firstQ:
+      title = "1q".i18n;
+      break;
+    case GradeType.secondQ:
+      title = "2q".i18n;
+      break;
+    case GradeType.thirdQ:
+      title = "3q".i18n;
+      break;
+    case GradeType.fourthQ:
+      title = "4q".i18n;
+      break;
+    default:
+      title = "final".i18n;
+  }
+
+  return title;
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_card.i18n.dart b/refilc_mobile_ui/lib/common/widgets/cretification/certification_card.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_card.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/cretification/certification_card.i18n.dart
index f9da983..8946d62
--- a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_card.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/cretification/certification_card.i18n.dart
@@ -1,36 +1,36 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "final": "Final grades",
-          "mid": "Midterm grades",
-          "1q": "1. Quarter grades",
-          "2q": "2. Quarter grades",
-          "3q": "3. Quarter grades",
-          "4q": "4. Quarter grades",
-        },
-        "hu_hu": {
-          "final": "Év végi jegyek",
-          "mid": "Félévi jegyek",
-          "1q": "1. Negyedéves jegyek",
-          "2q": "2. Negyedéves jegyek",
-          "3q": "3. Negyedéves jegyek",
-          "4q": "4. Negyedéves jegyek",
-        },
-        "de_de": {
-          "final": "Zeugnis Noten",
-          "mid": "Halbjährlich Noten",
-          "1q": "1. Quartal Noten",
-          "2q": "2. Quartal Noten",
-          "3q": "3. Quartal Noten",
-          "4q": "4. Quartal Noten",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "final": "Final grades",
+          "mid": "Midterm grades",
+          "1q": "1. Quarter grades",
+          "2q": "2. Quarter grades",
+          "3q": "3. Quarter grades",
+          "4q": "4. Quarter grades",
+        },
+        "hu_hu": {
+          "final": "Év végi jegyek",
+          "mid": "Félévi jegyek",
+          "1q": "1. Negyedéves jegyek",
+          "2q": "2. Negyedéves jegyek",
+          "3q": "3. Negyedéves jegyek",
+          "4q": "4. Negyedéves jegyek",
+        },
+        "de_de": {
+          "final": "Zeugnis Noten",
+          "mid": "Halbjährlich Noten",
+          "1q": "1. Quartal Noten",
+          "2q": "2. Quartal Noten",
+          "3q": "3. Quartal Noten",
+          "4q": "4. Quartal Noten",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_tile.dart b/refilc_mobile_ui/lib/common/widgets/cretification/certification_tile.dart
old mode 100755
new mode 100644
similarity index 59%
rename from filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/cretification/certification_tile.dart
index 83421f5..badbc48
--- a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/cretification/certification_tile.dart
@@ -1,91 +1,109 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:provider/provider.dart';
-import 'certification_tile.i18n.dart';
-
-class CertificationTile extends StatelessWidget {
-  const CertificationTile(this.grade, {Key? key, this.onTap, this.padding}) : super(key: key);
-
-  final Function()? onTap;
-  final Grade grade;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    bool isSubjectView = SubjectGradesContainer.of(context) != null;
-    String certificationName;
-
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    switch (grade.type) {
-      case GradeType.endYear:
-        certificationName = "final".i18n;
-        break;
-      case GradeType.halfYear:
-        certificationName = "mid".i18n;
-        break;
-      case GradeType.firstQ:
-        certificationName = "1q".i18n;
-        break;
-      case GradeType.secondQ:
-        certificationName = "2q".i18n;
-        break;
-      case GradeType.thirdQ:
-        certificationName = "3q".i18n;
-        break;
-      case GradeType.fourthQ:
-        certificationName = "4q".i18n;
-        break;
-      case GradeType.levelExam:
-        certificationName = "equivalency".i18n;
-        break;
-      case GradeType.unknown:
-      default:
-        certificationName = "unknown".i18n;
-    }
-
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      borderRadius: BorderRadius.circular(8.0),
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding:
-              isSubjectView ? const EdgeInsets.only(left: 12.0, right: 12.0, top: 2.0, bottom: 8.0) : const EdgeInsets.only(left: 8.0, right: 12.0),
-          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-          onTap: onTap,
-          leading: isSubjectView
-              ? GradeValueWidget(
-                  grade.value,
-                  complemented: grade.description == 'Dicséret',
-                )
-              : Padding(
-                  padding: const EdgeInsets.only(left: 2.0),
-                  child: Icon(SubjectIcon.resolveVariant(subject: grade.subject, context: context),
-                      size: 28.0, color: AppColors.of(context).text.withOpacity(.75)),
-                ),
-          minLeadingWidth: isSubjectView ? 32.0 : 42.0,
-          trailing: isSubjectView
-              ? const Icon(FeatherIcons.award)
-              : GradeValueWidget(
-                  grade.value,
-                  complemented: grade.description == 'Dicséret',
-                ),
-          title: Text(isSubjectView ? certificationName : grade.subject.renamedTo ?? grade.subject.name.capital(),
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: TextStyle(fontWeight: FontWeight.w700, fontSize: 18.0, fontStyle: grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null)),
-          subtitle: Text(grade.value.valueName, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16.0)),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:provider/provider.dart';
+import 'certification_tile.i18n.dart';
+
+class CertificationTile extends StatelessWidget {
+  const CertificationTile(this.grade, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final Function()? onTap;
+  final Grade grade;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    bool isSubjectView = SubjectGradesContainer.of(context) != null;
+    String certificationName;
+
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    switch (grade.type) {
+      case GradeType.endYear:
+        certificationName = "final".i18n;
+        break;
+      case GradeType.halfYear:
+        certificationName = "mid".i18n;
+        break;
+      case GradeType.firstQ:
+        certificationName = "1q".i18n;
+        break;
+      case GradeType.secondQ:
+        certificationName = "2q".i18n;
+        break;
+      case GradeType.thirdQ:
+        certificationName = "3q".i18n;
+        break;
+      case GradeType.fourthQ:
+        certificationName = "4q".i18n;
+        break;
+      case GradeType.levelExam:
+        certificationName = "equivalency".i18n;
+        break;
+      case GradeType.unknown:
+      default:
+        certificationName = "unknown".i18n;
+    }
+
+    return Material(
+      color: Theme.of(context).colorScheme.background,
+      borderRadius: BorderRadius.circular(8.0),
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: isSubjectView
+              ? const EdgeInsets.only(
+                  left: 12.0, right: 12.0, top: 2.0, bottom: 8.0)
+              : const EdgeInsets.only(left: 8.0, right: 12.0),
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+          onTap: onTap,
+          leading: isSubjectView
+              ? GradeValueWidget(
+                  grade.value,
+                  complemented: grade.description == 'Dicséret',
+                )
+              : Padding(
+                  padding: const EdgeInsets.only(left: 2.0),
+                  child: Icon(
+                      SubjectIcon.resolveVariant(
+                          subject: grade.subject, context: context),
+                      size: 28.0,
+                      color: AppColors.of(context).text.withOpacity(.75)),
+                ),
+          minLeadingWidth: isSubjectView ? 32.0 : 42.0,
+          trailing: isSubjectView
+              ? const Icon(FeatherIcons.award)
+              : GradeValueWidget(
+                  grade.value,
+                  complemented: grade.description == 'Dicséret',
+                ),
+          title: Text(
+              isSubjectView
+                  ? certificationName
+                  : grade.subject.renamedTo ?? grade.subject.name.capital(),
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: TextStyle(
+                  fontWeight: FontWeight.w700,
+                  fontSize: 18.0,
+                  fontStyle: grade.subject.isRenamed &&
+                          settingsProvider.renamedSubjectsItalics
+                      ? FontStyle.italic
+                      : null)),
+          subtitle: Text(grade.value.valueName,
+              style:
+                  const TextStyle(fontWeight: FontWeight.w600, fontSize: 16.0)),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/cretification/certification_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/cretification/certification_tile.i18n.dart
index 95b4118..37f3f33
--- a/filcnaplo_mobile_ui/lib/common/widgets/cretification/certification_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/cretification/certification_tile.i18n.dart
@@ -1,45 +1,45 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "final": "Final",
-          "mid": "Mid year",
-          "1q": "1. Quarter",
-          "2q": "2. Quarter",
-          "3q": "3. Quarter",
-          "4q": "4. Quarter",
-          "equivalency": "Equivalency test",
-          "unknown": "Unknown",
-          "classavg": "Class Average",
-        },
-        "hu_hu": {
-          "final": "Év vége",
-          "mid": "Félév",
-          "1q": "1. Negyedév",
-          "2q": "2. Negyedév",
-          "3q": "3. Negyedév",
-          "4q": "4. Negyedév",
-          "equivalency": "Osztályozó",
-          "unknown": "Ismeretlen",
-          "classavg": "Osztályátlag",
-        },
-        "de_de": {
-          "final": "Zeugnis",
-          "mid": "Halbjährlich",
-          "1q": "1. Quartal",
-          "2q": "2. Quartal",
-          "3q": "3. Quartal",
-          "4q": "4. Quartal",
-          "equivalency": "Zulassungsprüfung",
-          "unknown": "Unbekannt",
-          "classavg": "Klassendurchschnitt",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "final": "Final",
+          "mid": "Mid year",
+          "1q": "1. Quarter",
+          "2q": "2. Quarter",
+          "3q": "3. Quarter",
+          "4q": "4. Quarter",
+          "equivalency": "Equivalency test",
+          "unknown": "Unknown",
+          "classavg": "Class Average",
+        },
+        "hu_hu": {
+          "final": "Év vége",
+          "mid": "Félév",
+          "1q": "1. Negyedév",
+          "2q": "2. Negyedév",
+          "3q": "3. Negyedév",
+          "4q": "4. Negyedév",
+          "equivalency": "Osztályozó",
+          "unknown": "Ismeretlen",
+          "classavg": "Osztályátlag",
+        },
+        "de_de": {
+          "final": "Zeugnis",
+          "mid": "Halbjährlich",
+          "1q": "1. Quartal",
+          "2q": "2. Quartal",
+          "3q": "3. Quartal",
+          "4q": "4. Quartal",
+          "equivalency": "Zulassungsprüfung",
+          "unknown": "Unbekannt",
+          "classavg": "Klassendurchschnitt",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/refilc_mobile_ui/lib/common/widgets/cretification/certification_view.dart b/refilc_mobile_ui/lib/common/widgets/cretification/certification_view.dart
new file mode 100644
index 0000000..1d26b4c
--- /dev/null
+++ b/refilc_mobile_ui/lib/common/widgets/cretification/certification_view.dart
@@ -0,0 +1,48 @@
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/widgets/cretification/certification_card.dart';
+import 'package:refilc_mobile_ui/common/widgets/cretification/certification_tile.dart';
+import 'package:refilc_mobile_ui/common/hero_scrollview.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+class CertificationView extends StatelessWidget {
+  const CertificationView(this.grades, {Key? key, required this.gradeType})
+      : super(key: key);
+
+  final List<Grade> grades;
+  final GradeType gradeType;
+
+  static show(List<Grade> grades,
+          {required BuildContext context, required GradeType gradeType}) =>
+      Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(
+          builder: (context) =>
+              CertificationView(grades, gradeType: gradeType)));
+
+  @override
+  Widget build(BuildContext context) {
+    grades.sort((a, b) => a.subject.name.compareTo(b.subject.name));
+    List<Widget> tiles = grades.map((e) => CertificationTile(e)).toList();
+    return Scaffold(
+        body: HeroScrollView(
+            title: getGradeTypeTitle(gradeType),
+            icon: FeatherIcons.award,
+            iconSize: 50,
+            child: ListView(
+              children: [
+                SafeArea(
+                  child: Panel(
+                    child: Column(
+                      children: tiles,
+                    ),
+                  ),
+                )
+              ],
+              shrinkWrap: true,
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              physics: const BouncingScrollPhysics(),
+            )));
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/custom_switch.dart b/refilc_mobile_ui/lib/common/widgets/custom_switch.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/custom_switch.dart
rename to refilc_mobile_ui/lib/common/widgets/custom_switch.dart
index a6640cc..0c845f3
--- a/filcnaplo_mobile_ui/lib/common/widgets/custom_switch.dart
+++ b/refilc_mobile_ui/lib/common/widgets/custom_switch.dart
@@ -1,60 +1,60 @@
-import 'package:flutter/material.dart';
-
-class CustomSwitch extends StatelessWidget {
-  final ValueChanged<bool> onChanged;
-  final bool value;
-
-  const CustomSwitch({
-    Key? key,
-    required this.onChanged,
-    required this.value,
-  }) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return GestureDetector(
-      onTap: () => onChanged(!value),
-      child: SizedBox(
-        height: 25,
-        width: 50,
-        child: Stack(
-          children: <Widget>[
-            AnimatedContainer(
-              height: 25,
-              width: 50,
-              curve: Curves.ease,
-              duration: const Duration(milliseconds: 400),
-              decoration: BoxDecoration(
-                borderRadius: const BorderRadius.all(
-                  Radius.circular(25.0),
-                ),
-                color: value ? Theme.of(context).colorScheme.secondary : Theme.of(context).highlightColor,
-              ),
-            ),
-            AnimatedAlign(
-              curve: Curves.ease,
-              duration: const Duration(milliseconds: 400),
-              alignment: !value ? Alignment.centerLeft : Alignment.centerRight,
-              child: Container(
-                height: 20,
-                width: 20,
-                margin: const EdgeInsets.symmetric(horizontal: 3),
-                decoration: BoxDecoration(
-                  shape: BoxShape.circle,
-                  color: Colors.white,
-                  boxShadow: [
-                    BoxShadow(
-                      color: Colors.black12.withOpacity(0.1),
-                      spreadRadius: 0.5,
-                      blurRadius: 1,
-                    )
-                  ],
-                ),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class CustomSwitch extends StatelessWidget {
+  final ValueChanged<bool> onChanged;
+  final bool value;
+
+  const CustomSwitch({
+    Key? key,
+    required this.onChanged,
+    required this.value,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(
+      onTap: () => onChanged(!value),
+      child: SizedBox(
+        height: 25,
+        width: 50,
+        child: Stack(
+          children: <Widget>[
+            AnimatedContainer(
+              height: 25,
+              width: 50,
+              curve: Curves.ease,
+              duration: const Duration(milliseconds: 400),
+              decoration: BoxDecoration(
+                borderRadius: const BorderRadius.all(
+                  Radius.circular(25.0),
+                ),
+                color: value ? Theme.of(context).colorScheme.secondary : Theme.of(context).highlightColor,
+              ),
+            ),
+            AnimatedAlign(
+              curve: Curves.ease,
+              duration: const Duration(milliseconds: 400),
+              alignment: !value ? Alignment.centerLeft : Alignment.centerRight,
+              child: Container(
+                height: 20,
+                width: 20,
+                margin: const EdgeInsets.symmetric(horizontal: 3),
+                decoration: BoxDecoration(
+                  shape: BoxShape.circle,
+                  color: Colors.white,
+                  boxShadow: [
+                    BoxShadow(
+                      color: Colors.black12.withOpacity(0.1),
+                      spreadRadius: 0.5,
+                      blurRadius: 1,
+                    )
+                  ],
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/event/event_tile.dart b/refilc_mobile_ui/lib/common/widgets/event/event_tile.dart
old mode 100755
new mode 100644
similarity index 79%
rename from filcnaplo_mobile_ui/lib/common/widgets/event/event_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/event/event_tile.dart
index 7076f8c..b2b1e4f
--- a/filcnaplo_mobile_ui/lib/common/widgets/event/event_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/event/event_tile.dart
@@ -1,46 +1,48 @@
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:flutter/material.dart';
-
-class EventTile extends StatelessWidget {
-  const EventTile(this.event, {Key? key, this.onTap, this.padding}) : super(key: key);
-
-  final Event event;
-  final void Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      borderRadius: BorderRadius.circular(14.0),
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: onTap,
-          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-          leading: const ProfileImage(
-            name: "!",
-            radius: 22.0,
-          ),
-          title: Text(
-            event.title,
-            maxLines: 2,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w600),
-          ),
-          subtitle: Text(
-            event.content.escapeHtml().replaceAll('\n', ' '),
-            maxLines: 1,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w500),
-          ),
-          minLeadingWidth: 0,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:flutter/material.dart';
+
+class EventTile extends StatelessWidget {
+  const EventTile(this.event, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final Event event;
+  final void Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      color: Theme.of(context).colorScheme.background,
+      borderRadius: BorderRadius.circular(14.0),
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: onTap,
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+          leading: const ProfileImage(
+            name: "!",
+            radius: 22.0,
+          ),
+          title: Text(
+            event.title,
+            maxLines: 2,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w600),
+          ),
+          subtitle: Text(
+            event.content.escapeHtml().replaceAll('\n', ' '),
+            maxLines: 1,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w500),
+          ),
+          minLeadingWidth: 0,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/event/event_view.dart b/refilc_mobile_ui/lib/common/widgets/event/event_view.dart
old mode 100755
new mode 100644
similarity index 84%
rename from filcnaplo_mobile_ui/lib/common/widgets/event/event_view.dart
rename to refilc_mobile_ui/lib/common/widgets/event/event_view.dart
index 0f75abe..1166037
--- a/filcnaplo_mobile_ui/lib/common/widgets/event/event_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/event/event_view.dart
@@ -1,57 +1,58 @@
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/common/sliding_bottom_sheet.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-import 'package:flutter_linkify/flutter_linkify.dart';
-
-class EventView extends StatelessWidget {
-  const EventView(this.event, {Key? key}) : super(key: key);
-
-  final Event event;
-
-  static void show(Event event, {required BuildContext context}) => showSlidingBottomSheet(context: context, child: EventView(event));
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          // Header
-          ListTile(
-            title: Text(
-              event.title,
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w600),
-            ),
-            trailing: Text(
-              event.start.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Details
-          Padding(
-            padding: const EdgeInsets.symmetric(horizontal: 12.0),
-            child: SelectableLinkify(
-              text: event.content.escapeHtml(),
-              options: const LinkifyOptions(looseUrl: true, removeWww: true),
-              onOpen: (link) {
-                launch(link.url,
-                    customTabsOption: CustomTabsOption(
-                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-                      showPageTitle: true,
-                    ));
-              },
-              style: const TextStyle(fontWeight: FontWeight.w400),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/common/sliding_bottom_sheet.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+import 'package:flutter_linkify/flutter_linkify.dart';
+
+class EventView extends StatelessWidget {
+  const EventView(this.event, {Key? key}) : super(key: key);
+
+  final Event event;
+
+  static void show(Event event, {required BuildContext context}) =>
+      showSlidingBottomSheet(context: context, child: EventView(event));
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          // Header
+          ListTile(
+            title: Text(
+              event.title,
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w600),
+            ),
+            trailing: Text(
+              event.start.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Details
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 12.0),
+            child: SelectableLinkify(
+              text: event.content.escapeHtml(),
+              options: const LinkifyOptions(looseUrl: true, removeWww: true),
+              onOpen: (link) {
+                launch(link.url,
+                    customTabsOption: CustomTabsOption(
+                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+                      showPageTitle: true,
+                    ));
+              },
+              style: const TextStyle(fontWeight: FontWeight.w400),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/event/event_viewable.dart b/refilc_mobile_ui/lib/common/widgets/event/event_viewable.dart
old mode 100755
new mode 100644
similarity index 59%
rename from filcnaplo_mobile_ui/lib/common/widgets/event/event_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/event/event_viewable.dart
index f58b192..76c6c50
--- a/filcnaplo_mobile_ui/lib/common/widgets/event/event_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/event/event_viewable.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo_kreta_api/models/event.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/event/event_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/event/event_view.dart';
-import 'package:flutter/material.dart';
-
-class EventViewable extends StatelessWidget {
-  const EventViewable(this.event, {Key? key}) : super(key: key);
-
-  final Event event;
-
-  @override
-  Widget build(BuildContext context) {
-    return EventTile(
-      event,
-      onTap: () => EventView.show(event, context: context),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/event.dart';
+import 'package:refilc_mobile_ui/common/widgets/event/event_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/event/event_view.dart';
+import 'package:flutter/material.dart';
+
+class EventViewable extends StatelessWidget {
+  const EventViewable(this.event, {Key? key}) : super(key: key);
+
+  final Event event;
+
+  @override
+  Widget build(BuildContext context) {
+    return EventTile(
+      event,
+      onTap: () => EventView.show(event, context: context),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_tile.dart b/refilc_mobile_ui/lib/common/widgets/exam/exam_tile.dart
old mode 100755
new mode 100644
similarity index 73%
rename from filcnaplo_mobile_ui/lib/common/widgets/exam/exam_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/exam/exam_tile.dart
index b72983b..8e23ba3
--- a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/exam/exam_tile.dart
@@ -1,58 +1,63 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-class ExamTile extends StatelessWidget {
-  const ExamTile(this.exam, {Key? key, this.onTap, this.padding}) : super(key: key);
-
-  final Exam exam;
-  final void Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      type: MaterialType.transparency,
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: onTap,
-          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-          leading: SizedBox(
-              width: 44,
-              height: 44,
-              child: Padding(
-                padding: const EdgeInsets.only(top: 2.0),
-                child: Icon(
-                  SubjectIcon.resolveVariant(subjectName: exam.subjectName, context: context),
-                  size: 28.0,
-                  color: AppColors.of(context).text.withOpacity(.75),
-                ),
-              )),
-          title: Text(
-            exam.description != "" ? exam.description : (exam.mode?.description ?? "Számonkérés"),
-            maxLines: 2,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w600),
-          ),
-          subtitle: Text(
-            exam.subjectName.capital(),
-            maxLines: 1,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w500),
-          ),
-          trailing: Icon(
-            FeatherIcons.edit,
-            color: AppColors.of(context).text.withOpacity(.75),
-          ),
-          minLeadingWidth: 0,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+class ExamTile extends StatelessWidget {
+  const ExamTile(this.exam, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final Exam exam;
+  final void Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      type: MaterialType.transparency,
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: onTap,
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+          leading: SizedBox(
+              width: 44,
+              height: 44,
+              child: Padding(
+                padding: const EdgeInsets.only(top: 2.0),
+                child: Icon(
+                  SubjectIcon.resolveVariant(
+                      subjectName: exam.subjectName, context: context),
+                  size: 28.0,
+                  color: AppColors.of(context).text.withOpacity(.75),
+                ),
+              )),
+          title: Text(
+            exam.description != ""
+                ? exam.description
+                : (exam.mode?.description ?? "Számonkérés"),
+            maxLines: 2,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w600),
+          ),
+          subtitle: Text(
+            exam.subjectName.capital(),
+            maxLines: 1,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w500),
+          ),
+          trailing: Icon(
+            FeatherIcons.edit,
+            color: AppColors.of(context).text.withOpacity(.75),
+          ),
+          minLeadingWidth: 0,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_view.dart b/refilc_mobile_ui/lib/common/widgets/exam/exam_view.dart
old mode 100755
new mode 100644
similarity index 84%
rename from filcnaplo_mobile_ui/lib/common/widgets/exam/exam_view.dart
rename to refilc_mobile_ui/lib/common/widgets/exam/exam_view.dart
index 4061baa..7266906
--- a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/exam/exam_view.dart
@@ -1,71 +1,71 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/exam.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_card.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/common/detail.dart';
-import 'package:flutter/material.dart';
-import 'exam_view.i18n.dart';
-
-class ExamView extends StatelessWidget {
-  const ExamView(this.exam, {Key? key}) : super(key: key);
-
-  final Exam exam;
-
-  static show(Exam exam, {required BuildContext context}) =>
-      showBottomCard(context: context, child: ExamView(exam));
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          // Header
-          ListTile(
-            leading: Padding(
-              padding: const EdgeInsets.only(left: 6.0),
-              child: Icon(
-                SubjectIcon.resolveVariant(
-                    subjectName: exam.subjectName, context: context),
-                size: 36.0,
-                color: AppColors.of(context).text.withOpacity(.75),
-              ),
-            ),
-            title: Text(
-              exam.subjectName.capital(),
-              maxLines: 1,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w600),
-            ),
-            subtitle: Text(
-              (exam.teacher.isRenamed
-                      ? exam.teacher.renamedTo
-                      : exam.teacher.name) ??
-                  '',
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-            trailing: Text(
-              exam.date.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Details
-          if (exam.writeDate.year != 0)
-            Detail(
-                title: "date".i18n,
-                description: exam.writeDate.format(context)),
-          if (exam.description != "")
-            Detail(title: "description".i18n, description: exam.description),
-          if (exam.mode != null)
-            Detail(title: "mode".i18n, description: exam.mode!.description),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:refilc_mobile_ui/common/bottom_card.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/common/detail.dart';
+import 'package:flutter/material.dart';
+import 'exam_view.i18n.dart';
+
+class ExamView extends StatelessWidget {
+  const ExamView(this.exam, {Key? key}) : super(key: key);
+
+  final Exam exam;
+
+  static show(Exam exam, {required BuildContext context}) =>
+      showBottomCard(context: context, child: ExamView(exam));
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          // Header
+          ListTile(
+            leading: Padding(
+              padding: const EdgeInsets.only(left: 6.0),
+              child: Icon(
+                SubjectIcon.resolveVariant(
+                    subjectName: exam.subjectName, context: context),
+                size: 36.0,
+                color: AppColors.of(context).text.withOpacity(.75),
+              ),
+            ),
+            title: Text(
+              exam.subjectName.capital(),
+              maxLines: 1,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w600),
+            ),
+            subtitle: Text(
+              (exam.teacher.isRenamed
+                      ? exam.teacher.renamedTo
+                      : exam.teacher.name) ??
+                  '',
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+            trailing: Text(
+              exam.date.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Details
+          if (exam.writeDate.year != 0)
+            Detail(
+                title: "date".i18n,
+                description: exam.writeDate.format(context)),
+          if (exam.description != "")
+            Detail(title: "description".i18n, description: exam.description),
+          if (exam.mode != null)
+            Detail(title: "mode".i18n, description: exam.mode!.description),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_view.i18n.dart b/refilc_mobile_ui/lib/common/widgets/exam/exam_view.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/exam/exam_view.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/exam/exam_view.i18n.dart
index 75d90b0..b038ec2
--- a/filcnaplo_mobile_ui/lib/common/widgets/exam/exam_view.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/exam/exam_view.i18n.dart
@@ -1,27 +1,27 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "date": "Date",
-          "description": "Description",
-          "mode": "Type",
-        },
-        "hu_hu": {
-          "date": "Írás ideje",
-          "description": "Leírás",
-          "mode": "Típus",
-        },
-        "de_de": {
-          "date": "Prüfungszeit",
-          "description": "Bezeichnung",
-          "mode": "Typ",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "date": "Date",
+          "description": "Description",
+          "mode": "Type",
+        },
+        "hu_hu": {
+          "date": "Írás ideje",
+          "description": "Leírás",
+          "mode": "Típus",
+        },
+        "de_de": {
+          "date": "Prüfungszeit",
+          "description": "Bezeichnung",
+          "mode": "Typ",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/refilc_mobile_ui/lib/common/widgets/exam/exam_viewable.dart b/refilc_mobile_ui/lib/common/widgets/exam/exam_viewable.dart
new file mode 100644
index 0000000..dc0b4a7
--- /dev/null
+++ b/refilc_mobile_ui/lib/common/widgets/exam/exam_viewable.dart
@@ -0,0 +1,20 @@
+import 'package:refilc_kreta_api/models/exam.dart';
+import 'package:refilc_mobile_ui/common/viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
+import 'package:refilc_mobile_ui/common/widgets/exam/exam_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/exam/exam_view.dart';
+import 'package:flutter/material.dart';
+
+class ExamViewable extends StatelessWidget {
+  const ExamViewable(this.exam, {Key? key}) : super(key: key);
+
+  final Exam exam;
+
+  @override
+  Widget build(BuildContext context) {
+    return Viewable(
+      tile: ExamTile(exam),
+      view: CardHandle(child: ExamView(exam)),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_subject_tile.dart b/refilc_mobile_ui/lib/common/widgets/grade/grade_subject_tile.dart
old mode 100755
new mode 100644
similarity index 83%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/grade_subject_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/grade_subject_tile.dart
index 35e6509..031fc7f
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_subject_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/grade_subject_tile.dart
@@ -1,87 +1,90 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class GradeSubjectTile extends StatelessWidget {
-  const GradeSubjectTile(this.subject,
-      {Key? key,
-      this.average = 0.0,
-      this.groupAverage = 0.0,
-      this.onTap,
-      this.averageBefore = 0.0})
-      : super(key: key);
-
-  final Subject subject;
-  final void Function()? onTap;
-  final double average;
-  final double groupAverage;
-  final double averageBefore;
-  @override
-  Widget build(BuildContext context) {
-    Color textColor = AppColors.of(context).text;
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    // Failing indicator
-    if (average < 2.0 && average >= 1.0) {
-      textColor = AppColors.of(context).red;
-    }
-
-    final String changeIcon = average < averageBefore ? "▼" : "▲";
-    final Color changeColor = average < averageBefore
-        ? Colors.redAccent
-        : Colors.lightGreenAccent.shade700;
-
-    return Material(
-      type: MaterialType.transparency,
-      child: ListTile(
-        minLeadingWidth: 32.0,
-        dense: true,
-        contentPadding: const EdgeInsets.only(left: 8.0, right: 6.0),
-        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-        visualDensity: VisualDensity.compact,
-        onTap: onTap,
-        leading: Icon(
-            SubjectIcon.resolveVariant(subject: subject, context: context),
-            color: textColor.withOpacity(.75)),
-        title: Text(
-          subject.renamedTo ?? subject.name.capital(),
-          maxLines: 2,
-          overflow: TextOverflow.ellipsis,
-          style: TextStyle(
-              fontWeight: FontWeight.w600,
-              fontSize: 14.0,
-              color: textColor,
-              fontStyle: settingsProvider.renamedSubjectsItalics && subject.isRenamed ? FontStyle.italic : null),
-        ),
-        trailing: Row(
-          mainAxisSize: MainAxisSize.min,
-          children: [
-            if (groupAverage != 0 && averageBefore == 0.0)
-              AverageDisplay(average: groupAverage, border: true),
-            const SizedBox(width: 6.0),
-            if (averageBefore != 0.0 && averageBefore != average) ...[
-              AverageDisplay(average: averageBefore),
-              Padding(
-                padding:
-                    const EdgeInsets.only(left: 6.0, right: 6.0, bottom: 3.5),
-                child: Text(
-                  changeIcon,
-                  style: TextStyle(
-                    color: changeColor,
-                    fontSize: 20.0,
-                  ),
-                ),
-              )
-            ],
-            AverageDisplay(average: average)
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class GradeSubjectTile extends StatelessWidget {
+  const GradeSubjectTile(this.subject,
+      {Key? key,
+      this.average = 0.0,
+      this.groupAverage = 0.0,
+      this.onTap,
+      this.averageBefore = 0.0})
+      : super(key: key);
+
+  final Subject subject;
+  final void Function()? onTap;
+  final double average;
+  final double groupAverage;
+  final double averageBefore;
+  @override
+  Widget build(BuildContext context) {
+    Color textColor = AppColors.of(context).text;
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    // Failing indicator
+    if (average < 2.0 && average >= 1.0) {
+      textColor = AppColors.of(context).red;
+    }
+
+    final String changeIcon = average < averageBefore ? "▼" : "▲";
+    final Color changeColor = average < averageBefore
+        ? Colors.redAccent
+        : Colors.lightGreenAccent.shade700;
+
+    return Material(
+      type: MaterialType.transparency,
+      child: ListTile(
+        minLeadingWidth: 32.0,
+        dense: true,
+        contentPadding: const EdgeInsets.only(left: 8.0, right: 6.0),
+        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+        visualDensity: VisualDensity.compact,
+        onTap: onTap,
+        leading: Icon(
+            SubjectIcon.resolveVariant(subject: subject, context: context),
+            color: textColor.withOpacity(.75)),
+        title: Text(
+          subject.renamedTo ?? subject.name.capital(),
+          maxLines: 2,
+          overflow: TextOverflow.ellipsis,
+          style: TextStyle(
+              fontWeight: FontWeight.w600,
+              fontSize: 14.0,
+              color: textColor,
+              fontStyle:
+                  settingsProvider.renamedSubjectsItalics && subject.isRenamed
+                      ? FontStyle.italic
+                      : null),
+        ),
+        trailing: Row(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            if (groupAverage != 0 && averageBefore == 0.0)
+              AverageDisplay(average: groupAverage, border: true),
+            const SizedBox(width: 6.0),
+            if (averageBefore != 0.0 && averageBefore != average) ...[
+              AverageDisplay(average: averageBefore),
+              Padding(
+                padding:
+                    const EdgeInsets.only(left: 6.0, right: 6.0, bottom: 3.5),
+                child: Text(
+                  changeIcon,
+                  style: TextStyle(
+                    color: changeColor,
+                    fontSize: 20.0,
+                  ),
+                ),
+              )
+            ],
+            AverageDisplay(average: average)
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_view.dart b/refilc_mobile_ui/lib/common/widgets/grade/grade_view.dart
old mode 100755
new mode 100644
similarity index 86%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/grade_view.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/grade_view.dart
index 4673b3d..4e1c784
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/grade_view.dart
@@ -1,80 +1,80 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_card.dart';
-import 'package:filcnaplo_mobile_ui/common/detail.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'grade_view.i18n.dart';
-
-class GradeView extends StatelessWidget {
-  const GradeView(this.grade, {Key? key}) : super(key: key);
-
-  static show(Grade grade, {required BuildContext context}) =>
-      showBottomCard(context: context, child: GradeView(grade));
-
-  final Grade grade;
-
-  @override
-  Widget build(BuildContext context) {
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          ListTile(
-            leading: GradeValueWidget(grade.value, fill: true),
-            title: Text(
-              grade.subject.renamedTo ?? grade.subject.name.capital(),
-              maxLines: 1,
-              overflow: TextOverflow.ellipsis,
-              style: TextStyle(
-                  fontWeight: FontWeight.w600,
-                  fontStyle: grade.subject.isRenamed &&
-                          settingsProvider.renamedSubjectsItalics
-                      ? FontStyle.italic
-                      : null),
-            ),
-            subtitle: Text(
-              !Provider.of<SettingsProvider>(context, listen: false)
-                      .presentationMode
-                  ? (grade.teacher.isRenamed
-                          ? grade.teacher.renamedTo
-                          : grade.teacher.name) ??
-                      ''
-                  : "Tanár",
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-            trailing: Text(
-              grade.date.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Grade Details
-          Detail(
-            title: "value".i18n,
-            description: "${grade.value.valueName} " + percentText(),
-          ),
-          if (grade.description != "")
-            Detail(title: "description".i18n, description: grade.description),
-          if (grade.mode.description != "")
-            Detail(title: "mode".i18n, description: grade.mode.description),
-          if (grade.writeDate.year != 0)
-            Detail(
-                title: "date".i18n,
-                description: grade.writeDate.format(context)),
-        ],
-      ),
-    );
-  }
-
-  String percentText() => grade.value.weight != 100 && grade.value.weight > 0
-      ? "${grade.value.weight}%"
-      : "";
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/common/bottom_card.dart';
+import 'package:refilc_mobile_ui/common/detail.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'grade_view.i18n.dart';
+
+class GradeView extends StatelessWidget {
+  const GradeView(this.grade, {Key? key}) : super(key: key);
+
+  static show(Grade grade, {required BuildContext context}) =>
+      showBottomCard(context: context, child: GradeView(grade));
+
+  final Grade grade;
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          ListTile(
+            leading: GradeValueWidget(grade.value, fill: true),
+            title: Text(
+              grade.subject.renamedTo ?? grade.subject.name.capital(),
+              maxLines: 1,
+              overflow: TextOverflow.ellipsis,
+              style: TextStyle(
+                  fontWeight: FontWeight.w600,
+                  fontStyle: grade.subject.isRenamed &&
+                          settingsProvider.renamedSubjectsItalics
+                      ? FontStyle.italic
+                      : null),
+            ),
+            subtitle: Text(
+              !Provider.of<SettingsProvider>(context, listen: false)
+                      .presentationMode
+                  ? (grade.teacher.isRenamed
+                          ? grade.teacher.renamedTo
+                          : grade.teacher.name) ??
+                      ''
+                  : "Tanár",
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+            trailing: Text(
+              grade.date.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Grade Details
+          Detail(
+            title: "value".i18n,
+            description: "${grade.value.valueName} " + percentText(),
+          ),
+          if (grade.description != "")
+            Detail(title: "description".i18n, description: grade.description),
+          if (grade.mode.description != "")
+            Detail(title: "mode".i18n, description: grade.mode.description),
+          if (grade.writeDate.year != 0)
+            Detail(
+                title: "date".i18n,
+                description: grade.writeDate.format(context)),
+        ],
+      ),
+    );
+  }
+
+  String percentText() => grade.value.weight != 100 && grade.value.weight > 0
+      ? "${grade.value.weight}%"
+      : "";
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_view.i18n.dart b/refilc_mobile_ui/lib/common/widgets/grade/grade_view.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/grade_view.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/grade_view.i18n.dart
index 4604c74..955073b
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_view.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/grade_view.i18n.dart
@@ -1,30 +1,30 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "value": "Value",
-          "date": "Date",
-          "description": "Description",
-          "mode": "Type",
-        },
-        "hu_hu": {
-          "value": "Érték",
-          "date": "Írás ideje",
-          "description": "Leírás",
-          "mode": "Típus",
-        },
-        "de_de": {
-          "value": "Notenwert",
-          "date": "Prüfungszeit",
-          "description": "Bezeichnung",
-          "mode": "Typ",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "value": "Value",
+          "date": "Date",
+          "description": "Description",
+          "mode": "Type",
+        },
+        "hu_hu": {
+          "value": "Érték",
+          "date": "Írás ideje",
+          "description": "Leírás",
+          "mode": "Típus",
+        },
+        "de_de": {
+          "value": "Notenwert",
+          "date": "Prüfungszeit",
+          "description": "Bezeichnung",
+          "mode": "Typ",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_viewable.dart b/refilc_mobile_ui/lib/common/widgets/grade/grade_viewable.dart
old mode 100755
new mode 100644
similarity index 57%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/grade_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/grade_viewable.dart
index 69547ed..df75d5b
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/grade_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/grade_viewable.dart
@@ -1,25 +1,25 @@
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/card_handle.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_view.dart';
-import 'package:filcnaplo_mobile_ui/common/viewable.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
-import 'package:flutter/material.dart';
-
-class GradeViewable extends StatelessWidget {
-  const GradeViewable(this.grade, {Key? key, this.padding}) : super(key: key);
-
-  final Grade grade;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    final subject = SubjectGradesContainer.of(context) != null;
-    final tile = GradeTile(grade, padding: subject ? EdgeInsets.zero : padding);
-
-    return Viewable(
-      tile: subject ? SubjectGradesContainer(child: tile) : tile,
-      view: CardHandle(child: GradeView(grade)),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/grade_view.dart';
+import 'package:refilc_mobile_ui/common/viewable.dart';
+import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
+import 'package:flutter/material.dart';
+
+class GradeViewable extends StatelessWidget {
+  const GradeViewable(this.grade, {Key? key, this.padding}) : super(key: key);
+
+  final Grade grade;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    final subject = SubjectGradesContainer.of(context) != null;
+    final tile = GradeTile(grade, padding: subject ? EdgeInsets.zero : padding);
+
+    return Viewable(
+      tile: subject ? SubjectGradesContainer(child: tile) : tile,
+      view: CardHandle(child: GradeView(grade)),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/new_grades.dart b/refilc_mobile_ui/lib/common/widgets/grade/new_grades.dart
old mode 100755
new mode 100644
similarity index 84%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/new_grades.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/new_grades.dart
index d666ddd..8f948d8
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/new_grades.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/new_grades.dart
@@ -1,160 +1,163 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/surprise_grade.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:rive/rive.dart';
-
-import 'new_grades.i18n.dart';
-
-class NewGradesSurprise extends StatelessWidget {
-  const NewGradesSurprise(this.grades, {Key? key, this.censored = false}) : super(key: key);
-
-  final List<Grade> grades;
-  final bool censored;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      type: MaterialType.transparency,
-      child: Padding(
-        padding: const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          shape: RoundedRectangleBorder(
-            side: BorderSide(
-              color: Theme.of(context).colorScheme.secondary,
-              width: 3.0,
-            ),
-            borderRadius: BorderRadius.circular(14.0),
-          ),
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: () => openingFun(context),
-          minLeadingWidth: 54,
-          leading: SizedBox(
-            width: 44,
-            height: 44,
-            child: Center(
-              child: Container(
-                decoration: BoxDecoration(boxShadow: [
-                  BoxShadow(
-                    color: Theme.of(context).colorScheme.secondary.withOpacity(.5),
-                    blurRadius: 18.0,
-                  )
-                ]),
-                child: const RiveAnimation.asset("assets/animations/backpack-2.riv"),
-              ),
-            ),
-          ),
-          title: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 85,
-                      height: 15,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.85),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  grades.length == 1 ?
-                    "new_grade".i18n :
-                    "new_grades".i18n,
-                  maxLines: 2,
-                  overflow: TextOverflow.ellipsis,
-                  style: const TextStyle(fontWeight: FontWeight.w600),
-                ),
-          subtitle: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 125,
-                      height: 10,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.45),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  "tap_to_open".i18n,
-                  maxLines: 1,
-                  overflow: TextOverflow.ellipsis,
-                  style: const TextStyle(fontWeight: FontWeight.w500),
-                ),
-          trailing: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 25,
-                      height: 25,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.45),
-                        borderRadius: BorderRadius.circular(25.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text.rich(
-                  TextSpan(children: [
-                    TextSpan(
-                        text: "${grades.length}",
-                        style: TextStyle(
-                          shadows: [
-                            Shadow(
-                              color: AppColors.of(context).text.withOpacity(.2),
-                              offset: const Offset(2, 2),
-                            )
-                          ],
-                        )),
-                    TextSpan(
-                      text: "x",
-                      style: TextStyle(
-                        fontSize: 20.0,
-                        color: AppColors.of(context).text.withOpacity(.5),
-                        fontWeight: FontWeight.w800,
-                      ),
-                    )
-                  ]),
-                  style: TextStyle(
-                    fontWeight: FontWeight.w700,
-                    fontSize: 28.0,
-                    color: AppColors.of(context).text.withOpacity(.75),
-                  ),
-                ),
-        ),
-      ),
-    );
-  }
-
-  void openingFun(BuildContext context) {
-    final settings = Provider.of<SettingsProvider>(context, listen: false);
-    if (!settings.gradeOpeningFun) return;
-
-    final gradeProvider = Provider.of<GradeProvider>(context, listen: false);
-
-    final newGrades = gradeProvider.grades.where((element) => element.date.isAfter(gradeProvider.lastSeenDate)).toList();
-    newGrades.sort((a, b) => a.date.compareTo(b.date));
-    WidgetsBinding.instance.addPostFrameCallback((_) async {
-      await Future.delayed(const Duration(milliseconds: 100));
-      for (final grade in newGrades) {
-        await showDialog(
-          context: context,
-          builder: (context) => SurpriseGrade(grade),
-          useRootNavigator: true,
-          barrierDismissible: false,
-          barrierColor: Colors.transparent,
-          useSafeArea: false,
-        );
-        await Future.delayed(const Duration(milliseconds: 300));
-      }
-      await gradeProvider.seenAll();
-    });
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/surprise_grade.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:rive/rive.dart';
+
+import 'new_grades.i18n.dart';
+
+class NewGradesSurprise extends StatelessWidget {
+  const NewGradesSurprise(this.grades, {Key? key, this.censored = false})
+      : super(key: key);
+
+  final List<Grade> grades;
+  final bool censored;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      type: MaterialType.transparency,
+      child: Padding(
+        padding: const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          shape: RoundedRectangleBorder(
+            side: BorderSide(
+              color: Theme.of(context).colorScheme.secondary,
+              width: 3.0,
+            ),
+            borderRadius: BorderRadius.circular(14.0),
+          ),
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: () => openingFun(context),
+          minLeadingWidth: 54,
+          leading: SizedBox(
+            width: 44,
+            height: 44,
+            child: Center(
+              child: Container(
+                decoration: BoxDecoration(boxShadow: [
+                  BoxShadow(
+                    color:
+                        Theme.of(context).colorScheme.secondary.withOpacity(.5),
+                    blurRadius: 18.0,
+                  )
+                ]),
+                child: const RiveAnimation.asset(
+                    "assets/animations/backpack-2.riv"),
+              ),
+            ),
+          ),
+          title: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 85,
+                      height: 15,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.85),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  grades.length == 1 ? "new_grade".i18n : "new_grades".i18n,
+                  maxLines: 2,
+                  overflow: TextOverflow.ellipsis,
+                  style: const TextStyle(fontWeight: FontWeight.w600),
+                ),
+          subtitle: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 125,
+                      height: 10,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.45),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  "tap_to_open".i18n,
+                  maxLines: 1,
+                  overflow: TextOverflow.ellipsis,
+                  style: const TextStyle(fontWeight: FontWeight.w500),
+                ),
+          trailing: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 25,
+                      height: 25,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.45),
+                        borderRadius: BorderRadius.circular(25.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text.rich(
+                  TextSpan(children: [
+                    TextSpan(
+                        text: "${grades.length}",
+                        style: TextStyle(
+                          shadows: [
+                            Shadow(
+                              color: AppColors.of(context).text.withOpacity(.2),
+                              offset: const Offset(2, 2),
+                            )
+                          ],
+                        )),
+                    TextSpan(
+                      text: "x",
+                      style: TextStyle(
+                        fontSize: 20.0,
+                        color: AppColors.of(context).text.withOpacity(.5),
+                        fontWeight: FontWeight.w800,
+                      ),
+                    )
+                  ]),
+                  style: TextStyle(
+                    fontWeight: FontWeight.w700,
+                    fontSize: 28.0,
+                    color: AppColors.of(context).text.withOpacity(.75),
+                  ),
+                ),
+        ),
+      ),
+    );
+  }
+
+  void openingFun(BuildContext context) {
+    final settings = Provider.of<SettingsProvider>(context, listen: false);
+    if (!settings.gradeOpeningFun) return;
+
+    final gradeProvider = Provider.of<GradeProvider>(context, listen: false);
+
+    final newGrades = gradeProvider.grades
+        .where((element) => element.date.isAfter(gradeProvider.lastSeenDate))
+        .toList();
+    newGrades.sort((a, b) => a.date.compareTo(b.date));
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
+      await Future.delayed(const Duration(milliseconds: 100));
+      for (final grade in newGrades) {
+        await showDialog(
+          context: context,
+          builder: (context) => SurpriseGrade(grade),
+          useRootNavigator: true,
+          barrierDismissible: false,
+          barrierColor: Colors.transparent,
+          useSafeArea: false,
+        );
+        await Future.delayed(const Duration(milliseconds: 300));
+      }
+      await gradeProvider.seenAll();
+    });
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/new_grades.i18n.dart b/refilc_mobile_ui/lib/common/widgets/grade/new_grades.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/new_grades.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/new_grades.i18n.dart
index 24a16ba..e6f700c
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/new_grades.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/new_grades.i18n.dart
@@ -1,45 +1,45 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "common": "Common",
-          "uncommon": "Uncommon",
-          "rare": "Rare",
-          "epic": "Epic",
-          "legendary": "Legendary",
-          "new_grade": "New grade",
-          "new_grades": "New grades",
-          "tap_to_open": "Tap to open now!",
-          "open_subtitle": "Tap to open...",
-        },
-        "hu_hu": {
-          "common": "Gyakori",
-          "uncommon": "Nem gyakori",
-          "rare": "Ritka",
-          "epic": "Epikus",
-          "legendary": "Legendás",
-          "new_grade": "Új jegy",
-          "new_grades": "Új jegyek",
-          "tap_to_open": "Nyisd ki őket!",
-          "open_subtitle": "Nyomd meg a kinyitáshoz...",
-        },
-        "de_de": {
-          "common": "Gemeinsam",
-          "uncommon": "Gelegentlich",
-          "rare": "Selten",
-          "epic": "Episch",
-          "legendary": "Legendär",
-          "new_grade": "Neue Note",
-          "new_grades": "Neue Noten",
-          "tap_to_open": "Tippen, um jetzt zu öffnen!",
-          "open_subtitle": "Antippen zum Öffnen...",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "common": "Common",
+          "uncommon": "Uncommon",
+          "rare": "Rare",
+          "epic": "Epic",
+          "legendary": "Legendary",
+          "new_grade": "New grade",
+          "new_grades": "New grades",
+          "tap_to_open": "Tap to open now!",
+          "open_subtitle": "Tap to open...",
+        },
+        "hu_hu": {
+          "common": "Gyakori",
+          "uncommon": "Nem gyakori",
+          "rare": "Ritka",
+          "epic": "Epikus",
+          "legendary": "Legendás",
+          "new_grade": "Új jegy",
+          "new_grades": "Új jegyek",
+          "tap_to_open": "Nyisd ki őket!",
+          "open_subtitle": "Nyomd meg a kinyitáshoz...",
+        },
+        "de_de": {
+          "common": "Gemeinsam",
+          "uncommon": "Gelegentlich",
+          "rare": "Selten",
+          "epic": "Episch",
+          "legendary": "Legendär",
+          "new_grade": "Neue Note",
+          "new_grades": "Neue Noten",
+          "tap_to_open": "Tippen, um jetzt zu öffnen!",
+          "open_subtitle": "Antippen zum Öffnen...",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/grade/surprise_grade.dart b/refilc_mobile_ui/lib/common/widgets/grade/surprise_grade.dart
old mode 100755
new mode 100644
similarity index 67%
rename from filcnaplo_mobile_ui/lib/common/widgets/grade/surprise_grade.dart
rename to refilc_mobile_ui/lib/common/widgets/grade/surprise_grade.dart
index ba787d3..121e387
--- a/filcnaplo_mobile_ui/lib/common/widgets/grade/surprise_grade.dart
+++ b/refilc_mobile_ui/lib/common/widgets/grade/surprise_grade.dart
@@ -1,389 +1,472 @@
-import 'dart:math';
-import 'dart:ui';
-
-import 'package:animated_background/animated_background.dart' as bg;
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_mobile_ui/pages/home/particle.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:rive/rive.dart' as rive;
-
-import 'new_grades.i18n.dart';
-
-class SurpriseGrade extends StatefulWidget {
-  const SurpriseGrade(this.grade, {Key? key}) : super(key: key);
-
-  final Grade grade;
-
-  @override
-  State<SurpriseGrade> createState() => _SurpriseGradeState();
-}
-
-class _SurpriseGradeState extends State<SurpriseGrade> with TickerProviderStateMixin {
-  late AnimationController _revealAnimFade;
-  late AnimationController _revealAnimScale;
-  late AnimationController _revealAnimGrade;
-  late AnimationController _revealAnimParticle;
-  late rive.RiveAnimationController _controller;
-
-  @override
-  void initState() {
-    super.initState();
-    _revealAnimFade = AnimationController(vsync: this, duration: const Duration(milliseconds: 500));
-    _revealAnimScale = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
-    _revealAnimGrade = AnimationController(vsync: this, duration: const Duration(seconds: 1));
-    _revealAnimParticle = AnimationController(vsync: this, duration: const Duration(seconds: 2));
-    _revealAnimScale.animateTo(0.7, duration: Duration.zero);
-    _controller = rive.SimpleAnimation('Timeline 1', autoplay: false);
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      _revealAnimFade.animateTo(1.0, curve: Curves.easeInOut);
-      Future.delayed(const Duration(milliseconds: 200), () {
-        _revealAnimScale.animateTo(1.0, curve: Curves.easeInOut).then((_) {
-          setState(() => subtitle = true);
-        });
-      });
-    });
-
-    seed = Random().nextInt(100000000);
-  }
-
-  @override
-  void dispose() {
-    _revealAnimFade.dispose();
-    _revealAnimScale.dispose();
-    _revealAnimGrade.dispose();
-    _revealAnimParticle.dispose();
-    _controller.dispose();
-    super.dispose();
-  }
-
-  bool hold = false;
-  bool subtitle = false;
-  late int seed;
-
-  void reveal() async {
-    if (!subtitle) {
-      _revealAnimParticle.animateBack(0.0, curve: Curves.fastLinearToSlowEaseIn, duration: const Duration(milliseconds: 300));
-      await Future.delayed(const Duration(milliseconds: 50));
-      _revealAnimGrade.animateBack(0.0, curve: Curves.fastLinearToSlowEaseIn);
-      await Future.delayed(const Duration(milliseconds: 50));
-      _revealAnimFade.animateBack(0.0, curve: Curves.easeInOut);
-      _revealAnimScale.animateBack(0.0, curve: Curves.easeInOut);
-      if (mounted) Navigator.of(context).pop();
-      return;
-    }
-    subtitle = false;
-    setState(() => hold = false);
-    _controller.isActive = true;
-    await Future.delayed(const Duration(seconds: 2));
-    if (mounted) _revealAnimGrade.animateTo(1.0, curve: Curves.fastLinearToSlowEaseIn);
-    await Future.delayed(const Duration(milliseconds: 700));
-    if (mounted) await _revealAnimParticle.animateTo(1.0, curve: Curves.fastLinearToSlowEaseIn);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return AnimatedBuilder(
-      animation: _revealAnimFade,
-      builder: (context, child) {
-        return FadeTransition(
-          opacity: _revealAnimFade,
-          child: Material(
-            color: Colors.black.withOpacity(.75),
-            child: Container(
-              color: Theme.of(context).colorScheme.secondary.withOpacity(.05),
-              child: Container(
-                decoration: const BoxDecoration(
-                  gradient: RadialGradient(
-                    colors: [Colors.transparent, Colors.black],
-                    radius: 1.5,
-                    stops: [0.2, 1.0],
-                  ),
-                ),
-                child: bg.AnimatedBackground(
-                  vsync: this,
-                  behaviour: bg.RandomParticleBehaviour(
-                    options: bg.ParticleOptions(
-                      baseColor: Theme.of(context).colorScheme.secondary,
-                      spawnMinSpeed: 5.0,
-                      spawnMaxSpeed: 10.0,
-                      minOpacity: .05,
-                      maxOpacity: .08,
-                      spawnMinRadius: 30.0,
-                      spawnMaxRadius: 50.0,
-                      particleCount: 20,
-                    ),
-                  ),
-                  child: ScaleTransition(
-                    scale: _revealAnimScale,
-                    child: child,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        );
-      },
-      child: AnimatedBuilder(
-          animation: _revealAnimGrade,
-          builder: (context, child) {
-            return Stack(
-              alignment: Alignment.center,
-              children: [
-                Column(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: [
-                    SlideTransition(
-                      position: _revealAnimGrade.drive(Tween(begin: Offset.zero, end: const Offset(0, 0.7))),
-                      child: AnimatedScale(
-                        scale: hold ? 1.1 : 1.0,
-                        curve: Curves.easeOutBack,
-                        duration: const Duration(milliseconds: 200),
-                        child: GestureDetector(
-                          onLongPressDown: (_) => setState(() => hold = true),
-                          onLongPressEnd: (_) => reveal(),
-                          onLongPressCancel: reveal,
-                          child: ScaleTransition(
-                            scale: CurvedAnimation(curve: Curves.easeInOut, parent: _revealAnimGrade.drive(Tween(begin: 1.0, end: 0.8))),
-                            child: Stack(
-                              alignment: Alignment.center,
-                              children: [
-                                SizedBox(
-                                  width: 300,
-                                  height: 300,
-                                  child: rive.RiveAnimation.asset(
-                                    "assets/animations/backpack-2.riv",
-                                    fit: BoxFit.contain,
-                                    controllers: [_controller],
-                                    antialiasing: false,
-                                  ),
-                                ),
-                                SlideTransition(
-                                  position: _revealAnimParticle.drive(Tween(begin: const Offset(0, 0.3), end: const Offset(0, 0.8))),
-                                  child: FadeTransition(
-                                    opacity: _revealAnimParticle,
-                                    child: ClipRRect(
-                                      borderRadius: BorderRadius.circular(24.0),
-                                      child: BackdropFilter(
-                                        filter: ImageFilter.blur(sigmaX: 32.0, sigmaY: 32.0),
-                                        child: Container(
-                                          width: double.infinity,
-                                          padding: const EdgeInsets.symmetric(horizontal: 32.0, vertical: 20.0),
-                                          decoration: BoxDecoration(
-                                            color: Colors.white.withOpacity(.3),
-                                            borderRadius: BorderRadius.circular(24.0),
-                                            border: Border.all(color: Colors.black.withOpacity(.3), width: 1.0),
-                                          ),
-                                          child: Row(
-                                            children: [
-                                              Expanded(
-                                                child: Column(
-                                                  crossAxisAlignment: CrossAxisAlignment.start,
-                                                  mainAxisSize: MainAxisSize.min,
-                                                  children: [
-                                                    if (widget.grade.description != "")
-                                                      Text(
-                                                        widget.grade.description,
-                                                        style: const TextStyle(
-                                                          color: Colors.white,
-                                                          fontWeight: FontWeight.bold,
-                                                          fontSize: 26.0,
-                                                        ),
-                                                        maxLines: 2,
-                                                        overflow: TextOverflow.ellipsis,
-                                                      ),
-                                                    Text(
-                                                      widget.grade.subject.renamedTo ?? widget.grade.subject.name.capital(),
-                                                      style: TextStyle(
-                                                          color: Colors.white.withOpacity(.8),
-                                                          fontWeight: FontWeight.bold,
-                                                          fontSize: 24.0,
-                                                          fontStyle: widget.grade.subject.isRenamed ? FontStyle.italic : null),
-                                                      maxLines: 2,
-                                                      overflow: TextOverflow.ellipsis,
-                                                    ),
-                                                    const SizedBox(height: 2),
-                                                    Text(
-                                                      "${widget.grade.value.weight}%",
-                                                      style: TextStyle(
-                                                        color: Colors.white.withOpacity(.7),
-                                                        fontWeight: FontWeight.w600,
-                                                        fontSize: 20.0,
-                                                      ),
-                                                      maxLines: 2,
-                                                      overflow: TextOverflow.ellipsis,
-                                                    ),
-                                                  ],
-                                                ),
-                                              ),
-                                              const SizedBox(width: 20.0),
-                                              Icon(
-                                                SubjectIcon.resolveVariant(subject: widget.grade.subject, context: context),
-                                                color: Colors.white,
-                                                size: 82.0,
-                                              ),
-                                            ],
-                                          ),
-                                        ),
-                                      ),
-                                    ),
-                                  ),
-                                ),
-                              ],
-                            ),
-                          ),
-                        ),
-                      ),
-                    ),
-                    const SizedBox(height: 42.0),
-                    AnimatedOpacity(
-                      opacity: subtitle ? 1.0 : 0.0,
-                      duration: const Duration(milliseconds: 300),
-                      child: Text(
-                        "open_subtitle".i18n,
-                        style: TextStyle(
-                          color: Colors.white.withOpacity(.8),
-                          fontWeight: FontWeight.w600,
-                          fontSize: 24.0,
-                        ),
-                      ),
-                    ),
-                  ],
-                ),
-                if (_revealAnimGrade.value > 0)
-                  AnimatedBuilder(
-                    animation: _revealAnimParticle,
-                    builder: (context, child) {
-                      bool shouldPaint = false;
-                      if (_revealAnimParticle.status == AnimationStatus.forward || _revealAnimParticle.status == AnimationStatus.reverse) {
-                        shouldPaint = true;
-                      }
-                      return ScaleTransition(
-                        scale: _revealAnimGrade,
-                        child: FadeTransition(
-                          opacity: _revealAnimGrade,
-                          child: SlideTransition(
-                            position: _revealAnimGrade.drive(Tween(begin: Offset.zero, end: const Offset(0, -0.6))),
-                            child: Column(
-                              mainAxisSize: MainAxisSize.min,
-                              children: [
-                                SlideTransition(
-                                  position: _revealAnimGrade.drive(Tween(begin: Offset.zero, end: const Offset(0, -0.9))),
-                                  child: Text(
-                                    ["legendary", "epic", "rare", "uncommon", "common"][5 - widget.grade.value.value].i18n,
-                                    style: TextStyle(
-                                      fontSize: 46.0,
-                                      fontWeight: FontWeight.bold,
-                                      color: gradeColor(context: context, value: widget.grade.value.value),
-                                      shadows: [
-                                        Shadow(
-                                          color: gradeColor(context: context, value: widget.grade.value.value).withOpacity(.5),
-                                          blurRadius: 24.0,
-                                        ),
-                                        Shadow(
-                                          color: gradeColor(context: context, value: widget.grade.value.value).withOpacity(.3),
-                                          offset: const Offset(-3, -3),
-                                        ),
-                                      ],
-                                    ),
-                                  ),
-                                ),
-                                const SizedBox(height: 32.0),
-                                ScaleTransition(
-                                  scale: CurvedAnimation(curve: Curves.easeInOutBack, parent: _revealAnimParticle.drive(Tween(begin: 0.6, end: 1.0))),
-                                  child: CustomPaint(
-                                    painter: PimpPainter(
-                                      particle: Sprinkles(),
-                                      controller: _revealAnimParticle,
-                                      seed: seed + 1,
-                                      shouldPaint: shouldPaint,
-                                    ),
-                                    child: CustomPaint(
-                                      painter: PimpPainter(
-                                        particle: Sprinkles(),
-                                        controller: _revealAnimParticle,
-                                        seed: seed,
-                                        shouldPaint: shouldPaint,
-                                      ),
-                                      child: RotationTransition(
-                                        turns:
-                                            CurvedAnimation(curve: Curves.easeInBack, parent: _revealAnimGrade).drive(Tween(begin: 0.95, end: 1.0)),
-                                        child: GradeValueWidget(
-                                          widget.grade.value,
-                                          fill: true,
-                                          contrast: true,
-                                          shadow: true,
-                                          outline: true,
-                                          size: 100.0,
-                                        ),
-                                      ),
-                                    ),
-                                  ),
-                                ),
-                              ],
-                            ),
-                          ),
-                        ),
-                      );
-                    },
-                  ),
-              ],
-            );
-          }),
-    );
-  }
-}
-
-class PimpPainter extends CustomPainter {
-  PimpPainter({required this.particle, required this.seed, required this.controller, required this.shouldPaint}) : super(repaint: controller);
-
-  final Particle particle;
-  final int seed;
-  final AnimationController controller;
-  final bool shouldPaint;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    if (shouldPaint) {
-      canvas.translate(size.width / 2, size.height / 2);
-      particle.paint(canvas, size, controller.value, seed);
-    }
-  }
-
-  @override
-  bool shouldRepaint(PimpPainter oldDelegate) => shouldPaint;
-}
-
-Color randomColor(int c) {
-  c = c % 5;
-  if (c == 0) return Colors.red.shade300;
-  if (c == 1) return Colors.green.shade300;
-  if (c == 2) return Colors.orange.shade300;
-  if (c == 3) return Colors.blue.shade300;
-  if (c == 4) return Colors.pink.shade300;
-  if (c == 5) return Colors.brown.shade300;
-  return Colors.black;
-}
-
-class Sprinkles extends Particle {
-  @override
-  void paint(Canvas canvas, Size size, progress, seed) {
-    Random random = Random(seed);
-    int randomMirrorOffset = random.nextInt(8) + 1;
-    CompositeParticle(children: [
-      Firework(),
-      RectangleMirror.builder(
-          numberOfParticles: 6,
-          particleBuilder: (n) {
-            return AnimatedPositionedParticle(
-              begin: const Offset(0.0, -10.0),
-              end: const Offset(0.0, -60.0),
-              child: FadingRect(width: 5.0, height: 15.0, color: randomColor(n)),
-            );
-          },
-          initialDistance: -pi / randomMirrorOffset),
-    ]).paint(canvas, size, progress, seed);
-  }
-}
+import 'dart:math';
+import 'dart:ui';
+
+import 'package:animated_background/animated_background.dart' as bg;
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/pages/home/particle.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:rive/rive.dart' as rive;
+
+import 'new_grades.i18n.dart';
+
+class SurpriseGrade extends StatefulWidget {
+  const SurpriseGrade(this.grade, {Key? key}) : super(key: key);
+
+  final Grade grade;
+
+  @override
+  State<SurpriseGrade> createState() => _SurpriseGradeState();
+}
+
+class _SurpriseGradeState extends State<SurpriseGrade>
+    with TickerProviderStateMixin {
+  late AnimationController _revealAnimFade;
+  late AnimationController _revealAnimScale;
+  late AnimationController _revealAnimGrade;
+  late AnimationController _revealAnimParticle;
+  late rive.RiveAnimationController _controller;
+
+  @override
+  void initState() {
+    super.initState();
+    _revealAnimFade = AnimationController(
+        vsync: this, duration: const Duration(milliseconds: 500));
+    _revealAnimScale = AnimationController(
+        vsync: this, duration: const Duration(milliseconds: 300));
+    _revealAnimGrade =
+        AnimationController(vsync: this, duration: const Duration(seconds: 1));
+    _revealAnimParticle =
+        AnimationController(vsync: this, duration: const Duration(seconds: 2));
+    _revealAnimScale.animateTo(0.7, duration: Duration.zero);
+    _controller = rive.SimpleAnimation('Timeline 1', autoplay: false);
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      _revealAnimFade.animateTo(1.0, curve: Curves.easeInOut);
+      Future.delayed(const Duration(milliseconds: 200), () {
+        _revealAnimScale.animateTo(1.0, curve: Curves.easeInOut).then((_) {
+          setState(() => subtitle = true);
+        });
+      });
+    });
+
+    seed = Random().nextInt(100000000);
+  }
+
+  @override
+  void dispose() {
+    _revealAnimFade.dispose();
+    _revealAnimScale.dispose();
+    _revealAnimGrade.dispose();
+    _revealAnimParticle.dispose();
+    _controller.dispose();
+    super.dispose();
+  }
+
+  bool hold = false;
+  bool subtitle = false;
+  late int seed;
+
+  void reveal() async {
+    if (!subtitle) {
+      _revealAnimParticle.animateBack(0.0,
+          curve: Curves.fastLinearToSlowEaseIn,
+          duration: const Duration(milliseconds: 300));
+      await Future.delayed(const Duration(milliseconds: 50));
+      _revealAnimGrade.animateBack(0.0, curve: Curves.fastLinearToSlowEaseIn);
+      await Future.delayed(const Duration(milliseconds: 50));
+      _revealAnimFade.animateBack(0.0, curve: Curves.easeInOut);
+      _revealAnimScale.animateBack(0.0, curve: Curves.easeInOut);
+      if (mounted) Navigator.of(context).pop();
+      return;
+    }
+    subtitle = false;
+    setState(() => hold = false);
+    _controller.isActive = true;
+    await Future.delayed(const Duration(seconds: 2));
+    if (mounted)
+      _revealAnimGrade.animateTo(1.0, curve: Curves.fastLinearToSlowEaseIn);
+    await Future.delayed(const Duration(milliseconds: 700));
+    if (mounted)
+      await _revealAnimParticle.animateTo(1.0,
+          curve: Curves.fastLinearToSlowEaseIn);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return AnimatedBuilder(
+      animation: _revealAnimFade,
+      builder: (context, child) {
+        return FadeTransition(
+          opacity: _revealAnimFade,
+          child: Material(
+            color: Colors.black.withOpacity(.75),
+            child: Container(
+              color: Theme.of(context).colorScheme.secondary.withOpacity(.05),
+              child: Container(
+                decoration: const BoxDecoration(
+                  gradient: RadialGradient(
+                    colors: [Colors.transparent, Colors.black],
+                    radius: 1.5,
+                    stops: [0.2, 1.0],
+                  ),
+                ),
+                child: bg.AnimatedBackground(
+                  vsync: this,
+                  behaviour: bg.RandomParticleBehaviour(
+                    options: bg.ParticleOptions(
+                      baseColor: Theme.of(context).colorScheme.secondary,
+                      spawnMinSpeed: 5.0,
+                      spawnMaxSpeed: 10.0,
+                      minOpacity: .05,
+                      maxOpacity: .08,
+                      spawnMinRadius: 30.0,
+                      spawnMaxRadius: 50.0,
+                      particleCount: 20,
+                    ),
+                  ),
+                  child: ScaleTransition(
+                    scale: _revealAnimScale,
+                    child: child,
+                  ),
+                ),
+              ),
+            ),
+          ),
+        );
+      },
+      child: AnimatedBuilder(
+          animation: _revealAnimGrade,
+          builder: (context, child) {
+            return Stack(
+              alignment: Alignment.center,
+              children: [
+                Column(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  children: [
+                    SlideTransition(
+                      position: _revealAnimGrade.drive(
+                          Tween(begin: Offset.zero, end: const Offset(0, 0.7))),
+                      child: AnimatedScale(
+                        scale: hold ? 1.1 : 1.0,
+                        curve: Curves.easeOutBack,
+                        duration: const Duration(milliseconds: 200),
+                        child: GestureDetector(
+                          onLongPressDown: (_) => setState(() => hold = true),
+                          onLongPressEnd: (_) => reveal(),
+                          onLongPressCancel: reveal,
+                          child: ScaleTransition(
+                            scale: CurvedAnimation(
+                                curve: Curves.easeInOut,
+                                parent: _revealAnimGrade
+                                    .drive(Tween(begin: 1.0, end: 0.8))),
+                            child: Stack(
+                              alignment: Alignment.center,
+                              children: [
+                                SizedBox(
+                                  width: 300,
+                                  height: 300,
+                                  child: rive.RiveAnimation.asset(
+                                    "assets/animations/backpack-2.riv",
+                                    fit: BoxFit.contain,
+                                    controllers: [_controller],
+                                    antialiasing: false,
+                                  ),
+                                ),
+                                SlideTransition(
+                                  position: _revealAnimParticle.drive(Tween(
+                                      begin: const Offset(0, 0.3),
+                                      end: const Offset(0, 0.8))),
+                                  child: FadeTransition(
+                                    opacity: _revealAnimParticle,
+                                    child: ClipRRect(
+                                      borderRadius: BorderRadius.circular(24.0),
+                                      child: BackdropFilter(
+                                        filter: ImageFilter.blur(
+                                            sigmaX: 32.0, sigmaY: 32.0),
+                                        child: Container(
+                                          width: double.infinity,
+                                          padding: const EdgeInsets.symmetric(
+                                              horizontal: 32.0, vertical: 20.0),
+                                          decoration: BoxDecoration(
+                                            color: Colors.white.withOpacity(.3),
+                                            borderRadius:
+                                                BorderRadius.circular(24.0),
+                                            border: Border.all(
+                                                color: Colors.black
+                                                    .withOpacity(.3),
+                                                width: 1.0),
+                                          ),
+                                          child: Row(
+                                            children: [
+                                              Expanded(
+                                                child: Column(
+                                                  crossAxisAlignment:
+                                                      CrossAxisAlignment.start,
+                                                  mainAxisSize:
+                                                      MainAxisSize.min,
+                                                  children: [
+                                                    if (widget.grade
+                                                            .description !=
+                                                        "")
+                                                      Text(
+                                                        widget
+                                                            .grade.description,
+                                                        style: const TextStyle(
+                                                          color: Colors.white,
+                                                          fontWeight:
+                                                              FontWeight.bold,
+                                                          fontSize: 26.0,
+                                                        ),
+                                                        maxLines: 2,
+                                                        overflow: TextOverflow
+                                                            .ellipsis,
+                                                      ),
+                                                    Text(
+                                                      widget.grade.subject
+                                                              .renamedTo ??
+                                                          widget.grade.subject
+                                                              .name
+                                                              .capital(),
+                                                      style: TextStyle(
+                                                          color: Colors.white
+                                                              .withOpacity(.8),
+                                                          fontWeight:
+                                                              FontWeight.bold,
+                                                          fontSize: 24.0,
+                                                          fontStyle: widget
+                                                                  .grade
+                                                                  .subject
+                                                                  .isRenamed
+                                                              ? FontStyle.italic
+                                                              : null),
+                                                      maxLines: 2,
+                                                      overflow:
+                                                          TextOverflow.ellipsis,
+                                                    ),
+                                                    const SizedBox(height: 2),
+                                                    Text(
+                                                      "${widget.grade.value.weight}%",
+                                                      style: TextStyle(
+                                                        color: Colors.white
+                                                            .withOpacity(.7),
+                                                        fontWeight:
+                                                            FontWeight.w600,
+                                                        fontSize: 20.0,
+                                                      ),
+                                                      maxLines: 2,
+                                                      overflow:
+                                                          TextOverflow.ellipsis,
+                                                    ),
+                                                  ],
+                                                ),
+                                              ),
+                                              const SizedBox(width: 20.0),
+                                              Icon(
+                                                SubjectIcon.resolveVariant(
+                                                    subject:
+                                                        widget.grade.subject,
+                                                    context: context),
+                                                color: Colors.white,
+                                                size: 82.0,
+                                              ),
+                                            ],
+                                          ),
+                                        ),
+                                      ),
+                                    ),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+                    const SizedBox(height: 42.0),
+                    AnimatedOpacity(
+                      opacity: subtitle ? 1.0 : 0.0,
+                      duration: const Duration(milliseconds: 300),
+                      child: Text(
+                        "open_subtitle".i18n,
+                        style: TextStyle(
+                          color: Colors.white.withOpacity(.8),
+                          fontWeight: FontWeight.w600,
+                          fontSize: 24.0,
+                        ),
+                      ),
+                    ),
+                  ],
+                ),
+                if (_revealAnimGrade.value > 0)
+                  AnimatedBuilder(
+                    animation: _revealAnimParticle,
+                    builder: (context, child) {
+                      bool shouldPaint = false;
+                      if (_revealAnimParticle.status ==
+                              AnimationStatus.forward ||
+                          _revealAnimParticle.status ==
+                              AnimationStatus.reverse) {
+                        shouldPaint = true;
+                      }
+                      return ScaleTransition(
+                        scale: _revealAnimGrade,
+                        child: FadeTransition(
+                          opacity: _revealAnimGrade,
+                          child: SlideTransition(
+                            position: _revealAnimGrade.drive(Tween(
+                                begin: Offset.zero,
+                                end: const Offset(0, -0.6))),
+                            child: Column(
+                              mainAxisSize: MainAxisSize.min,
+                              children: [
+                                SlideTransition(
+                                  position: _revealAnimGrade.drive(Tween(
+                                      begin: Offset.zero,
+                                      end: const Offset(0, -0.9))),
+                                  child: Text(
+                                    [
+                                      "legendary",
+                                      "epic",
+                                      "rare",
+                                      "uncommon",
+                                      "common"
+                                    ][5 - widget.grade.value.value]
+                                        .i18n,
+                                    style: TextStyle(
+                                      fontSize: 46.0,
+                                      fontWeight: FontWeight.bold,
+                                      color: gradeColor(
+                                          context: context,
+                                          value: widget.grade.value.value),
+                                      shadows: [
+                                        Shadow(
+                                          color: gradeColor(
+                                                  context: context,
+                                                  value:
+                                                      widget.grade.value.value)
+                                              .withOpacity(.5),
+                                          blurRadius: 24.0,
+                                        ),
+                                        Shadow(
+                                          color: gradeColor(
+                                                  context: context,
+                                                  value:
+                                                      widget.grade.value.value)
+                                              .withOpacity(.3),
+                                          offset: const Offset(-3, -3),
+                                        ),
+                                      ],
+                                    ),
+                                  ),
+                                ),
+                                const SizedBox(height: 32.0),
+                                ScaleTransition(
+                                  scale: CurvedAnimation(
+                                      curve: Curves.easeInOutBack,
+                                      parent: _revealAnimParticle
+                                          .drive(Tween(begin: 0.6, end: 1.0))),
+                                  child: CustomPaint(
+                                    painter: PimpPainter(
+                                      particle: Sprinkles(),
+                                      controller: _revealAnimParticle,
+                                      seed: seed + 1,
+                                      shouldPaint: shouldPaint,
+                                    ),
+                                    child: CustomPaint(
+                                      painter: PimpPainter(
+                                        particle: Sprinkles(),
+                                        controller: _revealAnimParticle,
+                                        seed: seed,
+                                        shouldPaint: shouldPaint,
+                                      ),
+                                      child: RotationTransition(
+                                        turns: CurvedAnimation(
+                                                curve: Curves.easeInBack,
+                                                parent: _revealAnimGrade)
+                                            .drive(
+                                                Tween(begin: 0.95, end: 1.0)),
+                                        child: GradeValueWidget(
+                                          widget.grade.value,
+                                          fill: true,
+                                          contrast: true,
+                                          shadow: true,
+                                          outline: true,
+                                          size: 100.0,
+                                        ),
+                                      ),
+                                    ),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ),
+                        ),
+                      );
+                    },
+                  ),
+              ],
+            );
+          }),
+    );
+  }
+}
+
+class PimpPainter extends CustomPainter {
+  PimpPainter(
+      {required this.particle,
+      required this.seed,
+      required this.controller,
+      required this.shouldPaint})
+      : super(repaint: controller);
+
+  final Particle particle;
+  final int seed;
+  final AnimationController controller;
+  final bool shouldPaint;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    if (shouldPaint) {
+      canvas.translate(size.width / 2, size.height / 2);
+      particle.paint(canvas, size, controller.value, seed);
+    }
+  }
+
+  @override
+  bool shouldRepaint(PimpPainter oldDelegate) => shouldPaint;
+}
+
+Color randomColor(int c) {
+  c = c % 5;
+  if (c == 0) return Colors.red.shade300;
+  if (c == 1) return Colors.green.shade300;
+  if (c == 2) return Colors.orange.shade300;
+  if (c == 3) return Colors.blue.shade300;
+  if (c == 4) return Colors.pink.shade300;
+  if (c == 5) return Colors.brown.shade300;
+  return Colors.black;
+}
+
+class Sprinkles extends Particle {
+  @override
+  void paint(Canvas canvas, Size size, progress, seed) {
+    Random random = Random(seed);
+    int randomMirrorOffset = random.nextInt(8) + 1;
+    CompositeParticle(children: [
+      Firework(),
+      RectangleMirror.builder(
+          numberOfParticles: 6,
+          particleBuilder: (n) {
+            return AnimatedPositionedParticle(
+              begin: const Offset(0.0, -10.0),
+              end: const Offset(0.0, -60.0),
+              child:
+                  FadingRect(width: 5.0, height: 15.0, color: randomColor(n)),
+            );
+          },
+          initialDistance: -pi / randomMirrorOffset),
+    ]).paint(canvas, size, progress, seed);
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.dart b/refilc_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.dart
old mode 100755
new mode 100644
similarity index 80%
rename from filcnaplo_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.dart
index c62cc45..2984432
--- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.dart
@@ -1,89 +1,92 @@
-import 'dart:io';
-import 'package:filcnaplo/helpers/attachment_helper.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/image_view.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:flutter/material.dart';
-
-import 'homework_attachment_tile.i18n.dart';
-
-class HomeworkAttachmentTile extends StatelessWidget {
-  const HomeworkAttachmentTile(this.attachment, {Key? key}) : super(key: key);
-
-  final HomeworkAttachment attachment;
-
-  Widget buildImage(BuildContext context) {
-    return FutureBuilder<String>(
-      future: attachment.download(context),
-      builder: (context, snapshot) {
-        return snapshot.hasData
-            ? Padding(
-                padding: const EdgeInsets.symmetric(vertical: 4.0),
-                child: ClipRRect(
-                  borderRadius: BorderRadius.circular(12.0),
-                  child: Material(
-                    child: InkWell(
-                      onTap: () {
-                        Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(
-                          builder: (context) => ImageView(snapshot.data!),
-                        ));
-                      },
-                      child: Ink.image(
-                        image: FileImage(File(snapshot.data ?? "")),
-                        height: 200.0,
-                        width: double.infinity,
-                        fit: BoxFit.cover,
-                      ),
-                      borderRadius: BorderRadius.circular(12.0),
-                    ),
-                  ),
-                ),
-              )
-            : Center(
-                child: Padding(
-                padding: const EdgeInsets.all(12.0),
-                child: CircularProgressIndicator(color: Theme.of(context).colorScheme.secondary),
-              ));
-      },
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (attachment.isImage) return buildImage(context);
-
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 4.0),
-      child: InkWell(
-        borderRadius: BorderRadius.circular(12.0),
-        onTap: () {
-          attachment.open(context).then((value) {
-            if (!value) {
-              ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
-                context: context,
-                content: Text("Failed to open attachment".i18n),
-                backgroundColor: AppColors.of(context).red,
-                duration: const Duration(seconds: 1),
-              ));
-            }
-          });
-        },
-        child: Padding(
-          padding: const EdgeInsets.all(8.0),
-          child: Row(children: [
-            const Icon(FeatherIcons.paperclip),
-            Expanded(
-              child: Padding(
-                padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                child: Text(attachment.name, maxLines: 2, overflow: TextOverflow.ellipsis),
-              ),
-            ),
-          ]),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:io';
+import 'package:refilc/helpers/attachment_helper.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/image_view.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:flutter/material.dart';
+
+import 'homework_attachment_tile.i18n.dart';
+
+class HomeworkAttachmentTile extends StatelessWidget {
+  const HomeworkAttachmentTile(this.attachment, {Key? key}) : super(key: key);
+
+  final HomeworkAttachment attachment;
+
+  Widget buildImage(BuildContext context) {
+    return FutureBuilder<String>(
+      future: attachment.download(context),
+      builder: (context, snapshot) {
+        return snapshot.hasData
+            ? Padding(
+                padding: const EdgeInsets.symmetric(vertical: 4.0),
+                child: ClipRRect(
+                  borderRadius: BorderRadius.circular(12.0),
+                  child: Material(
+                    child: InkWell(
+                      onTap: () {
+                        Navigator.of(context, rootNavigator: true)
+                            .push(MaterialPageRoute(
+                          builder: (context) => ImageView(snapshot.data!),
+                        ));
+                      },
+                      child: Ink.image(
+                        image: FileImage(File(snapshot.data ?? "")),
+                        height: 200.0,
+                        width: double.infinity,
+                        fit: BoxFit.cover,
+                      ),
+                      borderRadius: BorderRadius.circular(12.0),
+                    ),
+                  ),
+                ),
+              )
+            : Center(
+                child: Padding(
+                padding: const EdgeInsets.all(12.0),
+                child: CircularProgressIndicator(
+                    color: Theme.of(context).colorScheme.secondary),
+              ));
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (attachment.isImage) return buildImage(context);
+
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 4.0),
+      child: InkWell(
+        borderRadius: BorderRadius.circular(12.0),
+        onTap: () {
+          attachment.open(context).then((value) {
+            if (!value) {
+              ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
+                context: context,
+                content: Text("Failed to open attachment".i18n),
+                backgroundColor: AppColors.of(context).red,
+                duration: const Duration(seconds: 1),
+              ));
+            }
+          });
+        },
+        child: Padding(
+          padding: const EdgeInsets.all(8.0),
+          child: Row(children: [
+            const Icon(FeatherIcons.paperclip),
+            Expanded(
+              child: Padding(
+                padding: const EdgeInsets.symmetric(horizontal: 12.0),
+                child: Text(attachment.name,
+                    maxLines: 2, overflow: TextOverflow.ellipsis),
+              ),
+            ),
+          ]),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.i18n.dart
index f68c6d5..170969f
--- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/homework/homework_attachment_tile.i18n.dart
@@ -1,21 +1,21 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Failed to open attachment": "Failed to open attachment",
-        },
-        "hu_hu": {
-          "Failed to open attachment": "Nem sikerült megnyitni a mellékletet",
-        },
-        "de_de": {
-          "Failed to open attachment": "Anhang konnte nicht geöffnet werden",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Failed to open attachment": "Failed to open attachment",
+        },
+        "hu_hu": {
+          "Failed to open attachment": "Nem sikerült megnyitni a mellékletet",
+        },
+        "de_de": {
+          "Failed to open attachment": "Anhang konnte nicht geöffnet werden",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart b/refilc_mobile_ui/lib/common/widgets/homework/homework_tile.dart
old mode 100755
new mode 100644
similarity index 87%
rename from filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/homework/homework_tile.dart
index 2013519..6158da3
--- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/homework/homework_tile.dart
@@ -1,111 +1,116 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-
-class HomeworkTile extends StatelessWidget {
-  const HomeworkTile(this.homework,
-      {Key? key, this.onTap, this.padding, this.censored = false})
-      : super(key: key);
-
-  final Homework homework;
-  final void Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-  final bool censored;
-
-  @override
-  Widget build(BuildContext context) {
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      borderRadius: BorderRadius.circular(8.0),
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: onTap,
-          shape:
-              RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-          leading: SizedBox(
-            width: 44,
-            height: 44,
-            child: censored
-                ? Container(
-                    decoration: BoxDecoration(
-                      color: AppColors.of(context).text.withOpacity(.55),
-                      borderRadius: BorderRadius.circular(60.0),
-                    ),
-                  )
-                : Padding(
-                    padding: const EdgeInsets.only(top: 2.0),
-                    child: Icon(
-                      SubjectIcon.resolveVariant(
-                          subjectName: homework.subject.name, context: context),
-                      size: 28.0,
-                      color: AppColors.of(context).text.withOpacity(.75),
-                    ),
-                  ),
-          ),
-          title: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 160,
-                      height: 15,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.85),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  homework.subject.renamedTo ?? homework.subject.name.capital(),
-                  maxLines: 2,
-                  overflow: TextOverflow.ellipsis,
-                  style: TextStyle(fontWeight: FontWeight.w600, fontStyle: homework.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
-                ),
-          subtitle: censored
-              ? Wrap(
-                  children: [
-                    Container(
-                      width: 100,
-                      height: 10,
-                      decoration: BoxDecoration(
-                        color: AppColors.of(context).text.withOpacity(.45),
-                        borderRadius: BorderRadius.circular(8.0),
-                      ),
-                    ),
-                  ],
-                )
-              : Text(
-                  homework.content.escapeHtml().replaceAll('\n', ' '),
-                  maxLines: 1,
-                  overflow: TextOverflow.ellipsis,
-                  style: const TextStyle(fontWeight: FontWeight.w500),
-                ),
-          trailing: censored
-              ? Container(
-                  width: 15,
-                  height: 15,
-                  decoration: BoxDecoration(
-                    color: AppColors.of(context).text.withOpacity(.45),
-                    borderRadius: BorderRadius.circular(8.0),
-                  ),
-                )
-              : Icon(
-                  FeatherIcons.home,
-                  color: AppColors.of(context).text.withOpacity(.75),
-                ),
-          minLeadingWidth: 0,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+
+class HomeworkTile extends StatelessWidget {
+  const HomeworkTile(this.homework,
+      {Key? key, this.onTap, this.padding, this.censored = false})
+      : super(key: key);
+
+  final Homework homework;
+  final void Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+  final bool censored;
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    return Material(
+      color: Theme.of(context).colorScheme.background,
+      borderRadius: BorderRadius.circular(8.0),
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: onTap,
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+          leading: SizedBox(
+            width: 44,
+            height: 44,
+            child: censored
+                ? Container(
+                    decoration: BoxDecoration(
+                      color: AppColors.of(context).text.withOpacity(.55),
+                      borderRadius: BorderRadius.circular(60.0),
+                    ),
+                  )
+                : Padding(
+                    padding: const EdgeInsets.only(top: 2.0),
+                    child: Icon(
+                      SubjectIcon.resolveVariant(
+                          subjectName: homework.subject.name, context: context),
+                      size: 28.0,
+                      color: AppColors.of(context).text.withOpacity(.75),
+                    ),
+                  ),
+          ),
+          title: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 160,
+                      height: 15,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.85),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  homework.subject.renamedTo ?? homework.subject.name.capital(),
+                  maxLines: 2,
+                  overflow: TextOverflow.ellipsis,
+                  style: TextStyle(
+                      fontWeight: FontWeight.w600,
+                      fontStyle: homework.subject.isRenamed &&
+                              settingsProvider.renamedSubjectsItalics
+                          ? FontStyle.italic
+                          : null),
+                ),
+          subtitle: censored
+              ? Wrap(
+                  children: [
+                    Container(
+                      width: 100,
+                      height: 10,
+                      decoration: BoxDecoration(
+                        color: AppColors.of(context).text.withOpacity(.45),
+                        borderRadius: BorderRadius.circular(8.0),
+                      ),
+                    ),
+                  ],
+                )
+              : Text(
+                  homework.content.escapeHtml().replaceAll('\n', ' '),
+                  maxLines: 1,
+                  overflow: TextOverflow.ellipsis,
+                  style: const TextStyle(fontWeight: FontWeight.w500),
+                ),
+          trailing: censored
+              ? Container(
+                  width: 15,
+                  height: 15,
+                  decoration: BoxDecoration(
+                    color: AppColors.of(context).text.withOpacity(.45),
+                    borderRadius: BorderRadius.circular(8.0),
+                  ),
+                )
+              : Icon(
+                  FeatherIcons.home,
+                  color: AppColors.of(context).text.withOpacity(.75),
+                ),
+          minLeadingWidth: 0,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_view.dart b/refilc_mobile_ui/lib/common/widgets/homework/homework_view.dart
old mode 100755
new mode 100644
similarity index 86%
rename from filcnaplo_mobile_ui/lib/common/widgets/homework/homework_view.dart
rename to refilc_mobile_ui/lib/common/widgets/homework/homework_view.dart
index 8e26d92..8420492
--- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/homework/homework_view.dart
@@ -1,104 +1,104 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/common/detail.dart';
-import 'package:filcnaplo_mobile_ui/common/sliding_bottom_sheet.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_attachment_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-import 'package:flutter_linkify/flutter_linkify.dart';
-import 'package:provider/provider.dart';
-import 'homework_view.i18n.dart';
-
-class HomeworkView extends StatelessWidget {
-  const HomeworkView(this.homework, {Key? key}) : super(key: key);
-
-  final Homework homework;
-
-  static show(Homework homework, {required BuildContext context}) {
-    showSlidingBottomSheet(context: context, child: HomeworkView(homework));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> attachmentTiles = [];
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    for (var attachment in homework.attachments) {
-      attachmentTiles.add(Padding(
-        padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4.0),
-        child: HomeworkAttachmentTile(
-          attachment,
-        ),
-      ));
-    }
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          // Header
-          ListTile(
-            leading: Icon(
-              SubjectIcon.resolveVariant(
-                  subjectName: homework.subject.name, context: context),
-              size: 36.0,
-            ),
-            title: Text(
-              homework.subject.renamedTo ?? homework.subject.name.capital(),
-              maxLines: 1,
-              overflow: TextOverflow.ellipsis,
-              style: TextStyle(
-                  fontWeight: FontWeight.w600,
-                  fontStyle: homework.subject.isRenamed &&
-                          settingsProvider.renamedSubjectsItalics
-                      ? FontStyle.italic
-                      : null),
-            ),
-            subtitle: Text(
-              (homework.teacher.isRenamed
-                      ? homework.teacher.renamedTo
-                      : homework.teacher.name) ??
-                  '',
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-            trailing: Text(
-              homework.date.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Details
-          if (homework.deadline.year != 0)
-            Detail(
-                title: "deadline".i18n,
-                description: homework.deadline.format(context)),
-          Padding(
-            padding:
-                const EdgeInsets.symmetric(horizontal: 18.0, vertical: 6.0),
-            child: SelectableLinkify(
-              text: homework.content.escapeHtml(),
-              options: const LinkifyOptions(looseUrl: true, removeWww: true),
-              onOpen: (link) {
-                launch(link.url,
-                    customTabsOption: CustomTabsOption(
-                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-                      showPageTitle: true,
-                    ));
-              },
-              style: const TextStyle(fontWeight: FontWeight.w400),
-            ),
-          ),
-
-          // Attachments
-          ...attachmentTiles,
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/common/detail.dart';
+import 'package:refilc_mobile_ui/common/sliding_bottom_sheet.dart';
+import 'package:refilc_mobile_ui/common/widgets/homework/homework_attachment_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+import 'package:flutter_linkify/flutter_linkify.dart';
+import 'package:provider/provider.dart';
+import 'homework_view.i18n.dart';
+
+class HomeworkView extends StatelessWidget {
+  const HomeworkView(this.homework, {Key? key}) : super(key: key);
+
+  final Homework homework;
+
+  static show(Homework homework, {required BuildContext context}) {
+    showSlidingBottomSheet(context: context, child: HomeworkView(homework));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    List<Widget> attachmentTiles = [];
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    for (var attachment in homework.attachments) {
+      attachmentTiles.add(Padding(
+        padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4.0),
+        child: HomeworkAttachmentTile(
+          attachment,
+        ),
+      ));
+    }
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          // Header
+          ListTile(
+            leading: Icon(
+              SubjectIcon.resolveVariant(
+                  subjectName: homework.subject.name, context: context),
+              size: 36.0,
+            ),
+            title: Text(
+              homework.subject.renamedTo ?? homework.subject.name.capital(),
+              maxLines: 1,
+              overflow: TextOverflow.ellipsis,
+              style: TextStyle(
+                  fontWeight: FontWeight.w600,
+                  fontStyle: homework.subject.isRenamed &&
+                          settingsProvider.renamedSubjectsItalics
+                      ? FontStyle.italic
+                      : null),
+            ),
+            subtitle: Text(
+              (homework.teacher.isRenamed
+                      ? homework.teacher.renamedTo
+                      : homework.teacher.name) ??
+                  '',
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+            trailing: Text(
+              homework.date.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Details
+          if (homework.deadline.year != 0)
+            Detail(
+                title: "deadline".i18n,
+                description: homework.deadline.format(context)),
+          Padding(
+            padding:
+                const EdgeInsets.symmetric(horizontal: 18.0, vertical: 6.0),
+            child: SelectableLinkify(
+              text: homework.content.escapeHtml(),
+              options: const LinkifyOptions(looseUrl: true, removeWww: true),
+              onOpen: (link) {
+                launch(link.url,
+                    customTabsOption: CustomTabsOption(
+                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+                      showPageTitle: true,
+                    ));
+              },
+              style: const TextStyle(fontWeight: FontWeight.w400),
+            ),
+          ),
+
+          // Attachments
+          ...attachmentTiles,
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_view.i18n.dart b/refilc_mobile_ui/lib/common/widgets/homework/homework_view.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/homework/homework_view.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/homework/homework_view.i18n.dart
index 6daea6e..1e9652b
--- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_view.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/homework/homework_view.i18n.dart
@@ -1,21 +1,21 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "deadline": "Deadline",
-        },
-        "hu_hu": {
-          "deadline": "Határidő",
-        },
-        "de_de": {
-          "deadline": "Termin",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "deadline": "Deadline",
+        },
+        "hu_hu": {
+          "deadline": "Határidő",
+        },
+        "de_de": {
+          "deadline": "Termin",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_viewable.dart b/refilc_mobile_ui/lib/common/widgets/homework/homework_viewable.dart
old mode 100755
new mode 100644
similarity index 60%
rename from filcnaplo_mobile_ui/lib/common/widgets/homework/homework_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/homework/homework_viewable.dart
index 29c69fa..0ae86c7
--- a/filcnaplo_mobile_ui/lib/common/widgets/homework/homework_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/homework/homework_viewable.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo_kreta_api/models/homework.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_view.dart';
-import 'package:flutter/material.dart';
-
-class HomeworkViewable extends StatelessWidget {
-  const HomeworkViewable(this.homework, {Key? key}) : super(key: key);
-
-  final Homework homework;
-
-  @override
-  Widget build(BuildContext context) {
-    return HomeworkTile(
-      homework,
-      onTap: () => HomeworkView.show(homework, context: context),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc_mobile_ui/common/widgets/homework/homework_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/homework/homework_view.dart';
+import 'package:flutter/material.dart';
+
+class HomeworkViewable extends StatelessWidget {
+  const HomeworkViewable(this.homework, {Key? key}) : super(key: key);
+
+  final Homework homework;
+
+  @override
+  Widget build(BuildContext context) {
+    return HomeworkTile(
+      homework,
+      onTap: () => HomeworkView.show(homework, context: context),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.dart b/refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.dart
old mode 100755
new mode 100644
similarity index 91%
rename from filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.dart
index 68540ab..f1ac08a
--- a/filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.dart
@@ -1,81 +1,81 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'changed_lesson_tile.i18n.dart';
-
-class ChangedLessonTile extends StatelessWidget {
-  const ChangedLessonTile(this.lesson, {Key? key, this.onTap, this.padding})
-      : super(key: key);
-
-  final Lesson lesson;
-  final void Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    String lessonIndexTrailing = "";
-
-    // Only put a trailing . if its a digit
-    if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
-
-    Color accent = Theme.of(context).colorScheme.secondary;
-
-    if (lesson.substituteTeacher?.name != '') {
-      accent = AppColors.of(context).yellow;
-    }
-
-    if (lesson.status?.name == "Elmaradt") {
-      accent = AppColors.of(context).red;
-    }
-
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      borderRadius: BorderRadius.circular(14.0),
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: onTap,
-          shape:
-              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-          leading: SizedBox(
-            width: 44.0,
-            height: 44.0,
-            child: Center(
-              child: Text(
-                lesson.lessonIndex + lessonIndexTrailing,
-                textAlign: TextAlign.center,
-                style: TextStyle(
-                  fontSize: 30.0,
-                  fontWeight: FontWeight.w600,
-                  color: accent,
-                ),
-              ),
-            ),
-          ),
-          title: Text(
-            lesson.substituteTeacher?.name != ""
-                ? "substituted".i18n
-                : "cancelled".i18n,
-            maxLines: 2,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w600),
-          ),
-          subtitle: Text(
-            lesson.subject.renamedTo ?? lesson.subject.name.capital(),
-            maxLines: 1,
-            overflow: TextOverflow.ellipsis,
-            style: TextStyle(
-                fontWeight: FontWeight.w500,
-                fontStyle: lesson.subject.isRenamed ? FontStyle.italic : null),
-          ),
-          trailing: const Icon(FeatherIcons.arrowRight),
-          minLeadingWidth: 0,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'changed_lesson_tile.i18n.dart';
+
+class ChangedLessonTile extends StatelessWidget {
+  const ChangedLessonTile(this.lesson, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final Lesson lesson;
+  final void Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    String lessonIndexTrailing = "";
+
+    // Only put a trailing . if its a digit
+    if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
+
+    Color accent = Theme.of(context).colorScheme.secondary;
+
+    if (lesson.substituteTeacher?.name != '') {
+      accent = AppColors.of(context).yellow;
+    }
+
+    if (lesson.status?.name == "Elmaradt") {
+      accent = AppColors.of(context).red;
+    }
+
+    return Material(
+      color: Theme.of(context).colorScheme.background,
+      borderRadius: BorderRadius.circular(14.0),
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: onTap,
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+          leading: SizedBox(
+            width: 44.0,
+            height: 44.0,
+            child: Center(
+              child: Text(
+                lesson.lessonIndex + lessonIndexTrailing,
+                textAlign: TextAlign.center,
+                style: TextStyle(
+                  fontSize: 30.0,
+                  fontWeight: FontWeight.w600,
+                  color: accent,
+                ),
+              ),
+            ),
+          ),
+          title: Text(
+            lesson.substituteTeacher?.name != ""
+                ? "substituted".i18n
+                : "cancelled".i18n,
+            maxLines: 2,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w600),
+          ),
+          subtitle: Text(
+            lesson.subject.renamedTo ?? lesson.subject.name.capital(),
+            maxLines: 1,
+            overflow: TextOverflow.ellipsis,
+            style: TextStyle(
+                fontWeight: FontWeight.w500,
+                fontStyle: lesson.subject.isRenamed ? FontStyle.italic : null),
+          ),
+          trailing: const Icon(FeatherIcons.arrowRight),
+          minLeadingWidth: 0,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.i18n.dart
index 71be760..fa50d6b
--- a/filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_tile.i18n.dart
@@ -1,24 +1,24 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "cancelled": "Cancelled lesson",
-          "substituted": "Substituted lesson",
-        },
-        "hu_hu": {
-          "cancelled": "Elmaradó óra",
-          "substituted": "Helyettesített óra",
-        },
-        "de_de": {
-          "cancelled": "Abgesagte Stunde",
-          "substituted": "Vertretene Stunden",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "cancelled": "Cancelled lesson",
+          "substituted": "Substituted lesson",
+        },
+        "hu_hu": {
+          "cancelled": "Elmaradó óra",
+          "substituted": "Helyettesített óra",
+        },
+        "de_de": {
+          "cancelled": "Abgesagte Stunde",
+          "substituted": "Vertretene Stunden",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_viewable.dart b/refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_viewable.dart
old mode 100755
new mode 100644
similarity index 61%
rename from filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_viewable.dart
index 65e7457..00e44a5
--- a/filcnaplo_mobile_ui/lib/common/widgets/lesson/changed_lesson_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/lesson/changed_lesson_viewable.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_tile.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.dart';
-import 'package:flutter/material.dart';
-
-class ChangedLessonViewable extends StatelessWidget {
-  const ChangedLessonViewable(this.lesson, {Key? key}) : super(key: key);
-
-  final Lesson lesson;
-
-  @override
-  Widget build(BuildContext context) {
-    return ChangedLessonTile(
-      lesson,
-      onTap: () => TimetablePage.jump(context, lesson: lesson),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/widgets/lesson/changed_lesson_tile.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
+import 'package:flutter/material.dart';
+
+class ChangedLessonViewable extends StatelessWidget {
+  const ChangedLessonViewable(this.lesson, {Key? key}) : super(key: key);
+
+  final Lesson lesson;
+
+  @override
+  Widget build(BuildContext context) {
+    return ChangedLessonTile(
+      lesson,
+      onTap: () => TimetablePage.jump(context, lesson: lesson),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_view.dart b/refilc_mobile_ui/lib/common/widgets/lesson/lesson_view.dart
old mode 100755
new mode 100644
similarity index 89%
rename from filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_view.dart
rename to refilc_mobile_ui/lib/common/widgets/lesson/lesson_view.dart
index fe5bf88..9028a95
--- a/filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/lesson/lesson_view.dart
@@ -1,106 +1,106 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_card.dart';
-import 'package:filcnaplo_mobile_ui/common/detail.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'lesson_view.i18n.dart';
-
-class LessonView extends StatelessWidget {
-  const LessonView(this.lesson, {Key? key}) : super(key: key);
-
-  final Lesson lesson;
-
-  @override
-  Widget build(BuildContext context) {
-    Color accent = Theme.of(context).colorScheme.secondary;
-    String lessonIndexTrailing = "";
-
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
-
-    if (lesson.substituteTeacher != null &&
-        lesson.substituteTeacher?.name != "") {
-      accent = AppColors.of(context).yellow;
-    }
-
-    if (lesson.status?.name == "Elmaradt") {
-      accent = AppColors.of(context).red;
-    }
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          // Header
-          ListTile(
-            leading: Padding(
-              padding: const EdgeInsets.only(left: 8.0),
-              child: Text(
-                lesson.lessonIndex + lessonIndexTrailing,
-                textAlign: TextAlign.center,
-                style: TextStyle(
-                  fontSize: 38.0,
-                  fontWeight: FontWeight.w600,
-                  color: accent,
-                ),
-              ),
-            ),
-            title: Text(
-              lesson.subject.renamedTo ?? lesson.subject.name.capital(),
-              maxLines: 1,
-              overflow: TextOverflow.ellipsis,
-              style: TextStyle(
-                  fontWeight: FontWeight.w600,
-                  fontStyle: lesson.subject.isRenamed &&
-                          settingsProvider.renamedSubjectsItalics
-                      ? FontStyle.italic
-                      : null),
-            ),
-            subtitle: Text(
-              ((lesson.substituteTeacher == null ||
-                          lesson.substituteTeacher!.name == "")
-                      ? (lesson.teacher.isRenamed
-                          ? lesson.teacher.renamedTo
-                          : lesson.teacher.name)
-                      : (lesson.substituteTeacher!.isRenamed
-                          ? lesson.substituteTeacher!.renamedTo
-                          : lesson.substituteTeacher!.name)) ??
-                  '',
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-            trailing: Text(
-              lesson.date.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Details
-          if (lesson.room != "")
-            Detail(
-                title: "Room".i18n,
-                description: lesson.room.replaceAll("_", " ")),
-          if (lesson.description != "")
-            Detail(title: "Description".i18n, description: lesson.description),
-          if (lesson.lessonYearIndex != null)
-            Detail(
-                title: "Lesson Number".i18n,
-                description: "${lesson.lessonYearIndex}."),
-          if (lesson.groupName != "")
-            Detail(title: "Group".i18n, description: lesson.groupName),
-        ],
-      ),
-    );
-  }
-
-  static show(Lesson lesson, {required BuildContext context}) {
-    showBottomCard(context: context, child: LessonView(lesson));
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/bottom_card.dart';
+import 'package:refilc_mobile_ui/common/detail.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'lesson_view.i18n.dart';
+
+class LessonView extends StatelessWidget {
+  const LessonView(this.lesson, {Key? key}) : super(key: key);
+
+  final Lesson lesson;
+
+  @override
+  Widget build(BuildContext context) {
+    Color accent = Theme.of(context).colorScheme.secondary;
+    String lessonIndexTrailing = "";
+
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
+
+    if (lesson.substituteTeacher != null &&
+        lesson.substituteTeacher?.name != "") {
+      accent = AppColors.of(context).yellow;
+    }
+
+    if (lesson.status?.name == "Elmaradt") {
+      accent = AppColors.of(context).red;
+    }
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          // Header
+          ListTile(
+            leading: Padding(
+              padding: const EdgeInsets.only(left: 8.0),
+              child: Text(
+                lesson.lessonIndex + lessonIndexTrailing,
+                textAlign: TextAlign.center,
+                style: TextStyle(
+                  fontSize: 38.0,
+                  fontWeight: FontWeight.w600,
+                  color: accent,
+                ),
+              ),
+            ),
+            title: Text(
+              lesson.subject.renamedTo ?? lesson.subject.name.capital(),
+              maxLines: 1,
+              overflow: TextOverflow.ellipsis,
+              style: TextStyle(
+                  fontWeight: FontWeight.w600,
+                  fontStyle: lesson.subject.isRenamed &&
+                          settingsProvider.renamedSubjectsItalics
+                      ? FontStyle.italic
+                      : null),
+            ),
+            subtitle: Text(
+              ((lesson.substituteTeacher == null ||
+                          lesson.substituteTeacher!.name == "")
+                      ? (lesson.teacher.isRenamed
+                          ? lesson.teacher.renamedTo
+                          : lesson.teacher.name)
+                      : (lesson.substituteTeacher!.isRenamed
+                          ? lesson.substituteTeacher!.renamedTo
+                          : lesson.substituteTeacher!.name)) ??
+                  '',
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+            trailing: Text(
+              lesson.date.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Details
+          if (lesson.room != "")
+            Detail(
+                title: "Room".i18n,
+                description: lesson.room.replaceAll("_", " ")),
+          if (lesson.description != "")
+            Detail(title: "Description".i18n, description: lesson.description),
+          if (lesson.lessonYearIndex != null)
+            Detail(
+                title: "Lesson Number".i18n,
+                description: "${lesson.lessonYearIndex}."),
+          if (lesson.groupName != "")
+            Detail(title: "Group".i18n, description: lesson.groupName),
+        ],
+      ),
+    );
+  }
+
+  static show(Lesson lesson, {required BuildContext context}) {
+    showBottomCard(context: context, child: LessonView(lesson));
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_view.i18n.dart b/refilc_mobile_ui/lib/common/widgets/lesson/lesson_view.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_view.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/lesson/lesson_view.i18n.dart
index 7eefaac..7cce274
--- a/filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_view.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/lesson/lesson_view.i18n.dart
@@ -1,30 +1,30 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Room": "Room",
-          "Description": "Description",
-          "Lesson Number": "Lesson Number",
-          "Group": "Group",
-        },
-        "hu_hu": {
-          "Room": "Terem",
-          "Description": "Leírás",
-          "Lesson Number": "Éves óraszám",
-          "Group": "Csoport",
-        },
-        "de_de": {
-          "Room": "Raum",
-          "Description": "Bezeichnung",
-          "Lesson Number": "Ordinalzahl",
-          "Group": "Gruppe",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Room": "Room",
+          "Description": "Description",
+          "Lesson Number": "Lesson Number",
+          "Group": "Group",
+        },
+        "hu_hu": {
+          "Room": "Terem",
+          "Description": "Leírás",
+          "Lesson Number": "Éves óraszám",
+          "Group": "Csoport",
+        },
+        "de_de": {
+          "Room": "Raum",
+          "Description": "Bezeichnung",
+          "Lesson Number": "Ordinalzahl",
+          "Group": "Gruppe",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_viewable.dart b/refilc_mobile_ui/lib/common/widgets/lesson/lesson_viewable.dart
old mode 100755
new mode 100644
similarity index 56%
rename from filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/lesson/lesson_viewable.dart
index d721d70..661753e
--- a/filcnaplo_mobile_ui/lib/common/widgets/lesson/lesson_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/lesson/lesson_viewable.dart
@@ -1,25 +1,26 @@
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/card_handle.dart';
-import 'package:filcnaplo/ui/widgets/lesson/lesson_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/lesson/lesson_view.dart';
-import 'package:flutter/material.dart';
-
-class LessonViewable extends StatelessWidget {
-  const LessonViewable(this.lesson, {Key? key, this.swapDesc = false}) : super(key: key);
-
-  final Lesson lesson;
-  final bool swapDesc;
-
-  @override
-  Widget build(BuildContext context) {
-    final tile = LessonTile(lesson, swapDesc: swapDesc);
-
-    if (lesson.subject.id == '' || tile.lesson.isEmpty) return tile;
-
-    return Viewable(
-      tile: tile,
-      view: CardHandle(child: LessonView(lesson)),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
+import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
+import 'package:flutter/material.dart';
+
+class LessonViewable extends StatelessWidget {
+  const LessonViewable(this.lesson, {Key? key, this.swapDesc = false})
+      : super(key: key);
+
+  final Lesson lesson;
+  final bool swapDesc;
+
+  @override
+  Widget build(BuildContext context) {
+    final tile = LessonTile(lesson, swapDesc: swapDesc);
+
+    if (lesson.subject.id == '' || tile.lesson.isEmpty) return tile;
+
+    return Viewable(
+      tile: tile,
+      view: CardHandle(child: LessonView(lesson)),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/message/attachment_tile.dart b/refilc_mobile_ui/lib/common/widgets/message/attachment_tile.dart
old mode 100755
new mode 100644
similarity index 83%
rename from filcnaplo_mobile_ui/lib/common/widgets/message/attachment_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/message/attachment_tile.dart
index 8ef597d..420bed7
--- a/filcnaplo_mobile_ui/lib/common/widgets/message/attachment_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/message/attachment_tile.dart
@@ -1,83 +1,85 @@
-import 'dart:io';
-
-import 'package:filcnaplo_kreta_api/models/attachment.dart';
-import 'package:filcnaplo/helpers/attachment_helper.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/image_view.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-class AttachmentTile extends StatelessWidget {
-  const AttachmentTile(this.attachment, {Key? key}) : super(key: key);
-
-  final Attachment attachment;
-
-  Widget buildImage(BuildContext context) {
-    return FutureBuilder<String>(
-      future: attachment.download(context),
-      builder: (context, snapshot) {
-        if (snapshot.hasData) {
-          return Padding(
-            padding: const EdgeInsets.symmetric(vertical: 4.0),
-            child: ClipRRect(
-              borderRadius: BorderRadius.circular(12.0),
-              child: Material(
-                child: InkWell(
-                  onTap: () {
-                    showModalBottomSheet(
-                      useRootNavigator: true,
-                      isScrollControlled: true,
-                      context: context,
-                      builder: (context) {
-                        return ImageView(snapshot.data!);
-                      },
-                    );
-                  },
-                  child: Ink.image(
-                    image: FileImage(File(snapshot.data ?? "")),
-                    height: 200.0,
-                    width: double.infinity,
-                    fit: BoxFit.cover,
-                  ),
-                  borderRadius: BorderRadius.circular(12.0),
-                ),
-              ),
-            ),
-          );
-        } else {
-          return Center(
-              child: Padding(
-            padding: const EdgeInsets.all(12.0),
-            child: CircularProgressIndicator(color: Theme.of(context).colorScheme.secondary),
-          ));
-        }
-      },
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (attachment.isImage) return buildImage(context);
-
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 4.0),
-      child: InkWell(
-        borderRadius: BorderRadius.circular(12.0),
-        onTap: () {
-          attachment.open(context);
-        },
-        child: Padding(
-          padding: const EdgeInsets.all(8.0),
-          child: Row(children: [
-            const Icon(FeatherIcons.paperclip),
-            Expanded(
-              child: Padding(
-                padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                child: Text(attachment.name, maxLines: 2, overflow: TextOverflow.ellipsis),
-              ),
-            ),
-          ]),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:io';
+
+import 'package:refilc_kreta_api/models/attachment.dart';
+import 'package:refilc/helpers/attachment_helper.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/image_view.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+class AttachmentTile extends StatelessWidget {
+  const AttachmentTile(this.attachment, {Key? key}) : super(key: key);
+
+  final Attachment attachment;
+
+  Widget buildImage(BuildContext context) {
+    return FutureBuilder<String>(
+      future: attachment.download(context),
+      builder: (context, snapshot) {
+        if (snapshot.hasData) {
+          return Padding(
+            padding: const EdgeInsets.symmetric(vertical: 4.0),
+            child: ClipRRect(
+              borderRadius: BorderRadius.circular(12.0),
+              child: Material(
+                child: InkWell(
+                  onTap: () {
+                    showModalBottomSheet(
+                      useRootNavigator: true,
+                      isScrollControlled: true,
+                      context: context,
+                      builder: (context) {
+                        return ImageView(snapshot.data!);
+                      },
+                    );
+                  },
+                  child: Ink.image(
+                    image: FileImage(File(snapshot.data ?? "")),
+                    height: 200.0,
+                    width: double.infinity,
+                    fit: BoxFit.cover,
+                  ),
+                  borderRadius: BorderRadius.circular(12.0),
+                ),
+              ),
+            ),
+          );
+        } else {
+          return Center(
+              child: Padding(
+            padding: const EdgeInsets.all(12.0),
+            child: CircularProgressIndicator(
+                color: Theme.of(context).colorScheme.secondary),
+          ));
+        }
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (attachment.isImage) return buildImage(context);
+
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 4.0),
+      child: InkWell(
+        borderRadius: BorderRadius.circular(12.0),
+        onTap: () {
+          attachment.open(context);
+        },
+        child: Padding(
+          padding: const EdgeInsets.all(8.0),
+          child: Row(children: [
+            const Icon(FeatherIcons.paperclip),
+            Expanded(
+              child: Padding(
+                padding: const EdgeInsets.symmetric(horizontal: 12.0),
+                child: Text(attachment.name,
+                    maxLines: 2, overflow: TextOverflow.ellipsis),
+              ),
+            ),
+          ]),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/message/image_view.dart b/refilc_mobile_ui/lib/common/widgets/message/image_view.dart
old mode 100755
new mode 100644
similarity index 84%
rename from filcnaplo_mobile_ui/lib/common/widgets/message/image_view.dart
rename to refilc_mobile_ui/lib/common/widgets/message/image_view.dart
index 50f34db..3bf3094
--- a/filcnaplo_mobile_ui/lib/common/widgets/message/image_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/message/image_view.dart
@@ -1,46 +1,47 @@
-import 'dart:io';
-
-import 'package:filcnaplo/helpers/share_helper.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:photo_view/photo_view.dart';
-
-class ImageView extends StatelessWidget {
-  const ImageView(this.path, {Key? key}) : super(key: key);
-
-  final String path;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).scaffoldBackgroundColor,
-      child: SafeArea(
-        minimum: const EdgeInsets.only(top: 24.0),
-        child: Scaffold(
-          appBar: AppBar(
-            leading: BackButton(color: AppColors.of(context).text),
-            actions: [
-              Padding(
-                padding: const EdgeInsets.only(right: 8.0),
-                child: IconButton(
-                  onPressed: () => ShareHelper.shareFile(path),
-                  icon: Icon(FeatherIcons.share2, color: AppColors.of(context).text),
-                  splashRadius: 24.0,
-                ),
-              ),
-            ],
-          ),
-          body: PhotoView(
-            imageProvider: FileImage(File(path)),
-            maxScale: 4.0,
-            minScale: PhotoViewComputedScale.contained,
-            backgroundDecoration: BoxDecoration(
-              color: Theme.of(context).scaffoldBackgroundColor,
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:io';
+
+import 'package:refilc/helpers/share_helper.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:photo_view/photo_view.dart';
+
+class ImageView extends StatelessWidget {
+  const ImageView(this.path, {Key? key}) : super(key: key);
+
+  final String path;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      color: Theme.of(context).scaffoldBackgroundColor,
+      child: SafeArea(
+        minimum: const EdgeInsets.only(top: 24.0),
+        child: Scaffold(
+          appBar: AppBar(
+            leading: BackButton(color: AppColors.of(context).text),
+            actions: [
+              Padding(
+                padding: const EdgeInsets.only(right: 8.0),
+                child: IconButton(
+                  onPressed: () => ShareHelper.shareFile(path),
+                  icon: Icon(FeatherIcons.share2,
+                      color: AppColors.of(context).text),
+                  splashRadius: 24.0,
+                ),
+              ),
+            ],
+          ),
+          body: PhotoView(
+            imageProvider: FileImage(File(path)),
+            maxScale: 4.0,
+            minScale: PhotoViewComputedScale.contained,
+            backgroundDecoration: BoxDecoration(
+              color: Theme.of(context).scaffoldBackgroundColor,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/message/message_view.dart b/refilc_mobile_ui/lib/common/widgets/message/message_view.dart
old mode 100755
new mode 100644
similarity index 82%
rename from filcnaplo_mobile_ui/lib/common/widgets/message/message_view.dart
rename to refilc_mobile_ui/lib/common/widgets/message/message_view.dart
index bd192ff..8eed0ba
--- a/filcnaplo_mobile_ui/lib/common/widgets/message/message_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/message/message_view.dart
@@ -1,53 +1,54 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/message_view_tile.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-
-class MessageView extends StatefulWidget {
-  const MessageView(this.messages, {Key? key}) : super(key: key);
-
-  final List<Message> messages;
-
-  static show(List<Message> messages, {required BuildContext context}) =>
-      Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(builder: (context) => MessageView(messages)));
-
-  @override
-  _MessageViewState createState() => _MessageViewState();
-}
-
-class _MessageViewState extends State<MessageView> {
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: AppBar(
-        leadingWidth: 64.0,
-        leading: BackButton(color: AppColors.of(context).text),
-        elevation: 0,
-        actions: const [
-          // Padding(
-          //   padding: EdgeInsets.only(right: 8.0),
-          //   child: IconButton(
-          //     onPressed: () {},
-          //     icon: Icon(FeatherIcons.archive, color: AppColors.of(context).text),
-          //     splashRadius: 32.0,
-          //   ),
-          // ),
-        ],
-      ),
-      body: SafeArea(
-        child: ListView.builder(
-          padding: EdgeInsets.zero,
-          physics: const BouncingScrollPhysics(),
-          itemCount: widget.messages.length,
-          itemBuilder: (context, index) {
-            return Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 24.0),
-              child: MessageViewTile(widget.messages[index]),
-            );
-          },
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/message_view_tile.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+
+class MessageView extends StatefulWidget {
+  const MessageView(this.messages, {Key? key}) : super(key: key);
+
+  final List<Message> messages;
+
+  static show(List<Message> messages, {required BuildContext context}) =>
+      Navigator.of(context, rootNavigator: true).push(
+          CupertinoPageRoute(builder: (context) => MessageView(messages)));
+
+  @override
+  _MessageViewState createState() => _MessageViewState();
+}
+
+class _MessageViewState extends State<MessageView> {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        leadingWidth: 64.0,
+        leading: BackButton(color: AppColors.of(context).text),
+        elevation: 0,
+        actions: const [
+          // Padding(
+          //   padding: EdgeInsets.only(right: 8.0),
+          //   child: IconButton(
+          //     onPressed: () {},
+          //     icon: Icon(FeatherIcons.archive, color: AppColors.of(context).text),
+          //     splashRadius: 32.0,
+          //   ),
+          // ),
+        ],
+      ),
+      body: SafeArea(
+        child: ListView.builder(
+          padding: EdgeInsets.zero,
+          physics: const BouncingScrollPhysics(),
+          itemCount: widget.messages.length,
+          itemBuilder: (context, index) {
+            return Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 24.0),
+              child: MessageViewTile(widget.messages[index]),
+            );
+          },
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/message/message_view_tile.dart b/refilc_mobile_ui/lib/common/widgets/message/message_view_tile.dart
old mode 100755
new mode 100644
similarity index 87%
rename from filcnaplo_mobile_ui/lib/common/widgets/message/message_view_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/message/message_view_tile.dart
index 42cfd29..14b23a7
--- a/filcnaplo_mobile_ui/lib/common/widgets/message/message_view_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/message/message_view_tile.dart
@@ -1,128 +1,128 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/attachment_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-// import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:flutter_linkify/flutter_linkify.dart';
-import 'package:provider/provider.dart';
-import 'message_view_tile.i18n.dart';
-
-class MessageViewTile extends StatelessWidget {
-  const MessageViewTile(this.message, {Key? key}) : super(key: key);
-
-  final Message message;
-
-  @override
-  Widget build(BuildContext context) {
-    UserProvider user = Provider.of<UserProvider>(context, listen: false);
-    String recipientLabel = "";
-
-    if (message.recipients.any((r) => r.name == user.student?.name)) {
-      recipientLabel = "me".i18n;
-    }
-
-    if (recipientLabel != "" && message.recipients.length > 1) {
-      recipientLabel += " +";
-      recipientLabel += message.recipients
-          .where((r) => r.name != user.student?.name)
-          .length
-          .toString();
-    }
-
-    if (recipientLabel == "") {
-      // note: convertint to set to remove duplicates
-      recipientLabel +=
-          message.recipients.map((r) => r.name).toSet().join(", ");
-    }
-
-    List<Widget> attachments = [];
-    for (var a in message.attachments) {
-      attachments.add(AttachmentTile(a));
-    }
-
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          // Subject
-          Text(
-            message.subject,
-            softWrap: true,
-            maxLines: 10,
-            style: const TextStyle(
-              fontWeight: FontWeight.w600,
-              fontSize: 24.0,
-            ),
-          ),
-
-          // Author
-          ListTile(
-            visualDensity: VisualDensity.compact,
-            contentPadding: EdgeInsets.zero,
-            leading: ProfileImage(
-              name: message.author,
-              backgroundColor: ColorUtils.stringToColor(message.author),
-            ),
-            title: Text(
-              message.author,
-              style: const TextStyle(fontWeight: FontWeight.w600),
-              overflow: TextOverflow.ellipsis,
-              maxLines: 2,
-            ),
-            subtitle: Text(
-              "to".i18n + " " + recipientLabel,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-              overflow: TextOverflow.ellipsis,
-              maxLines: 1,
-            ),
-            trailing: const Row(
-              mainAxisSize: MainAxisSize.min,
-              children: [
-                // IconButton(
-                //   onPressed: () {},
-                //   icon: Icon(FeatherIcons.cornerUpLeft, color: AppColors.of(context).text),
-                //   splashRadius: 24.0,
-                //   padding: EdgeInsets.zero,
-                //   visualDensity: VisualDensity.compact,
-                // ),
-                // IconButton(
-                //   onPressed: () {},
-                //   icon: Icon(FeatherIcons.share2, color: AppColors.of(context).text),
-                //   splashRadius: 24.0,
-                //   padding: EdgeInsets.zero,
-                //   visualDensity: VisualDensity.compact,
-                // ),
-              ],
-            ),
-          ),
-
-          // Content
-          Panel(
-            padding: const EdgeInsets.all(12.0),
-            child: SelectableLinkify(
-              text: message.content.escapeHtml(),
-              options: const LinkifyOptions(looseUrl: true, removeWww: true),
-              onOpen: (link) {
-                launch(link.url,
-                    customTabsOption: CustomTabsOption(
-                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-                      showPageTitle: true,
-                    ));
-              },
-              style: const TextStyle(fontWeight: FontWeight.w400),
-            ),
-          ),
-
-          // Attachments
-          ...attachments,
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/attachment_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+// import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:flutter_linkify/flutter_linkify.dart';
+import 'package:provider/provider.dart';
+import 'message_view_tile.i18n.dart';
+
+class MessageViewTile extends StatelessWidget {
+  const MessageViewTile(this.message, {Key? key}) : super(key: key);
+
+  final Message message;
+
+  @override
+  Widget build(BuildContext context) {
+    UserProvider user = Provider.of<UserProvider>(context, listen: false);
+    String recipientLabel = "";
+
+    if (message.recipients.any((r) => r.name == user.student?.name)) {
+      recipientLabel = "me".i18n;
+    }
+
+    if (recipientLabel != "" && message.recipients.length > 1) {
+      recipientLabel += " +";
+      recipientLabel += message.recipients
+          .where((r) => r.name != user.student?.name)
+          .length
+          .toString();
+    }
+
+    if (recipientLabel == "") {
+      // note: convertint to set to remove duplicates
+      recipientLabel +=
+          message.recipients.map((r) => r.name).toSet().join(", ");
+    }
+
+    List<Widget> attachments = [];
+    for (var a in message.attachments) {
+      attachments.add(AttachmentTile(a));
+    }
+
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          // Subject
+          Text(
+            message.subject,
+            softWrap: true,
+            maxLines: 10,
+            style: const TextStyle(
+              fontWeight: FontWeight.w600,
+              fontSize: 24.0,
+            ),
+          ),
+
+          // Author
+          ListTile(
+            visualDensity: VisualDensity.compact,
+            contentPadding: EdgeInsets.zero,
+            leading: ProfileImage(
+              name: message.author,
+              backgroundColor: ColorUtils.stringToColor(message.author),
+            ),
+            title: Text(
+              message.author,
+              style: const TextStyle(fontWeight: FontWeight.w600),
+              overflow: TextOverflow.ellipsis,
+              maxLines: 2,
+            ),
+            subtitle: Text(
+              "to".i18n + " " + recipientLabel,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+              overflow: TextOverflow.ellipsis,
+              maxLines: 1,
+            ),
+            trailing: const Row(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                // IconButton(
+                //   onPressed: () {},
+                //   icon: Icon(FeatherIcons.cornerUpLeft, color: AppColors.of(context).text),
+                //   splashRadius: 24.0,
+                //   padding: EdgeInsets.zero,
+                //   visualDensity: VisualDensity.compact,
+                // ),
+                // IconButton(
+                //   onPressed: () {},
+                //   icon: Icon(FeatherIcons.share2, color: AppColors.of(context).text),
+                //   splashRadius: 24.0,
+                //   padding: EdgeInsets.zero,
+                //   visualDensity: VisualDensity.compact,
+                // ),
+              ],
+            ),
+          ),
+
+          // Content
+          Panel(
+            padding: const EdgeInsets.all(12.0),
+            child: SelectableLinkify(
+              text: message.content.escapeHtml(),
+              options: const LinkifyOptions(looseUrl: true, removeWww: true),
+              onOpen: (link) {
+                launch(link.url,
+                    customTabsOption: CustomTabsOption(
+                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+                      showPageTitle: true,
+                    ));
+              },
+              style: const TextStyle(fontWeight: FontWeight.w400),
+            ),
+          ),
+
+          // Attachments
+          ...attachments,
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/message/message_view_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/message/message_view_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/message/message_view_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/message/message_view_tile.i18n.dart
index 6f05afa..828644a
--- a/filcnaplo_mobile_ui/lib/common/widgets/message/message_view_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/message/message_view_tile.i18n.dart
@@ -1,24 +1,24 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "me": "me",
-          "to": "to",
-        },
-        "hu_hu": {
-          "me": "én",
-          "to": "Címzett:",
-        },
-        "de_de": {
-          "me": "mich",
-          "to": "zu",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "me": "me",
+          "to": "to",
+        },
+        "hu_hu": {
+          "me": "én",
+          "to": "Címzett:",
+        },
+        "de_de": {
+          "me": "mich",
+          "to": "zu",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/message/message_viewable.dart b/refilc_mobile_ui/lib/common/widgets/message/message_viewable.dart
old mode 100755
new mode 100644
similarity index 68%
rename from filcnaplo_mobile_ui/lib/common/widgets/message/message_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/message/message_viewable.dart
index 410288d..4f98e8a
--- a/filcnaplo_mobile_ui/lib/common/widgets/message/message_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/message/message_viewable.dart
@@ -1,32 +1,34 @@
-import 'package:animations/animations.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo/ui/widgets/message/message_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/message_view.dart';
-import 'package:flutter/material.dart';
-
-class MessageViewable extends StatelessWidget {
-  const MessageViewable(this.message, {Key? key}) : super(key: key);
-
-  final Message message;
-
-  @override
-  Widget build(BuildContext context) {
-    return OpenContainer(
-      openBuilder: (context, _) {
-        return MessageView([message]);
-      },
-      closedBuilder: (context, VoidCallback openContainer) {
-        return MessageTile(message);
-      },
-      closedElevation: 0,
-      openShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-      closedShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-      middleColor: Theme.of(context).colorScheme.background,
-      openColor: Theme.of(context).scaffoldBackgroundColor,
-      closedColor: Theme.of(context).colorScheme.background,
-      transitionType: ContainerTransitionType.fadeThrough,
-      transitionDuration: const Duration(milliseconds: 400),
-      useRootNavigator: true,
-    );
-  }
-}
+import 'package:animations/animations.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc/ui/widgets/message/message_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/message_view.dart';
+import 'package:flutter/material.dart';
+
+class MessageViewable extends StatelessWidget {
+  const MessageViewable(this.message, {Key? key}) : super(key: key);
+
+  final Message message;
+
+  @override
+  Widget build(BuildContext context) {
+    return OpenContainer(
+      openBuilder: (context, _) {
+        return MessageView([message]);
+      },
+      closedBuilder: (context, VoidCallback openContainer) {
+        return MessageTile(message);
+      },
+      closedElevation: 0,
+      openShape:
+          RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+      closedShape:
+          RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+      middleColor: Theme.of(context).colorScheme.background,
+      openColor: Theme.of(context).scaffoldBackgroundColor,
+      closedColor: Theme.of(context).colorScheme.background,
+      transitionType: ContainerTransitionType.fadeThrough,
+      transitionDuration: const Duration(milliseconds: 400),
+      useRootNavigator: true,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/miss_tile.dart b/refilc_mobile_ui/lib/common/widgets/miss_tile.dart
old mode 100755
new mode 100644
similarity index 83%
rename from filcnaplo_mobile_ui/lib/common/widgets/miss_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/miss_tile.dart
index 6c453de..24855bb
--- a/filcnaplo_mobile_ui/lib/common/widgets/miss_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/miss_tile.dart
@@ -1,51 +1,52 @@
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'miss_tile.i18n.dart';
-
-class MissTile extends StatelessWidget {
-  const MissTile(this.note, {Key? key}) : super(key: key);
-
-  final Note note;
-
-  @override
-  Widget build(BuildContext context) {
-    return ListTile(
-      leading: Icon(_missIcon(), color: Theme.of(context).colorScheme.secondary, size: 36.0),
-      visualDensity: VisualDensity.compact,
-      title: Text(
-        _missName(),
-        style: const TextStyle(
-          fontWeight: FontWeight.w600,
-        ),
-      ),
-      subtitle: Text(
-        note.content.split("órán nem volt")[0].capital(),
-        maxLines: 2,
-        overflow: TextOverflow.ellipsis,
-        style: const TextStyle(
-          fontWeight: FontWeight.w500,
-        ),
-      ),
-    );
-  }
-
-  IconData _missIcon() {
-    if (note.type?.name == "HaziFeladatHiany") {
-      return FeatherIcons.home;
-    } else if (note.type?.name == "Felszereleshiany") {
-      return FeatherIcons.book;
-    }
-    return FeatherIcons.slash;
-  }
-
-  String _missName() {
-    if (note.type?.name == "HaziFeladatHiany") {
-      return "Missing homework".i18n;
-    } else if (note.type?.name == "Felszereleshiany") {
-      return "Missing equipment".i18n;
-    }
-    return "?";
-  }
-}
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'miss_tile.i18n.dart';
+
+class MissTile extends StatelessWidget {
+  const MissTile(this.note, {Key? key}) : super(key: key);
+
+  final Note note;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListTile(
+      leading: Icon(_missIcon(),
+          color: Theme.of(context).colorScheme.secondary, size: 36.0),
+      visualDensity: VisualDensity.compact,
+      title: Text(
+        _missName(),
+        style: const TextStyle(
+          fontWeight: FontWeight.w600,
+        ),
+      ),
+      subtitle: Text(
+        note.content.split("órán nem volt")[0].capital(),
+        maxLines: 2,
+        overflow: TextOverflow.ellipsis,
+        style: const TextStyle(
+          fontWeight: FontWeight.w500,
+        ),
+      ),
+    );
+  }
+
+  IconData _missIcon() {
+    if (note.type?.name == "HaziFeladatHiany") {
+      return FeatherIcons.home;
+    } else if (note.type?.name == "Felszereleshiany") {
+      return FeatherIcons.book;
+    }
+    return FeatherIcons.slash;
+  }
+
+  String _missName() {
+    if (note.type?.name == "HaziFeladatHiany") {
+      return "Missing homework".i18n;
+    } else if (note.type?.name == "Felszereleshiany") {
+      return "Missing equipment".i18n;
+    }
+    return "?";
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/miss_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/miss_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/miss_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/miss_tile.i18n.dart
index f337e3d..1f44a7c
--- a/filcnaplo_mobile_ui/lib/common/widgets/miss_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/miss_tile.i18n.dart
@@ -1,24 +1,24 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Missing homework": "Missing homework",
-          "Missing equipment": "Missing equipment",
-        },
-        "hu_hu": {
-          "Missing homework": "Házi feladat hiány",
-          "Missing equipment": "Felszerelés Hiány",
-        },
-        "de_de": {
-          "Missing homework": "Fehlende Hausaufgaben",
-          "Missing equipment": "Fehlende Ausrüstung",
-        }
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Missing homework": "Missing homework",
+          "Missing equipment": "Missing equipment",
+        },
+        "hu_hu": {
+          "Missing homework": "Házi feladat hiány",
+          "Missing equipment": "Felszerelés Hiány",
+        },
+        "de_de": {
+          "Missing homework": "Fehlende Hausaufgaben",
+          "Missing equipment": "Fehlende Ausrüstung",
+        }
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.dart b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.dart
old mode 100755
new mode 100644
similarity index 73%
rename from filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.dart
index a6e149f..1e75191
--- a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.dart
@@ -1,35 +1,38 @@
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'missed_exam_tile.i18n.dart';
-
-class MissedExamTile extends StatelessWidget {
-  const MissedExamTile(this.missedExams, {Key? key, this.onTap, this.padding}) : super(key: key);
-
-  final List<Lesson> missedExams;
-  final Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-      child: PanelButton(
-        padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 6),
-        leading: SizedBox(
-            width: 36,
-            height: 36,
-            child: Icon(
-              FeatherIcons.slash,
-              color: AppColors.of(context).red.withOpacity(.75),
-              size: 28.0,
-            )),
-        title: Text("missed_exams".plural(missedExams.length).fill([missedExams.length])),
-        trailing: const Icon(FeatherIcons.arrowRight),
-        onPressed: onTap,
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'missed_exam_tile.i18n.dart';
+
+class MissedExamTile extends StatelessWidget {
+  const MissedExamTile(this.missedExams, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final List<Lesson> missedExams;
+  final Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+      child: PanelButton(
+        padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 6),
+        leading: SizedBox(
+            width: 36,
+            height: 36,
+            child: Icon(
+              FeatherIcons.slash,
+              color: AppColors.of(context).red.withOpacity(.75),
+              size: 28.0,
+            )),
+        title: Text("missed_exams"
+            .plural(missedExams.length)
+            .fill([missedExams.length])),
+        trailing: const Icon(FeatherIcons.arrowRight),
+        onPressed: onTap,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.i18n.dart
index 47ed140..2362b96
--- a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_tile.i18n.dart
@@ -1,63 +1,63 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "goodmorning": "Good morning, %s!",
-          "goodafternoon": "Good afternoon, %s!",
-          "goodevening": "Good evening, %s!",
-          "goodrest": "⛱️ Have a nice holiday, %s!",
-          "happybirthday": "🎂 Happy birthday, %s!",
-          "merryxmas": "🎄 Merry Christmas, %s!",
-          "happynewyear": "🎉 Happy New Year, %s!",
-          "empty": "Nothing to see here.",
-          "All": "All",
-          "Grades": "Grades",
-          "Messages": "Messages",
-          "Absences": "Absences",
-          "update_available": "Update Available",
-          "missed_exams": "You missed %s exams this week.".one("You missed an exam this week."),
-          "missed_exam_contact": "Contact %s, to resolve it!",
-        },
-        "hu_hu": {
-          "goodmorning": "Jó reggelt, %s!",
-          "goodafternoon": "Szép napot, %s!",
-          "goodevening": "Szép estét, %s!",
-          "goodrest": "⛱️ Jó szünetet, %s!",
-          "happybirthday": "🎂 Boldog születésnapot, %s!",
-          "merryxmas": "🎄 Boldog Karácsonyt, %s!",
-          "happynewyear": "🎉 Boldog új évet, %s!",
-          "empty": "Nincs itt semmi látnivaló.",
-          "All": "Összes",
-          "Grades": "Jegyek",
-          "Messages": "Üzenetek",
-          "Absences": "Hiányok",
-          "update_available": "Frissítés elérhető",
-          "missed_exams": "Ezen a héten hiányoztál %s dolgozatról.".one("Ezen a héten hiányoztál egy dolgozatról."),
-          "missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
-        },
-        "de_de": {
-          "goodmorning": "Guten morgen, %s!",
-          "goodafternoon": "Guten Tag, %s!",
-          "goodevening": "Guten Abend, %s!",
-          "goodrest": "⛱️ Schöne Ferien, %s!",
-          "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
-          "merryxmas": "🎄 Frohe Weihnachten, %s!",
-          "happynewyear": "🎉 Frohes neues Jahr, %s!",
-          "empty": "Hier gibt es nichts zu sehen.",
-          "All": "Alles",
-          "Grades": "Noten",
-          "Messages": "Nachrichten",
-          "Absences": "Fehlen",
-          "update_available": "Update verfügbar",
-          "missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.".one("Diese Woche haben Sie eine Prüfung verpasst."),
-          "missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "goodmorning": "Good morning, %s!",
+          "goodafternoon": "Good afternoon, %s!",
+          "goodevening": "Good evening, %s!",
+          "goodrest": "⛱️ Have a nice holiday, %s!",
+          "happybirthday": "🎂 Happy birthday, %s!",
+          "merryxmas": "🎄 Merry Christmas, %s!",
+          "happynewyear": "🎉 Happy New Year, %s!",
+          "empty": "Nothing to see here.",
+          "All": "All",
+          "Grades": "Grades",
+          "Messages": "Messages",
+          "Absences": "Absences",
+          "update_available": "Update Available",
+          "missed_exams": "You missed %s exams this week.".one("You missed an exam this week."),
+          "missed_exam_contact": "Contact %s, to resolve it!",
+        },
+        "hu_hu": {
+          "goodmorning": "Jó reggelt, %s!",
+          "goodafternoon": "Szép napot, %s!",
+          "goodevening": "Szép estét, %s!",
+          "goodrest": "⛱️ Jó szünetet, %s!",
+          "happybirthday": "🎂 Boldog születésnapot, %s!",
+          "merryxmas": "🎄 Boldog Karácsonyt, %s!",
+          "happynewyear": "🎉 Boldog új évet, %s!",
+          "empty": "Nincs itt semmi látnivaló.",
+          "All": "Összes",
+          "Grades": "Jegyek",
+          "Messages": "Üzenetek",
+          "Absences": "Hiányok",
+          "update_available": "Frissítés elérhető",
+          "missed_exams": "Ezen a héten hiányoztál %s dolgozatról.".one("Ezen a héten hiányoztál egy dolgozatról."),
+          "missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
+        },
+        "de_de": {
+          "goodmorning": "Guten morgen, %s!",
+          "goodafternoon": "Guten Tag, %s!",
+          "goodevening": "Guten Abend, %s!",
+          "goodrest": "⛱️ Schöne Ferien, %s!",
+          "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
+          "merryxmas": "🎄 Frohe Weihnachten, %s!",
+          "happynewyear": "🎉 Frohes neues Jahr, %s!",
+          "empty": "Hier gibt es nichts zu sehen.",
+          "All": "Alles",
+          "Grades": "Noten",
+          "Messages": "Nachrichten",
+          "Absences": "Fehlen",
+          "update_available": "Update verfügbar",
+          "missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.".one("Diese Woche haben Sie eine Prüfung verpasst."),
+          "missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
old mode 100755
new mode 100644
similarity index 83%
rename from filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
rename to refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
index 6178cc7..2536458
--- a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
@@ -1,79 +1,79 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:provider/provider.dart';
-import 'missed_exam_tile.i18n.dart';
-
-class MissedExamView extends StatelessWidget {
-  const MissedExamView(this.missedExams, {Key? key}) : super(key: key);
-
-  final List<Lesson> missedExams;
-
-  static show(List<Lesson> missedExams, {required BuildContext context}) =>
-      showRoundedModalBottomSheet(context, child: MissedExamView(missedExams));
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> tiles = missedExams.map((e) => MissedExamViewTile(e)).toList();
-    return Column(children: tiles);
-  }
-}
-
-class MissedExamViewTile extends StatelessWidget {
-  const MissedExamViewTile(this.lesson, {Key? key, this.padding})
-      : super(key: key);
-
-  final EdgeInsetsGeometry? padding;
-  final Lesson lesson;
-
-  @override
-  Widget build(BuildContext context) {
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    String? teacherName = lesson.teacher.isRenamed
-        ? lesson.teacher.renamedTo
-        : lesson.teacher.name;
-
-    return Material(
-      type: MaterialType.transparency,
-      child: Padding(
-        padding: padding ??
-            const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
-        child: ListTile(
-          shape:
-              RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-          leading: Icon(
-            SubjectIcon.resolveVariant(
-                subject: lesson.subject, context: context),
-            color: AppColors.of(context).text.withOpacity(.8),
-            size: 32.0,
-          ),
-          title: Text(
-            "${lesson.subject.renamedTo ?? lesson.subject.name.capital()} • ${lesson.date.format(context)}",
-            style: TextStyle(
-                fontWeight: FontWeight.w600,
-                fontStyle: lesson.subject.isRenamed &&
-                        settingsProvider.renamedSubjectsItalics
-                    ? FontStyle.italic
-                    : null),
-          ),
-          subtitle: Text(
-            "missed_exam_contact".i18n.fill([teacherName ?? '']),
-            style: const TextStyle(fontWeight: FontWeight.w500),
-          ),
-          trailing: const Icon(FeatherIcons.arrowRight),
-          onTap: () {
-            Navigator.of(context, rootNavigator: true).pop();
-            TimetablePage.jump(context, lesson: lesson);
-          },
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:provider/provider.dart';
+import 'missed_exam_tile.i18n.dart';
+
+class MissedExamView extends StatelessWidget {
+  const MissedExamView(this.missedExams, {Key? key}) : super(key: key);
+
+  final List<Lesson> missedExams;
+
+  static show(List<Lesson> missedExams, {required BuildContext context}) =>
+      showRoundedModalBottomSheet(context, child: MissedExamView(missedExams));
+
+  @override
+  Widget build(BuildContext context) {
+    List<Widget> tiles = missedExams.map((e) => MissedExamViewTile(e)).toList();
+    return Column(children: tiles);
+  }
+}
+
+class MissedExamViewTile extends StatelessWidget {
+  const MissedExamViewTile(this.lesson, {Key? key, this.padding})
+      : super(key: key);
+
+  final EdgeInsetsGeometry? padding;
+  final Lesson lesson;
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    String? teacherName = lesson.teacher.isRenamed
+        ? lesson.teacher.renamedTo
+        : lesson.teacher.name;
+
+    return Material(
+      type: MaterialType.transparency,
+      child: Padding(
+        padding: padding ??
+            const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
+        child: ListTile(
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+          leading: Icon(
+            SubjectIcon.resolveVariant(
+                subject: lesson.subject, context: context),
+            color: AppColors.of(context).text.withOpacity(.8),
+            size: 32.0,
+          ),
+          title: Text(
+            "${lesson.subject.renamedTo ?? lesson.subject.name.capital()} • ${lesson.date.format(context)}",
+            style: TextStyle(
+                fontWeight: FontWeight.w600,
+                fontStyle: lesson.subject.isRenamed &&
+                        settingsProvider.renamedSubjectsItalics
+                    ? FontStyle.italic
+                    : null),
+          ),
+          subtitle: Text(
+            "missed_exam_contact".i18n.fill([teacherName ?? '']),
+            style: const TextStyle(fontWeight: FontWeight.w500),
+          ),
+          trailing: const Icon(FeatherIcons.arrowRight),
+          onTap: () {
+            Navigator.of(context, rootNavigator: true).pop();
+            TimetablePage.jump(context, lesson: lesson);
+          },
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_viewable.dart b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_viewable.dart
old mode 100755
new mode 100644
similarity index 60%
rename from filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_viewable.dart
index d060621..c43bc8b
--- a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/missed_exam/missed_exam_viewable.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/missed_exam/missed_exam_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/missed_exam/missed_exam_view.dart';
-import 'package:flutter/material.dart';
-
-class MissedExamViewable extends StatelessWidget {
-  const MissedExamViewable(this.missedExams, {Key? key}) : super(key: key);
-
-  final List<Lesson> missedExams;
-
-  @override
-  Widget build(BuildContext context) {
-    return MissedExamTile(
-      missedExams,
-      onTap: () => MissedExamView.show(missedExams, context: context),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/widgets/missed_exam/missed_exam_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/missed_exam/missed_exam_view.dart';
+import 'package:flutter/material.dart';
+
+class MissedExamViewable extends StatelessWidget {
+  const MissedExamViewable(this.missedExams, {Key? key}) : super(key: key);
+
+  final List<Lesson> missedExams;
+
+  @override
+  Widget build(BuildContext context) {
+    return MissedExamTile(
+      missedExams,
+      onTap: () => MissedExamView.show(missedExams, context: context),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/note/note_tile.dart b/refilc_mobile_ui/lib/common/widgets/note/note_tile.dart
old mode 100755
new mode 100644
similarity index 87%
rename from filcnaplo_mobile_ui/lib/common/widgets/note/note_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/note/note_tile.dart
index c3761c9..55994d2
--- a/filcnaplo_mobile_ui/lib/common/widgets/note/note_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/note/note_tile.dart
@@ -1,56 +1,56 @@
-import 'package:filcnaplo/utils/color.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:flutter/material.dart';
-
-class NoteTile extends StatelessWidget {
-  const NoteTile(this.note, {Key? key, this.onTap, this.padding})
-      : super(key: key);
-
-  final Note note;
-  final void Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      type: MaterialType.transparency,
-      child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-        child: ListTile(
-          visualDensity: VisualDensity.compact,
-          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
-          onTap: onTap,
-          shape:
-              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-          leading: ProfileImage(
-            name: (note.teacher.isRenamed
-                    ? note.teacher.renamedTo
-                    : note.teacher.name) ??
-                '',
-            radius: 22.0,
-            backgroundColor: ColorUtils.stringToColor(
-              (note.teacher.isRenamed
-                      ? note.teacher.renamedTo
-                      : note.teacher.name) ??
-                  '',
-            ),
-          ),
-          title: Text(
-            note.title,
-            maxLines: 2,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w600),
-          ),
-          subtitle: Text(
-            note.content.replaceAll('\n', ' '),
-            maxLines: 1,
-            overflow: TextOverflow.ellipsis,
-            style: const TextStyle(fontWeight: FontWeight.w500),
-          ),
-          minLeadingWidth: 0,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/utils/color.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:flutter/material.dart';
+
+class NoteTile extends StatelessWidget {
+  const NoteTile(this.note, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final Note note;
+  final void Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      type: MaterialType.transparency,
+      child: Padding(
+        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+        child: ListTile(
+          visualDensity: VisualDensity.compact,
+          contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
+          onTap: onTap,
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+          leading: ProfileImage(
+            name: (note.teacher.isRenamed
+                    ? note.teacher.renamedTo
+                    : note.teacher.name) ??
+                '',
+            radius: 22.0,
+            backgroundColor: ColorUtils.stringToColor(
+              (note.teacher.isRenamed
+                      ? note.teacher.renamedTo
+                      : note.teacher.name) ??
+                  '',
+            ),
+          ),
+          title: Text(
+            note.title,
+            maxLines: 2,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w600),
+          ),
+          subtitle: Text(
+            note.content.replaceAll('\n', ' '),
+            maxLines: 1,
+            overflow: TextOverflow.ellipsis,
+            style: const TextStyle(fontWeight: FontWeight.w500),
+          ),
+          minLeadingWidth: 0,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/note/note_view.dart b/refilc_mobile_ui/lib/common/widgets/note/note_view.dart
old mode 100755
new mode 100644
similarity index 87%
rename from filcnaplo_mobile_ui/lib/common/widgets/note/note_view.dart
rename to refilc_mobile_ui/lib/common/widgets/note/note_view.dart
index 64680af..201f0ec
--- a/filcnaplo_mobile_ui/lib/common/widgets/note/note_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/note/note_view.dart
@@ -1,84 +1,84 @@
-import 'package:filcnaplo/utils/color.dart';
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_mobile_ui/common/sliding_bottom_sheet.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-import 'package:flutter_linkify/flutter_linkify.dart';
-
-class NoteView extends StatelessWidget {
-  const NoteView(this.note, {Key? key}) : super(key: key);
-
-  final Note note;
-
-  static void show(Note note, {required BuildContext context}) =>
-      showSlidingBottomSheet(context: context, child: NoteView(note));
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          // Header
-          ListTile(
-            leading: ProfileImage(
-              name: (note.teacher.isRenamed
-                      ? note.teacher.renamedTo
-                      : note.teacher.name) ??
-                  '',
-              radius: 22.0,
-              backgroundColor: ColorUtils.stringToColor(
-                (note.teacher.isRenamed
-                        ? note.teacher.renamedTo
-                        : note.teacher.name) ??
-                    '',
-              ),
-            ),
-            title: Text(
-              note.title,
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w600),
-            ),
-            subtitle: Text(
-              (note.teacher.isRenamed
-                      ? note.teacher.renamedTo
-                      : note.teacher.name) ??
-                  '',
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-            trailing: Text(
-              note.date.format(context),
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-
-          // Details
-          SafeArea(
-            child: Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 12.0),
-              child: SelectableLinkify(
-                text: note.content.escapeHtml(),
-                options: const LinkifyOptions(looseUrl: true, removeWww: true),
-                onOpen: (link) {
-                  launch(link.url,
-                      customTabsOption: CustomTabsOption(
-                        toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-                        showPageTitle: true,
-                      ));
-                },
-                style: const TextStyle(fontWeight: FontWeight.w400),
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/utils/color.dart';
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_mobile_ui/common/sliding_bottom_sheet.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+import 'package:flutter_linkify/flutter_linkify.dart';
+
+class NoteView extends StatelessWidget {
+  const NoteView(this.note, {Key? key}) : super(key: key);
+
+  final Note note;
+
+  static void show(Note note, {required BuildContext context}) =>
+      showSlidingBottomSheet(context: context, child: NoteView(note));
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          // Header
+          ListTile(
+            leading: ProfileImage(
+              name: (note.teacher.isRenamed
+                      ? note.teacher.renamedTo
+                      : note.teacher.name) ??
+                  '',
+              radius: 22.0,
+              backgroundColor: ColorUtils.stringToColor(
+                (note.teacher.isRenamed
+                        ? note.teacher.renamedTo
+                        : note.teacher.name) ??
+                    '',
+              ),
+            ),
+            title: Text(
+              note.title,
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w600),
+            ),
+            subtitle: Text(
+              (note.teacher.isRenamed
+                      ? note.teacher.renamedTo
+                      : note.teacher.name) ??
+                  '',
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+            trailing: Text(
+              note.date.format(context),
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+
+          // Details
+          SafeArea(
+            child: Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 12.0),
+              child: SelectableLinkify(
+                text: note.content.escapeHtml(),
+                options: const LinkifyOptions(looseUrl: true, removeWww: true),
+                onOpen: (link) {
+                  launch(link.url,
+                      customTabsOption: CustomTabsOption(
+                        toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+                        showPageTitle: true,
+                      ));
+                },
+                style: const TextStyle(fontWeight: FontWeight.w400),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/note/note_viewable.dart b/refilc_mobile_ui/lib/common/widgets/note/note_viewable.dart
old mode 100755
new mode 100644
similarity index 59%
rename from filcnaplo_mobile_ui/lib/common/widgets/note/note_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/note/note_viewable.dart
index 8208845..9e77135
--- a/filcnaplo_mobile_ui/lib/common/widgets/note/note_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/note/note_viewable.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo_kreta_api/models/note.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/note/note_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/note/note_view.dart';
-import 'package:flutter/material.dart';
-
-class NoteViewable extends StatelessWidget {
-  const NoteViewable(this.note, {Key? key}) : super(key: key);
-
-  final Note note;
-
-  @override
-  Widget build(BuildContext context) {
-    return NoteTile(
-      note,
-      onTap: () => NoteView.show(note, context: context),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/note.dart';
+import 'package:refilc_mobile_ui/common/widgets/note/note_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/note/note_view.dart';
+import 'package:flutter/material.dart';
+
+class NoteViewable extends StatelessWidget {
+  const NoteViewable(this.note, {Key? key}) : super(key: key);
+
+  final Note note;
+
+  @override
+  Widget build(BuildContext context) {
+    return NoteTile(
+      note,
+      onTap: () => NoteView.show(note, context: context),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/statistics_tile.dart b/refilc_mobile_ui/lib/common/widgets/statistics_tile.dart
old mode 100755
new mode 100644
similarity index 82%
rename from filcnaplo_mobile_ui/lib/common/widgets/statistics_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/statistics_tile.dart
index 268a254..20eecd6
--- a/filcnaplo_mobile_ui/lib/common/widgets/statistics_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/statistics_tile.dart
@@ -1,107 +1,114 @@
-import 'package:auto_size_text/auto_size_text.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-
-class StatisticsTile extends StatelessWidget {
-  const StatisticsTile({
-    Key? key,
-    required this.value,
-    this.title,
-    this.decimal = true,
-    this.color,
-    this.valueSuffix = '',
-    this.fill = false,
-    this.outline = false,
-  }) : super(key: key);
-
-  final double value;
-  final Widget? title;
-  final bool decimal;
-  final Color? color;
-  final String valueSuffix;
-  final bool fill;
-  final bool outline;
-
-  @override
-  Widget build(BuildContext context) {
-    String valueText;
-    if (decimal) {
-      valueText = value.toStringAsFixed(2);
-    } else {
-      valueText = value.toStringAsFixed(0);
-    }
-    if (I18n.of(context).locale.languageCode != "en") valueText = valueText.replaceAll(".", ",");
-
-    if (value.isNaN) {
-      valueText = "?";
-    }
-
-    return Container(
-      width: double.infinity,
-      padding: const EdgeInsets.all(18.0),
-      decoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(12.0),
-        color: Theme.of(context).colorScheme.background,
-        boxShadow: [
-          BoxShadow(
-            offset: const Offset(0, 21),
-            blurRadius: 23.0,
-            color: Theme.of(context).shadowColor,
-          )
-        ],
-      ),
-      constraints: const BoxConstraints(
-        minHeight: 140.0,
-      ),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-        children: [
-          if (title != null)
-            DefaultTextStyle(
-              style: Theme.of(context).textTheme.bodyMedium!.copyWith(
-                    fontWeight: FontWeight.w600,
-                    fontSize: 18.0,
-                  ),
-              child: title!,
-            ),
-          if (title != null) const SizedBox(height: 4.0),
-          Container(
-            margin: const EdgeInsets.only(top: 4.0),
-            padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
-            decoration: BoxDecoration(
-              color: fill ? (color ?? gradeColor(context: context, value: value)).withOpacity(.2) : null,
-              border: outline || fill
-                  ? Border.all(
-                      color: (color ?? gradeColor(context: context, value: value)).withOpacity(outline ? 1.0 : 0.0),
-                      width: fill ? 2.0 : 5.0,
-                    )
-                  : null,
-              borderRadius: BorderRadius.circular(45.0),
-            ),
-            child: AutoSizeText.rich(
-              TextSpan(
-                text: valueText,
-                children: [
-                  if (valueSuffix != "")
-                    TextSpan(
-                      text: valueSuffix,
-                      style: const TextStyle(fontSize: 24.0),
-                    ),
-                ],
-              ),
-              maxLines: 1,
-              minFontSize: 5,
-              textAlign: TextAlign.center,
-              style: TextStyle(
-                color: color ?? gradeColor(context: context, value: value),
-                fontWeight: FontWeight.w800,
-                fontSize: 32.0,
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'package:auto_size_text/auto_size_text.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+
+class StatisticsTile extends StatelessWidget {
+  const StatisticsTile({
+    Key? key,
+    required this.value,
+    this.title,
+    this.decimal = true,
+    this.color,
+    this.valueSuffix = '',
+    this.fill = false,
+    this.outline = false,
+  }) : super(key: key);
+
+  final double value;
+  final Widget? title;
+  final bool decimal;
+  final Color? color;
+  final String valueSuffix;
+  final bool fill;
+  final bool outline;
+
+  @override
+  Widget build(BuildContext context) {
+    String valueText;
+    if (decimal) {
+      valueText = value.toStringAsFixed(2);
+    } else {
+      valueText = value.toStringAsFixed(0);
+    }
+    if (I18n.of(context).locale.languageCode != "en")
+      valueText = valueText.replaceAll(".", ",");
+
+    if (value.isNaN) {
+      valueText = "?";
+    }
+
+    return Container(
+      width: double.infinity,
+      padding: const EdgeInsets.all(18.0),
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(12.0),
+        color: Theme.of(context).colorScheme.background,
+        boxShadow: [
+          BoxShadow(
+            offset: const Offset(0, 21),
+            blurRadius: 23.0,
+            color: Theme.of(context).shadowColor,
+          )
+        ],
+      ),
+      constraints: const BoxConstraints(
+        minHeight: 140.0,
+      ),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+        children: [
+          if (title != null)
+            DefaultTextStyle(
+              style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+                    fontWeight: FontWeight.w600,
+                    fontSize: 18.0,
+                  ),
+              child: title!,
+            ),
+          if (title != null) const SizedBox(height: 4.0),
+          Container(
+            margin: const EdgeInsets.only(top: 4.0),
+            padding:
+                const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
+            decoration: BoxDecoration(
+              color: fill
+                  ? (color ?? gradeColor(context: context, value: value))
+                      .withOpacity(.2)
+                  : null,
+              border: outline || fill
+                  ? Border.all(
+                      color:
+                          (color ?? gradeColor(context: context, value: value))
+                              .withOpacity(outline ? 1.0 : 0.0),
+                      width: fill ? 2.0 : 5.0,
+                    )
+                  : null,
+              borderRadius: BorderRadius.circular(45.0),
+            ),
+            child: AutoSizeText.rich(
+              TextSpan(
+                text: valueText,
+                children: [
+                  if (valueSuffix != "")
+                    TextSpan(
+                      text: valueSuffix,
+                      style: const TextStyle(fontSize: 24.0),
+                    ),
+                ],
+              ),
+              maxLines: 1,
+              minFontSize: 5,
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                color: color ?? gradeColor(context: context, value: value),
+                fontWeight: FontWeight.w800,
+                fontSize: 32.0,
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/update/update_tile.dart b/refilc_mobile_ui/lib/common/widgets/update/update_tile.dart
old mode 100755
new mode 100644
similarity index 82%
rename from filcnaplo_mobile_ui/lib/common/widgets/update/update_tile.dart
rename to refilc_mobile_ui/lib/common/widgets/update/update_tile.dart
index 41c66e4..12b3a21
--- a/filcnaplo_mobile_ui/lib/common/widgets/update/update_tile.dart
+++ b/refilc_mobile_ui/lib/common/widgets/update/update_tile.dart
@@ -1,32 +1,33 @@
-import 'package:filcnaplo/models/release.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'update_tile.i18n.dart';
-
-class UpdateTile extends StatelessWidget {
-  const UpdateTile(this.release, {Key? key, this.onTap, this.padding}) : super(key: key);
-
-  final Release release;
-  final Function()? onTap;
-  final EdgeInsetsGeometry? padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
-      child: PanelButton(
-        onPressed: onTap,
-        title: Text("update_available".i18n),
-        leading: const Icon(FeatherIcons.download),
-        trailing: Text(
-          release.tag,
-          style: TextStyle(
-            fontWeight: FontWeight.w500,
-            color: Theme.of(context).colorScheme.secondary,
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/release.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'update_tile.i18n.dart';
+
+class UpdateTile extends StatelessWidget {
+  const UpdateTile(this.release, {Key? key, this.onTap, this.padding})
+      : super(key: key);
+
+  final Release release;
+  final Function()? onTap;
+  final EdgeInsetsGeometry? padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
+      child: PanelButton(
+        onPressed: onTap,
+        title: Text("update_available".i18n),
+        leading: const Icon(FeatherIcons.download),
+        trailing: Text(
+          release.tag,
+          style: TextStyle(
+            fontWeight: FontWeight.w500,
+            color: Theme.of(context).colorScheme.secondary,
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/update/update_tile.i18n.dart b/refilc_mobile_ui/lib/common/widgets/update/update_tile.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/common/widgets/update/update_tile.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/update/update_tile.i18n.dart
index 0416ea2..be1183a
--- a/filcnaplo_mobile_ui/lib/common/widgets/update/update_tile.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/update/update_tile.i18n.dart
@@ -1,21 +1,21 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "update_available": "Update Available",
-        },
-        "hu_hu": {
-          "update_available": "Frissítés elérhető",
-        },
-        "de_de": {
-          "update_available": "Update verfügbar",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "update_available": "Update Available",
+        },
+        "hu_hu": {
+          "update_available": "Frissítés elérhető",
+        },
+        "de_de": {
+          "update_available": "Update verfügbar",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/update/update_viewable.dart b/refilc_mobile_ui/lib/common/widgets/update/update_viewable.dart
old mode 100755
new mode 100644
similarity index 61%
rename from filcnaplo_mobile_ui/lib/common/widgets/update/update_viewable.dart
rename to refilc_mobile_ui/lib/common/widgets/update/update_viewable.dart
index 0eb6a1c..65eb257
--- a/filcnaplo_mobile_ui/lib/common/widgets/update/update_viewable.dart
+++ b/refilc_mobile_ui/lib/common/widgets/update/update_viewable.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo/models/release.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/update/update_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/update/updates_view.dart';
-import 'package:flutter/material.dart';
-
-class UpdateViewable extends StatelessWidget {
-  const UpdateViewable(this.release, {Key? key}) : super(key: key);
-
-  final Release release;
-
-  @override
-  Widget build(BuildContext context) {
-    return UpdateTile(
-      release,
-      onTap: () => UpdateView.show(release, context: context),
-    );
-  }
-}
+import 'package:refilc/models/release.dart';
+import 'package:refilc_mobile_ui/common/widgets/update/update_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/update/updates_view.dart';
+import 'package:flutter/material.dart';
+
+class UpdateViewable extends StatelessWidget {
+  const UpdateViewable(this.release, {Key? key}) : super(key: key);
+
+  final Release release;
+
+  @override
+  Widget build(BuildContext context) {
+    return UpdateTile(
+      release,
+      onTap: () => UpdateView.show(release, context: context),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/update/updates_view.dart b/refilc_mobile_ui/lib/common/widgets/update/updates_view.dart
old mode 100755
new mode 100644
similarity index 89%
rename from filcnaplo_mobile_ui/lib/common/widgets/update/updates_view.dart
rename to refilc_mobile_ui/lib/common/widgets/update/updates_view.dart
index 7463ce5..9698d14
--- a/filcnaplo_mobile_ui/lib/common/widgets/update/updates_view.dart
+++ b/refilc_mobile_ui/lib/common/widgets/update/updates_view.dart
@@ -1,183 +1,183 @@
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'package:filcnaplo/models/release.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_card.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/material_action_button.dart';
-import 'package:filcnaplo/helpers/update_helper.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-import 'package:flutter_markdown/flutter_markdown.dart';
-import 'package:provider/provider.dart';
-import 'package:connectivity_plus/connectivity_plus.dart';
-import 'updates_view.i18n.dart';
-
-class UpdateView extends StatefulWidget {
-  const UpdateView(this.release, {Key? key}) : super(key: key);
-
-  final Release release;
-
-  static void show(Release release, {required BuildContext context}) =>
-      showBottomCard(context: context, child: UpdateView(release));
-
-  @override
-  _UpdateViewState createState() => _UpdateViewState();
-}
-
-class _UpdateViewState extends State<UpdateView> {
-  double progress = 0.0;
-  UpdateState state = UpdateState.none;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.all(12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Padding(
-            padding: const EdgeInsets.symmetric(horizontal: 12.0),
-            child: Row(
-              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-              children: [
-                Column(
-                  crossAxisAlignment: CrossAxisAlignment.start,
-                  children: [
-                    Text(
-                      "new_update".i18n,
-                      style: const TextStyle(
-                          fontWeight: FontWeight.w700, fontSize: 18.0),
-                    ),
-                    Text(
-                      "${widget.release.version}",
-                      style: TextStyle(
-                        fontWeight: FontWeight.w600,
-                        fontSize: 16.0,
-                        color: AppColors.of(context).text.withOpacity(0.6),
-                      ),
-                    ),
-                  ],
-                ),
-                ClipRRect(
-                  borderRadius: BorderRadius.circular(18.0),
-                  child: Image.asset(
-                    "assets/icons/ic_launcher.png",
-                    width: 64.0,
-                  ),
-                )
-              ],
-            ),
-          ),
-
-          // Description
-          Container(
-            margin: const EdgeInsets.only(top: 8.0),
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(12.0),
-            ),
-            child: SizedBox(
-              height: 200.0,
-              child: Markdown(
-                padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                physics: const BouncingScrollPhysics(),
-                data: widget.release.body,
-                onTapLink: (text, href, title) => launch(href ?? ""),
-              ),
-            ),
-          ),
-
-          // Download button
-          Center(
-            child: MaterialActionButton(
-              child: Row(
-                mainAxisSize: MainAxisSize.min,
-                children: [
-                  if (state == UpdateState.downloading ||
-                      state == UpdateState.preparing)
-                    Container(
-                      height: 18.0,
-                      width: 18.0,
-                      margin: const EdgeInsets.only(right: 8.0),
-                      child: CircularProgressIndicator(
-                        value: progress > 0.05 ? progress : null,
-                        color: ColorUtils.foregroundColor(
-                            AppColors.of(context).filc),
-                      ),
-                    ),
-                  Text([
-                    "download".i18n,
-                    "downloading".i18n,
-                    "downloading".i18n,
-                    "installing".i18n
-                  ][state.index]
-                      .toUpperCase()),
-                ],
-              ),
-              backgroundColor: AppColors.of(context).filc,
-              onPressed:
-                  state == UpdateState.none ? () => downloadPrecheck() : null,
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-
-  String fmtSize() =>
-      "${(widget.release.downloads.first.size / 1024 / 1024).toStringAsFixed(1)} MB";
-
-  void downloadPrecheck() {
-    final status = Provider.of<StatusProvider>(context, listen: false);
-    if (status.networkType == ConnectivityResult.mobile) {
-      showDialog(
-        context: context,
-        builder: (context) => AlertDialog(
-          title: Text("mobileAlertTitle".i18n),
-          content: Text("mobileAlertDesc".i18n.fill([fmtSize()])),
-          actions: [
-            TextButton(
-              onPressed: () {
-                Navigator.of(context).pop(false);
-              },
-              child: Text("no".i18n),
-            ),
-            TextButton(
-              onPressed: () {
-                Navigator.of(context).pop(true);
-              },
-              child: Text("yes".i18n),
-            ),
-          ],
-        ),
-      ).then((value) => value ? download() : null);
-    } else {
-      download();
-    }
-  }
-
-  void download() {
-    widget.release
-        .install(updateCallback: (p, s) {
-          if (mounted) {
-            setState(() {
-              progress = p;
-              state = s;
-            });
-          }
-        })
-        .then((_) => Navigator.of(context).maybePop())
-        .catchError((error, stackTrace) {
-          if (mounted) {
-            Navigator.of(context).maybePop();
-            ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
-              context: context,
-              content: Text("error".i18n),
-              backgroundColor: AppColors.of(context).red,
-            ));
-            setState(() => state = UpdateState.none);
-          }
-          return true;
-        });
-  }
-}
+import 'package:refilc/api/providers/status_provider.dart';
+import 'package:refilc/models/release.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:refilc_mobile_ui/common/bottom_card.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_mobile_ui/common/material_action_button.dart';
+import 'package:refilc/helpers/update_helper.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+import 'package:flutter_markdown/flutter_markdown.dart';
+import 'package:provider/provider.dart';
+import 'package:connectivity_plus/connectivity_plus.dart';
+import 'updates_view.i18n.dart';
+
+class UpdateView extends StatefulWidget {
+  const UpdateView(this.release, {Key? key}) : super(key: key);
+
+  final Release release;
+
+  static void show(Release release, {required BuildContext context}) =>
+      showBottomCard(context: context, child: UpdateView(release));
+
+  @override
+  _UpdateViewState createState() => _UpdateViewState();
+}
+
+class _UpdateViewState extends State<UpdateView> {
+  double progress = 0.0;
+  UpdateState state = UpdateState.none;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.all(12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 12.0),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    Text(
+                      "new_update".i18n,
+                      style: const TextStyle(
+                          fontWeight: FontWeight.w700, fontSize: 18.0),
+                    ),
+                    Text(
+                      "${widget.release.version}",
+                      style: TextStyle(
+                        fontWeight: FontWeight.w600,
+                        fontSize: 16.0,
+                        color: AppColors.of(context).text.withOpacity(0.6),
+                      ),
+                    ),
+                  ],
+                ),
+                ClipRRect(
+                  borderRadius: BorderRadius.circular(18.0),
+                  child: Image.asset(
+                    "assets/icons/ic_launcher.png",
+                    width: 64.0,
+                  ),
+                )
+              ],
+            ),
+          ),
+
+          // Description
+          Container(
+            margin: const EdgeInsets.only(top: 8.0),
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.circular(12.0),
+            ),
+            child: SizedBox(
+              height: 200.0,
+              child: Markdown(
+                padding: const EdgeInsets.symmetric(horizontal: 12.0),
+                physics: const BouncingScrollPhysics(),
+                data: widget.release.body,
+                onTapLink: (text, href, title) => launch(href ?? ""),
+              ),
+            ),
+          ),
+
+          // Download button
+          Center(
+            child: MaterialActionButton(
+              child: Row(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  if (state == UpdateState.downloading ||
+                      state == UpdateState.preparing)
+                    Container(
+                      height: 18.0,
+                      width: 18.0,
+                      margin: const EdgeInsets.only(right: 8.0),
+                      child: CircularProgressIndicator(
+                        value: progress > 0.05 ? progress : null,
+                        color: ColorUtils.foregroundColor(
+                            AppColors.of(context).filc),
+                      ),
+                    ),
+                  Text([
+                    "download".i18n,
+                    "downloading".i18n,
+                    "downloading".i18n,
+                    "installing".i18n
+                  ][state.index]
+                      .toUpperCase()),
+                ],
+              ),
+              backgroundColor: AppColors.of(context).filc,
+              onPressed:
+                  state == UpdateState.none ? () => downloadPrecheck() : null,
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  String fmtSize() =>
+      "${(widget.release.downloads.first.size / 1024 / 1024).toStringAsFixed(1)} MB";
+
+  void downloadPrecheck() {
+    final status = Provider.of<StatusProvider>(context, listen: false);
+    if (status.networkType == ConnectivityResult.mobile) {
+      showDialog(
+        context: context,
+        builder: (context) => AlertDialog(
+          title: Text("mobileAlertTitle".i18n),
+          content: Text("mobileAlertDesc".i18n.fill([fmtSize()])),
+          actions: [
+            TextButton(
+              onPressed: () {
+                Navigator.of(context).pop(false);
+              },
+              child: Text("no".i18n),
+            ),
+            TextButton(
+              onPressed: () {
+                Navigator.of(context).pop(true);
+              },
+              child: Text("yes".i18n),
+            ),
+          ],
+        ),
+      ).then((value) => value ? download() : null);
+    } else {
+      download();
+    }
+  }
+
+  void download() {
+    widget.release
+        .install(updateCallback: (p, s) {
+          if (mounted) {
+            setState(() {
+              progress = p;
+              state = s;
+            });
+          }
+        })
+        .then((_) => Navigator.of(context).maybePop())
+        .catchError((error, stackTrace) {
+          if (mounted) {
+            Navigator.of(context).maybePop();
+            ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
+              context: context,
+              content: Text("error".i18n),
+              backgroundColor: AppColors.of(context).red,
+            ));
+            setState(() => state = UpdateState.none);
+          }
+          return true;
+        });
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/update/updates_view.i18n.dart b/refilc_mobile_ui/lib/common/widgets/update/updates_view.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/common/widgets/update/updates_view.i18n.dart
rename to refilc_mobile_ui/lib/common/widgets/update/updates_view.i18n.dart
index 1cdb48a..012924b
--- a/filcnaplo_mobile_ui/lib/common/widgets/update/updates_view.i18n.dart
+++ b/refilc_mobile_ui/lib/common/widgets/update/updates_view.i18n.dart
@@ -1,46 +1,46 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "new_update": "New Update",
-          "download": "download",
-          "downloading": "downloading",
-          "installing": "installing",
-          "error": "Failed to install update!",
-          "no": "No",
-          "yes": "Yes",
-          "mobileAlertTitle": "Hold up!",
-          "mobileAlertDesc": "You're on mobile network trying to download a %s update. Are you sure you want to continue?"
-        },
-        "hu_hu": {
-          "new_update": "Új frissítés",
-          "download": "Letöltés",
-          "downloading": "Letöltés",
-          "installing": "Telepítés",
-          "error": "Nem sikerült telepíteni a frissítést!",
-          "no": "Nem",
-          "yes": "Igen",
-          "mobileAlertTitle": "Figyelem!",
-          "mobileAlertDesc": "Jelenleg mobil interneten vagy, és egy %s méretű frissítést próbálsz letölteni. Biztosan folytatod?"
-        },
-        "de_de": {
-          "new_update": "Neues Update",
-          "download": "herunterladen",
-          "downloading": "Herunterladen",
-          "installing": "Installation",
-          "error": "Update konnte nicht installiert werden!",
-          "no": "Nein",
-          "yes": "Ja",
-          "mobileAlertTitle": "Achtung!",
-          "mobileAlertDesc":
-              "Sie befinden sich gerade im mobilen Internet und versuchen, ein %s Update herunterzuladen. Sind Sie sicher, dass Sie weitermachen wollen?"
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "new_update": "New Update",
+          "download": "download",
+          "downloading": "downloading",
+          "installing": "installing",
+          "error": "Failed to install update!",
+          "no": "No",
+          "yes": "Yes",
+          "mobileAlertTitle": "Hold up!",
+          "mobileAlertDesc": "You're on mobile network trying to download a %s update. Are you sure you want to continue?"
+        },
+        "hu_hu": {
+          "new_update": "Új frissítés",
+          "download": "Letöltés",
+          "downloading": "Letöltés",
+          "installing": "Telepítés",
+          "error": "Nem sikerült telepíteni a frissítést!",
+          "no": "Nem",
+          "yes": "Igen",
+          "mobileAlertTitle": "Figyelem!",
+          "mobileAlertDesc": "Jelenleg mobil interneten vagy, és egy %s méretű frissítést próbálsz letölteni. Biztosan folytatod?"
+        },
+        "de_de": {
+          "new_update": "Neues Update",
+          "download": "herunterladen",
+          "downloading": "Herunterladen",
+          "installing": "Installation",
+          "error": "Update konnte nicht installiert werden!",
+          "no": "Nein",
+          "yes": "Ja",
+          "mobileAlertTitle": "Achtung!",
+          "mobileAlertDesc":
+              "Sie befinden sich gerade im mobilen Internet und versuchen, ein %s Update herunterzuladen. Sind Sie sicher, dass Sie weitermachen wollen?"
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/absences/absence_subject_view.dart b/refilc_mobile_ui/lib/pages/absences/absence_subject_view.dart
old mode 100755
new mode 100644
similarity index 71%
rename from filcnaplo_mobile_ui/lib/pages/absences/absence_subject_view.dart
rename to refilc_mobile_ui/lib/pages/absences/absence_subject_view.dart
index dcf162f..8a600f1
--- a/filcnaplo_mobile_ui/lib/pages/absences/absence_subject_view.dart
+++ b/refilc_mobile_ui/lib/pages/absences/absence_subject_view.dart
@@ -1,91 +1,91 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo/utils/reverse_search.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/hero_scrollview.dart';
-import 'package:filcnaplo_mobile_ui/pages/absences/absence_subject_view_container.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_view.i18n.dart';
-import 'package:provider/provider.dart';
-
-class AbsenceSubjectView extends StatelessWidget {
-  const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []})
-      : super(key: key);
-
-  final Subject subject;
-  final List<Absence> absences;
-
-  static void show(Subject subject, List<Absence> absences,
-      {required BuildContext context}) {
-    Navigator.of(context, rootNavigator: true)
-        .push<Absence>(CupertinoPageRoute(
-            builder: (context) =>
-                AbsenceSubjectView(subject, absences: absences)))
-        .then((value) {
-      if (value == null) return;
-
-      Future.delayed(const Duration(milliseconds: 250)).then((_) {
-        ReverseSearch.getLessonByAbsence(value, context).then((lesson) {
-          if (lesson != null) {
-            TimetablePage.jump(context, lesson: lesson);
-          } else {
-            ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
-              content: Text("Cannot find lesson".i18n,
-                  style: const TextStyle(color: Colors.white)),
-              backgroundColor: AppColors.of(context).red,
-              context: context,
-            ));
-          }
-        });
-      });
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final dateWidgets = absences
-        .map((a) => DateWidget(
-              widget: AbsenceViewable(a, padding: EdgeInsets.zero),
-              date: a.date,
-            ))
-        .toList();
-    List<Widget> absenceTiles = sortDateWidgets(context,
-        dateWidgets: dateWidgets,
-        padding: const EdgeInsets.symmetric(vertical: 6.0),
-        hasShadow: true);
-
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    return Scaffold(
-      body: HeroScrollView(
-        title: subject.renamedTo ?? subject.name.capital(),
-        italic: subject.isRenamed && settingsProvider.renamedSubjectsItalics,
-        icon: SubjectIcon.resolveVariant(subject: subject, context: context),
-        child: AbsenceSubjectViewContainer(
-          child: CupertinoScrollbar(
-            child: ListView.builder(
-              physics: const BouncingScrollPhysics(),
-              padding: const EdgeInsets.all(24.0),
-              shrinkWrap: true,
-              itemBuilder: (context, index) => Padding(
-                padding: const EdgeInsets.only(bottom: 12.0),
-                child: absenceTiles[index],
-              ),
-              itemCount: absenceTiles.length,
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc/utils/reverse_search.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart';
+import 'package:refilc_mobile_ui/common/hero_scrollview.dart';
+import 'package:refilc_mobile_ui/pages/absences/absence_subject_view_container.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
+import 'package:refilc/ui/filter/sort.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_view.i18n.dart';
+import 'package:provider/provider.dart';
+
+class AbsenceSubjectView extends StatelessWidget {
+  const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []})
+      : super(key: key);
+
+  final Subject subject;
+  final List<Absence> absences;
+
+  static void show(Subject subject, List<Absence> absences,
+      {required BuildContext context}) {
+    Navigator.of(context, rootNavigator: true)
+        .push<Absence>(CupertinoPageRoute(
+            builder: (context) =>
+                AbsenceSubjectView(subject, absences: absences)))
+        .then((value) {
+      if (value == null) return;
+
+      Future.delayed(const Duration(milliseconds: 250)).then((_) {
+        ReverseSearch.getLessonByAbsence(value, context).then((lesson) {
+          if (lesson != null) {
+            TimetablePage.jump(context, lesson: lesson);
+          } else {
+            ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
+              content: Text("Cannot find lesson".i18n,
+                  style: const TextStyle(color: Colors.white)),
+              backgroundColor: AppColors.of(context).red,
+              context: context,
+            ));
+          }
+        });
+      });
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final dateWidgets = absences
+        .map((a) => DateWidget(
+              widget: AbsenceViewable(a, padding: EdgeInsets.zero),
+              date: a.date,
+            ))
+        .toList();
+    List<Widget> absenceTiles = sortDateWidgets(context,
+        dateWidgets: dateWidgets,
+        padding: const EdgeInsets.symmetric(vertical: 6.0),
+        hasShadow: true);
+
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    return Scaffold(
+      body: HeroScrollView(
+        title: subject.renamedTo ?? subject.name.capital(),
+        italic: subject.isRenamed && settingsProvider.renamedSubjectsItalics,
+        icon: SubjectIcon.resolveVariant(subject: subject, context: context),
+        child: AbsenceSubjectViewContainer(
+          child: CupertinoScrollbar(
+            child: ListView.builder(
+              physics: const BouncingScrollPhysics(),
+              padding: const EdgeInsets.all(24.0),
+              shrinkWrap: true,
+              itemBuilder: (context, index) => Padding(
+                padding: const EdgeInsets.only(bottom: 12.0),
+                child: absenceTiles[index],
+              ),
+              itemCount: absenceTiles.length,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/absences/absence_subject_view_container.dart b/refilc_mobile_ui/lib/pages/absences/absence_subject_view_container.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/absences/absence_subject_view_container.dart
rename to refilc_mobile_ui/lib/pages/absences/absence_subject_view_container.dart
index a0f1b87..53836c7
--- a/filcnaplo_mobile_ui/lib/pages/absences/absence_subject_view_container.dart
+++ b/refilc_mobile_ui/lib/pages/absences/absence_subject_view_container.dart
@@ -1,10 +1,10 @@
-import 'package:flutter/material.dart';
-
-class AbsenceSubjectViewContainer extends InheritedWidget {
-  const AbsenceSubjectViewContainer({Key? key, required Widget child}) : super(key: key, child: child);
-
-  static AbsenceSubjectViewContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<AbsenceSubjectViewContainer>();
-
-  @override
-  bool updateShouldNotify(AbsenceSubjectViewContainer oldWidget) => false;
-}
+import 'package:flutter/material.dart';
+
+class AbsenceSubjectViewContainer extends InheritedWidget {
+  const AbsenceSubjectViewContainer({Key? key, required Widget child}) : super(key: key, child: child);
+
+  static AbsenceSubjectViewContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<AbsenceSubjectViewContainer>();
+
+  @override
+  bool updateShouldNotify(AbsenceSubjectViewContainer oldWidget) => false;
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/absences/absences_page.dart b/refilc_mobile_ui/lib/pages/absences/absences_page.dart
old mode 100755
new mode 100644
similarity index 88%
rename from filcnaplo_mobile_ui/lib/pages/absences/absences_page.dart
rename to refilc_mobile_ui/lib/pages/absences/absences_page.dart
index dc2218d..af3793b
--- a/filcnaplo_mobile_ui/lib/pages/absences/absences_page.dart
+++ b/refilc_mobile_ui/lib/pages/absences/absences_page.dart
@@ -1,428 +1,428 @@
-import 'dart:math';
-
-import 'package:animations/animations.dart';
-import 'package:auto_size_text/auto_size_text.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/action_button.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.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/profile_image/profile_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_subject_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/statistics_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/miss_tile.dart';
-import 'package:filcnaplo_mobile_ui/pages/absences/absence_subject_view.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'absences_page.i18n.dart';
-
-enum AbsenceFilter { absences, delays, misses }
-
-class SubjectAbsence {
-  Subject subject;
-  List<Absence> absences;
-  double percentage;
-
-  SubjectAbsence(
-      {required this.subject, this.absences = const [], this.percentage = 0.0});
-}
-
-class AbsencesPage extends StatefulWidget {
-  const AbsencesPage({Key? key}) : super(key: key);
-
-  @override
-  _AbsencesPageState createState() => _AbsencesPageState();
-}
-
-class _AbsencesPageState extends State<AbsencesPage>
-    with TickerProviderStateMixin {
-  late UserProvider user;
-  late AbsenceProvider absenceProvider;
-  late TimetableProvider timetableProvider;
-  late NoteProvider noteProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late TabController _tabController;
-  late List<SubjectAbsence> absences = [];
-  final Map<Subject, Lesson> _lessonCount = {};
-
-  @override
-  void initState() {
-    super.initState();
-
-    _tabController = TabController(length: 3, vsync: this);
-    timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
-
-    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
-      for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
-        if (!lesson.isEmpty &&
-            lesson.subject.id != '' &&
-            lesson.lessonYearIndex != null) {
-          _lessonCount.update(
-            lesson.subject,
-            (value) {
-              if (lesson.lessonYearIndex! > value.lessonYearIndex!) {
-                return lesson;
-              } else {
-                return value;
-              }
-            },
-            ifAbsent: () => lesson,
-          );
-        }
-      }
-      setState(() {});
-    });
-  }
-
-  void buildSubjectAbsences() {
-    Map<Subject, SubjectAbsence> _absences = {};
-
-    for (final absence in absenceProvider.absences) {
-      if (absence.delay != 0) continue;
-
-      if (!_absences.containsKey(absence.subject)) {
-        _absences[absence.subject] =
-            SubjectAbsence(subject: absence.subject, absences: [absence]);
-      } else {
-        _absences[absence.subject]?.absences.add(absence);
-      }
-    }
-
-    _absences.forEach((subject, absence) {
-      final absentLessonsOfSubject = absenceProvider.absences
-          .where((e) => e.subject == subject && e.delay == 0)
-          .length;
-      final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
-
-      double absentLessonsOfSubjectPercentage;
-
-      if (absentLessonsOfSubject <= totalLessonsOfSubject) {
-        absentLessonsOfSubjectPercentage =
-            absentLessonsOfSubject / totalLessonsOfSubject * 100;
-      } else {
-        absentLessonsOfSubjectPercentage = -1;
-      }
-
-      _absences[subject]?.percentage =
-          absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
-    });
-
-    absences = _absences.values.toList();
-    absences.sort((a, b) => -a.percentage.compareTo(b.percentage));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    absenceProvider = Provider.of<AbsenceProvider>(context);
-    noteProvider = Provider.of<NoteProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-    timetableProvider = Provider.of<TimetableProvider>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    buildSubjectAbsences();
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 12.0),
-        child: NestedScrollView(
-          physics: const BouncingScrollPhysics(
-              parent: AlwaysScrollableScrollPhysics()),
-          headerSliverBuilder: (context, _) => [
-            SliverAppBar(
-              pinned: true,
-              floating: false,
-              snap: false,
-              centerTitle: false,
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-              actions: [
-                // Profile Icon
-                Padding(
-                  padding: const EdgeInsets.only(right: 24.0),
-                  child: ProfileButton(
-                    child: ProfileImage(
-                      heroTag: "profile",
-                      name: firstName,
-                      backgroundColor: Theme.of(context)
-                          .colorScheme
-                          .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
-                      badge: updateProvider.available,
-                      role: user.role,
-                      profilePictureString: user.picture,
-                    ),
-                  ),
-                ),
-              ],
-              automaticallyImplyLeading: false,
-              shadowColor: Theme.of(context).shadowColor,
-              title: Padding(
-                padding: const EdgeInsets.only(left: 8.0),
-                child: Text(
-                  "Absences".i18n,
-                  style: TextStyle(
-                      color: AppColors.of(context).text,
-                      fontSize: 32.0,
-                      fontWeight: FontWeight.bold),
-                ),
-              ),
-              bottom: FilterBar(
-                items: [
-                  Tab(text: "Absences".i18n),
-                  Tab(text: "Delays".i18n),
-                  Tab(text: "Misses".i18n),
-                ],
-                controller: _tabController,
-                disableFading: true,
-              ),
-            ),
-          ],
-          body: TabBarView(
-              physics: const BouncingScrollPhysics(),
-              controller: _tabController,
-              children: List.generate(
-                  3, (index) => filterViewBuilder(context, index))),
-        ),
-      ),
-    );
-  }
-
-  List<DateWidget> getFilterWidgets(AbsenceFilter activeData) {
-    List<DateWidget> items = [];
-    switch (activeData) {
-      case AbsenceFilter.absences:
-        for (var a in absences) {
-          items.add(DateWidget(
-            date: DateTime.fromMillisecondsSinceEpoch(0),
-            widget: AbsenceSubjectTile(
-              a.subject,
-              percentage: a.percentage,
-              excused: a.absences
-                  .where((a) => a.state == Justification.excused)
-                  .length,
-              unexcused: a.absences
-                  .where((a) => a.state == Justification.unexcused)
-                  .length,
-              pending: a.absences
-                  .where((a) => a.state == Justification.pending)
-                  .length,
-              onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
-                  context: context),
-            ),
-          ));
-        }
-        break;
-      case AbsenceFilter.delays:
-        for (var absence in absenceProvider.absences) {
-          if (absence.delay != 0) {
-            items.add(DateWidget(
-              date: absence.date,
-              widget: AbsenceViewable(absence, padding: EdgeInsets.zero),
-            ));
-          }
-        }
-        break;
-      case AbsenceFilter.misses:
-        for (var note in noteProvider.notes) {
-          if (note.type?.name == "HaziFeladatHiany" ||
-              note.type?.name == "Felszereleshiany") {
-            items.add(DateWidget(
-              date: note.date,
-              widget: MissTile(note),
-            ));
-          }
-        }
-        break;
-    }
-    return items;
-  }
-
-  Widget filterViewBuilder(context, int activeData) {
-    List<Widget> filterWidgets = [];
-
-    if (activeData > 0) {
-      filterWidgets = sortDateWidgets(
-        context,
-        dateWidgets: getFilterWidgets(AbsenceFilter.values[activeData]),
-        padding: EdgeInsets.zero,
-        hasShadow: true,
-      );
-    } else {
-      filterWidgets = [
-        Padding(
-          padding: const EdgeInsets.only(bottom: 24.0),
-          child: Panel(
-            title: Row(
-              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-              children: [
-                Text("Subjects".i18n),
-                Padding(
-                  padding: const EdgeInsets.only(right: 4.0),
-                  child: IconButton(
-                    onPressed: () {
-                      showDialog(
-                        context: context,
-                        builder: (context) => AlertDialog(
-                          shape: RoundedRectangleBorder(
-                              borderRadius: BorderRadius.circular(12.0)),
-                          title: Text("attention".i18n),
-                          content: Text("attention_body".i18n),
-                          actions: [
-                            ActionButton(
-                                label: "Ok",
-                                onTap: () => Navigator.of(context).pop())
-                          ],
-                        ),
-                      );
-                    },
-                    padding: EdgeInsets.zero,
-                    splashRadius: 24.0,
-                    visualDensity: VisualDensity.compact,
-                    constraints: BoxConstraints.tight(const Size(42.0, 42.0)),
-                    icon: const Icon(FeatherIcons.info),
-                  ),
-                ),
-              ],
-            ),
-            child: PageTransitionSwitcher(
-              transitionBuilder: (
-                Widget child,
-                Animation<double> primaryAnimation,
-                Animation<double> secondaryAnimation,
-              ) {
-                return FadeThroughTransition(
-                  child: child,
-                  animation: primaryAnimation,
-                  secondaryAnimation: secondaryAnimation,
-                  fillColor: Theme.of(context).colorScheme.background,
-                );
-              },
-              child: Column(
-                children: getFilterWidgets(AbsenceFilter.values[activeData])
-                    .map((e) => e.widget)
-                    .cast<Widget>()
-                    .toList(),
-              ),
-            ),
-          ),
-        )
-      ];
-    }
-
-    return Padding(
-      padding: const EdgeInsets.only(top: 12.0),
-      child: RefreshIndicator(
-        color: Theme.of(context).colorScheme.secondary,
-        onRefresh: () async {
-          await absenceProvider.fetch();
-          await noteProvider.fetch();
-        },
-        child: ListView.builder(
-          padding: EdgeInsets.zero,
-          physics: const BouncingScrollPhysics(),
-          itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
-          itemBuilder: (context, index) {
-            if (filterWidgets.isNotEmpty) {
-              if ((index == 0 && activeData == 1) ||
-                  (index == 0 && activeData == 0)) {
-                int value1 = 0;
-                int value2 = 0;
-                String title1 = "";
-                String title2 = "";
-                String suffix = "";
-
-                if (activeData == AbsenceFilter.absences.index) {
-                  value1 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay == 0 && e.state == Justification.excused)
-                      .length;
-                  value2 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay == 0 && e.state == Justification.unexcused)
-                      .length;
-                  title1 = "stat_1".i18n;
-                  title2 = "stat_2".i18n;
-                  suffix = " " + "hr".i18n;
-                } else if (activeData == AbsenceFilter.delays.index) {
-                  value1 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay != 0 && e.state == Justification.excused)
-                      .map((e) => e.delay)
-                      .fold(0, (a, b) => a + b);
-                  value2 = absenceProvider.absences
-                      .where((e) =>
-                          e.delay != 0 && e.state == Justification.unexcused)
-                      .map((e) => e.delay)
-                      .fold(0, (a, b) => a + b);
-                  title1 = "stat_3".i18n;
-                  title2 = "stat_4".i18n;
-                  suffix = " " + "min".i18n;
-                }
-
-                return Padding(
-                  padding: const EdgeInsets.only(
-                      bottom: 24.0, left: 24.0, right: 24.0),
-                  child: Row(children: [
-                    Expanded(
-                      child: StatisticsTile(
-                        title: AutoSizeText(
-                          title1,
-                          textAlign: TextAlign.center,
-                          maxLines: 2,
-                          overflow: TextOverflow.ellipsis,
-                        ),
-                        valueSuffix: suffix,
-                        value: value1.toDouble(),
-                        decimal: false,
-                        color: AppColors.of(context).green,
-                      ),
-                    ),
-                    const SizedBox(width: 24.0),
-                    Expanded(
-                      child: StatisticsTile(
-                        title: AutoSizeText(
-                          title2,
-                          textAlign: TextAlign.center,
-                          maxLines: 2,
-                          overflow: TextOverflow.ellipsis,
-                        ),
-                        valueSuffix: suffix,
-                        value: value2.toDouble(),
-                        decimal: false,
-                        color: AppColors.of(context).red,
-                      ),
-                    ),
-                  ]),
-                );
-              }
-
-              return Padding(
-                padding:
-                    const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
-                child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
-              );
-            } else {
-              return Empty(subtitle: "empty".i18n);
-            }
-          },
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:animations/animations.dart';
+import 'package:auto_size_text/auto_size_text.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/action_button.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_subject_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart';
+import 'package:refilc_mobile_ui/common/widgets/statistics_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/miss_tile.dart';
+import 'package:refilc_mobile_ui/pages/absences/absence_subject_view.dart';
+import 'package:refilc/ui/filter/sort.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'absences_page.i18n.dart';
+
+enum AbsenceFilter { absences, delays, misses }
+
+class SubjectAbsence {
+  Subject subject;
+  List<Absence> absences;
+  double percentage;
+
+  SubjectAbsence(
+      {required this.subject, this.absences = const [], this.percentage = 0.0});
+}
+
+class AbsencesPage extends StatefulWidget {
+  const AbsencesPage({Key? key}) : super(key: key);
+
+  @override
+  _AbsencesPageState createState() => _AbsencesPageState();
+}
+
+class _AbsencesPageState extends State<AbsencesPage>
+    with TickerProviderStateMixin {
+  late UserProvider user;
+  late AbsenceProvider absenceProvider;
+  late TimetableProvider timetableProvider;
+  late NoteProvider noteProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late TabController _tabController;
+  late List<SubjectAbsence> absences = [];
+  final Map<Subject, Lesson> _lessonCount = {};
+
+  @override
+  void initState() {
+    super.initState();
+
+    _tabController = TabController(length: 3, vsync: this);
+    timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
+
+    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
+      for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
+        if (!lesson.isEmpty &&
+            lesson.subject.id != '' &&
+            lesson.lessonYearIndex != null) {
+          _lessonCount.update(
+            lesson.subject,
+            (value) {
+              if (lesson.lessonYearIndex! > value.lessonYearIndex!) {
+                return lesson;
+              } else {
+                return value;
+              }
+            },
+            ifAbsent: () => lesson,
+          );
+        }
+      }
+      setState(() {});
+    });
+  }
+
+  void buildSubjectAbsences() {
+    Map<Subject, SubjectAbsence> _absences = {};
+
+    for (final absence in absenceProvider.absences) {
+      if (absence.delay != 0) continue;
+
+      if (!_absences.containsKey(absence.subject)) {
+        _absences[absence.subject] =
+            SubjectAbsence(subject: absence.subject, absences: [absence]);
+      } else {
+        _absences[absence.subject]?.absences.add(absence);
+      }
+    }
+
+    _absences.forEach((subject, absence) {
+      final absentLessonsOfSubject = absenceProvider.absences
+          .where((e) => e.subject == subject && e.delay == 0)
+          .length;
+      final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
+
+      double absentLessonsOfSubjectPercentage;
+
+      if (absentLessonsOfSubject <= totalLessonsOfSubject) {
+        absentLessonsOfSubjectPercentage =
+            absentLessonsOfSubject / totalLessonsOfSubject * 100;
+      } else {
+        absentLessonsOfSubjectPercentage = -1;
+      }
+
+      _absences[subject]?.percentage =
+          absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
+    });
+
+    absences = _absences.values.toList();
+    absences.sort((a, b) => -a.percentage.compareTo(b.percentage));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    absenceProvider = Provider.of<AbsenceProvider>(context);
+    noteProvider = Provider.of<NoteProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+    timetableProvider = Provider.of<TimetableProvider>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    buildSubjectAbsences();
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 12.0),
+        child: NestedScrollView(
+          physics: const BouncingScrollPhysics(
+              parent: AlwaysScrollableScrollPhysics()),
+          headerSliverBuilder: (context, _) => [
+            SliverAppBar(
+              pinned: true,
+              floating: false,
+              snap: false,
+              centerTitle: false,
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+              actions: [
+                // Profile Icon
+                Padding(
+                  padding: const EdgeInsets.only(right: 24.0),
+                  child: ProfileButton(
+                    child: ProfileImage(
+                      heroTag: "profile",
+                      name: firstName,
+                      backgroundColor: Theme.of(context)
+                          .colorScheme
+                          .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
+                      badge: updateProvider.available,
+                      role: user.role,
+                      profilePictureString: user.picture,
+                    ),
+                  ),
+                ),
+              ],
+              automaticallyImplyLeading: false,
+              shadowColor: Theme.of(context).shadowColor,
+              title: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  "Absences".i18n,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontSize: 32.0,
+                      fontWeight: FontWeight.bold),
+                ),
+              ),
+              bottom: FilterBar(
+                items: [
+                  Tab(text: "Absences".i18n),
+                  Tab(text: "Delays".i18n),
+                  Tab(text: "Misses".i18n),
+                ],
+                controller: _tabController,
+                disableFading: true,
+              ),
+            ),
+          ],
+          body: TabBarView(
+              physics: const BouncingScrollPhysics(),
+              controller: _tabController,
+              children: List.generate(
+                  3, (index) => filterViewBuilder(context, index))),
+        ),
+      ),
+    );
+  }
+
+  List<DateWidget> getFilterWidgets(AbsenceFilter activeData) {
+    List<DateWidget> items = [];
+    switch (activeData) {
+      case AbsenceFilter.absences:
+        for (var a in absences) {
+          items.add(DateWidget(
+            date: DateTime.fromMillisecondsSinceEpoch(0),
+            widget: AbsenceSubjectTile(
+              a.subject,
+              percentage: a.percentage,
+              excused: a.absences
+                  .where((a) => a.state == Justification.excused)
+                  .length,
+              unexcused: a.absences
+                  .where((a) => a.state == Justification.unexcused)
+                  .length,
+              pending: a.absences
+                  .where((a) => a.state == Justification.pending)
+                  .length,
+              onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
+                  context: context),
+            ),
+          ));
+        }
+        break;
+      case AbsenceFilter.delays:
+        for (var absence in absenceProvider.absences) {
+          if (absence.delay != 0) {
+            items.add(DateWidget(
+              date: absence.date,
+              widget: AbsenceViewable(absence, padding: EdgeInsets.zero),
+            ));
+          }
+        }
+        break;
+      case AbsenceFilter.misses:
+        for (var note in noteProvider.notes) {
+          if (note.type?.name == "HaziFeladatHiany" ||
+              note.type?.name == "Felszereleshiany") {
+            items.add(DateWidget(
+              date: note.date,
+              widget: MissTile(note),
+            ));
+          }
+        }
+        break;
+    }
+    return items;
+  }
+
+  Widget filterViewBuilder(context, int activeData) {
+    List<Widget> filterWidgets = [];
+
+    if (activeData > 0) {
+      filterWidgets = sortDateWidgets(
+        context,
+        dateWidgets: getFilterWidgets(AbsenceFilter.values[activeData]),
+        padding: EdgeInsets.zero,
+        hasShadow: true,
+      );
+    } else {
+      filterWidgets = [
+        Padding(
+          padding: const EdgeInsets.only(bottom: 24.0),
+          child: Panel(
+            title: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Text("Subjects".i18n),
+                Padding(
+                  padding: const EdgeInsets.only(right: 4.0),
+                  child: IconButton(
+                    onPressed: () {
+                      showDialog(
+                        context: context,
+                        builder: (context) => AlertDialog(
+                          shape: RoundedRectangleBorder(
+                              borderRadius: BorderRadius.circular(12.0)),
+                          title: Text("attention".i18n),
+                          content: Text("attention_body".i18n),
+                          actions: [
+                            ActionButton(
+                                label: "Ok",
+                                onTap: () => Navigator.of(context).pop())
+                          ],
+                        ),
+                      );
+                    },
+                    padding: EdgeInsets.zero,
+                    splashRadius: 24.0,
+                    visualDensity: VisualDensity.compact,
+                    constraints: BoxConstraints.tight(const Size(42.0, 42.0)),
+                    icon: const Icon(FeatherIcons.info),
+                  ),
+                ),
+              ],
+            ),
+            child: PageTransitionSwitcher(
+              transitionBuilder: (
+                Widget child,
+                Animation<double> primaryAnimation,
+                Animation<double> secondaryAnimation,
+              ) {
+                return FadeThroughTransition(
+                  child: child,
+                  animation: primaryAnimation,
+                  secondaryAnimation: secondaryAnimation,
+                  fillColor: Theme.of(context).colorScheme.background,
+                );
+              },
+              child: Column(
+                children: getFilterWidgets(AbsenceFilter.values[activeData])
+                    .map((e) => e.widget)
+                    .cast<Widget>()
+                    .toList(),
+              ),
+            ),
+          ),
+        )
+      ];
+    }
+
+    return Padding(
+      padding: const EdgeInsets.only(top: 12.0),
+      child: RefreshIndicator(
+        color: Theme.of(context).colorScheme.secondary,
+        onRefresh: () async {
+          await absenceProvider.fetch();
+          await noteProvider.fetch();
+        },
+        child: ListView.builder(
+          padding: EdgeInsets.zero,
+          physics: const BouncingScrollPhysics(),
+          itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
+          itemBuilder: (context, index) {
+            if (filterWidgets.isNotEmpty) {
+              if ((index == 0 && activeData == 1) ||
+                  (index == 0 && activeData == 0)) {
+                int value1 = 0;
+                int value2 = 0;
+                String title1 = "";
+                String title2 = "";
+                String suffix = "";
+
+                if (activeData == AbsenceFilter.absences.index) {
+                  value1 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay == 0 && e.state == Justification.excused)
+                      .length;
+                  value2 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay == 0 && e.state == Justification.unexcused)
+                      .length;
+                  title1 = "stat_1".i18n;
+                  title2 = "stat_2".i18n;
+                  suffix = " " + "hr".i18n;
+                } else if (activeData == AbsenceFilter.delays.index) {
+                  value1 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay != 0 && e.state == Justification.excused)
+                      .map((e) => e.delay)
+                      .fold(0, (a, b) => a + b);
+                  value2 = absenceProvider.absences
+                      .where((e) =>
+                          e.delay != 0 && e.state == Justification.unexcused)
+                      .map((e) => e.delay)
+                      .fold(0, (a, b) => a + b);
+                  title1 = "stat_3".i18n;
+                  title2 = "stat_4".i18n;
+                  suffix = " " + "min".i18n;
+                }
+
+                return Padding(
+                  padding: const EdgeInsets.only(
+                      bottom: 24.0, left: 24.0, right: 24.0),
+                  child: Row(children: [
+                    Expanded(
+                      child: StatisticsTile(
+                        title: AutoSizeText(
+                          title1,
+                          textAlign: TextAlign.center,
+                          maxLines: 2,
+                          overflow: TextOverflow.ellipsis,
+                        ),
+                        valueSuffix: suffix,
+                        value: value1.toDouble(),
+                        decimal: false,
+                        color: AppColors.of(context).green,
+                      ),
+                    ),
+                    const SizedBox(width: 24.0),
+                    Expanded(
+                      child: StatisticsTile(
+                        title: AutoSizeText(
+                          title2,
+                          textAlign: TextAlign.center,
+                          maxLines: 2,
+                          overflow: TextOverflow.ellipsis,
+                        ),
+                        valueSuffix: suffix,
+                        value: value2.toDouble(),
+                        decimal: false,
+                        color: AppColors.of(context).red,
+                      ),
+                    ),
+                  ]),
+                );
+              }
+
+              return Padding(
+                padding:
+                    const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
+                child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
+              );
+            } else {
+              return Empty(subtitle: "empty".i18n);
+            }
+          },
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/absences/absences_page.i18n.dart b/refilc_mobile_ui/lib/pages/absences/absences_page.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/absences/absences_page.i18n.dart
rename to refilc_mobile_ui/lib/pages/absences/absences_page.i18n.dart
index 91b7621..2b37c00
--- a/filcnaplo_mobile_ui/lib/pages/absences/absences_page.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/absences/absences_page.i18n.dart
@@ -1,57 +1,57 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension ScreensLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Absences": "Absences",
-          "Delays": "Delays",
-          "Misses": "Misses",
-          "empty": "You have no absences.",
-          "stat_1": "Excused Absences",
-          "stat_2": "Unexcused Absences",
-          "stat_3": "Excused Delay",
-          "stat_4": "Unexcused Delay",
-          "min": "min",
-          "hr": "hrs",
-          "Subjects": "Subjects",
-          "attention": "Attention!",
-          "attention_body": "Percentage calculations are only an approximation so they may not be accurate.",
-        },
-        "hu_hu": {
-          "Absences": "Hiányzások",
-          "Delays": "Késések",
-          "Misses": "Hiányok",
-          "empty": "Nincsenek hiányaid.",
-          "stat_1": "Igazolt hiányzások",
-          "stat_2": "Igazolatlan hiányzások",
-          "stat_3": "Igazolt Késés",
-          "stat_4": "Igazolatlan Késés",
-          "min": "perc",
-          "hr": "óra",
-          "Subjects": "Tantárgyak",
-          "attention": "Figyelem!",
-          "attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.",
-        },
-        "de_de": {
-          "Absences": "Fehlen",
-          "Delays": "Verspätung",
-          "Misses": "Fehlt",
-          "empty": "Sie haben keine Fehlen.",
-          "stat_1": "Entschuldigte Fehlen",
-          "stat_2": "Unentschuldigte Fehlen",
-          "stat_3": "Entschuldigte Verspätung",
-          "stat_4": "Unentschuldigte Verspätung",
-          "min": "min",
-          "hr": "hrs",
-          "Subjects": "Fächer",
-          "attention": "Achtung!",
-          "attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension ScreensLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Absences": "Absences",
+          "Delays": "Delays",
+          "Misses": "Misses",
+          "empty": "You have no absences.",
+          "stat_1": "Excused Absences",
+          "stat_2": "Unexcused Absences",
+          "stat_3": "Excused Delay",
+          "stat_4": "Unexcused Delay",
+          "min": "min",
+          "hr": "hrs",
+          "Subjects": "Subjects",
+          "attention": "Attention!",
+          "attention_body": "Percentage calculations are only an approximation so they may not be accurate.",
+        },
+        "hu_hu": {
+          "Absences": "Hiányzások",
+          "Delays": "Késések",
+          "Misses": "Hiányok",
+          "empty": "Nincsenek hiányaid.",
+          "stat_1": "Igazolt hiányzások",
+          "stat_2": "Igazolatlan hiányzások",
+          "stat_3": "Igazolt Késés",
+          "stat_4": "Igazolatlan Késés",
+          "min": "perc",
+          "hr": "óra",
+          "Subjects": "Tantárgyak",
+          "attention": "Figyelem!",
+          "attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.",
+        },
+        "de_de": {
+          "Absences": "Fehlen",
+          "Delays": "Verspätung",
+          "Misses": "Fehlt",
+          "empty": "Sie haben keine Fehlen.",
+          "stat_1": "Entschuldigte Fehlen",
+          "stat_2": "Unentschuldigte Fehlen",
+          "stat_3": "Entschuldigte Verspätung",
+          "stat_4": "Unentschuldigte Verspätung",
+          "min": "min",
+          "hr": "hrs",
+          "Subjects": "Fächer",
+          "attention": "Achtung!",
+          "attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator.dart b/refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator.dart
old mode 100755
new mode 100644
similarity index 89%
rename from filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator.dart
rename to refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator.dart
index 384afa5..3f046ed
--- a/filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator.dart
+++ b/refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator.dart
@@ -1,178 +1,178 @@
-import 'dart:math';
-
-import 'package:filcnaplo_kreta_api/models/category.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/teacher.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/material_action_button.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
-import 'grade_calculator.i18n.dart';
-
-class GradeCalculator extends StatefulWidget {
-  const GradeCalculator(this.subject, {Key? key}) : super(key: key);
-
-  final Subject subject;
-
-  @override
-  _GradeCalculatorState createState() => _GradeCalculatorState();
-}
-
-class _GradeCalculatorState extends State<GradeCalculator> {
-  late GradeCalculatorProvider calculatorProvider;
-
-  final _weightController = TextEditingController(text: "100");
-
-  double newValue = 5.0;
-  double newWeight = 100.0;
-
-  @override
-  Widget build(BuildContext context) {
-    calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
-
-    return Container(
-      width: double.infinity,
-      padding: const EdgeInsets.all(6.0),
-      child: Column(
-        children: [
-          Padding(
-            padding: const EdgeInsets.only(bottom: 8.0),
-            child: Text(
-              "Grade Calculator".i18n,
-              style:
-                  const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w600),
-            ),
-          ),
-
-          // Grade value
-          Row(children: [
-            Expanded(
-              child: Slider(
-                thumbColor: Theme.of(context).colorScheme.secondary,
-                activeColor: Theme.of(context).colorScheme.secondary,
-                value: newValue,
-                min: 1.0,
-                max: 5.0,
-                divisions: 4,
-                label: "${newValue.toInt()}",
-                onChanged: (value) => setState(() => newValue = value),
-              ),
-            ),
-            Container(
-              width: 80.0,
-              padding: const EdgeInsets.only(right: 12.0),
-              child: Center(
-                  child: GradeValueWidget(
-                      GradeValue(newValue.toInt(), "", "", 0))),
-            ),
-          ]),
-
-          // Grade weight
-          Row(children: [
-            Expanded(
-              child: Slider(
-                thumbColor: Theme.of(context).colorScheme.secondary,
-                activeColor: Theme.of(context).colorScheme.secondary,
-                value: newWeight.clamp(50, 400),
-                min: 50.0,
-                max: 400.0,
-                divisions: 7,
-                label: "${newWeight.toInt()}%",
-                onChanged: (value) => setState(() {
-                  newWeight = value;
-                  _weightController.text = newWeight.toInt().toString();
-                }),
-              ),
-            ),
-            Container(
-              width: 80.0,
-              padding: const EdgeInsets.only(right: 12.0),
-              child: Center(
-                child: TextField(
-                  controller: _weightController,
-                  style: const TextStyle(
-                      fontWeight: FontWeight.w600, fontSize: 22.0),
-                  autocorrect: false,
-                  textAlign: TextAlign.right,
-                  keyboardType: TextInputType.number,
-                  inputFormatters: [
-                    FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
-                    LengthLimitingTextInputFormatter(3),
-                  ],
-                  decoration: const InputDecoration(
-                    border: InputBorder.none,
-                    enabledBorder: InputBorder.none,
-                    focusedBorder: InputBorder.none,
-                    hintText: "100",
-                    suffixText: "%",
-                    suffixStyle: TextStyle(fontSize: 18.0),
-                  ),
-                  onChanged: (value) {
-                    setState(() {
-                      newWeight = double.tryParse(value) ?? 100.0;
-                    });
-                  },
-                ),
-              ),
-            ),
-          ]),
-          Container(
-            width: 120.0,
-            padding: const EdgeInsets.symmetric(vertical: 12.0),
-            child: MaterialActionButton(
-              child: Text("Add Grade".i18n),
-              onPressed: () {
-                if (calculatorProvider.ghosts.length >= 50) {
-                  ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
-                      content: Text("limit_reached".i18n), context: context));
-                  return;
-                }
-
-                DateTime date;
-
-                if (calculatorProvider.ghosts.isNotEmpty) {
-                  List<Grade> grades = calculatorProvider.ghosts;
-                  grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
-                  date = grades.first.date.add(const Duration(days: 7));
-                } else {
-                  List<Grade> grades = calculatorProvider.grades
-                      .where((e) =>
-                          e.type == GradeType.midYear &&
-                          e.subject == widget.subject)
-                      .toList();
-                  grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
-                  date = grades.first.date;
-                }
-
-                calculatorProvider.addGhost(Grade(
-                  id: randomId(),
-                  date: date,
-                  writeDate: date,
-                  description: "Ghost Grade".i18n,
-                  value:
-                      GradeValue(newValue.toInt(), "", "", newWeight.toInt()),
-                  teacher: Teacher.fromString("Ghost"),
-                  type: GradeType.ghost,
-                  form: "",
-                  subject: widget.subject,
-                  mode: Category.fromJson({}),
-                  seenDate: DateTime(0),
-                  groupId: "",
-                ));
-              },
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-
-  String randomId() {
-    var rng = Random();
-    return rng.nextInt(1000000000).toString();
-  }
-}
+import 'dart:math';
+
+import 'package:refilc_kreta_api/models/category.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/teacher.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_mobile_ui/common/material_action_button.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
+import 'grade_calculator.i18n.dart';
+
+class GradeCalculator extends StatefulWidget {
+  const GradeCalculator(this.subject, {Key? key}) : super(key: key);
+
+  final Subject subject;
+
+  @override
+  _GradeCalculatorState createState() => _GradeCalculatorState();
+}
+
+class _GradeCalculatorState extends State<GradeCalculator> {
+  late GradeCalculatorProvider calculatorProvider;
+
+  final _weightController = TextEditingController(text: "100");
+
+  double newValue = 5.0;
+  double newWeight = 100.0;
+
+  @override
+  Widget build(BuildContext context) {
+    calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
+
+    return Container(
+      width: double.infinity,
+      padding: const EdgeInsets.all(6.0),
+      child: Column(
+        children: [
+          Padding(
+            padding: const EdgeInsets.only(bottom: 8.0),
+            child: Text(
+              "Grade Calculator".i18n,
+              style:
+                  const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w600),
+            ),
+          ),
+
+          // Grade value
+          Row(children: [
+            Expanded(
+              child: Slider(
+                thumbColor: Theme.of(context).colorScheme.secondary,
+                activeColor: Theme.of(context).colorScheme.secondary,
+                value: newValue,
+                min: 1.0,
+                max: 5.0,
+                divisions: 4,
+                label: "${newValue.toInt()}",
+                onChanged: (value) => setState(() => newValue = value),
+              ),
+            ),
+            Container(
+              width: 80.0,
+              padding: const EdgeInsets.only(right: 12.0),
+              child: Center(
+                  child: GradeValueWidget(
+                      GradeValue(newValue.toInt(), "", "", 0))),
+            ),
+          ]),
+
+          // Grade weight
+          Row(children: [
+            Expanded(
+              child: Slider(
+                thumbColor: Theme.of(context).colorScheme.secondary,
+                activeColor: Theme.of(context).colorScheme.secondary,
+                value: newWeight.clamp(50, 400),
+                min: 50.0,
+                max: 400.0,
+                divisions: 7,
+                label: "${newWeight.toInt()}%",
+                onChanged: (value) => setState(() {
+                  newWeight = value;
+                  _weightController.text = newWeight.toInt().toString();
+                }),
+              ),
+            ),
+            Container(
+              width: 80.0,
+              padding: const EdgeInsets.only(right: 12.0),
+              child: Center(
+                child: TextField(
+                  controller: _weightController,
+                  style: const TextStyle(
+                      fontWeight: FontWeight.w600, fontSize: 22.0),
+                  autocorrect: false,
+                  textAlign: TextAlign.right,
+                  keyboardType: TextInputType.number,
+                  inputFormatters: [
+                    FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
+                    LengthLimitingTextInputFormatter(3),
+                  ],
+                  decoration: const InputDecoration(
+                    border: InputBorder.none,
+                    enabledBorder: InputBorder.none,
+                    focusedBorder: InputBorder.none,
+                    hintText: "100",
+                    suffixText: "%",
+                    suffixStyle: TextStyle(fontSize: 18.0),
+                  ),
+                  onChanged: (value) {
+                    setState(() {
+                      newWeight = double.tryParse(value) ?? 100.0;
+                    });
+                  },
+                ),
+              ),
+            ),
+          ]),
+          Container(
+            width: 120.0,
+            padding: const EdgeInsets.symmetric(vertical: 12.0),
+            child: MaterialActionButton(
+              child: Text("Add Grade".i18n),
+              onPressed: () {
+                if (calculatorProvider.ghosts.length >= 50) {
+                  ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
+                      content: Text("limit_reached".i18n), context: context));
+                  return;
+                }
+
+                DateTime date;
+
+                if (calculatorProvider.ghosts.isNotEmpty) {
+                  List<Grade> grades = calculatorProvider.ghosts;
+                  grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
+                  date = grades.first.date.add(const Duration(days: 7));
+                } else {
+                  List<Grade> grades = calculatorProvider.grades
+                      .where((e) =>
+                          e.type == GradeType.midYear &&
+                          e.subject == widget.subject)
+                      .toList();
+                  grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
+                  date = grades.first.date;
+                }
+
+                calculatorProvider.addGhost(Grade(
+                  id: randomId(),
+                  date: date,
+                  writeDate: date,
+                  description: "Ghost Grade".i18n,
+                  value:
+                      GradeValue(newValue.toInt(), "", "", newWeight.toInt()),
+                  teacher: Teacher.fromString("Ghost"),
+                  type: GradeType.ghost,
+                  form: "",
+                  subject: widget.subject,
+                  mode: Category.fromJson({}),
+                  seenDate: DateTime(0),
+                  groupId: "",
+                ));
+              },
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  String randomId() {
+    var rng = Random();
+    return rng.nextInt(1000000000).toString();
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator.i18n.dart b/refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator.i18n.dart
rename to refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator.i18n.dart
index a83e3df..7c0565c
--- a/filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator.i18n.dart
@@ -1,33 +1,33 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Grades": "Grades",
-          "Ghost Grade": "Ghost Grade",
-          "Grade Calculator": "Average calculator",
-          "Add Grade": "Add Grade",
-          "limit_reached": "You cannot add more Ghost Grades.",
-        },
-        "hu_hu": {
-          "Grades": "Jegyek",
-          "Ghost Grade": "Szellem jegy",
-          "Grade Calculator": "Átlag számoló",
-          "Add Grade": "Hozzáadás",
-          "limit_reached": "Nem adhatsz hozzá több jegyet.",
-        },
-        "de_de": {
-          "Grades": "Noten",
-          "Ghost Grade": "Geist Noten",
-          "Grade Calculator": "Mittelwert-Rechner",
-          "Add Grade": "Hinzufügen",
-          "limit_reached": "Sie können keine weiteren Noten hinzufügen.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Grades": "Grades",
+          "Ghost Grade": "Ghost Grade",
+          "Grade Calculator": "Average calculator",
+          "Add Grade": "Add Grade",
+          "limit_reached": "You cannot add more Ghost Grades.",
+        },
+        "hu_hu": {
+          "Grades": "Jegyek",
+          "Ghost Grade": "Szellem jegy",
+          "Grade Calculator": "Átlag számoló",
+          "Add Grade": "Hozzáadás",
+          "limit_reached": "Nem adhatsz hozzá több jegyet.",
+        },
+        "de_de": {
+          "Grades": "Noten",
+          "Ghost Grade": "Geist Noten",
+          "Grade Calculator": "Mittelwert-Rechner",
+          "Add Grade": "Hinzufügen",
+          "limit_reached": "Sie können keine weiteren Noten hinzufügen.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator_provider.dart b/refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator_provider.dart
old mode 100755
new mode 100644
similarity index 71%
rename from filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator_provider.dart
rename to refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator_provider.dart
index 00383e8..662ce41
--- a/filcnaplo_mobile_ui/lib/pages/grades/calculator/grade_calculator_provider.dart
+++ b/refilc_mobile_ui/lib/pages/grades/calculator/grade_calculator_provider.dart
@@ -1,53 +1,53 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-
-class GradeCalculatorProvider extends GradeProvider {
-  GradeCalculatorProvider({
-    List<Grade> initialGrades = const [],
-    required SettingsProvider settings,
-    required UserProvider user,
-    required DatabaseProvider database,
-    required KretaClient kreta,
-  }) : super(
-          initialGrades: initialGrades,
-          settings: settings,
-          database: database,
-          kreta: kreta,
-          user: user,
-        );
-
-  List<Grade> _grades = [];
-  List<Grade> _ghosts = [];
-  @override
-  List<Grade> get grades => _grades + _ghosts;
-  List<Grade> get ghosts => _ghosts;
-
-  void addGhost(Grade grade) {
-    _ghosts.add(grade);
-    notifyListeners();
-  }
-
-  void addGrade(Grade grade) {
-    _grades.add(grade);
-    notifyListeners();
-  }
-
-  void removeGrade(Grade ghost) {
-    _ghosts.removeWhere((e) => ghost.id == e.id);
-    notifyListeners();
-  }
-
-  void addAllGrades(List<Grade> grades) {
-    _grades.addAll(grades);
-    notifyListeners();
-  }
-
-  void clear() {
-    _grades = [];
-    _ghosts = [];
-  }
-}
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+
+class GradeCalculatorProvider extends GradeProvider {
+  GradeCalculatorProvider({
+    List<Grade> initialGrades = const [],
+    required SettingsProvider settings,
+    required UserProvider user,
+    required DatabaseProvider database,
+    required KretaClient kreta,
+  }) : super(
+          initialGrades: initialGrades,
+          settings: settings,
+          database: database,
+          kreta: kreta,
+          user: user,
+        );
+
+  List<Grade> _grades = [];
+  List<Grade> _ghosts = [];
+  @override
+  List<Grade> get grades => _grades + _ghosts;
+  List<Grade> get ghosts => _ghosts;
+
+  void addGhost(Grade grade) {
+    _ghosts.add(grade);
+    notifyListeners();
+  }
+
+  void addGrade(Grade grade) {
+    _grades.add(grade);
+    notifyListeners();
+  }
+
+  void removeGrade(Grade ghost) {
+    _ghosts.removeWhere((e) => ghost.id == e.id);
+    notifyListeners();
+  }
+
+  void addAllGrades(List<Grade> grades) {
+    _grades.addAll(grades);
+    notifyListeners();
+  }
+
+  void clear() {
+    _grades = [];
+    _ghosts = [];
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/fail_warning.dart b/refilc_mobile_ui/lib/pages/grades/fail_warning.dart
old mode 100755
new mode 100644
similarity index 79%
rename from filcnaplo_mobile_ui/lib/pages/grades/fail_warning.dart
rename to refilc_mobile_ui/lib/pages/grades/fail_warning.dart
index 9e893fe..5537938
--- a/filcnaplo_mobile_ui/lib/pages/grades/fail_warning.dart
+++ b/refilc_mobile_ui/lib/pages/grades/fail_warning.dart
@@ -1,39 +1,40 @@
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'grades_page.i18n.dart';
-
-class FailWarning extends StatelessWidget {
-  const FailWarning({Key? key, required this.subjectAvgs}) : super(key: key);
-
-  final Map<Subject, double> subjectAvgs;
-
-  @override
-  Widget build(BuildContext context) {
-    final failingSubjectCount = subjectAvgs.values.where((avg) => avg < 2.0).length;
-
-    if (failingSubjectCount == 0) {
-      return const SizedBox();
-    }
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 24.0),
-      child: Panel(
-        title: Text("fail_warning".i18n),
-        padding: const EdgeInsets.all(16.0),
-        child: Row(
-          children: [
-            Icon(
-              FeatherIcons.alertTriangle,
-              color: Colors.orange.withOpacity(.5),
-              size: 20.0,
-            ),
-            const SizedBox(width: 12.0),
-            Text("fail_warning_description".i18n.fill([failingSubjectCount])),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'grades_page.i18n.dart';
+
+class FailWarning extends StatelessWidget {
+  const FailWarning({Key? key, required this.subjectAvgs}) : super(key: key);
+
+  final Map<Subject, double> subjectAvgs;
+
+  @override
+  Widget build(BuildContext context) {
+    final failingSubjectCount =
+        subjectAvgs.values.where((avg) => avg < 2.0).length;
+
+    if (failingSubjectCount == 0) {
+      return const SizedBox();
+    }
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 24.0),
+      child: Panel(
+        title: Text("fail_warning".i18n),
+        padding: const EdgeInsets.all(16.0),
+        child: Row(
+          children: [
+            Icon(
+              FeatherIcons.alertTriangle,
+              color: Colors.orange.withOpacity(.5),
+              size: 20.0,
+            ),
+            const SizedBox(width: 12.0),
+            Text("fail_warning_description".i18n.fill([failingSubjectCount])),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart b/refilc_mobile_ui/lib/pages/grades/grade_subject_view.dart
old mode 100755
new mode 100644
similarity index 83%
rename from filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart
rename to refilc_mobile_ui/lib/pages/grades/grade_subject_view.dart
index 21949b2..998da40
--- a/filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart
+++ b/refilc_mobile_ui/lib/pages/grades/grade_subject_view.dart
@@ -1,370 +1,370 @@
-import 'dart:math';
-
-import 'package:animations/animations.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/utils/format.dart';
-// import 'package:filcnaplo_kreta_api/client/api.dart';
-// import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/trend_display.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_tile.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_viewable.dart';
-import 'package:filcnaplo_mobile_ui/common/hero_scrollview.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/grades_count.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner_screen.dart';
-import 'package:filcnaplo_premium/models/premium_scopes.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'grades_page.i18n.dart';
-// import 'package:filcnaplo_premium/ui/mobile/goal_planner/new_goal.dart';
-
-class GradeSubjectView extends StatefulWidget {
-  const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
-      : super(key: key);
-
-  final Subject subject;
-  final double groupAverage;
-
-  void push(BuildContext context, {bool root = false}) {
-    Navigator.of(context, rootNavigator: root)
-        .push(CupertinoPageRoute(builder: (context) => this));
-  }
-
-  @override
-  State<GradeSubjectView> createState() => _GradeSubjectViewState();
-}
-
-class _GradeSubjectViewState extends State<GradeSubjectView> {
-  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
-
-  // Controllers
-  PersistentBottomSheetController? _sheetController;
-  final ScrollController _scrollController = ScrollController();
-
-  List<Widget> gradeTiles = [];
-
-  // Providers
-  late GradeProvider gradeProvider;
-  late GradeCalculatorProvider calculatorProvider;
-  late SettingsProvider settingsProvider;
-  late DatabaseProvider dbProvider;
-  late UserProvider user;
-
-  late double average;
-  late Widget gradeGraph;
-
-  bool gradeCalcMode = false;
-
-  String plan = '';
-
-  List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
-      ? gradeProvider.grades.where((e) => e.subject == subject).toList()
-      : calculatorProvider.grades.where((e) => e.subject == subject).toList();
-
-  bool showGraph(List<Grade> subjectGrades) {
-    if (gradeCalcMode) return true;
-
-    final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
-    final maxGradeDate = gradeDates.fold(0, max);
-    final minGradeDate = gradeDates.fold(0, min);
-    if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
-      return false; // naplo/#78
-    }
-
-    return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
-  }
-
-  void buildTiles(List<Grade> subjectGrades) {
-    List<Widget> tiles = [];
-
-    if (showGraph(subjectGrades)) {
-      tiles.add(gradeGraph);
-    } else {
-      tiles.add(Container(height: 24.0));
-    }
-
-    tiles.add(Padding(
-      padding: const EdgeInsets.only(bottom: 24.0),
-      child: Panel(
-        child: GradesCount(grades: getSubjectGrades(widget.subject).toList()),
-      ),
-    ));
-
-    List<Widget> _gradeTiles = [];
-
-    if (!gradeCalcMode) {
-      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
-      for (var grade in subjectGrades) {
-        if (grade.type == GradeType.midYear) {
-          _gradeTiles.add(GradeViewable(grade));
-        } else {
-          _gradeTiles.add(CertificationTile(grade, padding: EdgeInsets.zero));
-        }
-      }
-    } else if (subjectGrades.isNotEmpty) {
-      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
-      for (var grade in subjectGrades) {
-        _gradeTiles.add(GradeTile(grade));
-      }
-    }
-    tiles.add(
-      PageTransitionSwitcher(
-        transitionBuilder: (
-          Widget child,
-          Animation<double> primaryAnimation,
-          Animation<double> secondaryAnimation,
-        ) {
-          return SharedAxisTransition(
-            animation: primaryAnimation,
-            secondaryAnimation: secondaryAnimation,
-            transitionType: SharedAxisTransitionType.vertical,
-            child: child,
-            fillColor: Colors.transparent,
-          );
-        },
-        child: _gradeTiles.isNotEmpty
-            ? Panel(
-                key: ValueKey(gradeCalcMode),
-                title: Text(
-                  gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
-                ),
-                child: Column(
-                  children: _gradeTiles,
-                ))
-            : const SizedBox(),
-      ),
-    );
-
-    tiles.add(Padding(
-        padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
-    gradeTiles = List.castFrom(tiles);
-  }
-
-  @override
-  void initState() {
-    super.initState();
-    user = Provider.of<UserProvider>(context, listen: false);
-    dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
-  }
-
-  void fetchGoalPlans() async {
-    plan = (await dbProvider.userQuery
-            .subjectGoalPlans(userId: user.id!))[widget.subject.id] ??
-        '';
-    setState(() {});
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    gradeProvider = Provider.of<GradeProvider>(context);
-    calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
-    settingsProvider = Provider.of<SettingsProvider>(context);
-
-    List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
-    average = AverageHelper.averageEvals(subjectGrades);
-    final prevAvg = subjectGrades.isNotEmpty
-        ? AverageHelper.averageEvals(subjectGrades
-            .where((e) => e.date.isBefore(subjectGrades
-                .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
-                .date
-                .subtract(const Duration(days: 30))))
-            .toList())
-        : 0.0;
-
-    gradeGraph = Padding(
-      padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
-      child: Panel(
-        title: Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: [
-            Text("annual_average".i18n),
-            if (average != prevAvg)
-              TrendDisplay(current: average, previous: prevAvg),
-          ],
-        ),
-        child: Container(
-          padding: const EdgeInsets.only(top: 16.0, right: 12.0),
-          child: GradeGraph(subjectGrades,
-              dayThreshold: 5, classAvg: widget.groupAverage),
-        ),
-      ),
-    );
-
-    if (!gradeCalcMode) {
-      buildTiles(subjectGrades);
-    } else {
-      List<Grade> ghostGrades = calculatorProvider.ghosts
-          .where((e) => e.subject == widget.subject)
-          .toList();
-      buildTiles(ghostGrades);
-    }
-
-    fetchGoalPlans();
-
-    return Scaffold(
-        key: _scaffoldKey,
-        floatingActionButtonLocation: ExpandableFab.location,
-        floatingActionButton: Visibility(
-          visible: !gradeCalcMode &&
-              subjectGrades
-                  .where((e) => e.type == GradeType.midYear)
-                  .isNotEmpty,
-          child: ExpandableFab(
-            backgroundColor: Theme.of(context).colorScheme.secondary,
-            type: ExpandableFabType.up,
-            distance: 50,
-            closeButtonStyle: ExpandableFabCloseButtonStyle(
-              backgroundColor: Theme.of(context).colorScheme.secondary,
-            ),
-            children: [
-              FloatingActionButton.small(
-                heroTag: "btn_ghost_grades",
-                child: const Icon(FeatherIcons.plus),
-                backgroundColor: Theme.of(context).colorScheme.secondary,
-                onPressed: () {
-                  gradeCalc(context);
-                },
-              ),
-              FloatingActionButton.small(
-                heroTag: "btn_goal_planner",
-                child: const Icon(FeatherIcons.flag, size: 20.0),
-                backgroundColor: Theme.of(context).colorScheme.secondary,
-                onPressed: () {
-                  if (!Provider.of<PremiumProvider>(context, listen: false)
-                      .hasScope(PremiumScopes.goalPlanner)) {
-                    PremiumLockedFeatureUpsell.show(
-                        context: context, feature: PremiumFeature.goalplanner);
-                    return;
-                  }
-
-                  // ScaffoldMessenger.of(context).showSnackBar(
-                  //     const SnackBar(content: Text("Hamarosan...")));
-
-                  Navigator.of(context).push(CupertinoPageRoute(
-                      builder: (context) =>
-                          GoalPlannerScreen(subject: widget.subject)));
-                },
-              ),
-            ],
-          ),
-        ),
-        body: RefreshIndicator(
-          onRefresh: () async {},
-          color: Theme.of(context).colorScheme.secondary,
-          child: HeroScrollView(
-              onClose: () {
-                if (_sheetController != null && gradeCalcMode) {
-                  _sheetController!.close();
-                } else {
-                  Navigator.of(context).pop();
-                }
-              },
-              navBarItems: [
-                const SizedBox(width: 6.0),
-                if (widget.groupAverage != 0)
-                  Center(
-                      child: AverageDisplay(
-                          average: widget.groupAverage, border: true)),
-                const SizedBox(width: 6.0),
-                if (average != 0)
-                  Center(child: AverageDisplay(average: average)),
-                const SizedBox(width: 6.0),
-                if (plan != '')
-                  Center(
-                    child: GestureDetector(
-                      onTap: () {
-                        Navigator.of(context).push(CupertinoPageRoute(
-                            builder: (context) =>
-                                GoalStateScreen(subject: widget.subject)));
-                      },
-                      child: Container(
-                        width: 54.0,
-                        padding: const EdgeInsets.symmetric(vertical: 8.0),
-                        decoration: BoxDecoration(
-                          borderRadius: BorderRadius.circular(45.0),
-                          color: Theme.of(context)
-                              .colorScheme
-                              .primary
-                              .withOpacity(.15),
-                        ),
-                        child: Icon(
-                          FeatherIcons.flag,
-                          size: 17.0,
-                          weight: 2.5,
-                          color: Theme.of(context).colorScheme.primary,
-                        ),
-                      ),
-                    ),
-                  ),
-                const SizedBox(width: 12.0),
-              ],
-              icon: SubjectIcon.resolveVariant(
-                  subject: widget.subject, context: context),
-              scrollController: _scrollController,
-              title: widget.subject.renamedTo ?? widget.subject.name.capital(),
-              italic: settingsProvider.renamedSubjectsItalics &&
-                  widget.subject.isRenamed,
-              child: SubjectGradesContainer(
-                child: CupertinoScrollbar(
-                  child: ListView.builder(
-                    physics: const BouncingScrollPhysics(),
-                    padding: const EdgeInsets.symmetric(horizontal: 24.0),
-                    shrinkWrap: true,
-                    itemBuilder: (context, index) => gradeTiles[index],
-                    itemCount: gradeTiles.length,
-                  ),
-                ),
-              )),
-        ));
-  }
-
-  void gradeCalc(BuildContext context) {
-    // Scroll to the top of the page
-    _scrollController.animateTo(100,
-        duration: const Duration(milliseconds: 500), curve: Curves.ease);
-
-    calculatorProvider.clear();
-    calculatorProvider.addAllGrades(gradeProvider.grades);
-
-    _sheetController = _scaffoldKey.currentState?.showBottomSheet(
-      (context) => RoundedBottomSheet(
-          child: GradeCalculator(widget.subject), borderRadius: 14.0),
-      backgroundColor: const Color(0x00000000),
-      elevation: 12.0,
-    );
-
-    // Hide the fab and grades
-    setState(() {
-      gradeCalcMode = true;
-    });
-
-    _sheetController!.closed.then((value) {
-      // Show fab and grades
-      if (mounted) {
-        setState(() {
-          gradeCalcMode = false;
-        });
-      }
-    });
-  }
-}
+import 'dart:math';
+
+import 'package:animations/animations.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/utils/format.dart';
+// import 'package:refilc_kreta_api/client/api.dart';
+// import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/trend_display.dart';
+import 'package:refilc_mobile_ui/common/widgets/cretification/certification_tile.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart';
+import 'package:refilc_mobile_ui/common/hero_scrollview.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
+import 'package:refilc_mobile_ui/pages/grades/grades_count.dart';
+import 'package:refilc_mobile_ui/pages/grades/graph.dart';
+import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_planner_screen.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_state_screen.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'grades_page.i18n.dart';
+// import 'package:refilc_premium/ui/mobile/goal_planner/new_goal.dart';
+
+class GradeSubjectView extends StatefulWidget {
+  const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
+      : super(key: key);
+
+  final Subject subject;
+  final double groupAverage;
+
+  void push(BuildContext context, {bool root = false}) {
+    Navigator.of(context, rootNavigator: root)
+        .push(CupertinoPageRoute(builder: (context) => this));
+  }
+
+  @override
+  State<GradeSubjectView> createState() => _GradeSubjectViewState();
+}
+
+class _GradeSubjectViewState extends State<GradeSubjectView> {
+  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+
+  // Controllers
+  PersistentBottomSheetController? _sheetController;
+  final ScrollController _scrollController = ScrollController();
+
+  List<Widget> gradeTiles = [];
+
+  // Providers
+  late GradeProvider gradeProvider;
+  late GradeCalculatorProvider calculatorProvider;
+  late SettingsProvider settingsProvider;
+  late DatabaseProvider dbProvider;
+  late UserProvider user;
+
+  late double average;
+  late Widget gradeGraph;
+
+  bool gradeCalcMode = false;
+
+  String plan = '';
+
+  List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
+      ? gradeProvider.grades.where((e) => e.subject == subject).toList()
+      : calculatorProvider.grades.where((e) => e.subject == subject).toList();
+
+  bool showGraph(List<Grade> subjectGrades) {
+    if (gradeCalcMode) return true;
+
+    final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
+    final maxGradeDate = gradeDates.fold(0, max);
+    final minGradeDate = gradeDates.fold(0, min);
+    if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
+      return false; // naplo/#78
+    }
+
+    return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
+  }
+
+  void buildTiles(List<Grade> subjectGrades) {
+    List<Widget> tiles = [];
+
+    if (showGraph(subjectGrades)) {
+      tiles.add(gradeGraph);
+    } else {
+      tiles.add(Container(height: 24.0));
+    }
+
+    tiles.add(Padding(
+      padding: const EdgeInsets.only(bottom: 24.0),
+      child: Panel(
+        child: GradesCount(grades: getSubjectGrades(widget.subject).toList()),
+      ),
+    ));
+
+    List<Widget> _gradeTiles = [];
+
+    if (!gradeCalcMode) {
+      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
+      for (var grade in subjectGrades) {
+        if (grade.type == GradeType.midYear) {
+          _gradeTiles.add(GradeViewable(grade));
+        } else {
+          _gradeTiles.add(CertificationTile(grade, padding: EdgeInsets.zero));
+        }
+      }
+    } else if (subjectGrades.isNotEmpty) {
+      subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
+      for (var grade in subjectGrades) {
+        _gradeTiles.add(GradeTile(grade));
+      }
+    }
+    tiles.add(
+      PageTransitionSwitcher(
+        transitionBuilder: (
+          Widget child,
+          Animation<double> primaryAnimation,
+          Animation<double> secondaryAnimation,
+        ) {
+          return SharedAxisTransition(
+            animation: primaryAnimation,
+            secondaryAnimation: secondaryAnimation,
+            transitionType: SharedAxisTransitionType.vertical,
+            child: child,
+            fillColor: Colors.transparent,
+          );
+        },
+        child: _gradeTiles.isNotEmpty
+            ? Panel(
+                key: ValueKey(gradeCalcMode),
+                title: Text(
+                  gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
+                ),
+                child: Column(
+                  children: _gradeTiles,
+                ))
+            : const SizedBox(),
+      ),
+    );
+
+    tiles.add(Padding(
+        padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
+    gradeTiles = List.castFrom(tiles);
+  }
+
+  @override
+  void initState() {
+    super.initState();
+    user = Provider.of<UserProvider>(context, listen: false);
+    dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
+  }
+
+  void fetchGoalPlans() async {
+    plan = (await dbProvider.userQuery
+            .subjectGoalPlans(userId: user.id!))[widget.subject.id] ??
+        '';
+    setState(() {});
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    gradeProvider = Provider.of<GradeProvider>(context);
+    calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
+    settingsProvider = Provider.of<SettingsProvider>(context);
+
+    List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
+    average = AverageHelper.averageEvals(subjectGrades);
+    final prevAvg = subjectGrades.isNotEmpty
+        ? AverageHelper.averageEvals(subjectGrades
+            .where((e) => e.date.isBefore(subjectGrades
+                .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
+                .date
+                .subtract(const Duration(days: 30))))
+            .toList())
+        : 0.0;
+
+    gradeGraph = Padding(
+      padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
+      child: Panel(
+        title: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text("annual_average".i18n),
+            if (average != prevAvg)
+              TrendDisplay(current: average, previous: prevAvg),
+          ],
+        ),
+        child: Container(
+          padding: const EdgeInsets.only(top: 16.0, right: 12.0),
+          child: GradeGraph(subjectGrades,
+              dayThreshold: 5, classAvg: widget.groupAverage),
+        ),
+      ),
+    );
+
+    if (!gradeCalcMode) {
+      buildTiles(subjectGrades);
+    } else {
+      List<Grade> ghostGrades = calculatorProvider.ghosts
+          .where((e) => e.subject == widget.subject)
+          .toList();
+      buildTiles(ghostGrades);
+    }
+
+    fetchGoalPlans();
+
+    return Scaffold(
+        key: _scaffoldKey,
+        floatingActionButtonLocation: ExpandableFab.location,
+        floatingActionButton: Visibility(
+          visible: !gradeCalcMode &&
+              subjectGrades
+                  .where((e) => e.type == GradeType.midYear)
+                  .isNotEmpty,
+          child: ExpandableFab(
+            backgroundColor: Theme.of(context).colorScheme.secondary,
+            type: ExpandableFabType.up,
+            distance: 50,
+            closeButtonStyle: ExpandableFabCloseButtonStyle(
+              backgroundColor: Theme.of(context).colorScheme.secondary,
+            ),
+            children: [
+              FloatingActionButton.small(
+                heroTag: "btn_ghost_grades",
+                child: const Icon(FeatherIcons.plus),
+                backgroundColor: Theme.of(context).colorScheme.secondary,
+                onPressed: () {
+                  gradeCalc(context);
+                },
+              ),
+              FloatingActionButton.small(
+                heroTag: "btn_goal_planner",
+                child: const Icon(FeatherIcons.flag, size: 20.0),
+                backgroundColor: Theme.of(context).colorScheme.secondary,
+                onPressed: () {
+                  if (!Provider.of<PremiumProvider>(context, listen: false)
+                      .hasScope(PremiumScopes.goalPlanner)) {
+                    PremiumLockedFeatureUpsell.show(
+                        context: context, feature: PremiumFeature.goalplanner);
+                    return;
+                  }
+
+                  // ScaffoldMessenger.of(context).showSnackBar(
+                  //     const SnackBar(content: Text("Hamarosan...")));
+
+                  Navigator.of(context).push(CupertinoPageRoute(
+                      builder: (context) =>
+                          GoalPlannerScreen(subject: widget.subject)));
+                },
+              ),
+            ],
+          ),
+        ),
+        body: RefreshIndicator(
+          onRefresh: () async {},
+          color: Theme.of(context).colorScheme.secondary,
+          child: HeroScrollView(
+              onClose: () {
+                if (_sheetController != null && gradeCalcMode) {
+                  _sheetController!.close();
+                } else {
+                  Navigator.of(context).pop();
+                }
+              },
+              navBarItems: [
+                const SizedBox(width: 6.0),
+                if (widget.groupAverage != 0)
+                  Center(
+                      child: AverageDisplay(
+                          average: widget.groupAverage, border: true)),
+                const SizedBox(width: 6.0),
+                if (average != 0)
+                  Center(child: AverageDisplay(average: average)),
+                const SizedBox(width: 6.0),
+                if (plan != '')
+                  Center(
+                    child: GestureDetector(
+                      onTap: () {
+                        Navigator.of(context).push(CupertinoPageRoute(
+                            builder: (context) =>
+                                GoalStateScreen(subject: widget.subject)));
+                      },
+                      child: Container(
+                        width: 54.0,
+                        padding: const EdgeInsets.symmetric(vertical: 8.0),
+                        decoration: BoxDecoration(
+                          borderRadius: BorderRadius.circular(45.0),
+                          color: Theme.of(context)
+                              .colorScheme
+                              .primary
+                              .withOpacity(.15),
+                        ),
+                        child: Icon(
+                          FeatherIcons.flag,
+                          size: 17.0,
+                          weight: 2.5,
+                          color: Theme.of(context).colorScheme.primary,
+                        ),
+                      ),
+                    ),
+                  ),
+                const SizedBox(width: 12.0),
+              ],
+              icon: SubjectIcon.resolveVariant(
+                  subject: widget.subject, context: context),
+              scrollController: _scrollController,
+              title: widget.subject.renamedTo ?? widget.subject.name.capital(),
+              italic: settingsProvider.renamedSubjectsItalics &&
+                  widget.subject.isRenamed,
+              child: SubjectGradesContainer(
+                child: CupertinoScrollbar(
+                  child: ListView.builder(
+                    physics: const BouncingScrollPhysics(),
+                    padding: const EdgeInsets.symmetric(horizontal: 24.0),
+                    shrinkWrap: true,
+                    itemBuilder: (context, index) => gradeTiles[index],
+                    itemCount: gradeTiles.length,
+                  ),
+                ),
+              )),
+        ));
+  }
+
+  void gradeCalc(BuildContext context) {
+    // Scroll to the top of the page
+    _scrollController.animateTo(100,
+        duration: const Duration(milliseconds: 500), curve: Curves.ease);
+
+    calculatorProvider.clear();
+    calculatorProvider.addAllGrades(gradeProvider.grades);
+
+    _sheetController = _scaffoldKey.currentState?.showBottomSheet(
+      (context) => RoundedBottomSheet(
+          child: GradeCalculator(widget.subject), borderRadius: 14.0),
+      backgroundColor: const Color(0x00000000),
+      elevation: 12.0,
+    );
+
+    // Hide the fab and grades
+    setState(() {
+      gradeCalcMode = true;
+    });
+
+    _sheetController!.closed.then((value) {
+      // Show fab and grades
+      if (mounted) {
+        setState(() {
+          gradeCalcMode = false;
+        });
+      }
+    });
+  }
+}
diff --git a/refilc_mobile_ui/lib/pages/grades/grades_count.dart b/refilc_mobile_ui/lib/pages/grades/grades_count.dart
new file mode 100644
index 0000000..ceac962
--- /dev/null
+++ b/refilc_mobile_ui/lib/pages/grades/grades_count.dart
@@ -0,0 +1,28 @@
+import 'package:flutter/material.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_mobile_ui/pages/grades/grades_count_item.dart';
+import 'package:collection/collection.dart';
+
+class GradesCount extends StatelessWidget {
+  const GradesCount({Key? key, required this.grades}) : super(key: key);
+
+  final List<Grade> grades;
+
+  @override
+  Widget build(BuildContext context) {
+    List<int> gradesCount = List.generate(5,
+        (int index) => grades.where((e) => e.value.value == index + 1).length);
+
+    return Padding(
+      padding:
+          const EdgeInsets.only(bottom: 6.0, top: 6.0, left: 12.0, right: 6.0),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.spaceAround,
+        children: gradesCount
+            .mapIndexed(
+                (index, e) => GradesCountItem(count: e, value: index + 1))
+            .toList(),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/grades_count_item.dart b/refilc_mobile_ui/lib/pages/grades/grades_count_item.dart
old mode 100755
new mode 100644
similarity index 77%
rename from filcnaplo_mobile_ui/lib/pages/grades/grades_count_item.dart
rename to refilc_mobile_ui/lib/pages/grades/grades_count_item.dart
index 9713e95..e7b5a7c
--- a/filcnaplo_mobile_ui/lib/pages/grades/grades_count_item.dart
+++ b/refilc_mobile_ui/lib/pages/grades/grades_count_item.dart
@@ -1,33 +1,35 @@
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:flutter/material.dart';
-
-class GradesCountItem extends StatelessWidget {
-  const GradesCountItem({Key? key, required this.count, required this.value}) : super(key: key);
-
-  final int count;
-  final int value;
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      children: [
-        Text.rich(
-          TextSpan(children: [
-            TextSpan(
-              text: count.toString(),
-              style: const TextStyle(fontWeight: FontWeight.w600),
-            ),
-            const TextSpan(
-              text: "x",
-              style: TextStyle(fontSize: 13.0),
-            ),
-          ]),
-          style: const TextStyle(fontSize: 15.0),
-        ),
-        const SizedBox(width: 5.0),
-        GradeValueWidget(GradeValue(value, "Value", "Value", 100), size: 19.0, fill: true, shadow: false),
-      ],
-    );
-  }
-}
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:flutter/material.dart';
+
+class GradesCountItem extends StatelessWidget {
+  const GradesCountItem({Key? key, required this.count, required this.value})
+      : super(key: key);
+
+  final int count;
+  final int value;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      children: [
+        Text.rich(
+          TextSpan(children: [
+            TextSpan(
+              text: count.toString(),
+              style: const TextStyle(fontWeight: FontWeight.w600),
+            ),
+            const TextSpan(
+              text: "x",
+              style: TextStyle(fontSize: 13.0),
+            ),
+          ]),
+          style: const TextStyle(fontSize: 15.0),
+        ),
+        const SizedBox(width: 5.0),
+        GradeValueWidget(GradeValue(value, "Value", "Value", 100),
+            size: 19.0, fill: true, shadow: false),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/grades_page.dart b/refilc_mobile_ui/lib/pages/grades/grades_page.dart
old mode 100755
new mode 100644
similarity index 84%
rename from filcnaplo_mobile_ui/lib/pages/grades/grades_page.dart
rename to refilc_mobile_ui/lib/pages/grades/grades_page.dart
index 8f0f6ca..81482b6
--- a/filcnaplo_mobile_ui/lib/pages/grades/grades_page.dart
+++ b/refilc_mobile_ui/lib/pages/grades/grades_page.dart
@@ -1,357 +1,357 @@
-import 'dart:math';
-
-import 'package:auto_size_text/auto_size_text.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-// import 'package:filcnaplo_kreta_api/client/api.dart';
-// import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/group_average.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/statistics_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_subject_tile.dart';
-import 'package:filcnaplo_mobile_ui/common/trend_display.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/fail_warning.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/grades_count.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/grade_subject_view.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo_premium/ui/mobile/grades/average_selector.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/premium_inline.dart';
-import 'grades_page.i18n.dart';
-
-class GradesPage extends StatefulWidget {
-  const GradesPage({Key? key}) : super(key: key);
-
-  @override
-  _GradesPageState createState() => _GradesPageState();
-}
-
-class _GradesPageState extends State<GradesPage> {
-  late UserProvider user;
-  late GradeProvider gradeProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late Widget yearlyGraph;
-  late Widget gradesCount;
-  List<Widget> subjectTiles = [];
-
-  int avgDropValue = 0;
-
-  List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
-      .grades
-      .where((e) =>
-          e.subject == subject &&
-          e.type == GradeType.midYear &&
-          (days == 0 ||
-              e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
-      .toList();
-
-  void generateTiles() {
-    List<Subject> subjects = gradeProvider.grades
-        .map((e) => e.subject)
-        .toSet()
-        .toList()
-      ..sort((a, b) => a.name.compareTo(b.name));
-    List<Widget> tiles = [];
-
-    Map<Subject, double> subjectAvgs = {};
-
-    tiles.addAll(subjects.map((subject) {
-      List<Grade> subjectGrades = getSubjectGrades(subject);
-
-      double avg = AverageHelper.averageEvals(subjectGrades);
-      double averageBefore = 0.0;
-
-      if (avgDropValue != 0) {
-        List<Grade> gradesBefore =
-            getSubjectGrades(subject, days: avgDropValue);
-        averageBefore =
-            avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore);
-      }
-      var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0");
-      double groupAverage = gradeProvider.groupAverages
-          .firstWhere((e) => e.subject == subject, orElse: () => nullavg)
-          .average;
-
-      if (avg != 0) subjectAvgs[subject] = avg;
-
-      return GradeSubjectTile(
-        subject,
-        averageBefore: averageBefore,
-        average: avg,
-        groupAverage: avgDropValue == 0 ? groupAverage : 0.0,
-        onTap: () {
-          GradeSubjectView(subject, groupAverage: groupAverage)
-              .push(context, root: true);
-        },
-      );
-    }));
-
-    if (tiles.isNotEmpty) {
-      tiles.insert(0, yearlyGraph);
-      tiles.insert(1, gradesCount);
-      tiles.insert(2, FailWarning(subjectAvgs: subjectAvgs));
-      tiles.insert(
-          3,
-          PanelTitle(
-              title: Text(avgDropValue == 0
-                  ? "Subjects".i18n
-                  : "Subjects_changes".i18n)));
-      tiles.insert(4, const PanelHeader(padding: EdgeInsets.only(top: 12.0)));
-      tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0)));
-      tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0)));
-    } else {
-      tiles.insert(
-        0,
-        // TextButton(
-        //     onPressed: () async {
-        //       var url = KretaAPI.averages(
-        //         user.instituteCode!,
-        //         user.id!,
-        //       );
-        //       print(url);
-        //       var res = await Provider.of<KretaClient>(context, listen: false)
-        //           .getAPI(url);
-        //       print(res);
-        //     },
-        //     child: Text('test')),
-        Padding(
-          padding: const EdgeInsets.only(top: 24.0),
-          child: Empty(subtitle: "empty".i18n),
-        ),
-      );
-    }
-
-    double subjectAvg = subjectAvgs.isNotEmpty
-        ? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
-            subjectAvgs.length
-        : 0.0;
-    final double classAvg = gradeProvider.groupAverages.isNotEmpty
-        ? gradeProvider.groupAverages
-                .map((e) => e.average)
-                .fold(0.0, (double a, double b) => a + b) /
-            gradeProvider.groupAverages.length
-        : 0.0;
-
-    if (subjectAvg > 0) {
-      tiles.add(Row(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Expanded(
-            child: StatisticsTile(
-              fill: true,
-              title: AutoSizeText(
-                "subjectavg".i18n,
-                textAlign: TextAlign.center,
-                maxLines: 2,
-                overflow: TextOverflow.ellipsis,
-              ),
-              value: subjectAvg,
-            ),
-          ),
-          const SizedBox(width: 24.0),
-          Expanded(
-            child: StatisticsTile(
-              outline: true,
-              title: AutoSizeText(
-                "classavg".i18n,
-                textAlign: TextAlign.center,
-                maxLines: 2,
-                wrapWords: false,
-                overflow: TextOverflow.ellipsis,
-              ),
-              value: classAvg,
-            ),
-          ),
-        ],
-      ));
-    }
-
-    tiles.add(Provider.of<PremiumProvider>(context, listen: false).hasPremium
-        ? const SizedBox()
-        : const Padding(
-            padding: EdgeInsets.only(top: 24.0),
-            child: PremiumInline(features: [
-              PremiumInlineFeature.goal,
-              PremiumInlineFeature.stats,
-            ]),
-          ));
-
-    // padding
-    tiles.add(const SizedBox(height: 32.0));
-
-    subjectTiles = List.castFrom(tiles);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    gradeProvider = Provider.of<GradeProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-    context.watch<PremiumProvider>();
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    final double totalClassAvg = gradeProvider.groupAverages.isEmpty
-        ? 0.0
-        : gradeProvider.groupAverages
-                .map((e) => e.average)
-                .fold(0.0, (double a, double b) => a + b) /
-            gradeProvider.groupAverages.length;
-
-    final now = gradeProvider.grades.isNotEmpty
-        ? gradeProvider.grades
-            .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
-            .date
-        : DateTime.now();
-
-    final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
-        .where((e) => e.type == GradeType.midYear)
-        .toList());
-    final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
-        .where((e) => e.type == GradeType.midYear)
-        .where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
-        .toList());
-
-    List<Grade> graphGrades = gradeProvider.grades
-        .where((e) =>
-            e.type == GradeType.midYear &&
-            (avgDropValue == 0 ||
-                e.date.isAfter(
-                    DateTime.now().subtract(Duration(days: avgDropValue)))))
-        .toList();
-
-    yearlyGraph = Padding(
-      padding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
-      child: Panel(
-        title: Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: [
-            PremiumAverageSelector(
-              value: avgDropValue,
-              onChanged: (value) {
-                setState(() {
-                  avgDropValue = value!;
-                });
-              },
-            ),
-            Row(
-              children: [
-                // if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true),
-                // const SizedBox(width: 4.0),
-                TrendDisplay(
-                    previous: prevStudentAvg, current: currentStudentAvg),
-                if (gradeProvider.grades
-                    .where((e) => e.type == GradeType.midYear)
-                    .isNotEmpty)
-                  AverageDisplay(average: currentStudentAvg),
-              ],
-            )
-          ],
-        ),
-        child: Container(
-          padding: const EdgeInsets.only(top: 12.0, right: 12.0),
-          child:
-              GradeGraph(graphGrades, dayThreshold: 2, classAvg: totalClassAvg),
-        ),
-      ),
-    );
-
-    gradesCount = Padding(
-      padding: const EdgeInsets.only(bottom: 24.0),
-      child: Panel(child: GradesCount(grades: graphGrades)),
-    );
-
-    generateTiles();
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 9.0),
-        child: NestedScrollView(
-          physics: const BouncingScrollPhysics(
-              parent: AlwaysScrollableScrollPhysics()),
-          headerSliverBuilder: (context, _) => [
-            SliverAppBar(
-              centerTitle: false,
-              pinned: true,
-              floating: false,
-              snap: false,
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-              actions: [
-                // Profile Icon
-                Padding(
-                  padding: const EdgeInsets.only(right: 24.0),
-                  child: ProfileButton(
-                    child: ProfileImage(
-                      heroTag: "profile",
-                      name: firstName,
-                      backgroundColor: Theme.of(context)
-                          .colorScheme
-                          .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
-                      badge: updateProvider.available,
-                      role: user.role,
-                      profilePictureString: user.picture,
-                    ),
-                  ),
-                ),
-              ],
-              automaticallyImplyLeading: false,
-              title: Padding(
-                padding: const EdgeInsets.only(left: 8.0),
-                child: Text(
-                  "Grades".i18n,
-                  style: TextStyle(
-                      color: AppColors.of(context).text,
-                      fontSize: 32.0,
-                      fontWeight: FontWeight.bold),
-                ),
-              ),
-              shadowColor: Theme.of(context).shadowColor,
-            ),
-          ],
-          body: RefreshIndicator(
-            onRefresh: () => gradeProvider.fetch(),
-            color: Theme.of(context).colorScheme.secondary,
-            child: ListView.builder(
-              padding: EdgeInsets.zero,
-              physics: const BouncingScrollPhysics(),
-              itemCount: max(subjectTiles.length, 1),
-              itemBuilder: (context, index) {
-                if (subjectTiles.isNotEmpty) {
-                  EdgeInsetsGeometry panelPadding =
-                      const EdgeInsets.symmetric(horizontal: 24.0);
-
-                  if (subjectTiles[index].runtimeType == GradeSubjectTile) {
-                    return Padding(
-                        padding: panelPadding,
-                        child: PanelBody(
-                          child: subjectTiles[index],
-                          padding: const EdgeInsets.symmetric(horizontal: 8.0),
-                        ));
-                  } else {
-                    return Padding(
-                        padding: panelPadding, child: subjectTiles[index]);
-                  }
-                } else {
-                  return Container();
-                }
-              },
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:auto_size_text/auto_size_text.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+// import 'package:refilc_kreta_api/client/api.dart';
+// import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/group_average.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/common/widgets/statistics_tile.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/grade_subject_tile.dart';
+import 'package:refilc_mobile_ui/common/trend_display.dart';
+import 'package:refilc_mobile_ui/pages/grades/fail_warning.dart';
+import 'package:refilc_mobile_ui/pages/grades/grades_count.dart';
+import 'package:refilc_mobile_ui/pages/grades/graph.dart';
+import 'package:refilc_mobile_ui/pages/grades/grade_subject_view.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc_premium/ui/mobile/grades/average_selector.dart';
+import 'package:refilc_premium/ui/mobile/premium/premium_inline.dart';
+import 'grades_page.i18n.dart';
+
+class GradesPage extends StatefulWidget {
+  const GradesPage({Key? key}) : super(key: key);
+
+  @override
+  _GradesPageState createState() => _GradesPageState();
+}
+
+class _GradesPageState extends State<GradesPage> {
+  late UserProvider user;
+  late GradeProvider gradeProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late Widget yearlyGraph;
+  late Widget gradesCount;
+  List<Widget> subjectTiles = [];
+
+  int avgDropValue = 0;
+
+  List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
+      .grades
+      .where((e) =>
+          e.subject == subject &&
+          e.type == GradeType.midYear &&
+          (days == 0 ||
+              e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
+      .toList();
+
+  void generateTiles() {
+    List<Subject> subjects = gradeProvider.grades
+        .map((e) => e.subject)
+        .toSet()
+        .toList()
+      ..sort((a, b) => a.name.compareTo(b.name));
+    List<Widget> tiles = [];
+
+    Map<Subject, double> subjectAvgs = {};
+
+    tiles.addAll(subjects.map((subject) {
+      List<Grade> subjectGrades = getSubjectGrades(subject);
+
+      double avg = AverageHelper.averageEvals(subjectGrades);
+      double averageBefore = 0.0;
+
+      if (avgDropValue != 0) {
+        List<Grade> gradesBefore =
+            getSubjectGrades(subject, days: avgDropValue);
+        averageBefore =
+            avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore);
+      }
+      var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0");
+      double groupAverage = gradeProvider.groupAverages
+          .firstWhere((e) => e.subject == subject, orElse: () => nullavg)
+          .average;
+
+      if (avg != 0) subjectAvgs[subject] = avg;
+
+      return GradeSubjectTile(
+        subject,
+        averageBefore: averageBefore,
+        average: avg,
+        groupAverage: avgDropValue == 0 ? groupAverage : 0.0,
+        onTap: () {
+          GradeSubjectView(subject, groupAverage: groupAverage)
+              .push(context, root: true);
+        },
+      );
+    }));
+
+    if (tiles.isNotEmpty) {
+      tiles.insert(0, yearlyGraph);
+      tiles.insert(1, gradesCount);
+      tiles.insert(2, FailWarning(subjectAvgs: subjectAvgs));
+      tiles.insert(
+          3,
+          PanelTitle(
+              title: Text(avgDropValue == 0
+                  ? "Subjects".i18n
+                  : "Subjects_changes".i18n)));
+      tiles.insert(4, const PanelHeader(padding: EdgeInsets.only(top: 12.0)));
+      tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0)));
+      tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0)));
+    } else {
+      tiles.insert(
+        0,
+        // TextButton(
+        //     onPressed: () async {
+        //       var url = KretaAPI.averages(
+        //         user.instituteCode!,
+        //         user.id!,
+        //       );
+        //       print(url);
+        //       var res = await Provider.of<KretaClient>(context, listen: false)
+        //           .getAPI(url);
+        //       print(res);
+        //     },
+        //     child: Text('test')),
+        Padding(
+          padding: const EdgeInsets.only(top: 24.0),
+          child: Empty(subtitle: "empty".i18n),
+        ),
+      );
+    }
+
+    double subjectAvg = subjectAvgs.isNotEmpty
+        ? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
+            subjectAvgs.length
+        : 0.0;
+    final double classAvg = gradeProvider.groupAverages.isNotEmpty
+        ? gradeProvider.groupAverages
+                .map((e) => e.average)
+                .fold(0.0, (double a, double b) => a + b) /
+            gradeProvider.groupAverages.length
+        : 0.0;
+
+    if (subjectAvg > 0) {
+      tiles.add(Row(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Expanded(
+            child: StatisticsTile(
+              fill: true,
+              title: AutoSizeText(
+                "subjectavg".i18n,
+                textAlign: TextAlign.center,
+                maxLines: 2,
+                overflow: TextOverflow.ellipsis,
+              ),
+              value: subjectAvg,
+            ),
+          ),
+          const SizedBox(width: 24.0),
+          Expanded(
+            child: StatisticsTile(
+              outline: true,
+              title: AutoSizeText(
+                "classavg".i18n,
+                textAlign: TextAlign.center,
+                maxLines: 2,
+                wrapWords: false,
+                overflow: TextOverflow.ellipsis,
+              ),
+              value: classAvg,
+            ),
+          ),
+        ],
+      ));
+    }
+
+    tiles.add(Provider.of<PremiumProvider>(context, listen: false).hasPremium
+        ? const SizedBox()
+        : const Padding(
+            padding: EdgeInsets.only(top: 24.0),
+            child: PremiumInline(features: [
+              PremiumInlineFeature.goal,
+              PremiumInlineFeature.stats,
+            ]),
+          ));
+
+    // padding
+    tiles.add(const SizedBox(height: 32.0));
+
+    subjectTiles = List.castFrom(tiles);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    gradeProvider = Provider.of<GradeProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+    context.watch<PremiumProvider>();
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    final double totalClassAvg = gradeProvider.groupAverages.isEmpty
+        ? 0.0
+        : gradeProvider.groupAverages
+                .map((e) => e.average)
+                .fold(0.0, (double a, double b) => a + b) /
+            gradeProvider.groupAverages.length;
+
+    final now = gradeProvider.grades.isNotEmpty
+        ? gradeProvider.grades
+            .reduce((v, e) => e.date.isAfter(v.date) ? e : v)
+            .date
+        : DateTime.now();
+
+    final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
+        .where((e) => e.type == GradeType.midYear)
+        .toList());
+    final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
+        .where((e) => e.type == GradeType.midYear)
+        .where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
+        .toList());
+
+    List<Grade> graphGrades = gradeProvider.grades
+        .where((e) =>
+            e.type == GradeType.midYear &&
+            (avgDropValue == 0 ||
+                e.date.isAfter(
+                    DateTime.now().subtract(Duration(days: avgDropValue)))))
+        .toList();
+
+    yearlyGraph = Padding(
+      padding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
+      child: Panel(
+        title: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            PremiumAverageSelector(
+              value: avgDropValue,
+              onChanged: (value) {
+                setState(() {
+                  avgDropValue = value!;
+                });
+              },
+            ),
+            Row(
+              children: [
+                // if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true),
+                // const SizedBox(width: 4.0),
+                TrendDisplay(
+                    previous: prevStudentAvg, current: currentStudentAvg),
+                if (gradeProvider.grades
+                    .where((e) => e.type == GradeType.midYear)
+                    .isNotEmpty)
+                  AverageDisplay(average: currentStudentAvg),
+              ],
+            )
+          ],
+        ),
+        child: Container(
+          padding: const EdgeInsets.only(top: 12.0, right: 12.0),
+          child:
+              GradeGraph(graphGrades, dayThreshold: 2, classAvg: totalClassAvg),
+        ),
+      ),
+    );
+
+    gradesCount = Padding(
+      padding: const EdgeInsets.only(bottom: 24.0),
+      child: Panel(child: GradesCount(grades: graphGrades)),
+    );
+
+    generateTiles();
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 9.0),
+        child: NestedScrollView(
+          physics: const BouncingScrollPhysics(
+              parent: AlwaysScrollableScrollPhysics()),
+          headerSliverBuilder: (context, _) => [
+            SliverAppBar(
+              centerTitle: false,
+              pinned: true,
+              floating: false,
+              snap: false,
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+              actions: [
+                // Profile Icon
+                Padding(
+                  padding: const EdgeInsets.only(right: 24.0),
+                  child: ProfileButton(
+                    child: ProfileImage(
+                      heroTag: "profile",
+                      name: firstName,
+                      backgroundColor: Theme.of(context)
+                          .colorScheme
+                          .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
+                      badge: updateProvider.available,
+                      role: user.role,
+                      profilePictureString: user.picture,
+                    ),
+                  ),
+                ),
+              ],
+              automaticallyImplyLeading: false,
+              title: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  "Grades".i18n,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontSize: 32.0,
+                      fontWeight: FontWeight.bold),
+                ),
+              ),
+              shadowColor: Theme.of(context).shadowColor,
+            ),
+          ],
+          body: RefreshIndicator(
+            onRefresh: () => gradeProvider.fetch(),
+            color: Theme.of(context).colorScheme.secondary,
+            child: ListView.builder(
+              padding: EdgeInsets.zero,
+              physics: const BouncingScrollPhysics(),
+              itemCount: max(subjectTiles.length, 1),
+              itemBuilder: (context, index) {
+                if (subjectTiles.isNotEmpty) {
+                  EdgeInsetsGeometry panelPadding =
+                      const EdgeInsets.symmetric(horizontal: 24.0);
+
+                  if (subjectTiles[index].runtimeType == GradeSubjectTile) {
+                    return Padding(
+                        padding: panelPadding,
+                        child: PanelBody(
+                          child: subjectTiles[index],
+                          padding: const EdgeInsets.symmetric(horizontal: 8.0),
+                        ));
+                  } else {
+                    return Padding(
+                        padding: panelPadding, child: subjectTiles[index]);
+                  }
+                } else {
+                  return Container();
+                }
+              },
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/pages/grades/grades_page.i18n.dart b/refilc_mobile_ui/lib/pages/grades/grades_page.i18n.dart
similarity index 97%
rename from filcnaplo_desktop_ui/lib/pages/grades/grades_page.i18n.dart
rename to refilc_mobile_ui/lib/pages/grades/grades_page.i18n.dart
index 11d7fbb..41d0d03 100644
--- a/filcnaplo_desktop_ui/lib/pages/grades/grades_page.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/grades/grades_page.i18n.dart
@@ -1,60 +1,60 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Grades": "Grades",
-          "Ghost Grades": "Grades",
-          "Subjects": "Subjects",
-          "Subjects_changes": "Subject Differences",
-          "empty": "You don't have any subjects.",
-          "annual_average": "Annual average",
-          "3_months_average": "3 Monthly Average",
-          "30_days_average": "Monthly Average",
-          "14_days_average": "2 Weekly Average",
-          "7_days_average": "Weekly Average",
-          "subjectavg": "Subject Average",
-          "classavg": "Class Average",
-          "fail_warning": "Faliure warning",
-          "fail_warning_description": "You are failing %d subject(s)",
-        },
-        "hu_hu": {
-          "Grades": "Jegyek",
-          "Ghost Grades": "Szellem jegyek",
-          "Subjects": "Tantárgyak",
-          "Subjects_changes": "Tantárgyi változások",
-          "empty": "Még nincs egy tárgyad sem.",
-          "annual_average": "Éves átlag",
-          "3_months_average": "Háromhavi átlag",
-          "30_days_average": "Havi átlag",
-          "14_days_average": "Kétheti átlag",
-          "7_days_average": "Heti átlag",
-          "subjectavg": "Tantárgyi átlag",
-          "classavg": "Osztályátlag",
-          "fail_warning": "Bukás figyelmeztető",
-          "fail_warning_description": "Bukásra állsz %d tantárgyból",
-        },
-        "de_de": {
-          "Grades": "Noten",
-          "Ghost Grades": "Geist Noten",
-          "Subjects": "Fächer",
-          "Subjects_changes": "Betreff Änderungen",
-          "empty": "Sie haben keine Fächer.",
-          "annual_average": "Jahresdurchschnitt",
-          "3_months_average": "Drei-Monats-Durchschnitt",
-          "30_days_average": "Monatsdurchschnitt",
-          "14_days_average": "Vierzehntägiger Durchschnitt",
-          "7_days_average": "Wöchentlicher Durchschnitt",
-          "subjectavg": "Fächer Durchschnitt",
-          "classavg": "Klassendurchschnitt",
-          "fail_warning": "Ausfallwarnung",
-          "fail_warning_description": "Sie werden in %d des Fachs durchfallen",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Grades": "Grades",
+          "Ghost Grades": "Grades",
+          "Subjects": "Subjects",
+          "Subjects_changes": "Subject Differences",
+          "empty": "You don't have any subjects.",
+          "annual_average": "Annual average",
+          "3_months_average": "3 Monthly Average",
+          "30_days_average": "Monthly Average",
+          "14_days_average": "2 Weekly Average",
+          "7_days_average": "Weekly Average",
+          "subjectavg": "Subject Average",
+          "classavg": "Class Average",
+          "fail_warning": "Faliure warning",
+          "fail_warning_description": "You are failing %d subject(s)",
+        },
+        "hu_hu": {
+          "Grades": "Jegyek",
+          "Ghost Grades": "Szellem jegyek",
+          "Subjects": "Tantárgyak",
+          "Subjects_changes": "Tantárgyi változások",
+          "empty": "Még nincs egy tárgyad sem.",
+          "annual_average": "Éves átlag",
+          "3_months_average": "Háromhavi átlag",
+          "30_days_average": "Havi átlag",
+          "14_days_average": "Kétheti átlag",
+          "7_days_average": "Heti átlag",
+          "subjectavg": "Tantárgyi átlag",
+          "classavg": "Osztályátlag",
+          "fail_warning": "Bukás figyelmeztető",
+          "fail_warning_description": "Bukásra állsz %d tantárgyból",
+        },
+        "de_de": {
+          "Grades": "Noten",
+          "Ghost Grades": "Geist Noten",
+          "Subjects": "Fächer",
+          "Subjects_changes": "Betreff Änderungen",
+          "empty": "Sie haben keine Fächer.",
+          "annual_average": "Jahresdurchschnitt",
+          "3_months_average": "Drei-Monats-Durchschnitt",
+          "30_days_average": "Monatsdurchschnitt",
+          "14_days_average": "Vierzehntägiger Durchschnitt",
+          "7_days_average": "Wöchentlicher Durchschnitt",
+          "subjectavg": "Fächer Durchschnitt",
+          "classavg": "Klassendurchschnitt",
+          "fail_warning": "Ausfallwarnung",
+          "fail_warning_description": "Sie werden in %d des Fachs durchfallen",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/graph.dart b/refilc_mobile_ui/lib/pages/grades/graph.dart
old mode 100755
new mode 100644
similarity index 74%
rename from filcnaplo_mobile_ui/lib/pages/grades/graph.dart
rename to refilc_mobile_ui/lib/pages/grades/graph.dart
index 5e0baa9..772c4ee
--- a/filcnaplo_mobile_ui/lib/pages/grades/graph.dart
+++ b/refilc_mobile_ui/lib/pages/grades/graph.dart
@@ -1,296 +1,340 @@
-import 'dart:math';
-
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:flutter/material.dart';
-import 'package:fl_chart/fl_chart.dart';
-import 'package:intl/intl.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:provider/provider.dart';
-import 'graph.i18n.dart';
-
-class GradeGraph extends StatefulWidget {
-  const GradeGraph(this.data, {Key? key, this.dayThreshold = 7, this.classAvg}) : super(key: key);
-
-  final List<Grade> data;
-  final int dayThreshold;
-  final double? classAvg;
-
-  @override
-  _GradeGraphState createState() => _GradeGraphState();
-}
-
-class _GradeGraphState extends State<GradeGraph> {
-  late SettingsProvider settings;
-
-  List<FlSpot> getSpots(List<Grade> data) {
-    List<FlSpot> subjectData = [];
-    List<List<Grade>> sortedData = [[]];
-
-    // Sort by date descending
-    data.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
-
-    // Sort data to points by treshold
-    for (var element in data) {
-      if (sortedData.last.isNotEmpty && sortedData.last.last.writeDate.difference(element.writeDate).inDays > widget.dayThreshold) {
-        sortedData.add([]);
-      }
-      for (var dataList in sortedData) {
-        dataList.add(element);
-      }
-    }
-
-    // Create FlSpots from points
-    for (var dataList in sortedData) {
-      double average = AverageHelper.averageEvals(dataList);
-
-      if (dataList.isNotEmpty) {
-        subjectData.add(FlSpot(
-          dataList[0].writeDate.month + (dataList[0].writeDate.day / 31) + ((dataList[0].writeDate.year - data.last.writeDate.year) * 12),
-          double.parse(average.toStringAsFixed(2)),
-        ));
-      }
-    }
-
-    return subjectData;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    settings = Provider.of<SettingsProvider>(context);
-
-    List<FlSpot> subjectSpots = [];
-    List<FlSpot> ghostSpots = [];
-    List<VerticalLine> extraLinesV = [];
-    List<HorizontalLine> extraLinesH = [];
-
-    // Filter data
-    List<Grade> data = widget.data
-        .where((e) => e.value.weight != 0)
-        .where((e) => e.type == GradeType.midYear)
-        .where((e) => e.gradeType?.name == "Osztalyzat")
-        .toList();
-
-    // Filter ghost data
-    List<Grade> ghostData = widget.data.where((e) => e.value.weight != 0).where((e) => e.type == GradeType.ghost).toList();
-
-    // Calculate average
-    double average = AverageHelper.averageEvals(data);
-
-    // Calculate graph color
-    Color averageColor = average >= 1 && average <= 5
-        ? ColorTween(begin: settings.gradeColors[average.floor() - 1], end: settings.gradeColors[average.ceil() - 1])
-            .transform(average - average.floor())!
-        : Theme.of(context).colorScheme.secondary;
-
-    subjectSpots = getSpots(data);
-
-    // naplo/#73
-    if (subjectSpots.isNotEmpty) {
-      ghostSpots = getSpots(data + ghostData);
-
-      // hax
-      ghostSpots = ghostSpots.where((e) => e.x >= subjectSpots.map((f) => f.x).reduce(max)).toList();
-      ghostSpots = ghostSpots.map((e) => FlSpot(e.x + 0.1, e.y)).toList();
-      ghostSpots.add(subjectSpots.firstWhere((e) => e.x >= subjectSpots.map((f) => f.x).reduce(max), orElse: () => const FlSpot(-1, -1)));
-      ghostSpots.removeWhere((element) => element.x == -1 && element.y == -1); // naplo/#74
-    }
-
-    Grade halfYearGrade = widget.data.lastWhere((e) => e.type == GradeType.halfYear, orElse: () => Grade.fromJson({}));
-
-    if (halfYearGrade.date.year != 0 && data.isNotEmpty) {
-      final maxX = ghostSpots.isNotEmpty ? ghostSpots.first.x : 0;
-      final x = halfYearGrade.writeDate.month + (halfYearGrade.writeDate.day / 31) + ((halfYearGrade.writeDate.year - data.last.writeDate.year) * 12);
-      if (x <= maxX) {
-        extraLinesV.add(
-          VerticalLine(
-            x: x,
-            strokeWidth: 3.0,
-            color: AppColors.of(context).red.withOpacity(.75),
-            label: VerticalLineLabel(
-              labelResolver: (_) => " " + "mid".i18n + " ​", // <- zwsp for padding
-              show: true,
-              alignment: Alignment.topLeft,
-              style: TextStyle(
-                backgroundColor: Theme.of(context).colorScheme.background,
-                color: AppColors.of(context).text,
-                fontSize: 16.0,
-                fontWeight: FontWeight.w600,
-              ),
-            ),
-          ),
-        );
-      }
-    }
-
-    // Horizontal line displaying the class average
-    if (widget.classAvg != null && widget.classAvg! > 0.0 && settings.graphClassAvg) {
-      extraLinesH.add(HorizontalLine(
-        y: widget.classAvg!,
-        color: AppColors.of(context).text.withOpacity(.75),
-      ));
-    }
-
-    // LineChart is really cute because it tries to render it's contents outside of it's rect.
-    return widget.data.length <= 2
-        ? SizedBox(
-            height: 150,
-            child: Center(
-              child: Text(
-                "not_enough_grades".i18n,
-                textAlign: TextAlign.center,
-                style: const TextStyle(fontWeight: FontWeight.bold),
-              ),
-            ),
-          )
-        : ClipRect(
-            child: SizedBox(
-              child: subjectSpots.length > 1
-                  ? Padding(
-                      padding: const EdgeInsets.only(top: 8.0, right: 8.0),
-                      child: LineChart(
-                        LineChartData(
-                          extraLinesData: ExtraLinesData(verticalLines: extraLinesV, horizontalLines: extraLinesH),
-                          lineBarsData: [
-                            LineChartBarData(
-                              preventCurveOverShooting: true,
-                              spots: subjectSpots,
-                              isCurved: true,
-                              colors: [averageColor],
-                              barWidth: 8,
-                              isStrokeCapRound: true,
-                              dotData: FlDotData(show: false),
-                              belowBarData: BarAreaData(
-                                show: true,
-                                colors: [
-                                  averageColor.withOpacity(0.7),
-                                  averageColor.withOpacity(0.3),
-                                  averageColor.withOpacity(0.2),
-                                  averageColor.withOpacity(0.1),
-                                ],
-                                gradientColorStops: [0.1, 0.6, 0.8, 1],
-                                gradientFrom: const Offset(0, 0),
-                                gradientTo: const Offset(0, 1),
-                              ),
-                            ),
-                            if (ghostData.isNotEmpty && ghostSpots.isNotEmpty)
-                              LineChartBarData(
-                                preventCurveOverShooting: true,
-                                spots: ghostSpots,
-                                isCurved: true,
-                                colors: [AppColors.of(context).text],
-                                barWidth: 8,
-                                isStrokeCapRound: true,
-                                dotData: FlDotData(show: false),
-                                belowBarData: BarAreaData(
-                                  show: true,
-                                  colors: [
-                                    AppColors.of(context).text.withOpacity(0.7),
-                                    AppColors.of(context).text.withOpacity(0.3),
-                                    AppColors.of(context).text.withOpacity(0.2),
-                                    AppColors.of(context).text.withOpacity(0.1),
-                                  ],
-                                  gradientColorStops: [0.1, 0.6, 0.8, 1],
-                                  gradientFrom: const Offset(0, 0),
-                                  gradientTo: const Offset(0, 1),
-                                ),
-                              ),
-                          ],
-                          minY: 1,
-                          maxY: 5,
-                          gridData: FlGridData(
-                            show: true,
-                            horizontalInterval: 1,
-                            // checkToShowVerticalLine: (_) => false,
-                            // getDrawingHorizontalLine: (_) => FlLine(
-                            //   color: AppColors.of(context).text.withOpacity(.15),
-                            //   strokeWidth: 2,
-                            // ),
-                            // getDrawingVerticalLine: (_) => FlLine(
-                            //   color: AppColors.of(context).text.withOpacity(.25),
-                            //   strokeWidth: 2,
-                            // ),
-                          ),
-                          lineTouchData: LineTouchData(
-                            touchTooltipData: LineTouchTooltipData(
-                              tooltipBgColor: Colors.grey.shade800,
-                              fitInsideVertically: true,
-                              fitInsideHorizontally: true,
-                            ),
-                            handleBuiltInTouches: true,
-                            touchSpotThreshold: 20.0,
-                            getTouchedSpotIndicator: (_, spots) {
-                              return List.generate(
-                                spots.length,
-                                (index) => TouchedSpotIndicatorData(
-                                  FlLine(
-                                    color: Colors.grey.shade900,
-                                    strokeWidth: 3.5,
-                                  ),
-                                  FlDotData(
-                                    getDotPainter: (a, b, c, d) => FlDotCirclePainter(
-                                      strokeWidth: 0,
-                                      color: Colors.grey.shade900,
-                                      radius: 10.0,
-                                    ),
-                                  ),
-                                ),
-                              );
-                            },
-                          ),
-                          borderData: FlBorderData(
-                            show: false,
-                            border: Border.all(
-                              color: Theme.of(context).scaffoldBackgroundColor,
-                              width: 4,
-                            ),
-                          ),
-                          titlesData: FlTitlesData(
-                            bottomTitles: SideTitles(
-                              showTitles: true,
-                              reservedSize: 24,
-                              getTextStyles: (context, value) => TextStyle(
-                                color: AppColors.of(context).text.withOpacity(.75),
-                                fontWeight: FontWeight.bold,
-                                fontSize: 14.0,
-                              ),
-                              margin: 12.0,
-                              getTitles: (value) {
-                                var format = DateFormat("MMM", I18n.of(context).locale.toString());
-
-                                String title = format.format(DateTime(0, value.floor() % 12)).replaceAll(".", "");
-                                title = title.substring(0, min(title.length, 4));
-
-                                return title.toUpperCase();
-                              },
-                              interval: () {
-                                List<Grade> tData = ghostData.isNotEmpty ? ghostData : data;
-                                tData.sort((a, b) => a.writeDate.compareTo(b.writeDate));
-                                return tData.first.writeDate.add(const Duration(days: 120)).isBefore(tData.last.writeDate) ? 2.0 : 1.0;
-                              }(),
-                              checkToShowTitle: (double minValue, double maxValue, SideTitles sideTitles, double appliedInterval, double value) { if (value == maxValue || value == minValue) return false; return true; },
-                            ),
-                            leftTitles: SideTitles(
-                              showTitles: true,
-                              interval: 1.0,
-                              getTextStyles: (context, value) => TextStyle(
-                                color: AppColors.of(context).text,
-                                fontWeight: FontWeight.bold,
-                                fontSize: 18.0,
-                              ),
-                              margin: 16,
-                            ),
-                            rightTitles: SideTitles(showTitles: false),
-                            topTitles: SideTitles(showTitles: false),
-                          ),
-                        ),
-                      ),
-                    )
-                  : null,
-              height: 158,
-            ),
-          );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:flutter/material.dart';
+import 'package:fl_chart/fl_chart.dart';
+import 'package:intl/intl.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:provider/provider.dart';
+import 'graph.i18n.dart';
+
+class GradeGraph extends StatefulWidget {
+  const GradeGraph(this.data, {Key? key, this.dayThreshold = 7, this.classAvg})
+      : super(key: key);
+
+  final List<Grade> data;
+  final int dayThreshold;
+  final double? classAvg;
+
+  @override
+  _GradeGraphState createState() => _GradeGraphState();
+}
+
+class _GradeGraphState extends State<GradeGraph> {
+  late SettingsProvider settings;
+
+  List<FlSpot> getSpots(List<Grade> data) {
+    List<FlSpot> subjectData = [];
+    List<List<Grade>> sortedData = [[]];
+
+    // Sort by date descending
+    data.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
+
+    // Sort data to points by treshold
+    for (var element in data) {
+      if (sortedData.last.isNotEmpty &&
+          sortedData.last.last.writeDate.difference(element.writeDate).inDays >
+              widget.dayThreshold) {
+        sortedData.add([]);
+      }
+      for (var dataList in sortedData) {
+        dataList.add(element);
+      }
+    }
+
+    // Create FlSpots from points
+    for (var dataList in sortedData) {
+      double average = AverageHelper.averageEvals(dataList);
+
+      if (dataList.isNotEmpty) {
+        subjectData.add(FlSpot(
+          dataList[0].writeDate.month +
+              (dataList[0].writeDate.day / 31) +
+              ((dataList[0].writeDate.year - data.last.writeDate.year) * 12),
+          double.parse(average.toStringAsFixed(2)),
+        ));
+      }
+    }
+
+    return subjectData;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    settings = Provider.of<SettingsProvider>(context);
+
+    List<FlSpot> subjectSpots = [];
+    List<FlSpot> ghostSpots = [];
+    List<VerticalLine> extraLinesV = [];
+    List<HorizontalLine> extraLinesH = [];
+
+    // Filter data
+    List<Grade> data = widget.data
+        .where((e) => e.value.weight != 0)
+        .where((e) => e.type == GradeType.midYear)
+        .where((e) => e.gradeType?.name == "Osztalyzat")
+        .toList();
+
+    // Filter ghost data
+    List<Grade> ghostData = widget.data
+        .where((e) => e.value.weight != 0)
+        .where((e) => e.type == GradeType.ghost)
+        .toList();
+
+    // Calculate average
+    double average = AverageHelper.averageEvals(data);
+
+    // Calculate graph color
+    Color averageColor = average >= 1 && average <= 5
+        ? ColorTween(
+                begin: settings.gradeColors[average.floor() - 1],
+                end: settings.gradeColors[average.ceil() - 1])
+            .transform(average - average.floor())!
+        : Theme.of(context).colorScheme.secondary;
+
+    subjectSpots = getSpots(data);
+
+    // naplo/#73
+    if (subjectSpots.isNotEmpty) {
+      ghostSpots = getSpots(data + ghostData);
+
+      // hax
+      ghostSpots = ghostSpots
+          .where((e) => e.x >= subjectSpots.map((f) => f.x).reduce(max))
+          .toList();
+      ghostSpots = ghostSpots.map((e) => FlSpot(e.x + 0.1, e.y)).toList();
+      ghostSpots.add(subjectSpots.firstWhere(
+          (e) => e.x >= subjectSpots.map((f) => f.x).reduce(max),
+          orElse: () => const FlSpot(-1, -1)));
+      ghostSpots.removeWhere(
+          (element) => element.x == -1 && element.y == -1); // naplo/#74
+    }
+
+    Grade halfYearGrade = widget.data.lastWhere(
+        (e) => e.type == GradeType.halfYear,
+        orElse: () => Grade.fromJson({}));
+
+    if (halfYearGrade.date.year != 0 && data.isNotEmpty) {
+      final maxX = ghostSpots.isNotEmpty ? ghostSpots.first.x : 0;
+      final x = halfYearGrade.writeDate.month +
+          (halfYearGrade.writeDate.day / 31) +
+          ((halfYearGrade.writeDate.year - data.last.writeDate.year) * 12);
+      if (x <= maxX) {
+        extraLinesV.add(
+          VerticalLine(
+            x: x,
+            strokeWidth: 3.0,
+            color: AppColors.of(context).red.withOpacity(.75),
+            label: VerticalLineLabel(
+              labelResolver: (_) =>
+                  " " + "mid".i18n + " ​", // <- zwsp for padding
+              show: true,
+              alignment: Alignment.topLeft,
+              style: TextStyle(
+                backgroundColor: Theme.of(context).colorScheme.background,
+                color: AppColors.of(context).text,
+                fontSize: 16.0,
+                fontWeight: FontWeight.w600,
+              ),
+            ),
+          ),
+        );
+      }
+    }
+
+    // Horizontal line displaying the class average
+    if (widget.classAvg != null &&
+        widget.classAvg! > 0.0 &&
+        settings.graphClassAvg) {
+      extraLinesH.add(HorizontalLine(
+        y: widget.classAvg!,
+        color: AppColors.of(context).text.withOpacity(.75),
+      ));
+    }
+
+    // LineChart is really cute because it tries to render it's contents outside of it's rect.
+    return widget.data.length <= 2
+        ? SizedBox(
+            height: 150,
+            child: Center(
+              child: Text(
+                "not_enough_grades".i18n,
+                textAlign: TextAlign.center,
+                style: const TextStyle(fontWeight: FontWeight.bold),
+              ),
+            ),
+          )
+        : ClipRect(
+            child: SizedBox(
+              child: subjectSpots.length > 1
+                  ? Padding(
+                      padding: const EdgeInsets.only(top: 8.0, right: 8.0),
+                      child: LineChart(
+                        LineChartData(
+                          extraLinesData: ExtraLinesData(
+                              verticalLines: extraLinesV,
+                              horizontalLines: extraLinesH),
+                          lineBarsData: [
+                            LineChartBarData(
+                              preventCurveOverShooting: true,
+                              spots: subjectSpots,
+                              isCurved: true,
+                              colors: [averageColor],
+                              barWidth: 8,
+                              isStrokeCapRound: true,
+                              dotData: FlDotData(show: false),
+                              belowBarData: BarAreaData(
+                                show: true,
+                                colors: [
+                                  averageColor.withOpacity(0.7),
+                                  averageColor.withOpacity(0.3),
+                                  averageColor.withOpacity(0.2),
+                                  averageColor.withOpacity(0.1),
+                                ],
+                                gradientColorStops: [0.1, 0.6, 0.8, 1],
+                                gradientFrom: const Offset(0, 0),
+                                gradientTo: const Offset(0, 1),
+                              ),
+                            ),
+                            if (ghostData.isNotEmpty && ghostSpots.isNotEmpty)
+                              LineChartBarData(
+                                preventCurveOverShooting: true,
+                                spots: ghostSpots,
+                                isCurved: true,
+                                colors: [AppColors.of(context).text],
+                                barWidth: 8,
+                                isStrokeCapRound: true,
+                                dotData: FlDotData(show: false),
+                                belowBarData: BarAreaData(
+                                  show: true,
+                                  colors: [
+                                    AppColors.of(context).text.withOpacity(0.7),
+                                    AppColors.of(context).text.withOpacity(0.3),
+                                    AppColors.of(context).text.withOpacity(0.2),
+                                    AppColors.of(context).text.withOpacity(0.1),
+                                  ],
+                                  gradientColorStops: [0.1, 0.6, 0.8, 1],
+                                  gradientFrom: const Offset(0, 0),
+                                  gradientTo: const Offset(0, 1),
+                                ),
+                              ),
+                          ],
+                          minY: 1,
+                          maxY: 5,
+                          gridData: FlGridData(
+                            show: true,
+                            horizontalInterval: 1,
+                            // checkToShowVerticalLine: (_) => false,
+                            // getDrawingHorizontalLine: (_) => FlLine(
+                            //   color: AppColors.of(context).text.withOpacity(.15),
+                            //   strokeWidth: 2,
+                            // ),
+                            // getDrawingVerticalLine: (_) => FlLine(
+                            //   color: AppColors.of(context).text.withOpacity(.25),
+                            //   strokeWidth: 2,
+                            // ),
+                          ),
+                          lineTouchData: LineTouchData(
+                            touchTooltipData: LineTouchTooltipData(
+                              tooltipBgColor: Colors.grey.shade800,
+                              fitInsideVertically: true,
+                              fitInsideHorizontally: true,
+                            ),
+                            handleBuiltInTouches: true,
+                            touchSpotThreshold: 20.0,
+                            getTouchedSpotIndicator: (_, spots) {
+                              return List.generate(
+                                spots.length,
+                                (index) => TouchedSpotIndicatorData(
+                                  FlLine(
+                                    color: Colors.grey.shade900,
+                                    strokeWidth: 3.5,
+                                  ),
+                                  FlDotData(
+                                    getDotPainter: (a, b, c, d) =>
+                                        FlDotCirclePainter(
+                                      strokeWidth: 0,
+                                      color: Colors.grey.shade900,
+                                      radius: 10.0,
+                                    ),
+                                  ),
+                                ),
+                              );
+                            },
+                          ),
+                          borderData: FlBorderData(
+                            show: false,
+                            border: Border.all(
+                              color: Theme.of(context).scaffoldBackgroundColor,
+                              width: 4,
+                            ),
+                          ),
+                          titlesData: FlTitlesData(
+                            bottomTitles: SideTitles(
+                              showTitles: true,
+                              reservedSize: 24,
+                              getTextStyles: (context, value) => TextStyle(
+                                color:
+                                    AppColors.of(context).text.withOpacity(.75),
+                                fontWeight: FontWeight.bold,
+                                fontSize: 14.0,
+                              ),
+                              margin: 12.0,
+                              getTitles: (value) {
+                                var format = DateFormat(
+                                    "MMM", I18n.of(context).locale.toString());
+
+                                String title = format
+                                    .format(DateTime(0, value.floor() % 12))
+                                    .replaceAll(".", "");
+                                title =
+                                    title.substring(0, min(title.length, 4));
+
+                                return title.toUpperCase();
+                              },
+                              interval: () {
+                                List<Grade> tData =
+                                    ghostData.isNotEmpty ? ghostData : data;
+                                tData.sort((a, b) =>
+                                    a.writeDate.compareTo(b.writeDate));
+                                return tData.first.writeDate
+                                        .add(const Duration(days: 120))
+                                        .isBefore(tData.last.writeDate)
+                                    ? 2.0
+                                    : 1.0;
+                              }(),
+                              checkToShowTitle: (double minValue,
+                                  double maxValue,
+                                  SideTitles sideTitles,
+                                  double appliedInterval,
+                                  double value) {
+                                if (value == maxValue || value == minValue)
+                                  return false;
+                                return true;
+                              },
+                            ),
+                            leftTitles: SideTitles(
+                              showTitles: true,
+                              interval: 1.0,
+                              getTextStyles: (context, value) => TextStyle(
+                                color: AppColors.of(context).text,
+                                fontWeight: FontWeight.bold,
+                                fontSize: 18.0,
+                              ),
+                              margin: 16,
+                            ),
+                            rightTitles: SideTitles(showTitles: false),
+                            topTitles: SideTitles(showTitles: false),
+                          ),
+                        ),
+                      ),
+                    )
+                  : null,
+              height: 158,
+            ),
+          );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/graph.i18n.dart b/refilc_mobile_ui/lib/pages/grades/graph.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/grades/graph.i18n.dart
rename to refilc_mobile_ui/lib/pages/grades/graph.i18n.dart
index 2272472..aa484c9
--- a/filcnaplo_mobile_ui/lib/pages/grades/graph.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/grades/graph.i18n.dart
@@ -1,24 +1,24 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "mid": "Mid year",
-          "not_enough_grades": "Not enough data to show a graph here.",
-        },
-        "hu_hu": {
-          "mid": "Félév",
-          "not_enough_grades": "Nem szereztél még elég jegyet grafikon mutatáshoz.",
-        },
-        "de_de": {
-          "mid": "Halbjährlich",
-          "not_enough_grades": "Noch nicht genug Noten, um die Grafik zu zeigen.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "mid": "Mid year",
+          "not_enough_grades": "Not enough data to show a graph here.",
+        },
+        "hu_hu": {
+          "mid": "Félév",
+          "not_enough_grades": "Nem szereztél még elég jegyet grafikon mutatáshoz.",
+        },
+        "de_de": {
+          "mid": "Halbjährlich",
+          "not_enough_grades": "Noch nicht genug Noten, um die Grafik zu zeigen.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/grades/subject_grades_container.dart b/refilc_mobile_ui/lib/pages/grades/subject_grades_container.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/grades/subject_grades_container.dart
rename to refilc_mobile_ui/lib/pages/grades/subject_grades_container.dart
index 58b2bc0..172ea02
--- a/filcnaplo_mobile_ui/lib/pages/grades/subject_grades_container.dart
+++ b/refilc_mobile_ui/lib/pages/grades/subject_grades_container.dart
@@ -1,10 +1,10 @@
-import 'package:flutter/material.dart';
-
-class SubjectGradesContainer extends InheritedWidget {
-  const SubjectGradesContainer({Key? key, required Widget child}) : super(key: key, child: child);
-
-  static SubjectGradesContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<SubjectGradesContainer>();
-
-  @override
-  bool updateShouldNotify(SubjectGradesContainer oldWidget) => false;
-}
+import 'package:flutter/material.dart';
+
+class SubjectGradesContainer extends InheritedWidget {
+  const SubjectGradesContainer({Key? key, required Widget child}) : super(key: key, child: child);
+
+  static SubjectGradesContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<SubjectGradesContainer>();
+
+  @override
+  bool updateShouldNotify(SubjectGradesContainer oldWidget) => false;
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/home_page.dart b/refilc_mobile_ui/lib/pages/home/home_page.dart
old mode 100755
new mode 100644
similarity index 89%
rename from filcnaplo_mobile_ui/lib/pages/home/home_page.dart
rename to refilc_mobile_ui/lib/pages/home/home_page.dart
index 02298d7..ee66e29
--- a/filcnaplo_mobile_ui/lib/pages/home/home_page.dart
+++ b/refilc_mobile_ui/lib/pages/home/home_page.dart
@@ -1,409 +1,409 @@
-// ignore_for_file: dead_code
-import 'dart:math';
-
-import 'package:filcnaplo/api/providers/live_card_provider.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:animated_list_plus/animated_list_plus.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/api/providers/sync.dart';
-import 'package:confetti/confetti.dart';
-import 'package:filcnaplo/models/settings.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'home_page.i18n.dart';
-import 'package:filcnaplo/ui/filter/widgets.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-
-class HomePage extends StatefulWidget {
-  const HomePage({Key? key}) : super(key: key);
-
-  @override
-  _HomePageState createState() => _HomePageState();
-}
-
-class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
-  late TabController _tabController;
-  late UserProvider user;
-  late SettingsProvider settings;
-  late UpdateProvider updateProvider;
-  late StatusProvider statusProvider;
-  late GradeProvider gradeProvider;
-  late TimetableProvider timetableProvider;
-  late MessageProvider messageProvider;
-  late AbsenceProvider absenceProvider;
-  late HomeworkProvider homeworkProvider;
-  late ExamProvider examProvider;
-  late NoteProvider noteProvider;
-  late EventProvider eventProvider;
-
-  late PageController _pageController;
-  ConfettiController? _confettiController;
-  late LiveCardProvider _liveCard;
-  late AnimationController _liveCardAnimation;
-
-  late String greeting;
-  late String firstName;
-
-  late List<String> listOrder;
-  static const pageCount = 4;
-
-  @override
-  void initState() {
-    super.initState();
-
-    _tabController = TabController(length: pageCount, vsync: this);
-    _pageController = PageController();
-    user = Provider.of<UserProvider>(context, listen: false);
-    _liveCard = Provider.of<LiveCardProvider>(context, listen: false);
-    _liveCardAnimation = AnimationController(
-        vsync: this, duration: const Duration(milliseconds: 500));
-
-    _liveCardAnimation.animateTo(_liveCard.show ? 1.0 : 0.0,
-        duration: Duration.zero);
-
-    listOrder = List.generate(pageCount, (index) => "$index");
-  }
-
-  @override
-  void dispose() {
-    // _filterController.dispose();
-    _pageController.dispose();
-    _tabController.dispose();
-    _confettiController?.dispose();
-    _liveCardAnimation.dispose();
-
-    super.dispose();
-  }
-
-  void setGreeting() {
-    DateTime now = DateTime.now();
-    if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
-        now.isAfter(DateTime(now.year, DateTime.june, 14))) {
-      greeting = "goodrest";
-
-      if (NavigationScreen.of(context)?.init("confetti") ?? false) {
-        _confettiController =
-            ConfettiController(duration: const Duration(seconds: 1));
-        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";
-
-      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";
-
-      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.month == DateTime.december &&
-        now.day >= 24 &&
-        now.day <= 26) {
-      greeting = "merryxmas";
-    } else if (now.month == DateTime.january && now.day == 1) {
-      greeting = "happynewyear";
-    } else if (now.hour >= 18) {
-      greeting = "goodevening";
-    } else if (now.hour >= 10) {
-      greeting = "goodafternoon";
-    } else if (now.hour >= 4) {
-      greeting = "goodmorning";
-    } else {
-      greeting = "goodevening";
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    settings = Provider.of<SettingsProvider>(context);
-    statusProvider = Provider.of<StatusProvider>(context, listen: false);
-    updateProvider = Provider.of<UpdateProvider>(context);
-    _liveCard = Provider.of<LiveCardProvider>(context);
-    gradeProvider = Provider.of<GradeProvider>(context);
-    context.watch<PremiumProvider>();
-
-    _liveCardAnimation.animateTo(_liveCard.show ? 1.0 : 0.0);
-
-    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: [
-          Padding(
-            padding: const EdgeInsets.only(top: 12.0),
-            child: NestedScrollView(
-                physics: const BouncingScrollPhysics(
-                    parent: AlwaysScrollableScrollPhysics()),
-                headerSliverBuilder: (context, _) => [
-                      AnimatedBuilder(
-                        animation: _liveCardAnimation,
-                        builder: (context, child) {
-                          return SliverAppBar(
-                            automaticallyImplyLeading: false,
-                            surfaceTintColor:
-                                Theme.of(context).scaffoldBackgroundColor,
-                            centerTitle: false,
-                            titleSpacing: 0.0,
-                            // Welcome text
-                            title: Padding(
-                              padding: const EdgeInsets.only(left: 24.0),
-                              child: Text(
-                                greeting.i18n.fill([firstName]),
-                                overflow: TextOverflow.fade,
-                                style: TextStyle(
-                                  fontWeight: FontWeight.bold,
-                                  fontSize: 18.0,
-                                  color: Theme.of(context)
-                                      .textTheme
-                                      .bodyMedium
-                                      ?.color,
-                                ),
-                              ),
-                            ),
-                            actions: [
-                              // Profile Icon
-                              Padding(
-                                padding: const EdgeInsets.only(right: 24.0),
-                                child: ProfileButton(
-                                  child: ProfileImage(
-                                    heroTag: "profile",
-                                    name: firstName,
-                                    backgroundColor: Theme.of(context)
-                                        .colorScheme
-                                        .primary, //!settings.presentationMode
-                                    //? ColorUtils.stringToColor(user.displayName ?? "?")
-                                    //: Theme.of(context).colorScheme.secondary,
-                                    badge: updateProvider.available,
-                                    role: user.role,
-                                    profilePictureString: user.picture,
-                                  ),
-                                ),
-                              ),
-                            ],
-
-                            expandedHeight: _liveCardAnimation.value * 234.0,
-
-                            // Live Card
-                            flexibleSpace: FlexibleSpaceBar(
-                              background: Padding(
-                                padding: EdgeInsets.only(
-                                  left: 24.0,
-                                  right: 24.0,
-                                  top:
-                                      58.0 + MediaQuery.of(context).padding.top,
-                                  bottom: 52.0,
-                                ),
-                                child: Transform.scale(
-                                  scale: _liveCardAnimation.value,
-                                  child: Opacity(
-                                    opacity: _liveCardAnimation.value,
-                                    child: const LiveCard(),
-                                  ),
-                                ),
-                              ),
-                            ),
-                            shadowColor: Colors.black,
-
-                            // Filter Bar
-                            bottom: FilterBar(
-                              items: [
-                                Tab(text: "All".i18n),
-                                Tab(text: "Grades".i18n),
-                                Tab(text: "Messages".i18n),
-                                Tab(text: "Absences".i18n),
-                              ],
-                              controller: _tabController,
-                              disableFading: true,
-                              onTap: (i) async {
-                                int selectedPage =
-                                    _pageController.page!.round();
-
-                                if (i == selectedPage) return;
-                                if (_pageController.page?.roundToDouble() !=
-                                    _pageController.page) {
-                                  _pageController.animateToPage(i,
-                                      curve: Curves.easeIn,
-                                      duration: kTabScrollDuration);
-                                  return;
-                                }
-
-                                // swap current page with target page
-                                setState(() {
-                                  _pageController.jumpToPage(i);
-                                  String currentList = listOrder[selectedPage];
-                                  listOrder[selectedPage] = listOrder[i];
-                                  listOrder[i] = currentList;
-                                });
-                              },
-                            ),
-                            pinned: true,
-                            floating: false,
-                            snap: false,
-                          );
-                        },
-                      ),
-                    ],
-                body: Padding(
-                  padding: const EdgeInsets.only(top: 12.0),
-                  child: NotificationListener<ScrollNotification>(
-                    onNotification: (notification) {
-                      // from flutter source
-                      if (notification is ScrollUpdateNotification &&
-                          !_tabController.indexIsChanging) {
-                        if ((_pageController.page! - _tabController.index)
-                                .abs() >
-                            1.0) {
-                          _tabController.index = _pageController.page!.floor();
-                        }
-                        _tabController.offset =
-                            (_pageController.page! - _tabController.index)
-                                .clamp(-1.0, 1.0);
-                      } else if (notification is ScrollEndNotification) {
-                        _tabController.index = _pageController.page!.round();
-                        if (!_tabController.indexIsChanging) {
-                          _tabController.offset =
-                              (_pageController.page! - _tabController.index)
-                                  .clamp(-1.0, 1.0);
-                        }
-                      }
-                      return false;
-                    },
-                    child: PageView.custom(
-                      controller: _pageController,
-                      childrenDelegate: SliverChildBuilderDelegate(
-                        (BuildContext context, int index) {
-                          return FutureBuilder<List<DateWidget>>(
-                            key: ValueKey<String>(listOrder[index]),
-                            future: getFilterWidgets(homeFilters[index],
-                                context: context),
-                            builder: (context, dateWidgets) => dateWidgets
-                                        .data !=
-                                    null
-                                ? RefreshIndicator(
-                                    color:
-                                        Theme.of(context).colorScheme.secondary,
-                                    onRefresh: () => syncAll(context),
-                                    child: ImplicitlyAnimatedList<Widget>(
-                                      items: [
-                                        if (index == 0)
-                                          const SizedBox(key: Key("\$premium")),
-                                        ...sortDateWidgets(context,
-                                            dateWidgets: dateWidgets.data!),
-                                      ],
-                                      itemBuilder: filterItemBuilder,
-                                      spawnIsolate: false,
-                                      areItemsTheSame: (a, b) => a.key == b.key,
-                                      physics: const BouncingScrollPhysics(
-                                          parent:
-                                              AlwaysScrollableScrollPhysics()),
-                                      padding: const EdgeInsets.symmetric(
-                                          horizontal: 24.0),
-                                    ))
-                                : Container(),
-                          );
-                        },
-                        childCount: 4,
-                        findChildIndexCallback: (Key key) {
-                          final ValueKey<String> valueKey =
-                              key as ValueKey<String>;
-                          final String data = valueKey.value;
-                          return listOrder.indexOf(data);
-                        },
-                      ),
-                      physics: const PageScrollPhysics()
-                          .applyTo(const BouncingScrollPhysics()),
-                    ),
-                  ),
-                )),
-          ),
-
-          // confetti 🎊
-          if (_confettiController != null)
-            Align(
-              alignment: Alignment.topCenter,
-              child: ConfettiWidget(
-                confettiController: _confettiController!,
-                blastDirectionality: BlastDirectionality.explosive,
-                emissionFrequency: 0.02,
-                numberOfParticles: 120,
-                maxBlastForce: 20,
-                minBlastForce: 10,
-                gravity: 0.3,
-                minimumSize: const Size(5, 5),
-                maximumSize: const Size(20, 20),
-              ),
-            ),
-        ],
-      ),
-    );
-  }
-
-  Future<Widget> filterViewBuilder(context, int activeData) async {
-    final activeFilter = homeFilters[activeData];
-
-    List<Widget> filterWidgets = sortDateWidgets(
-      context,
-      dateWidgets: await getFilterWidgets(activeFilter, context: context),
-      showDivider: true,
-    );
-
-    return Padding(
-      padding: const EdgeInsets.only(top: 12.0),
-      child: RefreshIndicator(
-        color: Theme.of(context).colorScheme.secondary,
-        onRefresh: () => syncAll(context),
-        child: ListView.builder(
-          padding: EdgeInsets.zero,
-          physics: const BouncingScrollPhysics(),
-          itemBuilder: (context, index) {
-            if (filterWidgets.isNotEmpty) {
-              return Padding(
-                padding: const EdgeInsets.symmetric(horizontal: 24.0),
-                child: filterWidgets[index],
-              );
-            } else {
-              return Empty(subtitle: "empty".i18n);
-            }
-          },
-          itemCount: max(filterWidgets.length, 1),
-        ),
-      ),
-    );
-  }
-}
+// ignore_for_file: dead_code
+import 'dart:math';
+
+import 'package:refilc/api/providers/live_card_provider.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:animated_list_plus/animated_list_plus.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/api/providers/sync.dart';
+import 'package:confetti/confetti.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/status_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/pages/home/live_card/live_card.dart';
+import 'package:refilc_mobile_ui/screens/navigation/navigation_screen.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'home_page.i18n.dart';
+import 'package:refilc/ui/filter/widgets.dart';
+import 'package:refilc/ui/filter/sort.dart';
+
+class HomePage extends StatefulWidget {
+  const HomePage({Key? key}) : super(key: key);
+
+  @override
+  _HomePageState createState() => _HomePageState();
+}
+
+class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
+  late TabController _tabController;
+  late UserProvider user;
+  late SettingsProvider settings;
+  late UpdateProvider updateProvider;
+  late StatusProvider statusProvider;
+  late GradeProvider gradeProvider;
+  late TimetableProvider timetableProvider;
+  late MessageProvider messageProvider;
+  late AbsenceProvider absenceProvider;
+  late HomeworkProvider homeworkProvider;
+  late ExamProvider examProvider;
+  late NoteProvider noteProvider;
+  late EventProvider eventProvider;
+
+  late PageController _pageController;
+  ConfettiController? _confettiController;
+  late LiveCardProvider _liveCard;
+  late AnimationController _liveCardAnimation;
+
+  late String greeting;
+  late String firstName;
+
+  late List<String> listOrder;
+  static const pageCount = 4;
+
+  @override
+  void initState() {
+    super.initState();
+
+    _tabController = TabController(length: pageCount, vsync: this);
+    _pageController = PageController();
+    user = Provider.of<UserProvider>(context, listen: false);
+    _liveCard = Provider.of<LiveCardProvider>(context, listen: false);
+    _liveCardAnimation = AnimationController(
+        vsync: this, duration: const Duration(milliseconds: 500));
+
+    _liveCardAnimation.animateTo(_liveCard.show ? 1.0 : 0.0,
+        duration: Duration.zero);
+
+    listOrder = List.generate(pageCount, (index) => "$index");
+  }
+
+  @override
+  void dispose() {
+    // _filterController.dispose();
+    _pageController.dispose();
+    _tabController.dispose();
+    _confettiController?.dispose();
+    _liveCardAnimation.dispose();
+
+    super.dispose();
+  }
+
+  void setGreeting() {
+    DateTime now = DateTime.now();
+    if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
+        now.isAfter(DateTime(now.year, DateTime.june, 14))) {
+      greeting = "goodrest";
+
+      if (NavigationScreen.of(context)?.init("confetti") ?? false) {
+        _confettiController =
+            ConfettiController(duration: const Duration(seconds: 1));
+        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";
+
+      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";
+
+      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.month == DateTime.december &&
+        now.day >= 24 &&
+        now.day <= 26) {
+      greeting = "merryxmas";
+    } else if (now.month == DateTime.january && now.day == 1) {
+      greeting = "happynewyear";
+    } else if (now.hour >= 18) {
+      greeting = "goodevening";
+    } else if (now.hour >= 10) {
+      greeting = "goodafternoon";
+    } else if (now.hour >= 4) {
+      greeting = "goodmorning";
+    } else {
+      greeting = "goodevening";
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    settings = Provider.of<SettingsProvider>(context);
+    statusProvider = Provider.of<StatusProvider>(context, listen: false);
+    updateProvider = Provider.of<UpdateProvider>(context);
+    _liveCard = Provider.of<LiveCardProvider>(context);
+    gradeProvider = Provider.of<GradeProvider>(context);
+    context.watch<PremiumProvider>();
+
+    _liveCardAnimation.animateTo(_liveCard.show ? 1.0 : 0.0);
+
+    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: [
+          Padding(
+            padding: const EdgeInsets.only(top: 12.0),
+            child: NestedScrollView(
+                physics: const BouncingScrollPhysics(
+                    parent: AlwaysScrollableScrollPhysics()),
+                headerSliverBuilder: (context, _) => [
+                      AnimatedBuilder(
+                        animation: _liveCardAnimation,
+                        builder: (context, child) {
+                          return SliverAppBar(
+                            automaticallyImplyLeading: false,
+                            surfaceTintColor:
+                                Theme.of(context).scaffoldBackgroundColor,
+                            centerTitle: false,
+                            titleSpacing: 0.0,
+                            // Welcome text
+                            title: Padding(
+                              padding: const EdgeInsets.only(left: 24.0),
+                              child: Text(
+                                greeting.i18n.fill([firstName]),
+                                overflow: TextOverflow.fade,
+                                style: TextStyle(
+                                  fontWeight: FontWeight.bold,
+                                  fontSize: 18.0,
+                                  color: Theme.of(context)
+                                      .textTheme
+                                      .bodyMedium
+                                      ?.color,
+                                ),
+                              ),
+                            ),
+                            actions: [
+                              // Profile Icon
+                              Padding(
+                                padding: const EdgeInsets.only(right: 24.0),
+                                child: ProfileButton(
+                                  child: ProfileImage(
+                                    heroTag: "profile",
+                                    name: firstName,
+                                    backgroundColor: Theme.of(context)
+                                        .colorScheme
+                                        .primary, //!settings.presentationMode
+                                    //? ColorUtils.stringToColor(user.displayName ?? "?")
+                                    //: Theme.of(context).colorScheme.secondary,
+                                    badge: updateProvider.available,
+                                    role: user.role,
+                                    profilePictureString: user.picture,
+                                  ),
+                                ),
+                              ),
+                            ],
+
+                            expandedHeight: _liveCardAnimation.value * 234.0,
+
+                            // Live Card
+                            flexibleSpace: FlexibleSpaceBar(
+                              background: Padding(
+                                padding: EdgeInsets.only(
+                                  left: 24.0,
+                                  right: 24.0,
+                                  top:
+                                      58.0 + MediaQuery.of(context).padding.top,
+                                  bottom: 52.0,
+                                ),
+                                child: Transform.scale(
+                                  scale: _liveCardAnimation.value,
+                                  child: Opacity(
+                                    opacity: _liveCardAnimation.value,
+                                    child: const LiveCard(),
+                                  ),
+                                ),
+                              ),
+                            ),
+                            shadowColor: Colors.black,
+
+                            // Filter Bar
+                            bottom: FilterBar(
+                              items: [
+                                Tab(text: "All".i18n),
+                                Tab(text: "Grades".i18n),
+                                Tab(text: "Messages".i18n),
+                                Tab(text: "Absences".i18n),
+                              ],
+                              controller: _tabController,
+                              disableFading: true,
+                              onTap: (i) async {
+                                int selectedPage =
+                                    _pageController.page!.round();
+
+                                if (i == selectedPage) return;
+                                if (_pageController.page?.roundToDouble() !=
+                                    _pageController.page) {
+                                  _pageController.animateToPage(i,
+                                      curve: Curves.easeIn,
+                                      duration: kTabScrollDuration);
+                                  return;
+                                }
+
+                                // swap current page with target page
+                                setState(() {
+                                  _pageController.jumpToPage(i);
+                                  String currentList = listOrder[selectedPage];
+                                  listOrder[selectedPage] = listOrder[i];
+                                  listOrder[i] = currentList;
+                                });
+                              },
+                            ),
+                            pinned: true,
+                            floating: false,
+                            snap: false,
+                          );
+                        },
+                      ),
+                    ],
+                body: Padding(
+                  padding: const EdgeInsets.only(top: 12.0),
+                  child: NotificationListener<ScrollNotification>(
+                    onNotification: (notification) {
+                      // from flutter source
+                      if (notification is ScrollUpdateNotification &&
+                          !_tabController.indexIsChanging) {
+                        if ((_pageController.page! - _tabController.index)
+                                .abs() >
+                            1.0) {
+                          _tabController.index = _pageController.page!.floor();
+                        }
+                        _tabController.offset =
+                            (_pageController.page! - _tabController.index)
+                                .clamp(-1.0, 1.0);
+                      } else if (notification is ScrollEndNotification) {
+                        _tabController.index = _pageController.page!.round();
+                        if (!_tabController.indexIsChanging) {
+                          _tabController.offset =
+                              (_pageController.page! - _tabController.index)
+                                  .clamp(-1.0, 1.0);
+                        }
+                      }
+                      return false;
+                    },
+                    child: PageView.custom(
+                      controller: _pageController,
+                      childrenDelegate: SliverChildBuilderDelegate(
+                        (BuildContext context, int index) {
+                          return FutureBuilder<List<DateWidget>>(
+                            key: ValueKey<String>(listOrder[index]),
+                            future: getFilterWidgets(homeFilters[index],
+                                context: context),
+                            builder: (context, dateWidgets) => dateWidgets
+                                        .data !=
+                                    null
+                                ? RefreshIndicator(
+                                    color:
+                                        Theme.of(context).colorScheme.secondary,
+                                    onRefresh: () => syncAll(context),
+                                    child: ImplicitlyAnimatedList<Widget>(
+                                      items: [
+                                        if (index == 0)
+                                          const SizedBox(key: Key("\$premium")),
+                                        ...sortDateWidgets(context,
+                                            dateWidgets: dateWidgets.data!),
+                                      ],
+                                      itemBuilder: filterItemBuilder,
+                                      spawnIsolate: false,
+                                      areItemsTheSame: (a, b) => a.key == b.key,
+                                      physics: const BouncingScrollPhysics(
+                                          parent:
+                                              AlwaysScrollableScrollPhysics()),
+                                      padding: const EdgeInsets.symmetric(
+                                          horizontal: 24.0),
+                                    ))
+                                : Container(),
+                          );
+                        },
+                        childCount: 4,
+                        findChildIndexCallback: (Key key) {
+                          final ValueKey<String> valueKey =
+                              key as ValueKey<String>;
+                          final String data = valueKey.value;
+                          return listOrder.indexOf(data);
+                        },
+                      ),
+                      physics: const PageScrollPhysics()
+                          .applyTo(const BouncingScrollPhysics()),
+                    ),
+                  ),
+                )),
+          ),
+
+          // confetti 🎊
+          if (_confettiController != null)
+            Align(
+              alignment: Alignment.topCenter,
+              child: ConfettiWidget(
+                confettiController: _confettiController!,
+                blastDirectionality: BlastDirectionality.explosive,
+                emissionFrequency: 0.02,
+                numberOfParticles: 120,
+                maxBlastForce: 20,
+                minBlastForce: 10,
+                gravity: 0.3,
+                minimumSize: const Size(5, 5),
+                maximumSize: const Size(20, 20),
+              ),
+            ),
+        ],
+      ),
+    );
+  }
+
+  Future<Widget> filterViewBuilder(context, int activeData) async {
+    final activeFilter = homeFilters[activeData];
+
+    List<Widget> filterWidgets = sortDateWidgets(
+      context,
+      dateWidgets: await getFilterWidgets(activeFilter, context: context),
+      showDivider: true,
+    );
+
+    return Padding(
+      padding: const EdgeInsets.only(top: 12.0),
+      child: RefreshIndicator(
+        color: Theme.of(context).colorScheme.secondary,
+        onRefresh: () => syncAll(context),
+        child: ListView.builder(
+          padding: EdgeInsets.zero,
+          physics: const BouncingScrollPhysics(),
+          itemBuilder: (context, index) {
+            if (filterWidgets.isNotEmpty) {
+              return Padding(
+                padding: const EdgeInsets.symmetric(horizontal: 24.0),
+                child: filterWidgets[index],
+              );
+            } else {
+              return Empty(subtitle: "empty".i18n);
+            }
+          },
+          itemCount: max(filterWidgets.length, 1),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/home_page.i18n.dart b/refilc_mobile_ui/lib/pages/home/home_page.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/home/home_page.i18n.dart
rename to refilc_mobile_ui/lib/pages/home/home_page.i18n.dart
index 9cd9ea6..16ddd14
--- a/filcnaplo_mobile_ui/lib/pages/home/home_page.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/home/home_page.i18n.dart
@@ -1,69 +1,69 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "goodmorning": "Good morning, %s!",
-          "goodafternoon": "Good afternoon, %s!",
-          "goodevening": "Good evening, %s!",
-          "goodrest": "⛱️ Have a nice holiday, %s!",
-          "happybirthday": "🎂 Happy birthday, %s!",
-          "merryxmas": "🎄 Merry Christmas, %s!",
-          "happynewyear": "🎉 Happy New Year, %s!",
-          "refilcopen": "🎈 reFilc is 1 year old, %s!",
-          "empty": "Nothing to see here.",
-          "All": "All",
-          "Grades": "Grades",
-          "Messages": "Messages",
-          "Absences": "Absences",
-          "update_available": "Update Available",
-          "missed_exams": "You missed %s exams this week."
-              .one("You missed an exam this week."),
-          "missed_exam_contact": "Contact %s, to resolve it!",
-        },
-        "hu_hu": {
-          "goodmorning": "Jó reggelt, %s!",
-          "goodafternoon": "Szép napot, %s!",
-          "goodevening": "Szép estét, %s!",
-          "goodrest": "⛱️ Jó szünetet, %s!",
-          "happybirthday": "🎂 Boldog születésnapot, %s!",
-          "merryxmas": "🎄 Boldog Karácsonyt, %s!",
-          "happynewyear": "🎉 Boldog új évet, %s!",
-          "refilcopen": "🎈 1 éves a reFilc, %s!",
-          "empty": "Nincs itt semmi látnivaló.",
-          "All": "Összes",
-          "Grades": "Jegyek",
-          "Messages": "Üzenetek",
-          "Absences": "Hiányok",
-          "update_available": "Frissítés elérhető",
-          "missed_exams": "Ezen a héten hiányoztál %s dolgozatról."
-              .one("Ezen a héten hiányoztál egy dolgozatról."),
-          "missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
-        },
-        "de_de": {
-          "goodmorning": "Guten morgen, %s!",
-          "goodafternoon": "Guten Tag, %s!",
-          "goodevening": "Guten Abend, %s!",
-          "goodrest": "⛱️ Schöne Ferien, %s!",
-          "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
-          "merryxmas": "🎄 Frohe Weihnachten, %s!",
-          "happynewyear": "🎉 Frohes neues Jahr, %s!",
-          "refilcopen": "🎈 reFilc ist 1 Jahr alt, %s!",
-          "empty": "Hier gibt es nichts zu sehen.",
-          "All": "Alles",
-          "Grades": "Noten",
-          "Messages": "Nachrichten",
-          "Absences": "Fehlen",
-          "update_available": "Update verfügbar",
-          "missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst."
-              .one("Diese Woche haben Sie eine Prüfung verpasst."),
-          "missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "goodmorning": "Good morning, %s!",
+          "goodafternoon": "Good afternoon, %s!",
+          "goodevening": "Good evening, %s!",
+          "goodrest": "⛱️ Have a nice holiday, %s!",
+          "happybirthday": "🎂 Happy birthday, %s!",
+          "merryxmas": "🎄 Merry Christmas, %s!",
+          "happynewyear": "🎉 Happy New Year, %s!",
+          "refilcopen": "🎈 reFilc is 1 year old, %s!",
+          "empty": "Nothing to see here.",
+          "All": "All",
+          "Grades": "Grades",
+          "Messages": "Messages",
+          "Absences": "Absences",
+          "update_available": "Update Available",
+          "missed_exams": "You missed %s exams this week."
+              .one("You missed an exam this week."),
+          "missed_exam_contact": "Contact %s, to resolve it!",
+        },
+        "hu_hu": {
+          "goodmorning": "Jó reggelt, %s!",
+          "goodafternoon": "Szép napot, %s!",
+          "goodevening": "Szép estét, %s!",
+          "goodrest": "⛱️ Jó szünetet, %s!",
+          "happybirthday": "🎂 Boldog születésnapot, %s!",
+          "merryxmas": "🎄 Boldog Karácsonyt, %s!",
+          "happynewyear": "🎉 Boldog új évet, %s!",
+          "refilcopen": "🎈 1 éves a reFilc, %s!",
+          "empty": "Nincs itt semmi látnivaló.",
+          "All": "Összes",
+          "Grades": "Jegyek",
+          "Messages": "Üzenetek",
+          "Absences": "Hiányok",
+          "update_available": "Frissítés elérhető",
+          "missed_exams": "Ezen a héten hiányoztál %s dolgozatról."
+              .one("Ezen a héten hiányoztál egy dolgozatról."),
+          "missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
+        },
+        "de_de": {
+          "goodmorning": "Guten morgen, %s!",
+          "goodafternoon": "Guten Tag, %s!",
+          "goodevening": "Guten Abend, %s!",
+          "goodrest": "⛱️ Schöne Ferien, %s!",
+          "happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
+          "merryxmas": "🎄 Frohe Weihnachten, %s!",
+          "happynewyear": "🎉 Frohes neues Jahr, %s!",
+          "refilcopen": "🎈 reFilc ist 1 Jahr alt, %s!",
+          "empty": "Hier gibt es nichts zu sehen.",
+          "All": "Alles",
+          "Grades": "Noten",
+          "Messages": "Nachrichten",
+          "Absences": "Fehlen",
+          "update_available": "Update verfügbar",
+          "missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst."
+              .one("Diese Woche haben Sie eine Prüfung verpasst."),
+          "missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart b/refilc_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
rename to refilc_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
index 03e5381..a49a84e
--- a/filcnaplo_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
+++ b/refilc_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
@@ -1,102 +1,102 @@
-import 'dart:async';
-
-import 'package:animated_flip_counter/animated_flip_counter.dart';
-import 'package:flutter/material.dart';
-import 'package:lottie/lottie.dart';
-
-class HeadsUpCountdown extends StatefulWidget {
-  const HeadsUpCountdown({Key? key, required this.maxTime, required this.elapsedTime}) : super(key: key);
-
-  final double maxTime;
-  final double elapsedTime;
-
-  @override
-  State<HeadsUpCountdown> createState() => _HeadsUpCountdownState();
-}
-
-class _HeadsUpCountdownState extends State<HeadsUpCountdown> {
-  static const _style = TextStyle(
-    color: Colors.white,
-    fontWeight: FontWeight.bold,
-    fontSize: 70.0,
-    letterSpacing: -.5,
-  );
-
-  late final Timer _timer;
-  late double elapsed;
-
-  @override
-  void initState() {
-    super.initState();
-    elapsed = widget.elapsedTime;
-    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
-      if (elapsed <= widget.maxTime) elapsed += 1;
-      setState(() {});
-
-      if (elapsed >= widget.maxTime) {
-        Future.delayed(const Duration(seconds: 5), () {
-          if (mounted) Navigator.of(context).pop();
-        });
-      }
-    });
-  }
-
-  @override
-  void dispose() {
-    _timer.cancel();
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final dur = Duration(seconds: (widget.maxTime - elapsed).round());
-    return Center(
-      child: Material(
-        type: MaterialType.transparency,
-        child: Stack(
-          alignment: Alignment.center,
-          children: [
-            AnimatedOpacity(
-              opacity: dur.inSeconds > 0 ? 1.0 : 0.0,
-              duration: const Duration(milliseconds: 500),
-              child: Row(
-                mainAxisAlignment: MainAxisAlignment.center,
-                children: [
-                  if ((dur.inHours % 24) > 0) ...[
-                    AnimatedFlipCounter(
-                      value: dur.inHours % 24,
-                      curve: Curves.fastLinearToSlowEaseIn,
-                      textStyle: _style,
-                    ),
-                    const Text(":", style: _style),
-                  ],
-                  AnimatedFlipCounter(
-                    duration: const Duration(seconds: 2),
-                    value: dur.inMinutes % 60,
-                    curve: Curves.fastLinearToSlowEaseIn,
-                    wholeDigits: (dur.inHours % 24) > 0 ? 2 : 1,
-                    textStyle: _style,
-                  ),
-                  const Text(":", style: _style),
-                  AnimatedFlipCounter(
-                    duration: const Duration(seconds: 1),
-                    value: dur.inSeconds % 60,
-                    curve: Curves.fastLinearToSlowEaseIn,
-                    wholeDigits: 2,
-                    textStyle: _style,
-                  ),
-                ],
-              ),
-            ),
-            if (dur.inSeconds < 0)
-              AnimatedOpacity(
-                opacity: dur.inSeconds > 0 ? 0.0 : 1.0,
-                duration: const Duration(milliseconds: 500),
-                child: Lottie.asset("assets/animations/bell-alert.json", width: 400),
-              ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'dart:async';
+
+import 'package:animated_flip_counter/animated_flip_counter.dart';
+import 'package:flutter/material.dart';
+import 'package:lottie/lottie.dart';
+
+class HeadsUpCountdown extends StatefulWidget {
+  const HeadsUpCountdown({Key? key, required this.maxTime, required this.elapsedTime}) : super(key: key);
+
+  final double maxTime;
+  final double elapsedTime;
+
+  @override
+  State<HeadsUpCountdown> createState() => _HeadsUpCountdownState();
+}
+
+class _HeadsUpCountdownState extends State<HeadsUpCountdown> {
+  static const _style = TextStyle(
+    color: Colors.white,
+    fontWeight: FontWeight.bold,
+    fontSize: 70.0,
+    letterSpacing: -.5,
+  );
+
+  late final Timer _timer;
+  late double elapsed;
+
+  @override
+  void initState() {
+    super.initState();
+    elapsed = widget.elapsedTime;
+    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
+      if (elapsed <= widget.maxTime) elapsed += 1;
+      setState(() {});
+
+      if (elapsed >= widget.maxTime) {
+        Future.delayed(const Duration(seconds: 5), () {
+          if (mounted) Navigator.of(context).pop();
+        });
+      }
+    });
+  }
+
+  @override
+  void dispose() {
+    _timer.cancel();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final dur = Duration(seconds: (widget.maxTime - elapsed).round());
+    return Center(
+      child: Material(
+        type: MaterialType.transparency,
+        child: Stack(
+          alignment: Alignment.center,
+          children: [
+            AnimatedOpacity(
+              opacity: dur.inSeconds > 0 ? 1.0 : 0.0,
+              duration: const Duration(milliseconds: 500),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                children: [
+                  if ((dur.inHours % 24) > 0) ...[
+                    AnimatedFlipCounter(
+                      value: dur.inHours % 24,
+                      curve: Curves.fastLinearToSlowEaseIn,
+                      textStyle: _style,
+                    ),
+                    const Text(":", style: _style),
+                  ],
+                  AnimatedFlipCounter(
+                    duration: const Duration(seconds: 2),
+                    value: dur.inMinutes % 60,
+                    curve: Curves.fastLinearToSlowEaseIn,
+                    wholeDigits: (dur.inHours % 24) > 0 ? 2 : 1,
+                    textStyle: _style,
+                  ),
+                  const Text(":", style: _style),
+                  AnimatedFlipCounter(
+                    duration: const Duration(seconds: 1),
+                    value: dur.inSeconds % 60,
+                    curve: Curves.fastLinearToSlowEaseIn,
+                    wholeDigits: 2,
+                    textStyle: _style,
+                  ),
+                ],
+              ),
+            ),
+            if (dur.inSeconds < 0)
+              AnimatedOpacity(
+                opacity: dur.inSeconds > 0 ? 0.0 : 1.0,
+                duration: const Duration(milliseconds: 500),
+                child: Lottie.asset("assets/animations/bell-alert.json", width: 400),
+              ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart b/refilc_mobile_ui/lib/pages/home/live_card/live_card.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart
rename to refilc_mobile_ui/lib/pages/home/live_card/live_card.dart
index 94840aa..d62aa17
--- a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart
+++ b/refilc_mobile_ui/lib/pages/home/live_card/live_card.dart
@@ -1,294 +1,294 @@
-import 'package:animations/animations.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_mobile_ui/pages/home/live_card/heads_up_countdown.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo/api/providers/live_card_provider.dart';
-import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card_widget.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:intl/intl.dart';
-import 'package:provider/provider.dart';
-import 'live_card.i18n.dart';
-
-class LiveCard extends StatefulWidget {
-  const LiveCard({Key? key}) : super(key: key);
-
-  @override
-  _LiveCardState createState() => _LiveCardState();
-}
-
-class _LiveCardState extends State<LiveCard> {
-  late void Function() listener;
-  late UserProvider _userProvider;
-  late LiveCardProvider liveCard;
-
-  @override
-  void initState() {
-    super.initState();
-    listener = () => setState(() {});
-    _userProvider = Provider.of<UserProvider>(context, listen: false);
-    liveCard = Provider.of<LiveCardProvider>(context, listen: false);
-    _userProvider.addListener(liveCard.update);
-  }
-
-  @override
-  void dispose() {
-    _userProvider.removeListener(liveCard.update);
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    liveCard = Provider.of<LiveCardProvider>(context);
-    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
-
-    if (!liveCard.show) return Container();
-
-    Widget child;
-    Duration bellDelay = liveCard.delay;
-
-    switch (liveCard.currentState) {
-      case LiveCardState.summary:
-        child = LiveCardWidget(
-          key: const Key('livecard.summary'),
-          title: 'Vége a tanévnek! 🥳',
-          icon: FeatherIcons.arrowRight,
-          description: Text(
-            'Irány az összefoglaláshoz',
-            style: TextStyle(
-              fontWeight: FontWeight.w500,
-              fontSize: 18.0,
-              color: Theme.of(context).textTheme.bodyMedium?.color,
-            ),
-          ),
-          onTap: () {
-            // showSlidingBottomSheet(
-            //   context,
-            //   useRootNavigator: true,
-            //   builder: (context) => SlidingSheetDialog(
-            //     color: Colors.black.withOpacity(0.99),
-            //     duration: const Duration(milliseconds: 400),
-            //     scrollSpec: const ScrollSpec.bouncingScroll(),
-            //     snapSpec: const SnapSpec(
-            //       snap: true,
-            //       snappings: [1.0],
-            //       initialSnap: 1.0,
-            //       positioning: SnapPositioning.relativeToAvailableSpace,
-            //     ),
-            //     minHeight: MediaQuery.of(context).size.height,
-            //     cornerRadius: 16,
-            //     cornerRadiusOnFullscreen: 0,
-            //     builder: (context, state) => const Material(
-            //       color: Colors.black,
-            //       child: SummaryScreen(
-            //         currentPage: 'start',
-            //       ),
-            //     ),
-            //   ),
-            // );
-            SummaryScreen.show(context: context, currentPage: 'start');
-          },
-        );
-        break;
-      case LiveCardState.morning:
-        child = LiveCardWidget(
-          key: const Key('livecard.morning'),
-          title: DateFormat("EEEE", I18n.of(context).locale.toString())
-              .format(DateTime.now())
-              .capital(),
-          icon: FeatherIcons.sun,
-          description: liveCard.nextLesson != null
-              ? Text.rich(
-                  TextSpan(
-                    children: [
-                      TextSpan(text: "first_lesson_1".i18n),
-                      TextSpan(
-                        text: liveCard.nextLesson!.subject.renamedTo ??
-                            liveCard.nextLesson!.subject.name.capital(),
-                        style: TextStyle(
-                            fontWeight: FontWeight.w600,
-                            color: Theme.of(context)
-                                .colorScheme
-                                .secondary
-                                .withOpacity(.85),
-                            fontStyle: liveCard.nextLesson!.subject.isRenamed &&
-                                    settingsProvider.renamedSubjectsItalics
-                                ? FontStyle.italic
-                                : null),
-                      ),
-                      TextSpan(text: "first_lesson_2".i18n),
-                      TextSpan(
-                        text: liveCard.nextLesson!.room.capital(),
-                        style: TextStyle(
-                          fontWeight: FontWeight.w600,
-                          color: Theme.of(context)
-                              .colorScheme
-                              .secondary
-                              .withOpacity(.85),
-                        ),
-                      ),
-                      TextSpan(text: "first_lesson_3".i18n),
-                      TextSpan(
-                        text: DateFormat('H:mm')
-                            .format(liveCard.nextLesson!.start),
-                        style: TextStyle(
-                          fontWeight: FontWeight.w600,
-                          color: Theme.of(context)
-                              .colorScheme
-                              .secondary
-                              .withOpacity(.85),
-                        ),
-                      ),
-                      TextSpan(text: "first_lesson_4".i18n),
-                    ],
-                  ),
-                )
-              : null,
-        );
-        break;
-      case LiveCardState.duringLesson:
-        final elapsedTime = DateTime.now()
-                .difference(liveCard.currentLesson!.start)
-                .inSeconds
-                .toDouble() +
-            bellDelay.inSeconds;
-        final maxTime = liveCard.currentLesson!.end
-            .difference(liveCard.currentLesson!.start)
-            .inSeconds
-            .toDouble();
-
-        final showMinutes = maxTime - elapsedTime > 60;
-
-        child = LiveCardWidget(
-          key: const Key('livecard.duringLesson'),
-          leading: liveCard.currentLesson!.lessonIndex +
-              (RegExp(r'\d').hasMatch(liveCard.currentLesson!.lessonIndex)
-                  ? "."
-                  : ""),
-          title: liveCard.currentLesson!.subject.renamedTo ??
-              liveCard.currentLesson!.subject.name.capital(),
-          titleItalic: liveCard.currentLesson!.subject.isRenamed,
-          subtitle: liveCard.currentLesson!.room,
-          icon: SubjectIcon.resolveVariant(
-              subject: liveCard.currentLesson!.subject, context: context),
-          description: liveCard.currentLesson!.description != ""
-              ? Text(liveCard.currentLesson!.description)
-              : null,
-          nextSubject: liveCard.nextLesson?.subject.renamedTo ??
-              liveCard.nextLesson?.subject.name.capital(),
-          nextSubjectItalic: liveCard.nextLesson?.subject.isRenamed == true &&
-              settingsProvider.renamedSubjectsItalics,
-          nextRoom: liveCard.nextLesson?.room,
-          progressMax: showMinutes ? maxTime / 60 : maxTime,
-          progressCurrent: showMinutes ? elapsedTime / 60 : elapsedTime,
-          progressAccuracy:
-              showMinutes ? ProgressAccuracy.minutes : ProgressAccuracy.seconds,
-          onProgressTap: () {
-            showDialog(
-              barrierColor: Colors.black,
-              context: context,
-              builder: (context) =>
-                  HeadsUpCountdown(maxTime: maxTime, elapsedTime: elapsedTime),
-            );
-          },
-        );
-        break;
-      case LiveCardState.duringBreak:
-        final iconFloorMap = {
-          "to room": FeatherIcons.chevronsRight,
-          "up floor": FilcIcons.upstairs,
-          "down floor": FilcIcons.downstairs,
-          "ground floor": FilcIcons.downstairs,
-        };
-
-        final diff = liveCard.getFloorDifference();
-
-        final maxTime = liveCard.nextLesson!.start
-            .difference(liveCard.prevLesson!.end)
-            .inSeconds
-            .toDouble();
-        final elapsedTime = DateTime.now()
-                .difference(liveCard.prevLesson!.end)
-                .inSeconds
-                .toDouble() +
-            bellDelay.inSeconds.toDouble();
-
-        final showMinutes = maxTime - elapsedTime > 60;
-
-        child = LiveCardWidget(
-          key: const Key('livecard.duringBreak'),
-          title: "break".i18n,
-          icon: iconFloorMap[diff],
-          description: liveCard.nextLesson!.room != liveCard.prevLesson!.room
-              ? Text("go $diff".i18n.fill([
-                  diff != "to room"
-                      ? (liveCard.nextLesson!.getFloor() ?? 0)
-                      : liveCard.nextLesson!.room
-                ]))
-              : Text("stay".i18n),
-          nextSubject: liveCard.nextLesson?.subject.renamedTo ??
-              liveCard.nextLesson?.subject.name.capital(),
-          nextSubjectItalic: liveCard.nextLesson?.subject.isRenamed == true &&
-              settingsProvider.renamedSubjectsItalics,
-          nextRoom: diff != "to room" ? liveCard.nextLesson?.room : null,
-          progressMax: showMinutes ? maxTime / 60 : maxTime,
-          progressCurrent: showMinutes ? elapsedTime / 60 : elapsedTime,
-          progressAccuracy:
-              showMinutes ? ProgressAccuracy.minutes : ProgressAccuracy.seconds,
-          onProgressTap: () {
-            showDialog(
-              barrierColor: Colors.black,
-              context: context,
-              builder: (context) => HeadsUpCountdown(
-                maxTime: maxTime,
-                elapsedTime: elapsedTime,
-              ),
-            );
-          },
-        );
-        break;
-      case LiveCardState.afternoon:
-        child = LiveCardWidget(
-          key: const Key('livecard.afternoon'),
-          title: DateFormat("EEEE", I18n.of(context).locale.toString())
-              .format(DateTime.now())
-              .capital(),
-          icon: FeatherIcons.coffee,
-        );
-        break;
-      case LiveCardState.night:
-        child = LiveCardWidget(
-          key: const Key('livecard.night'),
-          title: DateFormat("EEEE", I18n.of(context).locale.toString())
-              .format(DateTime.now())
-              .capital(),
-          icon: FeatherIcons.moon,
-        );
-        break;
-      default:
-        child = Container();
-    }
-
-    return PageTransitionSwitcher(
-      transitionBuilder: (
-        Widget child,
-        Animation<double> primaryAnimation,
-        Animation<double> secondaryAnimation,
-      ) {
-        return SharedAxisTransition(
-          animation: primaryAnimation,
-          secondaryAnimation: secondaryAnimation,
-          transitionType: SharedAxisTransitionType.horizontal,
-          child: child,
-          fillColor: Theme.of(context).scaffoldBackgroundColor,
-        );
-      },
-      child: child,
-    );
-  }
-}
+import 'package:animations/animations.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_mobile_ui/pages/home/live_card/heads_up_countdown.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc/api/providers/live_card_provider.dart';
+import 'package:refilc_mobile_ui/pages/home/live_card/live_card_widget.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:intl/intl.dart';
+import 'package:provider/provider.dart';
+import 'live_card.i18n.dart';
+
+class LiveCard extends StatefulWidget {
+  const LiveCard({Key? key}) : super(key: key);
+
+  @override
+  _LiveCardState createState() => _LiveCardState();
+}
+
+class _LiveCardState extends State<LiveCard> {
+  late void Function() listener;
+  late UserProvider _userProvider;
+  late LiveCardProvider liveCard;
+
+  @override
+  void initState() {
+    super.initState();
+    listener = () => setState(() {});
+    _userProvider = Provider.of<UserProvider>(context, listen: false);
+    liveCard = Provider.of<LiveCardProvider>(context, listen: false);
+    _userProvider.addListener(liveCard.update);
+  }
+
+  @override
+  void dispose() {
+    _userProvider.removeListener(liveCard.update);
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    liveCard = Provider.of<LiveCardProvider>(context);
+    SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    if (!liveCard.show) return Container();
+
+    Widget child;
+    Duration bellDelay = liveCard.delay;
+
+    switch (liveCard.currentState) {
+      case LiveCardState.summary:
+        child = LiveCardWidget(
+          key: const Key('livecard.summary'),
+          title: 'Vége a tanévnek! 🥳',
+          icon: FeatherIcons.arrowRight,
+          description: Text(
+            'Irány az összefoglaláshoz',
+            style: TextStyle(
+              fontWeight: FontWeight.w500,
+              fontSize: 18.0,
+              color: Theme.of(context).textTheme.bodyMedium?.color,
+            ),
+          ),
+          onTap: () {
+            // showSlidingBottomSheet(
+            //   context,
+            //   useRootNavigator: true,
+            //   builder: (context) => SlidingSheetDialog(
+            //     color: Colors.black.withOpacity(0.99),
+            //     duration: const Duration(milliseconds: 400),
+            //     scrollSpec: const ScrollSpec.bouncingScroll(),
+            //     snapSpec: const SnapSpec(
+            //       snap: true,
+            //       snappings: [1.0],
+            //       initialSnap: 1.0,
+            //       positioning: SnapPositioning.relativeToAvailableSpace,
+            //     ),
+            //     minHeight: MediaQuery.of(context).size.height,
+            //     cornerRadius: 16,
+            //     cornerRadiusOnFullscreen: 0,
+            //     builder: (context, state) => const Material(
+            //       color: Colors.black,
+            //       child: SummaryScreen(
+            //         currentPage: 'start',
+            //       ),
+            //     ),
+            //   ),
+            // );
+            SummaryScreen.show(context: context, currentPage: 'start');
+          },
+        );
+        break;
+      case LiveCardState.morning:
+        child = LiveCardWidget(
+          key: const Key('livecard.morning'),
+          title: DateFormat("EEEE", I18n.of(context).locale.toString())
+              .format(DateTime.now())
+              .capital(),
+          icon: FeatherIcons.sun,
+          description: liveCard.nextLesson != null
+              ? Text.rich(
+                  TextSpan(
+                    children: [
+                      TextSpan(text: "first_lesson_1".i18n),
+                      TextSpan(
+                        text: liveCard.nextLesson!.subject.renamedTo ??
+                            liveCard.nextLesson!.subject.name.capital(),
+                        style: TextStyle(
+                            fontWeight: FontWeight.w600,
+                            color: Theme.of(context)
+                                .colorScheme
+                                .secondary
+                                .withOpacity(.85),
+                            fontStyle: liveCard.nextLesson!.subject.isRenamed &&
+                                    settingsProvider.renamedSubjectsItalics
+                                ? FontStyle.italic
+                                : null),
+                      ),
+                      TextSpan(text: "first_lesson_2".i18n),
+                      TextSpan(
+                        text: liveCard.nextLesson!.room.capital(),
+                        style: TextStyle(
+                          fontWeight: FontWeight.w600,
+                          color: Theme.of(context)
+                              .colorScheme
+                              .secondary
+                              .withOpacity(.85),
+                        ),
+                      ),
+                      TextSpan(text: "first_lesson_3".i18n),
+                      TextSpan(
+                        text: DateFormat('H:mm')
+                            .format(liveCard.nextLesson!.start),
+                        style: TextStyle(
+                          fontWeight: FontWeight.w600,
+                          color: Theme.of(context)
+                              .colorScheme
+                              .secondary
+                              .withOpacity(.85),
+                        ),
+                      ),
+                      TextSpan(text: "first_lesson_4".i18n),
+                    ],
+                  ),
+                )
+              : null,
+        );
+        break;
+      case LiveCardState.duringLesson:
+        final elapsedTime = DateTime.now()
+                .difference(liveCard.currentLesson!.start)
+                .inSeconds
+                .toDouble() +
+            bellDelay.inSeconds;
+        final maxTime = liveCard.currentLesson!.end
+            .difference(liveCard.currentLesson!.start)
+            .inSeconds
+            .toDouble();
+
+        final showMinutes = maxTime - elapsedTime > 60;
+
+        child = LiveCardWidget(
+          key: const Key('livecard.duringLesson'),
+          leading: liveCard.currentLesson!.lessonIndex +
+              (RegExp(r'\d').hasMatch(liveCard.currentLesson!.lessonIndex)
+                  ? "."
+                  : ""),
+          title: liveCard.currentLesson!.subject.renamedTo ??
+              liveCard.currentLesson!.subject.name.capital(),
+          titleItalic: liveCard.currentLesson!.subject.isRenamed,
+          subtitle: liveCard.currentLesson!.room,
+          icon: SubjectIcon.resolveVariant(
+              subject: liveCard.currentLesson!.subject, context: context),
+          description: liveCard.currentLesson!.description != ""
+              ? Text(liveCard.currentLesson!.description)
+              : null,
+          nextSubject: liveCard.nextLesson?.subject.renamedTo ??
+              liveCard.nextLesson?.subject.name.capital(),
+          nextSubjectItalic: liveCard.nextLesson?.subject.isRenamed == true &&
+              settingsProvider.renamedSubjectsItalics,
+          nextRoom: liveCard.nextLesson?.room,
+          progressMax: showMinutes ? maxTime / 60 : maxTime,
+          progressCurrent: showMinutes ? elapsedTime / 60 : elapsedTime,
+          progressAccuracy:
+              showMinutes ? ProgressAccuracy.minutes : ProgressAccuracy.seconds,
+          onProgressTap: () {
+            showDialog(
+              barrierColor: Colors.black,
+              context: context,
+              builder: (context) =>
+                  HeadsUpCountdown(maxTime: maxTime, elapsedTime: elapsedTime),
+            );
+          },
+        );
+        break;
+      case LiveCardState.duringBreak:
+        final iconFloorMap = {
+          "to room": FeatherIcons.chevronsRight,
+          "up floor": FilcIcons.upstairs,
+          "down floor": FilcIcons.downstairs,
+          "ground floor": FilcIcons.downstairs,
+        };
+
+        final diff = liveCard.getFloorDifference();
+
+        final maxTime = liveCard.nextLesson!.start
+            .difference(liveCard.prevLesson!.end)
+            .inSeconds
+            .toDouble();
+        final elapsedTime = DateTime.now()
+                .difference(liveCard.prevLesson!.end)
+                .inSeconds
+                .toDouble() +
+            bellDelay.inSeconds.toDouble();
+
+        final showMinutes = maxTime - elapsedTime > 60;
+
+        child = LiveCardWidget(
+          key: const Key('livecard.duringBreak'),
+          title: "break".i18n,
+          icon: iconFloorMap[diff],
+          description: liveCard.nextLesson!.room != liveCard.prevLesson!.room
+              ? Text("go $diff".i18n.fill([
+                  diff != "to room"
+                      ? (liveCard.nextLesson!.getFloor() ?? 0)
+                      : liveCard.nextLesson!.room
+                ]))
+              : Text("stay".i18n),
+          nextSubject: liveCard.nextLesson?.subject.renamedTo ??
+              liveCard.nextLesson?.subject.name.capital(),
+          nextSubjectItalic: liveCard.nextLesson?.subject.isRenamed == true &&
+              settingsProvider.renamedSubjectsItalics,
+          nextRoom: diff != "to room" ? liveCard.nextLesson?.room : null,
+          progressMax: showMinutes ? maxTime / 60 : maxTime,
+          progressCurrent: showMinutes ? elapsedTime / 60 : elapsedTime,
+          progressAccuracy:
+              showMinutes ? ProgressAccuracy.minutes : ProgressAccuracy.seconds,
+          onProgressTap: () {
+            showDialog(
+              barrierColor: Colors.black,
+              context: context,
+              builder: (context) => HeadsUpCountdown(
+                maxTime: maxTime,
+                elapsedTime: elapsedTime,
+              ),
+            );
+          },
+        );
+        break;
+      case LiveCardState.afternoon:
+        child = LiveCardWidget(
+          key: const Key('livecard.afternoon'),
+          title: DateFormat("EEEE", I18n.of(context).locale.toString())
+              .format(DateTime.now())
+              .capital(),
+          icon: FeatherIcons.coffee,
+        );
+        break;
+      case LiveCardState.night:
+        child = LiveCardWidget(
+          key: const Key('livecard.night'),
+          title: DateFormat("EEEE", I18n.of(context).locale.toString())
+              .format(DateTime.now())
+              .capital(),
+          icon: FeatherIcons.moon,
+        );
+        break;
+      default:
+        child = Container();
+    }
+
+    return PageTransitionSwitcher(
+      transitionBuilder: (
+        Widget child,
+        Animation<double> primaryAnimation,
+        Animation<double> secondaryAnimation,
+      ) {
+        return SharedAxisTransition(
+          animation: primaryAnimation,
+          secondaryAnimation: secondaryAnimation,
+          transitionType: SharedAxisTransitionType.horizontal,
+          child: child,
+          fillColor: Theme.of(context).scaffoldBackgroundColor,
+        );
+      },
+      child: child,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart b/refilc_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
rename to refilc_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
index 70c006b..2dbca77
--- a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
@@ -1,57 +1,57 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "next": "Next",
-          "remaining min": "%d mins".one("%d min"),
-          "remaining sec": "%d secs".one("%d sec"),
-          "break": "Break",
-          "go to room": "Go to room %s.",
-          "go ground floor": "Go to the ground floor.",
-          "go up floor": "Go upstairs, to floor %d.",
-          "go down floor": "Go downstaris, to floor %d.",
-          "stay": "Stay in this room.",
-          "first_lesson_1": "Your first lesson will be ",
-          "first_lesson_2": " in room ",
-          "first_lesson_3": ", at ",
-          "first_lesson_4": ".",
-        },
-        "hu_hu": {
-          "next": "Következő",
-          "remaining min": "%d perc".one("%d perc"),
-          "remaining sec": "%d másodperc".one("%d másodperc"),
-          "break": "Szünet",
-          "go to room": "Menj a(z) %s terembe.",
-          "go ground floor": "Menj a földszintre.",
-          "go up floor": "Menj fel a(z) %d. emeletre.",
-          "go down floor": "Menj le a(z) %d. emeletre.",
-          "stay": "Maradj ebben a teremben.",
-          "first_lesson_1": "Az első órád ",
-          "first_lesson_2": " lesz, a ",
-          "first_lesson_3": " teremben, ",
-          "first_lesson_4": "-kor.",
-        },
-        "de_de": {
-          "next": "Nächste",
-          "remaining min": "%d Minuten".one("%d Minute"),
-          "remaining sec": "%d Sekunden".one("%d Sekunden"),
-          "break": "Pause",
-          "go to room": "Geh in den Raum %s.",
-          "go ground floor": "Geh dir Treppe hinunter.",
-          "go up floor": "Geh in die %d. Stock hinauf.",
-          "go down floor": "Geh runter in den %d. Stock.",
-          "stay": "Im Zimmer bleiben.",
-          "first_lesson_1": "Ihre erste Stunde ist ",
-          "first_lesson_2": ", in Raum ",
-          "first_lesson_3": ", um ",
-          "first_lesson_4": " Uhr.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "next": "Next",
+          "remaining min": "%d mins".one("%d min"),
+          "remaining sec": "%d secs".one("%d sec"),
+          "break": "Break",
+          "go to room": "Go to room %s.",
+          "go ground floor": "Go to the ground floor.",
+          "go up floor": "Go upstairs, to floor %d.",
+          "go down floor": "Go downstaris, to floor %d.",
+          "stay": "Stay in this room.",
+          "first_lesson_1": "Your first lesson will be ",
+          "first_lesson_2": " in room ",
+          "first_lesson_3": ", at ",
+          "first_lesson_4": ".",
+        },
+        "hu_hu": {
+          "next": "Következő",
+          "remaining min": "%d perc".one("%d perc"),
+          "remaining sec": "%d másodperc".one("%d másodperc"),
+          "break": "Szünet",
+          "go to room": "Menj a(z) %s terembe.",
+          "go ground floor": "Menj a földszintre.",
+          "go up floor": "Menj fel a(z) %d. emeletre.",
+          "go down floor": "Menj le a(z) %d. emeletre.",
+          "stay": "Maradj ebben a teremben.",
+          "first_lesson_1": "Az első órád ",
+          "first_lesson_2": " lesz, a ",
+          "first_lesson_3": " teremben, ",
+          "first_lesson_4": "-kor.",
+        },
+        "de_de": {
+          "next": "Nächste",
+          "remaining min": "%d Minuten".one("%d Minute"),
+          "remaining sec": "%d Sekunden".one("%d Sekunden"),
+          "break": "Pause",
+          "go to room": "Geh in den Raum %s.",
+          "go ground floor": "Geh dir Treppe hinunter.",
+          "go up floor": "Geh in die %d. Stock hinauf.",
+          "go down floor": "Geh runter in den %d. Stock.",
+          "stay": "Im Zimmer bleiben.",
+          "first_lesson_1": "Ihre erste Stunde ist ",
+          "first_lesson_2": ", in Raum ",
+          "first_lesson_3": ", um ",
+          "first_lesson_4": " Uhr.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card_widget.dart b/refilc_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
rename to refilc_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
index 658fcaa..f07327b
--- a/filcnaplo_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
+++ b/refilc_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
@@ -1,386 +1,386 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/common/progress_bar.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'live_card.i18n.dart';
-
-enum ProgressAccuracy { minutes, seconds }
-
-class LiveCardWidget extends StatefulWidget {
-  const LiveCardWidget({
-    Key? key,
-    this.isEvent = false,
-    this.leading,
-    this.title,
-    this.titleItalic = false,
-    this.subtitle,
-    this.icon,
-    this.description,
-    this.nextRoom,
-    this.nextSubject,
-    this.nextSubjectItalic = false,
-    this.progressCurrent,
-    this.progressMax,
-    this.progressAccuracy = ProgressAccuracy.minutes,
-    this.onProgressTap,
-    this.onTap,
-  }) : super(key: key);
-
-  final bool isEvent;
-  final String? leading;
-  final String? title;
-  final bool titleItalic;
-  final String? subtitle;
-  final IconData? icon;
-  final Widget? description;
-  final String? nextSubject;
-  final bool nextSubjectItalic;
-  final String? nextRoom;
-  final double? progressCurrent;
-  final double? progressMax;
-  final ProgressAccuracy? progressAccuracy;
-  final Function()? onProgressTap;
-  final Function()? onTap;
-
-  @override
-  State<LiveCardWidget> createState() => _LiveCardWidgetState();
-}
-
-class _LiveCardWidgetState extends State<LiveCardWidget> {
-  bool hold = false;
-
-  @override
-  Widget build(BuildContext context) {
-    return GestureDetector(
-      onLongPressDown: (_) => setState(() => hold = true),
-      onLongPressEnd: (_) => setState(() => hold = false),
-      onLongPressCancel: () => setState(() => hold = false),
-      onTap: widget.onTap,
-      child: AnimatedScale(
-        scale: hold ? 1.03 : 1.0,
-        curve: Curves.easeInOutBack,
-        duration: const Duration(milliseconds: 300),
-        child: Container(
-          margin: const EdgeInsets.symmetric(vertical: 2.0),
-          padding: const EdgeInsets.all(12.0),
-          decoration: BoxDecoration(
-            color: Theme.of(context).colorScheme.background,
-            borderRadius: BorderRadius.circular(16.0),
-            boxShadow: [
-              BoxShadow(
-                offset: const Offset(0, 21),
-                blurRadius: 23.0,
-                color: Theme.of(context).shadowColor,
-              )
-            ],
-          ),
-          child: Container(
-            padding: const EdgeInsets.symmetric(horizontal: 6.0),
-            child: OverflowBox(
-              maxHeight: 96.0,
-              child: widget.isEvent
-                  ? Column(
-                      crossAxisAlignment: CrossAxisAlignment.center,
-                      mainAxisAlignment: MainAxisAlignment.center,
-                      children: [
-                        Text(
-                          widget.title ?? 'Esemény',
-                          style: TextStyle(
-                            fontWeight: FontWeight.bold,
-                            fontSize: 24.0,
-                            color:
-                                Theme.of(context).textTheme.bodyMedium?.color,
-                            fontStyle:
-                                widget.titleItalic ? FontStyle.italic : null,
-                          ),
-                        ),
-                        Row(
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          mainAxisAlignment: MainAxisAlignment.center,
-                          children: [
-                            widget.description ??
-                                Text(
-                                  'Nincs leírás megadva.',
-                                  style: TextStyle(
-                                    fontWeight: FontWeight.w500,
-                                    fontSize: 18.0,
-                                    color: Theme.of(context)
-                                        .textTheme
-                                        .bodyMedium
-                                        ?.color,
-                                  ),
-                                ),
-                            SizedBox(
-                              height: 15,
-                              child: Container(
-                                decoration: BoxDecoration(
-                                  color: Theme.of(context)
-                                      .colorScheme
-                                      .secondary
-                                      .withOpacity(0.5),
-                                  borderRadius: const BorderRadius.all(
-                                    Radius.circular(10),
-                                  ),
-                                ),
-                                child: Padding(
-                                  padding: const EdgeInsets.all(4),
-                                  child: Icon(widget.icon),
-                                ),
-                              ),
-                            ),
-                          ],
-                        ),
-                      ],
-                    )
-                  : Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      mainAxisAlignment: MainAxisAlignment.spaceAround,
-                      children: [
-                        Expanded(
-                          child: Row(
-                            crossAxisAlignment: CrossAxisAlignment.start,
-                            children: [
-                              if (widget.leading != null)
-                                Padding(
-                                  padding: const EdgeInsets.only(
-                                      right: 12.0, top: 8.0),
-                                  child: Text(
-                                    widget.leading!,
-                                    textAlign: TextAlign.center,
-                                    style: TextStyle(
-                                      fontSize: 32.0,
-                                      fontWeight: FontWeight.w600,
-                                      color: Theme.of(context)
-                                          .colorScheme
-                                          .secondary,
-                                    ),
-                                  ),
-                                ),
-                              Expanded(
-                                child: Column(
-                                  crossAxisAlignment: CrossAxisAlignment.start,
-                                  mainAxisAlignment:
-                                      MainAxisAlignment.spaceAround,
-                                  children: [
-                                    Row(
-                                      children: [
-                                        if (widget.title != null)
-                                          Expanded(
-                                            child: Text.rich(
-                                              TextSpan(
-                                                children: [
-                                                  TextSpan(
-                                                      text: widget.title!,
-                                                      style: TextStyle(
-                                                          fontStyle: widget
-                                                                  .titleItalic
-                                                              ? FontStyle.italic
-                                                              : null)),
-                                                  if (widget.subtitle != null)
-                                                    WidgetSpan(
-                                                      child: Container(
-                                                        margin: const EdgeInsets
-                                                                .only(
-                                                            left: 6.0,
-                                                            bottom: 3.0),
-                                                        padding:
-                                                            const EdgeInsets
-                                                                    .symmetric(
-                                                                horizontal: 4.0,
-                                                                vertical: 2.0),
-                                                        decoration:
-                                                            BoxDecoration(
-                                                          color: Theme.of(
-                                                                  context)
-                                                              .colorScheme
-                                                              .secondary
-                                                              .withOpacity(.3),
-                                                          borderRadius:
-                                                              BorderRadius
-                                                                  .circular(
-                                                                      4.0),
-                                                        ),
-                                                        child: Text(
-                                                          widget.subtitle!,
-                                                          style: TextStyle(
-                                                            height: 1.2,
-                                                            fontSize: 14.0,
-                                                            fontWeight:
-                                                                FontWeight.w600,
-                                                            color: Theme.of(
-                                                                    context)
-                                                                .colorScheme
-                                                                .secondary,
-                                                          ),
-                                                        ),
-                                                      ),
-                                                    ),
-                                                ],
-                                              ),
-                                              style: const TextStyle(
-                                                  fontWeight: FontWeight.w600,
-                                                  fontSize: 22.0),
-                                              maxLines: 1,
-                                              softWrap: false,
-                                              overflow: TextOverflow.ellipsis,
-                                            ),
-                                          ),
-                                        if (widget.title != null)
-                                          const SizedBox(width: 6.0),
-                                        if (widget.icon != null)
-                                          Padding(
-                                            padding: const EdgeInsets.symmetric(
-                                                vertical: 4.0),
-                                            child: Icon(
-                                              widget.icon,
-                                              size: 26.0,
-                                              color: AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(.75),
-                                            ),
-                                          ),
-                                      ],
-                                    ),
-                                    if (widget.description != null)
-                                      DefaultTextStyle(
-                                        style: Theme.of(context)
-                                            .textTheme
-                                            .bodyMedium!
-                                            .copyWith(
-                                              fontWeight: FontWeight.w500,
-                                              fontSize: 16.0,
-                                              height: 1.0,
-                                              color: AppColors.of(context)
-                                                  .text
-                                                  .withOpacity(.75),
-                                            ),
-                                        maxLines:
-                                            !(widget.nextSubject == null &&
-                                                    widget.progressCurrent ==
-                                                        null &&
-                                                    widget.progressMax == null)
-                                                ? 1
-                                                : 2,
-                                        softWrap: false,
-                                        overflow: TextOverflow.ellipsis,
-                                        child: widget.description!,
-                                      ),
-                                  ],
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        if (!(widget.nextSubject == null &&
-                            widget.progressCurrent == null &&
-                            widget.progressMax == null))
-                          Padding(
-                            padding: const EdgeInsets.only(top: 8.0),
-                            child: Row(
-                              children: [
-                                if (widget.nextSubject != null)
-                                  const Icon(FeatherIcons.arrowRight,
-                                      size: 12.0),
-                                if (widget.nextSubject != null)
-                                  const SizedBox(width: 4.0),
-                                if (widget.nextSubject != null)
-                                  Expanded(
-                                    child: Text.rich(
-                                      TextSpan(
-                                        children: [
-                                          TextSpan(
-                                              text: widget.nextSubject!,
-                                              style: TextStyle(
-                                                  fontStyle:
-                                                      widget.nextSubjectItalic
-                                                          ? FontStyle.italic
-                                                          : null)),
-                                          if (widget.nextRoom != null)
-                                            WidgetSpan(
-                                              child: Container(
-                                                margin: const EdgeInsets.only(
-                                                    left: 4.0),
-                                                padding:
-                                                    const EdgeInsets.symmetric(
-                                                        horizontal: 3.0,
-                                                        vertical: 1.5),
-                                                decoration: BoxDecoration(
-                                                  color: Theme.of(context)
-                                                      .colorScheme
-                                                      .secondary
-                                                      .withOpacity(.25),
-                                                  borderRadius:
-                                                      BorderRadius.circular(
-                                                          4.0),
-                                                ),
-                                                child: Text(
-                                                  widget.nextRoom!,
-                                                  style: TextStyle(
-                                                    height: 1.1,
-                                                    fontSize: 11.0,
-                                                    fontWeight: FontWeight.w600,
-                                                    color: Theme.of(context)
-                                                        .colorScheme
-                                                        .secondary
-                                                        .withOpacity(.9),
-                                                  ),
-                                                ),
-                                              ),
-                                            ),
-                                        ],
-                                      ),
-                                      style: TextStyle(
-                                        color: AppColors.of(context)
-                                            .text
-                                            .withOpacity(.8),
-                                        fontWeight: FontWeight.w600,
-                                      ),
-                                      maxLines: 1,
-                                      overflow: TextOverflow.ellipsis,
-                                      softWrap: false,
-                                    ),
-                                  ),
-                                if (widget.nextRoom == null &&
-                                    widget.nextSubject == null)
-                                  const Spacer(),
-                                if (widget.progressCurrent != null &&
-                                    widget.progressMax != null)
-                                  GestureDetector(
-                                    onTap: widget.onProgressTap,
-                                    child: Container(
-                                      color: Colors.transparent,
-                                      child: Text(
-                                        "remaining ${widget.progressAccuracy == ProgressAccuracy.minutes ? 'min' : 'sec'}"
-                                            .plural((widget.progressMax! -
-                                                    widget.progressCurrent!)
-                                                .round()),
-                                        maxLines: 1,
-                                        style: TextStyle(
-                                          fontWeight: FontWeight.w500,
-                                          color: AppColors.of(context)
-                                              .text
-                                              .withOpacity(.75),
-                                        ),
-                                      ),
-                                    ),
-                                  )
-                              ],
-                            ),
-                          ),
-                        if (widget.progressCurrent != null &&
-                            widget.progressMax != null)
-                          Padding(
-                            padding: const EdgeInsets.symmetric(vertical: 4.0),
-                            child: ProgressBar(
-                                value: widget.progressCurrent! /
-                                    widget.progressMax!),
-                          )
-                      ],
-                    ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_mobile_ui/common/progress_bar.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'live_card.i18n.dart';
+
+enum ProgressAccuracy { minutes, seconds }
+
+class LiveCardWidget extends StatefulWidget {
+  const LiveCardWidget({
+    Key? key,
+    this.isEvent = false,
+    this.leading,
+    this.title,
+    this.titleItalic = false,
+    this.subtitle,
+    this.icon,
+    this.description,
+    this.nextRoom,
+    this.nextSubject,
+    this.nextSubjectItalic = false,
+    this.progressCurrent,
+    this.progressMax,
+    this.progressAccuracy = ProgressAccuracy.minutes,
+    this.onProgressTap,
+    this.onTap,
+  }) : super(key: key);
+
+  final bool isEvent;
+  final String? leading;
+  final String? title;
+  final bool titleItalic;
+  final String? subtitle;
+  final IconData? icon;
+  final Widget? description;
+  final String? nextSubject;
+  final bool nextSubjectItalic;
+  final String? nextRoom;
+  final double? progressCurrent;
+  final double? progressMax;
+  final ProgressAccuracy? progressAccuracy;
+  final Function()? onProgressTap;
+  final Function()? onTap;
+
+  @override
+  State<LiveCardWidget> createState() => _LiveCardWidgetState();
+}
+
+class _LiveCardWidgetState extends State<LiveCardWidget> {
+  bool hold = false;
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(
+      onLongPressDown: (_) => setState(() => hold = true),
+      onLongPressEnd: (_) => setState(() => hold = false),
+      onLongPressCancel: () => setState(() => hold = false),
+      onTap: widget.onTap,
+      child: AnimatedScale(
+        scale: hold ? 1.03 : 1.0,
+        curve: Curves.easeInOutBack,
+        duration: const Duration(milliseconds: 300),
+        child: Container(
+          margin: const EdgeInsets.symmetric(vertical: 2.0),
+          padding: const EdgeInsets.all(12.0),
+          decoration: BoxDecoration(
+            color: Theme.of(context).colorScheme.background,
+            borderRadius: BorderRadius.circular(16.0),
+            boxShadow: [
+              BoxShadow(
+                offset: const Offset(0, 21),
+                blurRadius: 23.0,
+                color: Theme.of(context).shadowColor,
+              )
+            ],
+          ),
+          child: Container(
+            padding: const EdgeInsets.symmetric(horizontal: 6.0),
+            child: OverflowBox(
+              maxHeight: 96.0,
+              child: widget.isEvent
+                  ? Column(
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: [
+                        Text(
+                          widget.title ?? 'Esemény',
+                          style: TextStyle(
+                            fontWeight: FontWeight.bold,
+                            fontSize: 24.0,
+                            color:
+                                Theme.of(context).textTheme.bodyMedium?.color,
+                            fontStyle:
+                                widget.titleItalic ? FontStyle.italic : null,
+                          ),
+                        ),
+                        Row(
+                          crossAxisAlignment: CrossAxisAlignment.center,
+                          mainAxisAlignment: MainAxisAlignment.center,
+                          children: [
+                            widget.description ??
+                                Text(
+                                  'Nincs leírás megadva.',
+                                  style: TextStyle(
+                                    fontWeight: FontWeight.w500,
+                                    fontSize: 18.0,
+                                    color: Theme.of(context)
+                                        .textTheme
+                                        .bodyMedium
+                                        ?.color,
+                                  ),
+                                ),
+                            SizedBox(
+                              height: 15,
+                              child: Container(
+                                decoration: BoxDecoration(
+                                  color: Theme.of(context)
+                                      .colorScheme
+                                      .secondary
+                                      .withOpacity(0.5),
+                                  borderRadius: const BorderRadius.all(
+                                    Radius.circular(10),
+                                  ),
+                                ),
+                                child: Padding(
+                                  padding: const EdgeInsets.all(4),
+                                  child: Icon(widget.icon),
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
+                      ],
+                    )
+                  : Column(
+                      crossAxisAlignment: CrossAxisAlignment.start,
+                      mainAxisAlignment: MainAxisAlignment.spaceAround,
+                      children: [
+                        Expanded(
+                          child: Row(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              if (widget.leading != null)
+                                Padding(
+                                  padding: const EdgeInsets.only(
+                                      right: 12.0, top: 8.0),
+                                  child: Text(
+                                    widget.leading!,
+                                    textAlign: TextAlign.center,
+                                    style: TextStyle(
+                                      fontSize: 32.0,
+                                      fontWeight: FontWeight.w600,
+                                      color: Theme.of(context)
+                                          .colorScheme
+                                          .secondary,
+                                    ),
+                                  ),
+                                ),
+                              Expanded(
+                                child: Column(
+                                  crossAxisAlignment: CrossAxisAlignment.start,
+                                  mainAxisAlignment:
+                                      MainAxisAlignment.spaceAround,
+                                  children: [
+                                    Row(
+                                      children: [
+                                        if (widget.title != null)
+                                          Expanded(
+                                            child: Text.rich(
+                                              TextSpan(
+                                                children: [
+                                                  TextSpan(
+                                                      text: widget.title!,
+                                                      style: TextStyle(
+                                                          fontStyle: widget
+                                                                  .titleItalic
+                                                              ? FontStyle.italic
+                                                              : null)),
+                                                  if (widget.subtitle != null)
+                                                    WidgetSpan(
+                                                      child: Container(
+                                                        margin: const EdgeInsets
+                                                            .only(
+                                                            left: 6.0,
+                                                            bottom: 3.0),
+                                                        padding:
+                                                            const EdgeInsets
+                                                                .symmetric(
+                                                                horizontal: 4.0,
+                                                                vertical: 2.0),
+                                                        decoration:
+                                                            BoxDecoration(
+                                                          color: Theme.of(
+                                                                  context)
+                                                              .colorScheme
+                                                              .secondary
+                                                              .withOpacity(.3),
+                                                          borderRadius:
+                                                              BorderRadius
+                                                                  .circular(
+                                                                      4.0),
+                                                        ),
+                                                        child: Text(
+                                                          widget.subtitle!,
+                                                          style: TextStyle(
+                                                            height: 1.2,
+                                                            fontSize: 14.0,
+                                                            fontWeight:
+                                                                FontWeight.w600,
+                                                            color: Theme.of(
+                                                                    context)
+                                                                .colorScheme
+                                                                .secondary,
+                                                          ),
+                                                        ),
+                                                      ),
+                                                    ),
+                                                ],
+                                              ),
+                                              style: const TextStyle(
+                                                  fontWeight: FontWeight.w600,
+                                                  fontSize: 22.0),
+                                              maxLines: 1,
+                                              softWrap: false,
+                                              overflow: TextOverflow.ellipsis,
+                                            ),
+                                          ),
+                                        if (widget.title != null)
+                                          const SizedBox(width: 6.0),
+                                        if (widget.icon != null)
+                                          Padding(
+                                            padding: const EdgeInsets.symmetric(
+                                                vertical: 4.0),
+                                            child: Icon(
+                                              widget.icon,
+                                              size: 26.0,
+                                              color: AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.75),
+                                            ),
+                                          ),
+                                      ],
+                                    ),
+                                    if (widget.description != null)
+                                      DefaultTextStyle(
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .bodyMedium!
+                                            .copyWith(
+                                              fontWeight: FontWeight.w500,
+                                              fontSize: 16.0,
+                                              height: 1.0,
+                                              color: AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.75),
+                                            ),
+                                        maxLines:
+                                            !(widget.nextSubject == null &&
+                                                    widget.progressCurrent ==
+                                                        null &&
+                                                    widget.progressMax == null)
+                                                ? 1
+                                                : 2,
+                                        softWrap: false,
+                                        overflow: TextOverflow.ellipsis,
+                                        child: widget.description!,
+                                      ),
+                                  ],
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                        if (!(widget.nextSubject == null &&
+                            widget.progressCurrent == null &&
+                            widget.progressMax == null))
+                          Padding(
+                            padding: const EdgeInsets.only(top: 8.0),
+                            child: Row(
+                              children: [
+                                if (widget.nextSubject != null)
+                                  const Icon(FeatherIcons.arrowRight,
+                                      size: 12.0),
+                                if (widget.nextSubject != null)
+                                  const SizedBox(width: 4.0),
+                                if (widget.nextSubject != null)
+                                  Expanded(
+                                    child: Text.rich(
+                                      TextSpan(
+                                        children: [
+                                          TextSpan(
+                                              text: widget.nextSubject!,
+                                              style: TextStyle(
+                                                  fontStyle:
+                                                      widget.nextSubjectItalic
+                                                          ? FontStyle.italic
+                                                          : null)),
+                                          if (widget.nextRoom != null)
+                                            WidgetSpan(
+                                              child: Container(
+                                                margin: const EdgeInsets.only(
+                                                    left: 4.0),
+                                                padding:
+                                                    const EdgeInsets.symmetric(
+                                                        horizontal: 3.0,
+                                                        vertical: 1.5),
+                                                decoration: BoxDecoration(
+                                                  color: Theme.of(context)
+                                                      .colorScheme
+                                                      .secondary
+                                                      .withOpacity(.25),
+                                                  borderRadius:
+                                                      BorderRadius.circular(
+                                                          4.0),
+                                                ),
+                                                child: Text(
+                                                  widget.nextRoom!,
+                                                  style: TextStyle(
+                                                    height: 1.1,
+                                                    fontSize: 11.0,
+                                                    fontWeight: FontWeight.w600,
+                                                    color: Theme.of(context)
+                                                        .colorScheme
+                                                        .secondary
+                                                        .withOpacity(.9),
+                                                  ),
+                                                ),
+                                              ),
+                                            ),
+                                        ],
+                                      ),
+                                      style: TextStyle(
+                                        color: AppColors.of(context)
+                                            .text
+                                            .withOpacity(.8),
+                                        fontWeight: FontWeight.w600,
+                                      ),
+                                      maxLines: 1,
+                                      overflow: TextOverflow.ellipsis,
+                                      softWrap: false,
+                                    ),
+                                  ),
+                                if (widget.nextRoom == null &&
+                                    widget.nextSubject == null)
+                                  const Spacer(),
+                                if (widget.progressCurrent != null &&
+                                    widget.progressMax != null)
+                                  GestureDetector(
+                                    onTap: widget.onProgressTap,
+                                    child: Container(
+                                      color: Colors.transparent,
+                                      child: Text(
+                                        "remaining ${widget.progressAccuracy == ProgressAccuracy.minutes ? 'min' : 'sec'}"
+                                            .plural((widget.progressMax! -
+                                                    widget.progressCurrent!)
+                                                .round()),
+                                        maxLines: 1,
+                                        style: TextStyle(
+                                          fontWeight: FontWeight.w500,
+                                          color: AppColors.of(context)
+                                              .text
+                                              .withOpacity(.75),
+                                        ),
+                                      ),
+                                    ),
+                                  )
+                              ],
+                            ),
+                          ),
+                        if (widget.progressCurrent != null &&
+                            widget.progressMax != null)
+                          Padding(
+                            padding: const EdgeInsets.symmetric(vertical: 4.0),
+                            child: ProgressBar(
+                                value: widget.progressCurrent! /
+                                    widget.progressMax!),
+                          )
+                      ],
+                    ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/home/particle.dart b/refilc_mobile_ui/lib/pages/home/particle.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/home/particle.dart
rename to refilc_mobile_ui/lib/pages/home/particle.dart
index d7d85c7..5c47a5d
--- a/filcnaplo_mobile_ui/lib/pages/home/particle.dart
+++ b/refilc_mobile_ui/lib/pages/home/particle.dart
@@ -1,438 +1,438 @@
-// MIT License
-
-// Copyright (c) 2018 Norbert Kozsir
-
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-// ignore_for_file: invalid_use_of_protected_member
-
-import 'dart:math';
-import 'package:flutter/material.dart';
-
-typedef ParticleBuilder = Particle Function(int index);
-
-abstract class Particle {
-  void paint(Canvas canvas, Size size, double progress, int seed);
-}
-
-class FourRandomSlotParticle extends Particle {
-  final List<Particle> children;
-
-  final double relativeDistanceToMiddle;
-
-  FourRandomSlotParticle({required this.children, this.relativeDistanceToMiddle = 2.0});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, int seed) {
-    Random random = Random(seed);
-    int side = 0;
-    for (Particle particle in children) {
-      PositionedParticle(
-        position: sideToOffset(side, size, random) * relativeDistanceToMiddle,
-        child: particle,
-      ).paint(canvas, size, progress, seed);
-      side++;
-    }
-  }
-
-  Offset sideToOffset(int side, Size size, Random random) {
-    if (side == 0) {
-      return Offset(-random.nextDouble() * (size.width / 2), -random.nextDouble() * (size.height / 2));
-    } else if (side == 1) {
-      return Offset(random.nextDouble() * (size.width / 2), -random.nextDouble() * (size.height / 2));
-    } else if (side == 2) {
-      return Offset(random.nextDouble() * (size.width / 2), random.nextDouble() * (size.height / 2));
-    } else if (side == 3) {
-      return Offset(-random.nextDouble() * (size.width / 2), random.nextDouble() * (size.height / 2));
-    } else {
-      throw Exception();
-    }
-  }
-
-  double randomOffset(Random random, int range) {
-    return range / 2 - random.nextInt(range);
-  }
-}
-
-class PoppingCircle extends Particle {
-  final Color color;
-
-  PoppingCircle({required this.color});
-
-  final double radius = 3.0;
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    if (progress < 0.5) {
-      canvas.drawCircle(
-          Offset.zero,
-          radius + (progress * 8),
-          Paint()
-            ..color = color
-            ..style = PaintingStyle.stroke
-            ..strokeWidth = 5.0 - progress * 2);
-    } else {
-      CircleMirror(
-        numberOfParticles: 4,
-        child: AnimatedPositionedParticle(
-            begin: const Offset(0.0, 5.0),
-            end: const Offset(0.0, 15.0),
-            child: FadingRect(
-              color: color,
-              height: 7.0,
-              width: 2.0,
-            )),
-        initialRotation: pi / 4,
-      ).paint(canvas, size, progress, seed);
-    }
-  }
-}
-
-class Firework extends Particle {
-  @override
-  void paint(Canvas canvas, Size size, double progress, int seed) {
-    FourRandomSlotParticle(children: [
-      IntervalParticle(
-        interval: const Interval(0.0, 0.5, curve: Curves.easeIn),
-        child: PoppingCircle(
-          color: Colors.deepOrangeAccent,
-        ),
-      ),
-      IntervalParticle(
-        interval: const Interval(0.2, 0.5, curve: Curves.easeIn),
-        child: PoppingCircle(
-          color: Colors.green,
-        ),
-      ),
-      IntervalParticle(
-        interval: const Interval(0.4, 0.8, curve: Curves.easeIn),
-        child: PoppingCircle(
-          color: Colors.indigo,
-        ),
-      ),
-      IntervalParticle(
-        interval: const Interval(0.5, 1.0, curve: Curves.easeIn),
-        child: PoppingCircle(
-          color: Colors.teal,
-        ),
-      ),
-    ]).paint(canvas, size, progress, seed);
-  }
-}
-
-/// Mirrors a given particle around a circle.
-///
-/// When using the default constructor you specify one [Particle], this particle
-/// is going to be used on its own, this implies that
-/// all mirrored particles are identical (expect for the rotation around the circle)
-class CircleMirror extends Particle {
-  final ParticleBuilder particleBuilder;
-
-  final double initialRotation;
-
-  final int numberOfParticles;
-
-  CircleMirror.builder({required this.particleBuilder, required this.initialRotation, required this.numberOfParticles});
-
-  CircleMirror({required Particle child, required this.initialRotation, required this.numberOfParticles}) : particleBuilder = ((index) => child);
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    canvas.save();
-    canvas.rotate(initialRotation);
-    for (int i = 0; i < numberOfParticles; i++) {
-      particleBuilder(i).paint(canvas, size, progress, seed);
-      canvas.rotate(pi / (numberOfParticles / 2));
-    }
-    canvas.restore();
-  }
-}
-
-/// Mirrors a given particle around a circle.
-///
-/// When using the default constructor you specify one [Particle], this particle
-/// is going to be used on its own, this implies that
-/// all mirrored particles are identical (expect for the rotation around the circle)
-class RectangleMirror extends Particle {
-  final ParticleBuilder particleBuilder;
-
-  /// Position of the first particle on the rect
-  final double initialDistance;
-
-  final int numberOfParticles;
-
-  RectangleMirror.builder({required this.particleBuilder, required this.initialDistance, required this.numberOfParticles});
-
-  RectangleMirror({required Particle child, required this.initialDistance, required this.numberOfParticles})
-      : particleBuilder = ((index) => child);
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    canvas.save();
-    double totalLength = size.width * 2 + size.height * 2;
-    double distanceBetweenParticles = totalLength / numberOfParticles;
-
-    bool onHorizontalAxis = true;
-    int side = 0;
-
-    assert((distanceBetweenParticles * numberOfParticles).round() == totalLength.round());
-
-    canvas.translate(-size.width / 2, -size.height / 2);
-
-    double currentDistance = initialDistance;
-    for (int i = 0; i < numberOfParticles; i++) {
-      while (true) {
-        if (onHorizontalAxis ? currentDistance > size.width : currentDistance > size.height) {
-          currentDistance -= onHorizontalAxis ? size.width : size.height;
-          onHorizontalAxis = !onHorizontalAxis;
-          side = (++side) % 4;
-        } else {
-          if (side == 0) {
-            assert(onHorizontalAxis);
-            moveTo(canvas, size, 0, currentDistance, 0.0, () {
-              particleBuilder(i).paint(canvas, size, progress, seed);
-            });
-          } else if (side == 1) {
-            assert(!onHorizontalAxis);
-            moveTo(canvas, size, 1, size.width, currentDistance, () {
-              particleBuilder(i).paint(canvas, size, progress, seed);
-            });
-          } else if (side == 2) {
-            assert(onHorizontalAxis);
-            moveTo(canvas, size, 2, size.width - currentDistance, size.height, () {
-              particleBuilder(i).paint(canvas, size, progress, seed);
-            });
-          } else if (side == 3) {
-            assert(!onHorizontalAxis);
-            moveTo(canvas, size, 3, 0.0, size.height - currentDistance, () {
-              particleBuilder(i).paint(canvas, size, progress, seed);
-            });
-          }
-          break;
-        }
-      }
-      currentDistance += distanceBetweenParticles;
-    }
-
-    canvas.restore();
-  }
-
-  void moveTo(Canvas canvas, Size size, int side, double x, double y, VoidCallback painter) {
-    canvas.save();
-    canvas.translate(x, y);
-    canvas.rotate(-atan2(size.width / 2 - x, size.height / 2 - y));
-    painter();
-    canvas.restore();
-  }
-}
-
-/// Offsets a child by a given [Offset]
-class PositionedParticle extends Particle {
-  PositionedParticle({required this.position, required this.child});
-
-  final Particle child;
-
-  final Offset position;
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    canvas.save();
-    canvas.translate(position.dx, position.dy);
-    child.paint(canvas, size, progress, seed);
-    canvas.restore();
-  }
-}
-
-/// Animates a childs position based on a Tween<Offset>
-class AnimatedPositionedParticle extends Particle {
-  AnimatedPositionedParticle({required Offset begin, required Offset end, required this.child}) : offsetTween = Tween<Offset>(begin: begin, end: end);
-
-  final Particle child;
-
-  final Tween<Offset> offsetTween;
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    canvas.save();
-    canvas.translate(offsetTween.lerp(progress).dx, offsetTween.lerp(progress).dy);
-    child.paint(canvas, size, progress, seed);
-    canvas.restore();
-  }
-}
-
-/// Specifies an [Interval] for its child.
-///
-/// Instead of applying a curve the the input parameters of the paint method,
-/// apply it with this Particle.
-///
-/// If you want you child to only animate from 0.0 - 0.5 (relative), specify an [Interval] with those values.
-class IntervalParticle extends Particle {
-  final Interval interval;
-
-  final Particle child;
-
-  IntervalParticle({required this.child, required this.interval});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    if (progress < interval.begin || progress > interval.end) return;
-    child.paint(canvas, size, interval.transform(progress), seed);
-  }
-}
-
-/// Does nothing else than holding a list of particles and painting them in that order
-class CompositeParticle extends Particle {
-  final List<Particle> children;
-
-  CompositeParticle({required this.children});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    for (Particle particle in children) {
-      particle.paint(canvas, size, progress, seed);
-    }
-  }
-}
-
-/// A particle which rotates the child.
-///
-/// Does not animate.
-class RotationParticle extends Particle {
-  final Particle child;
-
-  final double rotation;
-
-  RotationParticle({required this.child, required this.rotation});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, int seed) {
-    canvas.save();
-    canvas.rotate(rotation);
-    child.paint(canvas, size, progress, seed);
-    canvas.restore();
-  }
-}
-
-/// A particle which rotates a child along a given [Tween]
-class AnimatedRotationParticle extends Particle {
-  final Particle child;
-
-  final Tween<double> rotation;
-
-  AnimatedRotationParticle({required this.child, required double begin, required double end}) : rotation = Tween<double>(begin: begin, end: end);
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, int seed) {
-    canvas.save();
-    canvas.rotate(rotation.lerp(progress));
-    child.paint(canvas, size, progress, seed);
-    canvas.restore();
-  }
-}
-
-/// Geometry
-///
-/// These are some basic geometric classes which also fade out as time goes on.
-/// Each primitive should draw itself at the origin. If the orientation matters it should be directed to the top
-/// (negative y)
-///
-/// A rectangle which also fades out over time.
-class FadingRect extends Particle {
-  final Color color;
-  final double width;
-  final double height;
-
-  FadingRect({required this.color, required this.width, required this.height});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    canvas.drawRect(Rect.fromLTWH(0.0, 0.0, width, height), Paint()..color = color.withOpacity(1 - progress));
-  }
-}
-
-/// A circle which fades out over time
-class FadingCircle extends Particle {
-  final Color color;
-  final double radius;
-
-  FadingCircle({required this.color, required this.radius});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, seed) {
-    canvas.drawCircle(Offset.zero, radius, Paint()..color = color.withOpacity(1 - progress));
-  }
-}
-
-/// A triangle which also fades out over time
-class FadingTriangle extends Particle {
-  /// This controls the shape of the triangle.
-  ///
-  /// Value between 0 and 1
-  final double variation;
-
-  final Color color;
-
-  /// The size of the base side of the triangle.
-  final double baseSize;
-
-  /// This is the factor of how much bigger then length than the width is
-  final double heightToBaseFactor;
-
-  FadingTriangle({required this.variation, required this.color, required this.baseSize, required this.heightToBaseFactor});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, int seed) {
-    Path path = Path();
-    path.moveTo(0.0, 0.0);
-    path.lineTo(baseSize * variation, baseSize * heightToBaseFactor);
-    path.lineTo(baseSize, 0.0);
-    path.close();
-    canvas.drawPath(path, Paint()..color = color.withOpacity(1 - progress));
-  }
-}
-
-/// An ugly looking "snake"
-///
-/// See for yourself
-class FadingSnake extends Particle {
-  final double width;
-  final double segmentLength;
-  final int segments;
-  final double curvyness;
-
-  final Color color;
-
-  FadingSnake({required this.width, required this.segmentLength, required this.segments, required this.curvyness, required this.color});
-
-  @override
-  void paint(Canvas canvas, Size size, double progress, int seed) {
-    canvas.save();
-    canvas.rotate(pi / 6);
-    Path path = Path();
-    for (int i = 0; i < segments; i++) {
-      path.quadraticBezierTo(curvyness * i, segmentLength * (i + 1), curvyness * (i + 1), segmentLength * (i + 1));
-    }
-    for (int i = segments - 1; i >= 0; i--) {
-      path.quadraticBezierTo(curvyness * (i + 1), segmentLength * i - curvyness, curvyness * i, segmentLength * i - curvyness);
-    }
-    path.close();
-    canvas.drawPath(path, Paint()..color = color);
-    canvas.restore();
-  }
-}
+// MIT License
+
+// Copyright (c) 2018 Norbert Kozsir
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// ignore_for_file: invalid_use_of_protected_member
+
+import 'dart:math';
+import 'package:flutter/material.dart';
+
+typedef ParticleBuilder = Particle Function(int index);
+
+abstract class Particle {
+  void paint(Canvas canvas, Size size, double progress, int seed);
+}
+
+class FourRandomSlotParticle extends Particle {
+  final List<Particle> children;
+
+  final double relativeDistanceToMiddle;
+
+  FourRandomSlotParticle({required this.children, this.relativeDistanceToMiddle = 2.0});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, int seed) {
+    Random random = Random(seed);
+    int side = 0;
+    for (Particle particle in children) {
+      PositionedParticle(
+        position: sideToOffset(side, size, random) * relativeDistanceToMiddle,
+        child: particle,
+      ).paint(canvas, size, progress, seed);
+      side++;
+    }
+  }
+
+  Offset sideToOffset(int side, Size size, Random random) {
+    if (side == 0) {
+      return Offset(-random.nextDouble() * (size.width / 2), -random.nextDouble() * (size.height / 2));
+    } else if (side == 1) {
+      return Offset(random.nextDouble() * (size.width / 2), -random.nextDouble() * (size.height / 2));
+    } else if (side == 2) {
+      return Offset(random.nextDouble() * (size.width / 2), random.nextDouble() * (size.height / 2));
+    } else if (side == 3) {
+      return Offset(-random.nextDouble() * (size.width / 2), random.nextDouble() * (size.height / 2));
+    } else {
+      throw Exception();
+    }
+  }
+
+  double randomOffset(Random random, int range) {
+    return range / 2 - random.nextInt(range);
+  }
+}
+
+class PoppingCircle extends Particle {
+  final Color color;
+
+  PoppingCircle({required this.color});
+
+  final double radius = 3.0;
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    if (progress < 0.5) {
+      canvas.drawCircle(
+          Offset.zero,
+          radius + (progress * 8),
+          Paint()
+            ..color = color
+            ..style = PaintingStyle.stroke
+            ..strokeWidth = 5.0 - progress * 2);
+    } else {
+      CircleMirror(
+        numberOfParticles: 4,
+        child: AnimatedPositionedParticle(
+            begin: const Offset(0.0, 5.0),
+            end: const Offset(0.0, 15.0),
+            child: FadingRect(
+              color: color,
+              height: 7.0,
+              width: 2.0,
+            )),
+        initialRotation: pi / 4,
+      ).paint(canvas, size, progress, seed);
+    }
+  }
+}
+
+class Firework extends Particle {
+  @override
+  void paint(Canvas canvas, Size size, double progress, int seed) {
+    FourRandomSlotParticle(children: [
+      IntervalParticle(
+        interval: const Interval(0.0, 0.5, curve: Curves.easeIn),
+        child: PoppingCircle(
+          color: Colors.deepOrangeAccent,
+        ),
+      ),
+      IntervalParticle(
+        interval: const Interval(0.2, 0.5, curve: Curves.easeIn),
+        child: PoppingCircle(
+          color: Colors.green,
+        ),
+      ),
+      IntervalParticle(
+        interval: const Interval(0.4, 0.8, curve: Curves.easeIn),
+        child: PoppingCircle(
+          color: Colors.indigo,
+        ),
+      ),
+      IntervalParticle(
+        interval: const Interval(0.5, 1.0, curve: Curves.easeIn),
+        child: PoppingCircle(
+          color: Colors.teal,
+        ),
+      ),
+    ]).paint(canvas, size, progress, seed);
+  }
+}
+
+/// Mirrors a given particle around a circle.
+///
+/// When using the default constructor you specify one [Particle], this particle
+/// is going to be used on its own, this implies that
+/// all mirrored particles are identical (expect for the rotation around the circle)
+class CircleMirror extends Particle {
+  final ParticleBuilder particleBuilder;
+
+  final double initialRotation;
+
+  final int numberOfParticles;
+
+  CircleMirror.builder({required this.particleBuilder, required this.initialRotation, required this.numberOfParticles});
+
+  CircleMirror({required Particle child, required this.initialRotation, required this.numberOfParticles}) : particleBuilder = ((index) => child);
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    canvas.save();
+    canvas.rotate(initialRotation);
+    for (int i = 0; i < numberOfParticles; i++) {
+      particleBuilder(i).paint(canvas, size, progress, seed);
+      canvas.rotate(pi / (numberOfParticles / 2));
+    }
+    canvas.restore();
+  }
+}
+
+/// Mirrors a given particle around a circle.
+///
+/// When using the default constructor you specify one [Particle], this particle
+/// is going to be used on its own, this implies that
+/// all mirrored particles are identical (expect for the rotation around the circle)
+class RectangleMirror extends Particle {
+  final ParticleBuilder particleBuilder;
+
+  /// Position of the first particle on the rect
+  final double initialDistance;
+
+  final int numberOfParticles;
+
+  RectangleMirror.builder({required this.particleBuilder, required this.initialDistance, required this.numberOfParticles});
+
+  RectangleMirror({required Particle child, required this.initialDistance, required this.numberOfParticles})
+      : particleBuilder = ((index) => child);
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    canvas.save();
+    double totalLength = size.width * 2 + size.height * 2;
+    double distanceBetweenParticles = totalLength / numberOfParticles;
+
+    bool onHorizontalAxis = true;
+    int side = 0;
+
+    assert((distanceBetweenParticles * numberOfParticles).round() == totalLength.round());
+
+    canvas.translate(-size.width / 2, -size.height / 2);
+
+    double currentDistance = initialDistance;
+    for (int i = 0; i < numberOfParticles; i++) {
+      while (true) {
+        if (onHorizontalAxis ? currentDistance > size.width : currentDistance > size.height) {
+          currentDistance -= onHorizontalAxis ? size.width : size.height;
+          onHorizontalAxis = !onHorizontalAxis;
+          side = (++side) % 4;
+        } else {
+          if (side == 0) {
+            assert(onHorizontalAxis);
+            moveTo(canvas, size, 0, currentDistance, 0.0, () {
+              particleBuilder(i).paint(canvas, size, progress, seed);
+            });
+          } else if (side == 1) {
+            assert(!onHorizontalAxis);
+            moveTo(canvas, size, 1, size.width, currentDistance, () {
+              particleBuilder(i).paint(canvas, size, progress, seed);
+            });
+          } else if (side == 2) {
+            assert(onHorizontalAxis);
+            moveTo(canvas, size, 2, size.width - currentDistance, size.height, () {
+              particleBuilder(i).paint(canvas, size, progress, seed);
+            });
+          } else if (side == 3) {
+            assert(!onHorizontalAxis);
+            moveTo(canvas, size, 3, 0.0, size.height - currentDistance, () {
+              particleBuilder(i).paint(canvas, size, progress, seed);
+            });
+          }
+          break;
+        }
+      }
+      currentDistance += distanceBetweenParticles;
+    }
+
+    canvas.restore();
+  }
+
+  void moveTo(Canvas canvas, Size size, int side, double x, double y, VoidCallback painter) {
+    canvas.save();
+    canvas.translate(x, y);
+    canvas.rotate(-atan2(size.width / 2 - x, size.height / 2 - y));
+    painter();
+    canvas.restore();
+  }
+}
+
+/// Offsets a child by a given [Offset]
+class PositionedParticle extends Particle {
+  PositionedParticle({required this.position, required this.child});
+
+  final Particle child;
+
+  final Offset position;
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    canvas.save();
+    canvas.translate(position.dx, position.dy);
+    child.paint(canvas, size, progress, seed);
+    canvas.restore();
+  }
+}
+
+/// Animates a childs position based on a Tween<Offset>
+class AnimatedPositionedParticle extends Particle {
+  AnimatedPositionedParticle({required Offset begin, required Offset end, required this.child}) : offsetTween = Tween<Offset>(begin: begin, end: end);
+
+  final Particle child;
+
+  final Tween<Offset> offsetTween;
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    canvas.save();
+    canvas.translate(offsetTween.lerp(progress).dx, offsetTween.lerp(progress).dy);
+    child.paint(canvas, size, progress, seed);
+    canvas.restore();
+  }
+}
+
+/// Specifies an [Interval] for its child.
+///
+/// Instead of applying a curve the the input parameters of the paint method,
+/// apply it with this Particle.
+///
+/// If you want you child to only animate from 0.0 - 0.5 (relative), specify an [Interval] with those values.
+class IntervalParticle extends Particle {
+  final Interval interval;
+
+  final Particle child;
+
+  IntervalParticle({required this.child, required this.interval});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    if (progress < interval.begin || progress > interval.end) return;
+    child.paint(canvas, size, interval.transform(progress), seed);
+  }
+}
+
+/// Does nothing else than holding a list of particles and painting them in that order
+class CompositeParticle extends Particle {
+  final List<Particle> children;
+
+  CompositeParticle({required this.children});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    for (Particle particle in children) {
+      particle.paint(canvas, size, progress, seed);
+    }
+  }
+}
+
+/// A particle which rotates the child.
+///
+/// Does not animate.
+class RotationParticle extends Particle {
+  final Particle child;
+
+  final double rotation;
+
+  RotationParticle({required this.child, required this.rotation});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, int seed) {
+    canvas.save();
+    canvas.rotate(rotation);
+    child.paint(canvas, size, progress, seed);
+    canvas.restore();
+  }
+}
+
+/// A particle which rotates a child along a given [Tween]
+class AnimatedRotationParticle extends Particle {
+  final Particle child;
+
+  final Tween<double> rotation;
+
+  AnimatedRotationParticle({required this.child, required double begin, required double end}) : rotation = Tween<double>(begin: begin, end: end);
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, int seed) {
+    canvas.save();
+    canvas.rotate(rotation.lerp(progress));
+    child.paint(canvas, size, progress, seed);
+    canvas.restore();
+  }
+}
+
+/// Geometry
+///
+/// These are some basic geometric classes which also fade out as time goes on.
+/// Each primitive should draw itself at the origin. If the orientation matters it should be directed to the top
+/// (negative y)
+///
+/// A rectangle which also fades out over time.
+class FadingRect extends Particle {
+  final Color color;
+  final double width;
+  final double height;
+
+  FadingRect({required this.color, required this.width, required this.height});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    canvas.drawRect(Rect.fromLTWH(0.0, 0.0, width, height), Paint()..color = color.withOpacity(1 - progress));
+  }
+}
+
+/// A circle which fades out over time
+class FadingCircle extends Particle {
+  final Color color;
+  final double radius;
+
+  FadingCircle({required this.color, required this.radius});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, seed) {
+    canvas.drawCircle(Offset.zero, radius, Paint()..color = color.withOpacity(1 - progress));
+  }
+}
+
+/// A triangle which also fades out over time
+class FadingTriangle extends Particle {
+  /// This controls the shape of the triangle.
+  ///
+  /// Value between 0 and 1
+  final double variation;
+
+  final Color color;
+
+  /// The size of the base side of the triangle.
+  final double baseSize;
+
+  /// This is the factor of how much bigger then length than the width is
+  final double heightToBaseFactor;
+
+  FadingTriangle({required this.variation, required this.color, required this.baseSize, required this.heightToBaseFactor});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, int seed) {
+    Path path = Path();
+    path.moveTo(0.0, 0.0);
+    path.lineTo(baseSize * variation, baseSize * heightToBaseFactor);
+    path.lineTo(baseSize, 0.0);
+    path.close();
+    canvas.drawPath(path, Paint()..color = color.withOpacity(1 - progress));
+  }
+}
+
+/// An ugly looking "snake"
+///
+/// See for yourself
+class FadingSnake extends Particle {
+  final double width;
+  final double segmentLength;
+  final int segments;
+  final double curvyness;
+
+  final Color color;
+
+  FadingSnake({required this.width, required this.segmentLength, required this.segments, required this.curvyness, required this.color});
+
+  @override
+  void paint(Canvas canvas, Size size, double progress, int seed) {
+    canvas.save();
+    canvas.rotate(pi / 6);
+    Path path = Path();
+    for (int i = 0; i < segments; i++) {
+      path.quadraticBezierTo(curvyness * i, segmentLength * (i + 1), curvyness * (i + 1), segmentLength * (i + 1));
+    }
+    for (int i = segments - 1; i >= 0; i--) {
+      path.quadraticBezierTo(curvyness * (i + 1), segmentLength * i - curvyness, curvyness * i, segmentLength * i - curvyness);
+    }
+    path.close();
+    canvas.drawPath(path, Paint()..color = color);
+    canvas.restore();
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/messages/messages_page.dart b/refilc_mobile_ui/lib/pages/messages/messages_page.dart
old mode 100755
new mode 100644
similarity index 86%
rename from filcnaplo_mobile_ui/lib/pages/messages/messages_page.dart
rename to refilc_mobile_ui/lib/pages/messages/messages_page.dart
index c064bef..73c5484
--- a/filcnaplo_mobile_ui/lib/pages/messages/messages_page.dart
+++ b/refilc_mobile_ui/lib/pages/messages/messages_page.dart
@@ -1,193 +1,193 @@
-import 'dart:math';
-
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/message.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo/ui/filter/sort.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/message/message_viewable.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'messages_page.i18n.dart';
-
-class MessagesPage extends StatefulWidget {
-  const MessagesPage({Key? key}) : super(key: key);
-
-  @override
-  _MessagesPageState createState() => _MessagesPageState();
-}
-
-class _MessagesPageState extends State<MessagesPage>
-    with TickerProviderStateMixin {
-  late UserProvider user;
-  late MessageProvider messageProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late TabController tabController;
-
-  @override
-  void initState() {
-    super.initState();
-
-    tabController = TabController(length: 4, vsync: this);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    messageProvider = Provider.of<MessageProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 12.0),
-        child: NestedScrollView(
-          physics: const BouncingScrollPhysics(
-              parent: AlwaysScrollableScrollPhysics()),
-          headerSliverBuilder: (context, _) => [
-            SliverAppBar(
-              pinned: true,
-              floating: false,
-              snap: false,
-              centerTitle: false,
-              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-              actions: [
-                // Profile Icon
-                Padding(
-                  padding: const EdgeInsets.only(right: 24.0),
-                  child: ProfileButton(
-                    child: ProfileImage(
-                      heroTag: "profile",
-                      name: firstName,
-                      backgroundColor: Theme.of(context)
-                          .colorScheme
-                          .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
-                      badge: updateProvider.available,
-                      role: user.role,
-                      profilePictureString: user.picture,
-                    ),
-                  ),
-                ),
-              ],
-              automaticallyImplyLeading: false,
-              shadowColor: Theme.of(context).shadowColor,
-              title: Padding(
-                padding: const EdgeInsets.only(left: 8.0),
-                child: Text(
-                  "Messages".i18n,
-                  style: TextStyle(
-                      color: AppColors.of(context).text,
-                      fontSize: 32.0,
-                      fontWeight: FontWeight.bold),
-                ),
-              ),
-              bottom: FilterBar(
-                items: [
-                  Tab(text: "Inbox".i18n),
-                  Tab(text: "Sent".i18n),
-                  Tab(text: "Trash".i18n),
-                  Tab(text: "Draft".i18n),
-                ],
-                controller: tabController,
-                disableFading: true,
-              ),
-            ),
-          ],
-          body: TabBarView(
-              physics: const BouncingScrollPhysics(),
-              controller: tabController,
-              children: List.generate(
-                  4, (index) => filterViewBuilder(context, index))),
-        ),
-      ),
-    );
-  }
-
-  List<DateWidget> getFilterWidgets(MessageType activeData) {
-    List<DateWidget> items = [];
-    switch (activeData) {
-      case MessageType.inbox:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.inbox) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-      case MessageType.sent:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.sent) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-      case MessageType.trash:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.trash) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-      case MessageType.draft:
-        for (var message in messageProvider.messages) {
-          if (message.type == MessageType.draft) {
-            items.add(DateWidget(
-              date: message.date,
-              widget: MessageViewable(message),
-            ));
-          }
-        }
-        break;
-    }
-    return items;
-  }
-
-  Widget filterViewBuilder(context, int activeData) {
-    List<Widget> filterWidgets = sortDateWidgets(context,
-        dateWidgets: getFilterWidgets(MessageType.values[activeData]),
-        hasShadow: true);
-
-    return Padding(
-      padding: const EdgeInsets.only(top: 12.0),
-      child: RefreshIndicator(
-        color: Theme.of(context).colorScheme.secondary,
-        onRefresh: () {
-          return Future.wait([
-            messageProvider.fetch(type: MessageType.inbox),
-            messageProvider.fetch(type: MessageType.sent),
-            messageProvider.fetch(type: MessageType.trash),
-          ]);
-        },
-        child: ListView.builder(
-          padding: EdgeInsets.zero,
-          physics: const BouncingScrollPhysics(),
-          itemBuilder: (context, index) => filterWidgets.isNotEmpty
-              ? Padding(
-                  padding: const EdgeInsets.symmetric(
-                      horizontal: 24.0, vertical: 6.0),
-                  child: filterWidgets[index],
-                )
-              : Empty(subtitle: "empty".i18n),
-          itemCount: max(filterWidgets.length, 1),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/ui/date_widget.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc/ui/filter/sort.dart';
+import 'package:refilc_mobile_ui/common/widgets/message/message_viewable.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'messages_page.i18n.dart';
+
+class MessagesPage extends StatefulWidget {
+  const MessagesPage({Key? key}) : super(key: key);
+
+  @override
+  _MessagesPageState createState() => _MessagesPageState();
+}
+
+class _MessagesPageState extends State<MessagesPage>
+    with TickerProviderStateMixin {
+  late UserProvider user;
+  late MessageProvider messageProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late TabController tabController;
+
+  @override
+  void initState() {
+    super.initState();
+
+    tabController = TabController(length: 4, vsync: this);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    messageProvider = Provider.of<MessageProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 12.0),
+        child: NestedScrollView(
+          physics: const BouncingScrollPhysics(
+              parent: AlwaysScrollableScrollPhysics()),
+          headerSliverBuilder: (context, _) => [
+            SliverAppBar(
+              pinned: true,
+              floating: false,
+              snap: false,
+              centerTitle: false,
+              surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+              actions: [
+                // Profile Icon
+                Padding(
+                  padding: const EdgeInsets.only(right: 24.0),
+                  child: ProfileButton(
+                    child: ProfileImage(
+                      heroTag: "profile",
+                      name: firstName,
+                      backgroundColor: Theme.of(context)
+                          .colorScheme
+                          .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
+                      badge: updateProvider.available,
+                      role: user.role,
+                      profilePictureString: user.picture,
+                    ),
+                  ),
+                ),
+              ],
+              automaticallyImplyLeading: false,
+              shadowColor: Theme.of(context).shadowColor,
+              title: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  "Messages".i18n,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontSize: 32.0,
+                      fontWeight: FontWeight.bold),
+                ),
+              ),
+              bottom: FilterBar(
+                items: [
+                  Tab(text: "Inbox".i18n),
+                  Tab(text: "Sent".i18n),
+                  Tab(text: "Trash".i18n),
+                  Tab(text: "Draft".i18n),
+                ],
+                controller: tabController,
+                disableFading: true,
+              ),
+            ),
+          ],
+          body: TabBarView(
+              physics: const BouncingScrollPhysics(),
+              controller: tabController,
+              children: List.generate(
+                  4, (index) => filterViewBuilder(context, index))),
+        ),
+      ),
+    );
+  }
+
+  List<DateWidget> getFilterWidgets(MessageType activeData) {
+    List<DateWidget> items = [];
+    switch (activeData) {
+      case MessageType.inbox:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.inbox) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+      case MessageType.sent:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.sent) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+      case MessageType.trash:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.trash) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+      case MessageType.draft:
+        for (var message in messageProvider.messages) {
+          if (message.type == MessageType.draft) {
+            items.add(DateWidget(
+              date: message.date,
+              widget: MessageViewable(message),
+            ));
+          }
+        }
+        break;
+    }
+    return items;
+  }
+
+  Widget filterViewBuilder(context, int activeData) {
+    List<Widget> filterWidgets = sortDateWidgets(context,
+        dateWidgets: getFilterWidgets(MessageType.values[activeData]),
+        hasShadow: true);
+
+    return Padding(
+      padding: const EdgeInsets.only(top: 12.0),
+      child: RefreshIndicator(
+        color: Theme.of(context).colorScheme.secondary,
+        onRefresh: () {
+          return Future.wait([
+            messageProvider.fetch(type: MessageType.inbox),
+            messageProvider.fetch(type: MessageType.sent),
+            messageProvider.fetch(type: MessageType.trash),
+          ]);
+        },
+        child: ListView.builder(
+          padding: EdgeInsets.zero,
+          physics: const BouncingScrollPhysics(),
+          itemBuilder: (context, index) => filterWidgets.isNotEmpty
+              ? Padding(
+                  padding: const EdgeInsets.symmetric(
+                      horizontal: 24.0, vertical: 6.0),
+                  child: filterWidgets[index],
+                )
+              : Empty(subtitle: "empty".i18n),
+          itemCount: max(filterWidgets.length, 1),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/messages/messages_page.i18n.dart b/refilc_mobile_ui/lib/pages/messages/messages_page.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/pages/messages/messages_page.i18n.dart
rename to refilc_mobile_ui/lib/pages/messages/messages_page.i18n.dart
index e584436..b1665e1
--- a/filcnaplo_mobile_ui/lib/pages/messages/messages_page.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/messages/messages_page.i18n.dart
@@ -1,36 +1,36 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Messages": "Messages",
-          "Inbox": "Inbox",
-          "Sent": "Sent",
-          "Trash": "Trash",
-          "Draft": "Draft",
-          "empty": "You have no messages.",
-        },
-        "hu_hu": {
-          "Messages": "Üzenetek",
-          "Inbox": "Beérkezett",
-          "Sent": "Elküldött",
-          "Trash": "Kuka",
-          "Draft": "Piszkozat",
-          "empty": "Nincsenek üzeneteid.",
-        },
-        "de_de": {
-          "Messages": "Nachrichten",
-          "Inbox": "Posteingang",
-          "Sent": "Gesendet",
-          "Trash": "Müll",
-          "Draft": "Entwurf",
-          "empty": "Sie haben keine Nachrichten.",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Messages": "Messages",
+          "Inbox": "Inbox",
+          "Sent": "Sent",
+          "Trash": "Trash",
+          "Draft": "Draft",
+          "empty": "You have no messages.",
+        },
+        "hu_hu": {
+          "Messages": "Üzenetek",
+          "Inbox": "Beérkezett",
+          "Sent": "Elküldött",
+          "Trash": "Kuka",
+          "Draft": "Piszkozat",
+          "empty": "Nincsenek üzeneteid.",
+        },
+        "de_de": {
+          "Messages": "Nachrichten",
+          "Inbox": "Posteingang",
+          "Sent": "Gesendet",
+          "Trash": "Müll",
+          "Draft": "Entwurf",
+          "empty": "Sie haben keine Nachrichten.",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/timetable/day_title.dart b/refilc_mobile_ui/lib/pages/timetable/day_title.dart
old mode 100755
new mode 100644
similarity index 79%
rename from filcnaplo_mobile_ui/lib/pages/timetable/day_title.dart
rename to refilc_mobile_ui/lib/pages/timetable/day_title.dart
index e3d4cd6..7cae125
--- a/filcnaplo_mobile_ui/lib/pages/timetable/day_title.dart
+++ b/refilc_mobile_ui/lib/pages/timetable/day_title.dart
@@ -1,62 +1,67 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-class DayTitle extends StatefulWidget {
-  const DayTitle({Key? key, required this.dayTitle, required this.controller}) : super(key: key);
-
-  final String Function(int) dayTitle;
-  final TabController controller;
-
-  @override
-  State<DayTitle> createState() => _DayTitleState();
-}
-
-class _DayTitleState extends State<DayTitle> {
-  @override
-  void initState() {
-    super.initState();
-    widget.controller.addListener(listener);
-  }
-
-  void listener() {
-    if (mounted) setState(() {});
-  }
-
-  @override
-  void dispose() {
-    widget.controller.removeListener(listener);
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    double width = MediaQuery.of(context).size.width;
-
-    return AnimatedBuilder(
-        animation: widget.controller.animation!,
-        builder: (context, _) {
-          double value = widget.controller.animation!.value;
-
-          return Transform.translate(
-            offset: Offset(-value * width / 1.5, 0),
-            child: Row(
-              children: List.generate(
-                widget.controller.length,
-                (index) {
-                  double opacity = (value - index + 1).clamp(0, 1);
-
-                  return SizedBox(
-                    width: MediaQuery.of(context).size.width / 1.5,
-                    child: Text(
-                      widget.dayTitle(index).capital(),
-                      style: TextStyle(color: AppColors.of(context).text.withOpacity(opacity), fontSize: 32.0, fontWeight: FontWeight.bold),
-                    ),
-                  );
-                },
-              ),
-            ),
-          );
-        });
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/utils/format.dart';
+
+class DayTitle extends StatefulWidget {
+  const DayTitle({Key? key, required this.dayTitle, required this.controller})
+      : super(key: key);
+
+  final String Function(int) dayTitle;
+  final TabController controller;
+
+  @override
+  State<DayTitle> createState() => _DayTitleState();
+}
+
+class _DayTitleState extends State<DayTitle> {
+  @override
+  void initState() {
+    super.initState();
+    widget.controller.addListener(listener);
+  }
+
+  void listener() {
+    if (mounted) setState(() {});
+  }
+
+  @override
+  void dispose() {
+    widget.controller.removeListener(listener);
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    double width = MediaQuery.of(context).size.width;
+
+    return AnimatedBuilder(
+        animation: widget.controller.animation!,
+        builder: (context, _) {
+          double value = widget.controller.animation!.value;
+
+          return Transform.translate(
+            offset: Offset(-value * width / 1.5, 0),
+            child: Row(
+              children: List.generate(
+                widget.controller.length,
+                (index) {
+                  double opacity = (value - index + 1).clamp(0, 1);
+
+                  return SizedBox(
+                    width: MediaQuery.of(context).size.width / 1.5,
+                    child: Text(
+                      widget.dayTitle(index).capital(),
+                      style: TextStyle(
+                          color:
+                              AppColors.of(context).text.withOpacity(opacity),
+                          fontSize: 32.0,
+                          fontWeight: FontWeight.bold),
+                    ),
+                  );
+                },
+              ),
+            ),
+          );
+        });
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/pages/timetable/timetable_page.dart b/refilc_mobile_ui/lib/pages/timetable/timetable_page.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/pages/timetable/timetable_page.dart
rename to refilc_mobile_ui/lib/pages/timetable/timetable_page.dart
index f447a73..1ae4586
--- a/filcnaplo_mobile_ui/lib/pages/timetable/timetable_page.dart
+++ b/refilc_mobile_ui/lib/pages/timetable/timetable_page.dart
@@ -1,550 +1,551 @@
-import 'dart:math';
-import 'package:animations/animations.dart';
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_mobile_ui/common/dot.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/lesson/lesson_view.dart';
-import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/lesson/lesson_viewable.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/day_title.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_route_handler.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:intl/intl.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:filcnaplo_premium/ui/mobile/timetable/fs_timetable_button.dart';
-import 'timetable_page.i18n.dart';
-
-// todo: "fix" overflow (priority: -1)
-
-class TimetablePage extends StatefulWidget {
-  const TimetablePage({Key? key, this.initialDay, this.initialWeek})
-      : super(key: key);
-
-  final DateTime? initialDay;
-  final Week? initialWeek;
-
-  static void jump(BuildContext context,
-      {Week? week, DateTime? day, Lesson? lesson}) {
-    // Go to timetable page with arguments
-    NavigationScreen.of(context)
-        ?.customRoute(navigationPageRoute((context) => TimetablePage(
-              initialDay: lesson?.date ?? day,
-              initialWeek: lesson?.date != null
-                  ? Week.fromDate(lesson!.date)
-                  : day != null
-                      ? Week.fromDate(day)
-                      : week,
-            )));
-
-    NavigationScreen.of(context)?.setPage("timetable");
-
-    // Show initial Lesson
-    if (lesson != null) LessonView.show(lesson, context: context);
-  }
-
-  @override
-  _TimetablePageState createState() => _TimetablePageState();
-}
-
-class _TimetablePageState extends State<TimetablePage>
-    with TickerProviderStateMixin, WidgetsBindingObserver {
-  late UserProvider user;
-  late TimetableProvider timetableProvider;
-  late UpdateProvider updateProvider;
-  late String firstName;
-  late TimetableController _controller;
-  late TabController _tabController;
-  late Widget empty;
-
-  int _getDayIndex(DateTime date) {
-    int index = 0;
-    if (_controller.days == null || (_controller.days?.isEmpty ?? true)) {
-      return index;
-    }
-
-    // find the first day with upcoming lessons
-    index = _controller.days!.indexWhere((day) => day.last.end.isAfter(date));
-    if (index == -1) index = 0; // fallback
-
-    return index;
-  }
-
-  // Update timetable on user change
-  Future<void> _userListener() async {
-    await Provider.of<KretaClient>(context, listen: false).refreshLogin();
-    if (mounted) _controller.jump(_controller.currentWeek, context: context);
-  }
-
-  // When the app comes to foreground, refresh the timetable
-  @override
-  void didChangeAppLifecycleState(AppLifecycleState state) {
-    if (state == AppLifecycleState.resumed) {
-      if (mounted) _controller.jump(_controller.currentWeek, context: context);
-    }
-  }
-
-  @override
-  void initState() {
-    super.initState();
-
-    // Initalize controllers
-    _controller = TimetableController();
-    _tabController = TabController(length: 0, vsync: this, initialIndex: 0);
-
-    empty = Empty(subtitle: "empty".i18n);
-
-    bool initial = true;
-
-    // Only update the TabController on week changes
-    _controller.addListener(() {
-      if (_controller.days == null) return;
-      setState(() {
-        _tabController = TabController(
-          length: _controller.days!.length,
-          vsync: this,
-          initialIndex:
-              min(_tabController.index, max(_controller.days!.length - 1, 0)),
-        );
-
-        if (initial ||
-            _controller.previousWeekId != _controller.currentWeekId) {
-          _tabController
-              .animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
-        }
-        initial = false;
-
-        // Empty is updated once every week change
-        empty = Empty(subtitle: "empty".i18n);
-      });
-    });
-
-    if (mounted) {
-      if (widget.initialWeek != null) {
-        _controller.jump(widget.initialWeek!, context: context, initial: true);
-      } else {
-        _controller.jump(_controller.currentWeek,
-            context: context, initial: true, skip: true);
-      }
-    }
-
-    // Listen for user changes
-    user = Provider.of<UserProvider>(context, listen: false);
-    user.addListener(_userListener);
-
-    // Register listening for app state changes to refresh the timetable
-    WidgetsBinding.instance.addObserver(this);
-  }
-
-  @override
-  void dispose() {
-    _tabController.dispose();
-    _controller.dispose();
-    user.removeListener(_userListener);
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  String dayTitle(int index) {
-    // Sometimes when changing weeks really fast,
-    // controller.days might be null or won't include index
-    try {
-      return DateFormat("EEEE", I18n.of(context).locale.languageCode)
-          .format(_controller.days![index].first.date);
-    } catch (e) {
-      return "timetable".i18n;
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    timetableProvider = Provider.of<TimetableProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-
-    // First name
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-
-    return Scaffold(
-      body: Padding(
-        padding: const EdgeInsets.only(top: 9.0),
-        child: RefreshIndicator(
-          onRefresh: () => mounted
-              ? _controller.jump(_controller.currentWeek,
-                  context: context, loader: false)
-              : Future.value(null),
-          color: Theme.of(context).colorScheme.secondary,
-          edgeOffset: 132.0,
-          child: NestedScrollView(
-            physics: const BouncingScrollPhysics(
-                parent: AlwaysScrollableScrollPhysics()),
-            headerSliverBuilder: (context, _) => [
-              SliverAppBar(
-                centerTitle: false,
-                pinned: true,
-                floating: false,
-                snap: false,
-                surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-                actions: [
-                  PremiumFSTimetableButton(controller: _controller, tabcontroller: _tabController),
-
-                  // Profile Icon
-                  Padding(
-                    padding: const EdgeInsets.only(right: 24.0),
-                    child: ProfileButton(
-                      child: ProfileImage(
-                        heroTag: "profile",
-                        name: firstName,
-                        backgroundColor: Theme.of(context)
-                            .colorScheme
-                            .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
-                        badge: updateProvider.available,
-                        role: user.role,
-                        profilePictureString: user.picture,
-                      ),
-                    ),
-                  ),
-                ],
-                automaticallyImplyLeading: false,
-                // Current day text
-                title: PageTransitionSwitcher(
-                  reverse:
-                      _controller.currentWeekId < _controller.previousWeekId,
-                  transitionBuilder: (
-                    Widget child,
-                    Animation<double> primaryAnimation,
-                    Animation<double> secondaryAnimation,
-                  ) {
-                    return SharedAxisTransition(
-                      animation: primaryAnimation,
-                      secondaryAnimation: secondaryAnimation,
-                      transitionType: SharedAxisTransitionType.horizontal,
-                      child: child,
-                      fillColor: Theme.of(context).scaffoldBackgroundColor,
-                    );
-                  },
-                  layoutBuilder: (List<Widget> entries) {
-                    return Stack(
-                      children: entries,
-                    );
-                  },
-                  child: Padding(
-                    padding: const EdgeInsets.only(left: 8.0),
-                    child: Row(
-                      children: [
-                        () {
-                          final show = _controller.days == null ||
-                              (_controller.loadType != LoadType.offline &&
-                                  _controller.loadType != LoadType.online);
-                          const duration = Duration(milliseconds: 150);
-                          return AnimatedOpacity(
-                            opacity: show ? 1.0 : 0.0,
-                            duration: duration,
-                            curve: Curves.easeInOut,
-                            child: AnimatedContainer(
-                              duration: duration,
-                              width: show ? 24.0 : 0.0,
-                              curve: Curves.easeInOut,
-                              child: const Padding(
-                                padding: EdgeInsets.only(right: 12.0),
-                                child: CupertinoActivityIndicator(),
-                              ),
-                            ),
-                          );
-                        }(),
-                        () {
-                          if ((_controller.days?.length ?? 0) > 0) {
-                            return DayTitle(
-                                controller: _tabController, dayTitle: dayTitle);
-                          } else {
-                            return Text(
-                              "timetable".i18n,
-                              style: TextStyle(
-                                fontSize: 32.0,
-                                fontWeight: FontWeight.bold,
-                                color: AppColors.of(context).text,
-                              ),
-                            );
-                          }
-                        }(),
-                      ],
-                    ),
-                  ),
-                ),
-                shadowColor: Theme.of(context).shadowColor,
-                bottom: PreferredSize(
-                  child: Padding(
-                    padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                    child: Row(
-                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                      children: [
-                        // Previous week
-                        IconButton(
-                            onPressed: _controller.currentWeekId == 0
-                                ? null
-                                : () => setState(() {
-                                      _controller.previous(context);
-                                    }),
-                            splashRadius: 24.0,
-                            icon: const Icon(FeatherIcons.chevronLeft),
-                            color: Theme.of(context).colorScheme.secondary),
-
-                        // Week selector
-                        InkWell(
-                          borderRadius: BorderRadius.circular(6.0),
-                          onTap: () => setState(() {
-                            _controller.current();
-                            if (mounted) {
-                              _controller.jump(
-                                _controller.currentWeek,
-                                context: context,
-                                loader: _controller.currentWeekId !=
-                                    _controller.previousWeekId,
-                              );
-                            }
-                            _tabController
-                                .animateTo(_getDayIndex(DateTime.now()));
-                          }),
-                          child: Padding(
-                            padding: const EdgeInsets.all(8.0),
-                            child: Text(
-                              "${_controller.currentWeekId + 1}. " +
-                                  "week".i18n +
-                                  " (" +
-                                  // Week start
-                                  DateFormat(
-                                          (_controller.currentWeek.start.year !=
-                                                      DateTime.now().year
-                                                  ? "yy. "
-                                                  : "") +
-                                              "MMM d.",
-                                          I18n.of(context).locale.languageCode)
-                                      .format(_controller.currentWeek.start) +
-                                  " - " +
-                                  // Week end
-                                  DateFormat(
-                                          (_controller.currentWeek.start.year !=
-                                                      DateTime.now().year
-                                                  ? "yy. "
-                                                  : "") +
-                                              "MMM d.",
-                                          I18n.of(context).locale.languageCode)
-                                      .format(_controller.currentWeek.end) +
-                                  ")",
-                              style: const TextStyle(
-                                fontWeight: FontWeight.w500,
-                                fontSize: 14.0,
-                              ),
-                            ),
-                          ),
-                        ),
-
-                        // Next week
-                        IconButton(
-                            onPressed: _controller.currentWeekId == 51
-                                ? null
-                                : () => setState(() {
-                                      _controller.next(context);
-                                    }),
-                            splashRadius: 24.0,
-                            icon: const Icon(FeatherIcons.chevronRight),
-                            color: Theme.of(context).colorScheme.secondary),
-                      ],
-                    ),
-                  ),
-                  preferredSize: const Size.fromHeight(50.0),
-                ),
-              ),
-            ],
-            body: PageTransitionSwitcher(
-              transitionBuilder: (
-                Widget child,
-                Animation<double> primaryAnimation,
-                Animation<double> secondaryAnimation,
-              ) {
-                return FadeThroughTransition(
-                  child: child,
-                  animation: primaryAnimation,
-                  secondaryAnimation: secondaryAnimation,
-                  fillColor: Theme.of(context).scaffoldBackgroundColor,
-                );
-              },
-              child: _controller.days != null
-                  ? Column(
-                      key: Key(_controller.currentWeek.toString()),
-                      children: [
-                        // Week view
-                        _tabController.length > 0
-                            ? Expanded(
-                                child: TabBarView(
-                                  physics: const BouncingScrollPhysics(),
-                                  controller: _tabController,
-                                  // days
-                                  children: List.generate(
-                                    _controller.days!.length,
-                                    (tab) => RefreshIndicator(
-                                      onRefresh: () => mounted
-                                          ? _controller.jump(
-                                              _controller.currentWeek,
-                                              context: context,
-                                              loader: false)
-                                          : Future.value(null),
-                                      color: Theme.of(context)
-                                          .colorScheme
-                                          .secondary,
-                                      child: ListView.builder(
-                                        padding: EdgeInsets.zero,
-                                        physics: const BouncingScrollPhysics(),
-                                        itemCount:
-                                            _controller.days![tab].length + 2,
-                                        itemBuilder: (context, index) {
-                                          if (_controller.days == null) {
-                                            return Container();
-                                          }
-
-                                          // Header
-                                          if (index == 0) {
-                                            return const Padding(
-                                              padding: EdgeInsets.only(
-                                                  top: 8.0,
-                                                  left: 24.0,
-                                                  right: 24.0),
-                                              child: PanelHeader(
-                                                  padding: EdgeInsets.only(
-                                                      top: 12.0)),
-                                            );
-                                          }
-
-                                          // Footer
-                                          if (index ==
-                                              _controller.days![tab].length +
-                                                  1) {
-                                            return const Padding(
-                                              padding: EdgeInsets.only(
-                                                  bottom: 8.0,
-                                                  left: 24.0,
-                                                  right: 24.0),
-                                              child: PanelFooter(
-                                                  padding: EdgeInsets.only(
-                                                      top: 12.0)),
-                                            );
-                                          }
-
-                                          // Body
-                                          final Lesson lesson =
-                                              _controller.days![tab][index - 1];
-                                          final bool swapDescDay = _controller
-                                                  .days![tab]
-                                                  .map(
-                                                      (l) => l.swapDesc ? 1 : 0)
-                                                  .reduce((a, b) => a + b) >=
-                                              _controller.days![tab].length *
-                                                  .5;
-
-                                          return Padding(
-                                            padding: const EdgeInsets.symmetric(
-                                                horizontal: 24.0),
-                                            child: PanelBody(
-                                              padding:
-                                                  const EdgeInsets.symmetric(
-                                                      horizontal: 10.0),
-                                              child: LessonViewable(
-                                                lesson,
-                                                swapDesc: swapDescDay,
-                                              ),
-                                            ),
-                                          );
-                                        },
-                                      ),
-                                    ),
-                                  ),
-                                ),
-                              )
-
-                            // Empty week
-                            : Expanded(
-                                child: Center(child: empty),
-                              ),
-
-                        // Day selector
-                        TabBar(
-                          dividerColor: Colors.transparent,
-                          controller: _tabController,
-                          // Label
-                          labelPadding: EdgeInsets.zero,
-                          labelColor: Theme.of(context).colorScheme.secondary,
-                          unselectedLabelColor:
-                              AppColors.of(context).text.withOpacity(0.9),
-                          // Indicator
-                          indicatorSize: TabBarIndicatorSize.tab,
-                          indicatorPadding: EdgeInsets.zero,
-                          indicator: BoxDecoration(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .secondary
-                                .withOpacity(0.25),
-                            borderRadius: BorderRadius.circular(45.0),
-                          ),
-                          overlayColor: MaterialStateProperty.all(
-                              const Color(0x00000000)),
-                          // Tabs
-                          padding: const EdgeInsets.symmetric(
-                              vertical: 6.0, horizontal: 8.0),
-                          tabs: List.generate(_tabController.length, (index) {
-                            String label = DateFormat(
-                                    "E", I18n.of(context).locale.languageCode)
-                                .format(_controller.days![index].first.date);
-                            return Tab(
-                              height: 46.0,
-                              child: Column(
-                                mainAxisAlignment: MainAxisAlignment.center,
-                                children: [
-                                  if (_sameDate(
-                                      _controller.days![index].first.date,
-                                      DateTime.now()))
-                                    Padding(
-                                      padding: const EdgeInsets.only(top: 4.0),
-                                      child: Dot(
-                                          size: 4.0,
-                                          color: Theme.of(context)
-                                              .colorScheme
-                                              .secondary),
-                                    ),
-                                  Text(
-                                    label.substring(0, min(2, label.length)),
-                                    style: const TextStyle(
-                                        fontSize: 26.0,
-                                        fontWeight: FontWeight.w600),
-                                  ),
-                                ],
-                              ),
-                            );
-                          }),
-                        ),
-                      ],
-                    )
-                  : const SizedBox(),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-// difference.inDays is not reliable
-bool _sameDate(DateTime a, DateTime b) =>
-    (a.year == b.year && a.month == b.month && a.day == b.day);
+import 'dart:math';
+import 'package:animations/animations.dart';
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_mobile_ui/common/dot.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
+import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
+import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_viewable.dart';
+import 'package:refilc_mobile_ui/pages/timetable/day_title.dart';
+import 'package:refilc_mobile_ui/screens/navigation/navigation_route_handler.dart';
+import 'package:refilc_mobile_ui/screens/navigation/navigation_screen.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:intl/intl.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:refilc_premium/ui/mobile/timetable/fs_timetable_button.dart';
+import 'timetable_page.i18n.dart';
+
+// todo: "fix" overflow (priority: -1)
+
+class TimetablePage extends StatefulWidget {
+  const TimetablePage({Key? key, this.initialDay, this.initialWeek})
+      : super(key: key);
+
+  final DateTime? initialDay;
+  final Week? initialWeek;
+
+  static void jump(BuildContext context,
+      {Week? week, DateTime? day, Lesson? lesson}) {
+    // Go to timetable page with arguments
+    NavigationScreen.of(context)
+        ?.customRoute(navigationPageRoute((context) => TimetablePage(
+              initialDay: lesson?.date ?? day,
+              initialWeek: lesson?.date != null
+                  ? Week.fromDate(lesson!.date)
+                  : day != null
+                      ? Week.fromDate(day)
+                      : week,
+            )));
+
+    NavigationScreen.of(context)?.setPage("timetable");
+
+    // Show initial Lesson
+    if (lesson != null) LessonView.show(lesson, context: context);
+  }
+
+  @override
+  _TimetablePageState createState() => _TimetablePageState();
+}
+
+class _TimetablePageState extends State<TimetablePage>
+    with TickerProviderStateMixin, WidgetsBindingObserver {
+  late UserProvider user;
+  late TimetableProvider timetableProvider;
+  late UpdateProvider updateProvider;
+  late String firstName;
+  late TimetableController _controller;
+  late TabController _tabController;
+  late Widget empty;
+
+  int _getDayIndex(DateTime date) {
+    int index = 0;
+    if (_controller.days == null || (_controller.days?.isEmpty ?? true)) {
+      return index;
+    }
+
+    // find the first day with upcoming lessons
+    index = _controller.days!.indexWhere((day) => day.last.end.isAfter(date));
+    if (index == -1) index = 0; // fallback
+
+    return index;
+  }
+
+  // Update timetable on user change
+  Future<void> _userListener() async {
+    await Provider.of<KretaClient>(context, listen: false).refreshLogin();
+    if (mounted) _controller.jump(_controller.currentWeek, context: context);
+  }
+
+  // When the app comes to foreground, refresh the timetable
+  @override
+  void didChangeAppLifecycleState(AppLifecycleState state) {
+    if (state == AppLifecycleState.resumed) {
+      if (mounted) _controller.jump(_controller.currentWeek, context: context);
+    }
+  }
+
+  @override
+  void initState() {
+    super.initState();
+
+    // Initalize controllers
+    _controller = TimetableController();
+    _tabController = TabController(length: 0, vsync: this, initialIndex: 0);
+
+    empty = Empty(subtitle: "empty".i18n);
+
+    bool initial = true;
+
+    // Only update the TabController on week changes
+    _controller.addListener(() {
+      if (_controller.days == null) return;
+      setState(() {
+        _tabController = TabController(
+          length: _controller.days!.length,
+          vsync: this,
+          initialIndex:
+              min(_tabController.index, max(_controller.days!.length - 1, 0)),
+        );
+
+        if (initial ||
+            _controller.previousWeekId != _controller.currentWeekId) {
+          _tabController
+              .animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
+        }
+        initial = false;
+
+        // Empty is updated once every week change
+        empty = Empty(subtitle: "empty".i18n);
+      });
+    });
+
+    if (mounted) {
+      if (widget.initialWeek != null) {
+        _controller.jump(widget.initialWeek!, context: context, initial: true);
+      } else {
+        _controller.jump(_controller.currentWeek,
+            context: context, initial: true, skip: true);
+      }
+    }
+
+    // Listen for user changes
+    user = Provider.of<UserProvider>(context, listen: false);
+    user.addListener(_userListener);
+
+    // Register listening for app state changes to refresh the timetable
+    WidgetsBinding.instance.addObserver(this);
+  }
+
+  @override
+  void dispose() {
+    _tabController.dispose();
+    _controller.dispose();
+    user.removeListener(_userListener);
+    WidgetsBinding.instance.removeObserver(this);
+    super.dispose();
+  }
+
+  String dayTitle(int index) {
+    // Sometimes when changing weeks really fast,
+    // controller.days might be null or won't include index
+    try {
+      return DateFormat("EEEE", I18n.of(context).locale.languageCode)
+          .format(_controller.days![index].first.date);
+    } catch (e) {
+      return "timetable".i18n;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    timetableProvider = Provider.of<TimetableProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+
+    // First name
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+
+    return Scaffold(
+      body: Padding(
+        padding: const EdgeInsets.only(top: 9.0),
+        child: RefreshIndicator(
+          onRefresh: () => mounted
+              ? _controller.jump(_controller.currentWeek,
+                  context: context, loader: false)
+              : Future.value(null),
+          color: Theme.of(context).colorScheme.secondary,
+          edgeOffset: 132.0,
+          child: NestedScrollView(
+            physics: const BouncingScrollPhysics(
+                parent: AlwaysScrollableScrollPhysics()),
+            headerSliverBuilder: (context, _) => [
+              SliverAppBar(
+                centerTitle: false,
+                pinned: true,
+                floating: false,
+                snap: false,
+                surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+                actions: [
+                  PremiumFSTimetableButton(
+                      controller: _controller, tabcontroller: _tabController),
+
+                  // Profile Icon
+                  Padding(
+                    padding: const EdgeInsets.only(right: 24.0),
+                    child: ProfileButton(
+                      child: ProfileImage(
+                        heroTag: "profile",
+                        name: firstName,
+                        backgroundColor: Theme.of(context)
+                            .colorScheme
+                            .primary, //ColorUtils.stringToColor(user.displayName ?? "?"),
+                        badge: updateProvider.available,
+                        role: user.role,
+                        profilePictureString: user.picture,
+                      ),
+                    ),
+                  ),
+                ],
+                automaticallyImplyLeading: false,
+                // Current day text
+                title: PageTransitionSwitcher(
+                  reverse:
+                      _controller.currentWeekId < _controller.previousWeekId,
+                  transitionBuilder: (
+                    Widget child,
+                    Animation<double> primaryAnimation,
+                    Animation<double> secondaryAnimation,
+                  ) {
+                    return SharedAxisTransition(
+                      animation: primaryAnimation,
+                      secondaryAnimation: secondaryAnimation,
+                      transitionType: SharedAxisTransitionType.horizontal,
+                      child: child,
+                      fillColor: Theme.of(context).scaffoldBackgroundColor,
+                    );
+                  },
+                  layoutBuilder: (List<Widget> entries) {
+                    return Stack(
+                      children: entries,
+                    );
+                  },
+                  child: Padding(
+                    padding: const EdgeInsets.only(left: 8.0),
+                    child: Row(
+                      children: [
+                        () {
+                          final show = _controller.days == null ||
+                              (_controller.loadType != LoadType.offline &&
+                                  _controller.loadType != LoadType.online);
+                          const duration = Duration(milliseconds: 150);
+                          return AnimatedOpacity(
+                            opacity: show ? 1.0 : 0.0,
+                            duration: duration,
+                            curve: Curves.easeInOut,
+                            child: AnimatedContainer(
+                              duration: duration,
+                              width: show ? 24.0 : 0.0,
+                              curve: Curves.easeInOut,
+                              child: const Padding(
+                                padding: EdgeInsets.only(right: 12.0),
+                                child: CupertinoActivityIndicator(),
+                              ),
+                            ),
+                          );
+                        }(),
+                        () {
+                          if ((_controller.days?.length ?? 0) > 0) {
+                            return DayTitle(
+                                controller: _tabController, dayTitle: dayTitle);
+                          } else {
+                            return Text(
+                              "timetable".i18n,
+                              style: TextStyle(
+                                fontSize: 32.0,
+                                fontWeight: FontWeight.bold,
+                                color: AppColors.of(context).text,
+                              ),
+                            );
+                          }
+                        }(),
+                      ],
+                    ),
+                  ),
+                ),
+                shadowColor: Theme.of(context).shadowColor,
+                bottom: PreferredSize(
+                  child: Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 12.0),
+                    child: Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        // Previous week
+                        IconButton(
+                            onPressed: _controller.currentWeekId == 0
+                                ? null
+                                : () => setState(() {
+                                      _controller.previous(context);
+                                    }),
+                            splashRadius: 24.0,
+                            icon: const Icon(FeatherIcons.chevronLeft),
+                            color: Theme.of(context).colorScheme.secondary),
+
+                        // Week selector
+                        InkWell(
+                          borderRadius: BorderRadius.circular(6.0),
+                          onTap: () => setState(() {
+                            _controller.current();
+                            if (mounted) {
+                              _controller.jump(
+                                _controller.currentWeek,
+                                context: context,
+                                loader: _controller.currentWeekId !=
+                                    _controller.previousWeekId,
+                              );
+                            }
+                            _tabController
+                                .animateTo(_getDayIndex(DateTime.now()));
+                          }),
+                          child: Padding(
+                            padding: const EdgeInsets.all(8.0),
+                            child: Text(
+                              "${_controller.currentWeekId + 1}. " +
+                                  "week".i18n +
+                                  " (" +
+                                  // Week start
+                                  DateFormat(
+                                          (_controller.currentWeek.start.year !=
+                                                      DateTime.now().year
+                                                  ? "yy. "
+                                                  : "") +
+                                              "MMM d.",
+                                          I18n.of(context).locale.languageCode)
+                                      .format(_controller.currentWeek.start) +
+                                  " - " +
+                                  // Week end
+                                  DateFormat(
+                                          (_controller.currentWeek.start.year !=
+                                                      DateTime.now().year
+                                                  ? "yy. "
+                                                  : "") +
+                                              "MMM d.",
+                                          I18n.of(context).locale.languageCode)
+                                      .format(_controller.currentWeek.end) +
+                                  ")",
+                              style: const TextStyle(
+                                fontWeight: FontWeight.w500,
+                                fontSize: 14.0,
+                              ),
+                            ),
+                          ),
+                        ),
+
+                        // Next week
+                        IconButton(
+                            onPressed: _controller.currentWeekId == 51
+                                ? null
+                                : () => setState(() {
+                                      _controller.next(context);
+                                    }),
+                            splashRadius: 24.0,
+                            icon: const Icon(FeatherIcons.chevronRight),
+                            color: Theme.of(context).colorScheme.secondary),
+                      ],
+                    ),
+                  ),
+                  preferredSize: const Size.fromHeight(50.0),
+                ),
+              ),
+            ],
+            body: PageTransitionSwitcher(
+              transitionBuilder: (
+                Widget child,
+                Animation<double> primaryAnimation,
+                Animation<double> secondaryAnimation,
+              ) {
+                return FadeThroughTransition(
+                  child: child,
+                  animation: primaryAnimation,
+                  secondaryAnimation: secondaryAnimation,
+                  fillColor: Theme.of(context).scaffoldBackgroundColor,
+                );
+              },
+              child: _controller.days != null
+                  ? Column(
+                      key: Key(_controller.currentWeek.toString()),
+                      children: [
+                        // Week view
+                        _tabController.length > 0
+                            ? Expanded(
+                                child: TabBarView(
+                                  physics: const BouncingScrollPhysics(),
+                                  controller: _tabController,
+                                  // days
+                                  children: List.generate(
+                                    _controller.days!.length,
+                                    (tab) => RefreshIndicator(
+                                      onRefresh: () => mounted
+                                          ? _controller.jump(
+                                              _controller.currentWeek,
+                                              context: context,
+                                              loader: false)
+                                          : Future.value(null),
+                                      color: Theme.of(context)
+                                          .colorScheme
+                                          .secondary,
+                                      child: ListView.builder(
+                                        padding: EdgeInsets.zero,
+                                        physics: const BouncingScrollPhysics(),
+                                        itemCount:
+                                            _controller.days![tab].length + 2,
+                                        itemBuilder: (context, index) {
+                                          if (_controller.days == null) {
+                                            return Container();
+                                          }
+
+                                          // Header
+                                          if (index == 0) {
+                                            return const Padding(
+                                              padding: EdgeInsets.only(
+                                                  top: 8.0,
+                                                  left: 24.0,
+                                                  right: 24.0),
+                                              child: PanelHeader(
+                                                  padding: EdgeInsets.only(
+                                                      top: 12.0)),
+                                            );
+                                          }
+
+                                          // Footer
+                                          if (index ==
+                                              _controller.days![tab].length +
+                                                  1) {
+                                            return const Padding(
+                                              padding: EdgeInsets.only(
+                                                  bottom: 8.0,
+                                                  left: 24.0,
+                                                  right: 24.0),
+                                              child: PanelFooter(
+                                                  padding: EdgeInsets.only(
+                                                      top: 12.0)),
+                                            );
+                                          }
+
+                                          // Body
+                                          final Lesson lesson =
+                                              _controller.days![tab][index - 1];
+                                          final bool swapDescDay = _controller
+                                                  .days![tab]
+                                                  .map(
+                                                      (l) => l.swapDesc ? 1 : 0)
+                                                  .reduce((a, b) => a + b) >=
+                                              _controller.days![tab].length *
+                                                  .5;
+
+                                          return Padding(
+                                            padding: const EdgeInsets.symmetric(
+                                                horizontal: 24.0),
+                                            child: PanelBody(
+                                              padding:
+                                                  const EdgeInsets.symmetric(
+                                                      horizontal: 10.0),
+                                              child: LessonViewable(
+                                                lesson,
+                                                swapDesc: swapDescDay,
+                                              ),
+                                            ),
+                                          );
+                                        },
+                                      ),
+                                    ),
+                                  ),
+                                ),
+                              )
+
+                            // Empty week
+                            : Expanded(
+                                child: Center(child: empty),
+                              ),
+
+                        // Day selector
+                        TabBar(
+                          dividerColor: Colors.transparent,
+                          controller: _tabController,
+                          // Label
+                          labelPadding: EdgeInsets.zero,
+                          labelColor: Theme.of(context).colorScheme.secondary,
+                          unselectedLabelColor:
+                              AppColors.of(context).text.withOpacity(0.9),
+                          // Indicator
+                          indicatorSize: TabBarIndicatorSize.tab,
+                          indicatorPadding: EdgeInsets.zero,
+                          indicator: BoxDecoration(
+                            color: Theme.of(context)
+                                .colorScheme
+                                .secondary
+                                .withOpacity(0.25),
+                            borderRadius: BorderRadius.circular(45.0),
+                          ),
+                          overlayColor: MaterialStateProperty.all(
+                              const Color(0x00000000)),
+                          // Tabs
+                          padding: const EdgeInsets.symmetric(
+                              vertical: 6.0, horizontal: 8.0),
+                          tabs: List.generate(_tabController.length, (index) {
+                            String label = DateFormat(
+                                    "E", I18n.of(context).locale.languageCode)
+                                .format(_controller.days![index].first.date);
+                            return Tab(
+                              height: 46.0,
+                              child: Column(
+                                mainAxisAlignment: MainAxisAlignment.center,
+                                children: [
+                                  if (_sameDate(
+                                      _controller.days![index].first.date,
+                                      DateTime.now()))
+                                    Padding(
+                                      padding: const EdgeInsets.only(top: 4.0),
+                                      child: Dot(
+                                          size: 4.0,
+                                          color: Theme.of(context)
+                                              .colorScheme
+                                              .secondary),
+                                    ),
+                                  Text(
+                                    label.substring(0, min(2, label.length)),
+                                    style: const TextStyle(
+                                        fontSize: 26.0,
+                                        fontWeight: FontWeight.w600),
+                                  ),
+                                ],
+                              ),
+                            );
+                          }),
+                        ),
+                      ],
+                    )
+                  : const SizedBox(),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+// difference.inDays is not reliable
+bool _sameDate(DateTime a, DateTime b) =>
+    (a.year == b.year && a.month == b.month && a.day == b.day);
diff --git a/filcnaplo_mobile_ui/lib/pages/timetable/timetable_page.i18n.dart b/refilc_mobile_ui/lib/pages/timetable/timetable_page.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/pages/timetable/timetable_page.i18n.dart
rename to refilc_mobile_ui/lib/pages/timetable/timetable_page.i18n.dart
index 0f97f62..f17d861
--- a/filcnaplo_mobile_ui/lib/pages/timetable/timetable_page.i18n.dart
+++ b/refilc_mobile_ui/lib/pages/timetable/timetable_page.i18n.dart
@@ -1,33 +1,33 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "timetable": "Timetable",
-          "empty": "No school this week!",
-          "week": "Week",
-          "error": "Failed to fetch timetable!",
-          "empty_timetable": "Timetable is empty!",
-        },
-        "hu_hu": {
-          "timetable": "Órarend",
-          "empty": "Ezen a héten nincs iskola.",
-          "week": "Hét",
-          "error": "Nem sikerült lekérni az órarendet!",
-          "empty_timetable": "Az órarend üres!",
-        },
-        "de_de": {
-          "timetable": "Zeitplan",
-          "empty": "Keine Schule diese Woche.",
-          "week": "Woche",
-          "error": "Der Fahrplan konnte nicht abgerufen werden!",
-          "empty_timetable": "Der Zeitplan ist blank!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "timetable": "Timetable",
+          "empty": "No school this week!",
+          "week": "Week",
+          "error": "Failed to fetch timetable!",
+          "empty_timetable": "Timetable is empty!",
+        },
+        "hu_hu": {
+          "timetable": "Órarend",
+          "empty": "Ezen a héten nincs iskola.",
+          "week": "Hét",
+          "error": "Nem sikerült lekérni az órarendet!",
+          "empty_timetable": "Az órarend üres!",
+        },
+        "de_de": {
+          "timetable": "Zeitplan",
+          "empty": "Keine Schule diese Woche.",
+          "week": "Woche",
+          "error": "Der Fahrplan konnte nicht abgerufen werden!",
+          "empty_timetable": "Der Zeitplan ist blank!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/active_sponsor_card.dart b/refilc_mobile_ui/lib/premium/components/active_sponsor_card.dart
old mode 100755
new mode 100644
similarity index 77%
rename from filcnaplo_mobile_ui/lib/premium/components/active_sponsor_card.dart
rename to refilc_mobile_ui/lib/premium/components/active_sponsor_card.dart
index abbdee1..c209483
--- a/filcnaplo_mobile_ui/lib/premium/components/active_sponsor_card.dart
+++ b/refilc_mobile_ui/lib/premium/components/active_sponsor_card.dart
@@ -1,142 +1,151 @@
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo_mobile_ui/premium/premium_screen.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_svg/svg.dart';
-import 'package:provider/provider.dart';
-
-class ActiveSponsorCard extends StatelessWidget {
-  const ActiveSponsorCard({super.key});
-
-  static PremiumFeatureLevel? estimateLevel(List<String> scopes) {
-    if (scopes.contains(PremiumScopes.all)) {
-      return PremiumFeatureLevel.tinta;
-    }
-    if (scopes.contains(PremiumScopes.timetableWidget) || scopes.contains(PremiumScopes.goalPlanner)) {
-      return PremiumFeatureLevel.tinta;
-    }
-    if (scopes.contains(PremiumScopes.customColors) || scopes.contains(PremiumScopes.nickname)) {
-      return PremiumFeatureLevel.kupak;
-    }
-    return null;
-  }
-
-  IconData _levelIcon(PremiumFeatureLevel level) {
-    switch (level) {
-      case PremiumFeatureLevel.kupak:
-        return FilcIcons.kupak;
-      case PremiumFeatureLevel.tinta:
-        return FilcIcons.tinta;
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final premium = Provider.of<PremiumProvider>(context, listen: false);
-    final level = estimateLevel(premium.scopes);
-
-    if (level == null) {
-      return const SizedBox();
-    }
-
-    Color glow;
-
-    switch (level) {
-      case PremiumFeatureLevel.kupak:
-        glow = Colors.lightGreen;
-        break;
-      case PremiumFeatureLevel.tinta:
-        glow = Colors.purple;
-        break;
-    }
-
-    return Container(
-      decoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(20.0),
-        boxShadow: [
-          BoxShadow(
-            color: glow.withOpacity(.4),
-            blurRadius: 42.0,
-          ),
-        ],
-      ),
-      child: Card(
-        margin: EdgeInsets.zero,
-        elevation: 0,
-        color: const Color(0xff2B2B2B),
-        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-        child: InkWell(
-          borderRadius: BorderRadius.circular(14.0),
-          splashColor: glow.withOpacity(.2),
-          onTap: () {
-            Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (context) {
-              return const PremiumScreen();
-            }));
-          },
-          child: Padding(
-            padding: const EdgeInsets.symmetric(vertical: 12.0),
-            child: Row(
-              children: [
-                Padding(
-                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
-                  child: Stack(
-                    children: [
-                      CircleAvatar(
-                        backgroundColor: Theme.of(context).colorScheme.secondary,
-                        backgroundImage: NetworkImage("https://github.com/${premium.login}.png?size=128"),
-                      ),
-                      Positioned.fill(
-                        child: Align(
-                          alignment: Alignment.bottomRight,
-                          child: Transform.translate(
-                            offset: const Offset(3.0, 4.0),
-                            child: Container(
-                              padding: const EdgeInsets.all(4.0),
-                              decoration: const BoxDecoration(
-                                color: Color(0xff2B2B2B),
-                                shape: BoxShape.circle,
-                              ),
-                              child: const SizedBox(
-                                height: 14.0,
-                                width: 14.0,
-                              ),
-                            ),
-                          ),
-                        ),
-                      ),
-                      Positioned.fill(
-                        child: Align(
-                          alignment: Alignment.bottomRight,
-                          child: SvgPicture.asset(
-                            "assets/images/github.svg",
-                            height: 14.0,
-                          ),
-                        ),
-                      ),
-                    ],
-                  ),
-                ),
-                Expanded(
-                  child: Text(
-                    premium.login,
-                    overflow: TextOverflow.ellipsis,
-                    style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 20, color: Colors.white),
-                  ),
-                ),
-                Padding(
-                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
-                  child: Icon(
-                    _levelIcon(level),
-                    color: Colors.white,
-                  ),
-                ),
-              ],
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc_mobile_ui/premium/premium_screen.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:provider/provider.dart';
+
+class ActiveSponsorCard extends StatelessWidget {
+  const ActiveSponsorCard({super.key});
+
+  static PremiumFeatureLevel? estimateLevel(List<String> scopes) {
+    if (scopes.contains(PremiumScopes.all)) {
+      return PremiumFeatureLevel.tinta;
+    }
+    if (scopes.contains(PremiumScopes.timetableWidget) ||
+        scopes.contains(PremiumScopes.goalPlanner)) {
+      return PremiumFeatureLevel.tinta;
+    }
+    if (scopes.contains(PremiumScopes.customColors) ||
+        scopes.contains(PremiumScopes.nickname)) {
+      return PremiumFeatureLevel.kupak;
+    }
+    return null;
+  }
+
+  IconData _levelIcon(PremiumFeatureLevel level) {
+    switch (level) {
+      case PremiumFeatureLevel.kupak:
+        return FilcIcons.kupak;
+      case PremiumFeatureLevel.tinta:
+        return FilcIcons.tinta;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final premium = Provider.of<PremiumProvider>(context, listen: false);
+    final level = estimateLevel(premium.scopes);
+
+    if (level == null) {
+      return const SizedBox();
+    }
+
+    Color glow;
+
+    switch (level) {
+      case PremiumFeatureLevel.kupak:
+        glow = Colors.lightGreen;
+        break;
+      case PremiumFeatureLevel.tinta:
+        glow = Colors.purple;
+        break;
+    }
+
+    return Container(
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(20.0),
+        boxShadow: [
+          BoxShadow(
+            color: glow.withOpacity(.4),
+            blurRadius: 42.0,
+          ),
+        ],
+      ),
+      child: Card(
+        margin: EdgeInsets.zero,
+        elevation: 0,
+        color: const Color(0xff2B2B2B),
+        shape:
+            RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+        child: InkWell(
+          borderRadius: BorderRadius.circular(14.0),
+          splashColor: glow.withOpacity(.2),
+          onTap: () {
+            Navigator.of(context, rootNavigator: true)
+                .push(MaterialPageRoute(builder: (context) {
+              return const PremiumScreen();
+            }));
+          },
+          child: Padding(
+            padding: const EdgeInsets.symmetric(vertical: 12.0),
+            child: Row(
+              children: [
+                Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
+                  child: Stack(
+                    children: [
+                      CircleAvatar(
+                        backgroundColor:
+                            Theme.of(context).colorScheme.secondary,
+                        backgroundImage: NetworkImage(
+                            "https://github.com/${premium.login}.png?size=128"),
+                      ),
+                      Positioned.fill(
+                        child: Align(
+                          alignment: Alignment.bottomRight,
+                          child: Transform.translate(
+                            offset: const Offset(3.0, 4.0),
+                            child: Container(
+                              padding: const EdgeInsets.all(4.0),
+                              decoration: const BoxDecoration(
+                                color: Color(0xff2B2B2B),
+                                shape: BoxShape.circle,
+                              ),
+                              child: const SizedBox(
+                                height: 14.0,
+                                width: 14.0,
+                              ),
+                            ),
+                          ),
+                        ),
+                      ),
+                      Positioned.fill(
+                        child: Align(
+                          alignment: Alignment.bottomRight,
+                          child: SvgPicture.asset(
+                            "assets/images/github.svg",
+                            height: 14.0,
+                          ),
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+                Expanded(
+                  child: Text(
+                    premium.login,
+                    overflow: TextOverflow.ellipsis,
+                    style: const TextStyle(
+                        fontWeight: FontWeight.w600,
+                        fontSize: 20,
+                        color: Colors.white),
+                  ),
+                ),
+                Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
+                  child: Icon(
+                    _levelIcon(level),
+                    color: Colors.white,
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/avatar_stack.dart b/refilc_mobile_ui/lib/premium/components/avatar_stack.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/premium/components/avatar_stack.dart
rename to refilc_mobile_ui/lib/premium/components/avatar_stack.dart
index 53f4701..844ac11
--- a/filcnaplo_mobile_ui/lib/premium/components/avatar_stack.dart
+++ b/refilc_mobile_ui/lib/premium/components/avatar_stack.dart
@@ -1,26 +1,26 @@
-import 'package:flutter/material.dart';
-
-class AvatarStack extends StatelessWidget {
-  const AvatarStack({Key? key, required this.children}) : super(key: key);
-
-  final List<Widget> children;
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        if (children.isNotEmpty) children[0],
-        if (children.length > 1)
-          Transform.translate(
-            offset: const Offset(-20.0, 0.0),
-            child: children[1],
-          ),
-        if (children.length > 2)
-          Transform.translate(
-            offset: const Offset(-40.0, 0.0),
-            child: children[2],
-          ),
-      ],
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class AvatarStack extends StatelessWidget {
+  const AvatarStack({Key? key, required this.children}) : super(key: key);
+
+  final List<Widget> children;
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: [
+        if (children.isNotEmpty) children[0],
+        if (children.length > 1)
+          Transform.translate(
+            offset: const Offset(-20.0, 0.0),
+            child: children[1],
+          ),
+        if (children.length > 2)
+          Transform.translate(
+            offset: const Offset(-40.0, 0.0),
+            child: children[2],
+          ),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/github_card.dart b/refilc_mobile_ui/lib/premium/components/github_card.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/premium/components/github_card.dart
rename to refilc_mobile_ui/lib/premium/components/github_card.dart
index 1eb3449..a6fce26
--- a/filcnaplo_mobile_ui/lib/premium/components/github_card.dart
+++ b/refilc_mobile_ui/lib/premium/components/github_card.dart
@@ -1,52 +1,52 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/svg.dart';
-
-class GithubCard extends StatelessWidget {
-  const GithubCard({super.key, this.onPressed});
-
-  final void Function()? onPressed;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: EdgeInsets.zero,
-      elevation: 0,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-      color: const Color(0xff2B2B2B),
-      child: Material(
-        type: MaterialType.transparency,
-        child: InkWell(
-          borderRadius: BorderRadius.circular(14.0),
-          onTap: onPressed,
-          child: Padding(
-            padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0).add(const EdgeInsets.only(top: 4.0)),
-            child: Column(
-              crossAxisAlignment: CrossAxisAlignment.start,
-              children: [
-                Row(
-                  children: [
-                    const Expanded(
-                      child: Text(
-                        "Támogass minket Githubon, hogy megszerezd a jutalmakat!",
-                        style: TextStyle(color: Colors.white),
-                      ),
-                    ),
-                    SvgPicture.asset("assets/images/github.svg"),
-                  ],
-                ),
-                const SizedBox(height: 4.0),
-                Chip(
-                  backgroundColor: Colors.black.withOpacity(.5),
-                  label: const Text(
-                    "Már támogatsz? Jelentkezz be!",
-                    style: TextStyle(color: Colors.white),
-                  ),
-                ),
-              ],
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+
+class GithubCard extends StatelessWidget {
+  const GithubCard({super.key, this.onPressed});
+
+  final void Function()? onPressed;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: EdgeInsets.zero,
+      elevation: 0,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+      color: const Color(0xff2B2B2B),
+      child: Material(
+        type: MaterialType.transparency,
+        child: InkWell(
+          borderRadius: BorderRadius.circular(14.0),
+          onTap: onPressed,
+          child: Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0).add(const EdgeInsets.only(top: 4.0)),
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                Row(
+                  children: [
+                    const Expanded(
+                      child: Text(
+                        "Támogass minket Githubon, hogy megszerezd a jutalmakat!",
+                        style: TextStyle(color: Colors.white),
+                      ),
+                    ),
+                    SvgPicture.asset("assets/images/github.svg"),
+                  ],
+                ),
+                const SizedBox(height: 4.0),
+                Chip(
+                  backgroundColor: Colors.black.withOpacity(.5),
+                  label: const Text(
+                    "Már támogatsz? Jelentkezz be!",
+                    style: TextStyle(color: Colors.white),
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/github_connect_button.dart b/refilc_mobile_ui/lib/premium/components/github_connect_button.dart
old mode 100755
new mode 100644
similarity index 78%
rename from filcnaplo_mobile_ui/lib/premium/components/github_connect_button.dart
rename to refilc_mobile_ui/lib/premium/components/github_connect_button.dart
index 23a467e..966fead
--- a/filcnaplo_mobile_ui/lib/premium/components/github_connect_button.dart
+++ b/refilc_mobile_ui/lib/premium/components/github_connect_button.dart
@@ -1,97 +1,107 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/activation_view/activation_view.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:flutter_svg/svg.dart';
-import 'package:provider/provider.dart';
-
-class GithubConnectButton extends StatelessWidget {
-  const GithubConnectButton({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    final premium = Provider.of<PremiumProvider>(context);
-
-    return Card(
-      margin: EdgeInsets.zero,
-      elevation: 0,
-      color: const Color(0xff2B2B2B),
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-      child: InkWell(
-        borderRadius: BorderRadius.circular(14.0),
-        onTap: () {
-          if (premium.hasPremium) {
-            premium.auth.refreshAuth(removePremium: true);
-            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-              content: Text(
-                "Prémium deaktiválva.",
-                style: TextStyle(color: AppColors.of(context).text, fontWeight: FontWeight.bold, fontSize: 18.0),
-              ),
-              backgroundColor: Theme.of(context).scaffoldBackgroundColor,
-            ));
-            return;
-          }
-
-          Navigator.of(context).push(MaterialPageRoute(builder: (context) {
-            return const PremiumActivationView();
-          }));
-        },
-        child: Padding(
-          padding: const EdgeInsets.symmetric(vertical: 12.0),
-          child: Row(
-            children: [
-              Padding(
-                padding: const EdgeInsets.symmetric(horizontal: 16.0),
-                child: Stack(
-                  children: [
-                    SvgPicture.asset(
-                      "assets/images/github.svg",
-                      height: 32.0,
-                    ),
-                    Positioned.fill(
-                      child: Align(
-                        alignment: Alignment.bottomRight,
-                        child: Transform.translate(
-                          offset: const Offset(3.0, 4.0),
-                          child: Container(
-                            padding: const EdgeInsets.all(4.0),
-                            decoration: const BoxDecoration(
-                              color: Color(0xff2B2B2B),
-                              shape: BoxShape.circle,
-                            ),
-                            child: const SizedBox(
-                              height: 14.0,
-                              width: 14.0,
-                            ),
-                          ),
-                        ),
-                      ),
-                    ),
-                    Positioned.fill(
-                      child: Align(
-                        alignment: Alignment.bottomRight,
-                        child: Transform.translate(
-                          offset: const Offset(2.0, 2.0),
-                          child: Icon(
-                            premium.hasPremium ? FeatherIcons.minusCircle : FeatherIcons.plusCircle,
-                            color: Colors.white,
-                            size: 16.0,
-                          ),
-                        ),
-                      ),
-                    ),
-                  ],
-                ),
-              ),
-              Text(
-                premium.hasPremium ? "GitHub szétkapcsolása" : "GitHub csatlakoztatása",
-                style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 20, color: Colors.white),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/activation_view/activation_view.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:provider/provider.dart';
+
+class GithubConnectButton extends StatelessWidget {
+  const GithubConnectButton({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final premium = Provider.of<PremiumProvider>(context);
+
+    return Card(
+      margin: EdgeInsets.zero,
+      elevation: 0,
+      color: const Color(0xff2B2B2B),
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+      child: InkWell(
+        borderRadius: BorderRadius.circular(14.0),
+        onTap: () {
+          if (premium.hasPremium) {
+            premium.auth.refreshAuth(removePremium: true);
+            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+              content: Text(
+                "Prémium deaktiválva.",
+                style: TextStyle(
+                    color: AppColors.of(context).text,
+                    fontWeight: FontWeight.bold,
+                    fontSize: 18.0),
+              ),
+              backgroundColor: Theme.of(context).scaffoldBackgroundColor,
+            ));
+            return;
+          }
+
+          Navigator.of(context).push(MaterialPageRoute(builder: (context) {
+            return const PremiumActivationView();
+          }));
+        },
+        child: Padding(
+          padding: const EdgeInsets.symmetric(vertical: 12.0),
+          child: Row(
+            children: [
+              Padding(
+                padding: const EdgeInsets.symmetric(horizontal: 16.0),
+                child: Stack(
+                  children: [
+                    SvgPicture.asset(
+                      "assets/images/github.svg",
+                      height: 32.0,
+                    ),
+                    Positioned.fill(
+                      child: Align(
+                        alignment: Alignment.bottomRight,
+                        child: Transform.translate(
+                          offset: const Offset(3.0, 4.0),
+                          child: Container(
+                            padding: const EdgeInsets.all(4.0),
+                            decoration: const BoxDecoration(
+                              color: Color(0xff2B2B2B),
+                              shape: BoxShape.circle,
+                            ),
+                            child: const SizedBox(
+                              height: 14.0,
+                              width: 14.0,
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+                    Positioned.fill(
+                      child: Align(
+                        alignment: Alignment.bottomRight,
+                        child: Transform.translate(
+                          offset: const Offset(2.0, 2.0),
+                          child: Icon(
+                            premium.hasPremium
+                                ? FeatherIcons.minusCircle
+                                : FeatherIcons.plusCircle,
+                            color: Colors.white,
+                            size: 16.0,
+                          ),
+                        ),
+                      ),
+                    ),
+                  ],
+                ),
+              ),
+              Text(
+                premium.hasPremium
+                    ? "GitHub szétkapcsolása"
+                    : "GitHub csatlakoztatása",
+                style: const TextStyle(
+                    fontWeight: FontWeight.w600,
+                    fontSize: 20,
+                    color: Colors.white),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/goal_card.dart b/refilc_mobile_ui/lib/premium/components/goal_card.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/premium/components/goal_card.dart
rename to refilc_mobile_ui/lib/premium/components/goal_card.dart
index 3cac000..ae82166
--- a/filcnaplo_mobile_ui/lib/premium/components/goal_card.dart
+++ b/refilc_mobile_ui/lib/premium/components/goal_card.dart
@@ -1,74 +1,74 @@
-import 'dart:ui';
-
-import 'package:flutter/material.dart';
-
-class PremiumGoalCard extends StatelessWidget {
-  const PremiumGoalCard({Key? key, this.progress = 100, this.target = 1}) : super(key: key);
-
-  final double progress;
-  final double target;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: EdgeInsets.zero,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
-      child: Padding(
-        padding: const EdgeInsets.all(20.0),
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            Text(
-              "Cél: ${target.round()} támogató",
-              style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18.0),
-            ),
-            const SizedBox(height: 8.0),
-            Stack(
-              alignment: Alignment.center,
-              children: [
-                Container(
-                  height: 12,
-                  decoration: BoxDecoration(
-                    color: Colors.black.withOpacity(.2),
-                    borderRadius: BorderRadius.circular(45.0),
-                  ),
-                ),
-                LayoutBuilder(
-                  builder: (context, size) {
-                    return Align(
-                      alignment: Alignment.centerLeft,
-                      child: Row(
-                        children: [
-                          Container(
-                            height: 12,
-                            width: size.maxWidth * (progress / 100),
-                            decoration: BoxDecoration(
-                              gradient: const LinearGradient(colors: [Color(0xFFFF2A9D), Color(0xFFFF37F7)]),
-                              borderRadius: BorderRadius.circular(45.0),
-                            ),
-                          ),
-                          Transform.translate(
-                            offset: const Offset(-15.0, 0),
-                            child: Stack(
-                              children: [
-                                ImageFiltered(
-                                  imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
-                                  child: Image.asset("assets/images/heart.png", color: Colors.black.withOpacity(.3)),
-                                ),
-                                Image.asset("assets/images/heart.png"),
-                              ],
-                            ),
-                          ),
-                        ],
-                      ),
-                    );
-                  },
-                ),
-              ],
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+class PremiumGoalCard extends StatelessWidget {
+  const PremiumGoalCard({Key? key, this.progress = 100, this.target = 1}) : super(key: key);
+
+  final double progress;
+  final double target;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: EdgeInsets.zero,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
+      child: Padding(
+        padding: const EdgeInsets.all(20.0),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Text(
+              "Cél: ${target.round()} támogató",
+              style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18.0),
+            ),
+            const SizedBox(height: 8.0),
+            Stack(
+              alignment: Alignment.center,
+              children: [
+                Container(
+                  height: 12,
+                  decoration: BoxDecoration(
+                    color: Colors.black.withOpacity(.2),
+                    borderRadius: BorderRadius.circular(45.0),
+                  ),
+                ),
+                LayoutBuilder(
+                  builder: (context, size) {
+                    return Align(
+                      alignment: Alignment.centerLeft,
+                      child: Row(
+                        children: [
+                          Container(
+                            height: 12,
+                            width: size.maxWidth * (progress / 100),
+                            decoration: BoxDecoration(
+                              gradient: const LinearGradient(colors: [Color(0xFFFF2A9D), Color(0xFFFF37F7)]),
+                              borderRadius: BorderRadius.circular(45.0),
+                            ),
+                          ),
+                          Transform.translate(
+                            offset: const Offset(-15.0, 0),
+                            child: Stack(
+                              children: [
+                                ImageFiltered(
+                                  imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
+                                  child: Image.asset("assets/images/heart.png", color: Colors.black.withOpacity(.3)),
+                                ),
+                                Image.asset("assets/images/heart.png"),
+                              ],
+                            ),
+                          ),
+                        ],
+                      ),
+                    );
+                  },
+                ),
+              ],
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/plan_card.dart b/refilc_mobile_ui/lib/premium/components/plan_card.dart
old mode 100755
new mode 100644
similarity index 71%
rename from filcnaplo_mobile_ui/lib/premium/components/plan_card.dart
rename to refilc_mobile_ui/lib/premium/components/plan_card.dart
index d5ccf55..3a36a83
--- a/filcnaplo_mobile_ui/lib/premium/components/plan_card.dart
+++ b/refilc_mobile_ui/lib/premium/components/plan_card.dart
@@ -1,138 +1,158 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-class PremiumPlanCard extends StatelessWidget {
-  const PremiumPlanCard({
-    Key? key,
-    this.icon,
-    this.title,
-    this.description,
-    this.price = 0,
-    this.url,
-    this.gradient,
-    this.active = false,
-  }) : super(key: key);
-
-  final Widget? icon;
-  final Widget? title;
-  final int price;
-  final Widget? description;
-  final String? url;
-  final Gradient? gradient;
-  final bool active;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: EdgeInsets.zero,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
-      child: InkWell(
-        customBorder: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
-        onTap: () {
-          if (url != null) {
-            launchUrl(
-              Uri.parse(url!),
-              mode: LaunchMode.externalApplication,
-            );
-          }
-        },
-        child: Padding(
-          padding: const EdgeInsets.all(20.0),
-          child: Column(
-            children: [
-              Row(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  if (!active)
-                    Expanded(
-                      child: Column(
-                        crossAxisAlignment: CrossAxisAlignment.start,
-                        children: [
-                          if (icon != null) ...[
-                            IconTheme(
-                              data: Theme.of(context).iconTheme.copyWith(size: 42.0),
-                              child: icon!,
-                            ),
-                            const SizedBox(height: 12.0),
-                          ],
-                          DefaultTextStyle(
-                            style: Theme.of(context).textTheme.displaySmall!.copyWith(fontWeight: FontWeight.bold, fontSize: 25.0),
-                            child: title!,
-                          ),
-                        ],
-                      ),
-                    )
-                  else
-                    Expanded(
-                      child: Align(
-                        alignment: Alignment.centerLeft,
-                        child: Container(
-                          decoration: BoxDecoration(
-                            gradient: gradient,
-                            borderRadius: BorderRadius.circular(99.0),
-                          ),
-                          child: Container(
-                            decoration: BoxDecoration(
-                              color: Theme.of(context).scaffoldBackgroundColor,
-                              borderRadius: BorderRadius.circular(99.0),
-                            ),
-                            margin: const EdgeInsets.all(4.0),
-                            padding: const EdgeInsets.symmetric(horizontal: 12.0),
-                            child: const Text(
-                              "Aktív",
-                              style: TextStyle(
-                                fontWeight: FontWeight.bold,
-                                fontSize: 20.0,
-                              ),
-                            ),
-                          ),
-                        ),
-                      ),
-                    ),
-                  Text.rich(
-                    TextSpan(children: [
-                      TextSpan(text: "\$$price"),
-                      TextSpan(
-                        text: " / hó",
-                        style: TextStyle(color: Theme.of(context).textTheme.bodyMedium!.color!.withOpacity(.7)),
-                      ),
-                    ]),
-                    style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 24.0),
-                  ),
-                ],
-              ),
-              if (active) ...[
-                const SizedBox(height: 18.0),
-                Row(
-                  children: [
-                    if (icon != null) ...[
-                      IconTheme(
-                        data: Theme.of(context).iconTheme.copyWith(size: 24.0, color: AppColors.of(context).text),
-                        child: icon!,
-                      ),
-                    ],
-                    const SizedBox(width: 12.0),
-                    DefaultTextStyle(
-                      style: Theme.of(context).textTheme.displaySmall!.copyWith(fontWeight: FontWeight.bold, fontSize: 25.0),
-                      child: title!,
-                    ),
-                  ],
-                ),
-              ],
-              const SizedBox(height: 6.0),
-              if (description != null)
-                DefaultTextStyle(
-                  style: Theme.of(context)
-                      .textTheme
-                      .bodyMedium!
-                      .copyWith(color: Theme.of(context).textTheme.bodyMedium!.color!.withOpacity(.8), fontSize: 18),
-                  child: description!,
-                ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class PremiumPlanCard extends StatelessWidget {
+  const PremiumPlanCard({
+    Key? key,
+    this.icon,
+    this.title,
+    this.description,
+    this.price = 0,
+    this.url,
+    this.gradient,
+    this.active = false,
+  }) : super(key: key);
+
+  final Widget? icon;
+  final Widget? title;
+  final int price;
+  final Widget? description;
+  final String? url;
+  final Gradient? gradient;
+  final bool active;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: EdgeInsets.zero,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
+      child: InkWell(
+        customBorder:
+            RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
+        onTap: () {
+          if (url != null) {
+            launchUrl(
+              Uri.parse(url!),
+              mode: LaunchMode.externalApplication,
+            );
+          }
+        },
+        child: Padding(
+          padding: const EdgeInsets.all(20.0),
+          child: Column(
+            children: [
+              Row(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  if (!active)
+                    Expanded(
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          if (icon != null) ...[
+                            IconTheme(
+                              data: Theme.of(context)
+                                  .iconTheme
+                                  .copyWith(size: 42.0),
+                              child: icon!,
+                            ),
+                            const SizedBox(height: 12.0),
+                          ],
+                          DefaultTextStyle(
+                            style: Theme.of(context)
+                                .textTheme
+                                .displaySmall!
+                                .copyWith(
+                                    fontWeight: FontWeight.bold,
+                                    fontSize: 25.0),
+                            child: title!,
+                          ),
+                        ],
+                      ),
+                    )
+                  else
+                    Expanded(
+                      child: Align(
+                        alignment: Alignment.centerLeft,
+                        child: Container(
+                          decoration: BoxDecoration(
+                            gradient: gradient,
+                            borderRadius: BorderRadius.circular(99.0),
+                          ),
+                          child: Container(
+                            decoration: BoxDecoration(
+                              color: Theme.of(context).scaffoldBackgroundColor,
+                              borderRadius: BorderRadius.circular(99.0),
+                            ),
+                            margin: const EdgeInsets.all(4.0),
+                            padding:
+                                const EdgeInsets.symmetric(horizontal: 12.0),
+                            child: const Text(
+                              "Aktív",
+                              style: TextStyle(
+                                fontWeight: FontWeight.bold,
+                                fontSize: 20.0,
+                              ),
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+                  Text.rich(
+                    TextSpan(children: [
+                      TextSpan(text: "\$$price"),
+                      TextSpan(
+                        text: " / hó",
+                        style: TextStyle(
+                            color: Theme.of(context)
+                                .textTheme
+                                .bodyMedium!
+                                .color!
+                                .withOpacity(.7)),
+                      ),
+                    ]),
+                    style: const TextStyle(
+                        fontWeight: FontWeight.bold, fontSize: 24.0),
+                  ),
+                ],
+              ),
+              if (active) ...[
+                const SizedBox(height: 18.0),
+                Row(
+                  children: [
+                    if (icon != null) ...[
+                      IconTheme(
+                        data: Theme.of(context).iconTheme.copyWith(
+                            size: 24.0, color: AppColors.of(context).text),
+                        child: icon!,
+                      ),
+                    ],
+                    const SizedBox(width: 12.0),
+                    DefaultTextStyle(
+                      style: Theme.of(context).textTheme.displaySmall!.copyWith(
+                          fontWeight: FontWeight.bold, fontSize: 25.0),
+                      child: title!,
+                    ),
+                  ],
+                ),
+              ],
+              const SizedBox(height: 6.0),
+              if (description != null)
+                DefaultTextStyle(
+                  style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+                      color: Theme.of(context)
+                          .textTheme
+                          .bodyMedium!
+                          .color!
+                          .withOpacity(.8),
+                      fontSize: 18),
+                  child: description!,
+                ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/reward_card.dart b/refilc_mobile_ui/lib/premium/components/reward_card.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/premium/components/reward_card.dart
rename to refilc_mobile_ui/lib/premium/components/reward_card.dart
index eeabb68..fc356d3
--- a/filcnaplo_mobile_ui/lib/premium/components/reward_card.dart
+++ b/refilc_mobile_ui/lib/premium/components/reward_card.dart
@@ -1,64 +1,64 @@
-import 'package:flutter/material.dart';
-
-class PremiumRewardCard extends StatelessWidget {
-  const PremiumRewardCard({Key? key, this.imageKey, this.icon, this.title, this.description, this.soon = false}) : super(key: key);
-
-  final String? imageKey;
-  final Widget? icon;
-  final Widget? title;
-  final Widget? description;
-  final bool soon;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: EdgeInsets.zero,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.0)),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          if (soon)
-            const Padding(
-              padding: EdgeInsets.only(left: 8.0),
-              child: Chip(
-                labelPadding: EdgeInsets.zero,
-                padding: EdgeInsets.symmetric(horizontal: 12.0),
-                backgroundColor: Color(0x777645D3),
-                label: Text("Hamarosan", style: TextStyle(fontWeight: FontWeight.w500)),
-              ),
-            ),
-          if (imageKey != null)
-            Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 14.0).add(EdgeInsets.only(bottom: 12.0, top: soon ? 0 : 14.0)),
-              child: Image.asset("assets/images/${imageKey!}.png"),
-            )
-          else
-            const SizedBox(height: 12),
-          Padding(
-            padding: const EdgeInsets.symmetric(horizontal: 12.0),
-            child: Row(
-              children: [
-                if (icon != null) ...[icon!, const SizedBox(width: 12.0)],
-                if (title != null)
-                  Expanded(
-                    child: DefaultTextStyle(
-                      style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontWeight: FontWeight.w700, fontSize: 20),
-                      child: title!,
-                    ),
-                  ),
-              ],
-            ),
-          ),
-          if (description != null)
-            Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 12.0).add(const EdgeInsets.only(top: 4.0, bottom: 12.0)),
-              child: DefaultTextStyle(
-                style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 16),
-                child: description!,
-              ),
-            ),
-        ],
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class PremiumRewardCard extends StatelessWidget {
+  const PremiumRewardCard({Key? key, this.imageKey, this.icon, this.title, this.description, this.soon = false}) : super(key: key);
+
+  final String? imageKey;
+  final Widget? icon;
+  final Widget? title;
+  final Widget? description;
+  final bool soon;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: EdgeInsets.zero,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.0)),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          if (soon)
+            const Padding(
+              padding: EdgeInsets.only(left: 8.0),
+              child: Chip(
+                labelPadding: EdgeInsets.zero,
+                padding: EdgeInsets.symmetric(horizontal: 12.0),
+                backgroundColor: Color(0x777645D3),
+                label: Text("Hamarosan", style: TextStyle(fontWeight: FontWeight.w500)),
+              ),
+            ),
+          if (imageKey != null)
+            Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 14.0).add(EdgeInsets.only(bottom: 12.0, top: soon ? 0 : 14.0)),
+              child: Image.asset("assets/images/${imageKey!}.png"),
+            )
+          else
+            const SizedBox(height: 12),
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 12.0),
+            child: Row(
+              children: [
+                if (icon != null) ...[icon!, const SizedBox(width: 12.0)],
+                if (title != null)
+                  Expanded(
+                    child: DefaultTextStyle(
+                      style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontWeight: FontWeight.w700, fontSize: 20),
+                      child: title!,
+                    ),
+                  ),
+              ],
+            ),
+          ),
+          if (description != null)
+            Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 12.0).add(const EdgeInsets.only(top: 4.0, bottom: 12.0)),
+              child: DefaultTextStyle(
+                style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 16),
+                child: description!,
+              ),
+            ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/supporter_chip.dart b/refilc_mobile_ui/lib/premium/components/supporter_chip.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/premium/components/supporter_chip.dart
rename to refilc_mobile_ui/lib/premium/components/supporter_chip.dart
index 188bdf0..d1f3777
--- a/filcnaplo_mobile_ui/lib/premium/components/supporter_chip.dart
+++ b/refilc_mobile_ui/lib/premium/components/supporter_chip.dart
@@ -1,35 +1,35 @@
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:flutter/material.dart';
-
-class SupporterChip extends StatelessWidget {
-  const SupporterChip({Key? key, required this.supporter}) : super(key: key);
-
-  final Supporter supporter;
-
-  @override
-  Widget build(BuildContext context) {
-    return Chip(
-      side: BorderSide.none,
-      shape: const StadiumBorder(side: BorderSide.none),
-      padding: const EdgeInsets.all(8.0),
-      avatar: supporter.avatar != ""
-          ? CircleAvatar(
-              backgroundColor: Theme.of(context).colorScheme.secondary,
-              backgroundImage: NetworkImage(supporter.avatar),
-            )
-          : null,
-      labelPadding: const EdgeInsets.only(left: 12.0, right: 8.0),
-      label: Text.rich(
-        TextSpan(children: [
-          TextSpan(text: supporter.name),
-          if (supporter.type == DonationType.once)
-            TextSpan(
-              text: "  \$${supporter.price}",
-              style: const TextStyle(fontWeight: FontWeight.w400),
-            ),
-        ]),
-        style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/supporter.dart';
+import 'package:flutter/material.dart';
+
+class SupporterChip extends StatelessWidget {
+  const SupporterChip({Key? key, required this.supporter}) : super(key: key);
+
+  final Supporter supporter;
+
+  @override
+  Widget build(BuildContext context) {
+    return Chip(
+      side: BorderSide.none,
+      shape: const StadiumBorder(side: BorderSide.none),
+      padding: const EdgeInsets.all(8.0),
+      avatar: supporter.avatar != ""
+          ? CircleAvatar(
+              backgroundColor: Theme.of(context).colorScheme.secondary,
+              backgroundImage: NetworkImage(supporter.avatar),
+            )
+          : null,
+      labelPadding: const EdgeInsets.only(left: 12.0, right: 8.0),
+      label: Text.rich(
+        TextSpan(children: [
+          TextSpan(text: supporter.name),
+          if (supporter.type == DonationType.once)
+            TextSpan(
+              text: "  \$${supporter.price}",
+              style: const TextStyle(fontWeight: FontWeight.w400),
+            ),
+        ]),
+        style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/supporter_group_card.dart b/refilc_mobile_ui/lib/premium/components/supporter_group_card.dart
old mode 100755
new mode 100644
similarity index 67%
rename from filcnaplo_mobile_ui/lib/premium/components/supporter_group_card.dart
rename to refilc_mobile_ui/lib/premium/components/supporter_group_card.dart
index cdc8f67..d1125a0
--- a/filcnaplo_mobile_ui/lib/premium/components/supporter_group_card.dart
+++ b/refilc_mobile_ui/lib/premium/components/supporter_group_card.dart
@@ -1,71 +1,79 @@
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/supporter_chip.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/supporter_tile.dart';
-import 'package:flutter/material.dart';
-
-class SupporterGroupCard extends StatelessWidget {
-  const SupporterGroupCard({
-    Key? key,
-    this.title,
-    this.icon,
-    this.expanded = false,
-    this.supporters = const [],
-    this.glow,
-  }) : super(key: key);
-
-  final Widget? icon;
-  final Widget? title;
-  final bool expanded;
-  final List<Supporter> supporters;
-  final Color? glow;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      decoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(20.0),
-        boxShadow: [
-          if (glow != null)
-            BoxShadow(
-              color: glow!.withOpacity(.2),
-              blurRadius: 60.0,
-            ),
-        ],
-      ),
-      child: Card(
-        margin: EdgeInsets.zero,
-        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
-        child: Padding(
-          padding: const EdgeInsets.all(24.0),
-          child: Column(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: [
-              Row(
-                children: [
-                  if (icon != null) ...[icon!, const SizedBox(width: 12.0)],
-                  if (title != null)
-                    Expanded(
-                      child: DefaultTextStyle(
-                        style: Theme.of(context).textTheme.titleLarge!.copyWith(fontWeight: FontWeight.w700),
-                        child: title!,
-                      ),
-                    ),
-                ],
-              ),
-              const SizedBox(height: 12.0),
-              if (expanded)
-                Column(
-                  children: supporters.map((e) => SupporterTile(supporter: e)).toList(),
-                )
-              else
-                Wrap(
-                  spacing: 8.0,
-                  children: supporters.map((e) => SupporterChip(supporter: e)).toList(),
-                ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/supporter.dart';
+import 'package:refilc_mobile_ui/premium/components/supporter_chip.dart';
+import 'package:refilc_mobile_ui/premium/components/supporter_tile.dart';
+import 'package:flutter/material.dart';
+
+class SupporterGroupCard extends StatelessWidget {
+  const SupporterGroupCard({
+    Key? key,
+    this.title,
+    this.icon,
+    this.expanded = false,
+    this.supporters = const [],
+    this.glow,
+  }) : super(key: key);
+
+  final Widget? icon;
+  final Widget? title;
+  final bool expanded;
+  final List<Supporter> supporters;
+  final Color? glow;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(20.0),
+        boxShadow: [
+          if (glow != null)
+            BoxShadow(
+              color: glow!.withOpacity(.2),
+              blurRadius: 60.0,
+            ),
+        ],
+      ),
+      child: Card(
+        margin: EdgeInsets.zero,
+        shape:
+            RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
+        child: Padding(
+          padding: const EdgeInsets.all(24.0),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Row(
+                children: [
+                  if (icon != null) ...[icon!, const SizedBox(width: 12.0)],
+                  if (title != null)
+                    Expanded(
+                      child: DefaultTextStyle(
+                        style: Theme.of(context)
+                            .textTheme
+                            .titleLarge!
+                            .copyWith(fontWeight: FontWeight.w700),
+                        child: title!,
+                      ),
+                    ),
+                ],
+              ),
+              const SizedBox(height: 12.0),
+              if (expanded)
+                Column(
+                  children: supporters
+                      .map((e) => SupporterTile(supporter: e))
+                      .toList(),
+                )
+              else
+                Wrap(
+                  spacing: 8.0,
+                  children: supporters
+                      .map((e) => SupporterChip(supporter: e))
+                      .toList(),
+                ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/supporter_tile.dart b/refilc_mobile_ui/lib/premium/components/supporter_tile.dart
old mode 100755
new mode 100644
similarity index 88%
rename from filcnaplo_mobile_ui/lib/premium/components/supporter_tile.dart
rename to refilc_mobile_ui/lib/premium/components/supporter_tile.dart
index a783a4d..4dab60b
--- a/filcnaplo_mobile_ui/lib/premium/components/supporter_tile.dart
+++ b/refilc_mobile_ui/lib/premium/components/supporter_tile.dart
@@ -1,23 +1,23 @@
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:flutter/material.dart';
-
-class SupporterTile extends StatelessWidget {
-  const SupporterTile({Key? key, required this.supporter}) : super(key: key);
-
-  final Supporter supporter;
-
-  @override
-  Widget build(BuildContext context) {
-    return ListTile(
-      contentPadding: EdgeInsets.zero,
-      leading: CircleAvatar(
-        backgroundImage: NetworkImage(supporter.avatar),
-      ),
-      title: Text(
-        supporter.name,
-        style: const TextStyle(fontWeight: FontWeight.bold),
-      ),
-      subtitle: Text(supporter.comment),
-    );
-  }
-}
+import 'package:refilc/models/supporter.dart';
+import 'package:flutter/material.dart';
+
+class SupporterTile extends StatelessWidget {
+  const SupporterTile({Key? key, required this.supporter}) : super(key: key);
+
+  final Supporter supporter;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListTile(
+      contentPadding: EdgeInsets.zero,
+      leading: CircleAvatar(
+        backgroundImage: NetworkImage(supporter.avatar),
+      ),
+      title: Text(
+        supporter.name,
+        style: const TextStyle(fontWeight: FontWeight.bold),
+      ),
+      subtitle: Text(supporter.comment),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/components/supporters_button.dart b/refilc_mobile_ui/lib/premium/components/supporters_button.dart
old mode 100755
new mode 100644
similarity index 62%
rename from filcnaplo_mobile_ui/lib/premium/components/supporters_button.dart
rename to refilc_mobile_ui/lib/premium/components/supporters_button.dart
index 7d9fb6d..0bb7b47
--- a/filcnaplo_mobile_ui/lib/premium/components/supporters_button.dart
+++ b/refilc_mobile_ui/lib/premium/components/supporters_button.dart
@@ -1,70 +1,83 @@
-import 'dart:math';
-
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/avatar_stack.dart';
-import 'package:filcnaplo_mobile_ui/premium/supporters_screen.dart';
-import 'package:flutter/material.dart';
-
-class SupportersButton extends StatelessWidget {
-  const SupportersButton({Key? key, required this.supporters}) : super(key: key);
-
-  final Future<Supporters?> supporters;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      shape: const StadiumBorder(),
-      margin: EdgeInsets.zero,
-      child: InkWell(
-        customBorder: const StadiumBorder(),
-        onTap: () {
-          Navigator.of(context).push(
-            MaterialPageRoute(builder: (context) => SupportersScreen(supporters: supporters)),
-          );
-        },
-        child: Container(
-          padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 14.0),
-          child: Row(
-            children: [
-              const Expanded(
-                child: Text(
-                  "Köszönjük, támogatók!",
-                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17.0),
-                ),
-              ),
-              FutureBuilder<Supporters?>(
-                  future: supporters,
-                  builder: (context, snapshot) {
-                    if (!snapshot.hasData) {
-                      return const SizedBox();
-                    }
-                    final sponsors = snapshot.data!.github.where((e) => e.type == DonationType.monthly).toList();
-                    sponsors.shuffle(Random((DateTime.now().millisecondsSinceEpoch / 1000 / 60 / 60 / 24).floor()));
-                    return AvatarStack(
-                      children: [
-                        // ignore: prefer_is_empty
-                        if (sponsors.length > 0 && sponsors[0].avatar != "")
-                          CircleAvatar(
-                            backgroundColor: Theme.of(context).colorScheme.secondary,
-                            backgroundImage: NetworkImage(sponsors[0].avatar),
-                          ),
-                        if (sponsors.length > 1 && sponsors[1].avatar != "")
-                          CircleAvatar(
-                            backgroundColor: Theme.of(context).colorScheme.secondary,
-                            backgroundImage: NetworkImage(sponsors[1].avatar),
-                          ),
-                        if (sponsors.length > 2 && sponsors[2].avatar != "")
-                          CircleAvatar(
-                            backgroundColor: Theme.of(context).colorScheme.secondary,
-                            backgroundImage: NetworkImage(sponsors[2].avatar),
-                          ),
-                      ],
-                    );
-                  }),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/models/supporter.dart';
+import 'package:refilc_mobile_ui/premium/components/avatar_stack.dart';
+import 'package:refilc_mobile_ui/premium/supporters_screen.dart';
+import 'package:flutter/material.dart';
+
+class SupportersButton extends StatelessWidget {
+  const SupportersButton({Key? key, required this.supporters})
+      : super(key: key);
+
+  final Future<Supporters?> supporters;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      shape: const StadiumBorder(),
+      margin: EdgeInsets.zero,
+      child: InkWell(
+        customBorder: const StadiumBorder(),
+        onTap: () {
+          Navigator.of(context).push(
+            MaterialPageRoute(
+                builder: (context) => SupportersScreen(supporters: supporters)),
+          );
+        },
+        child: Container(
+          padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 14.0),
+          child: Row(
+            children: [
+              const Expanded(
+                child: Text(
+                  "Köszönjük, támogatók!",
+                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17.0),
+                ),
+              ),
+              FutureBuilder<Supporters?>(
+                  future: supporters,
+                  builder: (context, snapshot) {
+                    if (!snapshot.hasData) {
+                      return const SizedBox();
+                    }
+                    final sponsors = snapshot.data!.github
+                        .where((e) => e.type == DonationType.monthly)
+                        .toList();
+                    sponsors.shuffle(Random(
+                        (DateTime.now().millisecondsSinceEpoch /
+                                1000 /
+                                60 /
+                                60 /
+                                24)
+                            .floor()));
+                    return AvatarStack(
+                      children: [
+                        // ignore: prefer_is_empty
+                        if (sponsors.length > 0 && sponsors[0].avatar != "")
+                          CircleAvatar(
+                            backgroundColor:
+                                Theme.of(context).colorScheme.secondary,
+                            backgroundImage: NetworkImage(sponsors[0].avatar),
+                          ),
+                        if (sponsors.length > 1 && sponsors[1].avatar != "")
+                          CircleAvatar(
+                            backgroundColor:
+                                Theme.of(context).colorScheme.secondary,
+                            backgroundImage: NetworkImage(sponsors[1].avatar),
+                          ),
+                        if (sponsors.length > 2 && sponsors[2].avatar != "")
+                          CircleAvatar(
+                            backgroundColor:
+                                Theme.of(context).colorScheme.secondary,
+                            backgroundImage: NetworkImage(sponsors[2].avatar),
+                          ),
+                      ],
+                    );
+                  }),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/premium_button.dart b/refilc_mobile_ui/lib/premium/premium_button.dart
old mode 100755
new mode 100644
similarity index 94%
rename from filcnaplo_mobile_ui/lib/premium/premium_button.dart
rename to refilc_mobile_ui/lib/premium/premium_button.dart
index 0b328cb..b3c9154
--- a/filcnaplo_mobile_ui/lib/premium/premium_button.dart
+++ b/refilc_mobile_ui/lib/premium/premium_button.dart
@@ -1,126 +1,126 @@
-import 'dart:ui';
-
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo_mobile_ui/premium/premium_screen.dart';
-import 'package:flutter/material.dart';
-import 'package:animations/animations.dart';
-
-class PremiumButton extends StatefulWidget {
-  const PremiumButton({Key? key}) : super(key: key);
-
-  @override
-  State<PremiumButton> createState() => _PremiumButtonState();
-}
-
-class _PremiumButtonState extends State<PremiumButton>
-    with TickerProviderStateMixin {
-  late final AnimationController _animation;
-  bool _heldDown = false;
-
-  @override
-  void initState() {
-    super.initState();
-    _animation =
-        AnimationController(vsync: this, duration: const Duration(seconds: 3));
-    _animation.repeat();
-  }
-
-  @override
-  void dispose() {
-    _animation.dispose();
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return OpenContainer(
-      openColor: Theme.of(context).scaffoldBackgroundColor,
-      closedColor: Theme.of(context).scaffoldBackgroundColor,
-      clipBehavior: Clip.none,
-      transitionType: ContainerTransitionType.fadeThrough,
-      openElevation: 0,
-      closedElevation: 0,
-      closedShape:
-          RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
-      openBuilder: (context, _) => const PremiumScreen(),
-      closedBuilder: (context, action) => GestureDetector(
-        onTapDown: (_) => setState(() => _heldDown = true),
-        onTapUp: (_) => setState(() => _heldDown = false),
-        onTapCancel: () => setState(() => _heldDown = false),
-        onTap: action,
-        child: Stack(
-          alignment: Alignment.center,
-          children: [
-            // RGB background animation
-            AnimatedBuilder(
-                animation: _animation,
-                builder: (context, child) {
-                  return Padding(
-                    padding: const EdgeInsets.symmetric(horizontal: 18.0),
-                    child: ClipRRect(
-                      borderRadius: BorderRadius.circular(14.0),
-                      child: ImageFiltered(
-                        imageFilter:
-                            ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
-                        child: Container(
-                          height: 70,
-                          decoration: BoxDecoration(
-                            gradient: SweepGradient(
-                                colors: const [
-                                  Colors.blue,
-                                  Colors.orange,
-                                  Colors.purple,
-                                  Colors.blue,
-                                ],
-                                transform: GradientRotation(
-                                    _animation.value * 6.283185)),
-                          ),
-                        ),
-                      ),
-                    ),
-                  );
-                }),
-
-            // Button background & text
-            BackdropFilter(
-              filter: ImageFilter.blur(sigmaX: 6.0, sigmaY: 6.0),
-              child: AnimatedScale(
-                duration: const Duration(milliseconds: 250),
-                curve: Curves.easeOutBack,
-                scale: _heldDown ? 1.03 : 1,
-                child: Container(
-                  margin: const EdgeInsets.symmetric(horizontal: 24.0),
-                  width: double.infinity,
-                  height: 60,
-                  decoration: BoxDecoration(
-                    borderRadius: BorderRadius.circular(14.0),
-                    gradient: const LinearGradient(colors: [
-                      Color(0xff124F3D),
-                      Color(0xff1EA18F),
-                    ]),
-                  ),
-                  child: const Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: [
-                      Icon(FilcIcons.premium, color: Colors.white),
-                      SizedBox(width: 12.0),
-                      Text(
-                        "reFilc Premium",
-                        style: TextStyle(
-                          color: Colors.white,
-                          fontWeight: FontWeight.bold,
-                          fontSize: 20.0,
-                        ),
-                        textAlign: TextAlign.center,
-                      ),
-                    ],
-                  ),
-                ),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'dart:ui';
+
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc_mobile_ui/premium/premium_screen.dart';
+import 'package:flutter/material.dart';
+import 'package:animations/animations.dart';
+
+class PremiumButton extends StatefulWidget {
+  const PremiumButton({Key? key}) : super(key: key);
+
+  @override
+  State<PremiumButton> createState() => _PremiumButtonState();
+}
+
+class _PremiumButtonState extends State<PremiumButton>
+    with TickerProviderStateMixin {
+  late final AnimationController _animation;
+  bool _heldDown = false;
+
+  @override
+  void initState() {
+    super.initState();
+    _animation =
+        AnimationController(vsync: this, duration: const Duration(seconds: 3));
+    _animation.repeat();
+  }
+
+  @override
+  void dispose() {
+    _animation.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return OpenContainer(
+      openColor: Theme.of(context).scaffoldBackgroundColor,
+      closedColor: Theme.of(context).scaffoldBackgroundColor,
+      clipBehavior: Clip.none,
+      transitionType: ContainerTransitionType.fadeThrough,
+      openElevation: 0,
+      closedElevation: 0,
+      closedShape:
+          RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
+      openBuilder: (context, _) => const PremiumScreen(),
+      closedBuilder: (context, action) => GestureDetector(
+        onTapDown: (_) => setState(() => _heldDown = true),
+        onTapUp: (_) => setState(() => _heldDown = false),
+        onTapCancel: () => setState(() => _heldDown = false),
+        onTap: action,
+        child: Stack(
+          alignment: Alignment.center,
+          children: [
+            // RGB background animation
+            AnimatedBuilder(
+                animation: _animation,
+                builder: (context, child) {
+                  return Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 18.0),
+                    child: ClipRRect(
+                      borderRadius: BorderRadius.circular(14.0),
+                      child: ImageFiltered(
+                        imageFilter:
+                            ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
+                        child: Container(
+                          height: 70,
+                          decoration: BoxDecoration(
+                            gradient: SweepGradient(
+                                colors: const [
+                                  Colors.blue,
+                                  Colors.orange,
+                                  Colors.purple,
+                                  Colors.blue,
+                                ],
+                                transform: GradientRotation(
+                                    _animation.value * 6.283185)),
+                          ),
+                        ),
+                      ),
+                    ),
+                  );
+                }),
+
+            // Button background & text
+            BackdropFilter(
+              filter: ImageFilter.blur(sigmaX: 6.0, sigmaY: 6.0),
+              child: AnimatedScale(
+                duration: const Duration(milliseconds: 250),
+                curve: Curves.easeOutBack,
+                scale: _heldDown ? 1.03 : 1,
+                child: Container(
+                  margin: const EdgeInsets.symmetric(horizontal: 24.0),
+                  width: double.infinity,
+                  height: 60,
+                  decoration: BoxDecoration(
+                    borderRadius: BorderRadius.circular(14.0),
+                    gradient: const LinearGradient(colors: [
+                      Color(0xff124F3D),
+                      Color(0xff1EA18F),
+                    ]),
+                  ),
+                  child: const Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      Icon(FilcIcons.premium, color: Colors.white),
+                      SizedBox(width: 12.0),
+                      Text(
+                        "reFilc Premium",
+                        style: TextStyle(
+                          color: Colors.white,
+                          fontWeight: FontWeight.bold,
+                          fontSize: 20.0,
+                        ),
+                        textAlign: TextAlign.center,
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/premium_screen.dart b/refilc_mobile_ui/lib/premium/premium_screen.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/premium/premium_screen.dart
rename to refilc_mobile_ui/lib/premium/premium_screen.dart
index c710a23..7dd3771
--- a/filcnaplo_mobile_ui/lib/premium/premium_screen.dart
+++ b/refilc_mobile_ui/lib/premium/premium_screen.dart
@@ -1,349 +1,349 @@
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/active_sponsor_card.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/github_card.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/github_connect_button.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/goal_card.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/plan_card.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/reward_card.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/supporters_button.dart';
-import 'package:filcnaplo_mobile_ui/premium/styles/gradients.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/activation_view/activation_view.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/svg.dart';
-import 'package:provider/provider.dart';
-
-class PremiumScreen extends StatelessWidget {
-  const PremiumScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    final middleColor = Theme.of(context).brightness == Brightness.dark
-        ? const Color.fromARGB(255, 20, 57, 46)
-        : const Color.fromARGB(255, 10, 140, 123);
-
-    final future = FilcAPI.getSupporters();
-
-    return FutureBuilder<Supporters?>(
-        future: future,
-        builder: (context, snapshot) {
-          return Scaffold(
-            body: CustomScrollView(
-              physics: const ClampingScrollPhysics(),
-              slivers: [
-                SliverAppBar(
-                  surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-                  automaticallyImplyLeading: false,
-                  flexibleSpace: Container(
-                    decoration: BoxDecoration(
-                      gradient: LinearGradient(
-                        begin: Alignment.topCenter,
-                        end: Alignment.bottomCenter,
-                        colors: [
-                          const Color(0xff124F3D),
-                          middleColor,
-                        ],
-                      ),
-                    ),
-                  ),
-                  actions: [
-                    Padding(
-                      padding: const EdgeInsets.only(right: 8.0),
-                      child: IconButton(
-                        onPressed: () {
-                          Navigator.of(context).pop();
-                        },
-                        icon: const Icon(Icons.close, color: Colors.white),
-                      ),
-                    ),
-                  ],
-                ),
-                SliverPadding(
-                  padding: const EdgeInsets.only(bottom: 25.0),
-                  sliver: SliverToBoxAdapter(
-                    child: Container(
-                      decoration: BoxDecoration(
-                        gradient: LinearGradient(
-                          begin: Alignment.topCenter,
-                          end: Alignment.bottomCenter,
-                          colors: [
-                            middleColor,
-                            Theme.of(context).scaffoldBackgroundColor,
-                          ],
-                        ),
-                      ),
-                      child: Row(
-                        children: [
-                          Expanded(
-                            child: Padding(
-                              padding:
-                                  const EdgeInsets.symmetric(horizontal: 24.0),
-                              child: Column(
-                                crossAxisAlignment: CrossAxisAlignment.start,
-                                children: [
-                                  const SizedBox(height: 64.0),
-                                  Image.asset("assets/images/logo.png"),
-                                  const SizedBox(height: 12.0),
-                                  const Text(
-                                    "Még több filc.",
-                                    style: TextStyle(
-                                        fontWeight: FontWeight.w600,
-                                        fontSize: 25.0,
-                                        color: Colors.white),
-                                  ),
-                                  const Text(
-                                    "reFilc Premium.",
-                                    style: TextStyle(
-                                        fontWeight: FontWeight.w800,
-                                        fontSize: 35.0,
-                                        color: Colors.white),
-                                  ),
-                                  const SizedBox(height: 15.0),
-                                  Text(
-                                    "Támogasd a filcet, és szerezz cserébe pár kényelmes jutalmat!",
-                                    style: TextStyle(
-                                        fontWeight: FontWeight.w500,
-                                        fontSize: 20,
-                                        color: Colors.white.withOpacity(.8)),
-                                  ),
-                                  const SizedBox(height: 25.0),
-                                  SupportersButton(supporters: future),
-                                ],
-                              ),
-                            ),
-                          ),
-                        ],
-                      ),
-                    ),
-                  ),
-                ),
-                SliverPadding(
-                  padding: const EdgeInsets.symmetric(horizontal: 24.0)
-                      .add(const EdgeInsets.only(bottom: 100)),
-                  sliver: SliverToBoxAdapter(
-                    child: Column(
-                      children: [
-                        PremiumPlanCard(
-                          icon: const Icon(FilcIcons.kupak),
-                          title: Text("Kupak",
-                              style: TextStyle(
-                                  foreground: GradientStyles.kupakPaint)),
-                          gradient: GradientStyles.kupak,
-                          price: 2,
-                          description: const Text(
-                              "Szabd személyre a filcet és láss részletesebb statisztikákat."),
-                          url:
-                              "https://github.com/sponsors/filc/sponsorships?tier_id=238453&preview=true",
-                          active: ActiveSponsorCard.estimateLevel(
-                                  context.watch<PremiumProvider>().scopes) ==
-                              PremiumFeatureLevel.kupak,
-                        ),
-                        const SizedBox(height: 8.0),
-                        PremiumPlanCard(
-                          icon: const Icon(FilcIcons.tinta),
-                          title: Text("Tinta",
-                              style: TextStyle(
-                                  foreground: GradientStyles.tintaPaint)),
-                          gradient: GradientStyles.tinta,
-                          price: 5,
-                          description: const Text(
-                              "Kényelmesebb órarend, asztali alkalmazás és célok kitűzése."),
-                          url:
-                              "https://github.com/sponsors/filc/sponsorships?tier_id=238454&preview=true",
-                          active: ActiveSponsorCard.estimateLevel(
-                                  context.watch<PremiumProvider>().scopes) ==
-                              PremiumFeatureLevel.tinta,
-                        ),
-                        const SizedBox(height: 12.0),
-                        PremiumGoalCard(
-                            progress: snapshot.data?.progress ?? 0,
-                            target: snapshot.data?.max ?? 1),
-                        const SizedBox(height: 12.0),
-                        const GithubConnectButton(),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(vertical: 14.0)
-                              .add(const EdgeInsets.only(top: 12.0)),
-                          child: const Row(
-                            children: [
-                              Icon(FilcIcons.kupak),
-                              SizedBox(width: 12.0),
-                              Expanded(
-                                child: Text(
-                                  "Kupak jutalmak",
-                                  style: TextStyle(
-                                      fontWeight: FontWeight.w500,
-                                      fontSize: 20),
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        PremiumRewardCard(
-                          imageKey: "premium_nickname_showcase",
-                          icon: SvgPicture.asset(
-                              "assets/images/nickname_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Profil személyre szabás"),
-                          description: const Text(
-                              "Állíts be egy saját becenevet és egy profilképet (akár animáltat is!)"),
-                        ),
-                        const SizedBox(height: 14.0),
-                        PremiumRewardCard(
-                          imageKey: "premium_theme_showcase",
-                          icon: SvgPicture.asset("assets/images/theme_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Téma+"),
-                          description: const Text(
-                              "Válassz saját háttérszínt és kártyaszínt is, akár saját HEX-kóddal!"),
-                        ),
-                        const SizedBox(height: 14.0),
-                        PremiumRewardCard(
-                          imageKey: "premium_stats_showcase",
-                          icon: SvgPicture.asset("assets/images/stats_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Részletes jegy statisztika"),
-                          description: const Text(
-                              "Válassz heti, havi és háromhavi időtartam közül, és pontosan lásd, mennyi jegyed van."),
-                        ),
-                        const SizedBox(height: 14.0),
-                        const PremiumRewardCard(
-                          title: Text("Még pár dolog..."),
-                          description: Text(
-                              "🔣\tVálassz ikon témát\n✨\tPrémium rang és csevegő a discord szerverünkön\n📬\tElsőbbségi segítségnyújtás"),
-                        ),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(vertical: 14.0)
-                              .add(const EdgeInsets.only(top: 12.0)),
-                          child: const Row(
-                            children: [
-                              Icon(FilcIcons.tinta),
-                              SizedBox(width: 12.0),
-                              Expanded(
-                                child: Text(
-                                  "Tinta jutalmak",
-                                  style: TextStyle(
-                                      fontWeight: FontWeight.w500,
-                                      fontSize: 20),
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        PremiumRewardCard(
-                          imageKey: "premium_timetable_showcase",
-                          icon: SvgPicture.asset(
-                              "assets/images/timetable_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Heti órarend nézet"),
-                          description: const Text(
-                              "Egy órarend, ami a teljes képernyődet kihasználja, csak nem olyan idegesítő, mint az eKRÉTA féle."),
-                        ),
-                        const SizedBox(height: 14.0),
-                        PremiumRewardCard(
-                          imageKey: "premium_widget_showcase",
-                          icon: SvgPicture.asset(
-                              "assets/images/widget_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Widget"),
-                          description: const Text(
-                              "Mindig lásd, milyen órád lesz, a kezdőképernyőd kényelméből."),
-                        ),
-                        const SizedBox(height: 14.0),
-                        PremiumRewardCard(
-                          soon: true,
-                          imageKey: "premium_goal_showcase",
-                          icon: SvgPicture.asset("assets/images/goal_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Cél követés"),
-                          description: const Text(
-                              "Add meg, mi a célod, és mi majd kiszámoljuk, hogyan juthatsz oda!"),
-                        ),
-                        const SizedBox(height: 14.0),
-                        PremiumRewardCard(
-                          soon: true,
-                          imageKey: "premium_desktop_showcase",
-                          icon: SvgPicture.asset(
-                              "assets/images/desktop_icon.svg",
-                              color: Theme.of(context).iconTheme.color),
-                          title: const Text("Asztali verzió"),
-                          description: const Text(
-                              "Érd el a reFilcet a gépeden is, és menekülj meg a csúnya felhasználói felületektől!"),
-                        ),
-                        const SizedBox(height: 14.0),
-                        const PremiumRewardCard(
-                          title: Text("Még pár dolog..."),
-                          description: Text(
-                              "🖋️\tMinden kupak jutalom\n✨\tKorai hozzáférés új verziókhoz"),
-                        ),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(vertical: 14.0)
-                              .add(const EdgeInsets.only(top: 12.0)),
-                          child: const Row(
-                            children: [
-                              SizedBox(width: 12.0),
-                              Expanded(
-                                child: Text(
-                                  "Mire vársz még?",
-                                  style: TextStyle(
-                                      fontWeight: FontWeight.w500,
-                                      fontSize: 20),
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        GithubCard(
-                          onPressed: () {
-                            Navigator.of(context)
-                                .push(MaterialPageRoute(builder: (context) {
-                              return const PremiumActivationView();
-                            }));
-                          },
-                        ),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(vertical: 14.0)
-                              .add(const EdgeInsets.only(top: 12.0)),
-                          child: const Row(
-                            children: [
-                              SizedBox(width: 12.0),
-                              Expanded(
-                                child: Text(
-                                  "Gyakori kérdések",
-                                  style: TextStyle(
-                                      fontWeight: FontWeight.w500,
-                                      fontSize: 20),
-                                ),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const PremiumRewardCard(
-                          title: Text("Mire költitek a pénzt?"),
-                          description: Text(
-                              "A pénz elsősorban az appstore évi \$100-os díját fedezi, a maradék a szerver a weboldal és új funkciók fejlesztésére fordítjuk."),
-                        ),
-                        const SizedBox(height: 14.0),
-                        const PremiumRewardCard(
-                          title: Text("Még mindig nyílt a forráskód?"),
-                          description: Text(
-                              "Igen, a reFilc teljesen nyílt forráskódú, és ez így is fog maradni. A prémium funkciók forráskódjához hozzáférnek a támogatók."),
-                        ),
-                        const SizedBox(height: 14.0),
-                        const PremiumRewardCard(
-                          title: Text("Hol tudok támogatni?"),
-                          description: Text(
-                              "A támogatáshoz szükséged van egy Github profilra, amit hozzá kell kötnöd a filc naplóhoz. A Github “Sponsors” funkciója segítségével kezeljük az támogatásod."),
-                        ),
-                      ],
-                    ),
-                  ),
-                ),
-              ],
-            ),
-          );
-        });
-  }
-}
+import 'package:refilc/api/client.dart';
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc/models/supporter.dart';
+import 'package:refilc_mobile_ui/premium/components/active_sponsor_card.dart';
+import 'package:refilc_mobile_ui/premium/components/github_card.dart';
+import 'package:refilc_mobile_ui/premium/components/github_connect_button.dart';
+import 'package:refilc_mobile_ui/premium/components/goal_card.dart';
+import 'package:refilc_mobile_ui/premium/components/plan_card.dart';
+import 'package:refilc_mobile_ui/premium/components/reward_card.dart';
+import 'package:refilc_mobile_ui/premium/components/supporters_button.dart';
+import 'package:refilc_mobile_ui/premium/styles/gradients.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/activation_view/activation_view.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:provider/provider.dart';
+
+class PremiumScreen extends StatelessWidget {
+  const PremiumScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final middleColor = Theme.of(context).brightness == Brightness.dark
+        ? const Color.fromARGB(255, 20, 57, 46)
+        : const Color.fromARGB(255, 10, 140, 123);
+
+    final future = FilcAPI.getSupporters();
+
+    return FutureBuilder<Supporters?>(
+        future: future,
+        builder: (context, snapshot) {
+          return Scaffold(
+            body: CustomScrollView(
+              physics: const ClampingScrollPhysics(),
+              slivers: [
+                SliverAppBar(
+                  surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+                  automaticallyImplyLeading: false,
+                  flexibleSpace: Container(
+                    decoration: BoxDecoration(
+                      gradient: LinearGradient(
+                        begin: Alignment.topCenter,
+                        end: Alignment.bottomCenter,
+                        colors: [
+                          const Color(0xff124F3D),
+                          middleColor,
+                        ],
+                      ),
+                    ),
+                  ),
+                  actions: [
+                    Padding(
+                      padding: const EdgeInsets.only(right: 8.0),
+                      child: IconButton(
+                        onPressed: () {
+                          Navigator.of(context).pop();
+                        },
+                        icon: const Icon(Icons.close, color: Colors.white),
+                      ),
+                    ),
+                  ],
+                ),
+                SliverPadding(
+                  padding: const EdgeInsets.only(bottom: 25.0),
+                  sliver: SliverToBoxAdapter(
+                    child: Container(
+                      decoration: BoxDecoration(
+                        gradient: LinearGradient(
+                          begin: Alignment.topCenter,
+                          end: Alignment.bottomCenter,
+                          colors: [
+                            middleColor,
+                            Theme.of(context).scaffoldBackgroundColor,
+                          ],
+                        ),
+                      ),
+                      child: Row(
+                        children: [
+                          Expanded(
+                            child: Padding(
+                              padding:
+                                  const EdgeInsets.symmetric(horizontal: 24.0),
+                              child: Column(
+                                crossAxisAlignment: CrossAxisAlignment.start,
+                                children: [
+                                  const SizedBox(height: 64.0),
+                                  Image.asset("assets/images/logo.png"),
+                                  const SizedBox(height: 12.0),
+                                  const Text(
+                                    "Még több filc.",
+                                    style: TextStyle(
+                                        fontWeight: FontWeight.w600,
+                                        fontSize: 25.0,
+                                        color: Colors.white),
+                                  ),
+                                  const Text(
+                                    "reFilc Premium.",
+                                    style: TextStyle(
+                                        fontWeight: FontWeight.w800,
+                                        fontSize: 35.0,
+                                        color: Colors.white),
+                                  ),
+                                  const SizedBox(height: 15.0),
+                                  Text(
+                                    "Támogasd a filcet, és szerezz cserébe pár kényelmes jutalmat!",
+                                    style: TextStyle(
+                                        fontWeight: FontWeight.w500,
+                                        fontSize: 20,
+                                        color: Colors.white.withOpacity(.8)),
+                                  ),
+                                  const SizedBox(height: 25.0),
+                                  SupportersButton(supporters: future),
+                                ],
+                              ),
+                            ),
+                          ),
+                        ],
+                      ),
+                    ),
+                  ),
+                ),
+                SliverPadding(
+                  padding: const EdgeInsets.symmetric(horizontal: 24.0)
+                      .add(const EdgeInsets.only(bottom: 100)),
+                  sliver: SliverToBoxAdapter(
+                    child: Column(
+                      children: [
+                        PremiumPlanCard(
+                          icon: const Icon(FilcIcons.kupak),
+                          title: Text("Kupak",
+                              style: TextStyle(
+                                  foreground: GradientStyles.kupakPaint)),
+                          gradient: GradientStyles.kupak,
+                          price: 2,
+                          description: const Text(
+                              "Szabd személyre a filcet és láss részletesebb statisztikákat."),
+                          url:
+                              "https://github.com/sponsors/filc/sponsorships?tier_id=238453&preview=true",
+                          active: ActiveSponsorCard.estimateLevel(
+                                  context.watch<PremiumProvider>().scopes) ==
+                              PremiumFeatureLevel.kupak,
+                        ),
+                        const SizedBox(height: 8.0),
+                        PremiumPlanCard(
+                          icon: const Icon(FilcIcons.tinta),
+                          title: Text("Tinta",
+                              style: TextStyle(
+                                  foreground: GradientStyles.tintaPaint)),
+                          gradient: GradientStyles.tinta,
+                          price: 5,
+                          description: const Text(
+                              "Kényelmesebb órarend, asztali alkalmazás és célok kitűzése."),
+                          url:
+                              "https://github.com/sponsors/filc/sponsorships?tier_id=238454&preview=true",
+                          active: ActiveSponsorCard.estimateLevel(
+                                  context.watch<PremiumProvider>().scopes) ==
+                              PremiumFeatureLevel.tinta,
+                        ),
+                        const SizedBox(height: 12.0),
+                        PremiumGoalCard(
+                            progress: snapshot.data?.progress ?? 0,
+                            target: snapshot.data?.max ?? 1),
+                        const SizedBox(height: 12.0),
+                        const GithubConnectButton(),
+                        Padding(
+                          padding: const EdgeInsets.symmetric(vertical: 14.0)
+                              .add(const EdgeInsets.only(top: 12.0)),
+                          child: const Row(
+                            children: [
+                              Icon(FilcIcons.kupak),
+                              SizedBox(width: 12.0),
+                              Expanded(
+                                child: Text(
+                                  "Kupak jutalmak",
+                                  style: TextStyle(
+                                      fontWeight: FontWeight.w500,
+                                      fontSize: 20),
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                        PremiumRewardCard(
+                          imageKey: "premium_nickname_showcase",
+                          icon: SvgPicture.asset(
+                              "assets/images/nickname_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Profil személyre szabás"),
+                          description: const Text(
+                              "Állíts be egy saját becenevet és egy profilképet (akár animáltat is!)"),
+                        ),
+                        const SizedBox(height: 14.0),
+                        PremiumRewardCard(
+                          imageKey: "premium_theme_showcase",
+                          icon: SvgPicture.asset("assets/images/theme_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Téma+"),
+                          description: const Text(
+                              "Válassz saját háttérszínt és kártyaszínt is, akár saját HEX-kóddal!"),
+                        ),
+                        const SizedBox(height: 14.0),
+                        PremiumRewardCard(
+                          imageKey: "premium_stats_showcase",
+                          icon: SvgPicture.asset("assets/images/stats_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Részletes jegy statisztika"),
+                          description: const Text(
+                              "Válassz heti, havi és háromhavi időtartam közül, és pontosan lásd, mennyi jegyed van."),
+                        ),
+                        const SizedBox(height: 14.0),
+                        const PremiumRewardCard(
+                          title: Text("Még pár dolog..."),
+                          description: Text(
+                              "🔣\tVálassz ikon témát\n✨\tPrémium rang és csevegő a discord szerverünkön\n📬\tElsőbbségi segítségnyújtás"),
+                        ),
+                        Padding(
+                          padding: const EdgeInsets.symmetric(vertical: 14.0)
+                              .add(const EdgeInsets.only(top: 12.0)),
+                          child: const Row(
+                            children: [
+                              Icon(FilcIcons.tinta),
+                              SizedBox(width: 12.0),
+                              Expanded(
+                                child: Text(
+                                  "Tinta jutalmak",
+                                  style: TextStyle(
+                                      fontWeight: FontWeight.w500,
+                                      fontSize: 20),
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                        PremiumRewardCard(
+                          imageKey: "premium_timetable_showcase",
+                          icon: SvgPicture.asset(
+                              "assets/images/timetable_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Heti órarend nézet"),
+                          description: const Text(
+                              "Egy órarend, ami a teljes képernyődet kihasználja, csak nem olyan idegesítő, mint az eKRÉTA féle."),
+                        ),
+                        const SizedBox(height: 14.0),
+                        PremiumRewardCard(
+                          imageKey: "premium_widget_showcase",
+                          icon: SvgPicture.asset(
+                              "assets/images/widget_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Widget"),
+                          description: const Text(
+                              "Mindig lásd, milyen órád lesz, a kezdőképernyőd kényelméből."),
+                        ),
+                        const SizedBox(height: 14.0),
+                        PremiumRewardCard(
+                          soon: true,
+                          imageKey: "premium_goal_showcase",
+                          icon: SvgPicture.asset("assets/images/goal_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Cél követés"),
+                          description: const Text(
+                              "Add meg, mi a célod, és mi majd kiszámoljuk, hogyan juthatsz oda!"),
+                        ),
+                        const SizedBox(height: 14.0),
+                        PremiumRewardCard(
+                          soon: true,
+                          imageKey: "premium_desktop_showcase",
+                          icon: SvgPicture.asset(
+                              "assets/images/desktop_icon.svg",
+                              color: Theme.of(context).iconTheme.color),
+                          title: const Text("Asztali verzió"),
+                          description: const Text(
+                              "Érd el a reFilcet a gépeden is, és menekülj meg a csúnya felhasználói felületektől!"),
+                        ),
+                        const SizedBox(height: 14.0),
+                        const PremiumRewardCard(
+                          title: Text("Még pár dolog..."),
+                          description: Text(
+                              "🖋️\tMinden kupak jutalom\n✨\tKorai hozzáférés új verziókhoz"),
+                        ),
+                        Padding(
+                          padding: const EdgeInsets.symmetric(vertical: 14.0)
+                              .add(const EdgeInsets.only(top: 12.0)),
+                          child: const Row(
+                            children: [
+                              SizedBox(width: 12.0),
+                              Expanded(
+                                child: Text(
+                                  "Mire vársz még?",
+                                  style: TextStyle(
+                                      fontWeight: FontWeight.w500,
+                                      fontSize: 20),
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                        GithubCard(
+                          onPressed: () {
+                            Navigator.of(context)
+                                .push(MaterialPageRoute(builder: (context) {
+                              return const PremiumActivationView();
+                            }));
+                          },
+                        ),
+                        Padding(
+                          padding: const EdgeInsets.symmetric(vertical: 14.0)
+                              .add(const EdgeInsets.only(top: 12.0)),
+                          child: const Row(
+                            children: [
+                              SizedBox(width: 12.0),
+                              Expanded(
+                                child: Text(
+                                  "Gyakori kérdések",
+                                  style: TextStyle(
+                                      fontWeight: FontWeight.w500,
+                                      fontSize: 20),
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                        const PremiumRewardCard(
+                          title: Text("Mire költitek a pénzt?"),
+                          description: Text(
+                              "A pénz elsősorban az appstore évi \$100-os díját fedezi, a maradék a szerver a weboldal és új funkciók fejlesztésére fordítjuk."),
+                        ),
+                        const SizedBox(height: 14.0),
+                        const PremiumRewardCard(
+                          title: Text("Még mindig nyílt a forráskód?"),
+                          description: Text(
+                              "Igen, a reFilc teljesen nyílt forráskódú, és ez így is fog maradni. A prémium funkciók forráskódjához hozzáférnek a támogatók."),
+                        ),
+                        const SizedBox(height: 14.0),
+                        const PremiumRewardCard(
+                          title: Text("Hol tudok támogatni?"),
+                          description: Text(
+                              "A támogatáshoz szükséged van egy Github profilra, amit hozzá kell kötnöd a filc naplóhoz. A Github “Sponsors” funkciója segítségével kezeljük az támogatásod."),
+                        ),
+                      ],
+                    ),
+                  ),
+                ),
+              ],
+            ),
+          );
+        });
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/styles/gradients.dart b/refilc_mobile_ui/lib/premium/styles/gradients.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/premium/styles/gradients.dart
rename to refilc_mobile_ui/lib/premium/styles/gradients.dart
index 408f006..17fa6de
--- a/filcnaplo_mobile_ui/lib/premium/styles/gradients.dart
+++ b/refilc_mobile_ui/lib/premium/styles/gradients.dart
@@ -1,13 +1,13 @@
-import 'package:flutter/widgets.dart';
-
-class GradientStyles {
-  static const tinta = LinearGradient(
-    colors: [Color(0xffB816E0), Color(0xff17D1BB)],
-  );
-  static final tintaPaint = Paint()..shader = tinta.createShader(const Rect.fromLTWH(0, 0, 200, 70));
-
-  static const kupak = LinearGradient(
-    colors: [Color(0xffF0BD0C), Color(0xff0CD070)],
-  );
-  static final kupakPaint = Paint()..shader = kupak.createShader(const Rect.fromLTWH(0, 0, 200, 70));
-}
+import 'package:flutter/widgets.dart';
+
+class GradientStyles {
+  static const tinta = LinearGradient(
+    colors: [Color(0xffB816E0), Color(0xff17D1BB)],
+  );
+  static final tintaPaint = Paint()..shader = tinta.createShader(const Rect.fromLTWH(0, 0, 200, 70));
+
+  static const kupak = LinearGradient(
+    colors: [Color(0xffF0BD0C), Color(0xff0CD070)],
+  );
+  static final kupakPaint = Paint()..shader = kupak.createShader(const Rect.fromLTWH(0, 0, 200, 70));
+}
diff --git a/filcnaplo_mobile_ui/lib/premium/supporters_screen.dart b/refilc_mobile_ui/lib/premium/supporters_screen.dart
old mode 100755
new mode 100644
similarity index 70%
rename from filcnaplo_mobile_ui/lib/premium/supporters_screen.dart
rename to refilc_mobile_ui/lib/premium/supporters_screen.dart
index 1f250ca..82d89b7
--- a/filcnaplo_mobile_ui/lib/premium/supporters_screen.dart
+++ b/refilc_mobile_ui/lib/premium/supporters_screen.dart
@@ -1,121 +1,143 @@
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo/models/supporter.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/premium/components/supporter_group_card.dart';
-import 'package:filcnaplo_mobile_ui/premium/styles/gradients.dart';
-import 'package:flutter/material.dart';
-
-class SupportersScreen extends StatelessWidget {
-  const SupportersScreen({Key? key, required this.supporters}) : super(key: key);
-
-  final Future<Supporters?> supporters;
-
-  @override
-  Widget build(BuildContext context) {
-    return FutureBuilder<Supporters?>(
-        future: supporters,
-        builder: (context, snapshot) {
-          final highlightedSupporters =
-              snapshot.data?.github.where((e) => e.type == DonationType.monthly && e.price >= 5 && e.comment != "").toList() ?? [];
-          final tintaSupporters =
-              snapshot.data?.github.where((e) => e.type == DonationType.monthly && e.price >= 5 && e.comment == "").toList() ?? [];
-          final kupakSupporters = snapshot.data?.github.where((e) => e.type == DonationType.monthly && e.price == 2).toList() ?? [];
-          final onetimeSupporters = snapshot.data?.github.where((e) => e.type == DonationType.once && e.price >= 5).toList() ?? [];
-          final patreonSupporters = snapshot.data?.patreon ?? [];
-
-          return Scaffold(
-            body: CustomScrollView(
-              slivers: [
-                SliverAppBar.large(
-                  surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-                  title: const Text(
-                    "Támogatók",
-                    style: TextStyle(fontWeight: FontWeight.w700),
-                  ),
-                ),
-                if (snapshot.hasData)
-                  SliverPadding(
-                    padding: const EdgeInsets.symmetric(horizontal: 16.0).add(const EdgeInsets.only(bottom: 24.0)),
-                    sliver: SliverToBoxAdapter(
-                      child: Text(
-                        snapshot.data!.description,
-                        style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0, color: AppColors.of(context).text.withOpacity(.7)),
-                      ),
-                    ),
-                  ),
-                if (!snapshot.hasData)
-                  const SliverPadding(
-                    padding: EdgeInsets.all(12.0),
-                    sliver: SliverToBoxAdapter(
-                      child: Center(child: CircularProgressIndicator()),
-                    ),
-                  ),
-                if (highlightedSupporters.isNotEmpty)
-                  SliverPadding(
-                    padding: const EdgeInsets.all(12.0),
-                    sliver: SliverToBoxAdapter(
-                      child: SupporterGroupCard(
-                        title: const Text("Kiemelt támogatók"),
-                        expanded: true,
-                        supporters: highlightedSupporters,
-                      ),
-                    ),
-                  ),
-                if (tintaSupporters.isNotEmpty)
-                  SliverPadding(
-                    padding: const EdgeInsets.all(12.0),
-                    sliver: SliverToBoxAdapter(
-                      child: SupporterGroupCard(
-                        icon: const Icon(FilcIcons.tinta),
-                        title: Text(
-                          "Tinta",
-                          style: TextStyle(
-                            foreground: GradientStyles.tintaPaint,
-                          ),
-                        ),
-                        glow: Colors.purple,
-                        supporters: tintaSupporters,
-                      ),
-                    ),
-                  ),
-                if (kupakSupporters.isNotEmpty)
-                  SliverPadding(
-                    padding: const EdgeInsets.all(12.0),
-                    sliver: SliverToBoxAdapter(
-                      child: SupporterGroupCard(
-                        icon: const Icon(FilcIcons.kupak),
-                        title: Text(
-                          "Kupak",
-                          style: TextStyle(foreground: GradientStyles.kupakPaint),
-                        ),
-                        glow: Colors.lightGreen,
-                        supporters: kupakSupporters,
-                      ),
-                    ),
-                  ),
-                if (onetimeSupporters.isNotEmpty)
-                  SliverPadding(
-                    padding: const EdgeInsets.all(12.0),
-                    sliver: SliverToBoxAdapter(
-                      child: SupporterGroupCard(
-                        title: const Text("Egyszeri támogatók"),
-                        supporters: onetimeSupporters,
-                      ),
-                    ),
-                  ),
-                if (patreonSupporters.isNotEmpty)
-                  SliverPadding(
-                    padding: const EdgeInsets.all(12.0),
-                    sliver: SliverToBoxAdapter(
-                      child: SupporterGroupCard(
-                        title: const Text("Régebbi támogatóink"),
-                        supporters: patreonSupporters,
-                      ),
-                    ),
-                  ),
-              ],
-            ),
-          );
-        });
-  }
-}
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc/models/supporter.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_mobile_ui/premium/components/supporter_group_card.dart';
+import 'package:refilc_mobile_ui/premium/styles/gradients.dart';
+import 'package:flutter/material.dart';
+
+class SupportersScreen extends StatelessWidget {
+  const SupportersScreen({Key? key, required this.supporters})
+      : super(key: key);
+
+  final Future<Supporters?> supporters;
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder<Supporters?>(
+        future: supporters,
+        builder: (context, snapshot) {
+          final highlightedSupporters = snapshot.data?.github
+                  .where((e) =>
+                      e.type == DonationType.monthly &&
+                      e.price >= 5 &&
+                      e.comment != "")
+                  .toList() ??
+              [];
+          final tintaSupporters = snapshot.data?.github
+                  .where((e) =>
+                      e.type == DonationType.monthly &&
+                      e.price >= 5 &&
+                      e.comment == "")
+                  .toList() ??
+              [];
+          final kupakSupporters = snapshot.data?.github
+                  .where((e) => e.type == DonationType.monthly && e.price == 2)
+                  .toList() ??
+              [];
+          final onetimeSupporters = snapshot.data?.github
+                  .where((e) => e.type == DonationType.once && e.price >= 5)
+                  .toList() ??
+              [];
+          final patreonSupporters = snapshot.data?.patreon ?? [];
+
+          return Scaffold(
+            body: CustomScrollView(
+              slivers: [
+                SliverAppBar.large(
+                  surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+                  title: const Text(
+                    "Támogatók",
+                    style: TextStyle(fontWeight: FontWeight.w700),
+                  ),
+                ),
+                if (snapshot.hasData)
+                  SliverPadding(
+                    padding: const EdgeInsets.symmetric(horizontal: 16.0)
+                        .add(const EdgeInsets.only(bottom: 24.0)),
+                    sliver: SliverToBoxAdapter(
+                      child: Text(
+                        snapshot.data!.description,
+                        style: TextStyle(
+                            fontWeight: FontWeight.w500,
+                            fontSize: 20.0,
+                            color: AppColors.of(context).text.withOpacity(.7)),
+                      ),
+                    ),
+                  ),
+                if (!snapshot.hasData)
+                  const SliverPadding(
+                    padding: EdgeInsets.all(12.0),
+                    sliver: SliverToBoxAdapter(
+                      child: Center(child: CircularProgressIndicator()),
+                    ),
+                  ),
+                if (highlightedSupporters.isNotEmpty)
+                  SliverPadding(
+                    padding: const EdgeInsets.all(12.0),
+                    sliver: SliverToBoxAdapter(
+                      child: SupporterGroupCard(
+                        title: const Text("Kiemelt támogatók"),
+                        expanded: true,
+                        supporters: highlightedSupporters,
+                      ),
+                    ),
+                  ),
+                if (tintaSupporters.isNotEmpty)
+                  SliverPadding(
+                    padding: const EdgeInsets.all(12.0),
+                    sliver: SliverToBoxAdapter(
+                      child: SupporterGroupCard(
+                        icon: const Icon(FilcIcons.tinta),
+                        title: Text(
+                          "Tinta",
+                          style: TextStyle(
+                            foreground: GradientStyles.tintaPaint,
+                          ),
+                        ),
+                        glow: Colors.purple,
+                        supporters: tintaSupporters,
+                      ),
+                    ),
+                  ),
+                if (kupakSupporters.isNotEmpty)
+                  SliverPadding(
+                    padding: const EdgeInsets.all(12.0),
+                    sliver: SliverToBoxAdapter(
+                      child: SupporterGroupCard(
+                        icon: const Icon(FilcIcons.kupak),
+                        title: Text(
+                          "Kupak",
+                          style:
+                              TextStyle(foreground: GradientStyles.kupakPaint),
+                        ),
+                        glow: Colors.lightGreen,
+                        supporters: kupakSupporters,
+                      ),
+                    ),
+                  ),
+                if (onetimeSupporters.isNotEmpty)
+                  SliverPadding(
+                    padding: const EdgeInsets.all(12.0),
+                    sliver: SliverToBoxAdapter(
+                      child: SupporterGroupCard(
+                        title: const Text("Egyszeri támogatók"),
+                        supporters: onetimeSupporters,
+                      ),
+                    ),
+                  ),
+                if (patreonSupporters.isNotEmpty)
+                  SliverPadding(
+                    padding: const EdgeInsets.all(12.0),
+                    sliver: SliverToBoxAdapter(
+                      child: SupporterGroupCard(
+                        title: const Text("Régebbi támogatóink"),
+                        supporters: patreonSupporters,
+                      ),
+                    ),
+                  ),
+              ],
+            ),
+          );
+        });
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/error_report_screen.dart b/refilc_mobile_ui/lib/screens/error_report_screen.dart
old mode 100755
new mode 100644
similarity index 78%
rename from filcnaplo_mobile_ui/lib/screens/error_report_screen.dart
rename to refilc_mobile_ui/lib/screens/error_report_screen.dart
index d4f87ef..6523157
--- a/filcnaplo_mobile_ui/lib/screens/error_report_screen.dart
+++ b/refilc_mobile_ui/lib/screens/error_report_screen.dart
@@ -1,200 +1,220 @@
-import 'dart:io';
-import 'dart:math';
-
-import 'package:filcnaplo/api/client.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'error_report_screen.i18n.dart';
-
-class ErrorReportScreen extends StatelessWidget {
-  final FlutterErrorDetails details;
-
-  const ErrorReportScreen(this.details, {Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: Colors.red,
-      body: SafeArea(
-        child: Padding(
-          padding: const EdgeInsets.all(12.0),
-          child: Column(
-            children: [
-              const Align(
-                child: BackButton(),
-                alignment: Alignment.topLeft,
-              ),
-              const Spacer(),
-              const Icon(
-                FeatherIcons.alertTriangle,
-                size: 100,
-              ),
-              const Spacer(),
-              Padding(
-                padding: const EdgeInsets.only(bottom: 4.0),
-                child: Text(
-                  "uhoh".i18n,
-                  style: const TextStyle(
-                    color: Colors.white,
-                    fontSize: 32.0,
-                    fontWeight: FontWeight.w900,
-                  ),
-                ),
-              ),
-              Text(
-                "description".i18n,
-                style: TextStyle(
-                  color: Colors.white.withOpacity(.95),
-                  fontSize: 24.0,
-                  fontWeight: FontWeight.w700,
-                ),
-              ),
-              const Spacer(),
-              Stack(
-                alignment: Alignment.topRight,
-                children: [
-                  Container(
-                    height: 110.0,
-                    width: double.infinity,
-                    padding: const EdgeInsets.all(12.0),
-                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(12.0), color: Colors.black.withOpacity(.2)),
-                    child: SingleChildScrollView(
-                      physics: const BouncingScrollPhysics(),
-                      child: Text(
-                        details.exceptionAsString(),
-                        style: const TextStyle(fontFamily: 'SpaceMono'),
-                      ),
-                    ),
-                  ),
-                  IconButton(
-                    icon: const Icon(FeatherIcons.info),
-                    onPressed: () {
-                      showDialog(context: context, builder: (context) => StacktracePopup(details));
-                    },
-                  )
-                ],
-              ),
-              const Spacer(),
-              SizedBox(
-                width: double.infinity,
-                child: TextButton(
-                  style: ButtonStyle(
-                    padding: MaterialStateProperty.all(const EdgeInsets.symmetric(vertical: 14.0)),
-                    backgroundColor: MaterialStateProperty.all(Colors.white),
-                    shape: MaterialStateProperty.all(
-                      RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
-                    ),
-                  ),
-                  child: Text(
-                    "submit".i18n,
-                    style: const TextStyle(
-                      color: Colors.black,
-                      fontSize: 17.0,
-                      fontWeight: FontWeight.bold,
-                    ),
-                  ),
-                  onPressed: () => reportProblem(context),
-                ),
-              ),
-              const SizedBox(height: 32.0)
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-
-  Future reportProblem(BuildContext context) async {
-    final report = ErrorReport(
-      os: Platform.operatingSystem + " " + Platform.operatingSystemVersion,
-      error: details.exceptionAsString(),
-      version: const String.fromEnvironment("APPVER", defaultValue: "?"),
-      stack: details.stack.toString(),
-    );
-    FilcAPI.sendReport(report);
-    Navigator.pop(context);
-  }
-}
-
-class StacktracePopup extends StatelessWidget {
-  final FlutterErrorDetails details;
-
-  const StacktracePopup(this.details, {Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    String stack = details.stack.toString();
-
-    return Container(
-      margin: const EdgeInsets.all(32.0),
-      child: Scaffold(
-        backgroundColor: Colors.transparent,
-        body: Container(
-          decoration: BoxDecoration(
-            color: Theme.of(context).scaffoldBackgroundColor,
-            borderRadius: BorderRadius.circular(4.0),
-          ),
-          padding: const EdgeInsets.only(top: 15.0, right: 15.0, left: 15.0),
-          child: Column(
-            children: [
-              Expanded(
-                child: ListView(children: [
-                  Padding(
-                    padding: const EdgeInsets.only(bottom: 10.0),
-                    child: Text(
-                      "details".i18n,
-                      style: const TextStyle(fontSize: 20.0),
-                    ),
-                  ),
-                  ErrorDetail(
-                    "error".i18n,
-                    details.exceptionAsString(),
-                  ),
-                  ErrorDetail("os".i18n, Platform.operatingSystem + " " + Platform.operatingSystemVersion),
-                  ErrorDetail("version".i18n, const String.fromEnvironment("APPVER", defaultValue: "?")),
-                  ErrorDetail("stack".i18n, stack.substring(0, min(stack.length, 5000)))
-                ]),
-              ),
-              TextButton(
-                  child: Text("done".i18n, style: TextStyle(color: Theme.of(context).colorScheme.secondary)),
-                  onPressed: () {
-                    Navigator.of(context).pop();
-                  })
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-class ErrorDetail extends StatelessWidget {
-  final String title;
-  final String content;
-
-  const ErrorDetail(this.title, this.content, {Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 10.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Text(
-            title,
-            style: const TextStyle(fontWeight: FontWeight.bold),
-          ),
-          Container(
-              child: Text(
-                content,
-                style: const TextStyle(fontFamily: 'SpaceMono', color: Colors.white),
-              ),
-              padding: const EdgeInsets.symmetric(horizontal: 6.5, vertical: 4.0),
-              margin: const EdgeInsets.only(top: 4.0),
-              decoration: BoxDecoration(color: Colors.black26, borderRadius: BorderRadius.circular(4.0)))
-        ],
-      ),
-    );
-  }
-}
+import 'dart:io';
+import 'dart:math';
+
+import 'package:refilc/api/client.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'error_report_screen.i18n.dart';
+
+class ErrorReportScreen extends StatelessWidget {
+  final FlutterErrorDetails details;
+
+  const ErrorReportScreen(this.details, {Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      backgroundColor: Colors.red,
+      body: SafeArea(
+        child: Padding(
+          padding: const EdgeInsets.all(12.0),
+          child: Column(
+            children: [
+              const Align(
+                child: BackButton(),
+                alignment: Alignment.topLeft,
+              ),
+              const Spacer(),
+              const Icon(
+                FeatherIcons.alertTriangle,
+                size: 100,
+              ),
+              const Spacer(),
+              Padding(
+                padding: const EdgeInsets.only(bottom: 4.0),
+                child: Text(
+                  "uhoh".i18n,
+                  style: const TextStyle(
+                    color: Colors.white,
+                    fontSize: 32.0,
+                    fontWeight: FontWeight.w900,
+                  ),
+                ),
+              ),
+              Text(
+                "description".i18n,
+                style: TextStyle(
+                  color: Colors.white.withOpacity(.95),
+                  fontSize: 24.0,
+                  fontWeight: FontWeight.w700,
+                ),
+              ),
+              const Spacer(),
+              Stack(
+                alignment: Alignment.topRight,
+                children: [
+                  Container(
+                    height: 110.0,
+                    width: double.infinity,
+                    padding: const EdgeInsets.all(12.0),
+                    decoration: BoxDecoration(
+                        borderRadius: BorderRadius.circular(12.0),
+                        color: Colors.black.withOpacity(.2)),
+                    child: SingleChildScrollView(
+                      physics: const BouncingScrollPhysics(),
+                      child: Text(
+                        details.exceptionAsString(),
+                        style: const TextStyle(fontFamily: 'SpaceMono'),
+                      ),
+                    ),
+                  ),
+                  IconButton(
+                    icon: const Icon(FeatherIcons.info),
+                    onPressed: () {
+                      showDialog(
+                          context: context,
+                          builder: (context) => StacktracePopup(details));
+                    },
+                  )
+                ],
+              ),
+              const Spacer(),
+              SizedBox(
+                width: double.infinity,
+                child: TextButton(
+                  style: ButtonStyle(
+                    padding: MaterialStateProperty.all(
+                        const EdgeInsets.symmetric(vertical: 14.0)),
+                    backgroundColor: MaterialStateProperty.all(Colors.white),
+                    shape: MaterialStateProperty.all(
+                      RoundedRectangleBorder(
+                          borderRadius: BorderRadius.circular(12.0)),
+                    ),
+                  ),
+                  child: Text(
+                    "submit".i18n,
+                    style: const TextStyle(
+                      color: Colors.black,
+                      fontSize: 17.0,
+                      fontWeight: FontWeight.bold,
+                    ),
+                  ),
+                  onPressed: () => reportProblem(context),
+                ),
+              ),
+              const SizedBox(height: 32.0)
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  Future reportProblem(BuildContext context) async {
+    final report = ErrorReport(
+      os: Platform.operatingSystem + " " + Platform.operatingSystemVersion,
+      error: details.exceptionAsString(),
+      version: const String.fromEnvironment("APPVER", defaultValue: "?"),
+      stack: details.stack.toString(),
+    );
+    FilcAPI.sendReport(report);
+    Navigator.pop(context);
+  }
+}
+
+class StacktracePopup extends StatelessWidget {
+  final FlutterErrorDetails details;
+
+  const StacktracePopup(this.details, {Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    String stack = details.stack.toString();
+
+    return Container(
+      margin: const EdgeInsets.all(32.0),
+      child: Scaffold(
+        backgroundColor: Colors.transparent,
+        body: Container(
+          decoration: BoxDecoration(
+            color: Theme.of(context).scaffoldBackgroundColor,
+            borderRadius: BorderRadius.circular(4.0),
+          ),
+          padding: const EdgeInsets.only(top: 15.0, right: 15.0, left: 15.0),
+          child: Column(
+            children: [
+              Expanded(
+                child: ListView(children: [
+                  Padding(
+                    padding: const EdgeInsets.only(bottom: 10.0),
+                    child: Text(
+                      "details".i18n,
+                      style: const TextStyle(fontSize: 20.0),
+                    ),
+                  ),
+                  ErrorDetail(
+                    "error".i18n,
+                    details.exceptionAsString(),
+                  ),
+                  ErrorDetail(
+                      "os".i18n,
+                      Platform.operatingSystem +
+                          " " +
+                          Platform.operatingSystemVersion),
+                  ErrorDetail(
+                      "version".i18n,
+                      const String.fromEnvironment("APPVER",
+                          defaultValue: "?")),
+                  ErrorDetail(
+                      "stack".i18n, stack.substring(0, min(stack.length, 5000)))
+                ]),
+              ),
+              TextButton(
+                  child: Text("done".i18n,
+                      style: TextStyle(
+                          color: Theme.of(context).colorScheme.secondary)),
+                  onPressed: () {
+                    Navigator.of(context).pop();
+                  })
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class ErrorDetail extends StatelessWidget {
+  final String title;
+  final String content;
+
+  const ErrorDetail(this.title, this.content, {Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 10.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Text(
+            title,
+            style: const TextStyle(fontWeight: FontWeight.bold),
+          ),
+          Container(
+              child: Text(
+                content,
+                style: const TextStyle(
+                    fontFamily: 'SpaceMono', color: Colors.white),
+              ),
+              padding:
+                  const EdgeInsets.symmetric(horizontal: 6.5, vertical: 4.0),
+              margin: const EdgeInsets.only(top: 4.0),
+              decoration: BoxDecoration(
+                  color: Colors.black26,
+                  borderRadius: BorderRadius.circular(4.0)))
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/error_report_screen.i18n.dart b/refilc_mobile_ui/lib/screens/error_report_screen.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/error_report_screen.i18n.dart
rename to refilc_mobile_ui/lib/screens/error_report_screen.i18n.dart
index bcec16b..498e799
--- a/filcnaplo_mobile_ui/lib/screens/error_report_screen.i18n.dart
+++ b/refilc_mobile_ui/lib/screens/error_report_screen.i18n.dart
@@ -1,45 +1,45 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension SettingsLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "uhoh": "Uh Oh!",
-          "description": "An error occurred!",
-          "submit": "Submit",
-          "details": "Details",
-          "error": "Error",
-          "os": "Operating System",
-          "version": "App Version",
-          "stack": "Stack Trace",
-          "done": "Done",
-        },
-        "hu_hu": {
-          "uhoh": "Ajajj!",
-          "description": "Hiba történt!",
-          "submit": "Probléma Jelentése",
-          "details": "Részletek",
-          "error": "Hiba",
-          "os": "Operációs Rendszer",
-          "version": "App Verzió",
-          "stack": "Stacktrace",
-          "done": "Kész",
-        },
-        "de_de": {
-          "uhoh": "Uh Oh!",
-          "description": "Ein Fehler ist aufgetreten!",
-          "submit": "Abschicken",
-          "details": "Details",
-          "error": "Fehler",
-          "os": "Betriebssystem",
-          "version": "App Version",
-          "stack": "Stack Trace",
-          "done": "Fertig",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension SettingsLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "uhoh": "Uh Oh!",
+          "description": "An error occurred!",
+          "submit": "Submit",
+          "details": "Details",
+          "error": "Error",
+          "os": "Operating System",
+          "version": "App Version",
+          "stack": "Stack Trace",
+          "done": "Done",
+        },
+        "hu_hu": {
+          "uhoh": "Ajajj!",
+          "description": "Hiba történt!",
+          "submit": "Probléma Jelentése",
+          "details": "Részletek",
+          "error": "Hiba",
+          "os": "Operációs Rendszer",
+          "version": "App Verzió",
+          "stack": "Stacktrace",
+          "done": "Kész",
+        },
+        "de_de": {
+          "uhoh": "Uh Oh!",
+          "description": "Ein Fehler ist aufgetreten!",
+          "submit": "Abschicken",
+          "details": "Details",
+          "error": "Fehler",
+          "os": "Betriebssystem",
+          "version": "App Version",
+          "stack": "Stack Trace",
+          "done": "Fertig",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/error_screen.dart b/refilc_mobile_ui/lib/screens/error_screen.dart
old mode 100755
new mode 100644
similarity index 90%
rename from filcnaplo_mobile_ui/lib/screens/error_screen.dart
rename to refilc_mobile_ui/lib/screens/error_screen.dart
index d33198f..09a9f16
--- a/filcnaplo_mobile_ui/lib/screens/error_screen.dart
+++ b/refilc_mobile_ui/lib/screens/error_screen.dart
@@ -1,64 +1,65 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-class ErrorScreen extends StatelessWidget {
-  const ErrorScreen(this.details, {Key? key}) : super(key: key);
-
-  final FlutterErrorDetails details;
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: AppBar(
-        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-        leading: BackButton(color: AppColors.of(context).text),
-        shadowColor: Colors.transparent,
-      ),
-      body: SafeArea(
-        child: Padding(
-          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-          child: Column(
-            children: [
-              Padding(
-                padding: const EdgeInsets.all(12.0),
-                child: Icon(FeatherIcons.alertTriangle, size: 48.0, color: AppColors.of(context).red),
-              ),
-              const Padding(
-                padding: EdgeInsets.all(12.0),
-                child: Text(
-                  "An error occurred...",
-                  style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0),
-                ),
-              ),
-              Expanded(
-                child: Container(
-                  padding: const EdgeInsets.all(12.0),
-                  width: double.infinity,
-                  decoration: BoxDecoration(
-                    borderRadius: BorderRadius.circular(14.0),
-                    color: Theme.of(context).colorScheme.background,
-                  ),
-                  child: CupertinoScrollbar(
-                    child: SingleChildScrollView(
-                      physics: const BouncingScrollPhysics(),
-                      child: SingleChildScrollView(
-                        physics: const BouncingScrollPhysics(),
-                        scrollDirection: Axis.horizontal,
-                        child: SelectableText(
-                          (details.exceptionAsString() + '\n'),
-                          style: const TextStyle(fontFamily: "monospace"),
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+class ErrorScreen extends StatelessWidget {
+  const ErrorScreen(this.details, {Key? key}) : super(key: key);
+
+  final FlutterErrorDetails details;
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+        leading: BackButton(color: AppColors.of(context).text),
+        shadowColor: Colors.transparent,
+      ),
+      body: SafeArea(
+        child: Padding(
+          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+          child: Column(
+            children: [
+              Padding(
+                padding: const EdgeInsets.all(12.0),
+                child: Icon(FeatherIcons.alertTriangle,
+                    size: 48.0, color: AppColors.of(context).red),
+              ),
+              const Padding(
+                padding: EdgeInsets.all(12.0),
+                child: Text(
+                  "An error occurred...",
+                  style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0),
+                ),
+              ),
+              Expanded(
+                child: Container(
+                  padding: const EdgeInsets.all(12.0),
+                  width: double.infinity,
+                  decoration: BoxDecoration(
+                    borderRadius: BorderRadius.circular(14.0),
+                    color: Theme.of(context).colorScheme.background,
+                  ),
+                  child: CupertinoScrollbar(
+                    child: SingleChildScrollView(
+                      physics: const BouncingScrollPhysics(),
+                      child: SingleChildScrollView(
+                        physics: const BouncingScrollPhysics(),
+                        scrollDirection: Axis.horizontal,
+                        child: SelectableText(
+                          (details.exceptionAsString() + '\n'),
+                          style: const TextStyle(fontFamily: "monospace"),
+                        ),
+                      ),
+                    ),
+                  ),
+                ),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/login_button.dart b/refilc_mobile_ui/lib/screens/login/login_button.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/login/login_button.dart
rename to refilc_mobile_ui/lib/screens/login/login_button.dart
index f2e69e8..4e183a0
--- a/filcnaplo_mobile_ui/lib/screens/login/login_button.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_button.dart
@@ -1,29 +1,29 @@
-import 'package:flutter/material.dart';
-
-class LoginButton extends StatelessWidget {
-  const LoginButton({Key? key, required this.onPressed, required this.child}) : super(key: key);
-
-  final void Function()? onPressed;
-  final Widget? child;
-
-  @override
-  Widget build(BuildContext context) {
-    return MaterialButton(
-      child: Padding(
-        padding: const EdgeInsets.symmetric(
-          vertical: 15.0,
-        ),
-        child: child,
-      ),
-      elevation: 0,
-      focusElevation: 0,
-      hoverElevation: 0,
-      highlightElevation: 0,
-      minWidth: MediaQuery.of(context).size.width - 64.0,
-      onPressed: onPressed,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
-      color: Colors.white,
-      textColor: Colors.black,
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class LoginButton extends StatelessWidget {
+  const LoginButton({Key? key, required this.onPressed, required this.child}) : super(key: key);
+
+  final void Function()? onPressed;
+  final Widget? child;
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialButton(
+      child: Padding(
+        padding: const EdgeInsets.symmetric(
+          vertical: 15.0,
+        ),
+        child: child,
+      ),
+      elevation: 0,
+      focusElevation: 0,
+      hoverElevation: 0,
+      highlightElevation: 0,
+      minWidth: MediaQuery.of(context).size.width - 64.0,
+      onPressed: onPressed,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
+      color: Colors.white,
+      textColor: Colors.black,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/login_input.dart b/refilc_mobile_ui/lib/screens/login/login_input.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/login/login_input.dart
rename to refilc_mobile_ui/lib/screens/login/login_input.dart
index 68088a3..ac660de
--- a/filcnaplo_mobile_ui/lib/screens/login/login_input.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_input.dart
@@ -1,105 +1,105 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-enum LoginInputStyle { username, password, school }
-
-class LoginInput extends StatefulWidget {
-  const LoginInput(
-      {Key? key,
-      required this.style,
-      this.controller,
-      this.focusNode,
-      this.onClear})
-      : super(key: key);
-
-  final Function()? onClear;
-  final LoginInputStyle style;
-  final TextEditingController? controller;
-  final FocusNode? focusNode;
-
-  @override
-  State<LoginInput> createState() => _LoginInputState();
-}
-
-class _LoginInputState extends State<LoginInput> {
-  late bool obscure;
-
-  @override
-  void initState() {
-    super.initState();
-    obscure = widget.style == LoginInputStyle.password;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    String autofill;
-
-    switch (widget.style) {
-      case LoginInputStyle.username:
-        autofill = AutofillHints.username;
-        break;
-      case LoginInputStyle.password:
-        autofill = AutofillHints.password;
-        break;
-      case LoginInputStyle.school:
-        autofill = AutofillHints.organizationName;
-        break;
-    }
-
-    return TextField(
-      focusNode: widget.focusNode,
-      controller: widget.controller,
-      cursorColor: const Color(0xff20AC9B),
-      textInputAction: TextInputAction.next,
-      autofillHints: [autofill],
-      obscureText: obscure,
-      scrollPhysics: const BouncingScrollPhysics(),
-      decoration: InputDecoration(
-        fillColor: Colors.black.withOpacity(0.15),
-        filled: true,
-        enabledBorder: UnderlineInputBorder(
-          borderRadius: BorderRadius.circular(12.0),
-          borderSide: const BorderSide(width: 0, color: Colors.transparent),
-        ),
-        focusedBorder: UnderlineInputBorder(
-          borderRadius: BorderRadius.circular(12.0),
-          borderSide: const BorderSide(width: 0, color: Colors.transparent),
-        ),
-        suffixIconConstraints:
-            const BoxConstraints(maxHeight: 42.0, maxWidth: 48.0),
-        suffixIcon: widget.style == LoginInputStyle.password ||
-                widget.style == LoginInputStyle.school
-            ? ClipOval(
-                child: Material(
-                  type: MaterialType.transparency,
-                  child: IconButton(
-                    splashRadius: 20.0,
-                    padding: EdgeInsets.zero,
-                    onPressed: () {
-                      if (widget.style == LoginInputStyle.password) {
-                        setState(() => obscure = !obscure);
-                      } else {
-                        widget.controller?.clear();
-                        if (widget.onClear != null) widget.onClear!();
-                      }
-                    },
-                    icon: Icon(
-                        widget.style == LoginInputStyle.password
-                            ? obscure
-                                ? FeatherIcons.eye
-                                : FeatherIcons.eyeOff
-                            : FeatherIcons.x,
-                        color: Colors.white),
-                  ),
-                ),
-              )
-            : null,
-      ),
-      style: const TextStyle(
-        fontSize: 14.0,
-        fontWeight: FontWeight.w500,
-        color: Colors.white,
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+enum LoginInputStyle { username, password, school }
+
+class LoginInput extends StatefulWidget {
+  const LoginInput(
+      {Key? key,
+      required this.style,
+      this.controller,
+      this.focusNode,
+      this.onClear})
+      : super(key: key);
+
+  final Function()? onClear;
+  final LoginInputStyle style;
+  final TextEditingController? controller;
+  final FocusNode? focusNode;
+
+  @override
+  State<LoginInput> createState() => _LoginInputState();
+}
+
+class _LoginInputState extends State<LoginInput> {
+  late bool obscure;
+
+  @override
+  void initState() {
+    super.initState();
+    obscure = widget.style == LoginInputStyle.password;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    String autofill;
+
+    switch (widget.style) {
+      case LoginInputStyle.username:
+        autofill = AutofillHints.username;
+        break;
+      case LoginInputStyle.password:
+        autofill = AutofillHints.password;
+        break;
+      case LoginInputStyle.school:
+        autofill = AutofillHints.organizationName;
+        break;
+    }
+
+    return TextField(
+      focusNode: widget.focusNode,
+      controller: widget.controller,
+      cursorColor: const Color(0xff20AC9B),
+      textInputAction: TextInputAction.next,
+      autofillHints: [autofill],
+      obscureText: obscure,
+      scrollPhysics: const BouncingScrollPhysics(),
+      decoration: InputDecoration(
+        fillColor: Colors.black.withOpacity(0.15),
+        filled: true,
+        enabledBorder: UnderlineInputBorder(
+          borderRadius: BorderRadius.circular(12.0),
+          borderSide: const BorderSide(width: 0, color: Colors.transparent),
+        ),
+        focusedBorder: UnderlineInputBorder(
+          borderRadius: BorderRadius.circular(12.0),
+          borderSide: const BorderSide(width: 0, color: Colors.transparent),
+        ),
+        suffixIconConstraints:
+            const BoxConstraints(maxHeight: 42.0, maxWidth: 48.0),
+        suffixIcon: widget.style == LoginInputStyle.password ||
+                widget.style == LoginInputStyle.school
+            ? ClipOval(
+                child: Material(
+                  type: MaterialType.transparency,
+                  child: IconButton(
+                    splashRadius: 20.0,
+                    padding: EdgeInsets.zero,
+                    onPressed: () {
+                      if (widget.style == LoginInputStyle.password) {
+                        setState(() => obscure = !obscure);
+                      } else {
+                        widget.controller?.clear();
+                        if (widget.onClear != null) widget.onClear!();
+                      }
+                    },
+                    icon: Icon(
+                        widget.style == LoginInputStyle.password
+                            ? obscure
+                                ? FeatherIcons.eye
+                                : FeatherIcons.eyeOff
+                            : FeatherIcons.x,
+                        color: Colors.white),
+                  ),
+                ),
+              )
+            : null,
+      ),
+      style: const TextStyle(
+        fontSize: 14.0,
+        fontWeight: FontWeight.w500,
+        color: Colors.white,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/login_route.dart b/refilc_mobile_ui/lib/screens/login/login_route.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/screens/login/login_route.dart
rename to refilc_mobile_ui/lib/screens/login/login_route.dart
index b9edfc2..4b7c3d6
--- a/filcnaplo_mobile_ui/lib/screens/login/login_route.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_route.dart
@@ -1,21 +1,21 @@
-import 'package:flutter/material.dart';
-
-Route loginRoute(Widget widget) {
-  return PageRouteBuilder(
-    pageBuilder: (context, animation, secondaryAnimation) => widget,
-    transitionDuration: const Duration(milliseconds: 650),
-    transitionsBuilder: (context, animation, secondaryAnimation, child) {
-      var curve = Curves.easeInOut;
-      var curveTween = CurveTween(curve: curve);
-      var begin = const Offset(1.0, 0.0);
-      var end = Offset.zero;
-      var tween = Tween(begin: begin, end: end).chain(curveTween);
-      var offsetAnimation = animation.drive(tween);
-
-      return SlideTransition(
-        position: offsetAnimation,
-        child: child,
-      );
-    },
-  );
-}
+import 'package:flutter/material.dart';
+
+Route loginRoute(Widget widget) {
+  return PageRouteBuilder(
+    pageBuilder: (context, animation, secondaryAnimation) => widget,
+    transitionDuration: const Duration(milliseconds: 650),
+    transitionsBuilder: (context, animation, secondaryAnimation, child) {
+      var curve = Curves.easeInOut;
+      var curveTween = CurveTween(curve: curve);
+      var begin = const Offset(1.0, 0.0);
+      var end = Offset.zero;
+      var tween = Tween(begin: begin, end: end).chain(curveTween);
+      var offsetAnimation = animation.drive(tween);
+
+      return SlideTransition(
+        position: offsetAnimation,
+        child: child,
+      );
+    },
+  );
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/login_screen.dart b/refilc_mobile_ui/lib/screens/login/login_screen.dart
old mode 100755
new mode 100644
similarity index 93%
rename from filcnaplo_mobile_ui/lib/screens/login/login_screen.dart
rename to refilc_mobile_ui/lib/screens/login/login_screen.dart
index 22b1c5c..9a19e69
--- a/filcnaplo_mobile_ui/lib/screens/login/login_screen.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_screen.dart
@@ -1,347 +1,347 @@
-// import 'dart:async';
-import 'dart:ui';
-
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/api/login.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/system_chrome.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/login_button.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'login_screen.i18n.dart';
-
-class LoginScreen extends StatefulWidget {
-  const LoginScreen({Key? key, this.back = false}) : super(key: key);
-
-  final bool back;
-
-  @override
-  _LoginScreenState createState() => _LoginScreenState();
-}
-
-class _LoginScreenState extends State<LoginScreen> {
-  final usernameController = TextEditingController();
-  final passwordController = TextEditingController();
-  final schoolController = SchoolInputController();
-  final _scrollController = ScrollController();
-
-  LoginState _loginState = LoginState.normal;
-  bool showBack = false;
-
-  // Scaffold Gradient background
-  final LinearGradient _backgroundGradient = const LinearGradient(
-    colors: [
-      Color.fromARGB(255, 61, 122, 244),
-      Color.fromARGB(255, 23, 77, 185),
-      Color.fromARGB(255, 7, 42, 112),
-    ],
-    begin: Alignment(-0.8, -1.0),
-    end: Alignment(0.8, 1.0),
-    stops: [-1.0, 0.0, 1.0],
-  );
-
-  late String tempUsername = '';
-
-  @override
-  void initState() {
-    super.initState();
-    showBack = widget.back;
-
-    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
-      statusBarColor: Colors.transparent,
-      statusBarIconBrightness: Brightness.light,
-      systemNavigationBarColor: Colors.white,
-      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,
-        ));
-      }
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Container(
-        decoration: BoxDecoration(gradient: _backgroundGradient),
-        child: SingleChildScrollView(
-          physics: const ClampingScrollPhysics(),
-          controller: _scrollController,
-          child: Container(
-            decoration: BoxDecoration(gradient: _backgroundGradient),
-            width: MediaQuery.of(context).size.width,
-            height: MediaQuery.of(context).size.height,
-            child: SafeArea(
-              child: Column(
-                mainAxisAlignment: MainAxisAlignment.center,
-                children: [
-                  if (showBack)
-                    Container(
-                      alignment: Alignment.topLeft,
-                      padding: const EdgeInsets.only(left: 16.0, top: 12.0),
-                      child: const ClipOval(
-                        child: Material(
-                          type: MaterialType.transparency,
-                          child: BackButton(color: Colors.white),
-                        ),
-                      ),
-                    ),
-
-                  const Spacer(),
-
-                  // App logo
-                  Padding(
-                    padding: const EdgeInsets.only(bottom: 24.0),
-                    child: ClipRect(
-                      child: Container(
-                        // Png shadow *hack*
-                        child: Stack(
-                          children: [
-                            Padding(
-                              padding: const EdgeInsets.only(top: 8.0),
-                              child: Opacity(
-                                  child: Image.asset(
-                                      "assets/icons/ic_splash.png",
-                                      color: Colors.black),
-                                  opacity: 0.3),
-                            ),
-                            BackdropFilter(
-                              filter:
-                                  ImageFilter.blur(sigmaX: 6.0, sigmaY: 6.0),
-                              child: Image.asset("assets/icons/ic_splash.png"),
-                            )
-                          ],
-                        ),
-                        width: MediaQuery.of(context).size.width / 4,
-                        margin: const EdgeInsets.only(
-                            left: 12.0, right: 12.0, bottom: 12.0),
-                      ),
-                    ),
-                  ),
-
-                  // Inputs
-                  Padding(
-                    padding: const EdgeInsets.symmetric(horizontal: 32.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: const TextStyle(
-                                      color: Colors.white,
-                                      fontWeight: FontWeight.w600,
-                                      fontSize: 14.0,
-                                    ),
-                                  ),
-                                ),
-                                Expanded(
-                                  child: Text(
-                                    "usernameHint".i18n,
-                                    maxLines: 1,
-                                    textAlign: TextAlign.right,
-                                    style: const TextStyle(
-                                      color: Colors.white54,
-                                      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: const TextStyle(
-                                      color: Colors.white,
-                                      fontWeight: FontWeight.w600,
-                                      fontSize: 14.0,
-                                    ),
-                                  ),
-                                ),
-                                Expanded(
-                                  child: Text(
-                                    "passwordHint".i18n,
-                                    maxLines: 1,
-                                    textAlign: TextAlign.right,
-                                    style: const TextStyle(
-                                      color: Colors.white54,
-                                      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: const TextStyle(
-                                color: Colors.white,
-                                fontWeight: FontWeight.w600,
-                                fontSize: 14.0,
-                              ),
-                            ),
-                          ),
-                          SchoolInput(
-                            scroll: _scrollController,
-                            controller: schoolController,
-                          ),
-                        ],
-                      ),
-                    ),
-                  ),
-
-                  // Log in button
-                  Padding(
-                    padding: const EdgeInsets.only(top: 42.0),
-                    child: Visibility(
-                      child: LoginButton(
-                        child: Text("login".i18n,
-                            maxLines: 1,
-                            style: const TextStyle(
-                              fontWeight: FontWeight.w600,
-                              fontSize: 15.0,
-                            )),
-                        onPressed: () => _loginAPI(context: context),
-                      ),
-                      visible: _loginState != LoginState.inProgress,
-                      replacement: const Padding(
-                        padding: EdgeInsets.symmetric(vertical: 6.0),
-                        child: CircularProgressIndicator(
-                          valueColor:
-                              AlwaysStoppedAnimation<Color>(Colors.white),
-                        ),
-                      ),
-                    ),
-                  ),
-                  if (_loginState == LoginState.missingFields ||
-                      _loginState == LoginState.invalidGrant ||
-                      _loginState == LoginState.failed)
-                    Padding(
-                      padding: const EdgeInsets.only(top: 8.0),
-                      child: Text(
-                        [
-                          "missing_fields",
-                          "invalid_grant",
-                          "error"
-                        ][_loginState.index]
-                            .i18n,
-                        style: const TextStyle(
-                          color: Colors.red,
-                          fontWeight: FontWeight.w500,
-                        ),
-                        textAlign: TextAlign.center,
-                      ),
-                    ),
-                  const Spacer()
-                ],
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-
-  void _loginAPI({required BuildContext context}) {
-    String username = usernameController.text;
-    String password = passwordController.text;
-
-    tempUsername = username;
-
-    if (username == "" ||
-        password == "" ||
-        schoolController.selectedSchool == null) {
-      return setState(() => _loginState = LoginState.missingFields);
-    }
-
-    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();
-  }
-}
+// import 'dart:async';
+import 'dart:ui';
+
+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/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:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'login_screen.i18n.dart';
+
+class LoginScreen extends StatefulWidget {
+  const LoginScreen({Key? key, this.back = false}) : super(key: key);
+
+  final bool back;
+
+  @override
+  _LoginScreenState createState() => _LoginScreenState();
+}
+
+class _LoginScreenState extends State<LoginScreen> {
+  final usernameController = TextEditingController();
+  final passwordController = TextEditingController();
+  final schoolController = SchoolInputController();
+  final _scrollController = ScrollController();
+
+  LoginState _loginState = LoginState.normal;
+  bool showBack = false;
+
+  // Scaffold Gradient background
+  final LinearGradient _backgroundGradient = const LinearGradient(
+    colors: [
+      Color.fromARGB(255, 61, 122, 244),
+      Color.fromARGB(255, 23, 77, 185),
+      Color.fromARGB(255, 7, 42, 112),
+    ],
+    begin: Alignment(-0.8, -1.0),
+    end: Alignment(0.8, 1.0),
+    stops: [-1.0, 0.0, 1.0],
+  );
+
+  late String tempUsername = '';
+
+  @override
+  void initState() {
+    super.initState();
+    showBack = widget.back;
+
+    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
+      statusBarColor: Colors.transparent,
+      statusBarIconBrightness: Brightness.light,
+      systemNavigationBarColor: Colors.white,
+      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,
+        ));
+      }
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      body: Container(
+        decoration: BoxDecoration(gradient: _backgroundGradient),
+        child: SingleChildScrollView(
+          physics: const ClampingScrollPhysics(),
+          controller: _scrollController,
+          child: Container(
+            decoration: BoxDecoration(gradient: _backgroundGradient),
+            width: MediaQuery.of(context).size.width,
+            height: MediaQuery.of(context).size.height,
+            child: SafeArea(
+              child: Column(
+                mainAxisAlignment: MainAxisAlignment.center,
+                children: [
+                  if (showBack)
+                    Container(
+                      alignment: Alignment.topLeft,
+                      padding: const EdgeInsets.only(left: 16.0, top: 12.0),
+                      child: const ClipOval(
+                        child: Material(
+                          type: MaterialType.transparency,
+                          child: BackButton(color: Colors.white),
+                        ),
+                      ),
+                    ),
+
+                  const Spacer(),
+
+                  // App logo
+                  Padding(
+                    padding: const EdgeInsets.only(bottom: 24.0),
+                    child: ClipRect(
+                      child: Container(
+                        // Png shadow *hack*
+                        child: Stack(
+                          children: [
+                            Padding(
+                              padding: const EdgeInsets.only(top: 8.0),
+                              child: Opacity(
+                                  child: Image.asset(
+                                      "assets/icons/ic_splash.png",
+                                      color: Colors.black),
+                                  opacity: 0.3),
+                            ),
+                            BackdropFilter(
+                              filter:
+                                  ImageFilter.blur(sigmaX: 6.0, sigmaY: 6.0),
+                              child: Image.asset("assets/icons/ic_splash.png"),
+                            )
+                          ],
+                        ),
+                        width: MediaQuery.of(context).size.width / 4,
+                        margin: const EdgeInsets.only(
+                            left: 12.0, right: 12.0, bottom: 12.0),
+                      ),
+                    ),
+                  ),
+
+                  // Inputs
+                  Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 32.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: const TextStyle(
+                                      color: Colors.white,
+                                      fontWeight: FontWeight.w600,
+                                      fontSize: 14.0,
+                                    ),
+                                  ),
+                                ),
+                                Expanded(
+                                  child: Text(
+                                    "usernameHint".i18n,
+                                    maxLines: 1,
+                                    textAlign: TextAlign.right,
+                                    style: const TextStyle(
+                                      color: Colors.white54,
+                                      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: const TextStyle(
+                                      color: Colors.white,
+                                      fontWeight: FontWeight.w600,
+                                      fontSize: 14.0,
+                                    ),
+                                  ),
+                                ),
+                                Expanded(
+                                  child: Text(
+                                    "passwordHint".i18n,
+                                    maxLines: 1,
+                                    textAlign: TextAlign.right,
+                                    style: const TextStyle(
+                                      color: Colors.white54,
+                                      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: const TextStyle(
+                                color: Colors.white,
+                                fontWeight: FontWeight.w600,
+                                fontSize: 14.0,
+                              ),
+                            ),
+                          ),
+                          SchoolInput(
+                            scroll: _scrollController,
+                            controller: schoolController,
+                          ),
+                        ],
+                      ),
+                    ),
+                  ),
+
+                  // Log in button
+                  Padding(
+                    padding: const EdgeInsets.only(top: 42.0),
+                    child: Visibility(
+                      child: LoginButton(
+                        child: Text("login".i18n,
+                            maxLines: 1,
+                            style: const TextStyle(
+                              fontWeight: FontWeight.w600,
+                              fontSize: 15.0,
+                            )),
+                        onPressed: () => _loginAPI(context: context),
+                      ),
+                      visible: _loginState != LoginState.inProgress,
+                      replacement: const Padding(
+                        padding: EdgeInsets.symmetric(vertical: 6.0),
+                        child: CircularProgressIndicator(
+                          valueColor:
+                              AlwaysStoppedAnimation<Color>(Colors.white),
+                        ),
+                      ),
+                    ),
+                  ),
+                  if (_loginState == LoginState.missingFields ||
+                      _loginState == LoginState.invalidGrant ||
+                      _loginState == LoginState.failed)
+                    Padding(
+                      padding: const EdgeInsets.only(top: 8.0),
+                      child: Text(
+                        [
+                          "missing_fields",
+                          "invalid_grant",
+                          "error"
+                        ][_loginState.index]
+                            .i18n,
+                        style: const TextStyle(
+                          color: Colors.red,
+                          fontWeight: FontWeight.w500,
+                        ),
+                        textAlign: TextAlign.center,
+                      ),
+                    ),
+                  const Spacer()
+                ],
+              ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  void _loginAPI({required BuildContext context}) {
+    String username = usernameController.text;
+    String password = passwordController.text;
+
+    tempUsername = username;
+
+    if (username == "" ||
+        password == "" ||
+        schoolController.selectedSchool == null) {
+      return setState(() => _loginState = LoginState.missingFields);
+    }
+
+    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();
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart b/refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart
rename to refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart
index 6e24d7c..9f969df
--- a/filcnaplo_mobile_ui/lib/screens/login/login_screen.i18n.dart
+++ b/refilc_mobile_ui/lib/screens/login/login_screen.i18n.dart
@@ -1,53 +1,53 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "username": "Username",
-          "usernameHint": "Student ID number",
-          "password": "Password",
-          "passwordHint": "Date of birth",
-          "school": "School",
-          "login": "Log in",
-          "welcome": "Welcome, %s!",
-          "missing_fields": "Missing Fields!",
-          "invalid_grant":
-              "Invalid Username/Password! (Try adding spaces after Username)",
-          "error": "Failed to log in.",
-          "schools_error": "Failed to get schools."
-        },
-        "hu_hu": {
-          "username": "Felhasználónév",
-          "usernameHint": "Oktatási azonosító",
-          "password": "Jelszó",
-          "passwordHint": "Születési dátum",
-          "school": "Iskola",
-          "login": "Belépés",
-          "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)",
-          "error": "Sikertelen bejelentkezés.",
-          "schools_error": "Nem sikerült lekérni az iskolákat."
-        },
-        "de_de": {
-          "username": "Benutzername",
-          "usernameHint": "Ausbildung ID",
-          "password": "Passwort",
-          "passwordHint": "Geburtsdatum",
-          "school": "Schule",
-          "login": "Einloggen",
-          "welcome": "Wilkommen, %s!",
-          "missing_fields": "Fehlende Felder!",
-          "invalid_grant": "Ungültiger Benutzername/Passwort!",
-          "error": "Anmeldung fehlgeschlagen.",
-          "schools_error": "Keine Schulen gefunden."
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "username": "Username",
+          "usernameHint": "Student ID number",
+          "password": "Password",
+          "passwordHint": "Date of birth",
+          "school": "School",
+          "login": "Log in",
+          "welcome": "Welcome, %s!",
+          "missing_fields": "Missing Fields!",
+          "invalid_grant":
+              "Invalid Username/Password! (Try adding spaces after Username)",
+          "error": "Failed to log in.",
+          "schools_error": "Failed to get schools."
+        },
+        "hu_hu": {
+          "username": "Felhasználónév",
+          "usernameHint": "Oktatási azonosító",
+          "password": "Jelszó",
+          "passwordHint": "Születési dátum",
+          "school": "Iskola",
+          "login": "Belépés",
+          "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)",
+          "error": "Sikertelen bejelentkezés.",
+          "schools_error": "Nem sikerült lekérni az iskolákat."
+        },
+        "de_de": {
+          "username": "Benutzername",
+          "usernameHint": "Ausbildung ID",
+          "password": "Passwort",
+          "passwordHint": "Geburtsdatum",
+          "school": "Schule",
+          "login": "Einloggen",
+          "welcome": "Wilkommen, %s!",
+          "missing_fields": "Fehlende Felder!",
+          "invalid_grant": "Ungültiger Benutzername/Passwort!",
+          "error": "Anmeldung fehlgeschlagen.",
+          "schools_error": "Keine Schulen gefunden."
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input.dart b/refilc_mobile_ui/lib/screens/login/school_input/school_input.dart
old mode 100755
new mode 100644
similarity index 78%
rename from filcnaplo_mobile_ui/lib/screens/login/school_input/school_input.dart
rename to refilc_mobile_ui/lib/screens/login/school_input/school_input.dart
index f3cf683..46352a3
--- a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input.dart
+++ b/refilc_mobile_ui/lib/screens/login/school_input/school_input.dart
@@ -1,117 +1,122 @@
-import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input_overlay.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input_tile.dart';
-import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_search.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo_kreta_api/models/school.dart';
-
-class SchoolInput extends StatefulWidget {
-  const SchoolInput({Key? key, required this.controller, required this.scroll}) : super(key: key);
-
-  final SchoolInputController controller;
-  final ScrollController scroll;
-
-  @override
-  _SchoolInputState createState() => _SchoolInputState();
-}
-
-class _SchoolInputState extends State<SchoolInput> {
-  final _focusNode = FocusNode();
-  final _layerLink = LayerLink();
-  late SchoolInputOverlay overlay;
-
-  @override
-  void initState() {
-    super.initState();
-
-    widget.controller.update = (fn) {
-      if (mounted) setState(fn);
-    };
-
-    overlay = SchoolInputOverlay(layerLink: _layerLink);
-
-    // Show school list when focused
-    _focusNode.addListener(() {
-      if (_focusNode.hasFocus) {
-        WidgetsBinding.instance.addPostFrameCallback((_) => overlay.createOverlayEntry(context));
-        Future.delayed(const Duration(milliseconds: 100)).then((value) {
-          if (mounted && widget.scroll.hasClients) {
-            widget.scroll.animateTo(widget.scroll.offset + 500, duration: const Duration(milliseconds: 500), curve: Curves.ease);
-          }
-        });
-      } else {
-        overlay.entry?.remove();
-      }
-    });
-
-    // LoginInput TextField listener
-    widget.controller.textController.addListener(() {
-      String text = widget.controller.textController.text;
-      if (text.isEmpty) {
-        overlay.children = null;
-        return;
-      }
-
-      List<School> results = searchSchools(widget.controller.schools ?? [], text);
-      setState(() {
-        overlay.children = results
-            .map((School e) => SchoolInputTile(
-                  school: e,
-                  onTap: () => _selectSchool(e),
-                ))
-            .toList();
-      });
-      Overlay.of(context).setState(() {});
-    });
-  }
-
-  void _selectSchool(School school) {
-    FocusScope.of(context).requestFocus(FocusNode());
-
-    setState(() {
-      widget.controller.selectedSchool = school;
-      widget.controller.textController.text = school.name;
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return CompositedTransformTarget(
-      link: _layerLink,
-      child: widget.controller.schools == null
-          ? Container(
-              width: double.infinity,
-              padding: const EdgeInsets.symmetric(vertical: 10.0),
-              decoration: BoxDecoration(
-                color: Colors.black.withOpacity(0.15),
-                borderRadius: BorderRadius.circular(12.0),
-              ),
-              child: const Center(
-                child: SizedBox(
-                  height: 28.0,
-                  width: 28.0,
-                  child: CircularProgressIndicator(
-                    color: Colors.white,
-                  ),
-                ),
-              ),
-            )
-          : LoginInput(
-              style: LoginInputStyle.school,
-              focusNode: _focusNode,
-              onClear: () {
-                widget.controller.selectedSchool = null;
-                FocusScope.of(context).requestFocus(_focusNode);
-              },
-              controller: widget.controller.textController,
-            ),
-    );
-  }
-}
-
-class SchoolInputController {
-  final textController = TextEditingController();
-  School? selectedSchool;
-  List<School>? schools;
-  late void Function(void Function()) update;
-}
+import 'package:refilc_mobile_ui/screens/login/login_input.dart';
+import 'package:refilc_mobile_ui/screens/login/school_input/school_input_overlay.dart';
+import 'package:refilc_mobile_ui/screens/login/school_input/school_input_tile.dart';
+import 'package:refilc_mobile_ui/screens/login/school_input/school_search.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc_kreta_api/models/school.dart';
+
+class SchoolInput extends StatefulWidget {
+  const SchoolInput({Key? key, required this.controller, required this.scroll})
+      : super(key: key);
+
+  final SchoolInputController controller;
+  final ScrollController scroll;
+
+  @override
+  _SchoolInputState createState() => _SchoolInputState();
+}
+
+class _SchoolInputState extends State<SchoolInput> {
+  final _focusNode = FocusNode();
+  final _layerLink = LayerLink();
+  late SchoolInputOverlay overlay;
+
+  @override
+  void initState() {
+    super.initState();
+
+    widget.controller.update = (fn) {
+      if (mounted) setState(fn);
+    };
+
+    overlay = SchoolInputOverlay(layerLink: _layerLink);
+
+    // Show school list when focused
+    _focusNode.addListener(() {
+      if (_focusNode.hasFocus) {
+        WidgetsBinding.instance
+            .addPostFrameCallback((_) => overlay.createOverlayEntry(context));
+        Future.delayed(const Duration(milliseconds: 100)).then((value) {
+          if (mounted && widget.scroll.hasClients) {
+            widget.scroll.animateTo(widget.scroll.offset + 500,
+                duration: const Duration(milliseconds: 500),
+                curve: Curves.ease);
+          }
+        });
+      } else {
+        overlay.entry?.remove();
+      }
+    });
+
+    // LoginInput TextField listener
+    widget.controller.textController.addListener(() {
+      String text = widget.controller.textController.text;
+      if (text.isEmpty) {
+        overlay.children = null;
+        return;
+      }
+
+      List<School> results =
+          searchSchools(widget.controller.schools ?? [], text);
+      setState(() {
+        overlay.children = results
+            .map((School e) => SchoolInputTile(
+                  school: e,
+                  onTap: () => _selectSchool(e),
+                ))
+            .toList();
+      });
+      Overlay.of(context).setState(() {});
+    });
+  }
+
+  void _selectSchool(School school) {
+    FocusScope.of(context).requestFocus(FocusNode());
+
+    setState(() {
+      widget.controller.selectedSchool = school;
+      widget.controller.textController.text = school.name;
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return CompositedTransformTarget(
+      link: _layerLink,
+      child: widget.controller.schools == null
+          ? Container(
+              width: double.infinity,
+              padding: const EdgeInsets.symmetric(vertical: 10.0),
+              decoration: BoxDecoration(
+                color: Colors.black.withOpacity(0.15),
+                borderRadius: BorderRadius.circular(12.0),
+              ),
+              child: const Center(
+                child: SizedBox(
+                  height: 28.0,
+                  width: 28.0,
+                  child: CircularProgressIndicator(
+                    color: Colors.white,
+                  ),
+                ),
+              ),
+            )
+          : LoginInput(
+              style: LoginInputStyle.school,
+              focusNode: _focusNode,
+              onClear: () {
+                widget.controller.selectedSchool = null;
+                FocusScope.of(context).requestFocus(_focusNode);
+              },
+              controller: widget.controller.textController,
+            ),
+    );
+  }
+}
+
+class SchoolInputController {
+  final textController = TextEditingController();
+  School? selectedSchool;
+  List<School>? schools;
+  late void Function(void Function()) update;
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_overlay.dart b/refilc_mobile_ui/lib/screens/login/school_input/school_input_overlay.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_overlay.dart
rename to refilc_mobile_ui/lib/screens/login/school_input/school_input_overlay.dart
index 833e361..85330bb
--- a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_overlay.dart
+++ b/refilc_mobile_ui/lib/screens/login/school_input/school_input_overlay.dart
@@ -1,72 +1,72 @@
-import 'package:flutter/material.dart';
-import 'school_input_overlay.i18n.dart';
-
-class SchoolInputOverlay {
-  OverlayEntry? entry;
-  final LayerLink layerLink;
-  List<Widget>? children;
-
-  SchoolInputOverlay({required this.layerLink});
-
-  void createOverlayEntry(BuildContext context) {
-    entry = OverlayEntry(builder: (_) => buildOverlayEntry(context));
-    Overlay.of(context).insert(entry!);
-  }
-
-  Widget buildOverlayEntry(BuildContext context) {
-    RenderBox renderBox = context.findRenderObject()! as RenderBox;
-    var size = renderBox.size;
-    return SchoolInputOverlayWidget(
-      children: children,
-      size: size,
-      layerLink: layerLink,
-    );
-  }
-}
-
-class SchoolInputOverlayWidget extends StatelessWidget {
-  const SchoolInputOverlayWidget({
-    Key? key,
-    required this.children,
-    required this.size,
-    required this.layerLink,
-  }) : super(key: key);
-
-  final Size size;
-  final List<Widget>? children;
-  final LayerLink layerLink;
-
-  @override
-  Widget build(BuildContext context) {
-    return children != null
-        ? Positioned(
-            width: size.width,
-            height: (children?.length ?? 0) > 0 ? 150.0 : 50.0,
-            child: CompositedTransformFollower(
-              link: layerLink,
-              showWhenUnlinked: false,
-              offset: Offset(0.0, size.height + 5.0),
-              child: Material(
-                color: Theme.of(context).colorScheme.background,
-                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-                elevation: 4.0,
-                shadowColor: Colors.black,
-                child: (children?.length ?? 0) > 0
-                    ? ListView.builder(
-                        physics: const BouncingScrollPhysics(),
-                        padding: EdgeInsets.zero,
-                        shrinkWrap: true,
-                        itemCount: children?.length ?? 0,
-                        itemBuilder: (context, index) {
-                          return children?[index] ?? Container();
-                        },
-                      )
-                    : Center(
-                        child: Text("noresults".i18n),
-                      ),
-              ),
-            ),
-          )
-        : Container();
-  }
-}
+import 'package:flutter/material.dart';
+import 'school_input_overlay.i18n.dart';
+
+class SchoolInputOverlay {
+  OverlayEntry? entry;
+  final LayerLink layerLink;
+  List<Widget>? children;
+
+  SchoolInputOverlay({required this.layerLink});
+
+  void createOverlayEntry(BuildContext context) {
+    entry = OverlayEntry(builder: (_) => buildOverlayEntry(context));
+    Overlay.of(context).insert(entry!);
+  }
+
+  Widget buildOverlayEntry(BuildContext context) {
+    RenderBox renderBox = context.findRenderObject()! as RenderBox;
+    var size = renderBox.size;
+    return SchoolInputOverlayWidget(
+      children: children,
+      size: size,
+      layerLink: layerLink,
+    );
+  }
+}
+
+class SchoolInputOverlayWidget extends StatelessWidget {
+  const SchoolInputOverlayWidget({
+    Key? key,
+    required this.children,
+    required this.size,
+    required this.layerLink,
+  }) : super(key: key);
+
+  final Size size;
+  final List<Widget>? children;
+  final LayerLink layerLink;
+
+  @override
+  Widget build(BuildContext context) {
+    return children != null
+        ? Positioned(
+            width: size.width,
+            height: (children?.length ?? 0) > 0 ? 150.0 : 50.0,
+            child: CompositedTransformFollower(
+              link: layerLink,
+              showWhenUnlinked: false,
+              offset: Offset(0.0, size.height + 5.0),
+              child: Material(
+                color: Theme.of(context).colorScheme.background,
+                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+                elevation: 4.0,
+                shadowColor: Colors.black,
+                child: (children?.length ?? 0) > 0
+                    ? ListView.builder(
+                        physics: const BouncingScrollPhysics(),
+                        padding: EdgeInsets.zero,
+                        shrinkWrap: true,
+                        itemCount: children?.length ?? 0,
+                        itemBuilder: (context, index) {
+                          return children?[index] ?? Container();
+                        },
+                      )
+                    : Center(
+                        child: Text("noresults".i18n),
+                      ),
+              ),
+            ),
+          )
+        : Container();
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_overlay.i18n.dart b/refilc_mobile_ui/lib/screens/login/school_input/school_input_overlay.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_overlay.i18n.dart
rename to refilc_mobile_ui/lib/screens/login/school_input/school_input_overlay.i18n.dart
index d830f4c..486d1d6
--- a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_overlay.i18n.dart
+++ b/refilc_mobile_ui/lib/screens/login/school_input/school_input_overlay.i18n.dart
@@ -1,21 +1,21 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "noresults": "No results!",
-        },
-        "hu_hu": {
-          "noresults": "Nincs találat!",
-        },
-        "de_de": {
-          "noresults": "Keine Treffer!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "noresults": "No results!",
+        },
+        "hu_hu": {
+          "noresults": "Nincs találat!",
+        },
+        "de_de": {
+          "noresults": "Keine Treffer!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_tile.dart b/refilc_mobile_ui/lib/screens/login/school_input/school_input_tile.dart
old mode 100755
new mode 100644
similarity index 93%
rename from filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_tile.dart
rename to refilc_mobile_ui/lib/screens/login/school_input/school_input_tile.dart
index a364c23..373357a
--- a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_input_tile.dart
+++ b/refilc_mobile_ui/lib/screens/login/school_input/school_input_tile.dart
@@ -1,62 +1,62 @@
-import 'package:filcnaplo_kreta_api/models/school.dart';
-import 'package:flutter/material.dart';
-
-class SchoolInputTile extends StatelessWidget {
-  const SchoolInputTile({Key? key, required this.school, this.onTap})
-      : super(key: key);
-
-  final School school;
-  final Function()? onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.all(4.0),
-      child: InkWell(
-        onTap: () {
-          onTap!();
-        },
-        borderRadius: BorderRadius.circular(6.0),
-        child: Padding(
-          padding: const EdgeInsets.all(6.0),
-          child: Column(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: [
-              // School name
-              Padding(
-                padding: const EdgeInsets.only(bottom: 4.0),
-                child: Text(
-                  school.name,
-                  maxLines: 2,
-                  overflow: TextOverflow.ellipsis,
-                  style: const TextStyle(fontWeight: FontWeight.w600),
-                ),
-              ),
-              Row(
-                children: [
-                  // School id
-                  Expanded(
-                    child: Text(
-                      school.instituteCode,
-                      maxLines: 1,
-                      overflow: TextOverflow.ellipsis,
-                    ),
-                  ),
-                  // School city
-                  Expanded(
-                    child: Text(
-                      school.city,
-                      textAlign: TextAlign.right,
-                      maxLines: 1,
-                      overflow: TextOverflow.ellipsis,
-                    ),
-                  ),
-                ],
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc_kreta_api/models/school.dart';
+import 'package:flutter/material.dart';
+
+class SchoolInputTile extends StatelessWidget {
+  const SchoolInputTile({Key? key, required this.school, this.onTap})
+      : super(key: key);
+
+  final School school;
+  final Function()? onTap;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.all(4.0),
+      child: InkWell(
+        onTap: () {
+          onTap!();
+        },
+        borderRadius: BorderRadius.circular(6.0),
+        child: Padding(
+          padding: const EdgeInsets.all(6.0),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              // School name
+              Padding(
+                padding: const EdgeInsets.only(bottom: 4.0),
+                child: Text(
+                  school.name,
+                  maxLines: 2,
+                  overflow: TextOverflow.ellipsis,
+                  style: const TextStyle(fontWeight: FontWeight.w600),
+                ),
+              ),
+              Row(
+                children: [
+                  // School id
+                  Expanded(
+                    child: Text(
+                      school.instituteCode,
+                      maxLines: 1,
+                      overflow: TextOverflow.ellipsis,
+                    ),
+                  ),
+                  // School city
+                  Expanded(
+                    child: Text(
+                      school.city,
+                      textAlign: TextAlign.right,
+                      maxLines: 1,
+                      overflow: TextOverflow.ellipsis,
+                    ),
+                  ),
+                ],
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_search.dart b/refilc_mobile_ui/lib/screens/login/school_input/school_search.dart
old mode 100755
new mode 100644
similarity index 80%
rename from filcnaplo_mobile_ui/lib/screens/login/school_input/school_search.dart
rename to refilc_mobile_ui/lib/screens/login/school_input/school_search.dart
index 4cbfb30..f310154
--- a/filcnaplo_mobile_ui/lib/screens/login/school_input/school_search.dart
+++ b/refilc_mobile_ui/lib/screens/login/school_input/school_search.dart
@@ -1,25 +1,25 @@
-import 'package:filcnaplo_kreta_api/models/school.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-List<School> searchSchools(List<School> all, String pattern) {
-  pattern = pattern.toLowerCase().specialChars();
-  if (pattern == "") return all;
-
-  List<School> results = [];
-
-  for (var item in all) {
-    int contains = 0;
-
-    pattern.split(" ").forEach((variation) {
-      if (item.name.toLowerCase().specialChars().contains(variation)) {
-        contains++;
-      }
-    });
-
-    if (contains == pattern.split(" ").length) results.add(item);
-  }
-
-  results.sort((a, b) => a.name.compareTo(b.name));
-
-  return results;
-}
+import 'package:refilc_kreta_api/models/school.dart';
+import 'package:refilc/utils/format.dart';
+
+List<School> searchSchools(List<School> all, String pattern) {
+  pattern = pattern.toLowerCase().specialChars();
+  if (pattern == "") return all;
+
+  List<School> results = [];
+
+  for (var item in all) {
+    int contains = 0;
+
+    pattern.split(" ").forEach((variation) {
+      if (item.name.toLowerCase().specialChars().contains(variation)) {
+        contains++;
+      }
+    });
+
+    if (contains == pattern.split(" ").length) results.add(item);
+  }
+
+  results.sort((a, b) => a.name.compareTo(b.name));
+
+  return results;
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/nabar.dart b/refilc_mobile_ui/lib/screens/navigation/nabar.dart
old mode 100755
new mode 100644
similarity index 71%
rename from filcnaplo_mobile_ui/lib/screens/navigation/nabar.dart
rename to refilc_mobile_ui/lib/screens/navigation/nabar.dart
index 97f5684..1560067
--- a/filcnaplo_mobile_ui/lib/screens/navigation/nabar.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/nabar.dart
@@ -1,27 +1,32 @@
-import 'package:filcnaplo_mobile_ui/screens/navigation/navbar_item.dart';
-import 'package:flutter/material.dart';
-
-class Navbar extends StatelessWidget {
-  const Navbar({Key? key, required this.selectedIndex, required this.onSelected, required this.items}) : super(key: key);
-
-  final int selectedIndex;
-  final void Function(int index) onSelected;
-  final List<NavItem> items;
-
-  @override
-  Widget build(BuildContext context) {
-    final List<Widget> buttons = List.generate(
-      items.length,
-      (index) => NavbarItem(
-        item: items[index],
-        active: index == selectedIndex,
-        onTap: () => onSelected(index),
-      ),
-    );
-
-    return Row(
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: buttons,
-    );
-  }
-}
+import 'package:refilc_mobile_ui/screens/navigation/navbar_item.dart';
+import 'package:flutter/material.dart';
+
+class Navbar extends StatelessWidget {
+  const Navbar(
+      {Key? key,
+      required this.selectedIndex,
+      required this.onSelected,
+      required this.items})
+      : super(key: key);
+
+  final int selectedIndex;
+  final void Function(int index) onSelected;
+  final List<NavItem> items;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> buttons = List.generate(
+      items.length,
+      (index) => NavbarItem(
+        item: items[index],
+        active: index == selectedIndex,
+        onTap: () => onSelected(index),
+      ),
+    );
+
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: buttons,
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/navbar_item.dart b/refilc_mobile_ui/lib/screens/navigation/navbar_item.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/navigation/navbar_item.dart
rename to refilc_mobile_ui/lib/screens/navigation/navbar_item.dart
index c28796b..20bb861
--- a/filcnaplo_mobile_ui/lib/screens/navigation/navbar_item.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/navbar_item.dart
@@ -1,64 +1,64 @@
-import 'package:flutter/material.dart';
-
-class NavItem {
-  final String title;
-  final Widget icon;
-  final Widget activeIcon;
-
-  const NavItem(
-      {required this.title, required this.icon, required this.activeIcon});
-}
-
-class NavbarItem extends StatelessWidget {
-  const NavbarItem({
-    Key? key,
-    required this.item,
-    required this.active,
-    required this.onTap,
-  }) : super(key: key);
-
-  final NavItem item;
-  final bool active;
-  final void Function() onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    final Widget icon = active ? item.activeIcon : item.icon;
-
-    return SafeArea(
-      child: GestureDetector(
-        onTap: onTap,
-        child: Padding(
-          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 6.0),
-          child: Container(
-            padding: const EdgeInsets.all(12.0),
-            decoration: BoxDecoration(
-              color: active
-                  ? Theme.of(context).colorScheme.secondary.withOpacity(.4)
-                  : null,
-              borderRadius: BorderRadius.circular(14.0),
-            ),
-            child: Stack(
-              children: [
-                IconTheme(
-                  data: IconThemeData(
-                    color: Theme.of(context).colorScheme.secondary,
-                  ),
-                  child: icon,
-                ),
-                IconTheme(
-                  data: IconThemeData(
-                    color: Theme.of(context).brightness == Brightness.light
-                        ? Colors.black.withOpacity(.5)
-                        : Colors.white.withOpacity(.3),
-                  ),
-                  child: icon,
-                ),
-              ],
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+
+class NavItem {
+  final String title;
+  final Widget icon;
+  final Widget activeIcon;
+
+  const NavItem(
+      {required this.title, required this.icon, required this.activeIcon});
+}
+
+class NavbarItem extends StatelessWidget {
+  const NavbarItem({
+    Key? key,
+    required this.item,
+    required this.active,
+    required this.onTap,
+  }) : super(key: key);
+
+  final NavItem item;
+  final bool active;
+  final void Function() onTap;
+
+  @override
+  Widget build(BuildContext context) {
+    final Widget icon = active ? item.activeIcon : item.icon;
+
+    return SafeArea(
+      child: GestureDetector(
+        onTap: onTap,
+        child: Padding(
+          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 6.0),
+          child: Container(
+            padding: const EdgeInsets.all(12.0),
+            decoration: BoxDecoration(
+              color: active
+                  ? Theme.of(context).colorScheme.secondary.withOpacity(.4)
+                  : null,
+              borderRadius: BorderRadius.circular(14.0),
+            ),
+            child: Stack(
+              children: [
+                IconTheme(
+                  data: IconThemeData(
+                    color: Theme.of(context).colorScheme.secondary,
+                  ),
+                  child: icon,
+                ),
+                IconTheme(
+                  data: IconThemeData(
+                    color: Theme.of(context).brightness == Brightness.light
+                        ? Colors.black.withOpacity(.5)
+                        : Colors.white.withOpacity(.3),
+                  ),
+                  child: icon,
+                ),
+              ],
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/navigation_route.dart b/refilc_mobile_ui/lib/screens/navigation/navigation_route.dart
similarity index 94%
rename from filcnaplo_desktop_ui/lib/screens/navigation/navigation_route.dart
rename to refilc_mobile_ui/lib/screens/navigation/navigation_route.dart
index fc3d87f..79778aa 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/navigation_route.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/navigation_route.dart
@@ -1,25 +1,25 @@
-class NavigationRoute {
-  late String _name;
-  late int _index;
-
-  final List<String> _internalPageMap = [
-    "home",
-    "grades",
-    "timetable",
-    "messages",
-    "absences",
-  ];
-
-  String get name => _name;
-  int get index => _index;
-
-  set name(String n) {
-    _name = n;
-    _index = _internalPageMap.indexOf(n);
-  }
-
-  set index(int i) {
-    _index = i;
-    _name = _internalPageMap.elementAt(i);
-  }
-}
+class NavigationRoute {
+  late String _name;
+  late int _index;
+
+  final List<String> _internalPageMap = [
+    "home",
+    "grades",
+    "timetable",
+    "messages",
+    "absences",
+  ];
+
+  String get name => _name;
+  int get index => _index;
+
+  set name(String n) {
+    _name = n;
+    _index = _internalPageMap.indexOf(n);
+  }
+
+  set index(int i) {
+    _index = i;
+    _name = _internalPageMap.elementAt(i);
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/navigation_route_handler.dart b/refilc_mobile_ui/lib/screens/navigation/navigation_route_handler.dart
old mode 100755
new mode 100644
similarity index 74%
rename from filcnaplo_mobile_ui/lib/screens/navigation/navigation_route_handler.dart
rename to refilc_mobile_ui/lib/screens/navigation/navigation_route_handler.dart
index 63d0ad2..c3d8a99
--- a/filcnaplo_mobile_ui/lib/screens/navigation/navigation_route_handler.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/navigation_route_handler.dart
@@ -1,38 +1,38 @@
-import 'package:filcnaplo_mobile_ui/pages/absences/absences_page.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/grades_page.dart';
-import 'package:filcnaplo_mobile_ui/pages/home/home_page.dart';
-import 'package:filcnaplo_mobile_ui/pages/messages/messages_page.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.dart';
-import 'package:flutter/material.dart';
-import 'package:animations/animations.dart';
-
-Route navigationRouteHandler(RouteSettings settings) {
-  switch (settings.name) {
-    case "home":
-      return navigationPageRoute((context) => const HomePage());
-    case "grades":
-      return navigationPageRoute((context) => const GradesPage());
-    case "timetable":
-      return navigationPageRoute((context) => const TimetablePage());
-    case "messages":
-      return navigationPageRoute((context) => const MessagesPage());
-    case "absences":
-      return navigationPageRoute((context) => const AbsencesPage());
-    default:
-      return navigationPageRoute((context) => const HomePage());
-  }
-}
-
-Route navigationPageRoute(Widget Function(BuildContext) builder) {
-  return PageRouteBuilder(
-    pageBuilder: (context, _, __) => builder(context),
-    transitionsBuilder: (context, animation, secondaryAnimation, child) {
-      return FadeThroughTransition(
-        fillColor: Theme.of(context).scaffoldBackgroundColor,
-        animation: animation,
-        secondaryAnimation: secondaryAnimation,
-        child: child,
-      );
-    },
-  );
-}
+import 'package:refilc_mobile_ui/pages/absences/absences_page.dart';
+import 'package:refilc_mobile_ui/pages/grades/grades_page.dart';
+import 'package:refilc_mobile_ui/pages/home/home_page.dart';
+import 'package:refilc_mobile_ui/pages/messages/messages_page.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.dart';
+import 'package:flutter/material.dart';
+import 'package:animations/animations.dart';
+
+Route navigationRouteHandler(RouteSettings settings) {
+  switch (settings.name) {
+    case "home":
+      return navigationPageRoute((context) => const HomePage());
+    case "grades":
+      return navigationPageRoute((context) => const GradesPage());
+    case "timetable":
+      return navigationPageRoute((context) => const TimetablePage());
+    case "messages":
+      return navigationPageRoute((context) => const MessagesPage());
+    case "absences":
+      return navigationPageRoute((context) => const AbsencesPage());
+    default:
+      return navigationPageRoute((context) => const HomePage());
+  }
+}
+
+Route navigationPageRoute(Widget Function(BuildContext) builder) {
+  return PageRouteBuilder(
+    pageBuilder: (context, _, __) => builder(context),
+    transitionsBuilder: (context, animation, secondaryAnimation, child) {
+      return FadeThroughTransition(
+        fillColor: Theme.of(context).scaffoldBackgroundColor,
+        animation: animation,
+        secondaryAnimation: secondaryAnimation,
+        child: child,
+      );
+    },
+  );
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/navigation_screen.dart b/refilc_mobile_ui/lib/screens/navigation/navigation_screen.dart
old mode 100755
new mode 100644
similarity index 86%
rename from filcnaplo_mobile_ui/lib/screens/navigation/navigation_screen.dart
rename to refilc_mobile_ui/lib/screens/navigation/navigation_screen.dart
index f5017de..a3feb61
--- a/filcnaplo_mobile_ui/lib/screens/navigation/navigation_screen.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/navigation_screen.dart
@@ -1,341 +1,341 @@
-import 'package:filcnaplo/api/providers/update_provider.dart';
-import 'package:filcnaplo/helpers/quick_actions.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/observer.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/system_chrome.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/nabar.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/navbar_item.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_route.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_route_handler.dart';
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo_mobile_ui/screens/navigation/status_bar.dart';
-import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_complete_modal.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo_mobile_ui/common/screens.i18n.dart';
-import 'package:filcnaplo/api/providers/news_provider.dart';
-import 'package:filcnaplo/api/providers/sync.dart';
-import 'package:home_widget/home_widget.dart';
-import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
-import 'package:background_fetch/background_fetch.dart';
-import 'package:filcnaplo_premium/providers/goal_provider.dart';
-import 'package:filcnaplo/api/providers/ad_provider.dart';
-
-class NavigationScreen extends StatefulWidget {
-  const NavigationScreen({Key? key}) : super(key: key);
-
-  static NavigationScreenState? of(BuildContext context) =>
-      context.findAncestorStateOfType<NavigationScreenState>();
-
-  @override
-  NavigationScreenState createState() => NavigationScreenState();
-}
-
-class NavigationScreenState extends State<NavigationScreen>
-    with WidgetsBindingObserver {
-  late NavigationRoute selected;
-  List<String> initializers = [];
-  final _navigatorState = GlobalKey<NavigatorState>();
-
-  late SettingsProvider settings;
-  late NewsProvider newsProvider;
-  late GoalProvider goalProvider;
-  late UpdateProvider updateProvider;
-  late GradeProvider gradeProvicer;
-  late AdProvider adProvider;
-
-  NavigatorState? get navigator => _navigatorState.currentState;
-
-  void customRoute(Route route) => navigator?.pushReplacement(route);
-
-  bool init(String id) {
-    if (initializers.contains(id)) return false;
-
-    initializers.add(id);
-
-    return true;
-  }
-
-  void _checkForWidgetLaunch() {
-    HomeWidget.initiallyLaunchedFromHomeWidget().then(_launchedFromWidget);
-  }
-
-  void _launchedFromWidget(Uri? uri) async {
-    if (uri == null) return;
-
-    if (uri.scheme == "timetable" && uri.authority == "refresh") {
-      Navigator.of(context).popUntil((route) => route.isFirst);
-
-      setPage("timetable");
-      _navigatorState.currentState
-          ?.pushNamedAndRemoveUntil("timetable", (_) => false);
-    } else if (uri.scheme == "settings" && uri.authority == "premium") {
-      Navigator.of(context).popUntil((route) => route.isFirst);
-
-      showSlidingBottomSheet(
-        context,
-        useRootNavigator: true,
-        builder: (context) => SlidingSheetDialog(
-          color: Theme.of(context).scaffoldBackgroundColor,
-          duration: const Duration(milliseconds: 400),
-          scrollSpec: const ScrollSpec.bouncingScroll(),
-          snapSpec: const SnapSpec(
-            snap: true,
-            snappings: [1.0],
-            initialSnap: 1.0,
-            positioning: SnapPositioning.relativeToSheetHeight,
-          ),
-          cornerRadius: 16,
-          cornerRadiusOnFullscreen: 0,
-          builder: (context, state) => Material(
-            color: Theme.of(context).scaffoldBackgroundColor,
-            child: const SettingsScreen(),
-          ),
-        ),
-      );
-    }
-  }
-
-  // Platform messages are asynchronous, so we initialize in an async method.
-  Future<void> initPlatformState() async {
-    // Configure BackgroundFetch.
-    int status = await BackgroundFetch.configure(
-        BackgroundFetchConfig(
-            minimumFetchInterval: 15,
-            stopOnTerminate: false,
-            enableHeadless: true,
-            requiresBatteryNotLow: false,
-            requiresCharging: false,
-            requiresStorageNotLow: false,
-            requiresDeviceIdle: false,
-            requiredNetworkType: NetworkType.ANY), (String taskId) async {
-      // <-- Event handler
-      // This is the fetch-event callback.
-      if (kDebugMode) {
-        print("[BackgroundFetch] Event received $taskId");
-      }
-
-      // IMPORTANT:  You must signal completion of your task or the OS can punish your app
-      // for taking too long in the background.
-      BackgroundFetch.finish(taskId);
-    }, (String taskId) async {
-      // <-- Task timeout handler.
-      // This task has exceeded its allowed running-time.  You must stop what you're doing and immediately .finish(taskId)
-      if (kDebugMode) {
-        print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
-      }
-      BackgroundFetch.finish(taskId);
-    });
-    if (kDebugMode) {
-      print('[BackgroundFetch] configure success: $status');
-    }
-
-    // If the widget was removed from the tree while the asynchronous platform
-    // message was in flight, we want to discard the reply rather than calling
-    // setState to update our non-existent appearance.
-    if (!mounted) return;
-  }
-
-  @override
-  void initState() {
-    super.initState();
-
-    HomeWidget.setAppGroupId('hu.refilc.naplo.group');
-
-    _checkForWidgetLaunch();
-    HomeWidget.widgetClicked.listen(_launchedFromWidget);
-
-    settings = Provider.of<SettingsProvider>(context, listen: false);
-    selected = NavigationRoute();
-    selected.index = settings.startPage.index; // set page index to start page
-
-    // add brightness observer
-    WidgetsBinding.instance.addObserver(this);
-
-    // set client User-Agent
-    Provider.of<KretaClient>(context, listen: false).userAgent =
-        settings.config.userAgent;
-
-    // get news
-    newsProvider = Provider.of<NewsProvider>(context, listen: false);
-    newsProvider.restore().then((value) => newsProvider.fetch());
-
-    // init grade provider (for goals)
-    gradeProvicer = Provider.of<GradeProvider>(context, listen: false);
-
-    // get goals
-    goalProvider = Provider.of<GoalProvider>(context, listen: false);
-    goalProvider.fetchDone(gradeProvider: gradeProvicer);
-
-    // get releases
-    updateProvider = Provider.of<UpdateProvider>(context, listen: false);
-    updateProvider.fetch();
-
-    // get advertisements
-    adProvider = Provider.of<AdProvider>(context, listen: false);
-    adProvider.fetch();
-
-    // initial sync
-    syncAll(context);
-    setupQuickActions();
-  }
-
-  @override
-  void dispose() {
-    WidgetsBinding.instance.removeObserver(this);
-    super.dispose();
-  }
-
-  @override
-  void didChangePlatformBrightness() {
-    if (settings.theme == ThemeMode.system) {
-      // ignore: deprecated_member_use
-      Brightness? brightness =
-          // ignore: deprecated_member_use
-          WidgetsBinding.instance.window.platformBrightness;
-      Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(
-          brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark);
-    }
-    super.didChangePlatformBrightness();
-  }
-
-  void setPage(String page) => setState(() => selected.name = page);
-
-  @override
-  Widget build(BuildContext context) {
-    setSystemChrome(context);
-    settings = Provider.of<SettingsProvider>(context);
-    newsProvider = Provider.of<NewsProvider>(context);
-    goalProvider = Provider.of<GoalProvider>(context);
-
-    // show news and complete goals
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      if (newsProvider.show) {
-        NewsView.show(newsProvider.news[0], context: context)
-            .then((value) => newsProvider.release());
-        newsProvider.lock();
-      }
-
-      if (goalProvider.hasDoneGoals) {
-        GoalCompleteModal.show(goalProvider.doneSubject!, context: context);
-        goalProvider.lock();
-      }
-    });
-
-    handleQuickActions(context, (page) {
-      setPage(page);
-      _navigatorState.currentState?.pushReplacementNamed(page);
-    });
-
-    return WillPopScope(
-      onWillPop: () async {
-        if (_navigatorState.currentState?.canPop() ?? false) {
-          _navigatorState.currentState?.pop();
-          if (!kDebugMode) {
-            return true;
-          }
-          return false;
-        }
-
-        if (selected.index != 0) {
-          setState(() => selected.index = 0);
-          _navigatorState.currentState?.pushReplacementNamed(selected.name);
-        }
-
-        return false;
-      },
-      child: Scaffold(
-        body: Column(
-          children: [
-            Expanded(
-              child: Stack(
-                alignment: Alignment.bottomCenter,
-                children: [
-                  Navigator(
-                    key: _navigatorState,
-                    initialRoute: selected.name,
-                    onGenerateRoute: (settings) =>
-                        navigationRouteHandler(settings),
-                  ),
-                ],
-              ),
-            ),
-
-            // Status bar
-            Material(
-              color: Theme.of(context).colorScheme.background,
-              child: const StatusBar(),
-            ),
-
-            // Bottom Navigaton Bar
-            Material(
-              color: Theme.of(context).scaffoldBackgroundColor,
-              child: MediaQuery.removePadding(
-                context: context,
-                removeTop: true,
-                child: Navbar(
-                  selectedIndex: selected.index,
-                  onSelected: onPageSelected,
-                  items: [
-                    NavItem(
-                      title: "home".i18n,
-                      icon: const Icon(FilcIcons.home),
-                      activeIcon: const Icon(FilcIcons.homefill),
-                    ),
-                    NavItem(
-                      title: "grades".i18n,
-                      icon: const Icon(FeatherIcons.bookmark),
-                      activeIcon: const Icon(FilcIcons.gradesfill),
-                    ),
-                    NavItem(
-                      title: "timetable".i18n,
-                      icon: const Icon(FeatherIcons.calendar),
-                      activeIcon: const Icon(FilcIcons.timetablefill),
-                    ),
-                    NavItem(
-                      title: "messages".i18n,
-                      icon: const Icon(FeatherIcons.messageSquare),
-                      activeIcon: const Icon(FilcIcons.messagesfill),
-                    ),
-                    NavItem(
-                      title: "absences".i18n,
-                      icon: const Icon(FeatherIcons.clock),
-                      activeIcon: const Icon(FilcIcons.absencesfill),
-                    ),
-                  ],
-                ),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-
-  void onPageSelected(int index) {
-    // Vibrate, then set the active screen
-    if (selected.index != index) {
-      switch (settings.vibrate) {
-        case VibrationStrength.light:
-          HapticFeedback.lightImpact();
-          break;
-        case VibrationStrength.medium:
-          HapticFeedback.mediumImpact();
-          break;
-        case VibrationStrength.strong:
-          HapticFeedback.heavyImpact();
-          break;
-        default:
-      }
-      setState(() => selected.index = index);
-      _navigatorState.currentState?.pushReplacementNamed(selected.name);
-    }
-  }
-}
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc/helpers/quick_actions.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/observer.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_mobile_ui/common/system_chrome.dart';
+import 'package:refilc_mobile_ui/screens/navigation/nabar.dart';
+import 'package:refilc_mobile_ui/screens/navigation/navbar_item.dart';
+import 'package:refilc_mobile_ui/screens/navigation/navigation_route.dart';
+import 'package:refilc_mobile_ui/screens/navigation/navigation_route_handler.dart';
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc_mobile_ui/screens/navigation/status_bar.dart';
+import 'package:refilc_mobile_ui/screens/news/news_view.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_complete_modal.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc_mobile_ui/common/screens.i18n.dart';
+import 'package:refilc/api/providers/news_provider.dart';
+import 'package:refilc/api/providers/sync.dart';
+import 'package:home_widget/home_widget.dart';
+import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
+import 'package:background_fetch/background_fetch.dart';
+import 'package:refilc_premium/providers/goal_provider.dart';
+import 'package:refilc/api/providers/ad_provider.dart';
+
+class NavigationScreen extends StatefulWidget {
+  const NavigationScreen({Key? key}) : super(key: key);
+
+  static NavigationScreenState? of(BuildContext context) =>
+      context.findAncestorStateOfType<NavigationScreenState>();
+
+  @override
+  NavigationScreenState createState() => NavigationScreenState();
+}
+
+class NavigationScreenState extends State<NavigationScreen>
+    with WidgetsBindingObserver {
+  late NavigationRoute selected;
+  List<String> initializers = [];
+  final _navigatorState = GlobalKey<NavigatorState>();
+
+  late SettingsProvider settings;
+  late NewsProvider newsProvider;
+  late GoalProvider goalProvider;
+  late UpdateProvider updateProvider;
+  late GradeProvider gradeProvicer;
+  late AdProvider adProvider;
+
+  NavigatorState? get navigator => _navigatorState.currentState;
+
+  void customRoute(Route route) => navigator?.pushReplacement(route);
+
+  bool init(String id) {
+    if (initializers.contains(id)) return false;
+
+    initializers.add(id);
+
+    return true;
+  }
+
+  void _checkForWidgetLaunch() {
+    HomeWidget.initiallyLaunchedFromHomeWidget().then(_launchedFromWidget);
+  }
+
+  void _launchedFromWidget(Uri? uri) async {
+    if (uri == null) return;
+
+    if (uri.scheme == "timetable" && uri.authority == "refresh") {
+      Navigator.of(context).popUntil((route) => route.isFirst);
+
+      setPage("timetable");
+      _navigatorState.currentState
+          ?.pushNamedAndRemoveUntil("timetable", (_) => false);
+    } else if (uri.scheme == "settings" && uri.authority == "premium") {
+      Navigator.of(context).popUntil((route) => route.isFirst);
+
+      showSlidingBottomSheet(
+        context,
+        useRootNavigator: true,
+        builder: (context) => SlidingSheetDialog(
+          color: Theme.of(context).scaffoldBackgroundColor,
+          duration: const Duration(milliseconds: 400),
+          scrollSpec: const ScrollSpec.bouncingScroll(),
+          snapSpec: const SnapSpec(
+            snap: true,
+            snappings: [1.0],
+            initialSnap: 1.0,
+            positioning: SnapPositioning.relativeToSheetHeight,
+          ),
+          cornerRadius: 16,
+          cornerRadiusOnFullscreen: 0,
+          builder: (context, state) => Material(
+            color: Theme.of(context).scaffoldBackgroundColor,
+            child: const SettingsScreen(),
+          ),
+        ),
+      );
+    }
+  }
+
+  // Platform messages are asynchronous, so we initialize in an async method.
+  Future<void> initPlatformState() async {
+    // Configure BackgroundFetch.
+    int status = await BackgroundFetch.configure(
+        BackgroundFetchConfig(
+            minimumFetchInterval: 15,
+            stopOnTerminate: false,
+            enableHeadless: true,
+            requiresBatteryNotLow: false,
+            requiresCharging: false,
+            requiresStorageNotLow: false,
+            requiresDeviceIdle: false,
+            requiredNetworkType: NetworkType.ANY), (String taskId) async {
+      // <-- Event handler
+      // This is the fetch-event callback.
+      if (kDebugMode) {
+        print("[BackgroundFetch] Event received $taskId");
+      }
+
+      // IMPORTANT:  You must signal completion of your task or the OS can punish your app
+      // for taking too long in the background.
+      BackgroundFetch.finish(taskId);
+    }, (String taskId) async {
+      // <-- Task timeout handler.
+      // This task has exceeded its allowed running-time.  You must stop what you're doing and immediately .finish(taskId)
+      if (kDebugMode) {
+        print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
+      }
+      BackgroundFetch.finish(taskId);
+    });
+    if (kDebugMode) {
+      print('[BackgroundFetch] configure success: $status');
+    }
+
+    // If the widget was removed from the tree while the asynchronous platform
+    // message was in flight, we want to discard the reply rather than calling
+    // setState to update our non-existent appearance.
+    if (!mounted) return;
+  }
+
+  @override
+  void initState() {
+    super.initState();
+
+    HomeWidget.setAppGroupId('hu.refilc.naplo.group');
+
+    _checkForWidgetLaunch();
+    HomeWidget.widgetClicked.listen(_launchedFromWidget);
+
+    settings = Provider.of<SettingsProvider>(context, listen: false);
+    selected = NavigationRoute();
+    selected.index = settings.startPage.index; // set page index to start page
+
+    // add brightness observer
+    WidgetsBinding.instance.addObserver(this);
+
+    // set client User-Agent
+    Provider.of<KretaClient>(context, listen: false).userAgent =
+        settings.config.userAgent;
+
+    // get news
+    newsProvider = Provider.of<NewsProvider>(context, listen: false);
+    newsProvider.restore().then((value) => newsProvider.fetch());
+
+    // init grade provider (for goals)
+    gradeProvicer = Provider.of<GradeProvider>(context, listen: false);
+
+    // get goals
+    goalProvider = Provider.of<GoalProvider>(context, listen: false);
+    goalProvider.fetchDone(gradeProvider: gradeProvicer);
+
+    // get releases
+    updateProvider = Provider.of<UpdateProvider>(context, listen: false);
+    updateProvider.fetch();
+
+    // get advertisements
+    adProvider = Provider.of<AdProvider>(context, listen: false);
+    adProvider.fetch();
+
+    // initial sync
+    syncAll(context);
+    setupQuickActions();
+  }
+
+  @override
+  void dispose() {
+    WidgetsBinding.instance.removeObserver(this);
+    super.dispose();
+  }
+
+  @override
+  void didChangePlatformBrightness() {
+    if (settings.theme == ThemeMode.system) {
+      // ignore: deprecated_member_use
+      Brightness? brightness =
+          // ignore: deprecated_member_use
+          WidgetsBinding.instance.window.platformBrightness;
+      Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(
+          brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark);
+    }
+    super.didChangePlatformBrightness();
+  }
+
+  void setPage(String page) => setState(() => selected.name = page);
+
+  @override
+  Widget build(BuildContext context) {
+    setSystemChrome(context);
+    settings = Provider.of<SettingsProvider>(context);
+    newsProvider = Provider.of<NewsProvider>(context);
+    goalProvider = Provider.of<GoalProvider>(context);
+
+    // show news and complete goals
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      if (newsProvider.show) {
+        NewsView.show(newsProvider.news[0], context: context)
+            .then((value) => newsProvider.release());
+        newsProvider.lock();
+      }
+
+      if (goalProvider.hasDoneGoals) {
+        GoalCompleteModal.show(goalProvider.doneSubject!, context: context);
+        goalProvider.lock();
+      }
+    });
+
+    handleQuickActions(context, (page) {
+      setPage(page);
+      _navigatorState.currentState?.pushReplacementNamed(page);
+    });
+
+    return WillPopScope(
+      onWillPop: () async {
+        if (_navigatorState.currentState?.canPop() ?? false) {
+          _navigatorState.currentState?.pop();
+          if (!kDebugMode) {
+            return true;
+          }
+          return false;
+        }
+
+        if (selected.index != 0) {
+          setState(() => selected.index = 0);
+          _navigatorState.currentState?.pushReplacementNamed(selected.name);
+        }
+
+        return false;
+      },
+      child: Scaffold(
+        body: Column(
+          children: [
+            Expanded(
+              child: Stack(
+                alignment: Alignment.bottomCenter,
+                children: [
+                  Navigator(
+                    key: _navigatorState,
+                    initialRoute: selected.name,
+                    onGenerateRoute: (settings) =>
+                        navigationRouteHandler(settings),
+                  ),
+                ],
+              ),
+            ),
+
+            // Status bar
+            Material(
+              color: Theme.of(context).colorScheme.background,
+              child: const StatusBar(),
+            ),
+
+            // Bottom Navigaton Bar
+            Material(
+              color: Theme.of(context).scaffoldBackgroundColor,
+              child: MediaQuery.removePadding(
+                context: context,
+                removeTop: true,
+                child: Navbar(
+                  selectedIndex: selected.index,
+                  onSelected: onPageSelected,
+                  items: [
+                    NavItem(
+                      title: "home".i18n,
+                      icon: const Icon(FilcIcons.home),
+                      activeIcon: const Icon(FilcIcons.homefill),
+                    ),
+                    NavItem(
+                      title: "grades".i18n,
+                      icon: const Icon(FeatherIcons.bookmark),
+                      activeIcon: const Icon(FilcIcons.gradesfill),
+                    ),
+                    NavItem(
+                      title: "timetable".i18n,
+                      icon: const Icon(FeatherIcons.calendar),
+                      activeIcon: const Icon(FilcIcons.timetablefill),
+                    ),
+                    NavItem(
+                      title: "messages".i18n,
+                      icon: const Icon(FeatherIcons.messageSquare),
+                      activeIcon: const Icon(FilcIcons.messagesfill),
+                    ),
+                    NavItem(
+                      title: "absences".i18n,
+                      icon: const Icon(FeatherIcons.clock),
+                      activeIcon: const Icon(FilcIcons.absencesfill),
+                    ),
+                  ],
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  void onPageSelected(int index) {
+    // Vibrate, then set the active screen
+    if (selected.index != index) {
+      switch (settings.vibrate) {
+        case VibrationStrength.light:
+          HapticFeedback.lightImpact();
+          break;
+        case VibrationStrength.medium:
+          HapticFeedback.mediumImpact();
+          break;
+        case VibrationStrength.strong:
+          HapticFeedback.heavyImpact();
+          break;
+        default:
+      }
+      setState(() => selected.index = index);
+      _navigatorState.currentState?.pushReplacementNamed(selected.name);
+    }
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart b/refilc_mobile_ui/lib/screens/navigation/status_bar.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart
rename to refilc_mobile_ui/lib/screens/navigation/status_bar.dart
index d79078f..eec38fb
--- a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/status_bar.dart
@@ -1,120 +1,120 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/color.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/api/providers/status_provider.dart';
-import 'status_bar.i18n.dart';
-
-class StatusBar extends StatefulWidget {
-  const StatusBar({Key? key}) : super(key: key);
-
-  @override
-  _StatusBarState createState() => _StatusBarState();
-}
-
-class _StatusBarState extends State<StatusBar> {
-  late StatusProvider statusProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    statusProvider = Provider.of<StatusProvider>(context);
-
-    Status? currentStatus = statusProvider.getStatus();
-    Color backgroundColor = _statusColor(currentStatus);
-    Color color = ColorUtils.foregroundColor(backgroundColor);
-
-    return AnimatedContainer(
-      duration: const Duration(milliseconds: 250),
-      curve: Curves.easeInOut,
-      height: currentStatus != null ? 32.0 : 0,
-      width: double.infinity,
-      color: Theme.of(context).scaffoldBackgroundColor,
-      child: Stack(
-        children: [
-          // Background
-          AnimatedContainer(
-            margin: const EdgeInsets.only(left: 6.0, right: 6.0, top: 8.0),
-            duration: const Duration(milliseconds: 250),
-            curve: Curves.easeInOut,
-            height: currentStatus != null ? 28.0 : 0,
-            decoration: BoxDecoration(
-              color: backgroundColor,
-              boxShadow: [
-                BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)
-              ],
-              borderRadius: BorderRadius.circular(45.0),
-            ),
-          ),
-
-          // Progress bar
-          if (currentStatus == Status.syncing)
-            Container(
-              margin: const EdgeInsets.only(left: 6.0, right: 6.0, top: 8.0),
-              alignment: Alignment.bottomLeft,
-              child: AnimatedContainer(
-                height: currentStatus != null ? 28.0 : 0,
-                duration: const Duration(milliseconds: 250),
-                curve: Curves.easeInOut,
-                width: MediaQuery.of(context).size.width *
-                        statusProvider.progress -
-                    16.0,
-                decoration: BoxDecoration(
-                  color:
-                      Theme.of(context).colorScheme.secondary.withOpacity(0.8),
-                  borderRadius: BorderRadius.circular(45.0),
-                ),
-              ),
-            ),
-
-          // Text
-          Padding(
-            padding: const EdgeInsets.only(top: 8.0),
-            child: Center(
-              child: Text(
-                _statusString(currentStatus),
-                style: TextStyle(color: color, fontWeight: FontWeight.w500),
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-
-  String _statusString(Status? status) {
-    switch (status) {
-      case Status.syncing:
-        return "Syncing data".i18n;
-      case Status.maintenance:
-        return "KRETA Maintenance".i18n;
-      case Status.apiError:
-        return "KRETA API error".i18n;
-      case Status.network:
-        return "No connection".i18n;
-      default:
-        return "";
-    }
-  }
-
-  Color _statusColor(Status? status) {
-    switch (status) {
-      case Status.maintenance:
-        return AppColors.of(context).red;
-      case Status.apiError:
-        return AppColors.of(context).red;
-      case Status.network:
-      case Status.syncing:
-      default:
-        HSLColor color =
-            HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor);
-        if (color.lightness >= 0.5) {
-          color = color.withSaturation(0.3);
-          color = color.withLightness(color.lightness - 0.1);
-        } else {
-          color = color.withSaturation(0);
-          color = color.withLightness(color.lightness + 0.2);
-        }
-        return color.toColor();
-    }
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/color.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/api/providers/status_provider.dart';
+import 'status_bar.i18n.dart';
+
+class StatusBar extends StatefulWidget {
+  const StatusBar({Key? key}) : super(key: key);
+
+  @override
+  _StatusBarState createState() => _StatusBarState();
+}
+
+class _StatusBarState extends State<StatusBar> {
+  late StatusProvider statusProvider;
+
+  @override
+  Widget build(BuildContext context) {
+    statusProvider = Provider.of<StatusProvider>(context);
+
+    Status? currentStatus = statusProvider.getStatus();
+    Color backgroundColor = _statusColor(currentStatus);
+    Color color = ColorUtils.foregroundColor(backgroundColor);
+
+    return AnimatedContainer(
+      duration: const Duration(milliseconds: 250),
+      curve: Curves.easeInOut,
+      height: currentStatus != null ? 32.0 : 0,
+      width: double.infinity,
+      color: Theme.of(context).scaffoldBackgroundColor,
+      child: Stack(
+        children: [
+          // Background
+          AnimatedContainer(
+            margin: const EdgeInsets.only(left: 6.0, right: 6.0, top: 8.0),
+            duration: const Duration(milliseconds: 250),
+            curve: Curves.easeInOut,
+            height: currentStatus != null ? 28.0 : 0,
+            decoration: BoxDecoration(
+              color: backgroundColor,
+              boxShadow: [
+                BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)
+              ],
+              borderRadius: BorderRadius.circular(45.0),
+            ),
+          ),
+
+          // Progress bar
+          if (currentStatus == Status.syncing)
+            Container(
+              margin: const EdgeInsets.only(left: 6.0, right: 6.0, top: 8.0),
+              alignment: Alignment.bottomLeft,
+              child: AnimatedContainer(
+                height: currentStatus != null ? 28.0 : 0,
+                duration: const Duration(milliseconds: 250),
+                curve: Curves.easeInOut,
+                width: MediaQuery.of(context).size.width *
+                        statusProvider.progress -
+                    16.0,
+                decoration: BoxDecoration(
+                  color:
+                      Theme.of(context).colorScheme.secondary.withOpacity(0.8),
+                  borderRadius: BorderRadius.circular(45.0),
+                ),
+              ),
+            ),
+
+          // Text
+          Padding(
+            padding: const EdgeInsets.only(top: 8.0),
+            child: Center(
+              child: Text(
+                _statusString(currentStatus),
+                style: TextStyle(color: color, fontWeight: FontWeight.w500),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  String _statusString(Status? status) {
+    switch (status) {
+      case Status.syncing:
+        return "Syncing data".i18n;
+      case Status.maintenance:
+        return "KRETA Maintenance".i18n;
+      case Status.apiError:
+        return "KRETA API error".i18n;
+      case Status.network:
+        return "No connection".i18n;
+      default:
+        return "";
+    }
+  }
+
+  Color _statusColor(Status? status) {
+    switch (status) {
+      case Status.maintenance:
+        return AppColors.of(context).red;
+      case Status.apiError:
+        return AppColors.of(context).red;
+      case Status.network:
+      case Status.syncing:
+      default:
+        HSLColor color =
+            HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor);
+        if (color.lightness >= 0.5) {
+          color = color.withSaturation(0.3);
+          color = color.withLightness(color.lightness - 0.1);
+        } else {
+          color = color.withSaturation(0);
+          color = color.withLightness(color.lightness + 0.2);
+        }
+        return color.toColor();
+    }
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart b/refilc_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
rename to refilc_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
index e86b9d2..5e6453d
--- a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
+++ b/refilc_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
@@ -1,30 +1,30 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "Syncing data": "Syncing data",
-          "KRETA Maintenance": "KRETA Maintenance",
-          "KRETA API error": "KRETA API Error",
-          "No connection": "No connection",
-        },
-        "hu_hu": {
-          "Syncing data": "Adatok frissítése",
-          "KRETA Maintenance": "KRÉTA Karbantartás",
-          "KRETA API error": "KRÉTA API Hiba",
-          "No connection": "Nincs kapcsolat",
-        },
-        "de_de": {
-          "Syncing data": "Daten aktualisieren",
-          "KRETA Maintenance": "KRETA Wartung",
-          "KRETA API error": "KRETA API Fehler",
-          "No connection": "Keine Verbindung",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Syncing data": "Syncing data",
+          "KRETA Maintenance": "KRETA Maintenance",
+          "KRETA API error": "KRETA API Error",
+          "No connection": "No connection",
+        },
+        "hu_hu": {
+          "Syncing data": "Adatok frissítése",
+          "KRETA Maintenance": "KRÉTA Karbantartás",
+          "KRETA API error": "KRÉTA API Hiba",
+          "No connection": "Nincs kapcsolat",
+        },
+        "de_de": {
+          "Syncing data": "Daten aktualisieren",
+          "KRETA Maintenance": "KRETA Wartung",
+          "KRETA API error": "KRETA API Fehler",
+          "No connection": "Keine Verbindung",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/news/news_screen.dart b/refilc_mobile_ui/lib/screens/news/news_screen.dart
old mode 100755
new mode 100644
similarity index 77%
rename from filcnaplo_mobile_ui/lib/screens/news/news_screen.dart
rename to refilc_mobile_ui/lib/screens/news/news_screen.dart
index 164afa3..f4fd4df
--- a/filcnaplo_mobile_ui/lib/screens/news/news_screen.dart
+++ b/refilc_mobile_ui/lib/screens/news/news_screen.dart
@@ -1,66 +1,66 @@
-import 'dart:math';
-
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/screens/news/news_tile.dart';
-import 'package:filcnaplo/models/news.dart';
-import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/api/providers/news_provider.dart';
-
-class NewsScreen extends StatelessWidget {
-  const NewsScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    var newsProvider = Provider.of<NewsProvider>(context);
-
-    List<News> news = [];
-    news = newsProvider.news.where((e) => e.title != "").toList();
-
-    return Scaffold(
-      appBar: AppBar(
-        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-        leading: BackButton(color: AppColors.of(context).text),
-        title: Text("news".i18n,
-            style: TextStyle(color: AppColors.of(context).text)),
-      ),
-      body: SafeArea(
-        child: RefreshIndicator(
-          onRefresh: () => newsProvider.fetch(),
-          child: ListView.builder(
-            physics: const BouncingScrollPhysics(
-                parent: AlwaysScrollableScrollPhysics()),
-            itemCount: max(news.length, 1),
-            itemBuilder: (context, index) {
-              if (news.isNotEmpty) {
-                return Padding(
-                  padding: const EdgeInsets.symmetric(
-                      horizontal: 24.0, vertical: 12.0),
-                  child: Panel(
-                    child: Material(
-                      type: MaterialType.transparency,
-                      child: NewsTile(
-                        news[index],
-                        onTap: () => NewsView.show(news[index],
-                            context: context, force: true),
-                      ),
-                    ),
-                  ),
-                );
-              } else {
-                return const Padding(
-                  padding: EdgeInsets.only(top: 24.0),
-                  child: Empty(subtitle: "Nothing to see here"),
-                );
-              }
-            },
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'dart:math';
+
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/screens/news/news_tile.dart';
+import 'package:refilc/models/news.dart';
+import 'package:refilc_mobile_ui/screens/news/news_view.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/api/providers/news_provider.dart';
+
+class NewsScreen extends StatelessWidget {
+  const NewsScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    var newsProvider = Provider.of<NewsProvider>(context);
+
+    List<News> news = [];
+    news = newsProvider.news.where((e) => e.title != "").toList();
+
+    return Scaffold(
+      appBar: AppBar(
+        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+        leading: BackButton(color: AppColors.of(context).text),
+        title: Text("news".i18n,
+            style: TextStyle(color: AppColors.of(context).text)),
+      ),
+      body: SafeArea(
+        child: RefreshIndicator(
+          onRefresh: () => newsProvider.fetch(),
+          child: ListView.builder(
+            physics: const BouncingScrollPhysics(
+                parent: AlwaysScrollableScrollPhysics()),
+            itemCount: max(news.length, 1),
+            itemBuilder: (context, index) {
+              if (news.isNotEmpty) {
+                return Padding(
+                  padding: const EdgeInsets.symmetric(
+                      horizontal: 24.0, vertical: 12.0),
+                  child: Panel(
+                    child: Material(
+                      type: MaterialType.transparency,
+                      child: NewsTile(
+                        news[index],
+                        onTap: () => NewsView.show(news[index],
+                            context: context, force: true),
+                      ),
+                    ),
+                  ),
+                );
+              } else {
+                return const Padding(
+                  padding: EdgeInsets.only(top: 24.0),
+                  child: Empty(subtitle: "Nothing to see here"),
+                );
+              }
+            },
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/news/news_tile.dart b/refilc_mobile_ui/lib/screens/news/news_tile.dart
old mode 100755
new mode 100644
similarity index 86%
rename from filcnaplo_mobile_ui/lib/screens/news/news_tile.dart
rename to refilc_mobile_ui/lib/screens/news/news_tile.dart
index e4ce1e5..afae89f
--- a/filcnaplo_mobile_ui/lib/screens/news/news_tile.dart
+++ b/refilc_mobile_ui/lib/screens/news/news_tile.dart
@@ -1,30 +1,30 @@
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/models/news.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-class NewsTile extends StatelessWidget {
-  const NewsTile(this.news, {Key? key, this.onTap}) : super(key: key);
-
-  final News news;
-  final Function()? onTap;
-
-  @override
-  Widget build(BuildContext context) {
-    return ListTile(
-      title: Text(
-        news.title,
-        maxLines: 1,
-        overflow: TextOverflow.ellipsis,
-        style: const TextStyle(fontWeight: FontWeight.w600),
-      ),
-      subtitle: Text(
-        news.content.escapeHtml().replaceAll("\n", " "),
-        maxLines: 2,
-        overflow: TextOverflow.ellipsis,
-        style: const TextStyle(fontWeight: FontWeight.w500),
-      ),
-      onTap: onTap,
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:refilc/models/news.dart';
+import 'package:refilc/utils/format.dart';
+
+class NewsTile extends StatelessWidget {
+  const NewsTile(this.news, {Key? key, this.onTap}) : super(key: key);
+
+  final News news;
+  final Function()? onTap;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListTile(
+      title: Text(
+        news.title,
+        maxLines: 1,
+        overflow: TextOverflow.ellipsis,
+        style: const TextStyle(fontWeight: FontWeight.w600),
+      ),
+      subtitle: Text(
+        news.content.escapeHtml().replaceAll("\n", " "),
+        maxLines: 2,
+        overflow: TextOverflow.ellipsis,
+        style: const TextStyle(fontWeight: FontWeight.w500),
+      ),
+      onTap: onTap,
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/news/news_view.dart b/refilc_mobile_ui/lib/screens/news/news_view.dart
old mode 100755
new mode 100644
similarity index 90%
rename from filcnaplo_mobile_ui/lib/screens/news/news_view.dart
rename to refilc_mobile_ui/lib/screens/news/news_view.dart
index ff12f7f..c544652
--- a/filcnaplo_mobile_ui/lib/screens/news/news_view.dart
+++ b/refilc_mobile_ui/lib/screens/news/news_view.dart
@@ -1,137 +1,137 @@
-import 'dart:io';
-
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_mobile_ui/common/dialog_button.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/models/news.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-import 'package:flutter_linkify/flutter_linkify.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
-
-class NewsView extends StatelessWidget {
-  const NewsView(this.news, {Key? key}) : super(key: key);
-
-  final News news;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
-      child: Material(
-        borderRadius: BorderRadius.circular(12.0),
-        child: Padding(
-          padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4.0),
-          child: Column(
-            children: [
-              // Content
-              Expanded(
-                child: ListView(
-                  physics: const BouncingScrollPhysics(),
-                  children: [
-                    Padding(
-                      padding: const EdgeInsets.only(
-                          left: 8.0, right: 6.0, top: 14.0, bottom: 8.0),
-                      child: Text(
-                        news.title,
-                        maxLines: 3,
-                        style: const TextStyle(
-                            fontWeight: FontWeight.w600, fontSize: 18.0),
-                      ),
-                    ),
-                    SelectableLinkify(
-                      text: news.content.escapeHtml(),
-                      options:
-                          const LinkifyOptions(looseUrl: true, removeWww: true),
-                      onOpen: (link) {
-                        launch(
-                          link.url,
-                          customTabsOption: CustomTabsOption(
-                              showPageTitle: true,
-                              toolbarColor:
-                                  Theme.of(context).scaffoldBackgroundColor),
-                        );
-                      },
-                      style: const TextStyle(
-                          fontWeight: FontWeight.w500, fontSize: 14.0),
-                    ),
-                  ],
-                ),
-              ),
-
-              // Actions
-              Row(
-                mainAxisAlignment: MainAxisAlignment.end,
-                children: [
-                  if (news.link != "")
-                    DialogButton(
-                      label: news.openLabel != ""
-                          ? news.openLabel
-                          : "open".i18n.toUpperCase(),
-                      onTap: () => launch(
-                        news.link,
-                        customTabsOption: CustomTabsOption(
-                            showPageTitle: true,
-                            toolbarColor:
-                                Theme.of(context).scaffoldBackgroundColor),
-                      ),
-                    ),
-                  DialogButton(
-                    label: "done".i18n,
-                    onTap: () => Navigator.of(context).maybePop(),
-                  ),
-                ],
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-
-  static Future<T?> show<T>(News news,
-      {required BuildContext context, bool force = false}) {
-    if (news.title == "") return Future<T?>.value(null);
-
-    bool popup = news.platform == 'all' || force;
-
-    if (Provider.of<SettingsProvider>(context, listen: false).newsEnabled ||
-        news.emergency ||
-        force) {
-      switch (news.platform.trim().toLowerCase()) {
-        case "android":
-          if (Platform.isAndroid) popup = true;
-          break;
-        case "ios":
-          if (Platform.isIOS) popup = true;
-          break;
-        case "linux":
-          if (Platform.isLinux) popup = true;
-          break;
-        case "windows":
-          if (Platform.isWindows) popup = true;
-          break;
-        case "macos":
-          if (Platform.isMacOS) popup = true;
-          break;
-        case "all":
-          popup = true;
-          break;
-        default:
-          popup = true;
-      }
-    } else {
-      popup = false;
-    }
-
-    if (popup) {
-      return showDialog<T?>(
-          context: context,
-          builder: (context) => NewsView(news),
-          barrierDismissible: true);
-    } else {
-      return Future<T?>.value(null);
-    }
-  }
-}
+import 'dart:io';
+
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_mobile_ui/common/dialog_button.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/models/news.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+import 'package:flutter_linkify/flutter_linkify.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
+
+class NewsView extends StatelessWidget {
+  const NewsView(this.news, {Key? key}) : super(key: key);
+
+  final News news;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
+      child: Material(
+        borderRadius: BorderRadius.circular(12.0),
+        child: Padding(
+          padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4.0),
+          child: Column(
+            children: [
+              // Content
+              Expanded(
+                child: ListView(
+                  physics: const BouncingScrollPhysics(),
+                  children: [
+                    Padding(
+                      padding: const EdgeInsets.only(
+                          left: 8.0, right: 6.0, top: 14.0, bottom: 8.0),
+                      child: Text(
+                        news.title,
+                        maxLines: 3,
+                        style: const TextStyle(
+                            fontWeight: FontWeight.w600, fontSize: 18.0),
+                      ),
+                    ),
+                    SelectableLinkify(
+                      text: news.content.escapeHtml(),
+                      options:
+                          const LinkifyOptions(looseUrl: true, removeWww: true),
+                      onOpen: (link) {
+                        launch(
+                          link.url,
+                          customTabsOption: CustomTabsOption(
+                              showPageTitle: true,
+                              toolbarColor:
+                                  Theme.of(context).scaffoldBackgroundColor),
+                        );
+                      },
+                      style: const TextStyle(
+                          fontWeight: FontWeight.w500, fontSize: 14.0),
+                    ),
+                  ],
+                ),
+              ),
+
+              // Actions
+              Row(
+                mainAxisAlignment: MainAxisAlignment.end,
+                children: [
+                  if (news.link != "")
+                    DialogButton(
+                      label: news.openLabel != ""
+                          ? news.openLabel
+                          : "open".i18n.toUpperCase(),
+                      onTap: () => launch(
+                        news.link,
+                        customTabsOption: CustomTabsOption(
+                            showPageTitle: true,
+                            toolbarColor:
+                                Theme.of(context).scaffoldBackgroundColor),
+                      ),
+                    ),
+                  DialogButton(
+                    label: "done".i18n,
+                    onTap: () => Navigator.of(context).maybePop(),
+                  ),
+                ],
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  static Future<T?> show<T>(News news,
+      {required BuildContext context, bool force = false}) {
+    if (news.title == "") return Future<T?>.value(null);
+
+    bool popup = news.platform == 'all' || force;
+
+    if (Provider.of<SettingsProvider>(context, listen: false).newsEnabled ||
+        news.emergency ||
+        force) {
+      switch (news.platform.trim().toLowerCase()) {
+        case "android":
+          if (Platform.isAndroid) popup = true;
+          break;
+        case "ios":
+          if (Platform.isIOS) popup = true;
+          break;
+        case "linux":
+          if (Platform.isLinux) popup = true;
+          break;
+        case "windows":
+          if (Platform.isWindows) popup = true;
+          break;
+        case "macos":
+          if (Platform.isMacOS) popup = true;
+          break;
+        case "all":
+          popup = true;
+          break;
+        default:
+          popup = true;
+      }
+    } else {
+      popup = false;
+    }
+
+    if (popup) {
+      return showDialog<T?>(
+          context: context,
+          builder: (context) => NewsView(news),
+          barrierDismissible: true);
+    } else {
+      return Future<T?>.value(null);
+    }
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/accounts/account_tile.dart b/refilc_mobile_ui/lib/screens/settings/accounts/account_tile.dart
old mode 100755
new mode 100644
similarity index 74%
rename from filcnaplo_mobile_ui/lib/screens/settings/accounts/account_tile.dart
rename to refilc_mobile_ui/lib/screens/settings/accounts/account_tile.dart
index 21715d3..57cb826
--- a/filcnaplo_mobile_ui/lib/screens/settings/accounts/account_tile.dart
+++ b/refilc_mobile_ui/lib/screens/settings/accounts/account_tile.dart
@@ -1,40 +1,48 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-
-class AccountTile extends StatelessWidget {
-  const AccountTile({Key? key, this.onTap, this.onTapMenu, this.profileImage, this.name, this.username}) : super(key: key);
-
-  final void Function()? onTap;
-  final void Function()? onTapMenu;
-  final Widget? profileImage;
-  final Widget? name;
-  final Widget? username;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Colors.transparent,
-      child: ListTile(
-        visualDensity: VisualDensity.compact,
-        contentPadding: const EdgeInsets.only(left: 12.0),
-        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-        onTap: onTap,
-        onLongPress: onTapMenu,
-        leading: profileImage,
-        title: name,
-        subtitle: username,
-        trailing: onTapMenu != null
-            ? Material(
-                color: Colors.transparent,
-                child: IconButton(
-                  splashRadius: 24.0,
-                  onPressed: onTapMenu,
-                  icon: Icon(FeatherIcons.moreVertical, color: AppColors.of(context).text.withOpacity(0.8)),
-                ),
-              )
-            : null,
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+
+class AccountTile extends StatelessWidget {
+  const AccountTile(
+      {Key? key,
+      this.onTap,
+      this.onTapMenu,
+      this.profileImage,
+      this.name,
+      this.username})
+      : super(key: key);
+
+  final void Function()? onTap;
+  final void Function()? onTapMenu;
+  final Widget? profileImage;
+  final Widget? name;
+  final Widget? username;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      color: Colors.transparent,
+      child: ListTile(
+        visualDensity: VisualDensity.compact,
+        contentPadding: const EdgeInsets.only(left: 12.0),
+        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+        onTap: onTap,
+        onLongPress: onTapMenu,
+        leading: profileImage,
+        title: name,
+        subtitle: username,
+        trailing: onTapMenu != null
+            ? Material(
+                color: Colors.transparent,
+                child: IconButton(
+                  splashRadius: 24.0,
+                  onPressed: onTapMenu,
+                  icon: Icon(FeatherIcons.moreVertical,
+                      color: AppColors.of(context).text.withOpacity(0.8)),
+                ),
+              )
+            : null,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/accounts/account_view.dart b/refilc_mobile_ui/lib/screens/settings/accounts/account_view.dart
old mode 100755
new mode 100644
similarity index 83%
rename from filcnaplo_mobile_ui/lib/screens/settings/accounts/account_view.dart
rename to refilc_mobile_ui/lib/screens/settings/accounts/account_view.dart
index b26f38d..68a98f7
--- a/filcnaplo_mobile_ui/lib/screens/settings/accounts/account_view.dart
+++ b/refilc_mobile_ui/lib/screens/settings/accounts/account_view.dart
@@ -1,61 +1,61 @@
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_card.dart';
-import 'package:filcnaplo_mobile_ui/common/detail.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_tile.dart';
-import 'package:flutter/material.dart';
-import 'package:intl/intl.dart';
-import 'account_view.i18n.dart';
-
-class AccountView extends StatelessWidget {
-  const AccountView(this.user, {Key? key}) : super(key: key);
-
-  final User user;
-
-  static void show(User user, {required BuildContext context}) =>
-      showBottomCard(context: context, child: AccountView(user));
-
-  @override
-  Widget build(BuildContext context) {
-    List<String> _nameParts = user.name.split(" ");
-    String _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          AccountTile(
-            profileImage: ProfileImage(
-              name: _firstName,
-              backgroundColor: Theme.of(context).colorScheme.primary,
-              role: user.role,
-            ),
-            name: SelectableText(
-              user.name,
-              style: const TextStyle(fontWeight: FontWeight.w500),
-              maxLines: 2,
-              minLines: 1,
-            ),
-            username: SelectableText(user.username),
-          ),
-
-          // User details
-          Detail(
-              title: "birthdate".i18n,
-              description:
-                  DateFormat("yyyy. MM. dd.").format(user.student.birth)),
-          Detail(title: "school".i18n, description: user.student.school.name),
-          if (user.student.className != null)
-            Detail(title: "class".i18n, description: user.student.className!),
-          if (user.student.address != null)
-            Detail(title: "address".i18n, description: user.student.address!),
-          if (user.student.parents.isNotEmpty)
-            Detail(
-                title: "parents".plural(user.student.parents.length),
-                description: user.student.parents.join(", ")),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/models/user.dart';
+import 'package:refilc_mobile_ui/common/bottom_card.dart';
+import 'package:refilc_mobile_ui/common/detail.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
+import 'package:refilc_mobile_ui/screens/settings/accounts/account_tile.dart';
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'account_view.i18n.dart';
+
+class AccountView extends StatelessWidget {
+  const AccountView(this.user, {Key? key}) : super(key: key);
+
+  final User user;
+
+  static void show(User user, {required BuildContext context}) =>
+      showBottomCard(context: context, child: AccountView(user));
+
+  @override
+  Widget build(BuildContext context) {
+    List<String> _nameParts = user.name.split(" ");
+    String _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          AccountTile(
+            profileImage: ProfileImage(
+              name: _firstName,
+              backgroundColor: Theme.of(context).colorScheme.primary,
+              role: user.role,
+            ),
+            name: SelectableText(
+              user.name,
+              style: const TextStyle(fontWeight: FontWeight.w500),
+              maxLines: 2,
+              minLines: 1,
+            ),
+            username: SelectableText(user.username),
+          ),
+
+          // User details
+          Detail(
+              title: "birthdate".i18n,
+              description:
+                  DateFormat("yyyy. MM. dd.").format(user.student.birth)),
+          Detail(title: "school".i18n, description: user.student.school.name),
+          if (user.student.className != null)
+            Detail(title: "class".i18n, description: user.student.className!),
+          if (user.student.address != null)
+            Detail(title: "address".i18n, description: user.student.address!),
+          if (user.student.parents.isNotEmpty)
+            Detail(
+                title: "parents".plural(user.student.parents.length),
+                description: user.student.parents.join(", ")),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/accounts/account_view.i18n.dart b/refilc_mobile_ui/lib/screens/settings/accounts/account_view.i18n.dart
old mode 100755
new mode 100644
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/settings/accounts/account_view.i18n.dart
rename to refilc_mobile_ui/lib/screens/settings/accounts/account_view.i18n.dart
index 0a01e51..7dd4471
--- a/filcnaplo_mobile_ui/lib/screens/settings/accounts/account_view.i18n.dart
+++ b/refilc_mobile_ui/lib/screens/settings/accounts/account_view.i18n.dart
@@ -1,33 +1,33 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension Localization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "birthdate": "Birth date",
-          "school": "School",
-          "class": "Class",
-          "address": "Home address",
-          "parents": "Parents".one("Parent"),
-        },
-        "hu_hu": {
-          "birthdate": "Születési dátum",
-          "school": "Iskola",
-          "class": "Osztály",
-          "address": "Lakcím",
-          "parents": "Szülők".one("Szülő"),
-        },
-        "de_de": {
-          "birthdate": "Geburtsdatum",
-          "school": "Schule",
-          "class": "Klasse",
-          "address": "Wohnanschrift",
-          "parents": "Eltern",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension Localization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "birthdate": "Birth date",
+          "school": "School",
+          "class": "Class",
+          "address": "Home address",
+          "parents": "Parents".one("Parent"),
+        },
+        "hu_hu": {
+          "birthdate": "Születési dátum",
+          "school": "Iskola",
+          "class": "Osztály",
+          "address": "Lakcím",
+          "parents": "Szülők".one("Szülő"),
+        },
+        "de_de": {
+          "birthdate": "Geburtsdatum",
+          "school": "Schule",
+          "class": "Klasse",
+          "address": "Wohnanschrift",
+          "parents": "Eltern",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/debug/subject_icon_gallery.dart b/refilc_mobile_ui/lib/screens/settings/debug/subject_icon_gallery.dart
old mode 100755
new mode 100644
similarity index 93%
rename from filcnaplo_mobile_ui/lib/screens/settings/debug/subject_icon_gallery.dart
rename to refilc_mobile_ui/lib/screens/settings/debug/subject_icon_gallery.dart
index d94bf84..5ab9447
--- a/filcnaplo_mobile_ui/lib/screens/settings/debug/subject_icon_gallery.dart
+++ b/refilc_mobile_ui/lib/screens/settings/debug/subject_icon_gallery.dart
@@ -1,81 +1,81 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/material.dart';
-
-class SubjectIconGallery extends StatelessWidget {
-  const SubjectIconGallery({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: AppBar(
-        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-        leading: BackButton(color: AppColors.of(context).text),
-        title: Text(
-          "Subject Icon Gallery",
-          style: TextStyle(color: AppColors.of(context).text),
-        ),
-      ),
-      body: ListView(
-        children: const [
-          SubjectIconItem("Matematika"),
-          SubjectIconItem("Magyar Nyelv"),
-          SubjectIconItem("Nyelvtan"),
-          SubjectIconItem("Irodalom"),
-          SubjectIconItem("Történelem"),
-          SubjectIconItem("Földrajz"),
-          SubjectIconItem("Rajz"),
-          SubjectIconItem("Vizuális kultúra"),
-          SubjectIconItem("Fizika"),
-          SubjectIconItem("Ének"),
-          SubjectIconItem("Testnevelés"),
-          SubjectIconItem("Kémia"),
-          SubjectIconItem("Biológia"),
-          SubjectIconItem("Természetismeret"),
-          SubjectIconItem("Erkölcstan"),
-          SubjectIconItem("Pénzügy"),
-          SubjectIconItem("Informatika"),
-          SubjectIconItem("Digitális kultúra"),
-          SubjectIconItem("Programozás"),
-          SubjectIconItem("Hálózat"),
-          SubjectIconItem("Színház technika"),
-          SubjectIconItem("Média"),
-          SubjectIconItem("Elektronika"),
-          SubjectIconItem("Gépészet"),
-          SubjectIconItem("Technika"),
-          SubjectIconItem("Tánc"),
-          SubjectIconItem("Filozófia"),
-          SubjectIconItem("Osztályfőnöki"),
-          SubjectIconItem("Gazdaság"),
-          SubjectIconItem("Szorgalom"),
-          SubjectIconItem("Magatartás"),
-          SubjectIconItem("Angol nyelv"),
-          SubjectIconItem("Linux"),
-        ],
-      ),
-    );
-  }
-}
-
-class SubjectIconItem extends StatelessWidget {
-  const SubjectIconItem(this.name, {Key? key}) : super(key: key);
-
-  final String name;
-
-  @override
-  Widget build(BuildContext context) {
-    return ListTile(
-      leading: Icon(
-        SubjectIcon.resolveVariant(subjectName: name, context: context),
-        color: AppColors.of(context).text,
-      ),
-      title: Text(
-        name,
-        style: TextStyle(
-          color: AppColors.of(context).text,
-          fontWeight: FontWeight.w500,
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/material.dart';
+
+class SubjectIconGallery extends StatelessWidget {
+  const SubjectIconGallery({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+        leading: BackButton(color: AppColors.of(context).text),
+        title: Text(
+          "Subject Icon Gallery",
+          style: TextStyle(color: AppColors.of(context).text),
+        ),
+      ),
+      body: ListView(
+        children: const [
+          SubjectIconItem("Matematika"),
+          SubjectIconItem("Magyar Nyelv"),
+          SubjectIconItem("Nyelvtan"),
+          SubjectIconItem("Irodalom"),
+          SubjectIconItem("Történelem"),
+          SubjectIconItem("Földrajz"),
+          SubjectIconItem("Rajz"),
+          SubjectIconItem("Vizuális kultúra"),
+          SubjectIconItem("Fizika"),
+          SubjectIconItem("Ének"),
+          SubjectIconItem("Testnevelés"),
+          SubjectIconItem("Kémia"),
+          SubjectIconItem("Biológia"),
+          SubjectIconItem("Természetismeret"),
+          SubjectIconItem("Erkölcstan"),
+          SubjectIconItem("Pénzügy"),
+          SubjectIconItem("Informatika"),
+          SubjectIconItem("Digitális kultúra"),
+          SubjectIconItem("Programozás"),
+          SubjectIconItem("Hálózat"),
+          SubjectIconItem("Színház technika"),
+          SubjectIconItem("Média"),
+          SubjectIconItem("Elektronika"),
+          SubjectIconItem("Gépészet"),
+          SubjectIconItem("Technika"),
+          SubjectIconItem("Tánc"),
+          SubjectIconItem("Filozófia"),
+          SubjectIconItem("Osztályfőnöki"),
+          SubjectIconItem("Gazdaság"),
+          SubjectIconItem("Szorgalom"),
+          SubjectIconItem("Magatartás"),
+          SubjectIconItem("Angol nyelv"),
+          SubjectIconItem("Linux"),
+        ],
+      ),
+    );
+  }
+}
+
+class SubjectIconItem extends StatelessWidget {
+  const SubjectIconItem(this.name, {Key? key}) : super(key: key);
+
+  final String name;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListTile(
+      leading: Icon(
+        SubjectIcon.resolveVariant(subjectName: name, context: context),
+        color: AppColors.of(context).text,
+      ),
+      title: Text(
+        name,
+        style: TextStyle(
+          color: AppColors.of(context).text,
+          fontWeight: FontWeight.w500,
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart b/refilc_mobile_ui/lib/screens/settings/notifications_screen.dart
similarity index 96%
rename from filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart
rename to refilc_mobile_ui/lib/screens/settings/notifications_screen.dart
index 5c60a9d..c4b14be 100644
--- a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.dart
+++ b/refilc_mobile_ui/lib/screens/settings/notifications_screen.dart
@@ -1,8 +1,8 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_mobile_ui/common/beta_chip.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_mobile_ui/common/beta_chip.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart b/refilc_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart
similarity index 100%
rename from filcnaplo_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart
rename to refilc_mobile_ui/lib/screens/settings/notifications_screen.i18n.dart
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/privacy_view.dart b/refilc_mobile_ui/lib/screens/settings/privacy_view.dart
old mode 100755
new mode 100644
similarity index 98%
rename from filcnaplo_mobile_ui/lib/screens/settings/privacy_view.dart
rename to refilc_mobile_ui/lib/screens/settings/privacy_view.dart
index 89a9c30..13a9257
--- a/filcnaplo_mobile_ui/lib/screens/settings/privacy_view.dart
+++ b/refilc_mobile_ui/lib/screens/settings/privacy_view.dart
@@ -1,59 +1,59 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
-import 'package:flutter_linkify/flutter_linkify.dart';
-import 'settings_screen.i18n.dart';
-
-class PrivacyView extends StatelessWidget {
-  const PrivacyView({Key? key}) : super(key: key);
-
-  static void show(BuildContext context) => showDialog(
-      context: context,
-      builder: (context) => const PrivacyView(),
-      barrierDismissible: true);
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
-      child: Material(
-        borderRadius: BorderRadius.circular(12.0),
-        child: Padding(
-          padding: const EdgeInsets.all(12.0),
-          child: ListView(
-            physics: const BouncingScrollPhysics(),
-            children: [
-              Padding(
-                padding: const EdgeInsets.all(8.0),
-                child: Text("privacy".i18n),
-              ),
-              SelectableLinkify(
-                text: """
-  • A reFilc (továbbiakban alkalmazás) egy mobilos, asztali és webes kliensalkalmazás, segítségével az e-Kréta rendszeréből letöltheted és felhasználóbarát módon megjelenítheted az adataidat. Tanulmányi adataid csak közvetlenül az alkalmazás és a Kréta-szerverek között közlekednek, titkosított kapcsolaton keresztül.
-
-  • A reFilc fejlesztői és/vagy üzemeltetői, valamint az alkalmazás a tanulmányi és személyes adataidat semmilyen célból és semmilyen körülmények között nem másolják, nem tárolják és harmadik félnek nem továbbítják. Ezeket így az Educational Development Informatikai Zrt. kezeli, az Ő adatkezeléssel kapcsolatos tájékoztatójukat itt találod: https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4065038
-
-  • Azok törlésével vagy módosítával kapcsolatban keresd az osztályfőnöködet vagy az iskolád rendszergazdáját.
-
-  • Az alkalmazás névtelen használati statisztikákat gyűjt, ezek alapján tudjuk meghatározni a felhasználók és a telepítések számát, valamint az eszközük platformját. Ezt a beállításokban kikapcsolhatod. Kérünk, hogy ha csak teheted, hagyd ezt a funkciót bekapcsolva, hogy pontosabb információnk legyen a felhasználóink platform-megoszlásáról.
-
-  • Amikor az alkalmazás hibába ütközik, lehetőség van hibajelentés küldésére. Ez személyes- és/vagy tanulmányi adatokat nem tartalmaz, viszont részletes információval szolgál a hibáról, annak okáról és eszközödről. A küldés előtt megjelenő képernyőn a te felelősséged átnézni a továbbításra kerülő adatsort. A hibajelentéseket a reFilc fejlesztői felületén és egy privát Discord szobában tároljuk, ezekhez csak az app fejlesztői férnek hozzá.
-
-  • Az alkalmazás (az alábbi platformokon: Android, Linux, Windows) minden egyes indításakor a reFilc API, valamint a Github API segítségével ellenőrzi, hogy elérhető-e új verzió, és kérésre innen letölti és telepíti a frissítést.
-
-  • Amennyiben az adataiddal kapcsolatban bármilyen kérdésed van (megtekintés, törlés, módosítás, adathordozás), keress minket a social@refilc.hu e-mail címen, vagy Discord szerverünkön!
-  
-  • A kliensalkalmazás bármely eszközön és platformon történő használatával tudomásul vetted és elfogadod a jelen adatkezelési tájékoztatót. A reFilc csapata fenntartja a jogot a tájékoztató módosítására és a módosításokról nem köteles értesíteni a felhasználóit!
-""",
-                onOpen: (link) => launch(link.url,
-                    customTabsOption: CustomTabsOption(
-                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-                      showPageTitle: true,
-                    )),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
+import 'package:flutter_linkify/flutter_linkify.dart';
+import 'settings_screen.i18n.dart';
+
+class PrivacyView extends StatelessWidget {
+  const PrivacyView({Key? key}) : super(key: key);
+
+  static void show(BuildContext context) => showDialog(
+      context: context,
+      builder: (context) => const PrivacyView(),
+      barrierDismissible: true);
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
+      child: Material(
+        borderRadius: BorderRadius.circular(12.0),
+        child: Padding(
+          padding: const EdgeInsets.all(12.0),
+          child: ListView(
+            physics: const BouncingScrollPhysics(),
+            children: [
+              Padding(
+                padding: const EdgeInsets.all(8.0),
+                child: Text("privacy".i18n),
+              ),
+              SelectableLinkify(
+                text: """
+  • A reFilc (továbbiakban alkalmazás) egy mobilos, asztali és webes kliensalkalmazás, segítségével az e-Kréta rendszeréből letöltheted és felhasználóbarát módon megjelenítheted az adataidat. Tanulmányi adataid csak közvetlenül az alkalmazás és a Kréta-szerverek között közlekednek, titkosított kapcsolaton keresztül.
+
+  • A reFilc fejlesztői és/vagy üzemeltetői, valamint az alkalmazás a tanulmányi és személyes adataidat semmilyen célból és semmilyen körülmények között nem másolják, nem tárolják és harmadik félnek nem továbbítják. Ezeket így az Educational Development Informatikai Zrt. kezeli, az Ő adatkezeléssel kapcsolatos tájékoztatójukat itt találod: https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4065038
+
+  • Azok törlésével vagy módosítával kapcsolatban keresd az osztályfőnöködet vagy az iskolád rendszergazdáját.
+
+  • Az alkalmazás névtelen használati statisztikákat gyűjt, ezek alapján tudjuk meghatározni a felhasználók és a telepítések számát, valamint az eszközük platformját. Ezt a beállításokban kikapcsolhatod. Kérünk, hogy ha csak teheted, hagyd ezt a funkciót bekapcsolva, hogy pontosabb információnk legyen a felhasználóink platform-megoszlásáról.
+
+  • Amikor az alkalmazás hibába ütközik, lehetőség van hibajelentés küldésére. Ez személyes- és/vagy tanulmányi adatokat nem tartalmaz, viszont részletes információval szolgál a hibáról, annak okáról és eszközödről. A küldés előtt megjelenő képernyőn a te felelősséged átnézni a továbbításra kerülő adatsort. A hibajelentéseket a reFilc fejlesztői felületén és egy privát Discord szobában tároljuk, ezekhez csak az app fejlesztői férnek hozzá.
+
+  • Az alkalmazás (az alábbi platformokon: Android, Linux, Windows) minden egyes indításakor a reFilc API, valamint a Github API segítségével ellenőrzi, hogy elérhető-e új verzió, és kérésre innen letölti és telepíti a frissítést.
+
+  • Amennyiben az adataiddal kapcsolatban bármilyen kérdésed van (megtekintés, törlés, módosítás, adathordozás), keress minket a social@refilc.hu e-mail címen, vagy Discord szerverünkön!
+  
+  • A kliensalkalmazás bármely eszközön és platformon történő használatával tudomásul vetted és elfogadod a jelen adatkezelési tájékoztatót. A reFilc csapata fenntartja a jogot a tájékoztató módosítására és a módosításokról nem köteles értesíteni a felhasználóit!
+""",
+                onOpen: (link) => launch(link.url,
+                    customTabsOption: CustomTabsOption(
+                      toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+                      showPageTitle: true,
+                    )),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_helper.dart b/refilc_mobile_ui/lib/screens/settings/settings_helper.dart
old mode 100755
new mode 100644
similarity index 91%
rename from filcnaplo_mobile_ui/lib/screens/settings/settings_helper.dart
rename to refilc_mobile_ui/lib/screens/settings/settings_helper.dart
index 44b1334..94cc582
--- a/filcnaplo_mobile_ui/lib/screens/settings/settings_helper.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_helper.dart
@@ -1,680 +1,680 @@
-// ignore_for_file: prefer_function_declarations_over_variables
-
-import 'dart:io';
-
-import 'package:filcnaplo/helpers/quick_actions.dart';
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/theme/observer.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
-import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/material_action_button.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo_mobile_ui/common/screens.i18n.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
-import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
-import 'package:filcnaplo/models/icon_pack.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
-
-class SettingsHelper {
-  static const Map<String, String> langMap = {
-    "en": "🇬🇧  English",
-    "hu": "🇭🇺  Magyar",
-    "de": "🇩🇪  Deutsch"
-  };
-
-  static const Map<Pages, String> pageTitle = {
-    Pages.home: "home",
-    Pages.grades: "grades",
-    Pages.timetable: "timetable",
-    Pages.messages: "messages",
-    Pages.absences: "absences",
-  };
-
-  static Map<VibrationStrength, String> vibrationTitle = {
-    VibrationStrength.off: "voff",
-    VibrationStrength.light: "vlight",
-    VibrationStrength.medium: "vmedium",
-    VibrationStrength.strong: "vstrong",
-  };
-
-  static Map<Pages, String> localizedPageTitles() => pageTitle
-      .map((key, value) => MapEntry(key, ScreensLocalization(value).i18n));
-  static Map<VibrationStrength, String> localizedVibrationTitles() =>
-      vibrationTitle
-          .map((key, value) => MapEntry(key, SettingsLocalization(value).i18n));
-
-  static void language(BuildContext context) {
-    showBottomSheetMenu(
-      context,
-      items: List.generate(langMap.length, (index) {
-        String lang = langMap.keys.toList()[index];
-        return BottomSheetMenuItem(
-          onPressed: () {
-            Provider.of<SettingsProvider>(context, listen: false)
-                .update(language: lang);
-            I18n.of(context).locale = Locale(lang, lang.toUpperCase());
-            Navigator.of(context).maybePop();
-            if (Platform.isAndroid || Platform.isIOS) {
-              setupQuickActions();
-            }
-          },
-          title: Row(
-            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-            children: [
-              Text(langMap.values.toList()[index]),
-              if (lang == I18n.of(context).locale.languageCode)
-                Icon(
-                  Icons.check_circle,
-                  color: Theme.of(context).colorScheme.secondary,
-                ),
-            ],
-          ),
-        );
-      }),
-    );
-  }
-
-  static void uwuMode(BuildContext context, value) {
-    final settings = Provider.of<SettingsProvider>(context, listen: false);
-    if (value) {
-      I18n.of(context).locale = const Locale('uw', 'UW');
-    } else {
-      I18n.of(context).locale =
-          Locale(settings.language, settings.language.toUpperCase());
-    }
-    if (Platform.isAndroid || Platform.isIOS) {
-      setupQuickActions();
-    }
-  }
-
-  static void iconPack(BuildContext context) {
-    final settings = Provider.of<SettingsProvider>(context, listen: false);
-    showBottomSheetMenu(
-      context,
-      items: List.generate(IconPack.values.length, (index) {
-        IconPack current = IconPack.values[index];
-        return BottomSheetMenuItem(
-          onPressed: () {
-            settings.update(iconPack: current);
-            Navigator.of(context).maybePop();
-          },
-          title: Row(
-            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-            children: [
-              Text(current.name.capital()),
-              if (current == settings.iconPack)
-                Icon(
-                  Icons.check_circle,
-                  color: Theme.of(context).colorScheme.secondary,
-                ),
-            ],
-          ),
-        );
-      }),
-    );
-  }
-
-  static void startPage(BuildContext context) {
-    Map<Pages, IconData> pageIcons = {
-      Pages.home: FilcIcons.home,
-      Pages.grades: FeatherIcons.bookmark,
-      Pages.timetable: FeatherIcons.calendar,
-      Pages.messages: FeatherIcons.messageSquare,
-      Pages.absences: FeatherIcons.clock,
-    };
-
-    showBottomSheetMenu(
-      context,
-      items: List.generate(Pages.values.length, (index) {
-        return BottomSheetMenuItem(
-          onPressed: () {
-            Provider.of<SettingsProvider>(context, listen: false)
-                .update(startPage: Pages.values[index]);
-            Navigator.of(context).maybePop();
-          },
-          title: Row(
-            children: [
-              Icon(pageIcons[Pages.values[index]],
-                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
-              const SizedBox(width: 16.0),
-              Text(localizedPageTitles()[Pages.values[index]] ?? ""),
-              const Spacer(),
-              if (Pages.values[index] ==
-                  Provider.of<SettingsProvider>(context, listen: false)
-                      .startPage)
-                Icon(
-                  Icons.check_circle,
-                  color: Theme.of(context).colorScheme.secondary,
-                ),
-            ],
-          ),
-        );
-      }),
-    );
-  }
-
-  static void rounding(BuildContext context) {
-    showRoundedModalBottomSheet(
-      context,
-      child: const RoundingSetting(),
-    );
-  }
-
-  static void theme(BuildContext context) {
-    var settings = Provider.of<SettingsProvider>(context, listen: false);
-    void Function(ThemeMode) setTheme = (mode) {
-      settings.update(theme: mode);
-      Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(mode);
-      Navigator.of(context).maybePop();
-    };
-
-    showBottomSheetMenu(context, items: [
-      BottomSheetMenuItem(
-        onPressed: () => setTheme(ThemeMode.system),
-        title: Row(
-          children: [
-            Padding(
-              padding: const EdgeInsets.only(right: 16.0),
-              child: Icon(FeatherIcons.smartphone,
-                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
-            ),
-            Text(SettingsLocalization("system").i18n),
-            const Spacer(),
-            if (settings.theme == ThemeMode.system)
-              Icon(
-                Icons.check_circle,
-                color: Theme.of(context).colorScheme.secondary,
-              ),
-          ],
-        ),
-      ),
-      BottomSheetMenuItem(
-        onPressed: () => setTheme(ThemeMode.light),
-        title: Row(
-          children: [
-            Padding(
-              padding: const EdgeInsets.only(right: 16.0),
-              child: Icon(FeatherIcons.sun,
-                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
-            ),
-            Text(SettingsLocalization("light").i18n),
-            const Spacer(),
-            if (settings.theme == ThemeMode.light)
-              Icon(
-                Icons.check_circle,
-                color: Theme.of(context).colorScheme.secondary,
-              ),
-          ],
-        ),
-      ),
-      BottomSheetMenuItem(
-        onPressed: () => setTheme(ThemeMode.dark),
-        title: Row(
-          children: [
-            Padding(
-              padding: const EdgeInsets.only(right: 16.0),
-              child: Icon(FeatherIcons.moon,
-                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
-            ),
-            Text(SettingsLocalization("dark").i18n),
-            const Spacer(),
-            if (settings.theme == ThemeMode.dark)
-              Icon(
-                Icons.check_circle,
-                color: Theme.of(context).colorScheme.secondary,
-              ),
-          ],
-        ),
-      )
-    ]);
-  }
-
-  static void accentColor(BuildContext context) {
-    Navigator.of(context, rootNavigator: true).push(
-      PageRouteBuilder(
-        pageBuilder: (context, _, __) =>
-            const PremiumCustomAccentColorSetting(),
-        transitionDuration: Duration.zero,
-        reverseTransitionDuration: Duration.zero,
-      ),
-    );
-  }
-
-  static void gradeColors(BuildContext context) {
-    showRoundedModalBottomSheet(
-      context,
-      child: const GradeColorsSetting(),
-    );
-  }
-
-  static void liveActivityColor(BuildContext context) {
-    showRoundedModalBottomSheet(
-      context,
-      child: const LiveActivityColorSetting(),
-    );
-  }
-
-  static void vibrate(BuildContext context) {
-    showBottomSheetMenu(
-      context,
-      items: List.generate(VibrationStrength.values.length, (index) {
-        VibrationStrength value = VibrationStrength.values[index];
-
-        return BottomSheetMenuItem(
-          onPressed: () {
-            Provider.of<SettingsProvider>(context, listen: false)
-                .update(vibrate: value);
-            Navigator.of(context).maybePop();
-          },
-          title: Row(
-            children: [
-              Container(
-                width: 12.0,
-                height: 12.0,
-                decoration: BoxDecoration(
-                  color: Theme.of(context)
-                      .colorScheme
-                      .secondary
-                      .withOpacity((index + 1) / (vibrationTitle.length + 1)),
-                  shape: BoxShape.circle,
-                ),
-              ),
-              const SizedBox(width: 16.0),
-              Text(localizedVibrationTitles()[value] ?? "?"),
-              const Spacer(),
-              if (value ==
-                  Provider.of<SettingsProvider>(context, listen: false).vibrate)
-                Icon(
-                  Icons.check_circle,
-                  color: Theme.of(context).colorScheme.secondary,
-                ),
-            ],
-          ),
-        );
-      }),
-    );
-  }
-
-  static void bellDelay(BuildContext context) {
-    showRoundedModalBottomSheet(
-      context,
-      child: const BellDelaySetting(),
-    );
-  }
-}
-
-// Rounding modal
-class RoundingSetting extends StatefulWidget {
-  const RoundingSetting({Key? key}) : super(key: key);
-
-  @override
-  _RoundingSettingState createState() => _RoundingSettingState();
-}
-
-class _RoundingSettingState extends State<RoundingSetting> {
-  late double rounding;
-
-  @override
-  void initState() {
-    super.initState();
-    rounding =
-        Provider.of<SettingsProvider>(context, listen: false).rounding / 10;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    int roundingResult;
-
-    if (4.5 >= 4.5.floor() + rounding) {
-      roundingResult = 5;
-    } else {
-      roundingResult = 4;
-    }
-
-    return Column(children: [
-      Row(
-        mainAxisAlignment: MainAxisAlignment.spaceBetween,
-        children: [
-          Expanded(
-            child: Slider(
-              value: rounding,
-              min: 0.1,
-              max: 0.9,
-              divisions: 8,
-              label: rounding.toStringAsFixed(1),
-              activeColor: Theme.of(context).colorScheme.secondary,
-              thumbColor: Theme.of(context).colorScheme.secondary,
-              onChanged: (v) => setState(() => rounding = v),
-            ),
-          ),
-          Container(
-            width: 50.0,
-            padding: const EdgeInsets.only(right: 16.0),
-            child: Center(
-              child: Text(rounding.toStringAsFixed(1),
-                  style: const TextStyle(
-                    fontWeight: FontWeight.w600,
-                    fontSize: 18.0,
-                  )),
-            ),
-          ),
-        ],
-      ),
-      Row(
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          const Text("4.5",
-              style: TextStyle(fontSize: 26.0, fontWeight: FontWeight.w500)),
-          const Padding(
-            padding: EdgeInsets.symmetric(horizontal: 24.0),
-            child: Icon(FeatherIcons.arrowRight, color: Colors.grey),
-          ),
-          GradeValueWidget(GradeValue(roundingResult, "", "", 100),
-              fill: true, size: 32.0),
-        ],
-      ),
-      Padding(
-        padding: const EdgeInsets.only(bottom: 12.0, top: 6.0),
-        child: MaterialActionButton(
-          child: Text(SettingsLocalization("done").i18n),
-          onPressed: () {
-            Provider.of<SettingsProvider>(context, listen: false)
-                .update(rounding: (rounding * 10).toInt());
-            Navigator.of(context).maybePop();
-          },
-        ),
-      ),
-    ]);
-  }
-}
-
-// Bell Delay Modal
-
-class BellDelaySetting extends StatefulWidget {
-  const BellDelaySetting({Key? key}) : super(key: key);
-
-  @override
-  State<BellDelaySetting> createState() => _BellDelaySettingState();
-}
-
-class _BellDelaySettingState extends State<BellDelaySetting>
-    with SingleTickerProviderStateMixin {
-  late TabController _tabController;
-  late Duration currentDelay;
-
-  @override
-  void initState() {
-    super.initState();
-    _tabController = TabController(
-        length: 2,
-        vsync: this,
-        initialIndex:
-            Provider.of<SettingsProvider>(context, listen: false).bellDelay > 0
-                ? 1
-                : 0);
-    currentDelay = Duration(
-        seconds:
-            Provider.of<SettingsProvider>(context, listen: false).bellDelay);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(
-      children: [
-        FilterBar(
-          scrollable: false,
-          items: [
-            Tab(text: SettingsLocalization("delay").i18n),
-            Tab(text: SettingsLocalization("hurry").i18n),
-          ],
-          controller: _tabController,
-          onTap: (i) async {
-            // swap current page with target page
-            setState(() {
-              currentDelay = i == 0 ? -currentDelay.abs() : currentDelay.abs();
-            });
-          },
-        ),
-        SizedBox(
-          height: 200,
-          child: CupertinoTheme(
-            data: CupertinoThemeData(
-              brightness: Theme.of(context).brightness,
-            ),
-            child: CupertinoTimerPicker(
-              key: UniqueKey(),
-              mode: CupertinoTimerPickerMode.ms,
-              initialTimerDuration: currentDelay.abs(),
-              onTimerDurationChanged: (Duration d) {
-                HapticFeedback.selectionClick();
-
-                currentDelay = _tabController.index == 0 ? -d : d;
-              },
-            ),
-          ),
-        ),
-        Text(SettingsLocalization("sync_help").i18n,
-            textAlign: TextAlign.center,
-            style: TextStyle(
-                fontSize: 12.0,
-                fontWeight: FontWeight.w500,
-                color: AppColors.of(context).text.withOpacity(.75))),
-        Padding(
-          padding: const EdgeInsets.only(bottom: 12.0, top: 6.0),
-          child: Column(
-            children: [
-              MaterialActionButton(
-                backgroundColor: AppColors.of(context).filc,
-                child: Text(SettingsLocalization("sync").i18n),
-                onPressed: () {
-                  final lessonProvider =
-                      Provider.of<TimetableProvider>(context, listen: false);
-
-                  Duration? closest;
-                  DateTime now = DateTime.now();
-                  for (var lesson
-                      in lessonProvider.getWeek(Week.current()) ?? []) {
-                    Duration sdiff = lesson.start.difference(now);
-                    Duration ediff = lesson.end.difference(now);
-
-                    if (closest == null || sdiff.abs() < closest.abs()) {
-                      closest = sdiff;
-                    }
-                    if (ediff.abs() < closest.abs()) closest = ediff;
-                  }
-                  if (closest != null) {
-                    if (closest.inHours.abs() >= 1) return;
-                    currentDelay = closest;
-                    Provider.of<SettingsProvider>(context, listen: false)
-                        .update(bellDelay: currentDelay.inSeconds);
-                    _tabController.index = currentDelay.inSeconds > 0 ? 1 : 0;
-                    setState(() {});
-                  }
-                },
-              ),
-              MaterialActionButton(
-                child: Text(SettingsLocalization("done").i18n),
-                onPressed: () {
-                  //Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt());
-                  Provider.of<SettingsProvider>(context, listen: false)
-                      .update(bellDelay: currentDelay.inSeconds);
-                  Navigator.of(context).maybePop();
-                },
-              ),
-            ],
-          ),
-        ),
-      ],
-    );
-  }
-}
-
-class GradeColorsSetting extends StatefulWidget {
-  const GradeColorsSetting({Key? key}) : super(key: key);
-
-  @override
-  _GradeColorsSettingState createState() => _GradeColorsSettingState();
-}
-
-class _GradeColorsSettingState extends State<GradeColorsSetting> {
-  Color currentColor = const Color(0x00000000);
-  late SettingsProvider settings;
-
-  @override
-  void initState() {
-    super.initState();
-    settings = Provider.of<SettingsProvider>(context, listen: false);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(children: [
-      Padding(
-        padding: const EdgeInsets.all(8.0),
-        child: Row(
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-          children: List.generate(5, (index) {
-            return ClipOval(
-              child: Material(
-                type: MaterialType.transparency,
-                child: InkWell(
-                  onTap: () {
-                    currentColor = settings.gradeColors[index];
-                    showRoundedModalBottomSheet(
-                      context,
-                      child: Column(children: [
-                        MaterialColorPicker(
-                          selectedColor: settings.gradeColors[index],
-                          onColorChange: (v) {
-                            setState(() {
-                              currentColor = v;
-                            });
-                          },
-                          allowShades: true,
-                          elevation: 0,
-                          physics: const NeverScrollableScrollPhysics(),
-                        ),
-                        Padding(
-                          padding: const EdgeInsets.only(bottom: 8.0),
-                          child: Row(
-                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-                            children: [
-                              MaterialActionButton(
-                                onPressed: () {
-                                  List<Color> colors =
-                                      List.castFrom(settings.gradeColors);
-                                  var defaultColors =
-                                      SettingsProvider.defaultSettings()
-                                          .gradeColors;
-                                  colors[index] = defaultColors[index];
-                                  settings.update(gradeColors: colors);
-                                  Navigator.of(context).maybePop();
-                                },
-                                child: Text(SettingsLocalization("reset").i18n),
-                              ),
-                              MaterialActionButton(
-                                onPressed: () {
-                                  List<Color> colors =
-                                      List.castFrom(settings.gradeColors);
-                                  colors[index] = currentColor.withAlpha(255);
-                                  settings.update(
-                                      gradeColors: settings.gradeColors);
-                                  Navigator.of(context).maybePop();
-                                },
-                                child: Text(SettingsLocalization("done").i18n),
-                              ),
-                            ],
-                          ),
-                        ),
-                      ]),
-                    ).then((value) => setState(() {}));
-                  },
-                  child: GradeValueWidget(GradeValue(index + 1, "", "", 0),
-                      fill: true, size: 36.0),
-                ),
-              ),
-            );
-          }),
-        ),
-      ),
-    ]);
-  }
-}
-
-class LiveActivityColorSetting extends StatefulWidget {
-  const LiveActivityColorSetting({Key? key}) : super(key: key);
-
-  @override
-  _LiveActivityColorSettingState createState() =>
-      _LiveActivityColorSettingState();
-}
-
-class _LiveActivityColorSettingState extends State<LiveActivityColorSetting> { 
-  late SettingsProvider settings;
-  Color currentColor = const Color(0x00000000);
-
-  @override
-  void initState() {
-    super.initState();
-    settings = Provider.of<SettingsProvider>(context, listen: false);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(children: [
-      Padding(
-        padding: const EdgeInsets.all(8.0),
-        child: Material(
-          type: MaterialType.transparency,
-          child: Column(children: [
-            MaterialColorPicker(
-              allowShades: false,
-              selectedColor: settings.liveActivityColor,
-              onMainColorChange: (k) {
-                setState(() {
-                  currentColor = k as Color;
-                  settings.update(
-                          liveActivityColor: currentColor.withAlpha(255));
-                      Navigator.of(context).maybePop();
-                });
-              },
-              elevation: 0,
-              physics: const NeverScrollableScrollPhysics(),
-            ),
-            Padding(
-              padding: const EdgeInsets.only(bottom: 8.0, top: 40.0),
-              child: Row(
-                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-                children: [
-                  MaterialActionButton(
-                    onPressed: () {
-                      var defaultColors =
-                          SettingsProvider.defaultSettings().liveActivityColor;
-                      settings.update(liveActivityColor: defaultColors);
-                      Navigator.of(context).maybePop();
-                    },
-                    child: Text(SettingsLocalization("reset").i18n),
-                  ),
-                ],
-              ),
-            ),
-          ]),
-        ),
-      ),
-    ]);
-  }
-}
+// ignore_for_file: prefer_function_declarations_over_variables
+
+import 'dart:io';
+
+import 'package:refilc/helpers/quick_actions.dart';
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/theme/observer.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc_mobile_ui/common/material_action_button.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc_mobile_ui/common/screens.i18n.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
+import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
+import 'package:refilc/models/icon_pack.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_premium/ui/mobile/settings/theme.dart';
+
+class SettingsHelper {
+  static const Map<String, String> langMap = {
+    "en": "🇬🇧  English",
+    "hu": "🇭🇺  Magyar",
+    "de": "🇩🇪  Deutsch"
+  };
+
+  static const Map<Pages, String> pageTitle = {
+    Pages.home: "home",
+    Pages.grades: "grades",
+    Pages.timetable: "timetable",
+    Pages.messages: "messages",
+    Pages.absences: "absences",
+  };
+
+  static Map<VibrationStrength, String> vibrationTitle = {
+    VibrationStrength.off: "voff",
+    VibrationStrength.light: "vlight",
+    VibrationStrength.medium: "vmedium",
+    VibrationStrength.strong: "vstrong",
+  };
+
+  static Map<Pages, String> localizedPageTitles() => pageTitle
+      .map((key, value) => MapEntry(key, ScreensLocalization(value).i18n));
+  static Map<VibrationStrength, String> localizedVibrationTitles() =>
+      vibrationTitle
+          .map((key, value) => MapEntry(key, SettingsLocalization(value).i18n));
+
+  static void language(BuildContext context) {
+    showBottomSheetMenu(
+      context,
+      items: List.generate(langMap.length, (index) {
+        String lang = langMap.keys.toList()[index];
+        return BottomSheetMenuItem(
+          onPressed: () {
+            Provider.of<SettingsProvider>(context, listen: false)
+                .update(language: lang);
+            I18n.of(context).locale = Locale(lang, lang.toUpperCase());
+            Navigator.of(context).maybePop();
+            if (Platform.isAndroid || Platform.isIOS) {
+              setupQuickActions();
+            }
+          },
+          title: Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              Text(langMap.values.toList()[index]),
+              if (lang == I18n.of(context).locale.languageCode)
+                Icon(
+                  Icons.check_circle,
+                  color: Theme.of(context).colorScheme.secondary,
+                ),
+            ],
+          ),
+        );
+      }),
+    );
+  }
+
+  static void uwuMode(BuildContext context, value) {
+    final settings = Provider.of<SettingsProvider>(context, listen: false);
+    if (value) {
+      I18n.of(context).locale = const Locale('uw', 'UW');
+    } else {
+      I18n.of(context).locale =
+          Locale(settings.language, settings.language.toUpperCase());
+    }
+    if (Platform.isAndroid || Platform.isIOS) {
+      setupQuickActions();
+    }
+  }
+
+  static void iconPack(BuildContext context) {
+    final settings = Provider.of<SettingsProvider>(context, listen: false);
+    showBottomSheetMenu(
+      context,
+      items: List.generate(IconPack.values.length, (index) {
+        IconPack current = IconPack.values[index];
+        return BottomSheetMenuItem(
+          onPressed: () {
+            settings.update(iconPack: current);
+            Navigator.of(context).maybePop();
+          },
+          title: Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              Text(current.name.capital()),
+              if (current == settings.iconPack)
+                Icon(
+                  Icons.check_circle,
+                  color: Theme.of(context).colorScheme.secondary,
+                ),
+            ],
+          ),
+        );
+      }),
+    );
+  }
+
+  static void startPage(BuildContext context) {
+    Map<Pages, IconData> pageIcons = {
+      Pages.home: FilcIcons.home,
+      Pages.grades: FeatherIcons.bookmark,
+      Pages.timetable: FeatherIcons.calendar,
+      Pages.messages: FeatherIcons.messageSquare,
+      Pages.absences: FeatherIcons.clock,
+    };
+
+    showBottomSheetMenu(
+      context,
+      items: List.generate(Pages.values.length, (index) {
+        return BottomSheetMenuItem(
+          onPressed: () {
+            Provider.of<SettingsProvider>(context, listen: false)
+                .update(startPage: Pages.values[index]);
+            Navigator.of(context).maybePop();
+          },
+          title: Row(
+            children: [
+              Icon(pageIcons[Pages.values[index]],
+                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
+              const SizedBox(width: 16.0),
+              Text(localizedPageTitles()[Pages.values[index]] ?? ""),
+              const Spacer(),
+              if (Pages.values[index] ==
+                  Provider.of<SettingsProvider>(context, listen: false)
+                      .startPage)
+                Icon(
+                  Icons.check_circle,
+                  color: Theme.of(context).colorScheme.secondary,
+                ),
+            ],
+          ),
+        );
+      }),
+    );
+  }
+
+  static void rounding(BuildContext context) {
+    showRoundedModalBottomSheet(
+      context,
+      child: const RoundingSetting(),
+    );
+  }
+
+  static void theme(BuildContext context) {
+    var settings = Provider.of<SettingsProvider>(context, listen: false);
+    void Function(ThemeMode) setTheme = (mode) {
+      settings.update(theme: mode);
+      Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(mode);
+      Navigator.of(context).maybePop();
+    };
+
+    showBottomSheetMenu(context, items: [
+      BottomSheetMenuItem(
+        onPressed: () => setTheme(ThemeMode.system),
+        title: Row(
+          children: [
+            Padding(
+              padding: const EdgeInsets.only(right: 16.0),
+              child: Icon(FeatherIcons.smartphone,
+                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
+            ),
+            Text(SettingsLocalization("system").i18n),
+            const Spacer(),
+            if (settings.theme == ThemeMode.system)
+              Icon(
+                Icons.check_circle,
+                color: Theme.of(context).colorScheme.secondary,
+              ),
+          ],
+        ),
+      ),
+      BottomSheetMenuItem(
+        onPressed: () => setTheme(ThemeMode.light),
+        title: Row(
+          children: [
+            Padding(
+              padding: const EdgeInsets.only(right: 16.0),
+              child: Icon(FeatherIcons.sun,
+                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
+            ),
+            Text(SettingsLocalization("light").i18n),
+            const Spacer(),
+            if (settings.theme == ThemeMode.light)
+              Icon(
+                Icons.check_circle,
+                color: Theme.of(context).colorScheme.secondary,
+              ),
+          ],
+        ),
+      ),
+      BottomSheetMenuItem(
+        onPressed: () => setTheme(ThemeMode.dark),
+        title: Row(
+          children: [
+            Padding(
+              padding: const EdgeInsets.only(right: 16.0),
+              child: Icon(FeatherIcons.moon,
+                  size: 20.0, color: Theme.of(context).colorScheme.secondary),
+            ),
+            Text(SettingsLocalization("dark").i18n),
+            const Spacer(),
+            if (settings.theme == ThemeMode.dark)
+              Icon(
+                Icons.check_circle,
+                color: Theme.of(context).colorScheme.secondary,
+              ),
+          ],
+        ),
+      )
+    ]);
+  }
+
+  static void accentColor(BuildContext context) {
+    Navigator.of(context, rootNavigator: true).push(
+      PageRouteBuilder(
+        pageBuilder: (context, _, __) =>
+            const PremiumCustomAccentColorSetting(),
+        transitionDuration: Duration.zero,
+        reverseTransitionDuration: Duration.zero,
+      ),
+    );
+  }
+
+  static void gradeColors(BuildContext context) {
+    showRoundedModalBottomSheet(
+      context,
+      child: const GradeColorsSetting(),
+    );
+  }
+
+  static void liveActivityColor(BuildContext context) {
+    showRoundedModalBottomSheet(
+      context,
+      child: const LiveActivityColorSetting(),
+    );
+  }
+
+  static void vibrate(BuildContext context) {
+    showBottomSheetMenu(
+      context,
+      items: List.generate(VibrationStrength.values.length, (index) {
+        VibrationStrength value = VibrationStrength.values[index];
+
+        return BottomSheetMenuItem(
+          onPressed: () {
+            Provider.of<SettingsProvider>(context, listen: false)
+                .update(vibrate: value);
+            Navigator.of(context).maybePop();
+          },
+          title: Row(
+            children: [
+              Container(
+                width: 12.0,
+                height: 12.0,
+                decoration: BoxDecoration(
+                  color: Theme.of(context)
+                      .colorScheme
+                      .secondary
+                      .withOpacity((index + 1) / (vibrationTitle.length + 1)),
+                  shape: BoxShape.circle,
+                ),
+              ),
+              const SizedBox(width: 16.0),
+              Text(localizedVibrationTitles()[value] ?? "?"),
+              const Spacer(),
+              if (value ==
+                  Provider.of<SettingsProvider>(context, listen: false).vibrate)
+                Icon(
+                  Icons.check_circle,
+                  color: Theme.of(context).colorScheme.secondary,
+                ),
+            ],
+          ),
+        );
+      }),
+    );
+  }
+
+  static void bellDelay(BuildContext context) {
+    showRoundedModalBottomSheet(
+      context,
+      child: const BellDelaySetting(),
+    );
+  }
+}
+
+// Rounding modal
+class RoundingSetting extends StatefulWidget {
+  const RoundingSetting({Key? key}) : super(key: key);
+
+  @override
+  _RoundingSettingState createState() => _RoundingSettingState();
+}
+
+class _RoundingSettingState extends State<RoundingSetting> {
+  late double rounding;
+
+  @override
+  void initState() {
+    super.initState();
+    rounding =
+        Provider.of<SettingsProvider>(context, listen: false).rounding / 10;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    int roundingResult;
+
+    if (4.5 >= 4.5.floor() + rounding) {
+      roundingResult = 5;
+    } else {
+      roundingResult = 4;
+    }
+
+    return Column(children: [
+      Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: [
+          Expanded(
+            child: Slider(
+              value: rounding,
+              min: 0.1,
+              max: 0.9,
+              divisions: 8,
+              label: rounding.toStringAsFixed(1),
+              activeColor: Theme.of(context).colorScheme.secondary,
+              thumbColor: Theme.of(context).colorScheme.secondary,
+              onChanged: (v) => setState(() => rounding = v),
+            ),
+          ),
+          Container(
+            width: 50.0,
+            padding: const EdgeInsets.only(right: 16.0),
+            child: Center(
+              child: Text(rounding.toStringAsFixed(1),
+                  style: const TextStyle(
+                    fontWeight: FontWeight.w600,
+                    fontSize: 18.0,
+                  )),
+            ),
+          ),
+        ],
+      ),
+      Row(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          const Text("4.5",
+              style: TextStyle(fontSize: 26.0, fontWeight: FontWeight.w500)),
+          const Padding(
+            padding: EdgeInsets.symmetric(horizontal: 24.0),
+            child: Icon(FeatherIcons.arrowRight, color: Colors.grey),
+          ),
+          GradeValueWidget(GradeValue(roundingResult, "", "", 100),
+              fill: true, size: 32.0),
+        ],
+      ),
+      Padding(
+        padding: const EdgeInsets.only(bottom: 12.0, top: 6.0),
+        child: MaterialActionButton(
+          child: Text(SettingsLocalization("done").i18n),
+          onPressed: () {
+            Provider.of<SettingsProvider>(context, listen: false)
+                .update(rounding: (rounding * 10).toInt());
+            Navigator.of(context).maybePop();
+          },
+        ),
+      ),
+    ]);
+  }
+}
+
+// Bell Delay Modal
+
+class BellDelaySetting extends StatefulWidget {
+  const BellDelaySetting({Key? key}) : super(key: key);
+
+  @override
+  State<BellDelaySetting> createState() => _BellDelaySettingState();
+}
+
+class _BellDelaySettingState extends State<BellDelaySetting>
+    with SingleTickerProviderStateMixin {
+  late TabController _tabController;
+  late Duration currentDelay;
+
+  @override
+  void initState() {
+    super.initState();
+    _tabController = TabController(
+        length: 2,
+        vsync: this,
+        initialIndex:
+            Provider.of<SettingsProvider>(context, listen: false).bellDelay > 0
+                ? 1
+                : 0);
+    currentDelay = Duration(
+        seconds:
+            Provider.of<SettingsProvider>(context, listen: false).bellDelay);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        FilterBar(
+          scrollable: false,
+          items: [
+            Tab(text: SettingsLocalization("delay").i18n),
+            Tab(text: SettingsLocalization("hurry").i18n),
+          ],
+          controller: _tabController,
+          onTap: (i) async {
+            // swap current page with target page
+            setState(() {
+              currentDelay = i == 0 ? -currentDelay.abs() : currentDelay.abs();
+            });
+          },
+        ),
+        SizedBox(
+          height: 200,
+          child: CupertinoTheme(
+            data: CupertinoThemeData(
+              brightness: Theme.of(context).brightness,
+            ),
+            child: CupertinoTimerPicker(
+              key: UniqueKey(),
+              mode: CupertinoTimerPickerMode.ms,
+              initialTimerDuration: currentDelay.abs(),
+              onTimerDurationChanged: (Duration d) {
+                HapticFeedback.selectionClick();
+
+                currentDelay = _tabController.index == 0 ? -d : d;
+              },
+            ),
+          ),
+        ),
+        Text(SettingsLocalization("sync_help").i18n,
+            textAlign: TextAlign.center,
+            style: TextStyle(
+                fontSize: 12.0,
+                fontWeight: FontWeight.w500,
+                color: AppColors.of(context).text.withOpacity(.75))),
+        Padding(
+          padding: const EdgeInsets.only(bottom: 12.0, top: 6.0),
+          child: Column(
+            children: [
+              MaterialActionButton(
+                backgroundColor: AppColors.of(context).filc,
+                child: Text(SettingsLocalization("sync").i18n),
+                onPressed: () {
+                  final lessonProvider =
+                      Provider.of<TimetableProvider>(context, listen: false);
+
+                  Duration? closest;
+                  DateTime now = DateTime.now();
+                  for (var lesson
+                      in lessonProvider.getWeek(Week.current()) ?? []) {
+                    Duration sdiff = lesson.start.difference(now);
+                    Duration ediff = lesson.end.difference(now);
+
+                    if (closest == null || sdiff.abs() < closest.abs()) {
+                      closest = sdiff;
+                    }
+                    if (ediff.abs() < closest.abs()) closest = ediff;
+                  }
+                  if (closest != null) {
+                    if (closest.inHours.abs() >= 1) return;
+                    currentDelay = closest;
+                    Provider.of<SettingsProvider>(context, listen: false)
+                        .update(bellDelay: currentDelay.inSeconds);
+                    _tabController.index = currentDelay.inSeconds > 0 ? 1 : 0;
+                    setState(() {});
+                  }
+                },
+              ),
+              MaterialActionButton(
+                child: Text(SettingsLocalization("done").i18n),
+                onPressed: () {
+                  //Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt());
+                  Provider.of<SettingsProvider>(context, listen: false)
+                      .update(bellDelay: currentDelay.inSeconds);
+                  Navigator.of(context).maybePop();
+                },
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
+
+class GradeColorsSetting extends StatefulWidget {
+  const GradeColorsSetting({Key? key}) : super(key: key);
+
+  @override
+  _GradeColorsSettingState createState() => _GradeColorsSettingState();
+}
+
+class _GradeColorsSettingState extends State<GradeColorsSetting> {
+  Color currentColor = const Color(0x00000000);
+  late SettingsProvider settings;
+
+  @override
+  void initState() {
+    super.initState();
+    settings = Provider.of<SettingsProvider>(context, listen: false);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(children: [
+      Padding(
+        padding: const EdgeInsets.all(8.0),
+        child: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+          children: List.generate(5, (index) {
+            return ClipOval(
+              child: Material(
+                type: MaterialType.transparency,
+                child: InkWell(
+                  onTap: () {
+                    currentColor = settings.gradeColors[index];
+                    showRoundedModalBottomSheet(
+                      context,
+                      child: Column(children: [
+                        MaterialColorPicker(
+                          selectedColor: settings.gradeColors[index],
+                          onColorChange: (v) {
+                            setState(() {
+                              currentColor = v;
+                            });
+                          },
+                          allowShades: true,
+                          elevation: 0,
+                          physics: const NeverScrollableScrollPhysics(),
+                        ),
+                        Padding(
+                          padding: const EdgeInsets.only(bottom: 8.0),
+                          child: Row(
+                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+                            children: [
+                              MaterialActionButton(
+                                onPressed: () {
+                                  List<Color> colors =
+                                      List.castFrom(settings.gradeColors);
+                                  var defaultColors =
+                                      SettingsProvider.defaultSettings()
+                                          .gradeColors;
+                                  colors[index] = defaultColors[index];
+                                  settings.update(gradeColors: colors);
+                                  Navigator.of(context).maybePop();
+                                },
+                                child: Text(SettingsLocalization("reset").i18n),
+                              ),
+                              MaterialActionButton(
+                                onPressed: () {
+                                  List<Color> colors =
+                                      List.castFrom(settings.gradeColors);
+                                  colors[index] = currentColor.withAlpha(255);
+                                  settings.update(
+                                      gradeColors: settings.gradeColors);
+                                  Navigator.of(context).maybePop();
+                                },
+                                child: Text(SettingsLocalization("done").i18n),
+                              ),
+                            ],
+                          ),
+                        ),
+                      ]),
+                    ).then((value) => setState(() {}));
+                  },
+                  child: GradeValueWidget(GradeValue(index + 1, "", "", 0),
+                      fill: true, size: 36.0),
+                ),
+              ),
+            );
+          }),
+        ),
+      ),
+    ]);
+  }
+}
+
+class LiveActivityColorSetting extends StatefulWidget {
+  const LiveActivityColorSetting({Key? key}) : super(key: key);
+
+  @override
+  _LiveActivityColorSettingState createState() =>
+      _LiveActivityColorSettingState();
+}
+
+class _LiveActivityColorSettingState extends State<LiveActivityColorSetting> {
+  late SettingsProvider settings;
+  Color currentColor = const Color(0x00000000);
+
+  @override
+  void initState() {
+    super.initState();
+    settings = Provider.of<SettingsProvider>(context, listen: false);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(children: [
+      Padding(
+        padding: const EdgeInsets.all(8.0),
+        child: Material(
+          type: MaterialType.transparency,
+          child: Column(children: [
+            MaterialColorPicker(
+              allowShades: false,
+              selectedColor: settings.liveActivityColor,
+              onMainColorChange: (k) {
+                setState(() {
+                  currentColor = k as Color;
+                  settings.update(
+                      liveActivityColor: currentColor.withAlpha(255));
+                  Navigator.of(context).maybePop();
+                });
+              },
+              elevation: 0,
+              physics: const NeverScrollableScrollPhysics(),
+            ),
+            Padding(
+              padding: const EdgeInsets.only(bottom: 8.0, top: 40.0),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+                children: [
+                  MaterialActionButton(
+                    onPressed: () {
+                      var defaultColors =
+                          SettingsProvider.defaultSettings().liveActivityColor;
+                      settings.update(liveActivityColor: defaultColors);
+                      Navigator.of(context).maybePop();
+                    },
+                    child: Text(SettingsLocalization("reset").i18n),
+                  ),
+                ],
+              ),
+            ),
+          ]),
+        ),
+      ),
+    ]);
+  }
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_route.dart b/refilc_mobile_ui/lib/screens/settings/settings_route.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/screens/settings/settings_route.dart
rename to refilc_mobile_ui/lib/screens/settings/settings_route.dart
index ff3f7fe..70195e8
--- a/filcnaplo_mobile_ui/lib/screens/settings/settings_route.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_route.dart
@@ -1,21 +1,21 @@
-import 'package:flutter/material.dart';
-
-Route settingsRoute(Widget widget) {
-  return PageRouteBuilder(
-    pageBuilder: (context, animation, secondaryAnimation) => widget,
-    transitionDuration: const Duration(milliseconds: 500),
-    transitionsBuilder: (context, animation, secondaryAnimation, child) {
-      var curve = Curves.ease;
-      var curveTween = CurveTween(curve: curve);
-      var begin = const Offset(0.0, 1.0);
-      var end = Offset.zero;
-      var tween = Tween(begin: begin, end: end).chain(curveTween);
-      var offsetAnimation = animation.drive(tween);
-
-      return SlideTransition(
-        position: offsetAnimation,
-        child: child,
-      );
-    },
-  );
-}
+import 'package:flutter/material.dart';
+
+Route settingsRoute(Widget widget) {
+  return PageRouteBuilder(
+    pageBuilder: (context, animation, secondaryAnimation) => widget,
+    transitionDuration: const Duration(milliseconds: 500),
+    transitionsBuilder: (context, animation, secondaryAnimation, child) {
+      var curve = Curves.ease;
+      var curveTween = CurveTween(curve: curve);
+      var begin = const Offset(0.0, 1.0);
+      var end = Offset.zero;
+      var tween = Tween(begin: begin, end: end).chain(curveTween);
+      var offsetAnimation = animation.drive(tween);
+
+      return SlideTransition(
+        position: offsetAnimation,
+        child: child,
+      );
+    },
+  );
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
old mode 100755
new mode 100644
similarity index 92%
rename from filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart
rename to refilc_mobile_ui/lib/screens/settings/settings_screen.dart
index 6a6339c..5a1de1d
--- a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_screen.dart
@@ -1,1021 +1,1021 @@
-import 'package:filcnaplo/api/providers/update_provider.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';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/client/client.dart';
-import 'package:filcnaplo_mobile_ui/common/action_button.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
-import 'package:filcnaplo_mobile_ui/common/system_chrome.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/update/updates_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/news/news_screen.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_tile.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/debug/subject_icon_gallery.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/notifications_screen.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/privacy_view.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_helper.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as tabs;
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:url_launcher/url_launcher.dart';
-import 'settings_screen.i18n.dart';
-import 'package:flutter/services.dart';
-import 'package:filcnaplo_premium/ui/mobile/settings/nickname.dart';
-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';
-
-class SettingsScreen extends StatefulWidget {
-  const SettingsScreen({Key? key}) : super(key: key);
-
-  @override
-  _SettingsScreenState createState() => _SettingsScreenState();
-}
-
-class _SettingsScreenState extends State<SettingsScreen>
-    with SingleTickerProviderStateMixin {
-  int devmodeCountdown = 5;
-  bool __ss = false; // secret settings
-
-  Future<Map>? futureRelease;
-
-  late UserProvider user;
-  late UpdateProvider updateProvider;
-  late SettingsProvider settings;
-  late KretaClient kretaClient;
-  late String firstName;
-  List<Widget> accountTiles = [];
-
-  late AnimationController _hideContainersController;
-
-  Future<void> restore() => Future.wait([
-        Provider.of<GradeProvider>(context, listen: false).restore(),
-        Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
-        Provider.of<ExamProvider>(context, listen: false).restore(),
-        Provider.of<HomeworkProvider>(context, listen: false).restore(),
-        Provider.of<MessageProvider>(context, listen: false).restore(),
-        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(),
-      ]);
-
-  void buildAccountTiles() {
-    accountTiles = [];
-    user.getUsers().forEach((account) {
-      if (account.id == user.id) return;
-
-      String _firstName;
-
-      List<String> _nameParts = account.displayName.split(" ");
-      if (!settings.presentationMode) {
-        _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
-      } else {
-        _firstName = "János";
-      }
-
-      accountTiles.add(
-        AccountTile(
-          name: Text(!settings.presentationMode ? account.name : "János",
-              style: const TextStyle(fontWeight: FontWeight.w500)),
-          username: Text(
-              !settings.presentationMode ? account.username : "01234567890"),
-          profileImage: ProfileImage(
-            name: _firstName,
-            role: account.role,
-            profilePictureString: account.picture,
-            backgroundColor: Theme.of(context)
-                .colorScheme
-                .primary, //!settings.presentationMode
-            //? ColorUtils.stringToColor(account.name)
-            //: Theme.of(context).colorScheme.secondary,
-          ),
-          onTap: () {
-            user.setUser(account.id);
-            restore().then((_) => user.setUser(account.id));
-            Navigator.of(context).pop();
-          },
-          onTapMenu: () => _showBottomSheet(account),
-        ),
-      );
-    });
-  }
-
-  void _showBottomSheet(User u) {
-    showBottomSheetMenu(context, items: [
-      BottomSheetMenuItem(
-        onPressed: () => AccountView.show(u, context: context),
-        icon: const Icon(FeatherIcons.user),
-        title: Text("personal_details".i18n),
-      ),
-      BottomSheetMenuItem(
-        onPressed: () => _openDKT(u),
-        icon: Icon(FeatherIcons.grid, color: AppColors.of(context).teal),
-        title: Text("open_dkt".i18n),
-      ),
-      UserMenuNickname(u),
-      UserMenuProfilePic(u),
-      // BottomSheetMenuItem(
-      //   onPressed: () {},
-      //   icon: Icon(FeatherIcons.camera),
-      //   title: Text("edit_profile_picture".i18n),
-      // ),
-      // BottomSheetMenuItem(
-      //   onPressed: () {},
-      //   icon: Icon(FeatherIcons.trash2, color: AppColors.of(context).red),
-      //   title: Text("remove_profile_picture".i18n),
-      // ),
-    ]);
-  }
-
-  void _openDKT(User u) => tabs.launch(
-      "https://dkttanulo.e-kreta.hu/sso?id_token=${kretaClient.idToken}",
-      customTabsOption: tabs.CustomTabsOption(
-        toolbarColor: Theme.of(context).scaffoldBackgroundColor,
-        showPageTitle: true,
-      ));
-
-  @override
-  void initState() {
-    super.initState();
-    Future.delayed(Duration.zero, () {
-      futureRelease = Provider.of<UpdateProvider>(context, listen: false)
-          .installedVersion();
-    });
-    _hideContainersController = AnimationController(
-        vsync: this, duration: const Duration(milliseconds: 200));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    user = Provider.of<UserProvider>(context);
-    settings = Provider.of<SettingsProvider>(context);
-    updateProvider = Provider.of<UpdateProvider>(context);
-    kretaClient = Provider.of<KretaClient>(context);
-
-    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
-    if (!settings.presentationMode) {
-      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
-    } else {
-      firstName = "János";
-    }
-
-    String startPageTitle =
-        SettingsHelper.localizedPageTitles()[settings.startPage] ?? "?";
-    String themeModeText = {
-          ThemeMode.light: "light".i18n,
-          ThemeMode.dark: "dark".i18n,
-          ThemeMode.system: "system".i18n
-        }[settings.theme] ??
-        "?";
-    String languageText = SettingsHelper.langMap[settings.language] ?? "?";
-    String vibrateTitle = {
-          VibrationStrength.off: "voff".i18n,
-          VibrationStrength.light: "vlight".i18n,
-          VibrationStrength.medium: "vmedium".i18n,
-          VibrationStrength.strong: "vstrong".i18n,
-        }[settings.vibrate] ??
-        "?";
-
-    buildAccountTiles();
-
-    if (settings.developerMode) devmodeCountdown = -1;
-
-    return AnimatedBuilder(
-      animation: _hideContainersController,
-      builder: (context, child) => Opacity(
-        opacity: 1 - _hideContainersController.value,
-        child: Column(
-          children: [
-            const SizedBox(height: 32.0),
-
-            Row(
-              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-              children: [
-                IconButton(
-                  splashRadius: 32.0,
-                  onPressed: () =>
-                      _showBottomSheet(user.getUser(user.id ?? "")),
-                  icon: Icon(FeatherIcons.moreVertical,
-                      color: AppColors.of(context).text.withOpacity(0.8)),
-                ),
-                IconButton(
-                  splashRadius: 26.0,
-                  onPressed: () {
-                    Navigator.of(context).pop();
-                  },
-                  icon: Icon(FeatherIcons.x,
-                      color: AppColors.of(context).text.withOpacity(0.8)),
-                ),
-              ],
-            ),
-
-            Padding(
-              padding: const EdgeInsets.symmetric(vertical: 8.0),
-              child: ProfileImage(
-                heroTag: "profile",
-                radius: 36.0,
-                onTap: () => _showBottomSheet(user.getUser(user.id ?? "")),
-                name: firstName,
-                badge: updateProvider.available,
-                role: user.role,
-                profilePictureString: user.picture,
-                backgroundColor: Theme.of(context)
-                    .colorScheme
-                    .primary, //!settings.presentationMode
-                //? ColorUtils.stringToColor(user.displayName ?? "?")
-                //: Theme.of(context).colorScheme.secondary,
-              ),
-            ),
-
-            Padding(
-              padding: const EdgeInsets.only(top: 4.0, bottom: 12.0),
-              child: GestureDetector(
-                onTap: () => _showBottomSheet(user.getUser(user.id ?? "")),
-                onDoubleTap: () => setState(() => __ss = true),
-                child: Text(
-                  !settings.presentationMode
-                      ? (user.displayName ?? "?")
-                      : "János",
-                  maxLines: 1,
-                  softWrap: false,
-                  overflow: TextOverflow.ellipsis,
-                  textAlign: TextAlign.center,
-                  style: TextStyle(
-                      fontSize: 20.0,
-                      fontWeight: FontWeight.w600,
-                      color: AppColors.of(context).text),
-                ),
-              ),
-            ),
-
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-              child: Panel(
-                child: Column(
-                  children: [
-                    // Account list
-                    ...accountTiles,
-
-                    if (accountTiles.isNotEmpty)
-                      Center(
-                        child: Container(
-                          margin: const EdgeInsets.only(top: 12.0, bottom: 4.0),
-                          height: 3.0,
-                          width: 75.0,
-                          decoration: BoxDecoration(
-                            borderRadius: BorderRadius.circular(12.0),
-                            color: AppColors.of(context).text.withOpacity(.25),
-                          ),
-                        ),
-                      ),
-
-                    // Account settings
-                    PanelButton(
-                      onPressed: () {
-                        Navigator.of(context)
-                            .pushNamed("login_back")
-                            .then((value) {
-                          setSystemChrome(context);
-                        });
-                      },
-                      title: Text("add_user".i18n),
-                      leading: const Icon(FeatherIcons.userPlus),
-                    ),
-                    PanelButton(
-                      onPressed: () 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 other Users left, go back to LoginScreen
-                        if (user.getUsers().isNotEmpty) {
-                          user.setUser(user.getUsers().first.id);
-                          restore().then(
-                              (_) => user.setUser(user.getUsers().first.id));
-                        } else {
-                          Navigator.of(context)
-                              .pushNamedAndRemoveUntil("login", (_) => false);
-                        }
-                      },
-                      title: Text("log_out".i18n),
-                      leading: Icon(FeatherIcons.logOut,
-                          color: AppColors.of(context).red),
-                    ),
-                  ],
-                ),
-              ),
-            ),
-
-            // Updates
-            if (updateProvider.available)
-              Padding(
-                padding: const EdgeInsets.symmetric(
-                    vertical: 12.0, horizontal: 24.0),
-                child: Panel(
-                  child: PanelButton(
-                    onPressed: () => _openUpdates(context),
-                    title: Text("update_available".i18n),
-                    leading: const Icon(FeatherIcons.download),
-                    trailing: Text(
-                      updateProvider.releases.first.tag,
-                      style: TextStyle(
-                        fontWeight: FontWeight.w500,
-                        color: Theme.of(context).colorScheme.secondary,
-                      ),
-                    ),
-                  ),
-                ),
-              ),
-
-            // const Padding(
-            //   padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-            //   child: PremiumBannerButton(),
-            // ),
-            // if (!context.watch<PremiumProvider>().hasPremium)
-            //   const ClipRect(
-            //     child: Padding(
-            //       padding: EdgeInsets.symmetric(vertical: 12.0),
-            //       child: PremiumButton(),
-            //     ),
-            //   )
-            // else
-            //   const Padding(
-            //     padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-            //     child: ActiveSponsorCard(),
-            //   ),
-
-            // General Settings
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-              child: Panel(
-                title: Text("general".i18n),
-                child: Column(
-                  children: [
-                    PanelButton(
-                      onPressed: () {
-                        SettingsHelper.language(context);
-                        setState(() {});
-                      },
-                      title: Text("language".i18n),
-                      leading: const Icon(FeatherIcons.globe),
-                      trailing: Text(
-                        languageText,
-                        style: const TextStyle(fontSize: 14.0),
-                      ),
-                    ),
-                    PanelButton(
-                      onPressed: () {
-                        SettingsHelper.startPage(context);
-                        setState(() {});
-                      },
-                      title: Text("startpage".i18n),
-                      leading: const Icon(FeatherIcons.play),
-                      trailing: Text(
-                        startPageTitle.capital(),
-                        style: const TextStyle(fontSize: 14.0),
-                      ),
-                    ),
-                    PanelButton(
-                      onPressed: () {
-                        SettingsHelper.rounding(context);
-                        setState(() {});
-                      },
-                      title: Text("rounding".i18n),
-                      leading: const Icon(FeatherIcons.gitCommit),
-                      trailing: Text(
-                        (settings.rounding / 10).toStringAsFixed(1),
-                        style: const TextStyle(fontSize: 14.0),
-                      ),
-                    ),
-                    PanelButton(
-                      onPressed: () {
-                        SettingsHelper.vibrate(context);
-                        setState(() {});
-                      },
-                      title: Text("vibrate".i18n),
-                      leading: const Icon(FeatherIcons.radio),
-                      trailing: Text(
-                        vibrateTitle,
-                        style: const TextStyle(fontSize: 14.0),
-                      ),
-                    ),
-                    PanelButton(
-                      padding: const EdgeInsets.only(left: 14.0),
-                      onPressed: () {
-                        SettingsHelper.bellDelay(context);
-                        setState(() {});
-                      },
-                      title: Text(
-                        "bell_delay".i18n,
-                        style: TextStyle(
-                            color: AppColors.of(context).text.withOpacity(
-                                settings.bellDelayEnabled ? 1.0 : .5)),
-                      ),
-                      leading: settings.bellDelayEnabled
-                          ? const Icon(FeatherIcons.bell)
-                          : Icon(FeatherIcons.bellOff,
-                              color:
-                                  AppColors.of(context).text.withOpacity(.25)),
-                      trailingDivider: true,
-                      trailing: Switch(
-                        onChanged: (v) => settings.update(bellDelayEnabled: v),
-                        value: settings.bellDelayEnabled,
-                        activeColor: Theme.of(context).colorScheme.secondary,
-                      ),
-                    ),
-                    Material(
-                        type: MaterialType.transparency,
-                        child: MenuNotifications(settings: settings)),
-                  ],
-                ),
-              ),
-            ),
-
-            if (kDebugMode)
-              Padding(
-                padding: const EdgeInsets.symmetric(
-                    vertical: 12.0, horizontal: 24.0),
-                child: Panel(
-                  title: const Text("Debug"),
-                  child: Column(
-                    children: [
-                      PanelButton(
-                        title: const Text("Subject Icon Gallery"),
-                        leading:
-                            const Icon(CupertinoIcons.rectangle_3_offgrid_fill),
-                        trailing: const Icon(Icons.arrow_forward),
-                        onPressed: () {
-                          Navigator.of(context, rootNavigator: true).push(
-                            CupertinoPageRoute(
-                                builder: (context) =>
-                                    const SubjectIconGallery()),
-                          );
-                        },
-                      )
-                    ],
-                  ),
-                ),
-              ),
-
-            // Secret Settings
-            if (__ss)
-              Padding(
-                padding: const EdgeInsets.symmetric(
-                    vertical: 12.0, horizontal: 24.0),
-                child: Panel(
-                  title: Text("secret".i18n),
-                  child: Column(
-                    children: [
-                      // Good student mode
-                      Material(
-                        type: MaterialType.transparency,
-                        child: SwitchListTile(
-                          contentPadding: const EdgeInsets.only(left: 12.0),
-                          shape: RoundedRectangleBorder(
-                              borderRadius: BorderRadius.circular(12.0)),
-                          title: Text("goodstudent".i18n,
-                              style:
-                                  const TextStyle(fontWeight: FontWeight.w500)),
-                          onChanged: (v) {
-                            if (v) {
-                              showDialog(
-                                context: context,
-                                builder: (context) => WillPopScope(
-                                  onWillPop: () async => false,
-                                  child: AlertDialog(
-                                    shape: RoundedRectangleBorder(
-                                        borderRadius:
-                                            BorderRadius.circular(12.0)),
-                                    title: Text("attention".i18n),
-                                    content:
-                                        Text("goodstudent_disclaimer".i18n),
-                                    actions: [
-                                      ActionButton(
-                                          label: "understand".i18n,
-                                          onTap: () {
-                                            Navigator.of(context).pop();
-                                            settings.update(goodStudent: v);
-                                            Provider.of<GradeProvider>(context,
-                                                    listen: false)
-                                                .convertBySettings();
-                                          })
-                                    ],
-                                  ),
-                                ),
-                              );
-                            } else {
-                              settings.update(goodStudent: v);
-                              Provider.of<GradeProvider>(context, listen: false)
-                                  .convertBySettings();
-                            }
-                          },
-                          value: settings.goodStudent,
-                          activeColor: Theme.of(context).colorScheme.secondary,
-                        ),
-                      ),
-
-                      // Presentation mode
-                      Material(
-                        type: MaterialType.transparency,
-                        child: SwitchListTile(
-                          contentPadding: const EdgeInsets.only(left: 12.0),
-                          shape: RoundedRectangleBorder(
-                              borderRadius: BorderRadius.circular(12.0)),
-                          title: Text("presentation".i18n,
-                              style:
-                                  const TextStyle(fontWeight: FontWeight.w500)),
-                          onChanged: (v) =>
-                              settings.update(presentationMode: v),
-                          value: settings.presentationMode,
-                          activeColor: Theme.of(context).colorScheme.secondary,
-                        ),
-                      ),
-
-                      // UwU-fied mode (why????)
-                      // Material(
-                      //   type: MaterialType.transparency,
-                      //   child: SwitchListTile(
-                      //     contentPadding: const EdgeInsets.only(left: 12.0),
-                      //     shape: RoundedRectangleBorder(
-                      //         borderRadius: BorderRadius.circular(12.0)),
-                      //     title: Text("uwufymode".i18n,
-                      //         style:
-                      //             const TextStyle(fontWeight: FontWeight.w500)),
-                      //     onChanged: (v) {
-                      //       SettingsHelper.uwuMode(context, v);
-                      //       setState(() {});
-                      //     },
-                      //     value: settings.presentationMode,
-                      //     activeColor: Theme.of(context).colorScheme.secondary,
-                      //   ),
-                      // ),
-                    ],
-                  ),
-                ),
-              ),
-
-            // Theme Settings
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-              child: Panel(
-                title: Text("appearance".i18n),
-                child: Column(
-                  children: [
-                    PanelButton(
-                      onPressed: () {
-                        SettingsHelper.theme(context);
-                        setState(() {});
-                      },
-                      title: Text("theme".i18n),
-                      leading: const Icon(FeatherIcons.sun),
-                      trailing: Text(
-                        themeModeText,
-                        style: const TextStyle(fontSize: 14.0),
-                      ),
-                    ),
-                    PanelButton(
-                      onPressed: () async {
-                        await _hideContainersController.forward();
-                        SettingsHelper.accentColor(context);
-                        setState(() {});
-                        _hideContainersController.reset();
-                      },
-                      title: Text("color".i18n),
-                      leading: const Icon(FeatherIcons.droplet),
-                      trailing: Container(
-                        width: 12.0,
-                        height: 12.0,
-                        decoration: BoxDecoration(
-                          color: Theme.of(context).colorScheme.secondary,
-                          shape: BoxShape.circle,
-                        ),
-                      ),
-                    ),
-                    PanelButton(
-                      onPressed: () {
-                        SettingsHelper.gradeColors(context);
-                        setState(() {});
-                      },
-                      title: Text("grade_colors".i18n),
-                      leading: const Icon(FeatherIcons.star),
-                      trailing: Row(
-                        mainAxisSize: MainAxisSize.min,
-                        children: List.generate(
-                          5,
-                          (i) => Container(
-                            margin: const EdgeInsets.only(left: 2.0),
-                            width: 12.0,
-                            height: 12.0,
-                            decoration: BoxDecoration(
-                              shape: BoxShape.circle,
-                              color: settings.gradeColors[i],
-                            ),
-                          ),
-                        ),
-                      ),
-                    ),
-                    Material(
-                      type: MaterialType.transparency,
-                      child: SwitchListTile(
-                        contentPadding: const EdgeInsets.only(left: 12.0),
-                        shape: RoundedRectangleBorder(
-                            borderRadius: BorderRadius.circular(12.0)),
-                        title: Row(
-                          children: [
-                            Icon(
-                              FeatherIcons.barChart,
-                              color: settings.graphClassAvg
-                                  ? Theme.of(context).colorScheme.secondary
-                                  : AppColors.of(context).text.withOpacity(.25),
-                            ),
-                            const SizedBox(width: 14.0),
-                            Expanded(
-                              child: Text(
-                                "graph_class_avg".i18n,
-                                style: TextStyle(
-                                  fontWeight: FontWeight.w600,
-                                  fontSize: 16.0,
-                                  color: AppColors.of(context).text.withOpacity(
-                                      settings.graphClassAvg ? 1.0 : .5),
-                                ),
-                              ),
-                            ),
-                          ],
-                        ),
-                        onChanged: (v) => settings.update(graphClassAvg: v),
-                        value: settings.graphClassAvg,
-                        activeColor: Theme.of(context).colorScheme.secondary,
-                      ),
-                    ),
-                    const PremiumIconPackSelector(),
-                    // If iOS, show the iOS specific settings
-
-                    if (defaultTargetPlatform == TargetPlatform.iOS)
-                      PanelButton(
-                        onPressed: () {
-                          SettingsHelper.liveActivityColor(context);
-                          setState(() {});
-                        },
-                        title: Text("live_activity_color".i18n),
-                        leading: const Icon(FeatherIcons.activity),
-                        trailing: Container(
-                          width: 12.0,
-                          height: 12.0,
-                          decoration: BoxDecoration(
-                            color: settings.liveActivityColor,
-                            shape: BoxShape.circle,
-                          ),
-                        ),
-                      ),
-                  ],
-                ),
-              ),
-            ),
-
-            // Notifications
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-              child: Panel(
-                title: Text("popups".i18n),
-                child: Material(
-                  type: MaterialType.transparency,
-                  child: SwitchListTile(
-                    contentPadding: const EdgeInsets.only(left: 12.0),
-                    shape: RoundedRectangleBorder(
-                        borderRadius: BorderRadius.circular(12.0)),
-                    title: Row(
-                      children: [
-                        Icon(
-                          Icons.newspaper_outlined,
-                          color: settings.newsEnabled
-                              ? Theme.of(context).colorScheme.secondary
-                              : AppColors.of(context).text.withOpacity(.25),
-                        ),
-                        const SizedBox(width: 14.0),
-                        Expanded(
-                          child: Text(
-                            "news".i18n,
-                            style: TextStyle(
-                              fontWeight: FontWeight.w600,
-                              fontSize: 16.0,
-                              color: AppColors.of(context)
-                                  .text
-                                  .withOpacity(settings.newsEnabled ? 1.0 : .5),
-                            ),
-                          ),
-                        ),
-                      ],
-                    ),
-                    onChanged: (v) => settings.update(newsEnabled: v),
-                    value: settings.newsEnabled,
-                    activeColor: Theme.of(context).colorScheme.secondary,
-                  ),
-                ),
-              ),
-            ),
-
-            // Extras
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-              child: Panel(
-                title: Text("extras".i18n),
-                child: Column(
-                  children: [
-                    Material(
-                      type: MaterialType.transparency,
-                      child: SwitchListTile(
-                        contentPadding: const EdgeInsets.only(left: 12.0),
-                        shape: RoundedRectangleBorder(
-                            borderRadius: BorderRadius.circular(12.0)),
-                        title: Row(
-                          children: [
-                            Icon(
-                              FeatherIcons.gift,
-                              color: settings.gradeOpeningFun
-                                  ? Theme.of(context).colorScheme.secondary
-                                  : AppColors.of(context).text.withOpacity(.25),
-                            ),
-                            const SizedBox(width: 14.0),
-                            Expanded(
-                              child: Text(
-                                "surprise_grades".i18n,
-                                style: TextStyle(
-                                  fontWeight: FontWeight.w600,
-                                  fontSize: 16.0,
-                                  color: AppColors.of(context).text.withOpacity(
-                                      settings.gradeOpeningFun ? 1.0 : .5),
-                                ),
-                              ),
-                            ),
-                          ],
-                        ),
-                        onChanged: (v) => settings.update(gradeOpeningFun: v),
-                        value: settings.gradeOpeningFun,
-                        activeColor: Theme.of(context).colorScheme.secondary,
-                      ),
-                    ),
-                    MenuRenamedSubjects(
-                      settings: settings,
-                    ),
-                    MenuRenamedTeachers(
-                      settings: settings,
-                    ),
-                  ],
-                ),
-              ),
-            ),
-
-            // About
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-              child: Panel(
-                title: Text("about".i18n),
-                child: Column(children: [
-                  PanelButton(
-                    leading: const Icon(FeatherIcons.mail),
-                    title: Text("news".i18n),
-                    onPressed: () => _openNews(context),
-                  ),
-                  PanelButton(
-                    leading: const Icon(FeatherIcons.lock),
-                    title: Text("privacy".i18n),
-                    // onPressed: () => launchUrl(
-                    //     Uri.parse("https://refilc.hu/privacy-policy"),
-                    //     mode: LaunchMode.inAppWebView),
-                    onPressed: () => _openPrivacy(context),
-                  ),
-                  PanelButton(
-                    leading: const Icon(FeatherIcons.atSign),
-                    title: const Text("Discord"),
-                    onPressed: () => launchUrl(
-                        Uri.parse("https://dc.refilc.hu"),
-                        mode: LaunchMode.externalApplication),
-                  ),
-                  PanelButton(
-                    leading: const Icon(FeatherIcons.globe),
-                    title: const Text("www.refilc.hu"),
-                    onPressed: () => launchUrl(
-                        Uri.parse("https://www.refilc.hu"),
-                        mode: LaunchMode.externalApplication),
-                  ),
-                  PanelButton(
-                    leading: const Icon(FeatherIcons.github),
-                    title: const Text("Github"),
-                    onPressed: () => launchUrl(
-                        Uri.parse("https://github.com/refilc"),
-                        mode: LaunchMode.externalApplication),
-                  ),
-                  PanelButton(
-                    leading: const Icon(FeatherIcons.award),
-                    title: Text("licenses".i18n),
-                    onPressed: () => showLicensePage(context: context),
-                  ),
-                  Tooltip(
-                    message: "data_collected".i18n,
-                    padding: const EdgeInsets.all(4.0),
-                    textStyle: TextStyle(
-                        fontWeight: FontWeight.w500,
-                        color: AppColors.of(context).text),
-                    decoration: BoxDecoration(
-                        color: Theme.of(context).colorScheme.background),
-                    child: Material(
-                      type: MaterialType.transparency,
-                      child: SwitchListTile(
-                        contentPadding: const EdgeInsets.only(left: 12.0),
-                        shape: RoundedRectangleBorder(
-                            borderRadius: BorderRadius.circular(12.0)),
-                        secondary: Icon(
-                          FeatherIcons.barChart2,
-                          color: settings.xFilcId != "none"
-                              ? Theme.of(context).colorScheme.secondary
-                              : AppColors.of(context).text.withOpacity(.25),
-                        ),
-                        title: Text(
-                          "Analytics".i18n,
-                          style: TextStyle(
-                            fontWeight: FontWeight.w600,
-                            fontSize: 16.0,
-                            color: AppColors.of(context).text.withOpacity(
-                                settings.xFilcId != "none" ? 1.0 : .5),
-                          ),
-                        ),
-                        subtitle: Text(
-                          "Anonymous Usage Analytics".i18n,
-                          style: TextStyle(
-                            color: AppColors.of(context).text.withOpacity(
-                                settings.xFilcId != "none" ? .5 : .2),
-                          ),
-                        ),
-                        onChanged: (v) {
-                          String newId;
-                          if (v == false) {
-                            newId = "none";
-                          } else if (settings.xFilcId == "none") {
-                            newId = SettingsProvider.defaultSettings().xFilcId;
-                          } else {
-                            newId = settings.xFilcId;
-                          }
-                          settings.update(xFilcId: newId);
-                        },
-                        value: settings.xFilcId != "none",
-                        activeColor: Theme.of(context).colorScheme.secondary,
-                      ),
-                    ),
-                  ),
-                ]),
-              ),
-            ),
-            if (settings.developerMode)
-              Padding(
-                padding: const EdgeInsets.symmetric(
-                    vertical: 12.0, horizontal: 24.0),
-                child: Panel(
-                  title: Text("devsettings".i18n),
-                  child: Column(
-                    children: [
-                      Material(
-                        type: MaterialType.transparency,
-                        child: SwitchListTile(
-                          contentPadding: const EdgeInsets.only(left: 12.0),
-                          shape: RoundedRectangleBorder(
-                              borderRadius: BorderRadius.circular(12.0)),
-                          title: Text("devmode".i18n,
-                              style:
-                                  const TextStyle(fontWeight: FontWeight.w500)),
-                          onChanged: (v) =>
-                              settings.update(developerMode: false),
-                          value: settings.developerMode,
-                          activeColor: Theme.of(context).colorScheme.secondary,
-                        ),
-                      ),
-                      PanelButton(
-                        leading: const Icon(FeatherIcons.copy),
-                        title: Text("copy_jwt".i18n),
-                        onPressed: () => Clipboard.setData(ClipboardData(
-                            text:
-                                Provider.of<KretaClient>(context, listen: false)
-                                    .accessToken!)),
-                      ),
-                      // if (Provider.of<PremiumProvider>(context, listen: false)
-                      //     .hasPremium)
-                      //   PanelButton(
-                      //     leading: const Icon(FeatherIcons.key),
-                      //     title: const Text("Remove Premium"),
-                      //     onPressed: () {
-                      //       Provider.of<PremiumProvider>(context, listen: false)
-                      //           .activate(removePremium: true);
-                      //       settings.update(
-                      //           accentColor: AccentColor.filc, store: true);
-                      //       Provider.of<ThemeModeObserver>(context,
-                      //               listen: false)
-                      //           .changeTheme(settings.theme);
-                      //     },
-                      //   ),
-                    ],
-                  ),
-                ),
-              ),
-            SafeArea(
-              top: false,
-              child: Center(
-                child: GestureDetector(
-                  child: FutureBuilder<Map>(
-                    future: futureRelease,
-                    builder: (context, release) {
-                      if (release.hasData) {
-                        return DefaultTextStyle(
-                          style: Theme.of(context)
-                              .textTheme
-                              .titleMedium!
-                              .copyWith(
-                                  fontWeight: FontWeight.w600,
-                                  color: AppColors.of(context)
-                                      .text
-                                      .withOpacity(0.65)),
-                          child: Text("v${release.data!['version']}"),
-                        );
-                      } else {
-                        String envAppVer = const String.fromEnvironment(
-                            "APPVER",
-                            defaultValue: "?");
-                        return DefaultTextStyle(
-                          style: Theme.of(context)
-                              .textTheme
-                              .titleMedium!
-                              .copyWith(
-                                  fontWeight: FontWeight.w600,
-                                  color: AppColors.of(context)
-                                      .text
-                                      .withOpacity(0.65)),
-                          child: Text("v$envAppVer"),
-                        );
-                      }
-                    },
-                  ),
-                  onTap: () {
-                    if (devmodeCountdown > 0) {
-                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-                        duration: const Duration(milliseconds: 200),
-                        content:
-                            Text("devmoretaps".i18n.fill([devmodeCountdown])),
-                      ));
-
-                      setState(() => devmodeCountdown--);
-                    } else if (devmodeCountdown == 0) {
-                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-                        content: Text("devactivated".i18n),
-                      ));
-
-                      settings.update(developerMode: true);
-
-                      setState(() => devmodeCountdown--);
-                    }
-                  },
-                ),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-
-  void _openNews(BuildContext context) =>
-      Navigator.of(context, rootNavigator: true)
-          .push(CupertinoPageRoute(builder: (context) => const NewsScreen()));
-  void _openUpdates(BuildContext context) =>
-      UpdateView.show(updateProvider.releases.first, context: context);
-  void _openPrivacy(BuildContext context) => PrivacyView.show(context);
-}
+import 'package:refilc/api/providers/update_provider.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/event_provider.dart';
+import 'package:refilc_kreta_api/providers/exam_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_kreta_api/providers/message_provider.dart';
+import 'package:refilc_kreta_api/providers/note_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/client/client.dart';
+import 'package:refilc_mobile_ui/common/action_button.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_mobile_ui/common/profile_image/profile_image.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';
+import 'package:refilc_mobile_ui/screens/settings/accounts/account_tile.dart';
+import 'package:refilc_mobile_ui/screens/settings/accounts/account_view.dart';
+import 'package:refilc_mobile_ui/screens/settings/debug/subject_icon_gallery.dart';
+import 'package:refilc_mobile_ui/screens/settings/notifications_screen.dart';
+import 'package:refilc_mobile_ui/screens/settings/privacy_view.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_helper.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as tabs;
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:url_launcher/url_launcher.dart';
+import 'settings_screen.i18n.dart';
+import 'package:flutter/services.dart';
+import 'package:refilc_premium/ui/mobile/settings/nickname.dart';
+import 'package:refilc_premium/ui/mobile/settings/profile_pic.dart';
+import 'package:refilc_premium/ui/mobile/settings/icon_pack.dart';
+import 'package:refilc_premium/ui/mobile/settings/modify_subject_names.dart';
+import 'package:refilc_premium/ui/mobile/settings/modify_teacher_names.dart';
+
+class SettingsScreen extends StatefulWidget {
+  const SettingsScreen({Key? key}) : super(key: key);
+
+  @override
+  _SettingsScreenState createState() => _SettingsScreenState();
+}
+
+class _SettingsScreenState extends State<SettingsScreen>
+    with SingleTickerProviderStateMixin {
+  int devmodeCountdown = 5;
+  bool __ss = false; // secret settings
+
+  Future<Map>? futureRelease;
+
+  late UserProvider user;
+  late UpdateProvider updateProvider;
+  late SettingsProvider settings;
+  late KretaClient kretaClient;
+  late String firstName;
+  List<Widget> accountTiles = [];
+
+  late AnimationController _hideContainersController;
+
+  Future<void> restore() => Future.wait([
+        Provider.of<GradeProvider>(context, listen: false).restore(),
+        Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
+        Provider.of<ExamProvider>(context, listen: false).restore(),
+        Provider.of<HomeworkProvider>(context, listen: false).restore(),
+        Provider.of<MessageProvider>(context, listen: false).restore(),
+        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(),
+      ]);
+
+  void buildAccountTiles() {
+    accountTiles = [];
+    user.getUsers().forEach((account) {
+      if (account.id == user.id) return;
+
+      String _firstName;
+
+      List<String> _nameParts = account.displayName.split(" ");
+      if (!settings.presentationMode) {
+        _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
+      } else {
+        _firstName = "János";
+      }
+
+      accountTiles.add(
+        AccountTile(
+          name: Text(!settings.presentationMode ? account.name : "János",
+              style: const TextStyle(fontWeight: FontWeight.w500)),
+          username: Text(
+              !settings.presentationMode ? account.username : "01234567890"),
+          profileImage: ProfileImage(
+            name: _firstName,
+            role: account.role,
+            profilePictureString: account.picture,
+            backgroundColor: Theme.of(context)
+                .colorScheme
+                .primary, //!settings.presentationMode
+            //? ColorUtils.stringToColor(account.name)
+            //: Theme.of(context).colorScheme.secondary,
+          ),
+          onTap: () {
+            user.setUser(account.id);
+            restore().then((_) => user.setUser(account.id));
+            Navigator.of(context).pop();
+          },
+          onTapMenu: () => _showBottomSheet(account),
+        ),
+      );
+    });
+  }
+
+  void _showBottomSheet(User u) {
+    showBottomSheetMenu(context, items: [
+      BottomSheetMenuItem(
+        onPressed: () => AccountView.show(u, context: context),
+        icon: const Icon(FeatherIcons.user),
+        title: Text("personal_details".i18n),
+      ),
+      BottomSheetMenuItem(
+        onPressed: () => _openDKT(u),
+        icon: Icon(FeatherIcons.grid, color: AppColors.of(context).teal),
+        title: Text("open_dkt".i18n),
+      ),
+      UserMenuNickname(u),
+      UserMenuProfilePic(u),
+      // BottomSheetMenuItem(
+      //   onPressed: () {},
+      //   icon: Icon(FeatherIcons.camera),
+      //   title: Text("edit_profile_picture".i18n),
+      // ),
+      // BottomSheetMenuItem(
+      //   onPressed: () {},
+      //   icon: Icon(FeatherIcons.trash2, color: AppColors.of(context).red),
+      //   title: Text("remove_profile_picture".i18n),
+      // ),
+    ]);
+  }
+
+  void _openDKT(User u) => tabs.launch(
+      "https://dkttanulo.e-kreta.hu/sso?id_token=${kretaClient.idToken}",
+      customTabsOption: tabs.CustomTabsOption(
+        toolbarColor: Theme.of(context).scaffoldBackgroundColor,
+        showPageTitle: true,
+      ));
+
+  @override
+  void initState() {
+    super.initState();
+    Future.delayed(Duration.zero, () {
+      futureRelease = Provider.of<UpdateProvider>(context, listen: false)
+          .installedVersion();
+    });
+    _hideContainersController = AnimationController(
+        vsync: this, duration: const Duration(milliseconds: 200));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    user = Provider.of<UserProvider>(context);
+    settings = Provider.of<SettingsProvider>(context);
+    updateProvider = Provider.of<UpdateProvider>(context);
+    kretaClient = Provider.of<KretaClient>(context);
+
+    List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
+    if (!settings.presentationMode) {
+      firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
+    } else {
+      firstName = "János";
+    }
+
+    String startPageTitle =
+        SettingsHelper.localizedPageTitles()[settings.startPage] ?? "?";
+    String themeModeText = {
+          ThemeMode.light: "light".i18n,
+          ThemeMode.dark: "dark".i18n,
+          ThemeMode.system: "system".i18n
+        }[settings.theme] ??
+        "?";
+    String languageText = SettingsHelper.langMap[settings.language] ?? "?";
+    String vibrateTitle = {
+          VibrationStrength.off: "voff".i18n,
+          VibrationStrength.light: "vlight".i18n,
+          VibrationStrength.medium: "vmedium".i18n,
+          VibrationStrength.strong: "vstrong".i18n,
+        }[settings.vibrate] ??
+        "?";
+
+    buildAccountTiles();
+
+    if (settings.developerMode) devmodeCountdown = -1;
+
+    return AnimatedBuilder(
+      animation: _hideContainersController,
+      builder: (context, child) => Opacity(
+        opacity: 1 - _hideContainersController.value,
+        child: Column(
+          children: [
+            const SizedBox(height: 32.0),
+
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                IconButton(
+                  splashRadius: 32.0,
+                  onPressed: () =>
+                      _showBottomSheet(user.getUser(user.id ?? "")),
+                  icon: Icon(FeatherIcons.moreVertical,
+                      color: AppColors.of(context).text.withOpacity(0.8)),
+                ),
+                IconButton(
+                  splashRadius: 26.0,
+                  onPressed: () {
+                    Navigator.of(context).pop();
+                  },
+                  icon: Icon(FeatherIcons.x,
+                      color: AppColors.of(context).text.withOpacity(0.8)),
+                ),
+              ],
+            ),
+
+            Padding(
+              padding: const EdgeInsets.symmetric(vertical: 8.0),
+              child: ProfileImage(
+                heroTag: "profile",
+                radius: 36.0,
+                onTap: () => _showBottomSheet(user.getUser(user.id ?? "")),
+                name: firstName,
+                badge: updateProvider.available,
+                role: user.role,
+                profilePictureString: user.picture,
+                backgroundColor: Theme.of(context)
+                    .colorScheme
+                    .primary, //!settings.presentationMode
+                //? ColorUtils.stringToColor(user.displayName ?? "?")
+                //: Theme.of(context).colorScheme.secondary,
+              ),
+            ),
+
+            Padding(
+              padding: const EdgeInsets.only(top: 4.0, bottom: 12.0),
+              child: GestureDetector(
+                onTap: () => _showBottomSheet(user.getUser(user.id ?? "")),
+                onDoubleTap: () => setState(() => __ss = true),
+                child: Text(
+                  !settings.presentationMode
+                      ? (user.displayName ?? "?")
+                      : "János",
+                  maxLines: 1,
+                  softWrap: false,
+                  overflow: TextOverflow.ellipsis,
+                  textAlign: TextAlign.center,
+                  style: TextStyle(
+                      fontSize: 20.0,
+                      fontWeight: FontWeight.w600,
+                      color: AppColors.of(context).text),
+                ),
+              ),
+            ),
+
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              child: Panel(
+                child: Column(
+                  children: [
+                    // Account list
+                    ...accountTiles,
+
+                    if (accountTiles.isNotEmpty)
+                      Center(
+                        child: Container(
+                          margin: const EdgeInsets.only(top: 12.0, bottom: 4.0),
+                          height: 3.0,
+                          width: 75.0,
+                          decoration: BoxDecoration(
+                            borderRadius: BorderRadius.circular(12.0),
+                            color: AppColors.of(context).text.withOpacity(.25),
+                          ),
+                        ),
+                      ),
+
+                    // Account settings
+                    PanelButton(
+                      onPressed: () {
+                        Navigator.of(context)
+                            .pushNamed("login_back")
+                            .then((value) {
+                          setSystemChrome(context);
+                        });
+                      },
+                      title: Text("add_user".i18n),
+                      leading: const Icon(FeatherIcons.userPlus),
+                    ),
+                    PanelButton(
+                      onPressed: () 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 other Users left, go back to LoginScreen
+                        if (user.getUsers().isNotEmpty) {
+                          user.setUser(user.getUsers().first.id);
+                          restore().then(
+                              (_) => user.setUser(user.getUsers().first.id));
+                        } else {
+                          Navigator.of(context)
+                              .pushNamedAndRemoveUntil("login", (_) => false);
+                        }
+                      },
+                      title: Text("log_out".i18n),
+                      leading: Icon(FeatherIcons.logOut,
+                          color: AppColors.of(context).red),
+                    ),
+                  ],
+                ),
+              ),
+            ),
+
+            // Updates
+            if (updateProvider.available)
+              Padding(
+                padding: const EdgeInsets.symmetric(
+                    vertical: 12.0, horizontal: 24.0),
+                child: Panel(
+                  child: PanelButton(
+                    onPressed: () => _openUpdates(context),
+                    title: Text("update_available".i18n),
+                    leading: const Icon(FeatherIcons.download),
+                    trailing: Text(
+                      updateProvider.releases.first.tag,
+                      style: TextStyle(
+                        fontWeight: FontWeight.w500,
+                        color: Theme.of(context).colorScheme.secondary,
+                      ),
+                    ),
+                  ),
+                ),
+              ),
+
+            // const Padding(
+            //   padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+            //   child: PremiumBannerButton(),
+            // ),
+            // if (!context.watch<PremiumProvider>().hasPremium)
+            //   const ClipRect(
+            //     child: Padding(
+            //       padding: EdgeInsets.symmetric(vertical: 12.0),
+            //       child: PremiumButton(),
+            //     ),
+            //   )
+            // else
+            //   const Padding(
+            //     padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+            //     child: ActiveSponsorCard(),
+            //   ),
+
+            // General Settings
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              child: Panel(
+                title: Text("general".i18n),
+                child: Column(
+                  children: [
+                    PanelButton(
+                      onPressed: () {
+                        SettingsHelper.language(context);
+                        setState(() {});
+                      },
+                      title: Text("language".i18n),
+                      leading: const Icon(FeatherIcons.globe),
+                      trailing: Text(
+                        languageText,
+                        style: const TextStyle(fontSize: 14.0),
+                      ),
+                    ),
+                    PanelButton(
+                      onPressed: () {
+                        SettingsHelper.startPage(context);
+                        setState(() {});
+                      },
+                      title: Text("startpage".i18n),
+                      leading: const Icon(FeatherIcons.play),
+                      trailing: Text(
+                        startPageTitle.capital(),
+                        style: const TextStyle(fontSize: 14.0),
+                      ),
+                    ),
+                    PanelButton(
+                      onPressed: () {
+                        SettingsHelper.rounding(context);
+                        setState(() {});
+                      },
+                      title: Text("rounding".i18n),
+                      leading: const Icon(FeatherIcons.gitCommit),
+                      trailing: Text(
+                        (settings.rounding / 10).toStringAsFixed(1),
+                        style: const TextStyle(fontSize: 14.0),
+                      ),
+                    ),
+                    PanelButton(
+                      onPressed: () {
+                        SettingsHelper.vibrate(context);
+                        setState(() {});
+                      },
+                      title: Text("vibrate".i18n),
+                      leading: const Icon(FeatherIcons.radio),
+                      trailing: Text(
+                        vibrateTitle,
+                        style: const TextStyle(fontSize: 14.0),
+                      ),
+                    ),
+                    PanelButton(
+                      padding: const EdgeInsets.only(left: 14.0),
+                      onPressed: () {
+                        SettingsHelper.bellDelay(context);
+                        setState(() {});
+                      },
+                      title: Text(
+                        "bell_delay".i18n,
+                        style: TextStyle(
+                            color: AppColors.of(context).text.withOpacity(
+                                settings.bellDelayEnabled ? 1.0 : .5)),
+                      ),
+                      leading: settings.bellDelayEnabled
+                          ? const Icon(FeatherIcons.bell)
+                          : Icon(FeatherIcons.bellOff,
+                              color:
+                                  AppColors.of(context).text.withOpacity(.25)),
+                      trailingDivider: true,
+                      trailing: Switch(
+                        onChanged: (v) => settings.update(bellDelayEnabled: v),
+                        value: settings.bellDelayEnabled,
+                        activeColor: Theme.of(context).colorScheme.secondary,
+                      ),
+                    ),
+                    Material(
+                        type: MaterialType.transparency,
+                        child: MenuNotifications(settings: settings)),
+                  ],
+                ),
+              ),
+            ),
+
+            if (kDebugMode)
+              Padding(
+                padding: const EdgeInsets.symmetric(
+                    vertical: 12.0, horizontal: 24.0),
+                child: Panel(
+                  title: const Text("Debug"),
+                  child: Column(
+                    children: [
+                      PanelButton(
+                        title: const Text("Subject Icon Gallery"),
+                        leading:
+                            const Icon(CupertinoIcons.rectangle_3_offgrid_fill),
+                        trailing: const Icon(Icons.arrow_forward),
+                        onPressed: () {
+                          Navigator.of(context, rootNavigator: true).push(
+                            CupertinoPageRoute(
+                                builder: (context) =>
+                                    const SubjectIconGallery()),
+                          );
+                        },
+                      )
+                    ],
+                  ),
+                ),
+              ),
+
+            // Secret Settings
+            if (__ss)
+              Padding(
+                padding: const EdgeInsets.symmetric(
+                    vertical: 12.0, horizontal: 24.0),
+                child: Panel(
+                  title: Text("secret".i18n),
+                  child: Column(
+                    children: [
+                      // Good student mode
+                      Material(
+                        type: MaterialType.transparency,
+                        child: SwitchListTile(
+                          contentPadding: const EdgeInsets.only(left: 12.0),
+                          shape: RoundedRectangleBorder(
+                              borderRadius: BorderRadius.circular(12.0)),
+                          title: Text("goodstudent".i18n,
+                              style:
+                                  const TextStyle(fontWeight: FontWeight.w500)),
+                          onChanged: (v) {
+                            if (v) {
+                              showDialog(
+                                context: context,
+                                builder: (context) => WillPopScope(
+                                  onWillPop: () async => false,
+                                  child: AlertDialog(
+                                    shape: RoundedRectangleBorder(
+                                        borderRadius:
+                                            BorderRadius.circular(12.0)),
+                                    title: Text("attention".i18n),
+                                    content:
+                                        Text("goodstudent_disclaimer".i18n),
+                                    actions: [
+                                      ActionButton(
+                                          label: "understand".i18n,
+                                          onTap: () {
+                                            Navigator.of(context).pop();
+                                            settings.update(goodStudent: v);
+                                            Provider.of<GradeProvider>(context,
+                                                    listen: false)
+                                                .convertBySettings();
+                                          })
+                                    ],
+                                  ),
+                                ),
+                              );
+                            } else {
+                              settings.update(goodStudent: v);
+                              Provider.of<GradeProvider>(context, listen: false)
+                                  .convertBySettings();
+                            }
+                          },
+                          value: settings.goodStudent,
+                          activeColor: Theme.of(context).colorScheme.secondary,
+                        ),
+                      ),
+
+                      // Presentation mode
+                      Material(
+                        type: MaterialType.transparency,
+                        child: SwitchListTile(
+                          contentPadding: const EdgeInsets.only(left: 12.0),
+                          shape: RoundedRectangleBorder(
+                              borderRadius: BorderRadius.circular(12.0)),
+                          title: Text("presentation".i18n,
+                              style:
+                                  const TextStyle(fontWeight: FontWeight.w500)),
+                          onChanged: (v) =>
+                              settings.update(presentationMode: v),
+                          value: settings.presentationMode,
+                          activeColor: Theme.of(context).colorScheme.secondary,
+                        ),
+                      ),
+
+                      // UwU-fied mode (why????)
+                      // Material(
+                      //   type: MaterialType.transparency,
+                      //   child: SwitchListTile(
+                      //     contentPadding: const EdgeInsets.only(left: 12.0),
+                      //     shape: RoundedRectangleBorder(
+                      //         borderRadius: BorderRadius.circular(12.0)),
+                      //     title: Text("uwufymode".i18n,
+                      //         style:
+                      //             const TextStyle(fontWeight: FontWeight.w500)),
+                      //     onChanged: (v) {
+                      //       SettingsHelper.uwuMode(context, v);
+                      //       setState(() {});
+                      //     },
+                      //     value: settings.presentationMode,
+                      //     activeColor: Theme.of(context).colorScheme.secondary,
+                      //   ),
+                      // ),
+                    ],
+                  ),
+                ),
+              ),
+
+            // Theme Settings
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              child: Panel(
+                title: Text("appearance".i18n),
+                child: Column(
+                  children: [
+                    PanelButton(
+                      onPressed: () {
+                        SettingsHelper.theme(context);
+                        setState(() {});
+                      },
+                      title: Text("theme".i18n),
+                      leading: const Icon(FeatherIcons.sun),
+                      trailing: Text(
+                        themeModeText,
+                        style: const TextStyle(fontSize: 14.0),
+                      ),
+                    ),
+                    PanelButton(
+                      onPressed: () async {
+                        await _hideContainersController.forward();
+                        SettingsHelper.accentColor(context);
+                        setState(() {});
+                        _hideContainersController.reset();
+                      },
+                      title: Text("color".i18n),
+                      leading: const Icon(FeatherIcons.droplet),
+                      trailing: Container(
+                        width: 12.0,
+                        height: 12.0,
+                        decoration: BoxDecoration(
+                          color: Theme.of(context).colorScheme.secondary,
+                          shape: BoxShape.circle,
+                        ),
+                      ),
+                    ),
+                    PanelButton(
+                      onPressed: () {
+                        SettingsHelper.gradeColors(context);
+                        setState(() {});
+                      },
+                      title: Text("grade_colors".i18n),
+                      leading: const Icon(FeatherIcons.star),
+                      trailing: Row(
+                        mainAxisSize: MainAxisSize.min,
+                        children: List.generate(
+                          5,
+                          (i) => Container(
+                            margin: const EdgeInsets.only(left: 2.0),
+                            width: 12.0,
+                            height: 12.0,
+                            decoration: BoxDecoration(
+                              shape: BoxShape.circle,
+                              color: settings.gradeColors[i],
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+                    Material(
+                      type: MaterialType.transparency,
+                      child: SwitchListTile(
+                        contentPadding: const EdgeInsets.only(left: 12.0),
+                        shape: RoundedRectangleBorder(
+                            borderRadius: BorderRadius.circular(12.0)),
+                        title: Row(
+                          children: [
+                            Icon(
+                              FeatherIcons.barChart,
+                              color: settings.graphClassAvg
+                                  ? Theme.of(context).colorScheme.secondary
+                                  : AppColors.of(context).text.withOpacity(.25),
+                            ),
+                            const SizedBox(width: 14.0),
+                            Expanded(
+                              child: Text(
+                                "graph_class_avg".i18n,
+                                style: TextStyle(
+                                  fontWeight: FontWeight.w600,
+                                  fontSize: 16.0,
+                                  color: AppColors.of(context).text.withOpacity(
+                                      settings.graphClassAvg ? 1.0 : .5),
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
+                        onChanged: (v) => settings.update(graphClassAvg: v),
+                        value: settings.graphClassAvg,
+                        activeColor: Theme.of(context).colorScheme.secondary,
+                      ),
+                    ),
+                    const PremiumIconPackSelector(),
+                    // If iOS, show the iOS specific settings
+
+                    if (defaultTargetPlatform == TargetPlatform.iOS)
+                      PanelButton(
+                        onPressed: () {
+                          SettingsHelper.liveActivityColor(context);
+                          setState(() {});
+                        },
+                        title: Text("live_activity_color".i18n),
+                        leading: const Icon(FeatherIcons.activity),
+                        trailing: Container(
+                          width: 12.0,
+                          height: 12.0,
+                          decoration: BoxDecoration(
+                            color: settings.liveActivityColor,
+                            shape: BoxShape.circle,
+                          ),
+                        ),
+                      ),
+                  ],
+                ),
+              ),
+            ),
+
+            // Notifications
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              child: Panel(
+                title: Text("popups".i18n),
+                child: Material(
+                  type: MaterialType.transparency,
+                  child: SwitchListTile(
+                    contentPadding: const EdgeInsets.only(left: 12.0),
+                    shape: RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(12.0)),
+                    title: Row(
+                      children: [
+                        Icon(
+                          Icons.newspaper_outlined,
+                          color: settings.newsEnabled
+                              ? Theme.of(context).colorScheme.secondary
+                              : AppColors.of(context).text.withOpacity(.25),
+                        ),
+                        const SizedBox(width: 14.0),
+                        Expanded(
+                          child: Text(
+                            "news".i18n,
+                            style: TextStyle(
+                              fontWeight: FontWeight.w600,
+                              fontSize: 16.0,
+                              color: AppColors.of(context)
+                                  .text
+                                  .withOpacity(settings.newsEnabled ? 1.0 : .5),
+                            ),
+                          ),
+                        ),
+                      ],
+                    ),
+                    onChanged: (v) => settings.update(newsEnabled: v),
+                    value: settings.newsEnabled,
+                    activeColor: Theme.of(context).colorScheme.secondary,
+                  ),
+                ),
+              ),
+            ),
+
+            // Extras
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              child: Panel(
+                title: Text("extras".i18n),
+                child: Column(
+                  children: [
+                    Material(
+                      type: MaterialType.transparency,
+                      child: SwitchListTile(
+                        contentPadding: const EdgeInsets.only(left: 12.0),
+                        shape: RoundedRectangleBorder(
+                            borderRadius: BorderRadius.circular(12.0)),
+                        title: Row(
+                          children: [
+                            Icon(
+                              FeatherIcons.gift,
+                              color: settings.gradeOpeningFun
+                                  ? Theme.of(context).colorScheme.secondary
+                                  : AppColors.of(context).text.withOpacity(.25),
+                            ),
+                            const SizedBox(width: 14.0),
+                            Expanded(
+                              child: Text(
+                                "surprise_grades".i18n,
+                                style: TextStyle(
+                                  fontWeight: FontWeight.w600,
+                                  fontSize: 16.0,
+                                  color: AppColors.of(context).text.withOpacity(
+                                      settings.gradeOpeningFun ? 1.0 : .5),
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
+                        onChanged: (v) => settings.update(gradeOpeningFun: v),
+                        value: settings.gradeOpeningFun,
+                        activeColor: Theme.of(context).colorScheme.secondary,
+                      ),
+                    ),
+                    MenuRenamedSubjects(
+                      settings: settings,
+                    ),
+                    MenuRenamedTeachers(
+                      settings: settings,
+                    ),
+                  ],
+                ),
+              ),
+            ),
+
+            // About
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+              child: Panel(
+                title: Text("about".i18n),
+                child: Column(children: [
+                  PanelButton(
+                    leading: const Icon(FeatherIcons.mail),
+                    title: Text("news".i18n),
+                    onPressed: () => _openNews(context),
+                  ),
+                  PanelButton(
+                    leading: const Icon(FeatherIcons.lock),
+                    title: Text("privacy".i18n),
+                    // onPressed: () => launchUrl(
+                    //     Uri.parse("https://refilc.hu/privacy-policy"),
+                    //     mode: LaunchMode.inAppWebView),
+                    onPressed: () => _openPrivacy(context),
+                  ),
+                  PanelButton(
+                    leading: const Icon(FeatherIcons.atSign),
+                    title: const Text("Discord"),
+                    onPressed: () => launchUrl(
+                        Uri.parse("https://dc.refilc.hu"),
+                        mode: LaunchMode.externalApplication),
+                  ),
+                  PanelButton(
+                    leading: const Icon(FeatherIcons.globe),
+                    title: const Text("www.refilc.hu"),
+                    onPressed: () => launchUrl(
+                        Uri.parse("https://www.refilc.hu"),
+                        mode: LaunchMode.externalApplication),
+                  ),
+                  PanelButton(
+                    leading: const Icon(FeatherIcons.github),
+                    title: const Text("Github"),
+                    onPressed: () => launchUrl(
+                        Uri.parse("https://github.com/refilc"),
+                        mode: LaunchMode.externalApplication),
+                  ),
+                  PanelButton(
+                    leading: const Icon(FeatherIcons.award),
+                    title: Text("licenses".i18n),
+                    onPressed: () => showLicensePage(context: context),
+                  ),
+                  Tooltip(
+                    message: "data_collected".i18n,
+                    padding: const EdgeInsets.all(4.0),
+                    textStyle: TextStyle(
+                        fontWeight: FontWeight.w500,
+                        color: AppColors.of(context).text),
+                    decoration: BoxDecoration(
+                        color: Theme.of(context).colorScheme.background),
+                    child: Material(
+                      type: MaterialType.transparency,
+                      child: SwitchListTile(
+                        contentPadding: const EdgeInsets.only(left: 12.0),
+                        shape: RoundedRectangleBorder(
+                            borderRadius: BorderRadius.circular(12.0)),
+                        secondary: Icon(
+                          FeatherIcons.barChart2,
+                          color: settings.xFilcId != "none"
+                              ? Theme.of(context).colorScheme.secondary
+                              : AppColors.of(context).text.withOpacity(.25),
+                        ),
+                        title: Text(
+                          "Analytics".i18n,
+                          style: TextStyle(
+                            fontWeight: FontWeight.w600,
+                            fontSize: 16.0,
+                            color: AppColors.of(context).text.withOpacity(
+                                settings.xFilcId != "none" ? 1.0 : .5),
+                          ),
+                        ),
+                        subtitle: Text(
+                          "Anonymous Usage Analytics".i18n,
+                          style: TextStyle(
+                            color: AppColors.of(context).text.withOpacity(
+                                settings.xFilcId != "none" ? .5 : .2),
+                          ),
+                        ),
+                        onChanged: (v) {
+                          String newId;
+                          if (v == false) {
+                            newId = "none";
+                          } else if (settings.xFilcId == "none") {
+                            newId = SettingsProvider.defaultSettings().xFilcId;
+                          } else {
+                            newId = settings.xFilcId;
+                          }
+                          settings.update(xFilcId: newId);
+                        },
+                        value: settings.xFilcId != "none",
+                        activeColor: Theme.of(context).colorScheme.secondary,
+                      ),
+                    ),
+                  ),
+                ]),
+              ),
+            ),
+            if (settings.developerMode)
+              Padding(
+                padding: const EdgeInsets.symmetric(
+                    vertical: 12.0, horizontal: 24.0),
+                child: Panel(
+                  title: Text("devsettings".i18n),
+                  child: Column(
+                    children: [
+                      Material(
+                        type: MaterialType.transparency,
+                        child: SwitchListTile(
+                          contentPadding: const EdgeInsets.only(left: 12.0),
+                          shape: RoundedRectangleBorder(
+                              borderRadius: BorderRadius.circular(12.0)),
+                          title: Text("devmode".i18n,
+                              style:
+                                  const TextStyle(fontWeight: FontWeight.w500)),
+                          onChanged: (v) =>
+                              settings.update(developerMode: false),
+                          value: settings.developerMode,
+                          activeColor: Theme.of(context).colorScheme.secondary,
+                        ),
+                      ),
+                      PanelButton(
+                        leading: const Icon(FeatherIcons.copy),
+                        title: Text("copy_jwt".i18n),
+                        onPressed: () => Clipboard.setData(ClipboardData(
+                            text:
+                                Provider.of<KretaClient>(context, listen: false)
+                                    .accessToken!)),
+                      ),
+                      // if (Provider.of<PremiumProvider>(context, listen: false)
+                      //     .hasPremium)
+                      //   PanelButton(
+                      //     leading: const Icon(FeatherIcons.key),
+                      //     title: const Text("Remove Premium"),
+                      //     onPressed: () {
+                      //       Provider.of<PremiumProvider>(context, listen: false)
+                      //           .activate(removePremium: true);
+                      //       settings.update(
+                      //           accentColor: AccentColor.filc, store: true);
+                      //       Provider.of<ThemeModeObserver>(context,
+                      //               listen: false)
+                      //           .changeTheme(settings.theme);
+                      //     },
+                      //   ),
+                    ],
+                  ),
+                ),
+              ),
+            SafeArea(
+              top: false,
+              child: Center(
+                child: GestureDetector(
+                  child: FutureBuilder<Map>(
+                    future: futureRelease,
+                    builder: (context, release) {
+                      if (release.hasData) {
+                        return DefaultTextStyle(
+                          style: Theme.of(context)
+                              .textTheme
+                              .titleMedium!
+                              .copyWith(
+                                  fontWeight: FontWeight.w600,
+                                  color: AppColors.of(context)
+                                      .text
+                                      .withOpacity(0.65)),
+                          child: Text("v${release.data!['version']}"),
+                        );
+                      } else {
+                        String envAppVer = const String.fromEnvironment(
+                            "APPVER",
+                            defaultValue: "?");
+                        return DefaultTextStyle(
+                          style: Theme.of(context)
+                              .textTheme
+                              .titleMedium!
+                              .copyWith(
+                                  fontWeight: FontWeight.w600,
+                                  color: AppColors.of(context)
+                                      .text
+                                      .withOpacity(0.65)),
+                          child: Text("v$envAppVer"),
+                        );
+                      }
+                    },
+                  ),
+                  onTap: () {
+                    if (devmodeCountdown > 0) {
+                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+                        duration: const Duration(milliseconds: 200),
+                        content:
+                            Text("devmoretaps".i18n.fill([devmodeCountdown])),
+                      ));
+
+                      setState(() => devmodeCountdown--);
+                    } else if (devmodeCountdown == 0) {
+                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+                        content: Text("devactivated".i18n),
+                      ));
+
+                      settings.update(developerMode: true);
+
+                      setState(() => devmodeCountdown--);
+                    }
+                  },
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  void _openNews(BuildContext context) =>
+      Navigator.of(context, rootNavigator: true)
+          .push(CupertinoPageRoute(builder: (context) => const NewsScreen()));
+  void _openUpdates(BuildContext context) =>
+      UpdateView.show(updateProvider.releases.first, context: context);
+  void _openPrivacy(BuildContext context) => PrivacyView.show(context);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart b/refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
old mode 100755
new mode 100644
similarity index 97%
rename from filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
rename to refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
index 3ff52aa..ff50bbe
--- a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
+++ b/refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart
@@ -1,224 +1,224 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension SettingsLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "personal_details": "Personal Details",
-          "open_dkt": "Open DKT",
-          "edit_nickname": "Edit Nickname",
-          "edit_profile_picture": "Edit Profile Picture",
-          "remove_profile_picture": "Remove Profile Picture",
-          "select_profile_picture": "to select a picture",
-          "click_here": "Click here",
-          "light": "Light",
-          "dark": "Dark",
-          "system": "System",
-          "add_user": "Add User",
-          "log_out": "Log Out",
-          "update_available": "Update Available",
-          "general": "General",
-          "language": "Language",
-          "startpage": "Startpage",
-          "rounding": "Rounding",
-          "appearance": "Appearance",
-          "theme": "Theme",
-          "color": "Color",
-          "grade_colors": "Grade Colors",
-          "live_activity_color": "Live Activity Color",
-          "notifications": "Notifications",
-          "popups": "Pop-up Alerts",
-          "news": "News",
-          "extras": "Extras",
-          "about": "About",
-          "supporters": "Supporters",
-          "privacy": "Privacy Policy",
-          "licenses": "Licenses",
-          "vibrate": "Vibration",
-          "voff": "Off",
-          "vlight": "Light",
-          "vmedium": "Medium",
-          "vstrong": "Strong",
-          "cancel": "Cancel",
-          "done": "Done",
-          "reset": "Reset",
-          "open": "Open",
-          "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",
-          "goodstudent": "Good student mode",
-          "attention": "Attention!",
-          "goodstudent_disclaimer":
-              "reFilc can not be held liable for the usage of this feature.\n\n(if your mother beats you up because you showed her fake grades, you can only blame yourself for it)",
-          "understand": "I understand",
-          "secret": "Secret Settings",
-          "bell_delay": "Bell Delay",
-          "delay": "Delay",
-          "hurry": "Hurry",
-          "sync": "Synchronize",
-          "sync_help": "Press the Synchronize button when the bell rings.",
-          "surprise_grades": "Surprise Grades",
-          "icon_pack": "Icon Pack",
-          "change_username": "Set a nickname",
-          "Accent Color": "Accent Color",
-          "Background Color": "Background Color",
-          "Highlight Color": "Highlight Color",
-          "Adaptive Theme": "Adaptive Theme",
-          "presentation": "Presentation mode",
-          "uwufymode": "UwU-fied mode (hungarian)",
-          "devmoretaps": "You are %s taps away from Developer Mode.",
-          "devactivated": "Developer Mode successfully activated.",
-          "devsettings": "Developer Settings",
-          "devmode": "Developer Mode",
-          "copy_jwt": "Copy JWT",
-        },
-        "hu_hu": {
-          "personal_details": "Személyes információk",
-          "open_dkt": "DKT megnyitása",
-          "edit_nickname": "Becenév szerkesztése",
-          "edit_profile_picture": "Profil-kép szerkesztése",
-          "remove_profile_picture": "Profil-kép törlése",
-          "select_profile_picture": "a kép kiválasztásához",
-          "click_here": "Kattints ide",
-          "light": "Világos",
-          "dark": "Sötét",
-          "system": "Rendszer",
-          "add_user": "Felhasználó hozzáadása",
-          "log_out": "Kijelentkezés",
-          "update_available": "Frissítés elérhető",
-          "general": "Általános",
-          "language": "Nyelv",
-          "startpage": "Kezdőlap",
-          "rounding": "Kerekítés",
-          "appearance": "Kinézet",
-          "theme": "Téma",
-          "color": "Színek",
-          "grade_colors": "Jegyek színei",
-          "live_activity_color": "Live Activity színe",
-          "notifications": "Értesítések",
-          "popups": "Pop-up értesítések",
-          "news": "Hírek",
-          "extras": "Extrák",
-          "about": "Névjegy",
-          "supporters": "Támogatók",
-          "privacy": "Adatvédelmi irányelvek",
-          "licenses": "Licencek",
-          "vibrate": "Rezgés",
-          "voff": "Kikapcsolás",
-          "vlight": "Alacsony",
-          "vmedium": "Közepes",
-          "vstrong": "Erős",
-          "cancel": "Mégsem",
-          "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ó",
-          "Analytics": "Analitika",
-          "Anonymous Usage Analytics": "Névtelen használati analitika",
-          "graph_class_avg": "Osztályátlag a grafikonon",
-          "goodstudent": "Jó tanuló mód",
-          "attention": "Figyelem!",
-          "goodstudent_disclaimer":
-              "A reFilc minden felelősséget elhárít a funkció használatával kapcsolatban.\n\n(Értsd: ha az anyád megver, mert megtévesztő ábrákat mutattál neki, azért csakis magadadat hibáztathatod.)",
-          "understand": "Értem",
-          "secret": "Titkos Beállítások",
-          "bell_delay": "Csengő eltolódása",
-          "delay": "Késleltetés",
-          "hurry": "Siettetés",
-          "sync": "Szinkronizálás",
-          "sync_help": "Csengetéskor nyomd meg a Szinkronizálás gombot.",
-          "surprise_grades": "Meglepetés jegyek",
-          "icon_pack": "Ikon séma",
-          "change_username": "Becenév beállítása",
-          "Accent Color": "Egyedi szín",
-          "Background Color": "Háttér színe",
-          "Highlight Color": "Panelek színe",
-          "Adaptive Theme": "Adaptív téma",
-          "presentation": "Bemutató mód",
-          "uwufymode": "UwU mód (magyar)",
-          "devmoretaps": "Még %s koppintásra vagy a Fejlesztői módtól.",
-          "devactivated": "Fejlesztői mód sikeresen aktiválva.",
-          "devsettings": "Fejlesztői Beállítások",
-          "devmode": "Fejlesztői mód",
-          "copy_jwt": "JWT másolása",
-        },
-        "de_de": {
-          "personal_details": "Persönliche Angaben",
-          "open_dkt": "Öffnen DKT",
-          "edit_nickname": "Spitznamen bearbeiten",
-          "edit_profile_picture": "Profilbild bearbeiten",
-          "remove_profile_picture": "Profilbild entfernen",
-          "select_profile_picture": "um ein Bild auszuwählen",
-          "click_here": "Klick hier",
-          "light": "Licht",
-          "dark": "Dunkel",
-          "system": "System",
-          "add_user": "Benutzer hinzufügen",
-          "log_out": "Abmelden",
-          "update_available": "Update verfügbar",
-          "general": "Allgemein",
-          "language": "Sprache",
-          "startpage": "Startseite",
-          "rounding": "Rundung",
-          "appearance": "Erscheinungsbild",
-          "theme": "Thema",
-          "color": "Farbe",
-          "grade_colors": "Grad Farben",
-          "live_activity_color": "Live Activity Farben",
-          "notifications": "Mitteilung",
-          "popups": "Popup-Nachrichten",
-          "news": "Nachrichten",
-          "extras": "Extras",
-          "about": "Informationen",
-          "supporters": "Unterstützer",
-          "privacy": "Datenschutzbestimmungen",
-          "licenses": "Lizenzen",
-          "vibrate": "Vibration",
-          "voff": "Aus",
-          "vlight": "Leicht",
-          "vmedium": "Mittel",
-          "vstrong": "Stark",
-          "cancel": "Abbrechen",
-          "done": "Fertig",
-          "reset": "Zurücksetzen",
-          "open": "Öffnen",
-          "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",
-          "goodstudent": "Guter Student Modus",
-          "attention": "Achtung!",
-          "goodstudent_disclaimer": "Same in English.",
-          "understand": "Ich verstehe",
-          "secret": "Geheime Einstellungen",
-          "bell_delay": "Klingelverzögerung",
-          "delay": "Verzögern",
-          "hurry": "Eile",
-          "sync": "Synchronisieren",
-          "sync_help": "Drücken Sie die Sync-Taste, wenn die Glocke läutet.",
-          "surprise_grades": "Überraschungsnoten",
-          "icon_pack": "Icon-Pack",
-          "change_username": "Einen Spitznamen festlegen",
-          "Accent Color": "Accent Color",
-          "Background Color": "Background Color",
-          "Highlight Color": "Highlight Color",
-          "Adaptive Theme": "Adaptive Theme",
-          "presentation": "Präsentationsmodus",
-          "uwufymode": "UwU-Modus (ungarisch)",
-          "devmoretaps": "Sie sind %s Taps vom Entwicklermodus entfernt.",
-          "devactivated": "Entwicklermodus erfolgreich aktiviert.",
-          "devsettings": "Entwickleroptionen",
-          "devmode": "Entwicklermodus",
-          "copy_jwt": "JWT kopieren",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension SettingsLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "personal_details": "Personal Details",
+          "open_dkt": "Open DKT",
+          "edit_nickname": "Edit Nickname",
+          "edit_profile_picture": "Edit Profile Picture",
+          "remove_profile_picture": "Remove Profile Picture",
+          "select_profile_picture": "to select a picture",
+          "click_here": "Click here",
+          "light": "Light",
+          "dark": "Dark",
+          "system": "System",
+          "add_user": "Add User",
+          "log_out": "Log Out",
+          "update_available": "Update Available",
+          "general": "General",
+          "language": "Language",
+          "startpage": "Startpage",
+          "rounding": "Rounding",
+          "appearance": "Appearance",
+          "theme": "Theme",
+          "color": "Color",
+          "grade_colors": "Grade Colors",
+          "live_activity_color": "Live Activity Color",
+          "notifications": "Notifications",
+          "popups": "Pop-up Alerts",
+          "news": "News",
+          "extras": "Extras",
+          "about": "About",
+          "supporters": "Supporters",
+          "privacy": "Privacy Policy",
+          "licenses": "Licenses",
+          "vibrate": "Vibration",
+          "voff": "Off",
+          "vlight": "Light",
+          "vmedium": "Medium",
+          "vstrong": "Strong",
+          "cancel": "Cancel",
+          "done": "Done",
+          "reset": "Reset",
+          "open": "Open",
+          "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",
+          "goodstudent": "Good student mode",
+          "attention": "Attention!",
+          "goodstudent_disclaimer":
+              "reFilc can not be held liable for the usage of this feature.\n\n(if your mother beats you up because you showed her fake grades, you can only blame yourself for it)",
+          "understand": "I understand",
+          "secret": "Secret Settings",
+          "bell_delay": "Bell Delay",
+          "delay": "Delay",
+          "hurry": "Hurry",
+          "sync": "Synchronize",
+          "sync_help": "Press the Synchronize button when the bell rings.",
+          "surprise_grades": "Surprise Grades",
+          "icon_pack": "Icon Pack",
+          "change_username": "Set a nickname",
+          "Accent Color": "Accent Color",
+          "Background Color": "Background Color",
+          "Highlight Color": "Highlight Color",
+          "Adaptive Theme": "Adaptive Theme",
+          "presentation": "Presentation mode",
+          "uwufymode": "UwU-fied mode (hungarian)",
+          "devmoretaps": "You are %s taps away from Developer Mode.",
+          "devactivated": "Developer Mode successfully activated.",
+          "devsettings": "Developer Settings",
+          "devmode": "Developer Mode",
+          "copy_jwt": "Copy JWT",
+        },
+        "hu_hu": {
+          "personal_details": "Személyes információk",
+          "open_dkt": "DKT megnyitása",
+          "edit_nickname": "Becenév szerkesztése",
+          "edit_profile_picture": "Profil-kép szerkesztése",
+          "remove_profile_picture": "Profil-kép törlése",
+          "select_profile_picture": "a kép kiválasztásához",
+          "click_here": "Kattints ide",
+          "light": "Világos",
+          "dark": "Sötét",
+          "system": "Rendszer",
+          "add_user": "Felhasználó hozzáadása",
+          "log_out": "Kijelentkezés",
+          "update_available": "Frissítés elérhető",
+          "general": "Általános",
+          "language": "Nyelv",
+          "startpage": "Kezdőlap",
+          "rounding": "Kerekítés",
+          "appearance": "Kinézet",
+          "theme": "Téma",
+          "color": "Színek",
+          "grade_colors": "Jegyek színei",
+          "live_activity_color": "Live Activity színe",
+          "notifications": "Értesítések",
+          "popups": "Pop-up értesítések",
+          "news": "Hírek",
+          "extras": "Extrák",
+          "about": "Névjegy",
+          "supporters": "Támogatók",
+          "privacy": "Adatvédelmi irányelvek",
+          "licenses": "Licencek",
+          "vibrate": "Rezgés",
+          "voff": "Kikapcsolás",
+          "vlight": "Alacsony",
+          "vmedium": "Közepes",
+          "vstrong": "Erős",
+          "cancel": "Mégsem",
+          "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ó",
+          "Analytics": "Analitika",
+          "Anonymous Usage Analytics": "Névtelen használati analitika",
+          "graph_class_avg": "Osztályátlag a grafikonon",
+          "goodstudent": "Jó tanuló mód",
+          "attention": "Figyelem!",
+          "goodstudent_disclaimer":
+              "A reFilc minden felelősséget elhárít a funkció használatával kapcsolatban.\n\n(Értsd: ha az anyád megver, mert megtévesztő ábrákat mutattál neki, azért csakis magadadat hibáztathatod.)",
+          "understand": "Értem",
+          "secret": "Titkos Beállítások",
+          "bell_delay": "Csengő eltolódása",
+          "delay": "Késleltetés",
+          "hurry": "Siettetés",
+          "sync": "Szinkronizálás",
+          "sync_help": "Csengetéskor nyomd meg a Szinkronizálás gombot.",
+          "surprise_grades": "Meglepetés jegyek",
+          "icon_pack": "Ikon séma",
+          "change_username": "Becenév beállítása",
+          "Accent Color": "Egyedi szín",
+          "Background Color": "Háttér színe",
+          "Highlight Color": "Panelek színe",
+          "Adaptive Theme": "Adaptív téma",
+          "presentation": "Bemutató mód",
+          "uwufymode": "UwU mód (magyar)",
+          "devmoretaps": "Még %s koppintásra vagy a Fejlesztői módtól.",
+          "devactivated": "Fejlesztői mód sikeresen aktiválva.",
+          "devsettings": "Fejlesztői Beállítások",
+          "devmode": "Fejlesztői mód",
+          "copy_jwt": "JWT másolása",
+        },
+        "de_de": {
+          "personal_details": "Persönliche Angaben",
+          "open_dkt": "Öffnen DKT",
+          "edit_nickname": "Spitznamen bearbeiten",
+          "edit_profile_picture": "Profilbild bearbeiten",
+          "remove_profile_picture": "Profilbild entfernen",
+          "select_profile_picture": "um ein Bild auszuwählen",
+          "click_here": "Klick hier",
+          "light": "Licht",
+          "dark": "Dunkel",
+          "system": "System",
+          "add_user": "Benutzer hinzufügen",
+          "log_out": "Abmelden",
+          "update_available": "Update verfügbar",
+          "general": "Allgemein",
+          "language": "Sprache",
+          "startpage": "Startseite",
+          "rounding": "Rundung",
+          "appearance": "Erscheinungsbild",
+          "theme": "Thema",
+          "color": "Farbe",
+          "grade_colors": "Grad Farben",
+          "live_activity_color": "Live Activity Farben",
+          "notifications": "Mitteilung",
+          "popups": "Popup-Nachrichten",
+          "news": "Nachrichten",
+          "extras": "Extras",
+          "about": "Informationen",
+          "supporters": "Unterstützer",
+          "privacy": "Datenschutzbestimmungen",
+          "licenses": "Lizenzen",
+          "vibrate": "Vibration",
+          "voff": "Aus",
+          "vlight": "Leicht",
+          "vmedium": "Mittel",
+          "vstrong": "Stark",
+          "cancel": "Abbrechen",
+          "done": "Fertig",
+          "reset": "Zurücksetzen",
+          "open": "Öffnen",
+          "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",
+          "goodstudent": "Guter Student Modus",
+          "attention": "Achtung!",
+          "goodstudent_disclaimer": "Same in English.",
+          "understand": "Ich verstehe",
+          "secret": "Geheime Einstellungen",
+          "bell_delay": "Klingelverzögerung",
+          "delay": "Verzögern",
+          "hurry": "Eile",
+          "sync": "Synchronisieren",
+          "sync_help": "Drücken Sie die Sync-Taste, wenn die Glocke läutet.",
+          "surprise_grades": "Überraschungsnoten",
+          "icon_pack": "Icon-Pack",
+          "change_username": "Einen Spitznamen festlegen",
+          "Accent Color": "Accent Color",
+          "Background Color": "Background Color",
+          "Highlight Color": "Highlight Color",
+          "Adaptive Theme": "Adaptive Theme",
+          "presentation": "Präsentationsmodus",
+          "uwufymode": "UwU-Modus (ungarisch)",
+          "devmoretaps": "Sie sind %s Taps vom Entwicklermodus entfernt.",
+          "devactivated": "Entwicklermodus erfolgreich aktiviert.",
+          "devsettings": "Entwickleroptionen",
+          "devmode": "Entwicklermodus",
+          "copy_jwt": "JWT kopieren",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/pages/allsum_page.dart b/refilc_mobile_ui/lib/screens/summary/pages/allsum_page.dart
similarity index 92%
rename from filcnaplo_mobile_ui/lib/screens/summary/pages/allsum_page.dart
rename to refilc_mobile_ui/lib/screens/summary/pages/allsum_page.dart
index b14a215..58edbe1 100644
--- a/filcnaplo_mobile_ui/lib/screens/summary/pages/allsum_page.dart
+++ b/refilc_mobile_ui/lib/screens/summary/pages/allsum_page.dart
@@ -1,11 +1,11 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/homework_provider.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart b/refilc_mobile_ui/lib/screens/summary/pages/grades_page.dart
similarity index 95%
rename from filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart
rename to refilc_mobile_ui/lib/screens/summary/pages/grades_page.dart
index 5b75cbb..a5b65a5 100644
--- a/filcnaplo_mobile_ui/lib/screens/summary/pages/grades_page.dart
+++ b/refilc_mobile_ui/lib/screens/summary/pages/grades_page.dart
@@ -1,14 +1,14 @@
 import 'dart:math';
 
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 import 'package:auto_size_text/auto_size_text.dart';
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/pages/lessons_page.dart b/refilc_mobile_ui/lib/screens/summary/pages/lessons_page.dart
similarity index 92%
rename from filcnaplo_mobile_ui/lib/screens/summary/pages/lessons_page.dart
rename to refilc_mobile_ui/lib/screens/summary/pages/lessons_page.dart
index cd7c248..eecf969 100644
--- a/filcnaplo_mobile_ui/lib/screens/summary/pages/lessons_page.dart
+++ b/refilc_mobile_ui/lib/screens/summary/pages/lessons_page.dart
@@ -1,16 +1,16 @@
 import 'dart:math';
 
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/absence.dart';
-import 'package:filcnaplo_kreta_api/models/lesson.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/week.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/absence.dart';
+import 'package:refilc_kreta_api/models/lesson.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/week.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/pages/personality_page.dart b/refilc_mobile_ui/lib/screens/summary/pages/personality_page.dart
similarity index 92%
rename from filcnaplo_mobile_ui/lib/screens/summary/pages/personality_page.dart
rename to refilc_mobile_ui/lib/screens/summary/pages/personality_page.dart
index 7702c7a..3fae236 100644
--- a/filcnaplo_mobile_ui/lib/screens/summary/pages/personality_page.dart
+++ b/refilc_mobile_ui/lib/screens/summary/pages/personality_page.dart
@@ -1,9 +1,9 @@
 import 'dart:io';
 
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/personality_card/empty_card.dart';
-import 'package:filcnaplo_mobile_ui/common/personality_card/personality_card.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc_mobile_ui/common/personality_card/empty_card.dart';
+import 'package:refilc_mobile_ui/common/personality_card/personality_card.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
 import 'package:provider/provider.dart';
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/pages/start_page.dart b/refilc_mobile_ui/lib/screens/summary/pages/start_page.dart
similarity index 89%
rename from filcnaplo_mobile_ui/lib/screens/summary/pages/start_page.dart
rename to refilc_mobile_ui/lib/screens/summary/pages/start_page.dart
index 90e807c..130361a 100644
--- a/filcnaplo_mobile_ui/lib/screens/summary/pages/start_page.dart
+++ b/refilc_mobile_ui/lib/screens/summary/pages/start_page.dart
@@ -1,8 +1,8 @@
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.dart';
-import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.dart';
+import 'package:refilc_mobile_ui/screens/summary/summary_screen.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
 import 'package:provider/provider.dart';
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart b/refilc_mobile_ui/lib/screens/summary/summary_screen.dart
similarity index 98%
rename from filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart
rename to refilc_mobile_ui/lib/screens/summary/summary_screen.dart
index 7798761..87df131 100644
--- a/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.dart
+++ b/refilc_mobile_ui/lib/screens/summary/summary_screen.dart
@@ -1,6 +1,6 @@
 import 'package:confetti/confetti.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
diff --git a/filcnaplo_mobile_ui/lib/screens/summary/summary_screen.i18n.dart b/refilc_mobile_ui/lib/screens/summary/summary_screen.i18n.dart
similarity index 100%
rename from filcnaplo_mobile_ui/lib/screens/summary/summary_screen.i18n.dart
rename to refilc_mobile_ui/lib/screens/summary/summary_screen.i18n.dart
diff --git a/filcnaplo_mobile_ui/pubspec.yaml b/refilc_mobile_ui/pubspec.yaml
similarity index 81%
rename from filcnaplo_mobile_ui/pubspec.yaml
rename to refilc_mobile_ui/pubspec.yaml
index fdfc57d..5e83b49 100644
--- a/filcnaplo_mobile_ui/pubspec.yaml
+++ b/refilc_mobile_ui/pubspec.yaml
@@ -1,4 +1,4 @@
-name: filcnaplo_mobile_ui
+name: refilc_mobile_ui
 publish_to: "none"
 
 environment:
@@ -9,13 +9,13 @@ dependencies:
     sdk: flutter
   cupertino_icons: ^1.0.2
 
-  # Filcnaplo main dep
-  filcnaplo:
-    path: ../filcnaplo/
-  filcnaplo_kreta_api:
-    path: ../filcnaplo_kreta_api/
-  filcnaplo_premium:
-    path: ../filcnaplo_premium/
+  # refilc main dep
+  refilc:
+    path: ../refilc/
+  refilc_kreta_api:
+    path: ../refilc_kreta_api/
+  refilc_premium:
+    path: ../refilc_premium/
 
   flutter_feather_icons: ^2.0.0+1
   provider: ^5.0.0
diff --git a/filcnaplo_premium/README.md b/refilc_premium/README.md
similarity index 96%
rename from filcnaplo_premium/README.md
rename to refilc_premium/README.md
index c7f8a35..979e950 100644
--- a/filcnaplo_premium/README.md
+++ b/refilc_premium/README.md
@@ -1,3 +1,3 @@
-# Premium ✨
-
-A collection of features only accessible for premium subscribers.
+# Premium ✨
+
+A collection of features only accessible for premium subscribers.
diff --git a/refilc_premium/analysis_options.yaml b/refilc_premium/analysis_options.yaml
new file mode 100644
index 0000000..fd16f92
--- /dev/null
+++ b/refilc_premium/analysis_options.yaml
@@ -0,0 +1,28 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/filcnaplo_premium/lib/api/auth.dart b/refilc_premium/lib/api/auth.dart
similarity index 92%
rename from filcnaplo_premium/lib/api/auth.dart
rename to refilc_premium/lib/api/auth.dart
index 3408919..e971134 100644
--- a/filcnaplo_premium/lib/api/auth.dart
+++ b/refilc_premium/lib/api/auth.dart
@@ -1,124 +1,124 @@
-import 'dart:async';
-import 'dart:developer';
-import 'dart:io';
-
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_premium/models/premium_scopes.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/services.dart';
-import 'package:home_widget/home_widget.dart';
-
-class PremiumAuth {
-  final SettingsProvider _settings;
-
-  PremiumAuth({required SettingsProvider settings}) : _settings = settings;
-
-  initAuth() {
-    finishAuth("igen");
-    // try {
-    //   _sub ??= uriLinkStream.listen(
-    //     (Uri? uri) {
-    //       if (uri != null) {
-    //         final accessToken = uri.queryParameters['access_token'];
-    //         if (accessToken != null) {
-    //           finishAuth(accessToken);
-    //         }
-    //       }
-    //     },
-    //     onError: (err) {
-    //       log("ERROR: initAuth: $err");
-    //     },
-    //   );
-
-    //   launchUrl(
-    //     Uri.parse("https://api.filcnaplo.hu/oauth"),
-    //     mode: LaunchMode.externalApplication,
-    //   );
-    // } catch (err, sta) {
-    //   log("ERROR: initAuth: $err\n$sta");
-    // }
-  }
-
-  Future<bool> finishAuth(String accessToken) async {
-    try {
-      // final res = await http.get(Uri.parse("${FilcAPI.premiumScopesApi}?access_token=${Uri.encodeComponent(accessToken)}"));
-      // final scopes = ((jsonDecode(res.body) as Map)["scopes"] as List).cast<String>();
-      // log("[INFO] Premium auth finish: ${scopes.join(',')}");
-      await _settings.update(premiumAccessToken: accessToken);
-      final result = await refreshAuth();
-      if (Platform.isAndroid) updateWidget();
-      return result;
-    } catch (err, sta) {
-      log("[ERROR] Premium auth failed: $err\n$sta");
-    }
-
-    await _settings.update(premiumAccessToken: "", premiumScopes: []);
-    if (Platform.isAndroid) updateWidget();
-    return false;
-  }
-
-  Future<bool?> updateWidget() async {
-    try {
-      return HomeWidget.updateWidget(name: 'widget_timetable.WidgetTimetable');
-    } on PlatformException catch (exception) {
-      if (kDebugMode) {
-        print('Error Updating Widget After Auth. $exception');
-      }
-    }
-    return false;
-  }
-
-  Future<bool> refreshAuth({bool removePremium = false}) async {
-    await _settings.update(
-      premiumAccessToken: "igen",
-      premiumScopes: [PremiumScopes.all],
-      premiumLogin: "igen",
-    );
-    return true;
-    //if (!removePremium) {
-    //if (_settings.premiumAccessToken == "") {
-    //  await _settings.update(premiumScopes: [], premiumLogin: "");
-    //  return false;
-    //}
-
-    // Skip premium check when disconnected
-    //try {
-    //  final status = await InternetAddress.lookup('github.com');
-    //  if (status.isEmpty) return false;
-    //} on SocketException catch (_) {
-    //  return false;
-    //}
-
-    //for (int tries = 0; tries < 3; tries++) {
-    //  try {
-    //    final res = await http.post(Uri.parse(FilcAPI.premiumApi), body: {
-    //      "access_token": _settings.premiumAccessToken,
-    //    });
-//
-    //    if (res.body == "") throw "empty body";
-
-    //    final premium = PremiumResult.fromJson(jsonDecode(res.body) as Map);
-    // Activation succeeded
-    //    log("[INFO] Premium activated: ${premium.scopes.join(',')}");
-    //    await _settings.update(
-    //      premiumAccessToken: premium.accessToken,
-    //      premiumScopes: premium.scopes,
-    //      premiumLogin: premium.login,
-    //    );
-    //    return true;
-    //  } catch (err, sta) {
-    //    log("[ERROR] Premium activation failed: $err\n$sta");
-    //  }
-
-    //  await Future.delayed(const Duration(seconds: 1));
-    //
-    //}
-
-    // Activation failed
-    //await _settings.update(
-    //    premiumAccessToken: "igen",
-    //    premiumScopes: [PremiumScopes.all],
-    //    premiumLogin: "igen");
-    //return false;
-  }
-}
+import 'dart:async';
+import 'dart:developer';
+import 'dart:io';
+
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/services.dart';
+import 'package:home_widget/home_widget.dart';
+
+class PremiumAuth {
+  final SettingsProvider _settings;
+
+  PremiumAuth({required SettingsProvider settings}) : _settings = settings;
+
+  initAuth() {
+    finishAuth("igen");
+    // try {
+    //   _sub ??= uriLinkStream.listen(
+    //     (Uri? uri) {
+    //       if (uri != null) {
+    //         final accessToken = uri.queryParameters['access_token'];
+    //         if (accessToken != null) {
+    //           finishAuth(accessToken);
+    //         }
+    //       }
+    //     },
+    //     onError: (err) {
+    //       log("ERROR: initAuth: $err");
+    //     },
+    //   );
+
+    //   launchUrl(
+    //     Uri.parse("https://api.refilc.hu/oauth"),
+    //     mode: LaunchMode.externalApplication,
+    //   );
+    // } catch (err, sta) {
+    //   log("ERROR: initAuth: $err\n$sta");
+    // }
+  }
+
+  Future<bool> finishAuth(String accessToken) async {
+    try {
+      // final res = await http.get(Uri.parse("${FilcAPI.premiumScopesApi}?access_token=${Uri.encodeComponent(accessToken)}"));
+      // final scopes = ((jsonDecode(res.body) as Map)["scopes"] as List).cast<String>();
+      // log("[INFO] Premium auth finish: ${scopes.join(',')}");
+      await _settings.update(premiumAccessToken: accessToken);
+      final result = await refreshAuth();
+      if (Platform.isAndroid) updateWidget();
+      return result;
+    } catch (err, sta) {
+      log("[ERROR] Premium auth failed: $err\n$sta");
+    }
+
+    await _settings.update(premiumAccessToken: "", premiumScopes: []);
+    if (Platform.isAndroid) updateWidget();
+    return false;
+  }
+
+  Future<bool?> updateWidget() async {
+    try {
+      return HomeWidget.updateWidget(name: 'widget_timetable.WidgetTimetable');
+    } on PlatformException catch (exception) {
+      if (kDebugMode) {
+        print('Error Updating Widget After Auth. $exception');
+      }
+    }
+    return false;
+  }
+
+  Future<bool> refreshAuth({bool removePremium = false}) async {
+    await _settings.update(
+      premiumAccessToken: "igen",
+      premiumScopes: [PremiumScopes.all],
+      premiumLogin: "igen",
+    );
+    return true;
+    //if (!removePremium) {
+    //if (_settings.premiumAccessToken == "") {
+    //  await _settings.update(premiumScopes: [], premiumLogin: "");
+    //  return false;
+    //}
+
+    // Skip premium check when disconnected
+    //try {
+    //  final status = await InternetAddress.lookup('github.com');
+    //  if (status.isEmpty) return false;
+    //} on SocketException catch (_) {
+    //  return false;
+    //}
+
+    //for (int tries = 0; tries < 3; tries++) {
+    //  try {
+    //    final res = await http.post(Uri.parse(FilcAPI.premiumApi), body: {
+    //      "access_token": _settings.premiumAccessToken,
+    //    });
+//
+    //    if (res.body == "") throw "empty body";
+
+    //    final premium = PremiumResult.fromJson(jsonDecode(res.body) as Map);
+    // Activation succeeded
+    //    log("[INFO] Premium activated: ${premium.scopes.join(',')}");
+    //    await _settings.update(
+    //      premiumAccessToken: premium.accessToken,
+    //      premiumScopes: premium.scopes,
+    //      premiumLogin: premium.login,
+    //    );
+    //    return true;
+    //  } catch (err, sta) {
+    //    log("[ERROR] Premium activation failed: $err\n$sta");
+    //  }
+
+    //  await Future.delayed(const Duration(seconds: 1));
+    //
+    //}
+
+    // Activation failed
+    //await _settings.update(
+    //    premiumAccessToken: "igen",
+    //    premiumScopes: [PremiumScopes.all],
+    //    premiumLogin: "igen");
+    //return false;
+  }
+}
diff --git a/filcnaplo_premium/lib/models/premium_result.dart b/refilc_premium/lib/models/premium_result.dart
similarity index 84%
rename from filcnaplo_premium/lib/models/premium_result.dart
rename to refilc_premium/lib/models/premium_result.dart
index 41270ea..74b35a9 100644
--- a/filcnaplo_premium/lib/models/premium_result.dart
+++ b/refilc_premium/lib/models/premium_result.dart
@@ -1,21 +1,21 @@
-import 'package:filcnaplo_premium/models/premium_scopes.dart';
-
-class PremiumResult {
-  final String accessToken;
-  final List<String> scopes;
-  final String login;
-
-  PremiumResult({
-    required this.accessToken,
-    required this.scopes,
-    required this.login,
-  });
-
-  factory PremiumResult.fromJson(Map json) {
-    return PremiumResult(
-      accessToken: json["access_token"] ?? "igen",
-      scopes: (json["scopes"] ?? [PremiumScopes.all]).cast<String>(),
-      login: json["login"] ?? "igen",
-    );
-  }
-}
+import 'package:refilc_premium/models/premium_scopes.dart';
+
+class PremiumResult {
+  final String accessToken;
+  final List<String> scopes;
+  final String login;
+
+  PremiumResult({
+    required this.accessToken,
+    required this.scopes,
+    required this.login,
+  });
+
+  factory PremiumResult.fromJson(Map json) {
+    return PremiumResult(
+      accessToken: json["access_token"] ?? "igen",
+      scopes: (json["scopes"] ?? [PremiumScopes.all]).cast<String>(),
+      login: json["login"] ?? "igen",
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/models/premium_scopes.dart b/refilc_premium/lib/models/premium_scopes.dart
similarity index 96%
rename from filcnaplo_premium/lib/models/premium_scopes.dart
rename to refilc_premium/lib/models/premium_scopes.dart
index f793723..09ab3d2 100644
--- a/filcnaplo_premium/lib/models/premium_scopes.dart
+++ b/refilc_premium/lib/models/premium_scopes.dart
@@ -1,33 +1,33 @@
-class PremiumScopes {
-  /// VIP
-  static const all = "filc.premium.*";
-
-  /// Kupak
-
-  /// Custom nickname
-  static const nickname = "filc.premium.NICKNAME";
-
-  /// Advanced grade statistics
-  static const gradeStats = "filc.premium.GRADE_STATS";
-
-  /// Advanced theme customization
-  static const customColors = "filc.premium.CUSTOM_COLORS";
-
-  /// Icon pack customization for subjects
-  static const customIcons = "filc.premium.CUSTOM_ICONS";
-
-  /// Modify subject names
-  static const renameSubjects = "filc.premium.RENAME_SUBJECTS";
-  static const renameTeachers = "filc.premium.RENAME_TEACHERS";
-
-  /// Tinta
-
-  /// Timetable homescreen widget
-  static const timetableWidget = "filc.premium.TIMETALBE_WIDGET";
-
-  /// Goal Planner
-  static const goalPlanner = "filc.premium.GOAL_PLANNER";
-
-  /// Fullscreen weekly timetable view
-  static const fsTimetable = "filc.premium.FS_TIMETABLE";
-}
+class PremiumScopes {
+  /// VIP
+  static const all = "filc.premium.*";
+
+  /// Kupak
+
+  /// Custom nickname
+  static const nickname = "filc.premium.NICKNAME";
+
+  /// Advanced grade statistics
+  static const gradeStats = "filc.premium.GRADE_STATS";
+
+  /// Advanced theme customization
+  static const customColors = "filc.premium.CUSTOM_COLORS";
+
+  /// Icon pack customization for subjects
+  static const customIcons = "filc.premium.CUSTOM_ICONS";
+
+  /// Modify subject names
+  static const renameSubjects = "filc.premium.RENAME_SUBJECTS";
+  static const renameTeachers = "filc.premium.RENAME_TEACHERS";
+
+  /// Tinta
+
+  /// Timetable homescreen widget
+  static const timetableWidget = "filc.premium.TIMETALBE_WIDGET";
+
+  /// Goal Planner
+  static const goalPlanner = "filc.premium.GOAL_PLANNER";
+
+  /// Fullscreen weekly timetable view
+  static const fsTimetable = "filc.premium.FS_TIMETABLE";
+}
diff --git a/filcnaplo_premium/lib/providers/goal_provider.dart b/refilc_premium/lib/providers/goal_provider.dart
similarity index 88%
rename from filcnaplo_premium/lib/providers/goal_provider.dart
rename to refilc_premium/lib/providers/goal_provider.dart
index 86b981d..c4c0f1e 100644
--- a/filcnaplo_premium/lib/providers/goal_provider.dart
+++ b/refilc_premium/lib/providers/goal_provider.dart
@@ -1,7 +1,7 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
 import 'package:flutter/widgets.dart';
 
 class GoalProvider extends ChangeNotifier {
diff --git a/filcnaplo_premium/lib/providers/premium_provider.dart b/refilc_premium/lib/providers/premium_provider.dart
similarity index 85%
rename from filcnaplo_premium/lib/providers/premium_provider.dart
rename to refilc_premium/lib/providers/premium_provider.dart
index 2f5fdfd..9565206 100644
--- a/filcnaplo_premium/lib/providers/premium_provider.dart
+++ b/refilc_premium/lib/providers/premium_provider.dart
@@ -1,27 +1,27 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_premium/api/auth.dart';
-import 'package:flutter/widgets.dart';
-
-class PremiumProvider extends ChangeNotifier {
-  final SettingsProvider _settings;
-  List<String> get scopes => _settings.premiumScopes;
-  bool hasScope(String scope) => true;
-  String get accessToken => _settings.premiumAccessToken;
-  String get login => _settings.premiumLogin;
-  bool get hasPremium => true;
-
-  late final PremiumAuth _auth;
-  PremiumAuth get auth => _auth;
-
-  PremiumProvider({required SettingsProvider settings}) : _settings = settings {
-    _auth = PremiumAuth(settings: _settings);
-    _settings.addListener(() {
-      notifyListeners();
-    });
-  }
-
-  Future<void> activate({bool removePremium = false}) async {
-    await _auth.refreshAuth(removePremium: removePremium);
-    notifyListeners();
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_premium/api/auth.dart';
+import 'package:flutter/widgets.dart';
+
+class PremiumProvider extends ChangeNotifier {
+  final SettingsProvider _settings;
+  List<String> get scopes => _settings.premiumScopes;
+  bool hasScope(String scope) => true;
+  String get accessToken => _settings.premiumAccessToken;
+  String get login => _settings.premiumLogin;
+  bool get hasPremium => true;
+
+  late final PremiumAuth _auth;
+  PremiumAuth get auth => _auth;
+
+  PremiumProvider({required SettingsProvider settings}) : _settings = settings {
+    _auth = PremiumAuth(settings: _settings);
+    _settings.addListener(() {
+      notifyListeners();
+    });
+  }
+
+  Future<void> activate({bool removePremium = false}) async {
+    await _auth.refreshAuth(removePremium: removePremium);
+    notifyListeners();
+  }
+}
diff --git a/filcnaplo_premium/lib/providers/share_provider.dart b/refilc_premium/lib/providers/share_provider.dart
similarity index 85%
rename from filcnaplo_premium/lib/providers/share_provider.dart
rename to refilc_premium/lib/providers/share_provider.dart
index 8407e43..edc7162 100644
--- a/filcnaplo_premium/lib/providers/share_provider.dart
+++ b/refilc_premium/lib/providers/share_provider.dart
@@ -1,8 +1,8 @@
-import 'package:filcnaplo/api/client.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/shared_theme.dart';
-// import 'package:filcnaplo/models/shared_theme.dart';
+import 'package:refilc/api/client.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/shared_theme.dart';
+// import 'package:refilc/models/shared_theme.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:provider/provider.dart';
 import 'package:uuid/uuid.dart';
diff --git a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/block_picker.dart b/refilc_premium/lib/ui/mobile/flutter_colorpicker/block_picker.dart
similarity index 75%
rename from filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/block_picker.dart
rename to refilc_premium/lib/ui/mobile/flutter_colorpicker/block_picker.dart
index dbf27f8..3dee3ad 100644
--- a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/block_picker.dart
+++ b/refilc_premium/lib/ui/mobile/flutter_colorpicker/block_picker.dart
@@ -1,137 +1,151 @@
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-
-/// Blocky Color Picker
-
-library block_colorpicker;
-
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/theme/colors/accent.dart';
-import 'utils.dart';
-
-/// Child widget for layout builder.
-typedef PickerItem = Widget Function(Color color);
-
-/// Customize the layout.
-typedef PickerLayoutBuilder = Widget Function(BuildContext context, List<Color> colors, PickerItem child);
-
-/// Customize the item shape.
-typedef PickerItemBuilder = Widget Function(Color color, bool isCurrentColor, void Function() changeColor);
-
-// Provide a list of colors for block color picker.
-// const List<Color> _defaultColors = [
-//   Colors.red,
-//   Colors.pink,
-//   Colors.purple,
-//   Colors.deepPurple,
-//   Colors.indigo,
-//   Colors.blue,
-//   Colors.lightBlue,
-//   Colors.cyan,
-//   Colors.teal,
-//   Colors.green,
-//   Colors.lightGreen,
-//   Colors.lime,
-//   Colors.yellow,
-//   Colors.amber,
-//   Colors.orange,
-//   Colors.deepOrange,
-//   Colors.brown,
-//   Colors.grey,
-//   Colors.blueGrey,
-//   Colors.black,
-// ];
-
-// Provide a layout for [BlockPicker].
-Widget _defaultLayoutBuilder(BuildContext context, List<Color> colors, PickerItem child) {
-  Orientation orientation = MediaQuery.of(context).orientation;
-
-  return SizedBox(
-    width: 300,
-    height: orientation == Orientation.portrait ? 360 : 200,
-    child: GridView.count(
-      crossAxisCount: orientation == Orientation.portrait ? 4 : 6,
-      crossAxisSpacing: 5,
-      mainAxisSpacing: 5,
-      children: [for (Color color in colors) child(color)],
-    ),
-  );
-}
-
-// Provide a shape for [BlockPicker].
-Widget _defaultItemBuilder(Color color, bool isCurrentColor, void Function() changeColor) {
-  return Container(
-    margin: const EdgeInsets.all(7),
-    decoration: BoxDecoration(
-      shape: BoxShape.circle,
-      color: color,
-      boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: const Offset(1, 2), blurRadius: 5)],
-    ),
-    child: Material(
-      color: Colors.transparent,
-      child: InkWell(
-        onTap: changeColor,
-        borderRadius: BorderRadius.circular(50),
-        child: AnimatedOpacity(
-          duration: const Duration(milliseconds: 210),
-          opacity: isCurrentColor ? 1 : 0,
-          child: Icon(Icons.done, color: useWhiteForeground(color) ? Colors.white : Colors.black),
-        ),
-      ),
-    ),
-  );
-}
-
-// The blocky color picker you can alter the layout and shape.
-class BlockPicker extends StatefulWidget {
-  BlockPicker({
-    Key? key,
-    required this.pickerColor,
-    required this.onColorChanged,
-    this.useInShowDialog = true,
-    this.layoutBuilder = _defaultLayoutBuilder,
-    this.itemBuilder = _defaultItemBuilder,
-  }) : super(key: key);
-
-  final Color? pickerColor;
-  final ValueChanged<Color> onColorChanged;
-  final List<Color> availableColors = accentColorMap.values.toList();
-  final bool useInShowDialog;
-  final PickerLayoutBuilder layoutBuilder;
-  final PickerItemBuilder itemBuilder;
-
-  @override
-  State<StatefulWidget> createState() => _BlockPickerState();
-}
-
-class _BlockPickerState extends State<BlockPicker> {
-  Color? _currentColor;
-
-  @override
-  void initState() {
-    _currentColor = widget.pickerColor;
-    super.initState();
-  }
-
-  void changeColor(Color color) {
-    setState(() => _currentColor = color);
-    widget.onColorChanged(color);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return widget.layoutBuilder(
-      context,
-      widget.availableColors,
-      (Color color) => widget.itemBuilder(
-        color,
-        (_currentColor != null && (widget.useInShowDialog ? true : widget.pickerColor != null))
-            ? (_currentColor?.value == color.value) && (widget.useInShowDialog ? true : widget.pickerColor?.value == color.value)
-            : false,
-        () => changeColor(color),
-      ),
-    );
-  }
-}
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+
+/// Blocky Color Picker
+
+library block_colorpicker;
+
+import 'package:flutter/material.dart';
+import 'package:refilc/theme/colors/accent.dart';
+import 'utils.dart';
+
+/// Child widget for layout builder.
+typedef PickerItem = Widget Function(Color color);
+
+/// Customize the layout.
+typedef PickerLayoutBuilder = Widget Function(
+    BuildContext context, List<Color> colors, PickerItem child);
+
+/// Customize the item shape.
+typedef PickerItemBuilder = Widget Function(
+    Color color, bool isCurrentColor, void Function() changeColor);
+
+// Provide a list of colors for block color picker.
+// const List<Color> _defaultColors = [
+//   Colors.red,
+//   Colors.pink,
+//   Colors.purple,
+//   Colors.deepPurple,
+//   Colors.indigo,
+//   Colors.blue,
+//   Colors.lightBlue,
+//   Colors.cyan,
+//   Colors.teal,
+//   Colors.green,
+//   Colors.lightGreen,
+//   Colors.lime,
+//   Colors.yellow,
+//   Colors.amber,
+//   Colors.orange,
+//   Colors.deepOrange,
+//   Colors.brown,
+//   Colors.grey,
+//   Colors.blueGrey,
+//   Colors.black,
+// ];
+
+// Provide a layout for [BlockPicker].
+Widget _defaultLayoutBuilder(
+    BuildContext context, List<Color> colors, PickerItem child) {
+  Orientation orientation = MediaQuery.of(context).orientation;
+
+  return SizedBox(
+    width: 300,
+    height: orientation == Orientation.portrait ? 360 : 200,
+    child: GridView.count(
+      crossAxisCount: orientation == Orientation.portrait ? 4 : 6,
+      crossAxisSpacing: 5,
+      mainAxisSpacing: 5,
+      children: [for (Color color in colors) child(color)],
+    ),
+  );
+}
+
+// Provide a shape for [BlockPicker].
+Widget _defaultItemBuilder(
+    Color color, bool isCurrentColor, void Function() changeColor) {
+  return Container(
+    margin: const EdgeInsets.all(7),
+    decoration: BoxDecoration(
+      shape: BoxShape.circle,
+      color: color,
+      boxShadow: [
+        BoxShadow(
+            color: color.withOpacity(0.8),
+            offset: const Offset(1, 2),
+            blurRadius: 5)
+      ],
+    ),
+    child: Material(
+      color: Colors.transparent,
+      child: InkWell(
+        onTap: changeColor,
+        borderRadius: BorderRadius.circular(50),
+        child: AnimatedOpacity(
+          duration: const Duration(milliseconds: 210),
+          opacity: isCurrentColor ? 1 : 0,
+          child: Icon(Icons.done,
+              color: useWhiteForeground(color) ? Colors.white : Colors.black),
+        ),
+      ),
+    ),
+  );
+}
+
+// The blocky color picker you can alter the layout and shape.
+class BlockPicker extends StatefulWidget {
+  BlockPicker({
+    Key? key,
+    required this.pickerColor,
+    required this.onColorChanged,
+    this.useInShowDialog = true,
+    this.layoutBuilder = _defaultLayoutBuilder,
+    this.itemBuilder = _defaultItemBuilder,
+  }) : super(key: key);
+
+  final Color? pickerColor;
+  final ValueChanged<Color> onColorChanged;
+  final List<Color> availableColors = accentColorMap.values.toList();
+  final bool useInShowDialog;
+  final PickerLayoutBuilder layoutBuilder;
+  final PickerItemBuilder itemBuilder;
+
+  @override
+  State<StatefulWidget> createState() => _BlockPickerState();
+}
+
+class _BlockPickerState extends State<BlockPicker> {
+  Color? _currentColor;
+
+  @override
+  void initState() {
+    _currentColor = widget.pickerColor;
+    super.initState();
+  }
+
+  void changeColor(Color color) {
+    setState(() => _currentColor = color);
+    widget.onColorChanged(color);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return widget.layoutBuilder(
+      context,
+      widget.availableColors,
+      (Color color) => widget.itemBuilder(
+        color,
+        (_currentColor != null &&
+                (widget.useInShowDialog ? true : widget.pickerColor != null))
+            ? (_currentColor?.value == color.value) &&
+                (widget.useInShowDialog
+                    ? true
+                    : widget.pickerColor?.value == color.value)
+            : false,
+        () => changeColor(color),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/colorpicker.dart b/refilc_premium/lib/ui/mobile/flutter_colorpicker/colorpicker.dart
similarity index 94%
rename from filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/colorpicker.dart
rename to refilc_premium/lib/ui/mobile/flutter_colorpicker/colorpicker.dart
index d10c6ca..e02a380 100644
--- a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/colorpicker.dart
+++ b/refilc_premium/lib/ui/mobile/flutter_colorpicker/colorpicker.dart
@@ -1,467 +1,467 @@
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-
-/// HSV(HSB)/HSL Color Picker example
-///
-/// You can create your own layout by importing `picker.dart`.
-
-library hsv_picker;
-
-import 'package:filcnaplo/models/shared_theme.dart';
-import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
-import 'package:filcnaplo_premium/providers/share_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/block_picker.dart';
-import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/palette.dart';
-import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/utils.dart';
-import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
-import 'package:filcnaplo_premium/ui/mobile/settings/theme.i18n.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:provider/provider.dart';
-
-class FilcColorPicker extends StatefulWidget {
-  const FilcColorPicker({
-    Key? key,
-    required this.colorMode,
-    required this.pickerColor,
-    required this.onColorChanged,
-    required this.onColorChangeEnd,
-    this.pickerHsvColor,
-    this.onHsvColorChanged,
-    this.paletteType = PaletteType.hsvWithHue,
-    this.enableAlpha = true,
-    @Deprecated('Use empty list in [labelTypes] to disable label.')
-    this.showLabel = true,
-    this.labelTypes = const [
-      ColorLabelType.rgb,
-      ColorLabelType.hsv,
-      ColorLabelType.hsl
-    ],
-    @Deprecated(
-        'Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.')
-    this.labelTextStyle,
-    this.displayThumbColor = false,
-    this.portraitOnly = false,
-    this.colorPickerWidth = 300.0,
-    this.pickerAreaHeightPercent = 1.0,
-    this.pickerAreaBorderRadius = const BorderRadius.all(Radius.zero),
-    this.hexInputBar = false,
-    this.hexInputController,
-    this.colorHistory,
-    this.onHistoryChanged,
-    required this.onThemeIdProvided,
-  }) : super(key: key);
-
-  final CustomColorMode colorMode;
-  final Color pickerColor;
-  final ValueChanged<Color> onColorChanged;
-  final void Function(Color color, {bool? adaptive}) onColorChangeEnd;
-  final HSVColor? pickerHsvColor;
-  final ValueChanged<HSVColor>? onHsvColorChanged;
-  final PaletteType paletteType;
-  final bool enableAlpha;
-  final bool showLabel;
-  final List<ColorLabelType> labelTypes;
-  final TextStyle? labelTextStyle;
-  final bool displayThumbColor;
-  final bool portraitOnly;
-  final double colorPickerWidth;
-  final double pickerAreaHeightPercent;
-  final BorderRadius pickerAreaBorderRadius;
-  final bool hexInputBar;
-  final TextEditingController? hexInputController;
-  final List<Color>? colorHistory;
-  final ValueChanged<List<Color>>? onHistoryChanged;
-  final void Function(SharedTheme theme) onThemeIdProvided;
-
-  @override
-  _FilcColorPickerState createState() => _FilcColorPickerState();
-}
-
-class _FilcColorPickerState extends State<FilcColorPicker> {
-  final idController = TextEditingController();
-
-  late final ShareProvider shareProvider;
-
-  HSVColor currentHsvColor = const HSVColor.fromAHSV(0.0, 0.0, 0.0, 0.0);
-  List<Color> colorHistory = [];
-  bool isAdvancedView = false;
-
-  @override
-  void initState() {
-    currentHsvColor = (widget.pickerHsvColor != null)
-        ? widget.pickerHsvColor as HSVColor
-        : HSVColor.fromColor(widget.pickerColor);
-    // If there's no initial text in `hexInputController`,
-    if (widget.hexInputController?.text.isEmpty == true) {
-      // set it to the current's color HEX value.
-      widget.hexInputController?.text = colorToHex(
-        currentHsvColor.toColor(),
-        enableAlpha: widget.enableAlpha,
-      );
-    }
-    // Listen to the text input, If there is an `hexInputController` provided.
-    widget.hexInputController?.addListener(colorPickerTextInputListener);
-    if (widget.colorHistory != null && widget.onHistoryChanged != null) {
-      colorHistory = widget.colorHistory ?? [];
-    }
-    shareProvider = Provider.of<ShareProvider>(context, listen: false);
-    super.initState();
-  }
-
-  @override
-  void didUpdateWidget(FilcColorPicker oldWidget) {
-    super.didUpdateWidget(oldWidget);
-    currentHsvColor = (widget.pickerHsvColor != null)
-        ? widget.pickerHsvColor as HSVColor
-        : HSVColor.fromColor(widget.pickerColor);
-  }
-
-  void colorPickerTextInputListener() {
-    // It can't be null really, since it's only listening if the controller
-    // is provided, but it may help to calm the Dart analyzer in the future.
-    if (widget.hexInputController == null) return;
-    // If a user is inserting/typing any text — try to get the color value from it,
-    // and interpret its transparency, dependent on the widget's settings.
-    final Color? color = colorFromHex(widget.hexInputController!.text,
-        enableAlpha: widget.enableAlpha);
-    // If it's the valid color:
-    if (color != null) {
-      // set it as the current color and
-      setState(() => currentHsvColor = HSVColor.fromColor(color));
-      // notify with a callback.
-      widget.onColorChanged(color);
-      if (widget.onHsvColorChanged != null) {
-        widget.onHsvColorChanged!(currentHsvColor);
-      }
-    }
-  }
-
-  @override
-  void dispose() {
-    widget.hexInputController?.removeListener(colorPickerTextInputListener);
-    super.dispose();
-  }
-
-  Widget colorPickerSlider(TrackType trackType) {
-    return ColorPickerSlider(
-      trackType,
-      currentHsvColor,
-      (HSVColor color) {
-        // Update text in `hexInputController` if provided.
-        widget.hexInputController?.text =
-            colorToHex(color.toColor(), enableAlpha: widget.enableAlpha);
-        setState(() => currentHsvColor = color);
-        widget.onColorChanged(currentHsvColor.toColor());
-        if (widget.onHsvColorChanged != null) {
-          widget.onHsvColorChanged!(currentHsvColor);
-        }
-      },
-      () => widget.onColorChangeEnd(currentHsvColor.toColor()),
-      (p) {
-        ScaffoldMessenger.of(context).clearSnackBars();
-        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-            content: Text(
-                "Move the ${p == 0 ? 'Saturation (second)' : 'Value (third)'} slider first.",
-                textAlign: TextAlign.center,
-                style: TextStyle(
-                    color: AppColors.of(context).text,
-                    fontWeight: FontWeight.w600)),
-            backgroundColor: AppColors.of(context).background));
-      },
-      displayThumbColor: widget.displayThumbColor,
-    );
-  }
-
-  void onColorChanging(HSVColor color) {
-    // Update text in `hexInputController` if provided.
-    widget.hexInputController?.text =
-        colorToHex(color.toColor(), enableAlpha: widget.enableAlpha);
-    setState(() => currentHsvColor = color);
-    widget.onColorChanged(currentHsvColor.toColor());
-    if (widget.onHsvColorChanged != null) {
-      widget.onHsvColorChanged!(currentHsvColor);
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (MediaQuery.of(context).orientation == Orientation.portrait ||
-        widget.portraitOnly) {
-      return Column(
-        children: [
-          if (widget.colorMode != CustomColorMode.theme &&
-              widget.colorMode != CustomColorMode.enterId)
-            Padding(
-              padding: const EdgeInsets.only(top: 8.0),
-              child: Column(
-                children: [
-                  Padding(
-                    padding: const EdgeInsets.only(left: 12.0, right: 12.0),
-                    child: SizedBox(
-                      height: 45.0,
-                      width: double.infinity,
-                      child: colorPickerSlider(TrackType.hue),
-                    ),
-                  ),
-                  Padding(
-                    padding: const EdgeInsets.only(left: 12.0, right: 12.0),
-                    child: SizedBox(
-                      height: 45.0,
-                      width: double.infinity,
-                      child: colorPickerSlider(TrackType.saturation),
-                    ),
-                  ),
-                  if (isAdvancedView)
-                    Padding(
-                      padding: const EdgeInsets.only(left: 12.0, right: 12.0),
-                      child: SizedBox(
-                        height: 45.0,
-                        width: double.infinity,
-                        child: colorPickerSlider(TrackType.value),
-                      ),
-                    ),
-                ],
-              ),
-            ),
-          if (isAdvancedView &&
-              widget.colorMode != CustomColorMode.theme &&
-              widget.colorMode != CustomColorMode.enterId)
-            Padding(
-              padding: const EdgeInsets.only(bottom: 6.0),
-              child: ColorPickerInput(
-                currentHsvColor.toColor(),
-                (Color color) {
-                  setState(() => currentHsvColor = HSVColor.fromColor(color));
-                  widget.onColorChanged(currentHsvColor.toColor());
-                  if (widget.onHsvColorChanged != null) {
-                    widget.onHsvColorChanged!(currentHsvColor);
-                  }
-                },
-                enableAlpha: false,
-                embeddedText: false,
-              ),
-            ),
-          if (widget.colorMode == CustomColorMode.enterId)
-            Padding(
-              padding:
-                  const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
-              child: Column(
-                children: [
-                  TextField(
-                    autocorrect: false,
-                    autofocus: true,
-                    onEditingComplete: () async {
-                      SharedTheme? theme = await shareProvider.getThemeById(
-                        context,
-                        id: idController.text.replaceAll(' ', ''),
-                      );
-
-                      if (theme != null) {
-                        widget.onThemeIdProvided(theme);
-                      } else {
-                        ScaffoldMessenger.of(context).showSnackBar(
-                          CustomSnackBar(
-                            content: Text("theme_not_found".i18n,
-                                style: const TextStyle(color: Colors.white)),
-                            backgroundColor: AppColors.of(context).red,
-                            context: context,
-                          ),
-                        );
-                      }
-                    },
-                    controller: idController,
-                    decoration: InputDecoration(
-                      hintText: 'theme_id'.i18n,
-                    ),
-                  ),
-                  // MaterialActionButton(
-                  //   child: Row(
-                  //     mainAxisSize: MainAxisSize.min,
-                  //     children: [
-                  //       Text('check_id'.i18n),
-                  //     ],
-                  //   ),
-                  //   backgroundColor: AppColors.of(context).filc,
-                  //   onPressed: () {},
-                  // ),
-                ],
-              ),
-            ),
-          if (widget.colorMode != CustomColorMode.enterId)
-            SizedBox(
-              height: 70 * (widget.colorMode == CustomColorMode.theme ? 2 : 1),
-              child: BlockPicker(
-                pickerColor: Colors.red,
-                layoutBuilder: (context, colors, child) {
-                  return GridView.count(
-                    shrinkWrap: true,
-                    crossAxisCount:
-                        widget.colorMode == CustomColorMode.theme ? 2 : 1,
-                    scrollDirection: Axis.horizontal,
-                    crossAxisSpacing: 15,
-                    physics: const BouncingScrollPhysics(),
-                    mainAxisSpacing: 15,
-                    padding: const EdgeInsets.symmetric(
-                        horizontal: 12.0, vertical: 8.0),
-                    children: List.generate(
-                        colors.toSet().length +
-                            (widget.colorMode == CustomColorMode.theme ? 1 : 0),
-                        (index) {
-                      if (widget.colorMode == CustomColorMode.theme) {
-                        if (index == 0) {
-                          return GestureDetector(
-                            onTap: () => widget.onColorChangeEnd(
-                                Colors.transparent,
-                                adaptive: true),
-                            child: ColorIndicator(
-                                HSVColor.fromColor(
-                                    const Color.fromARGB(255, 255, 238, 177)),
-                                icon: CupertinoIcons.wand_stars,
-                                currentHsvColor: currentHsvColor,
-                                width: 30,
-                                height: 30,
-                                adaptive: true),
-                          );
-                        }
-                        index--;
-                      }
-                      return GestureDetector(
-                        onTap: () => widget.onColorChangeEnd(colors[index]),
-                        child: ColorIndicator(HSVColor.fromColor(colors[index]),
-                            currentHsvColor: currentHsvColor,
-                            width: 30,
-                            height: 30),
-                      );
-                    }),
-                  );
-                },
-                onColorChanged: (c) => {},
-              ),
-            ),
-          if (widget.colorMode != CustomColorMode.theme &&
-              widget.colorMode != CustomColorMode.enterId)
-            Material(
-              color: Colors.transparent,
-              child: InkWell(
-                customBorder: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(20),
-                ),
-                onTap: () => setState(() {
-                  isAdvancedView = !isAdvancedView;
-                }),
-                child: Padding(
-                  padding:
-                      const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
-                  child: Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    mainAxisSize: MainAxisSize.min,
-                    children: [
-                      Switch(
-                        onChanged: (v) => setState(() => isAdvancedView = v),
-                        value: isAdvancedView,
-                      ),
-                      const SizedBox(width: 12.0),
-                      Text(
-                        "advanced".i18n,
-                        style: TextStyle(
-                          fontWeight: FontWeight.w600,
-                          fontSize: 16.0,
-                          color: AppColors.of(context)
-                              .text
-                              .withOpacity(isAdvancedView ? 1.0 : .5),
-                        ),
-                      ),
-                    ],
-                  ),
-                ),
-              ),
-            ),
-        ],
-      );
-    } else {
-      return Row(
-        children: [
-          //SizedBox(width: widget.colorPickerWidth, height: widget.colorPickerWidth * widget.pickerAreaHeightPercent, child: colorPicker()),
-          Column(
-            children: [
-              Row(
-                children: <Widget>[
-                  const SizedBox(width: 20.0),
-                  GestureDetector(
-                    onTap: () => setState(() {
-                      if (widget.onHistoryChanged != null &&
-                          !colorHistory.contains(currentHsvColor.toColor())) {
-                        colorHistory.add(currentHsvColor.toColor());
-                        widget.onHistoryChanged!(colorHistory);
-                      }
-                    }),
-                    child: ColorIndicator(currentHsvColor),
-                  ),
-                  Column(
-                    children: <Widget>[
-                      //SizedBox(height: 40.0, width: 260.0, child: sliderByPaletteType()),
-                      if (widget.enableAlpha)
-                        SizedBox(
-                            height: 40.0,
-                            width: 260.0,
-                            child: colorPickerSlider(TrackType.alpha)),
-                    ],
-                  ),
-                  const SizedBox(width: 10.0),
-                ],
-              ),
-              if (colorHistory.isNotEmpty)
-                SizedBox(
-                  width: widget.colorPickerWidth,
-                  height: 50,
-                  child: ListView(
-                      scrollDirection: Axis.horizontal,
-                      children: <Widget>[
-                        for (Color color in colorHistory)
-                          Padding(
-                            key: Key(color.hashCode.toString()),
-                            padding: const EdgeInsets.fromLTRB(15, 18, 0, 0),
-                            child: Center(
-                              child: GestureDetector(
-                                onTap: () =>
-                                    onColorChanging(HSVColor.fromColor(color)),
-                                onLongPress: () {
-                                  if (colorHistory.remove(color)) {
-                                    widget.onHistoryChanged!(colorHistory);
-                                    setState(() {});
-                                  }
-                                },
-                                child: ColorIndicator(HSVColor.fromColor(color),
-                                    width: 30, height: 30),
-                              ),
-                            ),
-                          ),
-                        const SizedBox(width: 15),
-                      ]),
-                ),
-              const SizedBox(height: 20.0),
-              if (widget.hexInputBar)
-                ColorPickerInput(
-                  currentHsvColor.toColor(),
-                  (Color color) {
-                    setState(() => currentHsvColor = HSVColor.fromColor(color));
-                    widget.onColorChanged(currentHsvColor.toColor());
-                    if (widget.onHsvColorChanged != null) {
-                      widget.onHsvColorChanged!(currentHsvColor);
-                    }
-                  },
-                  enableAlpha: widget.enableAlpha,
-                  embeddedText: false,
-                ),
-              const SizedBox(height: 5),
-            ],
-          ),
-        ],
-      );
-    }
-  }
-}
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+
+/// HSV(HSB)/HSL Color Picker example
+///
+/// You can create your own layout by importing `picker.dart`.
+
+library hsv_picker;
+
+import 'package:refilc/models/shared_theme.dart';
+import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
+import 'package:refilc_premium/providers/share_provider.dart';
+import 'package:refilc_premium/ui/mobile/flutter_colorpicker/block_picker.dart';
+import 'package:refilc_premium/ui/mobile/flutter_colorpicker/palette.dart';
+import 'package:refilc_premium/ui/mobile/flutter_colorpicker/utils.dart';
+import 'package:refilc_premium/ui/mobile/settings/theme.dart';
+import 'package:refilc_premium/ui/mobile/settings/theme.i18n.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:provider/provider.dart';
+
+class FilcColorPicker extends StatefulWidget {
+  const FilcColorPicker({
+    Key? key,
+    required this.colorMode,
+    required this.pickerColor,
+    required this.onColorChanged,
+    required this.onColorChangeEnd,
+    this.pickerHsvColor,
+    this.onHsvColorChanged,
+    this.paletteType = PaletteType.hsvWithHue,
+    this.enableAlpha = true,
+    @Deprecated('Use empty list in [labelTypes] to disable label.')
+    this.showLabel = true,
+    this.labelTypes = const [
+      ColorLabelType.rgb,
+      ColorLabelType.hsv,
+      ColorLabelType.hsl
+    ],
+    @Deprecated(
+        'Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.')
+    this.labelTextStyle,
+    this.displayThumbColor = false,
+    this.portraitOnly = false,
+    this.colorPickerWidth = 300.0,
+    this.pickerAreaHeightPercent = 1.0,
+    this.pickerAreaBorderRadius = const BorderRadius.all(Radius.zero),
+    this.hexInputBar = false,
+    this.hexInputController,
+    this.colorHistory,
+    this.onHistoryChanged,
+    required this.onThemeIdProvided,
+  }) : super(key: key);
+
+  final CustomColorMode colorMode;
+  final Color pickerColor;
+  final ValueChanged<Color> onColorChanged;
+  final void Function(Color color, {bool? adaptive}) onColorChangeEnd;
+  final HSVColor? pickerHsvColor;
+  final ValueChanged<HSVColor>? onHsvColorChanged;
+  final PaletteType paletteType;
+  final bool enableAlpha;
+  final bool showLabel;
+  final List<ColorLabelType> labelTypes;
+  final TextStyle? labelTextStyle;
+  final bool displayThumbColor;
+  final bool portraitOnly;
+  final double colorPickerWidth;
+  final double pickerAreaHeightPercent;
+  final BorderRadius pickerAreaBorderRadius;
+  final bool hexInputBar;
+  final TextEditingController? hexInputController;
+  final List<Color>? colorHistory;
+  final ValueChanged<List<Color>>? onHistoryChanged;
+  final void Function(SharedTheme theme) onThemeIdProvided;
+
+  @override
+  _FilcColorPickerState createState() => _FilcColorPickerState();
+}
+
+class _FilcColorPickerState extends State<FilcColorPicker> {
+  final idController = TextEditingController();
+
+  late final ShareProvider shareProvider;
+
+  HSVColor currentHsvColor = const HSVColor.fromAHSV(0.0, 0.0, 0.0, 0.0);
+  List<Color> colorHistory = [];
+  bool isAdvancedView = false;
+
+  @override
+  void initState() {
+    currentHsvColor = (widget.pickerHsvColor != null)
+        ? widget.pickerHsvColor as HSVColor
+        : HSVColor.fromColor(widget.pickerColor);
+    // If there's no initial text in `hexInputController`,
+    if (widget.hexInputController?.text.isEmpty == true) {
+      // set it to the current's color HEX value.
+      widget.hexInputController?.text = colorToHex(
+        currentHsvColor.toColor(),
+        enableAlpha: widget.enableAlpha,
+      );
+    }
+    // Listen to the text input, If there is an `hexInputController` provided.
+    widget.hexInputController?.addListener(colorPickerTextInputListener);
+    if (widget.colorHistory != null && widget.onHistoryChanged != null) {
+      colorHistory = widget.colorHistory ?? [];
+    }
+    shareProvider = Provider.of<ShareProvider>(context, listen: false);
+    super.initState();
+  }
+
+  @override
+  void didUpdateWidget(FilcColorPicker oldWidget) {
+    super.didUpdateWidget(oldWidget);
+    currentHsvColor = (widget.pickerHsvColor != null)
+        ? widget.pickerHsvColor as HSVColor
+        : HSVColor.fromColor(widget.pickerColor);
+  }
+
+  void colorPickerTextInputListener() {
+    // It can't be null really, since it's only listening if the controller
+    // is provided, but it may help to calm the Dart analyzer in the future.
+    if (widget.hexInputController == null) return;
+    // If a user is inserting/typing any text — try to get the color value from it,
+    // and interpret its transparency, dependent on the widget's settings.
+    final Color? color = colorFromHex(widget.hexInputController!.text,
+        enableAlpha: widget.enableAlpha);
+    // If it's the valid color:
+    if (color != null) {
+      // set it as the current color and
+      setState(() => currentHsvColor = HSVColor.fromColor(color));
+      // notify with a callback.
+      widget.onColorChanged(color);
+      if (widget.onHsvColorChanged != null) {
+        widget.onHsvColorChanged!(currentHsvColor);
+      }
+    }
+  }
+
+  @override
+  void dispose() {
+    widget.hexInputController?.removeListener(colorPickerTextInputListener);
+    super.dispose();
+  }
+
+  Widget colorPickerSlider(TrackType trackType) {
+    return ColorPickerSlider(
+      trackType,
+      currentHsvColor,
+      (HSVColor color) {
+        // Update text in `hexInputController` if provided.
+        widget.hexInputController?.text =
+            colorToHex(color.toColor(), enableAlpha: widget.enableAlpha);
+        setState(() => currentHsvColor = color);
+        widget.onColorChanged(currentHsvColor.toColor());
+        if (widget.onHsvColorChanged != null) {
+          widget.onHsvColorChanged!(currentHsvColor);
+        }
+      },
+      () => widget.onColorChangeEnd(currentHsvColor.toColor()),
+      (p) {
+        ScaffoldMessenger.of(context).clearSnackBars();
+        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+            content: Text(
+                "Move the ${p == 0 ? 'Saturation (second)' : 'Value (third)'} slider first.",
+                textAlign: TextAlign.center,
+                style: TextStyle(
+                    color: AppColors.of(context).text,
+                    fontWeight: FontWeight.w600)),
+            backgroundColor: AppColors.of(context).background));
+      },
+      displayThumbColor: widget.displayThumbColor,
+    );
+  }
+
+  void onColorChanging(HSVColor color) {
+    // Update text in `hexInputController` if provided.
+    widget.hexInputController?.text =
+        colorToHex(color.toColor(), enableAlpha: widget.enableAlpha);
+    setState(() => currentHsvColor = color);
+    widget.onColorChanged(currentHsvColor.toColor());
+    if (widget.onHsvColorChanged != null) {
+      widget.onHsvColorChanged!(currentHsvColor);
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (MediaQuery.of(context).orientation == Orientation.portrait ||
+        widget.portraitOnly) {
+      return Column(
+        children: [
+          if (widget.colorMode != CustomColorMode.theme &&
+              widget.colorMode != CustomColorMode.enterId)
+            Padding(
+              padding: const EdgeInsets.only(top: 8.0),
+              child: Column(
+                children: [
+                  Padding(
+                    padding: const EdgeInsets.only(left: 12.0, right: 12.0),
+                    child: SizedBox(
+                      height: 45.0,
+                      width: double.infinity,
+                      child: colorPickerSlider(TrackType.hue),
+                    ),
+                  ),
+                  Padding(
+                    padding: const EdgeInsets.only(left: 12.0, right: 12.0),
+                    child: SizedBox(
+                      height: 45.0,
+                      width: double.infinity,
+                      child: colorPickerSlider(TrackType.saturation),
+                    ),
+                  ),
+                  if (isAdvancedView)
+                    Padding(
+                      padding: const EdgeInsets.only(left: 12.0, right: 12.0),
+                      child: SizedBox(
+                        height: 45.0,
+                        width: double.infinity,
+                        child: colorPickerSlider(TrackType.value),
+                      ),
+                    ),
+                ],
+              ),
+            ),
+          if (isAdvancedView &&
+              widget.colorMode != CustomColorMode.theme &&
+              widget.colorMode != CustomColorMode.enterId)
+            Padding(
+              padding: const EdgeInsets.only(bottom: 6.0),
+              child: ColorPickerInput(
+                currentHsvColor.toColor(),
+                (Color color) {
+                  setState(() => currentHsvColor = HSVColor.fromColor(color));
+                  widget.onColorChanged(currentHsvColor.toColor());
+                  if (widget.onHsvColorChanged != null) {
+                    widget.onHsvColorChanged!(currentHsvColor);
+                  }
+                },
+                enableAlpha: false,
+                embeddedText: false,
+              ),
+            ),
+          if (widget.colorMode == CustomColorMode.enterId)
+            Padding(
+              padding:
+                  const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
+              child: Column(
+                children: [
+                  TextField(
+                    autocorrect: false,
+                    autofocus: true,
+                    onEditingComplete: () async {
+                      SharedTheme? theme = await shareProvider.getThemeById(
+                        context,
+                        id: idController.text.replaceAll(' ', ''),
+                      );
+
+                      if (theme != null) {
+                        widget.onThemeIdProvided(theme);
+                      } else {
+                        ScaffoldMessenger.of(context).showSnackBar(
+                          CustomSnackBar(
+                            content: Text("theme_not_found".i18n,
+                                style: const TextStyle(color: Colors.white)),
+                            backgroundColor: AppColors.of(context).red,
+                            context: context,
+                          ),
+                        );
+                      }
+                    },
+                    controller: idController,
+                    decoration: InputDecoration(
+                      hintText: 'theme_id'.i18n,
+                    ),
+                  ),
+                  // MaterialActionButton(
+                  //   child: Row(
+                  //     mainAxisSize: MainAxisSize.min,
+                  //     children: [
+                  //       Text('check_id'.i18n),
+                  //     ],
+                  //   ),
+                  //   backgroundColor: AppColors.of(context).filc,
+                  //   onPressed: () {},
+                  // ),
+                ],
+              ),
+            ),
+          if (widget.colorMode != CustomColorMode.enterId)
+            SizedBox(
+              height: 70 * (widget.colorMode == CustomColorMode.theme ? 2 : 1),
+              child: BlockPicker(
+                pickerColor: Colors.red,
+                layoutBuilder: (context, colors, child) {
+                  return GridView.count(
+                    shrinkWrap: true,
+                    crossAxisCount:
+                        widget.colorMode == CustomColorMode.theme ? 2 : 1,
+                    scrollDirection: Axis.horizontal,
+                    crossAxisSpacing: 15,
+                    physics: const BouncingScrollPhysics(),
+                    mainAxisSpacing: 15,
+                    padding: const EdgeInsets.symmetric(
+                        horizontal: 12.0, vertical: 8.0),
+                    children: List.generate(
+                        colors.toSet().length +
+                            (widget.colorMode == CustomColorMode.theme ? 1 : 0),
+                        (index) {
+                      if (widget.colorMode == CustomColorMode.theme) {
+                        if (index == 0) {
+                          return GestureDetector(
+                            onTap: () => widget.onColorChangeEnd(
+                                Colors.transparent,
+                                adaptive: true),
+                            child: ColorIndicator(
+                                HSVColor.fromColor(
+                                    const Color.fromARGB(255, 255, 238, 177)),
+                                icon: CupertinoIcons.wand_stars,
+                                currentHsvColor: currentHsvColor,
+                                width: 30,
+                                height: 30,
+                                adaptive: true),
+                          );
+                        }
+                        index--;
+                      }
+                      return GestureDetector(
+                        onTap: () => widget.onColorChangeEnd(colors[index]),
+                        child: ColorIndicator(HSVColor.fromColor(colors[index]),
+                            currentHsvColor: currentHsvColor,
+                            width: 30,
+                            height: 30),
+                      );
+                    }),
+                  );
+                },
+                onColorChanged: (c) => {},
+              ),
+            ),
+          if (widget.colorMode != CustomColorMode.theme &&
+              widget.colorMode != CustomColorMode.enterId)
+            Material(
+              color: Colors.transparent,
+              child: InkWell(
+                customBorder: RoundedRectangleBorder(
+                  borderRadius: BorderRadius.circular(20),
+                ),
+                onTap: () => setState(() {
+                  isAdvancedView = !isAdvancedView;
+                }),
+                child: Padding(
+                  padding:
+                      const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    mainAxisSize: MainAxisSize.min,
+                    children: [
+                      Switch(
+                        onChanged: (v) => setState(() => isAdvancedView = v),
+                        value: isAdvancedView,
+                      ),
+                      const SizedBox(width: 12.0),
+                      Text(
+                        "advanced".i18n,
+                        style: TextStyle(
+                          fontWeight: FontWeight.w600,
+                          fontSize: 16.0,
+                          color: AppColors.of(context)
+                              .text
+                              .withOpacity(isAdvancedView ? 1.0 : .5),
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+        ],
+      );
+    } else {
+      return Row(
+        children: [
+          //SizedBox(width: widget.colorPickerWidth, height: widget.colorPickerWidth * widget.pickerAreaHeightPercent, child: colorPicker()),
+          Column(
+            children: [
+              Row(
+                children: <Widget>[
+                  const SizedBox(width: 20.0),
+                  GestureDetector(
+                    onTap: () => setState(() {
+                      if (widget.onHistoryChanged != null &&
+                          !colorHistory.contains(currentHsvColor.toColor())) {
+                        colorHistory.add(currentHsvColor.toColor());
+                        widget.onHistoryChanged!(colorHistory);
+                      }
+                    }),
+                    child: ColorIndicator(currentHsvColor),
+                  ),
+                  Column(
+                    children: <Widget>[
+                      //SizedBox(height: 40.0, width: 260.0, child: sliderByPaletteType()),
+                      if (widget.enableAlpha)
+                        SizedBox(
+                            height: 40.0,
+                            width: 260.0,
+                            child: colorPickerSlider(TrackType.alpha)),
+                    ],
+                  ),
+                  const SizedBox(width: 10.0),
+                ],
+              ),
+              if (colorHistory.isNotEmpty)
+                SizedBox(
+                  width: widget.colorPickerWidth,
+                  height: 50,
+                  child: ListView(
+                      scrollDirection: Axis.horizontal,
+                      children: <Widget>[
+                        for (Color color in colorHistory)
+                          Padding(
+                            key: Key(color.hashCode.toString()),
+                            padding: const EdgeInsets.fromLTRB(15, 18, 0, 0),
+                            child: Center(
+                              child: GestureDetector(
+                                onTap: () =>
+                                    onColorChanging(HSVColor.fromColor(color)),
+                                onLongPress: () {
+                                  if (colorHistory.remove(color)) {
+                                    widget.onHistoryChanged!(colorHistory);
+                                    setState(() {});
+                                  }
+                                },
+                                child: ColorIndicator(HSVColor.fromColor(color),
+                                    width: 30, height: 30),
+                              ),
+                            ),
+                          ),
+                        const SizedBox(width: 15),
+                      ]),
+                ),
+              const SizedBox(height: 20.0),
+              if (widget.hexInputBar)
+                ColorPickerInput(
+                  currentHsvColor.toColor(),
+                  (Color color) {
+                    setState(() => currentHsvColor = HSVColor.fromColor(color));
+                    widget.onColorChanged(currentHsvColor.toColor());
+                    if (widget.onHsvColorChanged != null) {
+                      widget.onHsvColorChanged!(currentHsvColor);
+                    }
+                  },
+                  enableAlpha: widget.enableAlpha,
+                  embeddedText: false,
+                ),
+              const SizedBox(height: 5),
+            ],
+          ),
+        ],
+      );
+    }
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/colors.dart b/refilc_premium/lib/ui/mobile/flutter_colorpicker/colors.dart
similarity index 97%
rename from filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/colors.dart
rename to refilc_premium/lib/ui/mobile/flutter_colorpicker/colors.dart
index bde7ec2..289cf20 100644
--- a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/colors.dart
+++ b/refilc_premium/lib/ui/mobile/flutter_colorpicker/colors.dart
@@ -1,174 +1,174 @@
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-
-import 'dart:ui';
-
-/// X11 Colors
-///
-/// https://en.wikipedia.org/wiki/X11_color_names
-
-const Map<String, Color> x11Colors = {
-  'aliceblue': Color(0xfff0f8ff),
-  'antiquewhite': Color(0xfffaebd7),
-  'aqua': Color(0xff00ffff),
-  'aquamarine': Color(0xff7fffd4),
-  'azure': Color(0xfff0ffff),
-  'beige': Color(0xfff5f5dc),
-  'bisque': Color(0xffffe4c4),
-  'black': Color(0xff000000),
-  'blanchedalmond': Color(0xffffebcd),
-  'blue': Color(0xff0000ff),
-  'blueviolet': Color(0xff8a2be2),
-  'brown': Color(0xffa52a2a),
-  'burlywood': Color(0xffdeb887),
-  'cadetblue': Color(0xff5f9ea0),
-  'chartreuse': Color(0xff7fff00),
-  'chocolate': Color(0xffd2691e),
-  'coral': Color(0xffff7f50),
-  'cornflower': Color(0xff6495ed),
-  'cornflowerblue': Color(0xff6495ed),
-  'cornsilk': Color(0xfffff8dc),
-  'crimson': Color(0xffdc143c),
-  'cyan': Color(0xff00ffff),
-  'darkblue': Color(0xff00008b),
-  'darkcyan': Color(0xff008b8b),
-  'darkgoldenrod': Color(0xffb8860b),
-  'darkgray': Color(0xffa9a9a9),
-  'darkgreen': Color(0xff006400),
-  'darkgrey': Color(0xffa9a9a9),
-  'darkkhaki': Color(0xffbdb76b),
-  'darkmagenta': Color(0xff8b008b),
-  'darkolivegreen': Color(0xff556b2f),
-  'darkorange': Color(0xffff8c00),
-  'darkorchid': Color(0xff9932cc),
-  'darkred': Color(0xff8b0000),
-  'darksalmon': Color(0xffe9967a),
-  'darkseagreen': Color(0xff8fbc8f),
-  'darkslateblue': Color(0xff483d8b),
-  'darkslategray': Color(0xff2f4f4f),
-  'darkslategrey': Color(0xff2f4f4f),
-  'darkturquoise': Color(0xff00ced1),
-  'darkviolet': Color(0xff9400d3),
-  'deeppink': Color(0xffff1493),
-  'deepskyblue': Color(0xff00bfff),
-  'dimgray': Color(0xff696969),
-  'dimgrey': Color(0xff696969),
-  'dodgerblue': Color(0xff1e90ff),
-  'firebrick': Color(0xffb22222),
-  'floralwhite': Color(0xfffffaf0),
-  'forestgreen': Color(0xff228b22),
-  'fuchsia': Color(0xffff00ff),
-  'gainsboro': Color(0xffdcdcdc),
-  'ghostwhite': Color(0xfff8f8ff),
-  'gold': Color(0xffffd700),
-  'goldenrod': Color(0xffdaa520),
-  'gray': Color(0xff808080),
-  'green': Color(0xff008000),
-  'greenyellow': Color(0xffadff2f),
-  'grey': Color(0xff808080),
-  'honeydew': Color(0xfff0fff0),
-  'hotpink': Color(0xffff69b4),
-  'indianred': Color(0xffcd5c5c),
-  'indigo': Color(0xff4b0082),
-  'ivory': Color(0xfffffff0),
-  'khaki': Color(0xfff0e68c),
-  'laserlemon': Color(0xffffff54),
-  'lavender': Color(0xffe6e6fa),
-  'lavenderblush': Color(0xfffff0f5),
-  'lawngreen': Color(0xff7cfc00),
-  'lemonchiffon': Color(0xfffffacd),
-  'lightblue': Color(0xffadd8e6),
-  'lightcoral': Color(0xfff08080),
-  'lightcyan': Color(0xffe0ffff),
-  'lightgoldenrod': Color(0xfffafad2),
-  'lightgoldenrodyellow': Color(0xfffafad2),
-  'lightgray': Color(0xffd3d3d3),
-  'lightgreen': Color(0xff90ee90),
-  'lightgrey': Color(0xffd3d3d3),
-  'lightpink': Color(0xffffb6c1),
-  'lightsalmon': Color(0xffffa07a),
-  'lightseagreen': Color(0xff20b2aa),
-  'lightskyblue': Color(0xff87cefa),
-  'lightslategray': Color(0xff778899),
-  'lightslategrey': Color(0xff778899),
-  'lightsteelblue': Color(0xffb0c4de),
-  'lightyellow': Color(0xffffffe0),
-  'lime': Color(0xff00ff00),
-  'limegreen': Color(0xff32cd32),
-  'linen': Color(0xfffaf0e6),
-  'magenta': Color(0xffff00ff),
-  'maroon': Color(0xff800000),
-  'maroon2': Color(0xff7f0000),
-  'maroon3': Color(0xffb03060),
-  'mediumaquamarine': Color(0xff66cdaa),
-  'mediumblue': Color(0xff0000cd),
-  'mediumorchid': Color(0xffba55d3),
-  'mediumpurple': Color(0xff9370db),
-  'mediumseagreen': Color(0xff3cb371),
-  'mediumslateblue': Color(0xff7b68ee),
-  'mediumspringgreen': Color(0xff00fa9a),
-  'mediumturquoise': Color(0xff48d1cc),
-  'mediumvioletred': Color(0xffc71585),
-  'midnightblue': Color(0xff191970),
-  'mintcream': Color(0xfff5fffa),
-  'mistyrose': Color(0xffffe4e1),
-  'moccasin': Color(0xffffe4b5),
-  'navajowhite': Color(0xffffdead),
-  'navy': Color(0xff000080),
-  'oldlace': Color(0xfffdf5e6),
-  'olive': Color(0xff808000),
-  'olivedrab': Color(0xff6b8e23),
-  'orange': Color(0xffffa500),
-  'orangered': Color(0xffff4500),
-  'orchid': Color(0xffda70d6),
-  'palegoldenrod': Color(0xffeee8aa),
-  'palegreen': Color(0xff98fb98),
-  'paleturquoise': Color(0xffafeeee),
-  'palevioletred': Color(0xffdb7093),
-  'papayawhip': Color(0xffffefd5),
-  'peachpuff': Color(0xffffdab9),
-  'peru': Color(0xffcd853f),
-  'pink': Color(0xffffc0cb),
-  'plum': Color(0xffdda0dd),
-  'powderblue': Color(0xffb0e0e6),
-  'purple': Color(0xff800080),
-  'purple2': Color(0xff7f007f),
-  'purple3': Color(0xffa020f0),
-  'rebeccapurple': Color(0xff663399),
-  'red': Color(0xffff0000),
-  'rosybrown': Color(0xffbc8f8f),
-  'royalblue': Color(0xff4169e1),
-  'saddlebrown': Color(0xff8b4513),
-  'salmon': Color(0xfffa8072),
-  'sandybrown': Color(0xfff4a460),
-  'seagreen': Color(0xff2e8b57),
-  'seashell': Color(0xfffff5ee),
-  'sienna': Color(0xffa0522d),
-  'silver': Color(0xffc0c0c0),
-  'skyblue': Color(0xff87ceeb),
-  'slateblue': Color(0xff6a5acd),
-  'slategray': Color(0xff708090),
-  'slategrey': Color(0xff708090),
-  'snow': Color(0xfffffafa),
-  'springgreen': Color(0xff00ff7f),
-  'steelblue': Color(0xff4682b4),
-  'tan': Color(0xffd2b48c),
-  'teal': Color(0xff008080),
-  'thistle': Color(0xffd8bfd8),
-  'tomato': Color(0xffff6347),
-  'turquoise': Color(0xff40e0d0),
-  'violet': Color(0xffee82ee),
-  'wheat': Color(0xfff5deb3),
-  'white': Color(0xffffffff),
-  'whitesmoke': Color(0xfff5f5f5),
-  'yellow': Color(0xffffff00),
-  'yellowgreen': Color(0xff9acd32),
-};
-
-Color? colorFromName(String val) => x11Colors[val.trim().replaceAll(' ', '').toLowerCase()];
-
-extension ColorExtension on String {
-  Color? toColor() => colorFromName(this);
-}
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+
+import 'dart:ui';
+
+/// X11 Colors
+///
+/// https://en.wikipedia.org/wiki/X11_color_names
+
+const Map<String, Color> x11Colors = {
+  'aliceblue': Color(0xfff0f8ff),
+  'antiquewhite': Color(0xfffaebd7),
+  'aqua': Color(0xff00ffff),
+  'aquamarine': Color(0xff7fffd4),
+  'azure': Color(0xfff0ffff),
+  'beige': Color(0xfff5f5dc),
+  'bisque': Color(0xffffe4c4),
+  'black': Color(0xff000000),
+  'blanchedalmond': Color(0xffffebcd),
+  'blue': Color(0xff0000ff),
+  'blueviolet': Color(0xff8a2be2),
+  'brown': Color(0xffa52a2a),
+  'burlywood': Color(0xffdeb887),
+  'cadetblue': Color(0xff5f9ea0),
+  'chartreuse': Color(0xff7fff00),
+  'chocolate': Color(0xffd2691e),
+  'coral': Color(0xffff7f50),
+  'cornflower': Color(0xff6495ed),
+  'cornflowerblue': Color(0xff6495ed),
+  'cornsilk': Color(0xfffff8dc),
+  'crimson': Color(0xffdc143c),
+  'cyan': Color(0xff00ffff),
+  'darkblue': Color(0xff00008b),
+  'darkcyan': Color(0xff008b8b),
+  'darkgoldenrod': Color(0xffb8860b),
+  'darkgray': Color(0xffa9a9a9),
+  'darkgreen': Color(0xff006400),
+  'darkgrey': Color(0xffa9a9a9),
+  'darkkhaki': Color(0xffbdb76b),
+  'darkmagenta': Color(0xff8b008b),
+  'darkolivegreen': Color(0xff556b2f),
+  'darkorange': Color(0xffff8c00),
+  'darkorchid': Color(0xff9932cc),
+  'darkred': Color(0xff8b0000),
+  'darksalmon': Color(0xffe9967a),
+  'darkseagreen': Color(0xff8fbc8f),
+  'darkslateblue': Color(0xff483d8b),
+  'darkslategray': Color(0xff2f4f4f),
+  'darkslategrey': Color(0xff2f4f4f),
+  'darkturquoise': Color(0xff00ced1),
+  'darkviolet': Color(0xff9400d3),
+  'deeppink': Color(0xffff1493),
+  'deepskyblue': Color(0xff00bfff),
+  'dimgray': Color(0xff696969),
+  'dimgrey': Color(0xff696969),
+  'dodgerblue': Color(0xff1e90ff),
+  'firebrick': Color(0xffb22222),
+  'floralwhite': Color(0xfffffaf0),
+  'forestgreen': Color(0xff228b22),
+  'fuchsia': Color(0xffff00ff),
+  'gainsboro': Color(0xffdcdcdc),
+  'ghostwhite': Color(0xfff8f8ff),
+  'gold': Color(0xffffd700),
+  'goldenrod': Color(0xffdaa520),
+  'gray': Color(0xff808080),
+  'green': Color(0xff008000),
+  'greenyellow': Color(0xffadff2f),
+  'grey': Color(0xff808080),
+  'honeydew': Color(0xfff0fff0),
+  'hotpink': Color(0xffff69b4),
+  'indianred': Color(0xffcd5c5c),
+  'indigo': Color(0xff4b0082),
+  'ivory': Color(0xfffffff0),
+  'khaki': Color(0xfff0e68c),
+  'laserlemon': Color(0xffffff54),
+  'lavender': Color(0xffe6e6fa),
+  'lavenderblush': Color(0xfffff0f5),
+  'lawngreen': Color(0xff7cfc00),
+  'lemonchiffon': Color(0xfffffacd),
+  'lightblue': Color(0xffadd8e6),
+  'lightcoral': Color(0xfff08080),
+  'lightcyan': Color(0xffe0ffff),
+  'lightgoldenrod': Color(0xfffafad2),
+  'lightgoldenrodyellow': Color(0xfffafad2),
+  'lightgray': Color(0xffd3d3d3),
+  'lightgreen': Color(0xff90ee90),
+  'lightgrey': Color(0xffd3d3d3),
+  'lightpink': Color(0xffffb6c1),
+  'lightsalmon': Color(0xffffa07a),
+  'lightseagreen': Color(0xff20b2aa),
+  'lightskyblue': Color(0xff87cefa),
+  'lightslategray': Color(0xff778899),
+  'lightslategrey': Color(0xff778899),
+  'lightsteelblue': Color(0xffb0c4de),
+  'lightyellow': Color(0xffffffe0),
+  'lime': Color(0xff00ff00),
+  'limegreen': Color(0xff32cd32),
+  'linen': Color(0xfffaf0e6),
+  'magenta': Color(0xffff00ff),
+  'maroon': Color(0xff800000),
+  'maroon2': Color(0xff7f0000),
+  'maroon3': Color(0xffb03060),
+  'mediumaquamarine': Color(0xff66cdaa),
+  'mediumblue': Color(0xff0000cd),
+  'mediumorchid': Color(0xffba55d3),
+  'mediumpurple': Color(0xff9370db),
+  'mediumseagreen': Color(0xff3cb371),
+  'mediumslateblue': Color(0xff7b68ee),
+  'mediumspringgreen': Color(0xff00fa9a),
+  'mediumturquoise': Color(0xff48d1cc),
+  'mediumvioletred': Color(0xffc71585),
+  'midnightblue': Color(0xff191970),
+  'mintcream': Color(0xfff5fffa),
+  'mistyrose': Color(0xffffe4e1),
+  'moccasin': Color(0xffffe4b5),
+  'navajowhite': Color(0xffffdead),
+  'navy': Color(0xff000080),
+  'oldlace': Color(0xfffdf5e6),
+  'olive': Color(0xff808000),
+  'olivedrab': Color(0xff6b8e23),
+  'orange': Color(0xffffa500),
+  'orangered': Color(0xffff4500),
+  'orchid': Color(0xffda70d6),
+  'palegoldenrod': Color(0xffeee8aa),
+  'palegreen': Color(0xff98fb98),
+  'paleturquoise': Color(0xffafeeee),
+  'palevioletred': Color(0xffdb7093),
+  'papayawhip': Color(0xffffefd5),
+  'peachpuff': Color(0xffffdab9),
+  'peru': Color(0xffcd853f),
+  'pink': Color(0xffffc0cb),
+  'plum': Color(0xffdda0dd),
+  'powderblue': Color(0xffb0e0e6),
+  'purple': Color(0xff800080),
+  'purple2': Color(0xff7f007f),
+  'purple3': Color(0xffa020f0),
+  'rebeccapurple': Color(0xff663399),
+  'red': Color(0xffff0000),
+  'rosybrown': Color(0xffbc8f8f),
+  'royalblue': Color(0xff4169e1),
+  'saddlebrown': Color(0xff8b4513),
+  'salmon': Color(0xfffa8072),
+  'sandybrown': Color(0xfff4a460),
+  'seagreen': Color(0xff2e8b57),
+  'seashell': Color(0xfffff5ee),
+  'sienna': Color(0xffa0522d),
+  'silver': Color(0xffc0c0c0),
+  'skyblue': Color(0xff87ceeb),
+  'slateblue': Color(0xff6a5acd),
+  'slategray': Color(0xff708090),
+  'slategrey': Color(0xff708090),
+  'snow': Color(0xfffffafa),
+  'springgreen': Color(0xff00ff7f),
+  'steelblue': Color(0xff4682b4),
+  'tan': Color(0xffd2b48c),
+  'teal': Color(0xff008080),
+  'thistle': Color(0xffd8bfd8),
+  'tomato': Color(0xffff6347),
+  'turquoise': Color(0xff40e0d0),
+  'violet': Color(0xffee82ee),
+  'wheat': Color(0xfff5deb3),
+  'white': Color(0xffffffff),
+  'whitesmoke': Color(0xfff5f5f5),
+  'yellow': Color(0xffffff00),
+  'yellowgreen': Color(0xff9acd32),
+};
+
+Color? colorFromName(String val) => x11Colors[val.trim().replaceAll(' ', '').toLowerCase()];
+
+extension ColorExtension on String {
+  Color? toColor() => colorFromName(this);
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/palette.dart b/refilc_premium/lib/ui/mobile/flutter_colorpicker/palette.dart
similarity index 87%
rename from filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/palette.dart
rename to refilc_premium/lib/ui/mobile/flutter_colorpicker/palette.dart
index fb33f69..0426f05 100644
--- a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/palette.dart
+++ b/refilc_premium/lib/ui/mobile/flutter_colorpicker/palette.dart
@@ -1,785 +1,828 @@
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-
-/// The components of HSV Color Picker
-///
-/// Try to create a Color Picker with other layout on your own :)
-
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/accent.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:flutter/gestures.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
-import 'utils.dart';
-
-/// Palette types for color picker area widget.
-enum PaletteType {
-  hsv,
-  hsvWithHue,
-  hsvWithValue,
-  hsvWithSaturation,
-  hsl,
-  hslWithHue,
-  hslWithLightness,
-  hslWithSaturation,
-  rgbWithBlue,
-  rgbWithGreen,
-  rgbWithRed,
-  hueWheel,
-}
-
-/// Track types for slider picker.
-enum TrackType {
-  hue,
-  saturation,
-  saturationForHSL,
-  value,
-  lightness,
-  red,
-  green,
-  blue,
-  alpha,
-}
-
-enum FilcTrackType {
-  hue,
-  saturation,
-  value,
-}
-
-/// Color information label type.
-enum ColorLabelType { hex, rgb, hsv, hsl }
-
-/// Types for slider picker widget.
-enum ColorModel { rgb, hsv, hsl }
-// enum ColorSpace { rgb, hsv, hsl, hsp, okhsv, okhsl, xyz, yuv, lab, lch, cmyk }
-
-/// Painter for SV mixture.
-class HSVWithHueColorPainter extends CustomPainter {
-  const HSVWithHueColorPainter(this.hsvColor, {this.pointerColor});
-
-  final HSVColor hsvColor;
-  final Color? pointerColor;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    final Rect rect = Offset.zero & size;
-    const Gradient gradientV = LinearGradient(
-      begin: Alignment.topCenter,
-      end: Alignment.bottomCenter,
-      colors: [Colors.white, Colors.black],
-    );
-    final Gradient gradientH = LinearGradient(
-      colors: [
-        Colors.white,
-        HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
-      ],
-    );
-    canvas.drawRect(rect, Paint()..shader = gradientV.createShader(rect));
-    canvas.drawRect(
-      rect,
-      Paint()
-        ..blendMode = BlendMode.multiply
-        ..shader = gradientH.createShader(rect),
-    );
-
-    canvas.drawCircle(
-      Offset(size.width * hsvColor.saturation, size.height * (1 - hsvColor.value)),
-      size.height * 0.04,
-      Paint()
-        ..color = pointerColor ?? (useWhiteForeground(hsvColor.toColor()) ? Colors.white : Colors.black)
-        ..strokeWidth = 1.5
-        ..style = PaintingStyle.stroke,
-    );
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) => false;
-}
-
-class _SliderLayout extends MultiChildLayoutDelegate {
-  static const String track = 'track';
-  static const String thumb = 'thumb';
-  static const String gestureContainer = 'gesturecontainer';
-
-  @override
-  void performLayout(Size size) {
-    layoutChild(
-      track,
-      BoxConstraints.tightFor(
-        width: size.width + 3,
-        height: size.height / 1.5,
-      ),
-    );
-    positionChild(track, const Offset(-2.0, 0));
-    layoutChild(
-      thumb,
-      const BoxConstraints.tightFor(width: 5.5, height: 10.5),
-    );
-    positionChild(thumb, Offset(0.0, (size.height / 1.5) / 2 - 4.5));
-    layoutChild(
-      gestureContainer,
-      BoxConstraints.tightFor(width: size.width, height: size.height),
-    );
-    positionChild(gestureContainer, Offset.zero);
-  }
-
-  @override
-  bool shouldRelayout(_SliderLayout oldDelegate) => false;
-}
-
-/// Painter for all kinds of track types.
-class TrackPainter extends CustomPainter {
-  const TrackPainter(this.trackType, this.hsvColor);
-
-  final TrackType trackType;
-  final HSVColor hsvColor;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    final Rect rect = Offset.zero & size;
-    if (trackType == TrackType.alpha) {
-      final Size chessSize = Size(size.height / 2, size.height / 2);
-      Paint chessPaintB = Paint()..color = const Color(0xffcccccc);
-      Paint chessPaintW = Paint()..color = Colors.white;
-      List.generate((size.height / chessSize.height).round(), (int y) {
-        List.generate((size.width / chessSize.width).round(), (int x) {
-          canvas.drawRect(
-            Offset(chessSize.width * x, chessSize.width * y) & chessSize,
-            (x + y) % 2 != 0 ? chessPaintW : chessPaintB,
-          );
-        });
-      });
-    }
-
-    switch (trackType) {
-      case TrackType.hue:
-        final List<Color> colors = [
-          const HSVColor.fromAHSV(1.0, 0.0, 1.0, 1.0).toColor(),
-          const HSVColor.fromAHSV(1.0, 60.0, 1.0, 1.0).toColor(),
-          const HSVColor.fromAHSV(1.0, 120.0, 1.0, 1.0).toColor(),
-          const HSVColor.fromAHSV(1.0, 180.0, 1.0, 1.0).toColor(),
-          const HSVColor.fromAHSV(1.0, 240.0, 1.0, 1.0).toColor(),
-          const HSVColor.fromAHSV(1.0, 300.0, 1.0, 1.0).toColor(),
-          const HSVColor.fromAHSV(1.0, 360.0, 1.0, 1.0).toColor(),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.saturation:
-        final List<Color> colors = [
-          HSVColor.fromAHSV(1.0, hsvColor.hue, 0.0, 1.0).toColor(),
-          HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.saturationForHSL:
-        final List<Color> colors = [
-          HSLColor.fromAHSL(1.0, hsvColor.hue, 0.0, 0.5).toColor(),
-          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 0.5).toColor(),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.value:
-        final List<Color> colors = [
-          HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 0.0).toColor(),
-          HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.lightness:
-        final List<Color> colors = [
-          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 0.0).toColor(),
-          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 0.5).toColor(),
-          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.red:
-        final List<Color> colors = [
-          hsvColor.toColor().withRed(0).withOpacity(1.0),
-          hsvColor.toColor().withRed(255).withOpacity(1.0),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.green:
-        final List<Color> colors = [
-          hsvColor.toColor().withGreen(0).withOpacity(1.0),
-          hsvColor.toColor().withGreen(255).withOpacity(1.0),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.blue:
-        final List<Color> colors = [
-          hsvColor.toColor().withBlue(0).withOpacity(1.0),
-          hsvColor.toColor().withBlue(255).withOpacity(1.0),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-      case TrackType.alpha:
-        final List<Color> colors = [
-          hsvColor.toColor().withOpacity(0.0),
-          hsvColor.toColor().withOpacity(1.0),
-        ];
-        Gradient gradient = LinearGradient(colors: colors);
-        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
-        break;
-    }
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) => false;
-}
-
-/// Painter for thumb of slider.
-class ThumbPainter extends CustomPainter {
-  const ThumbPainter({this.thumbColor, this.fullThumbColor = false});
-
-  final Color? thumbColor;
-  final bool fullThumbColor;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    canvas.drawShadow(
-      Path()
-        ..addOval(
-          Rect.fromCircle(center: const Offset(0.5, 2.0), radius: size.width * 1.8),
-        ),
-      Colors.black,
-      3.0,
-      true,
-    );
-    canvas.drawCircle(
-        Offset(0.0, size.height * 0.4),
-        size.height,
-        Paint()
-          ..color = Colors.white
-          ..style = PaintingStyle.fill);
-    if (thumbColor != null) {
-      canvas.drawCircle(
-          Offset(0.0, size.height * 0.4),
-          size.height * (fullThumbColor ? 1.0 : 0.65),
-          Paint()
-            ..color = thumbColor!
-            ..style = PaintingStyle.fill);
-    }
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) => false;
-}
-
-/// Painter for chess type alpha background in color indicator widget.
-class IndicatorPainter extends CustomPainter {
-  const IndicatorPainter(this.color);
-
-  final Color color;
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    final Size chessSize = Size(size.width / 10, size.height / 10);
-    final Paint chessPaintB = Paint()..color = const Color(0xFFCCCCCC);
-    final Paint chessPaintW = Paint()..color = Colors.white;
-    List.generate((size.height / chessSize.height).round(), (int y) {
-      List.generate((size.width / chessSize.width).round(), (int x) {
-        canvas.drawRect(
-          Offset(chessSize.width * x, chessSize.height * y) & chessSize,
-          (x + y) % 2 != 0 ? chessPaintW : chessPaintB,
-        );
-      });
-    });
-
-    canvas.drawCircle(
-        Offset(size.width / 2, size.height / 2),
-        size.height / 2,
-        Paint()
-          ..color = color
-          ..style = PaintingStyle.fill);
-  }
-
-  @override
-  bool shouldRepaint(CustomPainter oldDelegate) => false;
-}
-
-/// Provide hex input wiget for 3/6/8 digits.
-class ColorPickerInput extends StatefulWidget {
-  const ColorPickerInput(
-    this.color,
-    this.onColorChanged, {
-    Key? key,
-    this.enableAlpha = true,
-    this.embeddedText = false,
-    this.disable = false,
-  }) : super(key: key);
-
-  final Color color;
-  final ValueChanged<Color> onColorChanged;
-  final bool enableAlpha;
-  final bool embeddedText;
-  final bool disable;
-
-  @override
-  _ColorPickerInputState createState() => _ColorPickerInputState();
-}
-
-class _ColorPickerInputState extends State<ColorPickerInput> {
-  TextEditingController textEditingController = TextEditingController();
-  int inputColor = 0;
-
-  @override
-  void dispose() {
-    textEditingController.dispose();
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (inputColor != widget.color.value) {
-      textEditingController.text = '#' +
-          widget.color.red.toRadixString(16).toUpperCase().padLeft(2, '0') +
-          widget.color.green.toRadixString(16).toUpperCase().padLeft(2, '0') +
-          widget.color.blue.toRadixString(16).toUpperCase().padLeft(2, '0') +
-          (widget.enableAlpha ? widget.color.alpha.toRadixString(16).toUpperCase().padLeft(2, '0') : '');
-    }
-    return Padding(
-      padding: const EdgeInsets.only(top: 6.0, left: 12.0, right: 12.0),
-      child: SizedBox(
-        width: double.infinity,
-        child: TextField(
-          enabled: !widget.disable,
-          controller: textEditingController,
-          style: TextStyle(
-            fontSize: 18,
-            color: Theme.of(context).colorScheme.onBackground,
-          ),
-          inputFormatters: [
-            UpperCaseTextFormatter(),
-            FilteringTextInputFormatter.allow(RegExp(kValidHexPattern)),
-          ],
-          decoration: InputDecoration(
-            isDense: true,
-            filled: true,
-            border: OutlineInputBorder(
-              borderRadius: BorderRadius.circular(12.0),
-              borderSide: const BorderSide(color: Colors.transparent, width: 0.0),
-            ),
-            enabledBorder: OutlineInputBorder(
-              borderRadius: BorderRadius.circular(12.0),
-              borderSide: const BorderSide(color: Colors.transparent, width: 0.0),
-            ),
-            focusedBorder: OutlineInputBorder(
-              borderRadius: BorderRadius.circular(12.0),
-              borderSide: const BorderSide(color: Colors.transparent, width: 0.0),
-            ),
-            contentPadding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
-            fillColor: AppColors.of(context).text.withOpacity(.1),
-          ),
-          onChanged: (String value) {
-            String input = value;
-            if (value.length == 9) {
-              input = value.split('').getRange(7, 9).join() + value.split('').getRange(1, 7).join();
-            }
-            final Color? color = colorFromHex(input);
-            if (color != null) {
-              widget.onColorChanged(color);
-              inputColor = color.value;
-            }
-          },
-        ),
-      ),
-    );
-  }
-}
-
-/*class ValueColorPickerSlider extends StatefulWidget {
-  ValueColorPickerSlider(this.trackType, this.initialHsvColor, this.onProgressChanged, this.onColorChangeEnd, {Key? key}) : super(key: key);
-
-  final TrackType trackType;
-  final HSVColor initialHsvColor;
-  final void Function(double progress) onProgressChanged;
-  final void Function() onColorChangeEnd;
-
-  @override
-  State<ValueColorPickerSlider> createState() => _ValueColorPickerSliderState();
-}
-
-class _ValueColorPickerSliderState extends State<ValueColorPickerSlider> {
-  HSVColor hsvColor = HSVColor.fromColor(Colors.red);
-
-  @override
-  void initState() {
-    super.initState();
-    hsvColor = widget.initialHsvColor;
-  }
-
-  void slideEvent(RenderBox getBox, BoxConstraints box, Offset globalPosition) {
-    double localDx = getBox.globalToLocal(globalPosition).dx - 15.0;
-    double progress = localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0);
-    setState(() {
-      switch (widget.trackType) {
-        case TrackType.hue:
-          hsvColor = hsvColor.withHue(progress * 359);
-          break;
-        case TrackType.saturation:
-          hsvColor = hsvColor.withSaturation(progress);
-          break;
-        case TrackType.value:
-          hsvColor = hsvColor.withValue(progress);
-          break;
-        default:
-          break;
-      }
-    });
-    widget.onProgressChanged(progress);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return LayoutBuilder(builder: (BuildContext context, BoxConstraints box) {
-      double thumbOffset = 15.0;
-      Color thumbColor = Colors.white;
-      switch (widget.trackType) {
-        case TrackType.hue:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.hue / 360;
-          break;
-        case TrackType.saturation:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.saturation;
-          break;
-        case TrackType.value:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.value;
-          break;
-        default:
-          break;
-      }
-
-      return CustomMultiChildLayout(
-        delegate: _SliderLayout(),
-        children: <Widget>[
-          LayoutId(
-            id: _SliderLayout.track,
-            child: ClipRRect(
-              borderRadius: const BorderRadius.all(Radius.circular(50.0)),
-              child: CustomPaint(
-                  painter: TrackPainter(
-                TrackType.values.firstWhere((element) => element == widget.trackType),
-                hsvColor,
-              )),
-            ),
-          ),
-          LayoutId(
-            id: _SliderLayout.thumb,
-            child: Transform.translate(
-              offset: Offset(thumbOffset, 0.0),
-              child: CustomPaint(
-                painter: ThumbPainter(
-                  thumbColor: thumbColor,
-                  fullThumbColor: false,
-                ),
-              ),
-            ),
-          ),
-          LayoutId(
-            id: _SliderLayout.gestureContainer,
-            child: LayoutBuilder(
-              builder: (BuildContext context, BoxConstraints box) {
-                RenderBox? getBox = context.findRenderObject() as RenderBox?;
-                return GestureDetector(
-                  onPanDown: (DragDownDetails details) => getBox != null ? slideEvent(getBox, box, details.globalPosition) : null,
-                  onPanEnd: (details) => widget.onColorChangeEnd(),
-                  onPanUpdate: (DragUpdateDetails details) => getBox != null ? slideEvent(getBox, box, details.globalPosition) : null,
-                );
-              },
-            ),
-          ),
-        ],
-      );
-    });
-  }
-}*/
-
-/// 9 track types for slider picker widget.
-class ColorPickerSlider extends StatelessWidget {
-  const ColorPickerSlider(
-    this.trackType,
-    this.hsvColor,
-    this.onColorChanged,
-    this.onColorChangeEnd,
-    this.onProblem, {
-    Key? key,
-    this.displayThumbColor = false,
-    this.fullThumbColor = false,
-  }) : super(key: key);
-
-  final TrackType trackType;
-  final HSVColor hsvColor;
-  final ValueChanged<HSVColor> onColorChanged;
-  final void Function() onColorChangeEnd;
-  final void Function(int v) onProblem;
-  final bool displayThumbColor;
-  final bool fullThumbColor;
-
-  void slideEvent(RenderBox getBox, BoxConstraints box, Offset globalPosition) {
-    double localDx = getBox.globalToLocal(globalPosition).dx - 15.0;
-    double progress = localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0);
-    switch (trackType) {
-      case TrackType.hue:
-        // 360 is the same as zero
-        // if set to 360, sliding to end goes to zero
-        final newColor = hsvColor.withHue(progress * 359);
-        if (newColor.saturation == 0) {
-          onProblem(0);
-          return;
-        }
-        onColorChanged(newColor);
-        break;
-      case TrackType.saturation:
-        final newColor = hsvColor.withSaturation(progress);
-        if (newColor.value == 0) {
-          onProblem(1);
-          return;
-        }
-        onColorChanged(newColor);
-        break;
-      case TrackType.value:
-        onColorChanged(hsvColor.withValue(progress));
-        break;
-      default:
-        break;
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return LayoutBuilder(builder: (BuildContext context, BoxConstraints box) {
-      double thumbOffset = 15.0;
-      Color thumbColor;
-      switch (trackType) {
-        case TrackType.hue:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.hue / 360;
-          thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor();
-          break;
-        case TrackType.saturation:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.saturation;
-          thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, hsvColor.saturation, 1.0).toColor();
-          break;
-        case TrackType.saturationForHSL:
-          thumbOffset += (box.maxWidth - 30.0) * hsvToHsl(hsvColor).saturation;
-          thumbColor = HSLColor.fromAHSL(1.0, hsvColor.hue, hsvToHsl(hsvColor).saturation, 0.5).toColor();
-          break;
-        case TrackType.value:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.value;
-          thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, hsvColor.value).toColor();
-          break;
-        case TrackType.lightness:
-          thumbOffset += (box.maxWidth - 30.0) * hsvToHsl(hsvColor).lightness;
-          thumbColor = HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, hsvToHsl(hsvColor).lightness).toColor();
-          break;
-        case TrackType.red:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().red / 0xff;
-          thumbColor = hsvColor.toColor().withOpacity(1.0);
-          break;
-        case TrackType.green:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().green / 0xff;
-          thumbColor = hsvColor.toColor().withOpacity(1.0);
-          break;
-        case TrackType.blue:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().blue / 0xff;
-          thumbColor = hsvColor.toColor().withOpacity(1.0);
-          break;
-        case TrackType.alpha:
-          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().opacity;
-          thumbColor = hsvColor.toColor().withOpacity(hsvColor.alpha);
-          break;
-      }
-
-      return CustomMultiChildLayout(
-        delegate: _SliderLayout(),
-        children: <Widget>[
-          LayoutId(
-            id: _SliderLayout.track,
-            child: ClipRRect(
-              borderRadius: const BorderRadius.all(Radius.circular(50.0)),
-              child: CustomPaint(
-                  painter: TrackPainter(
-                trackType,
-                hsvColor,
-              )),
-            ),
-          ),
-          LayoutId(
-            id: _SliderLayout.thumb,
-            child: Transform.translate(
-              offset: Offset(thumbOffset, 0.0),
-              child: CustomPaint(
-                painter: ThumbPainter(
-                  thumbColor: displayThumbColor ? thumbColor : null,
-                  fullThumbColor: fullThumbColor,
-                ),
-              ),
-            ),
-          ),
-          LayoutId(
-            id: _SliderLayout.gestureContainer,
-            child: LayoutBuilder(
-              builder: (BuildContext context, BoxConstraints box) {
-                RenderBox? getBox = context.findRenderObject() as RenderBox?;
-                return GestureDetector(
-                  onPanDown: (DragDownDetails details) => getBox != null ? slideEvent(getBox, box, details.globalPosition) : null,
-                  onPanEnd: (details) {
-                    if ((trackType == TrackType.hue && hsvColor.saturation == 0) || (trackType == TrackType.saturation && hsvColor.value == 0)) {
-                      return;
-                    }
-                    onColorChangeEnd();
-                  },
-                  onPanUpdate: (DragUpdateDetails details) => getBox != null ? slideEvent(getBox, box, details.globalPosition) : null,
-                );
-              },
-            ),
-          ),
-        ],
-      );
-    });
-  }
-}
-
-/// Simple round color indicator.
-class ColorIndicator extends StatelessWidget {
-  const ColorIndicator(
-    this.hsvColor, {
-    Key? key,
-    this.currentHsvColor,
-    this.icon,
-    this.width = 50.0,
-    this.height = 50.0,
-    this.adaptive = false,
-  }) : super(key: key);
-
-  final HSVColor hsvColor;
-  final HSVColor? currentHsvColor;
-  final double width;
-  final double height;
-  final IconData? icon;
-  final bool adaptive;
-
-  @override
-  Widget build(BuildContext context) {
-    Color color = hsvColor.toColor();
-
-    return Container(
-      width: width,
-      height: height,
-      decoration: BoxDecoration(
-        shape: BoxShape.circle,
-        color: color,
-        boxShadow: [
-          BoxShadow(
-              color: useWhiteForeground(color) ? Colors.white.withOpacity(.5) : Colors.black.withOpacity(.5),
-              offset: const Offset(0, 0),
-              blurRadius: 5)
-        ],
-      ),
-      child: Material(
-        color: Colors.transparent,
-        child: AnimatedOpacity(
-          duration: const Duration(milliseconds: 210),
-          opacity: (icon != null || currentHsvColor == hsvColor) &&
-                  (adaptive || Provider.of<SettingsProvider>(context, listen: false).accentColor != AccentColor.adaptive)
-              ? 1
-              : 0,
-          child: Icon(icon ?? Icons.done, color: useWhiteForeground(color) ? Colors.white : Colors.black),
-        ),
-      ),
-    );
-  }
-}
-
-/// Provide Rectangle & Circle 2 categories, 10 variations of palette widget.
-class ColorPickerArea extends StatelessWidget {
-  const ColorPickerArea(
-    this.hsvColor,
-    this.onColorChanged,
-    this.onChangeEnd,
-    this.paletteType, {
-    Key? key,
-  }) : super(key: key);
-
-  final HSVColor hsvColor;
-  final ValueChanged<HSVColor> onColorChanged;
-  final void Function() onChangeEnd;
-  final PaletteType paletteType;
-
-  /*void _handleColorRectChange(double horizontal, double vertical) {
-    onColorChanged(hsvColor.withSaturation(horizontal).withValue(vertical));
-  }*/
-
-  void _handleGesture(Offset position, BuildContext context, double height, double width) {
-    RenderBox? getBox = context.findRenderObject() as RenderBox?;
-    if (getBox == null) return;
-
-    Offset localOffset = getBox.globalToLocal(position);
-    double horizontal = localOffset.dx.clamp(0.0, width);
-    double vertical = localOffset.dy.clamp(0.0, height);
-
-    //_handleColorRectChange(horizontal / width, 1 - vertical / height);
-
-    onColorChanged(hsvColor.withSaturation(horizontal).withValue(vertical));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return LayoutBuilder(
-      builder: (BuildContext context, BoxConstraints constraints) {
-        double width = constraints.maxWidth;
-        double height = constraints.maxHeight;
-
-        return RawGestureDetector(
-          gestures: {
-            _AlwaysWinPanGestureRecognizer: GestureRecognizerFactoryWithHandlers<_AlwaysWinPanGestureRecognizer>(
-              () => _AlwaysWinPanGestureRecognizer(),
-              (_AlwaysWinPanGestureRecognizer instance) {
-                instance
-                  ..onDown = ((details) => _handleGesture(details.globalPosition, context, height, width))
-                  ..onEnd = ((d) => onChangeEnd())
-                  ..onUpdate = ((details) => _handleGesture(details.globalPosition, context, height, width));
-              },
-            ),
-          },
-          child: Builder(
-            builder: (BuildContext _) {
-              return CustomPaint(painter: HSVWithHueColorPainter(hsvColor));
-            },
-          ),
-        );
-      },
-    );
-  }
-}
-
-class _AlwaysWinPanGestureRecognizer extends PanGestureRecognizer {
-  @override
-  void addAllowedPointer(event) {
-    super.addAllowedPointer(event);
-    resolve(GestureDisposition.accepted);
-  }
-
-  @override
-  String get debugDescription => 'alwaysWin';
-}
-
-/// Uppercase text formater
-class UpperCaseTextFormatter extends TextInputFormatter {
-  @override
-  TextEditingValue formatEditUpdate(oldValue, TextEditingValue newValue) =>
-      TextEditingValue(text: newValue.text.toUpperCase(), selection: newValue.selection);
-}
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+
+/// The components of HSV Color Picker
+///
+/// Try to create a Color Picker with other layout on your own :)
+
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/accent.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
+import 'utils.dart';
+
+/// Palette types for color picker area widget.
+enum PaletteType {
+  hsv,
+  hsvWithHue,
+  hsvWithValue,
+  hsvWithSaturation,
+  hsl,
+  hslWithHue,
+  hslWithLightness,
+  hslWithSaturation,
+  rgbWithBlue,
+  rgbWithGreen,
+  rgbWithRed,
+  hueWheel,
+}
+
+/// Track types for slider picker.
+enum TrackType {
+  hue,
+  saturation,
+  saturationForHSL,
+  value,
+  lightness,
+  red,
+  green,
+  blue,
+  alpha,
+}
+
+enum FilcTrackType {
+  hue,
+  saturation,
+  value,
+}
+
+/// Color information label type.
+enum ColorLabelType { hex, rgb, hsv, hsl }
+
+/// Types for slider picker widget.
+enum ColorModel { rgb, hsv, hsl }
+// enum ColorSpace { rgb, hsv, hsl, hsp, okhsv, okhsl, xyz, yuv, lab, lch, cmyk }
+
+/// Painter for SV mixture.
+class HSVWithHueColorPainter extends CustomPainter {
+  const HSVWithHueColorPainter(this.hsvColor, {this.pointerColor});
+
+  final HSVColor hsvColor;
+  final Color? pointerColor;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final Rect rect = Offset.zero & size;
+    const Gradient gradientV = LinearGradient(
+      begin: Alignment.topCenter,
+      end: Alignment.bottomCenter,
+      colors: [Colors.white, Colors.black],
+    );
+    final Gradient gradientH = LinearGradient(
+      colors: [
+        Colors.white,
+        HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
+      ],
+    );
+    canvas.drawRect(rect, Paint()..shader = gradientV.createShader(rect));
+    canvas.drawRect(
+      rect,
+      Paint()
+        ..blendMode = BlendMode.multiply
+        ..shader = gradientH.createShader(rect),
+    );
+
+    canvas.drawCircle(
+      Offset(
+          size.width * hsvColor.saturation, size.height * (1 - hsvColor.value)),
+      size.height * 0.04,
+      Paint()
+        ..color = pointerColor ??
+            (useWhiteForeground(hsvColor.toColor())
+                ? Colors.white
+                : Colors.black)
+        ..strokeWidth = 1.5
+        ..style = PaintingStyle.stroke,
+    );
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) => false;
+}
+
+class _SliderLayout extends MultiChildLayoutDelegate {
+  static const String track = 'track';
+  static const String thumb = 'thumb';
+  static const String gestureContainer = 'gesturecontainer';
+
+  @override
+  void performLayout(Size size) {
+    layoutChild(
+      track,
+      BoxConstraints.tightFor(
+        width: size.width + 3,
+        height: size.height / 1.5,
+      ),
+    );
+    positionChild(track, const Offset(-2.0, 0));
+    layoutChild(
+      thumb,
+      const BoxConstraints.tightFor(width: 5.5, height: 10.5),
+    );
+    positionChild(thumb, Offset(0.0, (size.height / 1.5) / 2 - 4.5));
+    layoutChild(
+      gestureContainer,
+      BoxConstraints.tightFor(width: size.width, height: size.height),
+    );
+    positionChild(gestureContainer, Offset.zero);
+  }
+
+  @override
+  bool shouldRelayout(_SliderLayout oldDelegate) => false;
+}
+
+/// Painter for all kinds of track types.
+class TrackPainter extends CustomPainter {
+  const TrackPainter(this.trackType, this.hsvColor);
+
+  final TrackType trackType;
+  final HSVColor hsvColor;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final Rect rect = Offset.zero & size;
+    if (trackType == TrackType.alpha) {
+      final Size chessSize = Size(size.height / 2, size.height / 2);
+      Paint chessPaintB = Paint()..color = const Color(0xffcccccc);
+      Paint chessPaintW = Paint()..color = Colors.white;
+      List.generate((size.height / chessSize.height).round(), (int y) {
+        List.generate((size.width / chessSize.width).round(), (int x) {
+          canvas.drawRect(
+            Offset(chessSize.width * x, chessSize.width * y) & chessSize,
+            (x + y) % 2 != 0 ? chessPaintW : chessPaintB,
+          );
+        });
+      });
+    }
+
+    switch (trackType) {
+      case TrackType.hue:
+        final List<Color> colors = [
+          const HSVColor.fromAHSV(1.0, 0.0, 1.0, 1.0).toColor(),
+          const HSVColor.fromAHSV(1.0, 60.0, 1.0, 1.0).toColor(),
+          const HSVColor.fromAHSV(1.0, 120.0, 1.0, 1.0).toColor(),
+          const HSVColor.fromAHSV(1.0, 180.0, 1.0, 1.0).toColor(),
+          const HSVColor.fromAHSV(1.0, 240.0, 1.0, 1.0).toColor(),
+          const HSVColor.fromAHSV(1.0, 300.0, 1.0, 1.0).toColor(),
+          const HSVColor.fromAHSV(1.0, 360.0, 1.0, 1.0).toColor(),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.saturation:
+        final List<Color> colors = [
+          HSVColor.fromAHSV(1.0, hsvColor.hue, 0.0, 1.0).toColor(),
+          HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.saturationForHSL:
+        final List<Color> colors = [
+          HSLColor.fromAHSL(1.0, hsvColor.hue, 0.0, 0.5).toColor(),
+          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 0.5).toColor(),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.value:
+        final List<Color> colors = [
+          HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 0.0).toColor(),
+          HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.lightness:
+        final List<Color> colors = [
+          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 0.0).toColor(),
+          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 0.5).toColor(),
+          HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, 1.0).toColor(),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.red:
+        final List<Color> colors = [
+          hsvColor.toColor().withRed(0).withOpacity(1.0),
+          hsvColor.toColor().withRed(255).withOpacity(1.0),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.green:
+        final List<Color> colors = [
+          hsvColor.toColor().withGreen(0).withOpacity(1.0),
+          hsvColor.toColor().withGreen(255).withOpacity(1.0),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.blue:
+        final List<Color> colors = [
+          hsvColor.toColor().withBlue(0).withOpacity(1.0),
+          hsvColor.toColor().withBlue(255).withOpacity(1.0),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+      case TrackType.alpha:
+        final List<Color> colors = [
+          hsvColor.toColor().withOpacity(0.0),
+          hsvColor.toColor().withOpacity(1.0),
+        ];
+        Gradient gradient = LinearGradient(colors: colors);
+        canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
+        break;
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) => false;
+}
+
+/// Painter for thumb of slider.
+class ThumbPainter extends CustomPainter {
+  const ThumbPainter({this.thumbColor, this.fullThumbColor = false});
+
+  final Color? thumbColor;
+  final bool fullThumbColor;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    canvas.drawShadow(
+      Path()
+        ..addOval(
+          Rect.fromCircle(
+              center: const Offset(0.5, 2.0), radius: size.width * 1.8),
+        ),
+      Colors.black,
+      3.0,
+      true,
+    );
+    canvas.drawCircle(
+        Offset(0.0, size.height * 0.4),
+        size.height,
+        Paint()
+          ..color = Colors.white
+          ..style = PaintingStyle.fill);
+    if (thumbColor != null) {
+      canvas.drawCircle(
+          Offset(0.0, size.height * 0.4),
+          size.height * (fullThumbColor ? 1.0 : 0.65),
+          Paint()
+            ..color = thumbColor!
+            ..style = PaintingStyle.fill);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) => false;
+}
+
+/// Painter for chess type alpha background in color indicator widget.
+class IndicatorPainter extends CustomPainter {
+  const IndicatorPainter(this.color);
+
+  final Color color;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final Size chessSize = Size(size.width / 10, size.height / 10);
+    final Paint chessPaintB = Paint()..color = const Color(0xFFCCCCCC);
+    final Paint chessPaintW = Paint()..color = Colors.white;
+    List.generate((size.height / chessSize.height).round(), (int y) {
+      List.generate((size.width / chessSize.width).round(), (int x) {
+        canvas.drawRect(
+          Offset(chessSize.width * x, chessSize.height * y) & chessSize,
+          (x + y) % 2 != 0 ? chessPaintW : chessPaintB,
+        );
+      });
+    });
+
+    canvas.drawCircle(
+        Offset(size.width / 2, size.height / 2),
+        size.height / 2,
+        Paint()
+          ..color = color
+          ..style = PaintingStyle.fill);
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) => false;
+}
+
+/// Provide hex input wiget for 3/6/8 digits.
+class ColorPickerInput extends StatefulWidget {
+  const ColorPickerInput(
+    this.color,
+    this.onColorChanged, {
+    Key? key,
+    this.enableAlpha = true,
+    this.embeddedText = false,
+    this.disable = false,
+  }) : super(key: key);
+
+  final Color color;
+  final ValueChanged<Color> onColorChanged;
+  final bool enableAlpha;
+  final bool embeddedText;
+  final bool disable;
+
+  @override
+  _ColorPickerInputState createState() => _ColorPickerInputState();
+}
+
+class _ColorPickerInputState extends State<ColorPickerInput> {
+  TextEditingController textEditingController = TextEditingController();
+  int inputColor = 0;
+
+  @override
+  void dispose() {
+    textEditingController.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (inputColor != widget.color.value) {
+      textEditingController.text = '#' +
+          widget.color.red.toRadixString(16).toUpperCase().padLeft(2, '0') +
+          widget.color.green.toRadixString(16).toUpperCase().padLeft(2, '0') +
+          widget.color.blue.toRadixString(16).toUpperCase().padLeft(2, '0') +
+          (widget.enableAlpha
+              ? widget.color.alpha
+                  .toRadixString(16)
+                  .toUpperCase()
+                  .padLeft(2, '0')
+              : '');
+    }
+    return Padding(
+      padding: const EdgeInsets.only(top: 6.0, left: 12.0, right: 12.0),
+      child: SizedBox(
+        width: double.infinity,
+        child: TextField(
+          enabled: !widget.disable,
+          controller: textEditingController,
+          style: TextStyle(
+            fontSize: 18,
+            color: Theme.of(context).colorScheme.onBackground,
+          ),
+          inputFormatters: [
+            UpperCaseTextFormatter(),
+            FilteringTextInputFormatter.allow(RegExp(kValidHexPattern)),
+          ],
+          decoration: InputDecoration(
+            isDense: true,
+            filled: true,
+            border: OutlineInputBorder(
+              borderRadius: BorderRadius.circular(12.0),
+              borderSide:
+                  const BorderSide(color: Colors.transparent, width: 0.0),
+            ),
+            enabledBorder: OutlineInputBorder(
+              borderRadius: BorderRadius.circular(12.0),
+              borderSide:
+                  const BorderSide(color: Colors.transparent, width: 0.0),
+            ),
+            focusedBorder: OutlineInputBorder(
+              borderRadius: BorderRadius.circular(12.0),
+              borderSide:
+                  const BorderSide(color: Colors.transparent, width: 0.0),
+            ),
+            contentPadding:
+                const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
+            fillColor: AppColors.of(context).text.withOpacity(.1),
+          ),
+          onChanged: (String value) {
+            String input = value;
+            if (value.length == 9) {
+              input = value.split('').getRange(7, 9).join() +
+                  value.split('').getRange(1, 7).join();
+            }
+            final Color? color = colorFromHex(input);
+            if (color != null) {
+              widget.onColorChanged(color);
+              inputColor = color.value;
+            }
+          },
+        ),
+      ),
+    );
+  }
+}
+
+/*class ValueColorPickerSlider extends StatefulWidget {
+  ValueColorPickerSlider(this.trackType, this.initialHsvColor, this.onProgressChanged, this.onColorChangeEnd, {Key? key}) : super(key: key);
+
+  final TrackType trackType;
+  final HSVColor initialHsvColor;
+  final void Function(double progress) onProgressChanged;
+  final void Function() onColorChangeEnd;
+
+  @override
+  State<ValueColorPickerSlider> createState() => _ValueColorPickerSliderState();
+}
+
+class _ValueColorPickerSliderState extends State<ValueColorPickerSlider> {
+  HSVColor hsvColor = HSVColor.fromColor(Colors.red);
+
+  @override
+  void initState() {
+    super.initState();
+    hsvColor = widget.initialHsvColor;
+  }
+
+  void slideEvent(RenderBox getBox, BoxConstraints box, Offset globalPosition) {
+    double localDx = getBox.globalToLocal(globalPosition).dx - 15.0;
+    double progress = localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0);
+    setState(() {
+      switch (widget.trackType) {
+        case TrackType.hue:
+          hsvColor = hsvColor.withHue(progress * 359);
+          break;
+        case TrackType.saturation:
+          hsvColor = hsvColor.withSaturation(progress);
+          break;
+        case TrackType.value:
+          hsvColor = hsvColor.withValue(progress);
+          break;
+        default:
+          break;
+      }
+    });
+    widget.onProgressChanged(progress);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return LayoutBuilder(builder: (BuildContext context, BoxConstraints box) {
+      double thumbOffset = 15.0;
+      Color thumbColor = Colors.white;
+      switch (widget.trackType) {
+        case TrackType.hue:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.hue / 360;
+          break;
+        case TrackType.saturation:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.saturation;
+          break;
+        case TrackType.value:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.value;
+          break;
+        default:
+          break;
+      }
+
+      return CustomMultiChildLayout(
+        delegate: _SliderLayout(),
+        children: <Widget>[
+          LayoutId(
+            id: _SliderLayout.track,
+            child: ClipRRect(
+              borderRadius: const BorderRadius.all(Radius.circular(50.0)),
+              child: CustomPaint(
+                  painter: TrackPainter(
+                TrackType.values.firstWhere((element) => element == widget.trackType),
+                hsvColor,
+              )),
+            ),
+          ),
+          LayoutId(
+            id: _SliderLayout.thumb,
+            child: Transform.translate(
+              offset: Offset(thumbOffset, 0.0),
+              child: CustomPaint(
+                painter: ThumbPainter(
+                  thumbColor: thumbColor,
+                  fullThumbColor: false,
+                ),
+              ),
+            ),
+          ),
+          LayoutId(
+            id: _SliderLayout.gestureContainer,
+            child: LayoutBuilder(
+              builder: (BuildContext context, BoxConstraints box) {
+                RenderBox? getBox = context.findRenderObject() as RenderBox?;
+                return GestureDetector(
+                  onPanDown: (DragDownDetails details) => getBox != null ? slideEvent(getBox, box, details.globalPosition) : null,
+                  onPanEnd: (details) => widget.onColorChangeEnd(),
+                  onPanUpdate: (DragUpdateDetails details) => getBox != null ? slideEvent(getBox, box, details.globalPosition) : null,
+                );
+              },
+            ),
+          ),
+        ],
+      );
+    });
+  }
+}*/
+
+/// 9 track types for slider picker widget.
+class ColorPickerSlider extends StatelessWidget {
+  const ColorPickerSlider(
+    this.trackType,
+    this.hsvColor,
+    this.onColorChanged,
+    this.onColorChangeEnd,
+    this.onProblem, {
+    Key? key,
+    this.displayThumbColor = false,
+    this.fullThumbColor = false,
+  }) : super(key: key);
+
+  final TrackType trackType;
+  final HSVColor hsvColor;
+  final ValueChanged<HSVColor> onColorChanged;
+  final void Function() onColorChangeEnd;
+  final void Function(int v) onProblem;
+  final bool displayThumbColor;
+  final bool fullThumbColor;
+
+  void slideEvent(RenderBox getBox, BoxConstraints box, Offset globalPosition) {
+    double localDx = getBox.globalToLocal(globalPosition).dx - 15.0;
+    double progress =
+        localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0);
+    switch (trackType) {
+      case TrackType.hue:
+        // 360 is the same as zero
+        // if set to 360, sliding to end goes to zero
+        final newColor = hsvColor.withHue(progress * 359);
+        if (newColor.saturation == 0) {
+          onProblem(0);
+          return;
+        }
+        onColorChanged(newColor);
+        break;
+      case TrackType.saturation:
+        final newColor = hsvColor.withSaturation(progress);
+        if (newColor.value == 0) {
+          onProblem(1);
+          return;
+        }
+        onColorChanged(newColor);
+        break;
+      case TrackType.value:
+        onColorChanged(hsvColor.withValue(progress));
+        break;
+      default:
+        break;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return LayoutBuilder(builder: (BuildContext context, BoxConstraints box) {
+      double thumbOffset = 15.0;
+      Color thumbColor;
+      switch (trackType) {
+        case TrackType.hue:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.hue / 360;
+          thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, 1.0).toColor();
+          break;
+        case TrackType.saturation:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.saturation;
+          thumbColor =
+              HSVColor.fromAHSV(1.0, hsvColor.hue, hsvColor.saturation, 1.0)
+                  .toColor();
+          break;
+        case TrackType.saturationForHSL:
+          thumbOffset += (box.maxWidth - 30.0) * hsvToHsl(hsvColor).saturation;
+          thumbColor = HSLColor.fromAHSL(
+                  1.0, hsvColor.hue, hsvToHsl(hsvColor).saturation, 0.5)
+              .toColor();
+          break;
+        case TrackType.value:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.value;
+          thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, hsvColor.value)
+              .toColor();
+          break;
+        case TrackType.lightness:
+          thumbOffset += (box.maxWidth - 30.0) * hsvToHsl(hsvColor).lightness;
+          thumbColor = HSLColor.fromAHSL(
+                  1.0, hsvColor.hue, 1.0, hsvToHsl(hsvColor).lightness)
+              .toColor();
+          break;
+        case TrackType.red:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().red / 0xff;
+          thumbColor = hsvColor.toColor().withOpacity(1.0);
+          break;
+        case TrackType.green:
+          thumbOffset +=
+              (box.maxWidth - 30.0) * hsvColor.toColor().green / 0xff;
+          thumbColor = hsvColor.toColor().withOpacity(1.0);
+          break;
+        case TrackType.blue:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().blue / 0xff;
+          thumbColor = hsvColor.toColor().withOpacity(1.0);
+          break;
+        case TrackType.alpha:
+          thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().opacity;
+          thumbColor = hsvColor.toColor().withOpacity(hsvColor.alpha);
+          break;
+      }
+
+      return CustomMultiChildLayout(
+        delegate: _SliderLayout(),
+        children: <Widget>[
+          LayoutId(
+            id: _SliderLayout.track,
+            child: ClipRRect(
+              borderRadius: const BorderRadius.all(Radius.circular(50.0)),
+              child: CustomPaint(
+                  painter: TrackPainter(
+                trackType,
+                hsvColor,
+              )),
+            ),
+          ),
+          LayoutId(
+            id: _SliderLayout.thumb,
+            child: Transform.translate(
+              offset: Offset(thumbOffset, 0.0),
+              child: CustomPaint(
+                painter: ThumbPainter(
+                  thumbColor: displayThumbColor ? thumbColor : null,
+                  fullThumbColor: fullThumbColor,
+                ),
+              ),
+            ),
+          ),
+          LayoutId(
+            id: _SliderLayout.gestureContainer,
+            child: LayoutBuilder(
+              builder: (BuildContext context, BoxConstraints box) {
+                RenderBox? getBox = context.findRenderObject() as RenderBox?;
+                return GestureDetector(
+                  onPanDown: (DragDownDetails details) => getBox != null
+                      ? slideEvent(getBox, box, details.globalPosition)
+                      : null,
+                  onPanEnd: (details) {
+                    if ((trackType == TrackType.hue &&
+                            hsvColor.saturation == 0) ||
+                        (trackType == TrackType.saturation &&
+                            hsvColor.value == 0)) {
+                      return;
+                    }
+                    onColorChangeEnd();
+                  },
+                  onPanUpdate: (DragUpdateDetails details) => getBox != null
+                      ? slideEvent(getBox, box, details.globalPosition)
+                      : null,
+                );
+              },
+            ),
+          ),
+        ],
+      );
+    });
+  }
+}
+
+/// Simple round color indicator.
+class ColorIndicator extends StatelessWidget {
+  const ColorIndicator(
+    this.hsvColor, {
+    Key? key,
+    this.currentHsvColor,
+    this.icon,
+    this.width = 50.0,
+    this.height = 50.0,
+    this.adaptive = false,
+  }) : super(key: key);
+
+  final HSVColor hsvColor;
+  final HSVColor? currentHsvColor;
+  final double width;
+  final double height;
+  final IconData? icon;
+  final bool adaptive;
+
+  @override
+  Widget build(BuildContext context) {
+    Color color = hsvColor.toColor();
+
+    return Container(
+      width: width,
+      height: height,
+      decoration: BoxDecoration(
+        shape: BoxShape.circle,
+        color: color,
+        boxShadow: [
+          BoxShadow(
+              color: useWhiteForeground(color)
+                  ? Colors.white.withOpacity(.5)
+                  : Colors.black.withOpacity(.5),
+              offset: const Offset(0, 0),
+              blurRadius: 5)
+        ],
+      ),
+      child: Material(
+        color: Colors.transparent,
+        child: AnimatedOpacity(
+          duration: const Duration(milliseconds: 210),
+          opacity: (icon != null || currentHsvColor == hsvColor) &&
+                  (adaptive ||
+                      Provider.of<SettingsProvider>(context, listen: false)
+                              .accentColor !=
+                          AccentColor.adaptive)
+              ? 1
+              : 0,
+          child: Icon(icon ?? Icons.done,
+              color: useWhiteForeground(color) ? Colors.white : Colors.black),
+        ),
+      ),
+    );
+  }
+}
+
+/// Provide Rectangle & Circle 2 categories, 10 variations of palette widget.
+class ColorPickerArea extends StatelessWidget {
+  const ColorPickerArea(
+    this.hsvColor,
+    this.onColorChanged,
+    this.onChangeEnd,
+    this.paletteType, {
+    Key? key,
+  }) : super(key: key);
+
+  final HSVColor hsvColor;
+  final ValueChanged<HSVColor> onColorChanged;
+  final void Function() onChangeEnd;
+  final PaletteType paletteType;
+
+  /*void _handleColorRectChange(double horizontal, double vertical) {
+    onColorChanged(hsvColor.withSaturation(horizontal).withValue(vertical));
+  }*/
+
+  void _handleGesture(
+      Offset position, BuildContext context, double height, double width) {
+    RenderBox? getBox = context.findRenderObject() as RenderBox?;
+    if (getBox == null) return;
+
+    Offset localOffset = getBox.globalToLocal(position);
+    double horizontal = localOffset.dx.clamp(0.0, width);
+    double vertical = localOffset.dy.clamp(0.0, height);
+
+    //_handleColorRectChange(horizontal / width, 1 - vertical / height);
+
+    onColorChanged(hsvColor.withSaturation(horizontal).withValue(vertical));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return LayoutBuilder(
+      builder: (BuildContext context, BoxConstraints constraints) {
+        double width = constraints.maxWidth;
+        double height = constraints.maxHeight;
+
+        return RawGestureDetector(
+          gestures: {
+            _AlwaysWinPanGestureRecognizer:
+                GestureRecognizerFactoryWithHandlers<
+                    _AlwaysWinPanGestureRecognizer>(
+              () => _AlwaysWinPanGestureRecognizer(),
+              (_AlwaysWinPanGestureRecognizer instance) {
+                instance
+                  ..onDown = ((details) => _handleGesture(
+                      details.globalPosition, context, height, width))
+                  ..onEnd = ((d) => onChangeEnd())
+                  ..onUpdate = ((details) => _handleGesture(
+                      details.globalPosition, context, height, width));
+              },
+            ),
+          },
+          child: Builder(
+            builder: (BuildContext _) {
+              return CustomPaint(painter: HSVWithHueColorPainter(hsvColor));
+            },
+          ),
+        );
+      },
+    );
+  }
+}
+
+class _AlwaysWinPanGestureRecognizer extends PanGestureRecognizer {
+  @override
+  void addAllowedPointer(event) {
+    super.addAllowedPointer(event);
+    resolve(GestureDisposition.accepted);
+  }
+
+  @override
+  String get debugDescription => 'alwaysWin';
+}
+
+/// Uppercase text formater
+class UpperCaseTextFormatter extends TextInputFormatter {
+  @override
+  TextEditingValue formatEditUpdate(oldValue, TextEditingValue newValue) =>
+      TextEditingValue(
+          text: newValue.text.toUpperCase(), selection: newValue.selection);
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/utils.dart b/refilc_premium/lib/ui/mobile/flutter_colorpicker/utils.dart
similarity index 97%
rename from filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/utils.dart
rename to refilc_premium/lib/ui/mobile/flutter_colorpicker/utils.dart
index 5e413a7..515ae1f 100644
--- a/filcnaplo_premium/lib/ui/mobile/flutter_colorpicker/utils.dart
+++ b/refilc_premium/lib/ui/mobile/flutter_colorpicker/utils.dart
@@ -1,220 +1,220 @@
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-// FROM: https://pub.dev/packages/flutter_colorpicker
-
-/// Common function lib
-
-import 'dart:math';
-import 'package:flutter/painting.dart';
-import 'colors.dart';
-
-/// Check if is good condition to use white foreground color by passing
-/// the background color, and optional bias.
-///
-/// Reference:
-///
-/// Old: https://www.w3.org/TR/WCAG20-TECHS/G18.html
-///
-/// New: https://github.com/mchome/flutter_statusbarcolor/issues/40
-bool useWhiteForeground(Color backgroundColor, {double bias = 0.0}) {
-  // Old:
-  // return 1.05 / (color.computeLuminance() + 0.05) > 4.5;
-
-  // New:
-  int v = sqrt(pow(backgroundColor.red, 2) * 0.299 +
-          pow(backgroundColor.green, 2) * 0.587 +
-          pow(backgroundColor.blue, 2) * 0.114)
-      .round();
-  return v < 130 + bias ? true : false;
-}
-
-/// Convert HSV to HSL
-///
-/// Reference: https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_HSL
-HSLColor hsvToHsl(HSVColor color) {
-  double s = 0.0;
-  double l = 0.0;
-  l = (2 - color.saturation) * color.value / 2;
-  if (l != 0) {
-    if (l == 1) {
-      s = 0.0;
-    } else if (l < 0.5) {
-      s = color.saturation * color.value / (l * 2);
-    } else {
-      s = color.saturation * color.value / (2 - l * 2);
-    }
-  }
-  return HSLColor.fromAHSL(
-    color.alpha,
-    color.hue,
-    s.clamp(0.0, 1.0),
-    l.clamp(0.0, 1.0),
-  );
-}
-
-/// Convert HSL to HSV
-///
-/// Reference: https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_HSV
-HSVColor hslToHsv(HSLColor color) {
-  double s = 0.0;
-  double v = 0.0;
-
-  v = color.lightness + color.saturation * (color.lightness < 0.5 ? color.lightness : 1 - color.lightness);
-  if (v != 0) s = 2 - 2 * color.lightness / v;
-
-  return HSVColor.fromAHSV(
-    color.alpha,
-    color.hue,
-    s.clamp(0.0, 1.0),
-    v.clamp(0.0, 1.0),
-  );
-}
-
-/// [RegExp] pattern for validation HEX color [String] inputs, allows only:
-///
-/// * exactly 1 to 8 digits in HEX format,
-/// * only Latin A-F characters, case insensitive,
-/// * and integer numbers 0,1,2,3,4,5,6,7,8,9,
-/// * with optional hash (`#`) symbol at the beginning (not calculated in length).
-///
-/// ```dart
-/// final RegExp hexInputValidator = RegExp(kValidHexPattern);
-/// if (hexInputValidator.hasMatch(hex)) print('$hex might be a valid HEX color');
-/// ```
-/// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet
-const String kValidHexPattern = r'^#?[0-9a-fA-F]{1,8}';
-
-/// [RegExp] pattern for validation complete HEX color [String], allows only:
-///
-/// * exactly 6 or 8 digits in HEX format,
-/// * only Latin A-F characters, case insensitive,
-/// * and integer numbers 0,1,2,3,4,5,6,7,8,9,
-/// * with optional hash (`#`) symbol at the beginning (not calculated in length).
-///
-/// ```dart
-/// final RegExp hexCompleteValidator = RegExp(kCompleteValidHexPattern);
-/// if (hexCompleteValidator.hasMatch(hex)) print('$hex is valid HEX color');
-/// ```
-/// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet
-const String kCompleteValidHexPattern = r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$';
-
-/// Try to convert text input or any [String] to valid [Color].
-/// The [String] must be provided in one of those formats:
-///
-/// * RGB
-/// * #RGB
-/// * RRGGBB
-/// * #RRGGBB
-/// * AARRGGBB
-/// * #AARRGGBB
-///
-/// Where: A stands for Alpha, R for Red, G for Green, and B for blue color.
-/// It will only accept 3/6/8 long HEXs with an optional hash (`#`) at the beginning.
-/// Allowed characters are Latin A-F case insensitive and numbers 0-9.
-/// Optional [enableAlpha] can be provided (it's `true` by default). If it's set
-/// to `false` transparency information (alpha channel) will be removed.
-/// ```dart
-/// /// // Valid 3 digit HEXs:
-/// colorFromHex('abc') == Color(0xffaabbcc)
-/// colorFromHex('ABc') == Color(0xffaabbcc)
-/// colorFromHex('ABC') == Color(0xffaabbcc)
-/// colorFromHex('#Abc') == Color(0xffaabbcc)
-/// colorFromHex('#abc') == Color(0xffaabbcc)
-/// colorFromHex('#ABC') == Color(0xffaabbcc)
-/// // Valid 6 digit HEXs:
-/// colorFromHex('aabbcc') == Color(0xffaabbcc)
-/// colorFromHex('AABbcc') == Color(0xffaabbcc)
-/// colorFromHex('AABBCC') == Color(0xffaabbcc)
-/// colorFromHex('#AABbcc') == Color(0xffaabbcc)
-/// colorFromHex('#aabbcc') == Color(0xffaabbcc)
-/// colorFromHex('#AABBCC') == Color(0xffaabbcc)
-/// // Valid 8 digit HEXs:
-/// colorFromHex('ffaabbcc') == Color(0xffaabbcc)
-/// colorFromHex('ffAABbcc') == Color(0xffaabbcc)
-/// colorFromHex('ffAABBCC') == Color(0xffaabbcc)
-/// colorFromHex('ffaabbcc', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('FFAAbbcc', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('ffAABBCC', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('FFaabbcc', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('#ffaabbcc') == Color(0xffaabbcc)
-/// colorFromHex('#ffAABbcc') == Color(0xffaabbcc)
-/// colorFromHex('#FFAABBCC') == Color(0xffaabbcc)
-/// colorFromHex('#ffaabbcc', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('#FFAAbbcc', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('#ffAABBCC', enableAlpha: true) == Color(0xffaabbcc)
-/// colorFromHex('#FFaabbcc', enableAlpha: true) == Color(0xffaabbcc)
-/// // Invalid HEXs:
-/// colorFromHex('bc') == null // length 2
-/// colorFromHex('aabbc') == null // length 5
-/// colorFromHex('#ffaabbccd') == null // length 9 (+#)
-/// colorFromHex('aabbcx') == null // x character
-/// colorFromHex('#aabbвв') == null // в non-latin character
-/// colorFromHex('') == null // empty
-/// ```
-/// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet
-Color? colorFromHex(String inputString, {bool enableAlpha = true}) {
-  // Registers validator for exactly 6 or 8 digits long HEX (with optional #).
-  final RegExp hexValidator = RegExp(kCompleteValidHexPattern);
-  // Validating input, if it does not match — it's not proper HEX.
-  if (!hexValidator.hasMatch(inputString)) return null;
-  // Remove optional hash if exists and convert HEX to UPPER CASE.
-  String hexToParse = inputString.replaceFirst('#', '').toUpperCase();
-  // It may allow HEXs with transparency information even if alpha is disabled,
-  if (!enableAlpha && hexToParse.length == 8) {
-    // but it will replace this info with 100% non-transparent value (FF).
-    hexToParse = 'FF${hexToParse.substring(2)}';
-  }
-  // HEX may be provided in 3-digits format, let's just duplicate each letter.
-  if (hexToParse.length == 3) {
-    hexToParse = hexToParse.split('').expand((i) => [i * 2]).join();
-  }
-  // We will need 8 digits to parse the color, let's add missing digits.
-  if (hexToParse.length == 6) hexToParse = 'FF$hexToParse';
-  // HEX must be valid now, but as a precaution, it will just "try" to parse it.
-  final intColorValue = int.tryParse(hexToParse, radix: 16);
-  // If for some reason HEX is not valid — abort the operation, return nothing.
-  if (intColorValue == null) return null;
-  // Register output color for the last step.
-  final color = Color(intColorValue);
-  // Decide to return color with transparency information or not.
-  return enableAlpha ? color : color.withAlpha(255);
-}
-
-/// Converts `dart:ui` [Color] to the 6/8 digits HEX [String].
-///
-/// Prefixes a hash (`#`) sign if [includeHashSign] is set to `true`.
-/// The result will be provided as UPPER CASE, it can be changed via [toUpperCase]
-/// flag set to `false` (default is `true`). Hex can be returned without alpha
-/// channel information (transparency), with the [enableAlpha] flag set to `false`.
-String colorToHex(
-  Color color, {
-  bool includeHashSign = false,
-  bool enableAlpha = true,
-  bool toUpperCase = true,
-}) {
-  final String hex = (includeHashSign ? '#' : '') +
-      (enableAlpha ? _padRadix(color.alpha) : '') +
-      _padRadix(color.red) +
-      _padRadix(color.green) +
-      _padRadix(color.blue);
-  return toUpperCase ? hex.toUpperCase() : hex;
-}
-
-// Shorthand for padLeft of RadixString, DRY.
-String _padRadix(int value) => value.toRadixString(16).padLeft(2, '0');
-
-// Extension for String
-extension ColorExtension1 on String {
-  Color? toColor() {
-    Color? color = colorFromName(this);
-    if (color != null) return color;
-    return colorFromHex(this);
-  }
-}
-
-// Extension from Color
-extension ColorExtension2 on Color {
-  String toHexString({bool includeHashSign = false, bool enableAlpha = true, bool toUpperCase = true}) =>
-      colorToHex(this, includeHashSign: false, enableAlpha: true, toUpperCase: true);
-}
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+// FROM: https://pub.dev/packages/flutter_colorpicker
+
+/// Common function lib
+
+import 'dart:math';
+import 'package:flutter/painting.dart';
+import 'colors.dart';
+
+/// Check if is good condition to use white foreground color by passing
+/// the background color, and optional bias.
+///
+/// Reference:
+///
+/// Old: https://www.w3.org/TR/WCAG20-TECHS/G18.html
+///
+/// New: https://github.com/mchome/flutter_statusbarcolor/issues/40
+bool useWhiteForeground(Color backgroundColor, {double bias = 0.0}) {
+  // Old:
+  // return 1.05 / (color.computeLuminance() + 0.05) > 4.5;
+
+  // New:
+  int v = sqrt(pow(backgroundColor.red, 2) * 0.299 +
+          pow(backgroundColor.green, 2) * 0.587 +
+          pow(backgroundColor.blue, 2) * 0.114)
+      .round();
+  return v < 130 + bias ? true : false;
+}
+
+/// Convert HSV to HSL
+///
+/// Reference: https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_HSL
+HSLColor hsvToHsl(HSVColor color) {
+  double s = 0.0;
+  double l = 0.0;
+  l = (2 - color.saturation) * color.value / 2;
+  if (l != 0) {
+    if (l == 1) {
+      s = 0.0;
+    } else if (l < 0.5) {
+      s = color.saturation * color.value / (l * 2);
+    } else {
+      s = color.saturation * color.value / (2 - l * 2);
+    }
+  }
+  return HSLColor.fromAHSL(
+    color.alpha,
+    color.hue,
+    s.clamp(0.0, 1.0),
+    l.clamp(0.0, 1.0),
+  );
+}
+
+/// Convert HSL to HSV
+///
+/// Reference: https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_HSV
+HSVColor hslToHsv(HSLColor color) {
+  double s = 0.0;
+  double v = 0.0;
+
+  v = color.lightness + color.saturation * (color.lightness < 0.5 ? color.lightness : 1 - color.lightness);
+  if (v != 0) s = 2 - 2 * color.lightness / v;
+
+  return HSVColor.fromAHSV(
+    color.alpha,
+    color.hue,
+    s.clamp(0.0, 1.0),
+    v.clamp(0.0, 1.0),
+  );
+}
+
+/// [RegExp] pattern for validation HEX color [String] inputs, allows only:
+///
+/// * exactly 1 to 8 digits in HEX format,
+/// * only Latin A-F characters, case insensitive,
+/// * and integer numbers 0,1,2,3,4,5,6,7,8,9,
+/// * with optional hash (`#`) symbol at the beginning (not calculated in length).
+///
+/// ```dart
+/// final RegExp hexInputValidator = RegExp(kValidHexPattern);
+/// if (hexInputValidator.hasMatch(hex)) print('$hex might be a valid HEX color');
+/// ```
+/// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet
+const String kValidHexPattern = r'^#?[0-9a-fA-F]{1,8}';
+
+/// [RegExp] pattern for validation complete HEX color [String], allows only:
+///
+/// * exactly 6 or 8 digits in HEX format,
+/// * only Latin A-F characters, case insensitive,
+/// * and integer numbers 0,1,2,3,4,5,6,7,8,9,
+/// * with optional hash (`#`) symbol at the beginning (not calculated in length).
+///
+/// ```dart
+/// final RegExp hexCompleteValidator = RegExp(kCompleteValidHexPattern);
+/// if (hexCompleteValidator.hasMatch(hex)) print('$hex is valid HEX color');
+/// ```
+/// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet
+const String kCompleteValidHexPattern = r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$';
+
+/// Try to convert text input or any [String] to valid [Color].
+/// The [String] must be provided in one of those formats:
+///
+/// * RGB
+/// * #RGB
+/// * RRGGBB
+/// * #RRGGBB
+/// * AARRGGBB
+/// * #AARRGGBB
+///
+/// Where: A stands for Alpha, R for Red, G for Green, and B for blue color.
+/// It will only accept 3/6/8 long HEXs with an optional hash (`#`) at the beginning.
+/// Allowed characters are Latin A-F case insensitive and numbers 0-9.
+/// Optional [enableAlpha] can be provided (it's `true` by default). If it's set
+/// to `false` transparency information (alpha channel) will be removed.
+/// ```dart
+/// /// // Valid 3 digit HEXs:
+/// colorFromHex('abc') == Color(0xffaabbcc)
+/// colorFromHex('ABc') == Color(0xffaabbcc)
+/// colorFromHex('ABC') == Color(0xffaabbcc)
+/// colorFromHex('#Abc') == Color(0xffaabbcc)
+/// colorFromHex('#abc') == Color(0xffaabbcc)
+/// colorFromHex('#ABC') == Color(0xffaabbcc)
+/// // Valid 6 digit HEXs:
+/// colorFromHex('aabbcc') == Color(0xffaabbcc)
+/// colorFromHex('AABbcc') == Color(0xffaabbcc)
+/// colorFromHex('AABBCC') == Color(0xffaabbcc)
+/// colorFromHex('#AABbcc') == Color(0xffaabbcc)
+/// colorFromHex('#aabbcc') == Color(0xffaabbcc)
+/// colorFromHex('#AABBCC') == Color(0xffaabbcc)
+/// // Valid 8 digit HEXs:
+/// colorFromHex('ffaabbcc') == Color(0xffaabbcc)
+/// colorFromHex('ffAABbcc') == Color(0xffaabbcc)
+/// colorFromHex('ffAABBCC') == Color(0xffaabbcc)
+/// colorFromHex('ffaabbcc', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('FFAAbbcc', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('ffAABBCC', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('FFaabbcc', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('#ffaabbcc') == Color(0xffaabbcc)
+/// colorFromHex('#ffAABbcc') == Color(0xffaabbcc)
+/// colorFromHex('#FFAABBCC') == Color(0xffaabbcc)
+/// colorFromHex('#ffaabbcc', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('#FFAAbbcc', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('#ffAABBCC', enableAlpha: true) == Color(0xffaabbcc)
+/// colorFromHex('#FFaabbcc', enableAlpha: true) == Color(0xffaabbcc)
+/// // Invalid HEXs:
+/// colorFromHex('bc') == null // length 2
+/// colorFromHex('aabbc') == null // length 5
+/// colorFromHex('#ffaabbccd') == null // length 9 (+#)
+/// colorFromHex('aabbcx') == null // x character
+/// colorFromHex('#aabbвв') == null // в non-latin character
+/// colorFromHex('') == null // empty
+/// ```
+/// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet
+Color? colorFromHex(String inputString, {bool enableAlpha = true}) {
+  // Registers validator for exactly 6 or 8 digits long HEX (with optional #).
+  final RegExp hexValidator = RegExp(kCompleteValidHexPattern);
+  // Validating input, if it does not match — it's not proper HEX.
+  if (!hexValidator.hasMatch(inputString)) return null;
+  // Remove optional hash if exists and convert HEX to UPPER CASE.
+  String hexToParse = inputString.replaceFirst('#', '').toUpperCase();
+  // It may allow HEXs with transparency information even if alpha is disabled,
+  if (!enableAlpha && hexToParse.length == 8) {
+    // but it will replace this info with 100% non-transparent value (FF).
+    hexToParse = 'FF${hexToParse.substring(2)}';
+  }
+  // HEX may be provided in 3-digits format, let's just duplicate each letter.
+  if (hexToParse.length == 3) {
+    hexToParse = hexToParse.split('').expand((i) => [i * 2]).join();
+  }
+  // We will need 8 digits to parse the color, let's add missing digits.
+  if (hexToParse.length == 6) hexToParse = 'FF$hexToParse';
+  // HEX must be valid now, but as a precaution, it will just "try" to parse it.
+  final intColorValue = int.tryParse(hexToParse, radix: 16);
+  // If for some reason HEX is not valid — abort the operation, return nothing.
+  if (intColorValue == null) return null;
+  // Register output color for the last step.
+  final color = Color(intColorValue);
+  // Decide to return color with transparency information or not.
+  return enableAlpha ? color : color.withAlpha(255);
+}
+
+/// Converts `dart:ui` [Color] to the 6/8 digits HEX [String].
+///
+/// Prefixes a hash (`#`) sign if [includeHashSign] is set to `true`.
+/// The result will be provided as UPPER CASE, it can be changed via [toUpperCase]
+/// flag set to `false` (default is `true`). Hex can be returned without alpha
+/// channel information (transparency), with the [enableAlpha] flag set to `false`.
+String colorToHex(
+  Color color, {
+  bool includeHashSign = false,
+  bool enableAlpha = true,
+  bool toUpperCase = true,
+}) {
+  final String hex = (includeHashSign ? '#' : '') +
+      (enableAlpha ? _padRadix(color.alpha) : '') +
+      _padRadix(color.red) +
+      _padRadix(color.green) +
+      _padRadix(color.blue);
+  return toUpperCase ? hex.toUpperCase() : hex;
+}
+
+// Shorthand for padLeft of RadixString, DRY.
+String _padRadix(int value) => value.toRadixString(16).padLeft(2, '0');
+
+// Extension for String
+extension ColorExtension1 on String {
+  Color? toColor() {
+    Color? color = colorFromName(this);
+    if (color != null) return color;
+    return colorFromHex(this);
+  }
+}
+
+// Extension from Color
+extension ColorExtension2 on Color {
+  String toHexString({bool includeHashSign = false, bool enableAlpha = true, bool toUpperCase = true}) =>
+      colorToHex(this, includeHashSign: false, enableAlpha: true, toUpperCase: true);
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_complete_modal.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_complete_modal.dart
similarity index 95%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_complete_modal.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_complete_modal.dart
index 0b2d9c1..a68ce82 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_complete_modal.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/goal_complete_modal.dart
@@ -1,9 +1,9 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_input.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_input.dart
similarity index 95%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_input.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_input.dart
index 6fdfe54..f440a4e 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_input.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/goal_input.dart
@@ -1,180 +1,180 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
-
-class GoalInput extends StatelessWidget {
-  const GoalInput(
-      {Key? key,
-      required this.currentAverage,
-      required this.value,
-      required this.onChanged})
-      : super(key: key);
-
-  final double currentAverage;
-  final double value;
-  final void Function(double value) onChanged;
-
-  void offsetToValue(Offset offset, Size size) {
-    double v = ((offset.dx / size.width * 4 + 1) * 10).round() / 10;
-    v = v.clamp(1.5, 5);
-    v = v.clamp(((currentAverage * 10).round() / 10), 5);
-    setValue(v);
-  }
-
-  void setValue(double v) {
-    if (v != value) {
-      HapticFeedback.lightImpact();
-    }
-    onChanged(v);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    SettingsProvider settings = Provider.of<SettingsProvider>(context);
-
-    List<int> presets = [2, 3, 4, 5];
-    presets = presets.where((e) => gradeToAvg(e) > currentAverage).toList();
-
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      children: [
-        LayoutBuilder(builder: (context, size) {
-          return GestureDetector(
-            onTapDown: (details) {
-              offsetToValue(details.localPosition, size.biggest);
-            },
-            onHorizontalDragUpdate: (details) {
-              offsetToValue(details.localPosition, size.biggest);
-            },
-            child: SizedBox(
-              height: 32.0,
-              width: double.infinity,
-              child: Padding(
-                padding: const EdgeInsets.only(right: 20.0),
-                child: CustomPaint(
-                  painter: GoalSliderPainter(
-                      value: (value - 1) / 4, settings: settings),
-                ),
-              ),
-            ),
-          );
-        }),
-        const SizedBox(height: 12.0),
-        Row(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: presets.map((e) {
-            final pv = (value * 10).round() / 10;
-            final selected = gradeToAvg(e) == pv;
-            return Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 12.0),
-              child: Container(
-                decoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(99.0),
-                  color:
-                      gradeColor(e, settings).withOpacity(selected ? 1.0 : 0.2),
-                  border: Border.all(color: gradeColor(e, settings), width: 4),
-                ),
-                child: Material(
-                  type: MaterialType.transparency,
-                  child: InkWell(
-                    borderRadius: BorderRadius.circular(99.0),
-                    onTap: () => setValue(gradeToAvg(e)),
-                    child: Padding(
-                      padding: const EdgeInsets.symmetric(
-                          vertical: 2.0, horizontal: 24.0),
-                      child: Text(
-                        e.toString(),
-                        style: TextStyle(
-                          color:
-                              selected ? Colors.white : gradeColor(e, settings),
-                          fontWeight: FontWeight.bold,
-                          fontSize: 24.0,
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ),
-            );
-          }).toList(),
-        )
-      ],
-    );
-  }
-}
-
-class GoalSliderPainter extends CustomPainter {
-  final double value;
-  final SettingsProvider settings;
-
-  GoalSliderPainter({required this.value, required this.settings});
-
-  @override
-  void paint(Canvas canvas, Size size) {
-    final radius = size.height / 2;
-    const cpadding = 4;
-    final rect = Rect.fromLTWH(0, 0, size.width + radius, size.height);
-    final vrect = Rect.fromLTWH(0, 0, size.width * value + radius, size.height);
-    canvas.drawRRect(
-      RRect.fromRectAndRadius(
-        rect,
-        const Radius.circular(99.0),
-      ),
-      Paint()..color = Colors.black.withOpacity(.1),
-    );
-    canvas.drawRRect(
-      RRect.fromRectAndRadius(
-        vrect,
-        const Radius.circular(99.0),
-      ),
-      Paint()
-        ..shader = LinearGradient(colors: [
-          settings.gradeColors[0],
-          settings.gradeColors[1],
-          settings.gradeColors[2],
-          settings.gradeColors[3],
-          settings.gradeColors[4],
-        ]).createShader(rect),
-    );
-    canvas.drawOval(
-      Rect.fromCircle(
-          center: Offset(size.width * value, size.height / 2),
-          radius: radius - cpadding),
-      Paint()..color = Colors.white,
-    );
-    for (int i = 1; i < 4; i++) {
-      canvas.drawOval(
-        Rect.fromCircle(
-            center: Offset(size.width / 4 * i, size.height / 2), radius: 4),
-        Paint()..color = Colors.white.withOpacity(.5),
-      );
-    }
-  }
-
-  @override
-  bool shouldRepaint(GoalSliderPainter oldDelegate) {
-    return oldDelegate.value != value;
-  }
-}
-
-double gradeToAvg(int grade) {
-  return grade - 0.5;
-}
-
-Color gradeColor(int grade, SettingsProvider settings) {
-  // return [
-  //   const Color(0xffFF3B30),
-  //   const Color(0xffFF9F0A),
-  //   const Color(0xffFFD60A),
-  //   const Color(0xff34C759),
-  //   const Color(0xff247665),
-  // ].elementAt(grade.clamp(1, 5) - 1);
-  return [
-    settings.gradeColors[0],
-    settings.gradeColors[1],
-    settings.gradeColors[2],
-    settings.gradeColors[3],
-    settings.gradeColors[4],
-  ].elementAt(grade.clamp(1, 5) - 1);
-}
+import 'package:refilc/models/settings.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
+
+class GoalInput extends StatelessWidget {
+  const GoalInput(
+      {Key? key,
+      required this.currentAverage,
+      required this.value,
+      required this.onChanged})
+      : super(key: key);
+
+  final double currentAverage;
+  final double value;
+  final void Function(double value) onChanged;
+
+  void offsetToValue(Offset offset, Size size) {
+    double v = ((offset.dx / size.width * 4 + 1) * 10).round() / 10;
+    v = v.clamp(1.5, 5);
+    v = v.clamp(((currentAverage * 10).round() / 10), 5);
+    setValue(v);
+  }
+
+  void setValue(double v) {
+    if (v != value) {
+      HapticFeedback.lightImpact();
+    }
+    onChanged(v);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsProvider settings = Provider.of<SettingsProvider>(context);
+
+    List<int> presets = [2, 3, 4, 5];
+    presets = presets.where((e) => gradeToAvg(e) > currentAverage).toList();
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        LayoutBuilder(builder: (context, size) {
+          return GestureDetector(
+            onTapDown: (details) {
+              offsetToValue(details.localPosition, size.biggest);
+            },
+            onHorizontalDragUpdate: (details) {
+              offsetToValue(details.localPosition, size.biggest);
+            },
+            child: SizedBox(
+              height: 32.0,
+              width: double.infinity,
+              child: Padding(
+                padding: const EdgeInsets.only(right: 20.0),
+                child: CustomPaint(
+                  painter: GoalSliderPainter(
+                      value: (value - 1) / 4, settings: settings),
+                ),
+              ),
+            ),
+          );
+        }),
+        const SizedBox(height: 12.0),
+        Row(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: presets.map((e) {
+            final pv = (value * 10).round() / 10;
+            final selected = gradeToAvg(e) == pv;
+            return Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 12.0),
+              child: Container(
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(99.0),
+                  color:
+                      gradeColor(e, settings).withOpacity(selected ? 1.0 : 0.2),
+                  border: Border.all(color: gradeColor(e, settings), width: 4),
+                ),
+                child: Material(
+                  type: MaterialType.transparency,
+                  child: InkWell(
+                    borderRadius: BorderRadius.circular(99.0),
+                    onTap: () => setValue(gradeToAvg(e)),
+                    child: Padding(
+                      padding: const EdgeInsets.symmetric(
+                          vertical: 2.0, horizontal: 24.0),
+                      child: Text(
+                        e.toString(),
+                        style: TextStyle(
+                          color:
+                              selected ? Colors.white : gradeColor(e, settings),
+                          fontWeight: FontWeight.bold,
+                          fontSize: 24.0,
+                        ),
+                      ),
+                    ),
+                  ),
+                ),
+              ),
+            );
+          }).toList(),
+        )
+      ],
+    );
+  }
+}
+
+class GoalSliderPainter extends CustomPainter {
+  final double value;
+  final SettingsProvider settings;
+
+  GoalSliderPainter({required this.value, required this.settings});
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final radius = size.height / 2;
+    const cpadding = 4;
+    final rect = Rect.fromLTWH(0, 0, size.width + radius, size.height);
+    final vrect = Rect.fromLTWH(0, 0, size.width * value + radius, size.height);
+    canvas.drawRRect(
+      RRect.fromRectAndRadius(
+        rect,
+        const Radius.circular(99.0),
+      ),
+      Paint()..color = Colors.black.withOpacity(.1),
+    );
+    canvas.drawRRect(
+      RRect.fromRectAndRadius(
+        vrect,
+        const Radius.circular(99.0),
+      ),
+      Paint()
+        ..shader = LinearGradient(colors: [
+          settings.gradeColors[0],
+          settings.gradeColors[1],
+          settings.gradeColors[2],
+          settings.gradeColors[3],
+          settings.gradeColors[4],
+        ]).createShader(rect),
+    );
+    canvas.drawOval(
+      Rect.fromCircle(
+          center: Offset(size.width * value, size.height / 2),
+          radius: radius - cpadding),
+      Paint()..color = Colors.white,
+    );
+    for (int i = 1; i < 4; i++) {
+      canvas.drawOval(
+        Rect.fromCircle(
+            center: Offset(size.width / 4 * i, size.height / 2), radius: 4),
+        Paint()..color = Colors.white.withOpacity(.5),
+      );
+    }
+  }
+
+  @override
+  bool shouldRepaint(GoalSliderPainter oldDelegate) {
+    return oldDelegate.value != value;
+  }
+}
+
+double gradeToAvg(int grade) {
+  return grade - 0.5;
+}
+
+Color gradeColor(int grade, SettingsProvider settings) {
+  // return [
+  //   const Color(0xffFF3B30),
+  //   const Color(0xffFF9F0A),
+  //   const Color(0xffFFD60A),
+  //   const Color(0xff34C759),
+  //   const Color(0xff247665),
+  // ].elementAt(grade.clamp(1, 5) - 1);
+  return [
+    settings.gradeColors[0],
+    settings.gradeColors[1],
+    settings.gradeColors[2],
+    settings.gradeColors[3],
+    settings.gradeColors[4],
+  ].elementAt(grade.clamp(1, 5) - 1);
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_planner.dart
similarity index 92%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_planner.dart
index 22878a9..0fcc725 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/goal_planner.dart
@@ -1,191 +1,191 @@
-/* 
- * Maintainer: DarK
- * Translated from C version
- * Minimal Working Fixed @ 2022.12.25
- * ##Please do NOT modify if you don't know whats going on##
- * 
- * Issue: #59
- * 
- * Future changes / ideas:
- *  - `best` should be configurable
- */
-import 'dart:math';
-import 'package:filcnaplo_kreta_api/models/category.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/models/teacher.dart';
-import 'package:flutter/foundation.dart' show listEquals;
-
-/// Generate list of grades that achieve the wanted goal.
-/// After generating possible options, it (when doing so would NOT result in empty list) filters with two criteria:
-///  - Plan should not contain more than 15 grades
-///  - Plan should not contain only one type of grade
-///
-/// **Usage**:
-///
-/// ```dart
-/// List<int> GoalPlanner(double goal, List<Grade> grades).solve().plan
-/// ```
-class GoalPlanner {
-  final double goal;
-  final List<Grade> grades;
-  List<Plan> plans = [];
-  GoalPlanner(this.goal, this.grades);
-
-  bool _allowed(int grade) => grade > goal;
-
-  void _generate(Generator g) {
-    // Exit condition 1: Generator has working plan.
-    if (g.currentAvg.avg >= goal) {
-      plans.add(Plan(g.plan));
-      return;
-    }
-    // Exit condition 2: Generator plan will never work.
-    if (!_allowed(g.gradeToAdd)) {
-      return;
-    }
-
-    for (int i = g.max; i >= 0; i--) {
-      int newGradeToAdd = g.gradeToAdd - 1;
-      List<int> newPlan =
-          GoalPlannerHelper._addToList<int>(g.plan, g.gradeToAdd, i);
-
-      Avg newAvg = GoalPlannerHelper._addToAvg(g.currentAvg, g.gradeToAdd, i);
-      int newN = GoalPlannerHelper.howManyNeeded(
-          newGradeToAdd,
-          grades +
-              newPlan
-                  .map((e) => Grade(
-                        id: '',
-                        date: DateTime(0),
-                        value: GradeValue(e, '', '', 100),
-                        teacher: Teacher.fromString(''),
-                        description: '',
-                        form: '',
-                        groupId: '',
-                        type: GradeType.midYear,
-                        subject: Subject.fromJson({}),
-                        mode: Category.fromJson({}),
-                        seenDate: DateTime(0),
-                        writeDate: DateTime(0),
-                      ))
-                  .toList(),
-          goal);
-
-      _generate(Generator(newGradeToAdd, newN, newAvg, newPlan));
-    }
-  }
-
-  List<Plan> solve() {
-    _generate(
-      Generator(
-        5,
-        GoalPlannerHelper.howManyNeeded(
-          5,
-          grades,
-          goal,
-        ),
-        Avg(GoalPlannerHelper.averageEvals(grades),
-            GoalPlannerHelper.weightSum(grades)),
-        [],
-      ),
-    );
-
-    // Calculate Statistics
-    for (var e in plans) {
-      e.sum = e.plan.fold(0, (int a, b) => a + b);
-      e.avg = e.sum / e.plan.length;
-      e.sigma = sqrt(
-          e.plan.map((i) => pow(i - e.avg, 2)).fold(0, (num a, b) => a + b) /
-              e.plan.length);
-    }
-
-    // filter without aggression
-    if (plans.where((e) => e.plan.length < 30).isNotEmpty) {
-      plans.removeWhere((e) => !(e.plan.length < 30));
-    }
-    if (plans.where((e) => e.sigma > 1).isNotEmpty) {
-      plans.removeWhere((e) => !(e.sigma > 1));
-    }
-
-    return plans;
-  }
-}
-
-class Avg {
-  final double avg;
-  final double n;
-
-  Avg(this.avg, this.n);
-}
-
-class Generator {
-  final int gradeToAdd;
-  final int max;
-  final Avg currentAvg;
-  final List<int> plan;
-
-  Generator(this.gradeToAdd, this.max, this.currentAvg, this.plan);
-}
-
-class Plan {
-  final List<int> plan;
-  int sum = 0;
-  double avg = 0;
-  int med = 0; // currently
-  int mod = 0; // unused
-  double sigma = 0;
-
-  Plan(this.plan);
-
-  String get dbString {
-    var finalString = '';
-    for (var i in plan) {
-      finalString += "$i,";
-    }
-    return finalString;
-  }
-
-  @override
-  bool operator ==(other) => other is Plan && listEquals(plan, other.plan);
-
-  @override
-  int get hashCode => Object.hashAll(plan);
-}
-
-class GoalPlannerHelper {
-  static Avg _addToAvg(Avg base, int grade, int n) =>
-      Avg((base.avg * base.n + grade * n) / (base.n + n), base.n + n);
-
-  static List<T> _addToList<T>(List<T> l, T e, int n) {
-    if (n == 0) return l;
-    List<T> tmp = l;
-    for (int i = 0; i < n; i++) {
-      tmp = tmp + [e];
-    }
-    return tmp;
-  }
-
-  static int howManyNeeded(int grade, List<Grade> base, double goal) {
-    double avg = averageEvals(base);
-    double wsum = weightSum(base);
-    if (avg >= goal) return 0;
-    if (grade * 1.0 == goal) return -1;
-    int candidate = (wsum * (avg - goal) / (goal - grade)).floor();
-    return (candidate * grade + avg * wsum) / (candidate + wsum) < goal
-        ? candidate + 1
-        : candidate;
-  }
-
-  static double averageEvals(List<Grade> grades, {bool finalAvg = false}) {
-    double average = grades
-            .map((e) => e.value.value * e.value.weight / 100.0)
-            .fold(0.0, (double a, double b) => a + b) /
-        weightSum(grades, finalAvg: finalAvg);
-    return average.isNaN ? 0.0 : average;
-  }
-
-  static double weightSum(List<Grade> grades, {bool finalAvg = false}) => grades
-      .map((e) => finalAvg ? 1 : e.value.weight / 100)
-      .fold(0, (a, b) => a + b);
-}
+/* 
+ * Maintainer: DarK
+ * Translated from C version
+ * Minimal Working Fixed @ 2022.12.25
+ * ##Please do NOT modify if you don't know whats going on##
+ * 
+ * Issue: #59
+ * 
+ * Future changes / ideas:
+ *  - `best` should be configurable
+ */
+import 'dart:math';
+import 'package:refilc_kreta_api/models/category.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/models/teacher.dart';
+import 'package:flutter/foundation.dart' show listEquals;
+
+/// Generate list of grades that achieve the wanted goal.
+/// After generating possible options, it (when doing so would NOT result in empty list) filters with two criteria:
+///  - Plan should not contain more than 15 grades
+///  - Plan should not contain only one type of grade
+///
+/// **Usage**:
+///
+/// ```dart
+/// List<int> GoalPlanner(double goal, List<Grade> grades).solve().plan
+/// ```
+class GoalPlanner {
+  final double goal;
+  final List<Grade> grades;
+  List<Plan> plans = [];
+  GoalPlanner(this.goal, this.grades);
+
+  bool _allowed(int grade) => grade > goal;
+
+  void _generate(Generator g) {
+    // Exit condition 1: Generator has working plan.
+    if (g.currentAvg.avg >= goal) {
+      plans.add(Plan(g.plan));
+      return;
+    }
+    // Exit condition 2: Generator plan will never work.
+    if (!_allowed(g.gradeToAdd)) {
+      return;
+    }
+
+    for (int i = g.max; i >= 0; i--) {
+      int newGradeToAdd = g.gradeToAdd - 1;
+      List<int> newPlan =
+          GoalPlannerHelper._addToList<int>(g.plan, g.gradeToAdd, i);
+
+      Avg newAvg = GoalPlannerHelper._addToAvg(g.currentAvg, g.gradeToAdd, i);
+      int newN = GoalPlannerHelper.howManyNeeded(
+          newGradeToAdd,
+          grades +
+              newPlan
+                  .map((e) => Grade(
+                        id: '',
+                        date: DateTime(0),
+                        value: GradeValue(e, '', '', 100),
+                        teacher: Teacher.fromString(''),
+                        description: '',
+                        form: '',
+                        groupId: '',
+                        type: GradeType.midYear,
+                        subject: Subject.fromJson({}),
+                        mode: Category.fromJson({}),
+                        seenDate: DateTime(0),
+                        writeDate: DateTime(0),
+                      ))
+                  .toList(),
+          goal);
+
+      _generate(Generator(newGradeToAdd, newN, newAvg, newPlan));
+    }
+  }
+
+  List<Plan> solve() {
+    _generate(
+      Generator(
+        5,
+        GoalPlannerHelper.howManyNeeded(
+          5,
+          grades,
+          goal,
+        ),
+        Avg(GoalPlannerHelper.averageEvals(grades),
+            GoalPlannerHelper.weightSum(grades)),
+        [],
+      ),
+    );
+
+    // Calculate Statistics
+    for (var e in plans) {
+      e.sum = e.plan.fold(0, (int a, b) => a + b);
+      e.avg = e.sum / e.plan.length;
+      e.sigma = sqrt(
+          e.plan.map((i) => pow(i - e.avg, 2)).fold(0, (num a, b) => a + b) /
+              e.plan.length);
+    }
+
+    // filter without aggression
+    if (plans.where((e) => e.plan.length < 30).isNotEmpty) {
+      plans.removeWhere((e) => !(e.plan.length < 30));
+    }
+    if (plans.where((e) => e.sigma > 1).isNotEmpty) {
+      plans.removeWhere((e) => !(e.sigma > 1));
+    }
+
+    return plans;
+  }
+}
+
+class Avg {
+  final double avg;
+  final double n;
+
+  Avg(this.avg, this.n);
+}
+
+class Generator {
+  final int gradeToAdd;
+  final int max;
+  final Avg currentAvg;
+  final List<int> plan;
+
+  Generator(this.gradeToAdd, this.max, this.currentAvg, this.plan);
+}
+
+class Plan {
+  final List<int> plan;
+  int sum = 0;
+  double avg = 0;
+  int med = 0; // currently
+  int mod = 0; // unused
+  double sigma = 0;
+
+  Plan(this.plan);
+
+  String get dbString {
+    var finalString = '';
+    for (var i in plan) {
+      finalString += "$i,";
+    }
+    return finalString;
+  }
+
+  @override
+  bool operator ==(other) => other is Plan && listEquals(plan, other.plan);
+
+  @override
+  int get hashCode => Object.hashAll(plan);
+}
+
+class GoalPlannerHelper {
+  static Avg _addToAvg(Avg base, int grade, int n) =>
+      Avg((base.avg * base.n + grade * n) / (base.n + n), base.n + n);
+
+  static List<T> _addToList<T>(List<T> l, T e, int n) {
+    if (n == 0) return l;
+    List<T> tmp = l;
+    for (int i = 0; i < n; i++) {
+      tmp = tmp + [e];
+    }
+    return tmp;
+  }
+
+  static int howManyNeeded(int grade, List<Grade> base, double goal) {
+    double avg = averageEvals(base);
+    double wsum = weightSum(base);
+    if (avg >= goal) return 0;
+    if (grade * 1.0 == goal) return -1;
+    int candidate = (wsum * (avg - goal) / (goal - grade)).floor();
+    return (candidate * grade + avg * wsum) / (candidate + wsum) < goal
+        ? candidate + 1
+        : candidate;
+  }
+
+  static double averageEvals(List<Grade> grades, {bool finalAvg = false}) {
+    double average = grades
+            .map((e) => e.value.value * e.value.weight / 100.0)
+            .fold(0.0, (double a, double b) => a + b) /
+        weightSum(grades, finalAvg: finalAvg);
+    return average.isNaN ? 0.0 : average;
+  }
+
+  static double weightSum(List<Grade> grades, {bool finalAvg = false}) => grades
+      .map((e) => finalAvg ? 1 : e.value.weight / 100)
+      .fold(0, (a, b) => a + b);
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart
similarity index 93%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart
index eef91b3..5768bf9 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart
@@ -1,19 +1,19 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/group_average.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_mobile_ui/common/round_border_icon.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_input.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner_screen.i18n.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/route_option.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/group_average.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_mobile_ui/common/round_border_icon.dart';
+import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_input.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_planner.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_planner_screen.i18n.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/route_option.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.i18n.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_planner_screen.i18n.dart
similarity index 100%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.i18n.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_planner_screen.i18n.dart
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart
similarity index 94%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart
index 0141fac..4679fdc 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart
@@ -1,18 +1,18 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/average_display.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/progress_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/round_border_icon.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/route_option.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_mobile_ui/common/average_display.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/progress_bar.dart';
+import 'package:refilc_mobile_ui/common/round_border_icon.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_planner.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/route_option.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart b/refilc_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart
similarity index 100%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/grade_display.dart b/refilc_premium/lib/ui/mobile/goal_planner/grade_display.dart
similarity index 83%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/grade_display.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/grade_display.dart
index 1a1142a..a6b156b 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/grade_display.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/grade_display.dart
@@ -1,34 +1,34 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_input.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class GradeDisplay extends StatelessWidget {
-  const GradeDisplay({Key? key, required this.grade}) : super(key: key);
-
-  final int grade;
-
-  @override
-  Widget build(BuildContext context) {
-    SettingsProvider settings = Provider.of<SettingsProvider>(context);
-
-    return Container(
-      width: 36,
-      height: 36,
-      decoration: BoxDecoration(
-        shape: BoxShape.circle,
-        color: gradeColor(grade, settings).withOpacity(.3),
-      ),
-      child: Center(
-        child: Text(
-          grade.toInt().toString(),
-          style: TextStyle(
-            fontWeight: FontWeight.bold,
-            fontSize: 22.0,
-            color: gradeColor(grade, settings),
-          ),
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_input.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class GradeDisplay extends StatelessWidget {
+  const GradeDisplay({Key? key, required this.grade}) : super(key: key);
+
+  final int grade;
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsProvider settings = Provider.of<SettingsProvider>(context);
+
+    return Container(
+      width: 36,
+      height: 36,
+      decoration: BoxDecoration(
+        shape: BoxShape.circle,
+        color: gradeColor(grade, settings).withOpacity(.3),
+      ),
+      child: Center(
+        child: Text(
+          grade.toInt().toString(),
+          style: TextStyle(
+            fontWeight: FontWeight.bold,
+            fontSize: 22.0,
+            color: gradeColor(grade, settings),
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/graph.dart b/refilc_premium/lib/ui/mobile/goal_planner/graph.dart
similarity index 97%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/graph.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/graph.dart
index 724b84a..6a7b6c2 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/graph.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/graph.dart
@@ -1,10 +1,10 @@
 import 'dart:math';
 
-import 'package:filcnaplo/helpers/average_helper.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/models/grade.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/graph.i18n.dart';
+import 'package:refilc/helpers/average_helper.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/graph.i18n.dart';
 import 'package:flutter/material.dart';
 import 'package:fl_chart/fl_chart.dart';
 import 'package:provider/provider.dart';
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/graph.i18n.dart b/refilc_premium/lib/ui/mobile/goal_planner/graph.i18n.dart
similarity index 100%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/graph.i18n.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/graph.i18n.dart
diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/route_option.dart b/refilc_premium/lib/ui/mobile/goal_planner/route_option.dart
similarity index 91%
rename from filcnaplo_premium/lib/ui/mobile/goal_planner/route_option.dart
rename to refilc_premium/lib/ui/mobile/goal_planner/route_option.dart
index dfc4b8b..2ef3608 100644
--- a/filcnaplo_premium/lib/ui/mobile/goal_planner/route_option.dart
+++ b/refilc_premium/lib/ui/mobile/goal_planner/route_option.dart
@@ -1,202 +1,202 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner_screen.i18n.dart';
-import 'package:filcnaplo_premium/ui/mobile/goal_planner/grade_display.dart';
-import 'package:flutter/material.dart';
-
-enum RouteMark { recommended, fastest }
-
-class RouteOption extends StatelessWidget {
-  const RouteOption(
-      {Key? key,
-      required this.plan,
-      this.mark,
-      this.selected = false,
-      required this.onSelected})
-      : super(key: key);
-
-  final Plan plan;
-  final RouteMark? mark;
-  final bool selected;
-  final void Function() onSelected;
-
-  Widget markLabel() {
-    const style = TextStyle(fontWeight: FontWeight.bold);
-
-    switch (mark!) {
-      case RouteMark.recommended:
-        return Text("recommended".i18n, style: style);
-      case RouteMark.fastest:
-        return Text("fastest".i18n, style: style);
-    }
-  }
-
-  Color markColor(BuildContext context) {
-    switch (mark) {
-      case RouteMark.recommended:
-        return const Color.fromARGB(255, 104, 93, 255);
-      case RouteMark.fastest:
-        return const Color.fromARGB(255, 255, 91, 146);
-      default:
-        return Theme.of(context).colorScheme.primary;
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> gradeWidgets = [];
-
-    for (int i = 5; i > 1; i--) {
-      final count = plan.plan.where((e) => e == i).length;
-
-      if (count > 4) {
-        gradeWidgets.add(Row(
-          mainAxisSize: MainAxisSize.min,
-          children: [
-            Text(
-              "${count}x",
-              style: TextStyle(
-                fontSize: 22.0,
-                fontWeight: FontWeight.w500,
-                color: AppColors.of(context).text.withOpacity(.7),
-              ),
-            ),
-            const SizedBox(width: 4.0),
-            GradeDisplay(grade: i),
-          ],
-        ));
-      } else {
-        gradeWidgets
-            .addAll(List.generate(count, (_) => GradeDisplay(grade: i)));
-      }
-
-      if (count > 0) {
-        gradeWidgets.add(SizedBox(
-          height: 36.0,
-          width: 32.0,
-          child: Center(
-              child: Icon(Icons.add,
-                  color: AppColors.of(context).text.withOpacity(.5))),
-        ));
-      }
-    }
-
-    gradeWidgets.removeLast();
-
-    return Padding(
-      padding: const EdgeInsets.only(bottom: 12.0),
-      child: SizedBox(
-        width: double.infinity,
-        child: Card(
-          surfaceTintColor:
-              selected ? markColor(context).withOpacity(.2) : Colors.white,
-          margin: EdgeInsets.zero,
-          elevation: 5,
-          shadowColor: Colors.transparent,
-          shape: RoundedRectangleBorder(
-            borderRadius: BorderRadius.circular(16.0),
-            side: selected
-                ? BorderSide(color: markColor(context), width: 4.0)
-                : BorderSide.none,
-          ),
-          child: InkWell(
-            borderRadius: BorderRadius.circular(16.0),
-            onTap: onSelected,
-            child: Padding(
-              padding: const EdgeInsets.only(
-                  top: 16.0, bottom: 16.0, left: 20.0, right: 12.0),
-              child: Column(
-                mainAxisSize: MainAxisSize.min,
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  if (mark != null) ...[
-                    Chip(
-                      label: markLabel(),
-                      visualDensity: VisualDensity.compact,
-                      backgroundColor:
-                          selected ? markColor(context) : Colors.transparent,
-                      labelPadding: const EdgeInsets.symmetric(horizontal: 8.0),
-                      labelStyle:
-                          TextStyle(color: selected ? Colors.white : null),
-                      shape: StadiumBorder(
-                        side: BorderSide(
-                          color: markColor(context),
-                          width: 3.0,
-                        ),
-                      ),
-                    ),
-                    const SizedBox(height: 6.0),
-                  ],
-                  Wrap(
-                    spacing: 4.0,
-                    runSpacing: 8.0,
-                    children: gradeWidgets,
-                  ),
-                ],
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-class RouteOptionRow extends StatelessWidget {
-  const RouteOptionRow({
-    Key? key,
-    required this.plan,
-    this.mark,
-  }) : super(key: key);
-
-  final Plan plan;
-  final RouteMark? mark;
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> gradeWidgets = [];
-
-    for (int i = 5; i > 1; i--) {
-      final count = plan.plan.where((e) => e == i).length;
-
-      if (count > 4) {
-        gradeWidgets.add(Row(
-          mainAxisSize: MainAxisSize.min,
-          children: [
-            Text(
-              "${count}x",
-              style: TextStyle(
-                fontSize: 22.0,
-                fontWeight: FontWeight.w500,
-                color: AppColors.of(context).text.withOpacity(.7),
-              ),
-            ),
-            const SizedBox(width: 4.0),
-            GradeDisplay(grade: i),
-          ],
-        ));
-      } else {
-        gradeWidgets
-            .addAll(List.generate(count, (_) => GradeDisplay(grade: i)));
-      }
-
-      if (count > 0) {
-        gradeWidgets.add(SizedBox(
-          height: 36.0,
-          width: 32.0,
-          child: Center(
-              child: Icon(Icons.add,
-                  color: AppColors.of(context).text.withOpacity(.5))),
-        ));
-      }
-    }
-
-    gradeWidgets.removeLast();
-
-    return Wrap(
-      spacing: 4.0,
-      runSpacing: 8.0,
-      children: gradeWidgets,
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_planner.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/goal_planner_screen.i18n.dart';
+import 'package:refilc_premium/ui/mobile/goal_planner/grade_display.dart';
+import 'package:flutter/material.dart';
+
+enum RouteMark { recommended, fastest }
+
+class RouteOption extends StatelessWidget {
+  const RouteOption(
+      {Key? key,
+      required this.plan,
+      this.mark,
+      this.selected = false,
+      required this.onSelected})
+      : super(key: key);
+
+  final Plan plan;
+  final RouteMark? mark;
+  final bool selected;
+  final void Function() onSelected;
+
+  Widget markLabel() {
+    const style = TextStyle(fontWeight: FontWeight.bold);
+
+    switch (mark!) {
+      case RouteMark.recommended:
+        return Text("recommended".i18n, style: style);
+      case RouteMark.fastest:
+        return Text("fastest".i18n, style: style);
+    }
+  }
+
+  Color markColor(BuildContext context) {
+    switch (mark) {
+      case RouteMark.recommended:
+        return const Color.fromARGB(255, 104, 93, 255);
+      case RouteMark.fastest:
+        return const Color.fromARGB(255, 255, 91, 146);
+      default:
+        return Theme.of(context).colorScheme.primary;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    List<Widget> gradeWidgets = [];
+
+    for (int i = 5; i > 1; i--) {
+      final count = plan.plan.where((e) => e == i).length;
+
+      if (count > 4) {
+        gradeWidgets.add(Row(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            Text(
+              "${count}x",
+              style: TextStyle(
+                fontSize: 22.0,
+                fontWeight: FontWeight.w500,
+                color: AppColors.of(context).text.withOpacity(.7),
+              ),
+            ),
+            const SizedBox(width: 4.0),
+            GradeDisplay(grade: i),
+          ],
+        ));
+      } else {
+        gradeWidgets
+            .addAll(List.generate(count, (_) => GradeDisplay(grade: i)));
+      }
+
+      if (count > 0) {
+        gradeWidgets.add(SizedBox(
+          height: 36.0,
+          width: 32.0,
+          child: Center(
+              child: Icon(Icons.add,
+                  color: AppColors.of(context).text.withOpacity(.5))),
+        ));
+      }
+    }
+
+    gradeWidgets.removeLast();
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 12.0),
+      child: SizedBox(
+        width: double.infinity,
+        child: Card(
+          surfaceTintColor:
+              selected ? markColor(context).withOpacity(.2) : Colors.white,
+          margin: EdgeInsets.zero,
+          elevation: 5,
+          shadowColor: Colors.transparent,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(16.0),
+            side: selected
+                ? BorderSide(color: markColor(context), width: 4.0)
+                : BorderSide.none,
+          ),
+          child: InkWell(
+            borderRadius: BorderRadius.circular(16.0),
+            onTap: onSelected,
+            child: Padding(
+              padding: const EdgeInsets.only(
+                  top: 16.0, bottom: 16.0, left: 20.0, right: 12.0),
+              child: Column(
+                mainAxisSize: MainAxisSize.min,
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  if (mark != null) ...[
+                    Chip(
+                      label: markLabel(),
+                      visualDensity: VisualDensity.compact,
+                      backgroundColor:
+                          selected ? markColor(context) : Colors.transparent,
+                      labelPadding: const EdgeInsets.symmetric(horizontal: 8.0),
+                      labelStyle:
+                          TextStyle(color: selected ? Colors.white : null),
+                      shape: StadiumBorder(
+                        side: BorderSide(
+                          color: markColor(context),
+                          width: 3.0,
+                        ),
+                      ),
+                    ),
+                    const SizedBox(height: 6.0),
+                  ],
+                  Wrap(
+                    spacing: 4.0,
+                    runSpacing: 8.0,
+                    children: gradeWidgets,
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class RouteOptionRow extends StatelessWidget {
+  const RouteOptionRow({
+    Key? key,
+    required this.plan,
+    this.mark,
+  }) : super(key: key);
+
+  final Plan plan;
+  final RouteMark? mark;
+
+  @override
+  Widget build(BuildContext context) {
+    List<Widget> gradeWidgets = [];
+
+    for (int i = 5; i > 1; i--) {
+      final count = plan.plan.where((e) => e == i).length;
+
+      if (count > 4) {
+        gradeWidgets.add(Row(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            Text(
+              "${count}x",
+              style: TextStyle(
+                fontSize: 22.0,
+                fontWeight: FontWeight.w500,
+                color: AppColors.of(context).text.withOpacity(.7),
+              ),
+            ),
+            const SizedBox(width: 4.0),
+            GradeDisplay(grade: i),
+          ],
+        ));
+      } else {
+        gradeWidgets
+            .addAll(List.generate(count, (_) => GradeDisplay(grade: i)));
+      }
+
+      if (count > 0) {
+        gradeWidgets.add(SizedBox(
+          height: 36.0,
+          width: 32.0,
+          child: Center(
+              child: Icon(Icons.add,
+                  color: AppColors.of(context).text.withOpacity(.5))),
+        ));
+      }
+    }
+
+    gradeWidgets.removeLast();
+
+    return Wrap(
+      spacing: 4.0,
+      runSpacing: 8.0,
+      children: gradeWidgets,
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/grades/average_selector.dart b/refilc_premium/lib/ui/mobile/grades/average_selector.dart
similarity index 76%
rename from filcnaplo_premium/lib/ui/mobile/grades/average_selector.dart
rename to refilc_premium/lib/ui/mobile/grades/average_selector.dart
index 134e70b..de56158 100644
--- a/filcnaplo_premium/lib/ui/mobile/grades/average_selector.dart
+++ b/refilc_premium/lib/ui/mobile/grades/average_selector.dart
@@ -1,105 +1,107 @@
-import 'package:filcnaplo/theme/colors/colors.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:dropdown_button2/dropdown_button2.dart';
-import 'package:filcnaplo_mobile_ui/pages/grades/grades_page.i18n.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-
-final Map<int, String> avgDropItems = {
-  0: "annual_average",
-  90: "3_months_average",
-  30: "30_days_average",
-  14: "14_days_average",
-  7: "7_days_average",
-};
-
-class PremiumAverageSelector extends StatefulWidget {
-  const PremiumAverageSelector({Key? key, this.onChanged, required this.value}) : super(key: key);
-
-  final Function(int?)? onChanged;
-  final int value;
-
-  @override
-  _PremiumAverageSelectorState createState() => _PremiumAverageSelectorState();
-}
-
-class _PremiumAverageSelectorState extends State<PremiumAverageSelector> {
-  @override
-  Widget build(BuildContext context) {
-    List<DropdownMenuItem<int>> dropdownItems = avgDropItems.keys.map((item) {
-      return DropdownMenuItem<int>(
-        value: item,
-        child: Text(
-          avgDropItems[item]!.i18n,
-          style: TextStyle(
-            fontSize: 14,
-            fontWeight: FontWeight.bold,
-            color: AppColors.of(context).text,
-          ),
-          overflow: TextOverflow.ellipsis,
-        ),
-      );
-    }).toList();
-
-    return DropdownButton2<int>(
-      items: dropdownItems,
-      onChanged: (int? value) {
-        if (Provider.of<PremiumProvider>(context, listen: false).hasScope(PremiumScopes.gradeStats)) {
-          if (widget.onChanged != null) {
-            setState(() {
-              widget.onChanged!(value);
-            });
-          }
-        } else {
-          PremiumLockedFeatureUpsell.show(context: context, feature: PremiumFeature.gradestats);
-        }
-      },
-      value: widget.value,
-      iconSize: 14,
-      iconEnabledColor: AppColors.of(context).text,
-      iconDisabledColor: AppColors.of(context).text,
-      underline: const SizedBox(),
-      itemHeight: 40,
-      itemPadding: const EdgeInsets.only(left: 14, right: 14),
-      dropdownWidth: 200,
-      dropdownPadding: null,
-      buttonDecoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(8),
-      ),
-      dropdownDecoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(14),
-      ),
-      dropdownElevation: 8,
-      scrollbarRadius: const Radius.circular(40),
-      scrollbarThickness: 6,
-      scrollbarAlwaysShow: true,
-      offset: const Offset(-10, -10),
-      buttonSplashColor: Colors.transparent,
-      customButton: SizedBox(
-        height: 30,
-        child: Row(
-          children: [
-            Text(
-              avgDropItems[widget.value]!.i18n,
-              style: Theme.of(context)
-                  .textTheme
-                  .titleSmall!
-                  .copyWith(fontWeight: FontWeight.w600, color: AppColors.of(context).text.withOpacity(0.65)),
-            ),
-            const SizedBox(
-              width: 4,
-            ),
-            Icon(
-              FeatherIcons.chevronDown,
-              size: 16,
-              color: AppColors.of(context).text,
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:dropdown_button2/dropdown_button2.dart';
+import 'package:refilc_mobile_ui/pages/grades/grades_page.i18n.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+
+final Map<int, String> avgDropItems = {
+  0: "annual_average",
+  90: "3_months_average",
+  30: "30_days_average",
+  14: "14_days_average",
+  7: "7_days_average",
+};
+
+class PremiumAverageSelector extends StatefulWidget {
+  const PremiumAverageSelector({Key? key, this.onChanged, required this.value})
+      : super(key: key);
+
+  final Function(int?)? onChanged;
+  final int value;
+
+  @override
+  _PremiumAverageSelectorState createState() => _PremiumAverageSelectorState();
+}
+
+class _PremiumAverageSelectorState extends State<PremiumAverageSelector> {
+  @override
+  Widget build(BuildContext context) {
+    List<DropdownMenuItem<int>> dropdownItems = avgDropItems.keys.map((item) {
+      return DropdownMenuItem<int>(
+        value: item,
+        child: Text(
+          avgDropItems[item]!.i18n,
+          style: TextStyle(
+            fontSize: 14,
+            fontWeight: FontWeight.bold,
+            color: AppColors.of(context).text,
+          ),
+          overflow: TextOverflow.ellipsis,
+        ),
+      );
+    }).toList();
+
+    return DropdownButton2<int>(
+      items: dropdownItems,
+      onChanged: (int? value) {
+        if (Provider.of<PremiumProvider>(context, listen: false)
+            .hasScope(PremiumScopes.gradeStats)) {
+          if (widget.onChanged != null) {
+            setState(() {
+              widget.onChanged!(value);
+            });
+          }
+        } else {
+          PremiumLockedFeatureUpsell.show(
+              context: context, feature: PremiumFeature.gradestats);
+        }
+      },
+      value: widget.value,
+      iconSize: 14,
+      iconEnabledColor: AppColors.of(context).text,
+      iconDisabledColor: AppColors.of(context).text,
+      underline: const SizedBox(),
+      itemHeight: 40,
+      itemPadding: const EdgeInsets.only(left: 14, right: 14),
+      dropdownWidth: 200,
+      dropdownPadding: null,
+      buttonDecoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(8),
+      ),
+      dropdownDecoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(14),
+      ),
+      dropdownElevation: 8,
+      scrollbarRadius: const Radius.circular(40),
+      scrollbarThickness: 6,
+      scrollbarAlwaysShow: true,
+      offset: const Offset(-10, -10),
+      buttonSplashColor: Colors.transparent,
+      customButton: SizedBox(
+        height: 30,
+        child: Row(
+          children: [
+            Text(
+              avgDropItems[widget.value]!.i18n,
+              style: Theme.of(context).textTheme.titleSmall!.copyWith(
+                  fontWeight: FontWeight.w600,
+                  color: AppColors.of(context).text.withOpacity(0.65)),
+            ),
+            const SizedBox(
+              width: 4,
+            ),
+            Icon(
+              FeatherIcons.chevronDown,
+              size: 16,
+              color: AppColors.of(context).text,
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/premium/activation_view/activation_dashboard.dart b/refilc_premium/lib/ui/mobile/premium/activation_view/activation_dashboard.dart
similarity index 95%
rename from filcnaplo_premium/lib/ui/mobile/premium/activation_view/activation_dashboard.dart
rename to refilc_premium/lib/ui/mobile/premium/activation_view/activation_dashboard.dart
index 7d6448f..5defb15 100644
--- a/filcnaplo_premium/lib/ui/mobile/premium/activation_view/activation_dashboard.dart
+++ b/refilc_premium/lib/ui/mobile/premium/activation_view/activation_dashboard.dart
@@ -1,197 +1,197 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:flutter_svg/svg.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
-
-class ActivationDashboard extends StatefulWidget {
-  const ActivationDashboard({super.key});
-
-  @override
-  State<ActivationDashboard> createState() => _ActivationDashboardState();
-}
-
-class _ActivationDashboardState extends State<ActivationDashboard> {
-  bool manualActivationLoading = false;
-
-  Future<void> onManualActivation() async {
-    final data = await Clipboard.getData("text/plain");
-    if (data == null || data.text == null || data.text == "") {
-      return;
-    }
-    setState(() {
-      manualActivationLoading = true;
-    });
-    final result =
-        await context.read<PremiumProvider>().auth.finishAuth(data.text!);
-    setState(() {
-      manualActivationLoading = false;
-    });
-
-    if (!result && mounted) {
-      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
-        content: Text(
-          "Sikertelen aktiválás. Kérlek próbáld újra később!",
-          style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
-        ),
-        backgroundColor: Colors.red,
-      ));
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(horizontal: 24.0),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.center,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          const Spacer(),
-          Center(
-            child: SvgPicture.asset(
-              "assets/images/github.svg",
-              height: 64.0,
-            ),
-          ),
-          const SizedBox(height: 32.0),
-          const Text(
-            "Jelentkezz be a GitHub felületén és adj hozzáférést a Filcnek, hogy aktiváld a Premiumot.",
-            textAlign: TextAlign.center,
-            style: TextStyle(fontWeight: FontWeight.w700, fontSize: 18.0),
-          ),
-          const SizedBox(height: 12.0),
-          Card(
-            shape: RoundedRectangleBorder(
-                borderRadius: BorderRadius.circular(14.0)),
-            child: const Padding(
-              padding: EdgeInsets.all(20.0),
-              child: Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  Row(
-                    children: [
-                      Icon(FeatherIcons.alertTriangle,
-                          size: 20.0, color: Colors.orange),
-                      SizedBox(width: 12.0),
-                      Text(
-                        "Figyelem!",
-                        style: TextStyle(
-                            fontSize: 18.0, fontWeight: FontWeight.bold),
-                      ),
-                    ],
-                  ),
-                  SizedBox(height: 6.0),
-                  Text(
-                    "Csak akkor érzékeli a Filc a támogatói státuszod, ha nem állítod privátra!",
-                    style: TextStyle(fontSize: 16.0),
-                  ),
-                ],
-              ),
-            ),
-          ),
-          const SizedBox(height: 12.0),
-          Card(
-            shape: RoundedRectangleBorder(
-                borderRadius: BorderRadius.circular(14.0)),
-            child: const Padding(
-              padding: EdgeInsets.all(20.0),
-              child: Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  Row(
-                    children: [
-                      Icon(FeatherIcons.alertTriangle,
-                          size: 20.0, color: Colors.orange),
-                      SizedBox(width: 12.0),
-                      Text(
-                        "Figyelem!",
-                        style: TextStyle(
-                            fontSize: 18.0, fontWeight: FontWeight.bold),
-                      ),
-                    ],
-                  ),
-                  SizedBox(height: 6.0),
-                  Text(
-                    "Ha friss támogató vagy, 5-10 percbe telhet az aktiválás. Kérlek gyere vissza később, és próbáld újra!",
-                    style: TextStyle(fontSize: 16.0),
-                  ),
-                ],
-              ),
-            ),
-          ),
-          const SizedBox(height: 12.0),
-          Card(
-            shape: RoundedRectangleBorder(
-                borderRadius: BorderRadius.circular(14.0)),
-            child: Padding(
-              padding: const EdgeInsets.all(20.0),
-              child: Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  const Text(
-                    "Ha bejelentkezés után nem lép vissza az alkalmazásba automatikusan, aktiváld a támogatásod manuálisan",
-                    style:
-                        TextStyle(fontSize: 15.0, fontWeight: FontWeight.w500),
-                  ),
-                  const SizedBox(height: 6.0),
-                  Center(
-                    child: TextButton.icon(
-                      onPressed: onManualActivation,
-                      style: ButtonStyle(
-                        foregroundColor: MaterialStatePropertyAll(
-                            Theme.of(context).colorScheme.secondary),
-                        overlayColor: MaterialStatePropertyAll(Theme.of(context)
-                            .colorScheme
-                            .secondary
-                            .withOpacity(.1)),
-                      ),
-                      icon: manualActivationLoading
-                          ? const SizedBox(
-                              child: CircularProgressIndicator(),
-                              height: 16.0,
-                              width: 16.0,
-                            )
-                          : const Icon(FeatherIcons.key, size: 20.0),
-                      label: const Padding(
-                        padding: EdgeInsets.only(left: 8.0),
-                        child: Text(
-                          "Aktiválás tokennel",
-                          style: TextStyle(fontSize: 16.0),
-                        ),
-                      ),
-                    ),
-                  ),
-                ],
-              ),
-            ),
-          ),
-          const Spacer(),
-          Padding(
-            padding: const EdgeInsets.only(bottom: 24.0),
-            child: Center(
-              child: TextButton.icon(
-                onPressed: () {
-                  Navigator.of(context).pop();
-                },
-                style: ButtonStyle(
-                  foregroundColor:
-                      MaterialStatePropertyAll(AppColors.of(context).text),
-                  overlayColor: MaterialStatePropertyAll(
-                      AppColors.of(context).text.withOpacity(.1)),
-                ),
-                icon: const Icon(FeatherIcons.arrowLeft, size: 20.0),
-                label: const Text(
-                  "Vissza",
-                  style: TextStyle(fontSize: 16.0),
-                ),
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
+
+class ActivationDashboard extends StatefulWidget {
+  const ActivationDashboard({super.key});
+
+  @override
+  State<ActivationDashboard> createState() => _ActivationDashboardState();
+}
+
+class _ActivationDashboardState extends State<ActivationDashboard> {
+  bool manualActivationLoading = false;
+
+  Future<void> onManualActivation() async {
+    final data = await Clipboard.getData("text/plain");
+    if (data == null || data.text == null || data.text == "") {
+      return;
+    }
+    setState(() {
+      manualActivationLoading = true;
+    });
+    final result =
+        await context.read<PremiumProvider>().auth.finishAuth(data.text!);
+    setState(() {
+      manualActivationLoading = false;
+    });
+
+    if (!result && mounted) {
+      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
+        content: Text(
+          "Sikertelen aktiválás. Kérlek próbáld újra később!",
+          style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
+        ),
+        backgroundColor: Colors.red,
+      ));
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 24.0),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.center,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          const Spacer(),
+          Center(
+            child: SvgPicture.asset(
+              "assets/images/github.svg",
+              height: 64.0,
+            ),
+          ),
+          const SizedBox(height: 32.0),
+          const Text(
+            "Jelentkezz be a GitHub felületén és adj hozzáférést a Filcnek, hogy aktiváld a Premiumot.",
+            textAlign: TextAlign.center,
+            style: TextStyle(fontWeight: FontWeight.w700, fontSize: 18.0),
+          ),
+          const SizedBox(height: 12.0),
+          Card(
+            shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(14.0)),
+            child: const Padding(
+              padding: EdgeInsets.all(20.0),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Row(
+                    children: [
+                      Icon(FeatherIcons.alertTriangle,
+                          size: 20.0, color: Colors.orange),
+                      SizedBox(width: 12.0),
+                      Text(
+                        "Figyelem!",
+                        style: TextStyle(
+                            fontSize: 18.0, fontWeight: FontWeight.bold),
+                      ),
+                    ],
+                  ),
+                  SizedBox(height: 6.0),
+                  Text(
+                    "Csak akkor érzékeli a Filc a támogatói státuszod, ha nem állítod privátra!",
+                    style: TextStyle(fontSize: 16.0),
+                  ),
+                ],
+              ),
+            ),
+          ),
+          const SizedBox(height: 12.0),
+          Card(
+            shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(14.0)),
+            child: const Padding(
+              padding: EdgeInsets.all(20.0),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Row(
+                    children: [
+                      Icon(FeatherIcons.alertTriangle,
+                          size: 20.0, color: Colors.orange),
+                      SizedBox(width: 12.0),
+                      Text(
+                        "Figyelem!",
+                        style: TextStyle(
+                            fontSize: 18.0, fontWeight: FontWeight.bold),
+                      ),
+                    ],
+                  ),
+                  SizedBox(height: 6.0),
+                  Text(
+                    "Ha friss támogató vagy, 5-10 percbe telhet az aktiválás. Kérlek gyere vissza később, és próbáld újra!",
+                    style: TextStyle(fontSize: 16.0),
+                  ),
+                ],
+              ),
+            ),
+          ),
+          const SizedBox(height: 12.0),
+          Card(
+            shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(14.0)),
+            child: Padding(
+              padding: const EdgeInsets.all(20.0),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  const Text(
+                    "Ha bejelentkezés után nem lép vissza az alkalmazásba automatikusan, aktiváld a támogatásod manuálisan",
+                    style:
+                        TextStyle(fontSize: 15.0, fontWeight: FontWeight.w500),
+                  ),
+                  const SizedBox(height: 6.0),
+                  Center(
+                    child: TextButton.icon(
+                      onPressed: onManualActivation,
+                      style: ButtonStyle(
+                        foregroundColor: MaterialStatePropertyAll(
+                            Theme.of(context).colorScheme.secondary),
+                        overlayColor: MaterialStatePropertyAll(Theme.of(context)
+                            .colorScheme
+                            .secondary
+                            .withOpacity(.1)),
+                      ),
+                      icon: manualActivationLoading
+                          ? const SizedBox(
+                              child: CircularProgressIndicator(),
+                              height: 16.0,
+                              width: 16.0,
+                            )
+                          : const Icon(FeatherIcons.key, size: 20.0),
+                      label: const Padding(
+                        padding: EdgeInsets.only(left: 8.0),
+                        child: Text(
+                          "Aktiválás tokennel",
+                          style: TextStyle(fontSize: 16.0),
+                        ),
+                      ),
+                    ),
+                  ),
+                ],
+              ),
+            ),
+          ),
+          const Spacer(),
+          Padding(
+            padding: const EdgeInsets.only(bottom: 24.0),
+            child: Center(
+              child: TextButton.icon(
+                onPressed: () {
+                  Navigator.of(context).pop();
+                },
+                style: ButtonStyle(
+                  foregroundColor:
+                      MaterialStatePropertyAll(AppColors.of(context).text),
+                  overlayColor: MaterialStatePropertyAll(
+                      AppColors.of(context).text.withOpacity(.1)),
+                ),
+                icon: const Icon(FeatherIcons.arrowLeft, size: 20.0),
+                label: const Text(
+                  "Vissza",
+                  style: TextStyle(fontSize: 16.0),
+                ),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/premium/activation_view/activation_view.dart b/refilc_premium/lib/ui/mobile/premium/activation_view/activation_view.dart
similarity index 76%
rename from filcnaplo_premium/lib/ui/mobile/premium/activation_view/activation_view.dart
rename to refilc_premium/lib/ui/mobile/premium/activation_view/activation_view.dart
index c0ee3fa..36ac9b1 100644
--- a/filcnaplo_premium/lib/ui/mobile/premium/activation_view/activation_view.dart
+++ b/refilc_premium/lib/ui/mobile/premium/activation_view/activation_view.dart
@@ -1,67 +1,72 @@
-import 'package:animations/animations.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/activation_view/activation_dashboard.dart';
-import 'package:flutter/material.dart';
-import 'package:lottie/lottie.dart';
-import 'package:provider/provider.dart';
-
-class PremiumActivationView extends StatefulWidget {
-  const PremiumActivationView({super.key});
-
-  @override
-  State<PremiumActivationView> createState() => _PremiumActivationViewState();
-}
-
-class _PremiumActivationViewState extends State<PremiumActivationView> with SingleTickerProviderStateMixin {
-  late AnimationController animation;
-  bool activated = false;
-
-  @override
-  void initState() {
-    super.initState();
-    context.read<PremiumProvider>().auth.initAuth();
-
-    animation = AnimationController(vsync: this, duration: const Duration(seconds: 2));
-  }
-
-  @override
-  void dispose() {
-    animation.dispose();
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final premium = context.watch<PremiumProvider>();
-
-    if (premium.hasPremium && !activated) {
-      activated = true;
-      animation.forward();
-      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
-        Future.delayed(const Duration(seconds: 2)).then((value) {
-          if (mounted) Navigator.of(context).pop();
-        });
-      });
-    }
-
-    return Scaffold(
-      body: PageTransitionSwitcher(
-        transitionBuilder: (child, primaryAnimation, secondaryAnimation) => SharedAxisTransition(
-          animation: primaryAnimation,
-          secondaryAnimation: secondaryAnimation,
-          transitionType: SharedAxisTransitionType.horizontal,
-          fillColor: Colors.transparent,
-          child: child,
-        ),
-        child: premium.hasPremium
-            ? Center(
-                child: SizedBox(
-                  width: 400,
-                  child: Lottie.network("https://assets2.lottiefiles.com/packages/lf20_wkebwzpz.json", controller: animation),
-                ),
-              )
-            : const SafeArea(child: ActivationDashboard()),
-      ),
-    );
-  }
-}
+import 'package:animations/animations.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/activation_view/activation_dashboard.dart';
+import 'package:flutter/material.dart';
+import 'package:lottie/lottie.dart';
+import 'package:provider/provider.dart';
+
+class PremiumActivationView extends StatefulWidget {
+  const PremiumActivationView({super.key});
+
+  @override
+  State<PremiumActivationView> createState() => _PremiumActivationViewState();
+}
+
+class _PremiumActivationViewState extends State<PremiumActivationView>
+    with SingleTickerProviderStateMixin {
+  late AnimationController animation;
+  bool activated = false;
+
+  @override
+  void initState() {
+    super.initState();
+    context.read<PremiumProvider>().auth.initAuth();
+
+    animation =
+        AnimationController(vsync: this, duration: const Duration(seconds: 2));
+  }
+
+  @override
+  void dispose() {
+    animation.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final premium = context.watch<PremiumProvider>();
+
+    if (premium.hasPremium && !activated) {
+      activated = true;
+      animation.forward();
+      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+        Future.delayed(const Duration(seconds: 2)).then((value) {
+          if (mounted) Navigator.of(context).pop();
+        });
+      });
+    }
+
+    return Scaffold(
+      body: PageTransitionSwitcher(
+        transitionBuilder: (child, primaryAnimation, secondaryAnimation) =>
+            SharedAxisTransition(
+          animation: primaryAnimation,
+          secondaryAnimation: secondaryAnimation,
+          transitionType: SharedAxisTransitionType.horizontal,
+          fillColor: Colors.transparent,
+          child: child,
+        ),
+        child: premium.hasPremium
+            ? Center(
+                child: SizedBox(
+                  width: 400,
+                  child: Lottie.network(
+                      "https://assets2.lottiefiles.com/packages/lf20_wkebwzpz.json",
+                      controller: animation),
+                ),
+              )
+            : const SafeArea(child: ActivationDashboard()),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/premium/premium_inline.dart b/refilc_premium/lib/ui/mobile/premium/premium_inline.dart
similarity index 82%
rename from filcnaplo_premium/lib/ui/mobile/premium/premium_inline.dart
rename to refilc_premium/lib/ui/mobile/premium/premium_inline.dart
index 07d0285..399aad2 100644
--- a/filcnaplo_premium/lib/ui/mobile/premium/premium_inline.dart
+++ b/refilc_premium/lib/ui/mobile/premium/premium_inline.dart
@@ -1,66 +1,69 @@
-import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
-import 'package:flutter/material.dart';
-
-enum PremiumInlineFeature { nickname, theme, widget, goal, stats }
-
-const Map<PremiumInlineFeature, String> _featureAssets = {
-  PremiumInlineFeature.nickname: "assets/images/premium_nickname_inline_showcase.png",
-  PremiumInlineFeature.theme: "assets/images/premium_theme_inline_showcase.png",
-  PremiumInlineFeature.widget: "assets/images/premium_widget_inline_showcase.png",
-  PremiumInlineFeature.goal: "assets/images/premium_goal_inline_showcase.png",
-  PremiumInlineFeature.stats: "assets/images/premium_stats_inline_showcase.png",
-};
-
-const Map<PremiumInlineFeature, PremiumFeature> _featuresInline = {
-  PremiumInlineFeature.nickname: PremiumFeature.profile,
-  PremiumInlineFeature.theme: PremiumFeature.customcolors,
-  PremiumInlineFeature.widget: PremiumFeature.widget,
-  PremiumInlineFeature.goal: PremiumFeature.goalplanner,
-  PremiumInlineFeature.stats: PremiumFeature.gradestats,
-};
-
-class PremiumInline extends StatelessWidget {
-  const PremiumInline({super.key, required this.features});
-
-  final List<PremiumInlineFeature> features;
-
-  String _getAsset() {
-    for (int i = 0; i < features.length; i++) {
-      if (DateTime.now().day % features.length == i) {
-        return _featureAssets[features[i]]!;
-      }
-    }
-
-    return _featureAssets[features[0]]!;
-  }
-
-  PremiumFeature _getFeature() {
-    for (int i = 0; i < features.length; i++) {
-      if (DateTime.now().day % features.length == i) {
-        return _featuresInline[features[i]]!;
-      }
-    }
-
-    return _featuresInline[features[0]]!;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        Image.asset(_getAsset()),
-        Positioned.fill(
-          child: Material(
-            type: MaterialType.transparency,
-            child: InkWell(
-              borderRadius: BorderRadius.circular(16.0),
-              onTap: () {
-                PremiumLockedFeatureUpsell.show(context: context, feature: _getFeature());
-              },
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-}
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+
+enum PremiumInlineFeature { nickname, theme, widget, goal, stats }
+
+const Map<PremiumInlineFeature, String> _featureAssets = {
+  PremiumInlineFeature.nickname:
+      "assets/images/premium_nickname_inline_showcase.png",
+  PremiumInlineFeature.theme: "assets/images/premium_theme_inline_showcase.png",
+  PremiumInlineFeature.widget:
+      "assets/images/premium_widget_inline_showcase.png",
+  PremiumInlineFeature.goal: "assets/images/premium_goal_inline_showcase.png",
+  PremiumInlineFeature.stats: "assets/images/premium_stats_inline_showcase.png",
+};
+
+const Map<PremiumInlineFeature, PremiumFeature> _featuresInline = {
+  PremiumInlineFeature.nickname: PremiumFeature.profile,
+  PremiumInlineFeature.theme: PremiumFeature.customcolors,
+  PremiumInlineFeature.widget: PremiumFeature.widget,
+  PremiumInlineFeature.goal: PremiumFeature.goalplanner,
+  PremiumInlineFeature.stats: PremiumFeature.gradestats,
+};
+
+class PremiumInline extends StatelessWidget {
+  const PremiumInline({super.key, required this.features});
+
+  final List<PremiumInlineFeature> features;
+
+  String _getAsset() {
+    for (int i = 0; i < features.length; i++) {
+      if (DateTime.now().day % features.length == i) {
+        return _featureAssets[features[i]]!;
+      }
+    }
+
+    return _featureAssets[features[0]]!;
+  }
+
+  PremiumFeature _getFeature() {
+    for (int i = 0; i < features.length; i++) {
+      if (DateTime.now().day % features.length == i) {
+        return _featuresInline[features[i]]!;
+      }
+    }
+
+    return _featuresInline[features[0]]!;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: [
+        Image.asset(_getAsset()),
+        Positioned.fill(
+          child: Material(
+            type: MaterialType.transparency,
+            child: InkWell(
+              borderRadius: BorderRadius.circular(16.0),
+              onTap: () {
+                PremiumLockedFeatureUpsell.show(
+                    context: context, feature: _getFeature());
+              },
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/premium/upsell.dart b/refilc_premium/lib/ui/mobile/premium/upsell.dart
similarity index 95%
rename from filcnaplo_premium/lib/ui/mobile/premium/upsell.dart
rename to refilc_premium/lib/ui/mobile/premium/upsell.dart
index 701791d..fef3d2d 100644
--- a/filcnaplo_premium/lib/ui/mobile/premium/upsell.dart
+++ b/refilc_premium/lib/ui/mobile/premium/upsell.dart
@@ -1,183 +1,183 @@
-import 'package:filcnaplo/icons/filc_icons.dart';
-import 'package:filcnaplo_mobile_ui/premium/premium_screen.dart';
-import 'package:flutter/material.dart';
-
-enum PremiumFeature {
-  gradestats,
-  customcolors,
-  profile,
-  iconpack,
-  subjectrename,
-  teacherrename,
-  weeklytimetable,
-  goalplanner,
-  widget,
-}
-
-enum PremiumFeatureLevel { kupak, tinta }
-
-const Map<PremiumFeature, PremiumFeatureLevel> _featureLevels = {
-  PremiumFeature.gradestats: PremiumFeatureLevel.kupak,
-  PremiumFeature.customcolors: PremiumFeatureLevel.kupak,
-  PremiumFeature.profile: PremiumFeatureLevel.kupak,
-  PremiumFeature.iconpack: PremiumFeatureLevel.kupak,
-  PremiumFeature.subjectrename: PremiumFeatureLevel.kupak,
-  PremiumFeature.weeklytimetable: PremiumFeatureLevel.tinta,
-  PremiumFeature.goalplanner: PremiumFeatureLevel.tinta,
-  PremiumFeature.widget: PremiumFeatureLevel.tinta,
-};
-
-const Map<PremiumFeature, String> _featureAssets = {
-  PremiumFeature.gradestats: "assets/images/premium_stats_showcase.png",
-  PremiumFeature.customcolors: "assets/images/premium_theme_showcase.png",
-  PremiumFeature.profile: "assets/images/premium_nickname_showcase.png",
-  PremiumFeature.weeklytimetable:
-      "assets/images/premium_timetable_showcase.png",
-  PremiumFeature.goalplanner: "assets/images/premium_goal_showcase.png",
-  PremiumFeature.widget: "assets/images/premium_widget_showcase.png",
-};
-
-const Map<PremiumFeature, String> _featureTitles = {
-  PremiumFeature.gradestats: "Találtál egy prémium funkciót.",
-  PremiumFeature.customcolors: "Több személyre szabás kell?",
-  PremiumFeature.profile: "Nem tetszik a neved?",
-  PremiumFeature.iconpack: "Jobban tetszettek a régi ikonok?",
-  PremiumFeature.subjectrename:
-      "Sokáig tart elolvasni, hogy \"Földrajz természettudomány\"?",
-  PremiumFeature.weeklytimetable: "Szeretnéd egyszerre az egész hetet látni?",
-  PremiumFeature.goalplanner: "Kövesd a céljaidat, sok-sok statisztikával.",
-  PremiumFeature.widget: "Órák a kezdőképernyőd kényelméből.",
-};
-
-const Map<PremiumFeature, String> _featureDescriptions = {
-  PremiumFeature.gradestats:
-      "Támogass Kupak szinten, hogy több statisztikát láthass. ",
-  PremiumFeature.customcolors:
-      "Támogass Kupak szinten, és szabd személyre az elemek, a háttér, és a panelek színeit.",
-  PremiumFeature.profile:
-      "Kupak szinten változtathatod a nevedet, sőt, akár a profilképedet is.",
-  PremiumFeature.iconpack:
-      "Támogass Kupak szinten, hogy ikon témát választhass.",
-  PremiumFeature.subjectrename:
-      "Támogass Kupak szinten, hogy átnevezhesd Föcire.",
-  PremiumFeature.weeklytimetable:
-      "Támogass Tinta szinten a heti órarend funkcióért.",
-  PremiumFeature.goalplanner: "A célkövetéshez támogass Tinta szinten.",
-  PremiumFeature.widget:
-      "Támogass Tinta szinten, és helyezz egy widgetet a kezdőképernyődre.",
-};
-
-class PremiumLockedFeatureUpsell extends StatelessWidget {
-  const PremiumLockedFeatureUpsell({super.key, required this.feature});
-
-  static void show(
-          {required BuildContext context, required PremiumFeature feature}) =>
-      showDialog(
-          context: context,
-          builder: (context) => PremiumLockedFeatureUpsell(feature: feature));
-
-  final PremiumFeature feature;
-
-  IconData _getIcon() => _featureLevels[feature] == PremiumFeatureLevel.kupak
-      ? FilcIcons.kupak
-      : FilcIcons.tinta;
-  Color _getColor(BuildContext context) =>
-      _featureLevels[feature] == PremiumFeatureLevel.kupak
-          ? const Color(0xffC8A708)
-          : Theme.of(context).brightness == Brightness.light
-              ? const Color(0xff691A9B)
-              : const Color(0xffA66FC8);
-  String? _getAsset() => _featureAssets[feature];
-  String _getTitle() => _featureTitles[feature]!;
-  String _getDescription() => _featureDescriptions[feature]!;
-
-  @override
-  Widget build(BuildContext context) {
-    final Color color = _getColor(context);
-
-    return Dialog(
-      child: Padding(
-        padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 16.0),
-        child: Column(
-          mainAxisSize: MainAxisSize.min,
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            // Title Bar
-            Row(
-              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-              children: [
-                Padding(
-                  padding: const EdgeInsets.only(left: 8.0),
-                  child: Icon(_getIcon()),
-                ),
-                IconButton(
-                  onPressed: () => Navigator.of(context).pop(),
-                  icon: const Icon(Icons.close),
-                ),
-              ],
-            ),
-
-            // Image showcase
-            if (_getAsset() != null)
-              Padding(
-                padding: const EdgeInsets.only(top: 8.0),
-                child: Image.asset(_getAsset()!),
-              ),
-
-            // Dialog title
-            Padding(
-              padding: const EdgeInsets.only(top: 12.0),
-              child: Text(
-                _getTitle(),
-                style: const TextStyle(
-                  fontWeight: FontWeight.bold,
-                  fontSize: 20.0,
-                ),
-              ),
-            ),
-
-            // Dialog description
-            Padding(
-              padding: const EdgeInsets.only(top: 8.0),
-              child: Text(
-                _getDescription(),
-                style: const TextStyle(
-                  fontSize: 16.0,
-                ),
-              ),
-            ),
-
-            // CTA button
-            Padding(
-              padding: const EdgeInsets.only(top: 8.0),
-              child: SizedBox(
-                width: double.infinity,
-                child: TextButton(
-                  style: ButtonStyle(
-                      backgroundColor:
-                          MaterialStatePropertyAll(color.withOpacity(.25)),
-                      foregroundColor: MaterialStatePropertyAll(color),
-                      overlayColor:
-                          MaterialStatePropertyAll(color.withOpacity(.1))),
-                  onPressed: () {
-                    Navigator.of(context, rootNavigator: true)
-                        .push(MaterialPageRoute(builder: (context) {
-                      return const PremiumScreen();
-                    }));
-                  },
-                  child: const Text(
-                    "Vigyél oda!",
-                    style: TextStyle(
-                      fontWeight: FontWeight.bold,
-                      fontSize: 18.0,
-                    ),
-                  ),
-                ),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
+import 'package:refilc/icons/filc_icons.dart';
+import 'package:refilc_mobile_ui/premium/premium_screen.dart';
+import 'package:flutter/material.dart';
+
+enum PremiumFeature {
+  gradestats,
+  customcolors,
+  profile,
+  iconpack,
+  subjectrename,
+  teacherrename,
+  weeklytimetable,
+  goalplanner,
+  widget,
+}
+
+enum PremiumFeatureLevel { kupak, tinta }
+
+const Map<PremiumFeature, PremiumFeatureLevel> _featureLevels = {
+  PremiumFeature.gradestats: PremiumFeatureLevel.kupak,
+  PremiumFeature.customcolors: PremiumFeatureLevel.kupak,
+  PremiumFeature.profile: PremiumFeatureLevel.kupak,
+  PremiumFeature.iconpack: PremiumFeatureLevel.kupak,
+  PremiumFeature.subjectrename: PremiumFeatureLevel.kupak,
+  PremiumFeature.weeklytimetable: PremiumFeatureLevel.tinta,
+  PremiumFeature.goalplanner: PremiumFeatureLevel.tinta,
+  PremiumFeature.widget: PremiumFeatureLevel.tinta,
+};
+
+const Map<PremiumFeature, String> _featureAssets = {
+  PremiumFeature.gradestats: "assets/images/premium_stats_showcase.png",
+  PremiumFeature.customcolors: "assets/images/premium_theme_showcase.png",
+  PremiumFeature.profile: "assets/images/premium_nickname_showcase.png",
+  PremiumFeature.weeklytimetable:
+      "assets/images/premium_timetable_showcase.png",
+  PremiumFeature.goalplanner: "assets/images/premium_goal_showcase.png",
+  PremiumFeature.widget: "assets/images/premium_widget_showcase.png",
+};
+
+const Map<PremiumFeature, String> _featureTitles = {
+  PremiumFeature.gradestats: "Találtál egy prémium funkciót.",
+  PremiumFeature.customcolors: "Több személyre szabás kell?",
+  PremiumFeature.profile: "Nem tetszik a neved?",
+  PremiumFeature.iconpack: "Jobban tetszettek a régi ikonok?",
+  PremiumFeature.subjectrename:
+      "Sokáig tart elolvasni, hogy \"Földrajz természettudomány\"?",
+  PremiumFeature.weeklytimetable: "Szeretnéd egyszerre az egész hetet látni?",
+  PremiumFeature.goalplanner: "Kövesd a céljaidat, sok-sok statisztikával.",
+  PremiumFeature.widget: "Órák a kezdőképernyőd kényelméből.",
+};
+
+const Map<PremiumFeature, String> _featureDescriptions = {
+  PremiumFeature.gradestats:
+      "Támogass Kupak szinten, hogy több statisztikát láthass. ",
+  PremiumFeature.customcolors:
+      "Támogass Kupak szinten, és szabd személyre az elemek, a háttér, és a panelek színeit.",
+  PremiumFeature.profile:
+      "Kupak szinten változtathatod a nevedet, sőt, akár a profilképedet is.",
+  PremiumFeature.iconpack:
+      "Támogass Kupak szinten, hogy ikon témát választhass.",
+  PremiumFeature.subjectrename:
+      "Támogass Kupak szinten, hogy átnevezhesd Föcire.",
+  PremiumFeature.weeklytimetable:
+      "Támogass Tinta szinten a heti órarend funkcióért.",
+  PremiumFeature.goalplanner: "A célkövetéshez támogass Tinta szinten.",
+  PremiumFeature.widget:
+      "Támogass Tinta szinten, és helyezz egy widgetet a kezdőképernyődre.",
+};
+
+class PremiumLockedFeatureUpsell extends StatelessWidget {
+  const PremiumLockedFeatureUpsell({super.key, required this.feature});
+
+  static void show(
+          {required BuildContext context, required PremiumFeature feature}) =>
+      showDialog(
+          context: context,
+          builder: (context) => PremiumLockedFeatureUpsell(feature: feature));
+
+  final PremiumFeature feature;
+
+  IconData _getIcon() => _featureLevels[feature] == PremiumFeatureLevel.kupak
+      ? FilcIcons.kupak
+      : FilcIcons.tinta;
+  Color _getColor(BuildContext context) =>
+      _featureLevels[feature] == PremiumFeatureLevel.kupak
+          ? const Color(0xffC8A708)
+          : Theme.of(context).brightness == Brightness.light
+              ? const Color(0xff691A9B)
+              : const Color(0xffA66FC8);
+  String? _getAsset() => _featureAssets[feature];
+  String _getTitle() => _featureTitles[feature]!;
+  String _getDescription() => _featureDescriptions[feature]!;
+
+  @override
+  Widget build(BuildContext context) {
+    final Color color = _getColor(context);
+
+    return Dialog(
+      child: Padding(
+        padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 16.0),
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            // Title Bar
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Padding(
+                  padding: const EdgeInsets.only(left: 8.0),
+                  child: Icon(_getIcon()),
+                ),
+                IconButton(
+                  onPressed: () => Navigator.of(context).pop(),
+                  icon: const Icon(Icons.close),
+                ),
+              ],
+            ),
+
+            // Image showcase
+            if (_getAsset() != null)
+              Padding(
+                padding: const EdgeInsets.only(top: 8.0),
+                child: Image.asset(_getAsset()!),
+              ),
+
+            // Dialog title
+            Padding(
+              padding: const EdgeInsets.only(top: 12.0),
+              child: Text(
+                _getTitle(),
+                style: const TextStyle(
+                  fontWeight: FontWeight.bold,
+                  fontSize: 20.0,
+                ),
+              ),
+            ),
+
+            // Dialog description
+            Padding(
+              padding: const EdgeInsets.only(top: 8.0),
+              child: Text(
+                _getDescription(),
+                style: const TextStyle(
+                  fontSize: 16.0,
+                ),
+              ),
+            ),
+
+            // CTA button
+            Padding(
+              padding: const EdgeInsets.only(top: 8.0),
+              child: SizedBox(
+                width: double.infinity,
+                child: TextButton(
+                  style: ButtonStyle(
+                      backgroundColor:
+                          MaterialStatePropertyAll(color.withOpacity(.25)),
+                      foregroundColor: MaterialStatePropertyAll(color),
+                      overlayColor:
+                          MaterialStatePropertyAll(color.withOpacity(.1))),
+                  onPressed: () {
+                    Navigator.of(context, rootNavigator: true)
+                        .push(MaterialPageRoute(builder: (context) {
+                      return const PremiumScreen();
+                    }));
+                  },
+                  child: const Text(
+                    "Vigyél oda!",
+                    style: TextStyle(
+                      fontWeight: FontWeight.bold,
+                      fontSize: 18.0,
+                    ),
+                  ),
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/icon_pack.dart b/refilc_premium/lib/ui/mobile/settings/icon_pack.dart
similarity index 63%
rename from filcnaplo_premium/lib/ui/mobile/settings/icon_pack.dart
rename to refilc_premium/lib/ui/mobile/settings/icon_pack.dart
index 2857946..b4659de 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/icon_pack.dart
+++ b/refilc_premium/lib/ui/mobile/settings/icon_pack.dart
@@ -1,39 +1,39 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
-import 'package:filcnaplo_mobile_ui/screens/settings/settings_helper.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:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo/utils/format.dart';
-
-class PremiumIconPackSelector extends StatelessWidget {
-  const PremiumIconPackSelector({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    final settings = Provider.of<SettingsProvider>(context);
-
-    return PanelButton(
-      onPressed: () {
-        if (!Provider.of<PremiumProvider>(context, listen: false)
-            .hasScope(PremiumScopes.customIcons)) {
-          PremiumLockedFeatureUpsell.show(
-              context: context, feature: PremiumFeature.iconpack);
-          return;
-        }
-
-        SettingsHelper.iconPack(context);
-      },
-      title: Text("icon_pack".i18n),
-      leading: const Icon(FeatherIcons.grid),
-      trailing: Text(
-        settings.iconPack.name.capital(),
-        style: const TextStyle(fontSize: 14.0),
-      ),
-    );
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_helper.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc/utils/format.dart';
+
+class PremiumIconPackSelector extends StatelessWidget {
+  const PremiumIconPackSelector({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final settings = Provider.of<SettingsProvider>(context);
+
+    return PanelButton(
+      onPressed: () {
+        if (!Provider.of<PremiumProvider>(context, listen: false)
+            .hasScope(PremiumScopes.customIcons)) {
+          PremiumLockedFeatureUpsell.show(
+              context: context, feature: PremiumFeature.iconpack);
+          return;
+        }
+
+        SettingsHelper.iconPack(context);
+      },
+      title: Text("icon_pack".i18n),
+      leading: const Icon(FeatherIcons.grid),
+      trailing: Text(
+        settings.iconPack.name.capital(),
+        style: const TextStyle(fontSize: 14.0),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/modify_names.i18n.dart b/refilc_premium/lib/ui/mobile/settings/modify_names.i18n.dart
similarity index 100%
rename from filcnaplo_premium/lib/ui/mobile/settings/modify_names.i18n.dart
rename to refilc_premium/lib/ui/mobile/settings/modify_names.i18n.dart
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/modify_subject_names.dart b/refilc_premium/lib/ui/mobile/settings/modify_subject_names.dart
similarity index 90%
rename from filcnaplo_premium/lib/ui/mobile/settings/modify_subject_names.dart
rename to refilc_premium/lib/ui/mobile/settings/modify_subject_names.dart
index 37daf97..7d75b11 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/modify_subject_names.dart
+++ b/refilc_premium/lib/ui/mobile/settings/modify_subject_names.dart
@@ -1,436 +1,438 @@
-import 'package:dropdown_button2/dropdown_button2.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/subject.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.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/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-
-import 'modify_names.i18n.dart';
-
-class MenuRenamedSubjects extends StatelessWidget {
-  const MenuRenamedSubjects({Key? key, required this.settings})
-      : super(key: key);
-
-  final SettingsProvider settings;
-
-  @override
-  Widget build(BuildContext context) {
-    return PanelButton(
-      padding: const EdgeInsets.only(left: 14.0),
-      onPressed: () {
-        if (!Provider.of<PremiumProvider>(context, listen: false)
-            .hasScope(PremiumScopes.renameSubjects)) {
-          PremiumLockedFeatureUpsell.show(
-              context: context, feature: PremiumFeature.subjectrename);
-          return;
-        }
-
-        Navigator.of(context, rootNavigator: true).push(
-          CupertinoPageRoute(builder: (context) => const ModifySubjectNames()),
-        );
-      },
-      title: Text(
-        "rename_subjects".i18n,
-        style: TextStyle(
-            color: AppColors.of(context)
-                .text
-                .withOpacity(settings.renamedSubjectsEnabled ? 1.0 : .5)),
-      ),
-      leading: settings.renamedSubjectsEnabled
-          ? const Icon(FeatherIcons.penTool)
-          : Icon(FeatherIcons.penTool,
-              color: AppColors.of(context).text.withOpacity(.25)),
-      trailingDivider: true,
-      trailing: Switch(
-        onChanged: (v) async {
-          if (!Provider.of<PremiumProvider>(context, listen: false)
-              .hasScope(PremiumScopes.renameSubjects)) {
-            PremiumLockedFeatureUpsell.show(
-                context: context, feature: PremiumFeature.subjectrename);
-            return;
-          }
-
-          settings.update(renamedSubjectsEnabled: v);
-          await Provider.of<GradeProvider>(context, listen: false)
-              .convertBySettings();
-          await Provider.of<TimetableProvider>(context, listen: false)
-              .convertBySettings();
-          await Provider.of<AbsenceProvider>(context, listen: false)
-              .convertBySettings();
-        },
-        value: settings.renamedSubjectsEnabled,
-        activeColor: Theme.of(context).colorScheme.secondary,
-      ),
-    );
-  }
-}
-
-class ModifySubjectNames extends StatefulWidget {
-  const ModifySubjectNames({Key? key}) : super(key: key);
-
-  @override
-  State<ModifySubjectNames> createState() => _ModifySubjectNamesState();
-}
-
-class _ModifySubjectNamesState extends State<ModifySubjectNames> {
-  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
-  final _subjectName = TextEditingController();
-  String? selectedSubjectId;
-
-  late List<Subject> subjects;
-  late UserProvider user;
-  late DatabaseProvider dbProvider;
-  late SettingsProvider settings;
-
-  @override
-  void initState() {
-    super.initState();
-    subjects = Provider.of<GradeProvider>(context, listen: false)
-        .grades
-        .map((e) => e.subject)
-        .toSet()
-        .toList()
-      ..sort((a, b) => a.name.compareTo(b.name));
-    user = Provider.of<UserProvider>(context, listen: false);
-    dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
-  }
-
-  Future<Map<String, String>> fetchRenamedSubjects() async {
-    return await dbProvider.userQuery.renamedSubjects(userId: user.id!);
-  }
-
-  void showRenameDialog() {
-    showDialog(
-      context: context,
-      builder: (context) => StatefulBuilder(builder: (context, setS) {
-        return AlertDialog(
-          shape: const RoundedRectangleBorder(
-              borderRadius: BorderRadius.all(Radius.circular(14.0))),
-          title: Text("rename_subject".i18n),
-          content: Column(
-            mainAxisSize: MainAxisSize.min,
-            children: [
-              DropdownButton2(
-                items: subjects
-                    .map((item) => DropdownMenuItem<String>(
-                          value: item.id,
-                          child: Text(
-                            item.name,
-                            style: TextStyle(
-                              fontSize: 14,
-                              fontWeight: FontWeight.bold,
-                              color: AppColors.of(context).text,
-                            ),
-                            overflow: TextOverflow.ellipsis,
-                          ),
-                        ))
-                    .toList(),
-                onChanged: (String? v) async {
-                  final renamedSubs = await fetchRenamedSubjects();
-
-                  setS(() {
-                    selectedSubjectId = v;
-
-                    if (renamedSubs.containsKey(selectedSubjectId)) {
-                      _subjectName.text = renamedSubs[selectedSubjectId]!;
-                    } else {
-                      _subjectName.text = "";
-                    }
-                  });
-                },
-                iconSize: 14,
-                iconEnabledColor: AppColors.of(context).text,
-                iconDisabledColor: AppColors.of(context).text,
-                underline: const SizedBox(),
-                itemHeight: 40,
-                itemPadding: const EdgeInsets.only(left: 14, right: 14),
-                buttonWidth: 50,
-                dropdownWidth: 300,
-                dropdownPadding: null,
-                buttonDecoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(8),
-                ),
-                dropdownDecoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(14),
-                ),
-                dropdownElevation: 8,
-                scrollbarRadius: const Radius.circular(40),
-                scrollbarThickness: 6,
-                scrollbarAlwaysShow: true,
-                offset: const Offset(-10, -10),
-                buttonSplashColor: Colors.transparent,
-                customButton: Container(
-                  width: double.infinity,
-                  decoration: BoxDecoration(
-                    border: Border.all(color: Colors.grey, width: 2),
-                    borderRadius: BorderRadius.circular(12.0),
-                  ),
-                  padding: const EdgeInsets.symmetric(
-                      vertical: 12.0, horizontal: 8.0),
-                  child: Text(
-                    selectedSubjectId == null
-                        ? "select_subject".i18n
-                        : subjects
-                            .firstWhere(
-                                (element) => element.id == selectedSubjectId)
-                            .name,
-                    style: Theme.of(context).textTheme.titleSmall!.copyWith(
-                        fontWeight: FontWeight.w700,
-                        color: AppColors.of(context).text.withOpacity(0.75)),
-                    overflow: TextOverflow.ellipsis,
-                    maxLines: 2,
-                    textAlign: TextAlign.center,
-                  ),
-                ),
-              ),
-              const Padding(
-                padding: EdgeInsets.symmetric(vertical: 8.0),
-                child: Icon(FeatherIcons.arrowDown, size: 32),
-              ),
-              TextField(
-                controller: _subjectName,
-                decoration: InputDecoration(
-                  border: OutlineInputBorder(
-                    borderSide:
-                        const BorderSide(color: Colors.grey, width: 1.5),
-                    borderRadius: BorderRadius.circular(12.0),
-                  ),
-                  focusedBorder: OutlineInputBorder(
-                    borderSide:
-                        const BorderSide(color: Colors.grey, width: 1.5),
-                    borderRadius: BorderRadius.circular(12.0),
-                  ),
-                  contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
-                  hintText: "modified_name".i18n,
-                  suffixIcon: IconButton(
-                    icon: const Icon(
-                      FeatherIcons.x,
-                      color: Colors.grey,
-                    ),
-                    onPressed: () {
-                      setState(() {
-                        _subjectName.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: () async {
-                if (selectedSubjectId != null) {
-                  final renamedSubs = await fetchRenamedSubjects();
-
-                  renamedSubs[selectedSubjectId!] = _subjectName.text;
-                  await dbProvider.userStore
-                      .storeRenamedSubjects(renamedSubs, userId: user.id!);
-                  await Provider.of<GradeProvider>(context, listen: false)
-                      .convertBySettings();
-                  await Provider.of<TimetableProvider>(context, listen: false)
-                      .convertBySettings();
-                  await Provider.of<AbsenceProvider>(context, listen: false)
-                      .convertBySettings();
-                }
-                Navigator.of(context).pop(true);
-                setState(() {});
-              },
-            ),
-          ],
-        );
-      }),
-    ).then((val) {
-      _subjectName.text = "";
-      selectedSubjectId = null;
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    settings = Provider.of<SettingsProvider>(context);
-    return Scaffold(
-        key: _scaffoldKey,
-        appBar: AppBar(
-          surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-          leading: BackButton(color: AppColors.of(context).text),
-          title: Text(
-            "modify_subjects".i18n,
-            style: TextStyle(color: AppColors.of(context).text),
-          ),
-        ),
-        body: Padding(
-          padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
-          child: SingleChildScrollView(
-            child: Column(
-              crossAxisAlignment: CrossAxisAlignment.start,
-              children: [
-                Panel(
-                  child: SwitchListTile(
-                      title: Text("italics_toggle".i18n),
-                      onChanged: (value) => settings.update(renamedSubjectsItalics: value),
-                      value: settings.renamedSubjectsItalics,),
-                ),
-                const SizedBox(
-                  height: 20,
-                ),
-                InkWell(
-                  onTap: showRenameDialog,
-                  borderRadius: BorderRadius.circular(12.0),
-                  child: Container(
-                    width: double.infinity,
-                    decoration: BoxDecoration(
-                      border: Border.all(color: Colors.grey, width: 2),
-                      borderRadius: BorderRadius.circular(12.0),
-                    ),
-                    padding: const EdgeInsets.symmetric(
-                        vertical: 18.0, horizontal: 12.0),
-                    child: Center(
-                      child: Text(
-                        "rename_new_subject".i18n,
-                        style: TextStyle(
-                          fontWeight: FontWeight.w600,
-                          fontSize: 18,
-                          color: AppColors.of(context).text.withOpacity(.85),
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-                const SizedBox(
-                  height: 30,
-                ),
-                FutureBuilder<Map<String, String>>(
-                  future: fetchRenamedSubjects(),
-                  builder: (context, snapshot) {
-                    if (!snapshot.hasData || snapshot.data!.isEmpty) {
-                      return Container();
-                    }
-
-                    return Panel(
-                      title: Text("renamed_subjects".i18n),
-                      child: Column(
-                        children: snapshot.data!.keys.map(
-                          (key) {
-                            Subject? subject = subjects
-                                .firstWhere((element) => key == element.id);
-                            String renameTo = snapshot.data![key]!;
-                            return RenamedSubjectItem(
-                              subject: subject,
-                              renamedTo: renameTo,
-                              modifyCallback: () {
-                                setState(() {
-                                  selectedSubjectId = subject.id;
-                                  _subjectName.text = renameTo;
-                                });
-                                showRenameDialog();
-                              },
-                              removeCallback: () {
-                                setState(() {
-                                  Map<String, String> subs =
-                                      Map.from(snapshot.data!);
-                                  subs.remove(key);
-                                  dbProvider.userStore.storeRenamedSubjects(
-                                      subs,
-                                      userId: user.id!);
-                                });
-                              },
-                            );
-                          },
-                        ).toList(),
-                      ),
-                    );
-                  },
-                ),
-              ],
-            ),
-          ),
-        ));
-  }
-}
-
-class RenamedSubjectItem extends StatelessWidget {
-  const RenamedSubjectItem({
-    Key? key,
-    required this.subject,
-    required this.renamedTo,
-    required this.modifyCallback,
-    required this.removeCallback,
-  }) : super(key: key);
-
-  final Subject subject;
-  final String renamedTo;
-  final void Function() modifyCallback;
-  final void Function() removeCallback;
-
-  @override
-  Widget build(BuildContext context) {
-    return ListTile(
-      minLeadingWidth: 32.0,
-      dense: true,
-      contentPadding:
-          const EdgeInsets.symmetric(horizontal: 16.0, vertical: 6.0),
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
-      visualDensity: VisualDensity.compact,
-      onTap: () {},
-      leading: Icon(
-          SubjectIcon.resolveVariant(subject: subject, context: context),
-          color: AppColors.of(context).text.withOpacity(.75)),
-      title: InkWell(
-        onTap: modifyCallback,
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            Text(
-              subject.name.capital(),
-              style: TextStyle(
-                  fontWeight: FontWeight.w500,
-                  fontSize: 14,
-                  color: AppColors.of(context).text.withOpacity(.75)),
-              maxLines: 1,
-              overflow: TextOverflow.ellipsis,
-            ),
-            Text(
-              renamedTo,
-              style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
-              maxLines: 2,
-              overflow: TextOverflow.ellipsis,
-            ),
-          ],
-        ),
-      ),
-      trailing: InkWell(
-        onTap: removeCallback,
-        child: Icon(FeatherIcons.trash,
-            color: AppColors.of(context).red.withOpacity(.75)),
-      ),
-    );
-  }
-}
+import 'package:dropdown_button2/dropdown_button2.dart';
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/subject.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+
+import 'modify_names.i18n.dart';
+
+class MenuRenamedSubjects extends StatelessWidget {
+  const MenuRenamedSubjects({Key? key, required this.settings})
+      : super(key: key);
+
+  final SettingsProvider settings;
+
+  @override
+  Widget build(BuildContext context) {
+    return PanelButton(
+      padding: const EdgeInsets.only(left: 14.0),
+      onPressed: () {
+        if (!Provider.of<PremiumProvider>(context, listen: false)
+            .hasScope(PremiumScopes.renameSubjects)) {
+          PremiumLockedFeatureUpsell.show(
+              context: context, feature: PremiumFeature.subjectrename);
+          return;
+        }
+
+        Navigator.of(context, rootNavigator: true).push(
+          CupertinoPageRoute(builder: (context) => const ModifySubjectNames()),
+        );
+      },
+      title: Text(
+        "rename_subjects".i18n,
+        style: TextStyle(
+            color: AppColors.of(context)
+                .text
+                .withOpacity(settings.renamedSubjectsEnabled ? 1.0 : .5)),
+      ),
+      leading: settings.renamedSubjectsEnabled
+          ? const Icon(FeatherIcons.penTool)
+          : Icon(FeatherIcons.penTool,
+              color: AppColors.of(context).text.withOpacity(.25)),
+      trailingDivider: true,
+      trailing: Switch(
+        onChanged: (v) async {
+          if (!Provider.of<PremiumProvider>(context, listen: false)
+              .hasScope(PremiumScopes.renameSubjects)) {
+            PremiumLockedFeatureUpsell.show(
+                context: context, feature: PremiumFeature.subjectrename);
+            return;
+          }
+
+          settings.update(renamedSubjectsEnabled: v);
+          await Provider.of<GradeProvider>(context, listen: false)
+              .convertBySettings();
+          await Provider.of<TimetableProvider>(context, listen: false)
+              .convertBySettings();
+          await Provider.of<AbsenceProvider>(context, listen: false)
+              .convertBySettings();
+        },
+        value: settings.renamedSubjectsEnabled,
+        activeColor: Theme.of(context).colorScheme.secondary,
+      ),
+    );
+  }
+}
+
+class ModifySubjectNames extends StatefulWidget {
+  const ModifySubjectNames({Key? key}) : super(key: key);
+
+  @override
+  State<ModifySubjectNames> createState() => _ModifySubjectNamesState();
+}
+
+class _ModifySubjectNamesState extends State<ModifySubjectNames> {
+  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+  final _subjectName = TextEditingController();
+  String? selectedSubjectId;
+
+  late List<Subject> subjects;
+  late UserProvider user;
+  late DatabaseProvider dbProvider;
+  late SettingsProvider settings;
+
+  @override
+  void initState() {
+    super.initState();
+    subjects = Provider.of<GradeProvider>(context, listen: false)
+        .grades
+        .map((e) => e.subject)
+        .toSet()
+        .toList()
+      ..sort((a, b) => a.name.compareTo(b.name));
+    user = Provider.of<UserProvider>(context, listen: false);
+    dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
+  }
+
+  Future<Map<String, String>> fetchRenamedSubjects() async {
+    return await dbProvider.userQuery.renamedSubjects(userId: user.id!);
+  }
+
+  void showRenameDialog() {
+    showDialog(
+      context: context,
+      builder: (context) => StatefulBuilder(builder: (context, setS) {
+        return AlertDialog(
+          shape: const RoundedRectangleBorder(
+              borderRadius: BorderRadius.all(Radius.circular(14.0))),
+          title: Text("rename_subject".i18n),
+          content: Column(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              DropdownButton2(
+                items: subjects
+                    .map((item) => DropdownMenuItem<String>(
+                          value: item.id,
+                          child: Text(
+                            item.name,
+                            style: TextStyle(
+                              fontSize: 14,
+                              fontWeight: FontWeight.bold,
+                              color: AppColors.of(context).text,
+                            ),
+                            overflow: TextOverflow.ellipsis,
+                          ),
+                        ))
+                    .toList(),
+                onChanged: (String? v) async {
+                  final renamedSubs = await fetchRenamedSubjects();
+
+                  setS(() {
+                    selectedSubjectId = v;
+
+                    if (renamedSubs.containsKey(selectedSubjectId)) {
+                      _subjectName.text = renamedSubs[selectedSubjectId]!;
+                    } else {
+                      _subjectName.text = "";
+                    }
+                  });
+                },
+                iconSize: 14,
+                iconEnabledColor: AppColors.of(context).text,
+                iconDisabledColor: AppColors.of(context).text,
+                underline: const SizedBox(),
+                itemHeight: 40,
+                itemPadding: const EdgeInsets.only(left: 14, right: 14),
+                buttonWidth: 50,
+                dropdownWidth: 300,
+                dropdownPadding: null,
+                buttonDecoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(8),
+                ),
+                dropdownDecoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(14),
+                ),
+                dropdownElevation: 8,
+                scrollbarRadius: const Radius.circular(40),
+                scrollbarThickness: 6,
+                scrollbarAlwaysShow: true,
+                offset: const Offset(-10, -10),
+                buttonSplashColor: Colors.transparent,
+                customButton: Container(
+                  width: double.infinity,
+                  decoration: BoxDecoration(
+                    border: Border.all(color: Colors.grey, width: 2),
+                    borderRadius: BorderRadius.circular(12.0),
+                  ),
+                  padding: const EdgeInsets.symmetric(
+                      vertical: 12.0, horizontal: 8.0),
+                  child: Text(
+                    selectedSubjectId == null
+                        ? "select_subject".i18n
+                        : subjects
+                            .firstWhere(
+                                (element) => element.id == selectedSubjectId)
+                            .name,
+                    style: Theme.of(context).textTheme.titleSmall!.copyWith(
+                        fontWeight: FontWeight.w700,
+                        color: AppColors.of(context).text.withOpacity(0.75)),
+                    overflow: TextOverflow.ellipsis,
+                    maxLines: 2,
+                    textAlign: TextAlign.center,
+                  ),
+                ),
+              ),
+              const Padding(
+                padding: EdgeInsets.symmetric(vertical: 8.0),
+                child: Icon(FeatherIcons.arrowDown, size: 32),
+              ),
+              TextField(
+                controller: _subjectName,
+                decoration: InputDecoration(
+                  border: OutlineInputBorder(
+                    borderSide:
+                        const BorderSide(color: Colors.grey, width: 1.5),
+                    borderRadius: BorderRadius.circular(12.0),
+                  ),
+                  focusedBorder: OutlineInputBorder(
+                    borderSide:
+                        const BorderSide(color: Colors.grey, width: 1.5),
+                    borderRadius: BorderRadius.circular(12.0),
+                  ),
+                  contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
+                  hintText: "modified_name".i18n,
+                  suffixIcon: IconButton(
+                    icon: const Icon(
+                      FeatherIcons.x,
+                      color: Colors.grey,
+                    ),
+                    onPressed: () {
+                      setState(() {
+                        _subjectName.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: () async {
+                if (selectedSubjectId != null) {
+                  final renamedSubs = await fetchRenamedSubjects();
+
+                  renamedSubs[selectedSubjectId!] = _subjectName.text;
+                  await dbProvider.userStore
+                      .storeRenamedSubjects(renamedSubs, userId: user.id!);
+                  await Provider.of<GradeProvider>(context, listen: false)
+                      .convertBySettings();
+                  await Provider.of<TimetableProvider>(context, listen: false)
+                      .convertBySettings();
+                  await Provider.of<AbsenceProvider>(context, listen: false)
+                      .convertBySettings();
+                }
+                Navigator.of(context).pop(true);
+                setState(() {});
+              },
+            ),
+          ],
+        );
+      }),
+    ).then((val) {
+      _subjectName.text = "";
+      selectedSubjectId = null;
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    settings = Provider.of<SettingsProvider>(context);
+    return Scaffold(
+        key: _scaffoldKey,
+        appBar: AppBar(
+          surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+          leading: BackButton(color: AppColors.of(context).text),
+          title: Text(
+            "modify_subjects".i18n,
+            style: TextStyle(color: AppColors.of(context).text),
+          ),
+        ),
+        body: Padding(
+          padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
+          child: SingleChildScrollView(
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                Panel(
+                  child: SwitchListTile(
+                    title: Text("italics_toggle".i18n),
+                    onChanged: (value) =>
+                        settings.update(renamedSubjectsItalics: value),
+                    value: settings.renamedSubjectsItalics,
+                  ),
+                ),
+                const SizedBox(
+                  height: 20,
+                ),
+                InkWell(
+                  onTap: showRenameDialog,
+                  borderRadius: BorderRadius.circular(12.0),
+                  child: Container(
+                    width: double.infinity,
+                    decoration: BoxDecoration(
+                      border: Border.all(color: Colors.grey, width: 2),
+                      borderRadius: BorderRadius.circular(12.0),
+                    ),
+                    padding: const EdgeInsets.symmetric(
+                        vertical: 18.0, horizontal: 12.0),
+                    child: Center(
+                      child: Text(
+                        "rename_new_subject".i18n,
+                        style: TextStyle(
+                          fontWeight: FontWeight.w600,
+                          fontSize: 18,
+                          color: AppColors.of(context).text.withOpacity(.85),
+                        ),
+                      ),
+                    ),
+                  ),
+                ),
+                const SizedBox(
+                  height: 30,
+                ),
+                FutureBuilder<Map<String, String>>(
+                  future: fetchRenamedSubjects(),
+                  builder: (context, snapshot) {
+                    if (!snapshot.hasData || snapshot.data!.isEmpty) {
+                      return Container();
+                    }
+
+                    return Panel(
+                      title: Text("renamed_subjects".i18n),
+                      child: Column(
+                        children: snapshot.data!.keys.map(
+                          (key) {
+                            Subject? subject = subjects
+                                .firstWhere((element) => key == element.id);
+                            String renameTo = snapshot.data![key]!;
+                            return RenamedSubjectItem(
+                              subject: subject,
+                              renamedTo: renameTo,
+                              modifyCallback: () {
+                                setState(() {
+                                  selectedSubjectId = subject.id;
+                                  _subjectName.text = renameTo;
+                                });
+                                showRenameDialog();
+                              },
+                              removeCallback: () {
+                                setState(() {
+                                  Map<String, String> subs =
+                                      Map.from(snapshot.data!);
+                                  subs.remove(key);
+                                  dbProvider.userStore.storeRenamedSubjects(
+                                      subs,
+                                      userId: user.id!);
+                                });
+                              },
+                            );
+                          },
+                        ).toList(),
+                      ),
+                    );
+                  },
+                ),
+              ],
+            ),
+          ),
+        ));
+  }
+}
+
+class RenamedSubjectItem extends StatelessWidget {
+  const RenamedSubjectItem({
+    Key? key,
+    required this.subject,
+    required this.renamedTo,
+    required this.modifyCallback,
+    required this.removeCallback,
+  }) : super(key: key);
+
+  final Subject subject;
+  final String renamedTo;
+  final void Function() modifyCallback;
+  final void Function() removeCallback;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListTile(
+      minLeadingWidth: 32.0,
+      dense: true,
+      contentPadding:
+          const EdgeInsets.symmetric(horizontal: 16.0, vertical: 6.0),
+      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+      visualDensity: VisualDensity.compact,
+      onTap: () {},
+      leading: Icon(
+          SubjectIcon.resolveVariant(subject: subject, context: context),
+          color: AppColors.of(context).text.withOpacity(.75)),
+      title: InkWell(
+        onTap: modifyCallback,
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Text(
+              subject.name.capital(),
+              style: TextStyle(
+                  fontWeight: FontWeight.w500,
+                  fontSize: 14,
+                  color: AppColors.of(context).text.withOpacity(.75)),
+              maxLines: 1,
+              overflow: TextOverflow.ellipsis,
+            ),
+            Text(
+              renamedTo,
+              style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
+              maxLines: 2,
+              overflow: TextOverflow.ellipsis,
+            ),
+          ],
+        ),
+      ),
+      trailing: InkWell(
+        onTap: removeCallback,
+        child: Icon(FeatherIcons.trash,
+            color: AppColors.of(context).red.withOpacity(.75)),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/modify_teacher_names.dart b/refilc_premium/lib/ui/mobile/settings/modify_teacher_names.dart
similarity index 94%
rename from filcnaplo_premium/lib/ui/mobile/settings/modify_teacher_names.dart
rename to refilc_premium/lib/ui/mobile/settings/modify_teacher_names.dart
index c9f9a55..cfa8d0e 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/modify_teacher_names.dart
+++ b/refilc_premium/lib/ui/mobile/settings/modify_teacher_names.dart
@@ -1,18 +1,18 @@
 import 'package:dropdown_button2/dropdown_button2.dart';
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'package:filcnaplo_kreta_api/models/teacher.dart';
-import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
-import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.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:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/utils/format.dart';
+import 'package:refilc_kreta_api/models/teacher.dart';
+import 'package:refilc_kreta_api/providers/absence_provider.dart';
+import 'package:refilc_kreta_api/providers/grade_provider.dart';
+import 'package:refilc_kreta_api/providers/timetable_provider.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_feather_icons/flutter_feather_icons.dart';
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/nickname.dart b/refilc_premium/lib/ui/mobile/settings/nickname.dart
similarity index 80%
rename from filcnaplo_premium/lib/ui/mobile/settings/nickname.dart
rename to refilc_premium/lib/ui/mobile/settings/nickname.dart
index 865537d..c8e6f99 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/nickname.dart
+++ b/refilc_premium/lib/ui/mobile/settings/nickname.dart
@@ -1,105 +1,105 @@
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.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';
-
-// ignore: must_be_immutable
-class UserMenuNickname extends StatelessWidget {
-  late User u;
-
-  UserMenuNickname(this.u, {Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return BottomSheetMenuItem(
-      onPressed: () {
-        if (!Provider.of<PremiumProvider>(context, listen: false)
-            .hasScope(PremiumScopes.nickname)) {
-          PremiumLockedFeatureUpsell.show(
-              context: context, feature: PremiumFeature.profile);
-          return;
-        }
-        showDialog(
-            context: context, builder: (context) => UserNicknameEditor(u));
-      },
-      icon: const Icon(FeatherIcons.edit2),
-      title: Text("edit_nickname".i18n),
-    );
-  }
-}
-
-// ignore: must_be_immutable
-class UserNicknameEditor extends StatefulWidget {
-  late User u;
-
-  UserNicknameEditor(this.u, {Key? key}) : super(key: key);
-
-  @override
-  State<UserNicknameEditor> createState() => _UserNicknameEditorState();
-}
-
-class _UserNicknameEditorState extends State<UserNicknameEditor> {
-  final _userName = TextEditingController();
-  late final UserProvider user;
-
-  @override
-  void initState() {
-    super.initState();
-    user = Provider.of<UserProvider>(context, listen: false);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return AlertDialog(
-      title: Text("change_username".i18n),
-      content: TextField(
-        controller: _userName,
-        autofocus: true,
-        decoration: InputDecoration(
-          border: const OutlineInputBorder(),
-          label: Text(widget.u.name),
-          suffixIcon: IconButton(
-            icon: const Icon(FeatherIcons.x),
-            onPressed: () {
-              setState(() {
-                _userName.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: () {
-            widget.u.nickname = _userName.text.trim();
-            Provider.of<DatabaseProvider>(context, listen: false)
-                .store
-                .storeUser(widget.u);
-            Provider.of<UserProvider>(context, listen: false).refresh();
-            Navigator.of(context).pop(true);
-          },
-        ),
-      ],
-    );
-  }
-}
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
+import 'package:provider/provider.dart';
+
+// ignore: must_be_immutable
+class UserMenuNickname extends StatelessWidget {
+  late User u;
+
+  UserMenuNickname(this.u, {Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BottomSheetMenuItem(
+      onPressed: () {
+        if (!Provider.of<PremiumProvider>(context, listen: false)
+            .hasScope(PremiumScopes.nickname)) {
+          PremiumLockedFeatureUpsell.show(
+              context: context, feature: PremiumFeature.profile);
+          return;
+        }
+        showDialog(
+            context: context, builder: (context) => UserNicknameEditor(u));
+      },
+      icon: const Icon(FeatherIcons.edit2),
+      title: Text("edit_nickname".i18n),
+    );
+  }
+}
+
+// ignore: must_be_immutable
+class UserNicknameEditor extends StatefulWidget {
+  late User u;
+
+  UserNicknameEditor(this.u, {Key? key}) : super(key: key);
+
+  @override
+  State<UserNicknameEditor> createState() => _UserNicknameEditorState();
+}
+
+class _UserNicknameEditorState extends State<UserNicknameEditor> {
+  final _userName = TextEditingController();
+  late final UserProvider user;
+
+  @override
+  void initState() {
+    super.initState();
+    user = Provider.of<UserProvider>(context, listen: false);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return AlertDialog(
+      title: Text("change_username".i18n),
+      content: TextField(
+        controller: _userName,
+        autofocus: true,
+        decoration: InputDecoration(
+          border: const OutlineInputBorder(),
+          label: Text(widget.u.name),
+          suffixIcon: IconButton(
+            icon: const Icon(FeatherIcons.x),
+            onPressed: () {
+              setState(() {
+                _userName.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: () {
+            widget.u.nickname = _userName.text.trim();
+            Provider.of<DatabaseProvider>(context, listen: false)
+                .store
+                .storeUser(widget.u);
+            Provider.of<UserProvider>(context, listen: false).refresh();
+            Navigator.of(context).pop(true);
+          },
+        ),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/profile_pic.dart b/refilc_premium/lib/ui/mobile/settings/profile_pic.dart
similarity index 89%
rename from filcnaplo_premium/lib/ui/mobile/settings/profile_pic.dart
rename to refilc_premium/lib/ui/mobile/settings/profile_pic.dart
index 154f168..493f0dd 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/profile_pic.dart
+++ b/refilc_premium/lib/ui/mobile/settings/profile_pic.dart
@@ -1,234 +1,234 @@
-import 'dart:convert';
-import 'dart:developer';
-import 'dart:io';
-
-import 'package:filcnaplo/api/providers/database_provider.dart';
-import 'package:filcnaplo/api/providers/user_provider.dart';
-import 'package:filcnaplo/models/user.dart';
-import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
-import 'package:filcnaplo_premium/models/premium_scopes.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.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:image_picker/image_picker.dart';
-import 'package:image_crop/image_crop.dart';
-
-// ignore: must_be_immutable
-class UserMenuProfilePic extends StatelessWidget {
-  late User u;
-
-  UserMenuProfilePic(this.u, {Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    if (!Provider.of<PremiumProvider>(context)
-        .hasScope(PremiumScopes.nickname)) {
-      return const SizedBox();
-    }
-
-    return BottomSheetMenuItem(
-      onPressed: () {
-        showDialog(
-            context: context, builder: (context) => UserProfilePicEditor(u));
-      },
-      icon: const Icon(FeatherIcons.camera),
-      title: Text("edit_profile_picture".i18n),
-    );
-  }
-}
-
-// ignore: must_be_immutable
-class UserProfilePicEditor extends StatefulWidget {
-  late User u;
-
-  UserProfilePicEditor(this.u, {Key? key}) : super(key: key);
-
-  @override
-  State<UserProfilePicEditor> createState() => _UserProfilePicEditorState();
-}
-
-class _UserProfilePicEditorState extends State<UserProfilePicEditor> {
-  late final UserProvider user;
-
-  final cropKey = GlobalKey<CropState>();
-  File? _file;
-  File? _sample;
-  File? _lastCropped;
-
-  File? image;
-  Future pickImage() async {
-    try {
-      final image = await ImagePicker().pickImage(source: ImageSource.gallery);
-      if (image == null) return;
-      File imageFile = File(image.path);
-
-      final sample = await ImageCrop.sampleImage(
-        file: imageFile,
-        preferredSize: context.size!.longestSide.ceil(),
-      );
-
-      _sample?.delete();
-      _file?.delete();
-
-      setState(() {
-        _sample = sample;
-        _file = imageFile;
-      });
-    } on PlatformException catch (e) {
-      log('Failed to pick image: $e');
-    }
-  }
-
-  Widget cropImageWidget() {
-    return SizedBox(
-      height: 300,
-      child: Crop.file(
-        _sample!,
-        key: cropKey,
-        aspectRatio: 1.0,
-      ),
-    );
-  }
-
-  Widget openImageWidget() {
-    return InkWell(
-      customBorder: RoundedRectangleBorder(
-        borderRadius: BorderRadius.circular(14.0),
-      ),
-      onTap: () => pickImage(),
-      child: Container(
-        decoration: BoxDecoration(
-          border: Border.all(color: Colors.grey),
-          borderRadius: BorderRadius.circular(14.0),
-        ),
-        width: double.infinity,
-        padding: const EdgeInsets.symmetric(vertical: 32.0, horizontal: 8.0),
-        child: Column(
-          children: [
-            Text(
-              "click_here".i18n,
-              style: const TextStyle(
-                fontSize: 22.0,
-                fontWeight: FontWeight.w600,
-              ),
-            ),
-            Text(
-              "select_profile_picture".i18n,
-              style: const TextStyle(
-                fontSize: 14.0,
-                fontWeight: FontWeight.w500,
-              ),
-            )
-          ],
-        ),
-      ),
-    );
-  }
-
-  Future<void> _cropImage() async {
-    final scale = cropKey.currentState!.scale;
-    final area = cropKey.currentState!.area;
-    if (area == null || _file == null) {
-      return;
-    }
-
-    final sample = await ImageCrop.sampleImage(
-      file: _file!,
-      preferredSize: (2000 / scale).round(),
-    );
-
-    final file = await ImageCrop.cropImage(
-      file: sample,
-      area: area,
-    );
-
-    sample.delete();
-
-    _lastCropped?.delete();
-    _lastCropped = file;
-
-    List<int> imageBytes = await _lastCropped!.readAsBytes();
-    String base64Image = base64Encode(imageBytes);
-    widget.u.picture = base64Image;
-    Provider.of<DatabaseProvider>(context, listen: false)
-        .store
-        .storeUser(widget.u);
-    Provider.of<UserProvider>(context, listen: false).refresh();
-
-    debugPrint('$file');
-  }
-
-  @override
-  void initState() {
-    super.initState();
-    user = Provider.of<UserProvider>(context, listen: false);
-  }
-
-  @override
-  void dispose() {
-    super.dispose();
-    _file?.delete();
-    _sample?.delete();
-    _lastCropped?.delete();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return AlertDialog(
-      shape: const RoundedRectangleBorder(
-          borderRadius: BorderRadius.all(Radius.circular(14.0))),
-      contentPadding: const EdgeInsets.only(top: 10.0),
-      title: Text("edit_profile_picture".i18n),
-      content: Column(
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          Padding(
-            padding:
-                const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-            child: _sample == null ? openImageWidget() : cropImageWidget(),
-          ),
-          if (widget.u.picture != "")
-            TextButton(
-              child: Text(
-                "remove_profile_picture".i18n,
-                style: const TextStyle(
-                    fontWeight: FontWeight.w500, color: Colors.red),
-              ),
-              onPressed: () {
-                widget.u.picture = "";
-                Provider.of<DatabaseProvider>(context, listen: false)
-                    .store
-                    .storeUser(widget.u);
-                Provider.of<UserProvider>(context, listen: false).refresh();
-                Navigator.of(context).pop(true);
-              },
-            ),
-        ],
-      ),
-      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: () async {
-            await _cropImage();
-            Navigator.of(context).pop(true);
-          },
-        ),
-      ],
-    );
-  }
-}
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io';
+
+import 'package:refilc/api/providers/database_provider.dart';
+import 'package:refilc/api/providers/user_provider.dart';
+import 'package:refilc/models/user.dart';
+import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu_item.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
+import 'package:provider/provider.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:image_crop/image_crop.dart';
+
+// ignore: must_be_immutable
+class UserMenuProfilePic extends StatelessWidget {
+  late User u;
+
+  UserMenuProfilePic(this.u, {Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    if (!Provider.of<PremiumProvider>(context)
+        .hasScope(PremiumScopes.nickname)) {
+      return const SizedBox();
+    }
+
+    return BottomSheetMenuItem(
+      onPressed: () {
+        showDialog(
+            context: context, builder: (context) => UserProfilePicEditor(u));
+      },
+      icon: const Icon(FeatherIcons.camera),
+      title: Text("edit_profile_picture".i18n),
+    );
+  }
+}
+
+// ignore: must_be_immutable
+class UserProfilePicEditor extends StatefulWidget {
+  late User u;
+
+  UserProfilePicEditor(this.u, {Key? key}) : super(key: key);
+
+  @override
+  State<UserProfilePicEditor> createState() => _UserProfilePicEditorState();
+}
+
+class _UserProfilePicEditorState extends State<UserProfilePicEditor> {
+  late final UserProvider user;
+
+  final cropKey = GlobalKey<CropState>();
+  File? _file;
+  File? _sample;
+  File? _lastCropped;
+
+  File? image;
+  Future pickImage() async {
+    try {
+      final image = await ImagePicker().pickImage(source: ImageSource.gallery);
+      if (image == null) return;
+      File imageFile = File(image.path);
+
+      final sample = await ImageCrop.sampleImage(
+        file: imageFile,
+        preferredSize: context.size!.longestSide.ceil(),
+      );
+
+      _sample?.delete();
+      _file?.delete();
+
+      setState(() {
+        _sample = sample;
+        _file = imageFile;
+      });
+    } on PlatformException catch (e) {
+      log('Failed to pick image: $e');
+    }
+  }
+
+  Widget cropImageWidget() {
+    return SizedBox(
+      height: 300,
+      child: Crop.file(
+        _sample!,
+        key: cropKey,
+        aspectRatio: 1.0,
+      ),
+    );
+  }
+
+  Widget openImageWidget() {
+    return InkWell(
+      customBorder: RoundedRectangleBorder(
+        borderRadius: BorderRadius.circular(14.0),
+      ),
+      onTap: () => pickImage(),
+      child: Container(
+        decoration: BoxDecoration(
+          border: Border.all(color: Colors.grey),
+          borderRadius: BorderRadius.circular(14.0),
+        ),
+        width: double.infinity,
+        padding: const EdgeInsets.symmetric(vertical: 32.0, horizontal: 8.0),
+        child: Column(
+          children: [
+            Text(
+              "click_here".i18n,
+              style: const TextStyle(
+                fontSize: 22.0,
+                fontWeight: FontWeight.w600,
+              ),
+            ),
+            Text(
+              "select_profile_picture".i18n,
+              style: const TextStyle(
+                fontSize: 14.0,
+                fontWeight: FontWeight.w500,
+              ),
+            )
+          ],
+        ),
+      ),
+    );
+  }
+
+  Future<void> _cropImage() async {
+    final scale = cropKey.currentState!.scale;
+    final area = cropKey.currentState!.area;
+    if (area == null || _file == null) {
+      return;
+    }
+
+    final sample = await ImageCrop.sampleImage(
+      file: _file!,
+      preferredSize: (2000 / scale).round(),
+    );
+
+    final file = await ImageCrop.cropImage(
+      file: sample,
+      area: area,
+    );
+
+    sample.delete();
+
+    _lastCropped?.delete();
+    _lastCropped = file;
+
+    List<int> imageBytes = await _lastCropped!.readAsBytes();
+    String base64Image = base64Encode(imageBytes);
+    widget.u.picture = base64Image;
+    Provider.of<DatabaseProvider>(context, listen: false)
+        .store
+        .storeUser(widget.u);
+    Provider.of<UserProvider>(context, listen: false).refresh();
+
+    debugPrint('$file');
+  }
+
+  @override
+  void initState() {
+    super.initState();
+    user = Provider.of<UserProvider>(context, listen: false);
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    _file?.delete();
+    _sample?.delete();
+    _lastCropped?.delete();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return AlertDialog(
+      shape: const RoundedRectangleBorder(
+          borderRadius: BorderRadius.all(Radius.circular(14.0))),
+      contentPadding: const EdgeInsets.only(top: 10.0),
+      title: Text("edit_profile_picture".i18n),
+      content: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          Padding(
+            padding:
+                const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+            child: _sample == null ? openImageWidget() : cropImageWidget(),
+          ),
+          if (widget.u.picture != "")
+            TextButton(
+              child: Text(
+                "remove_profile_picture".i18n,
+                style: const TextStyle(
+                    fontWeight: FontWeight.w500, color: Colors.red),
+              ),
+              onPressed: () {
+                widget.u.picture = "";
+                Provider.of<DatabaseProvider>(context, listen: false)
+                    .store
+                    .storeUser(widget.u);
+                Provider.of<UserProvider>(context, listen: false).refresh();
+                Navigator.of(context).pop(true);
+              },
+            ),
+        ],
+      ),
+      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: () async {
+            await _cropImage();
+            Navigator.of(context).pop(true);
+          },
+        ),
+      ],
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/share_theme.dart b/refilc_premium/lib/ui/mobile/settings/share_theme.dart
similarity index 92%
rename from filcnaplo_premium/lib/ui/mobile/settings/share_theme.dart
rename to refilc_premium/lib/ui/mobile/settings/share_theme.dart
index cbbe917..987ad7b 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/share_theme.dart
+++ b/refilc_premium/lib/ui/mobile/settings/share_theme.dart
@@ -1,4 +1,4 @@
-import 'package:filcnaplo/models/settings.dart';
+import 'package:refilc/models/settings.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/theme.dart b/refilc_premium/lib/ui/mobile/settings/theme.dart
similarity index 95%
rename from filcnaplo_premium/lib/ui/mobile/settings/theme.dart
rename to refilc_premium/lib/ui/mobile/settings/theme.dart
index 33cff7a..cf39d9c 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/theme.dart
+++ b/refilc_premium/lib/ui/mobile/settings/theme.dart
@@ -1,896 +1,896 @@
-import 'package:filcnaplo/models/settings.dart';
-import 'package:filcnaplo/models/shared_theme.dart';
-import 'package:filcnaplo/theme/colors/accent.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo/theme/observer.dart';
-import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
-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/filter_bar.dart';
-import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
-import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_tile.dart';
-import 'package:filcnaplo_premium/models/premium_scopes.dart';
-import 'package:filcnaplo_premium/providers/premium_provider.dart';
-import 'package:filcnaplo_premium/providers/share_provider.dart';
-import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/colorpicker.dart';
-import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'theme.i18n.dart';
-import 'package:share_plus/share_plus.dart';
-
-class PremiumCustomAccentColorSetting extends StatefulWidget {
-  const PremiumCustomAccentColorSetting({Key? key}) : super(key: key);
-
-  @override
-  State<PremiumCustomAccentColorSetting> createState() =>
-      _PremiumCustomAccentColorSettingState();
-}
-
-enum CustomColorMode {
-  theme,
-  saved,
-  accent,
-  background,
-  highlight,
-  enterId,
-}
-
-class _PremiumCustomAccentColorSettingState
-    extends State<PremiumCustomAccentColorSetting>
-    with TickerProviderStateMixin {
-  late final SettingsProvider settings;
-  late final ShareProvider shareProvider;
-  bool colorSelection = false;
-  bool customColorMenu = false;
-  CustomColorMode colorMode = CustomColorMode.theme;
-  final customColorInput = TextEditingController();
-  final unknownColor = Colors.black;
-
-  late TabController _testTabController;
-  late TabController _colorsTabController;
-  late AnimationController _openAnimController;
-
-  late final Animation<double> backgroundAnimation =
-      Tween<double>(begin: 0, end: 1).animate(
-    CurvedAnimation(
-      parent: _openAnimController,
-      curve: const Interval(0.2, 1.0, curve: Curves.easeInOut),
-    ),
-  );
-
-  late final Animation<double> fullPageAnimation =
-      Tween<double>(begin: 0, end: 1).animate(
-    CurvedAnimation(
-      parent: _openAnimController,
-      curve: const Interval(0.0, 0.6, curve: Curves.easeInOut),
-    ),
-  );
-
-  late final Animation<double> backContainerAnimation =
-      Tween<double>(begin: 100, end: 0).animate(
-    CurvedAnimation(
-      parent: _openAnimController,
-      curve: const Interval(0.0, 0.9, curve: Curves.easeInOut),
-    ),
-  );
-
-  late final Animation<double> backContentAnimation =
-      Tween<double>(begin: 100, end: 0).animate(
-    CurvedAnimation(
-      parent: _openAnimController,
-      curve: const Interval(0.2, 1.0, curve: Curves.easeInOut),
-    ),
-  );
-
-  late final Animation<double> backContentScaleAnimation =
-      Tween<double>(begin: 0.8, end: 0.9).animate(
-    CurvedAnimation(
-      parent: _openAnimController,
-      curve: const Interval(0.45, 1.0, curve: Curves.easeInOut),
-    ),
-  );
-
-  late final Animation<double> pickerContainerAnimation =
-      Tween<double>(begin: 0, end: 1).animate(
-    CurvedAnimation(
-      parent: _openAnimController,
-      curve: const Interval(0.25, 0.8, curve: Curves.easeInOut),
-    ),
-  );
-
-  @override
-  void initState() {
-    super.initState();
-    _colorsTabController = TabController(length: 5, vsync: this);
-    _testTabController = TabController(length: 4, vsync: this);
-    settings = Provider.of<SettingsProvider>(context, listen: false);
-    shareProvider = Provider.of<ShareProvider>(context, listen: false);
-
-    _openAnimController = AnimationController(
-        vsync: this, duration: const Duration(milliseconds: 750));
-    _openAnimController.forward();
-  }
-
-  @override
-  void dispose() {
-    _openAnimController.dispose();
-    super.dispose();
-  }
-
-  void setTheme(ThemeMode mode, bool store) async {
-    await settings.update(theme: mode, store: store);
-    Provider.of<ThemeModeObserver>(context, listen: false)
-        .changeTheme(mode, updateNavbarColor: false);
-  }
-
-  dynamic getCustomColor() {
-    switch (colorMode) {
-      case CustomColorMode.theme:
-        return accentColorMap[settings.accentColor];
-      case CustomColorMode.saved:
-        return [
-          settings.customBackgroundColor,
-          settings.customHighlightColor,
-          settings.customAccentColor
-        ];
-      case CustomColorMode.background:
-        return settings.customBackgroundColor;
-      case CustomColorMode.highlight:
-        return settings.customHighlightColor;
-      case CustomColorMode.accent:
-        return settings.customAccentColor;
-      case CustomColorMode.enterId:
-        // do nothing here lol
-        break;
-    }
-  }
-
-  void updateCustomColor(dynamic v, bool store,
-      {Color? accent, Color? background, Color? panels}) {
-    if (colorMode != CustomColorMode.theme) {
-      settings.update(accentColor: AccentColor.custom, store: store);
-    }
-    switch (colorMode) {
-      case CustomColorMode.theme:
-        settings.update(
-            accentColor: accentColorMap.keys.firstWhere(
-                (element) => accentColorMap[element] == v,
-                orElse: () => AccentColor.filc),
-            store: store);
-        settings.update(
-            customBackgroundColor: AppColors.of(context).background,
-            store: store);
-        settings.update(
-            customHighlightColor: AppColors.of(context).highlight,
-            store: store);
-        settings.update(customAccentColor: v, store: store);
-        break;
-      case CustomColorMode.saved:
-        settings.update(customBackgroundColor: v[0], store: store);
-        settings.update(customHighlightColor: v[1], store: store);
-        settings.update(customAccentColor: v[3], store: store);
-        break;
-      case CustomColorMode.background:
-        settings.update(customBackgroundColor: v, store: store);
-        break;
-      case CustomColorMode.highlight:
-        settings.update(customHighlightColor: v, store: store);
-        break;
-      case CustomColorMode.accent:
-        settings.update(customAccentColor: v, store: store);
-        break;
-      case CustomColorMode.enterId:
-        settings.update(customBackgroundColor: background, store: store);
-        settings.update(customHighlightColor: panels, store: store);
-        settings.update(customAccentColor: accent, store: store);
-        break;
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    bool hasAccess = Provider.of<PremiumProvider>(context)
-        .hasScope(PremiumScopes.customColors);
-    bool isBackgroundDifferent = Theme.of(context).colorScheme.background !=
-        AppColors.of(context).background;
-
-    ThemeMode currentTheme = Theme.of(context).brightness == Brightness.light
-        ? ThemeMode.light
-        : ThemeMode.dark;
-
-    return WillPopScope(
-      onWillPop: () async {
-        Provider.of<ThemeModeObserver>(context, listen: false)
-            .changeTheme(settings.theme, updateNavbarColor: true);
-        return true;
-      },
-      child: AnimatedBuilder(
-        animation: _openAnimController,
-        builder: (context, child) {
-          final backgroundGradientBottomColor = isBackgroundDifferent
-              ? Theme.of(context).colorScheme.background
-              : HSVColor.fromColor(Theme.of(context).colorScheme.background)
-                  .withValue(currentTheme == ThemeMode.dark
-                      ? 0.1 * _openAnimController.value
-                      : 1.0 - (0.1 * _openAnimController.value))
-                  .withAlpha(1.0)
-                  .toColor();
-
-          SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
-            systemNavigationBarColor: backgroundGradientBottomColor,
-          ));
-
-          return Container(
-            decoration: BoxDecoration(
-              gradient: LinearGradient(
-                begin: Alignment.topCenter,
-                end: Alignment.bottomCenter,
-                stops: const [0.0, 0.75],
-                colors: isBackgroundDifferent
-                    ? [
-                        Theme.of(context).colorScheme.background.withOpacity(1 -
-                            ((currentTheme == ThemeMode.dark ? 0.65 : 0.45) *
-                                backgroundAnimation.value)),
-                        backgroundGradientBottomColor,
-                      ]
-                    : [
-                        backgroundGradientBottomColor,
-                        backgroundGradientBottomColor
-                      ],
-              ),
-            ),
-            child: Opacity(
-              opacity: fullPageAnimation.value,
-              child: Scaffold(
-                backgroundColor: Colors.transparent,
-                appBar: AppBar(
-                  surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-                  leading: BackButton(color: AppColors.of(context).text),
-                  actions: [
-                    Padding(
-                      padding: const EdgeInsets.only(right: 10.0),
-                      child: IconButton(
-                        focusColor: Colors.transparent,
-                        highlightColor: Colors.transparent,
-                        splashColor: Colors.transparent,
-                        onPressed: () async {
-                          // ScaffoldMessenger.of(context).showSnackBar(
-                          //   const SnackBar(
-                          //     duration: Duration(milliseconds: 1000),
-                          //     content: Text(
-                          //       "Hamarosan...",
-                          //     ),
-                          //   ),
-                          // );
-                          SharedTheme theme =
-                              await shareProvider.shareCurrentTheme(context);
-                          Share.share(theme.id,
-                              subject: 'reFilc Téma / reFilc Theme');
-                        },
-                        icon: const Icon(
-                          FeatherIcons.share2,
-                          size: 22.0,
-                        ),
-                      ),
-                    ),
-                  ],
-                  title: Text(
-                    "theme_prev".i18n,
-                    style: TextStyle(color: AppColors.of(context).text),
-                  ),
-                  backgroundColor: Colors.transparent,
-                  elevation: 0,
-                ),
-                body: Stack(
-                  children: [
-                    Opacity(
-                      opacity: 1 - backContainerAnimation.value * (1 / 100),
-                      child: Transform.translate(
-                        offset: Offset(0, backContainerAnimation.value),
-                        child: Container(
-                          height: double.infinity,
-                          width: double.infinity,
-                          decoration: BoxDecoration(
-                            borderRadius: BorderRadius.circular(24),
-                            gradient: LinearGradient(
-                                begin: Alignment.topCenter,
-                                end: Alignment.bottomCenter,
-                                stops: const [
-                                  0.35,
-                                  0.75
-                                ],
-                                colors: [
-                                  Theme.of(context).colorScheme.background,
-                                  isBackgroundDifferent
-                                      ? HSVColor.fromColor(Theme.of(context)
-                                              .colorScheme
-                                              .background)
-                                          .withSaturation((HSVColor.fromColor(
-                                                          Theme.of(context)
-                                                              .colorScheme
-                                                              .background)
-                                                      .saturation -
-                                                  0.15)
-                                              .clamp(0.0, 1.0))
-                                          .toColor()
-                                      : backgroundGradientBottomColor,
-                                ]),
-                          ),
-                          margin: const EdgeInsets.symmetric(
-                              vertical: 30, horizontal: 20),
-                        ),
-                      ),
-                    ),
-                    Padding(
-                      padding: const EdgeInsets.only(top: 8.0),
-                      child: SizedBox(
-                        width: double.infinity,
-                        child: Padding(
-                          padding: const EdgeInsets.only(top: 24.0),
-                          child: Opacity(
-                            opacity: 1 - backContentAnimation.value * (1 / 100),
-                            child: SingleChildScrollView(
-                              physics: const BouncingScrollPhysics(),
-                              child: Transform.translate(
-                                offset:
-                                    Offset(0, -24 + backContentAnimation.value),
-                                child: Transform.scale(
-                                  scale: backContentScaleAnimation.value,
-                                  child: Column(
-                                    children: [
-                                      Padding(
-                                        padding: const EdgeInsets.symmetric(
-                                            horizontal: 32.0, vertical: 6.0),
-                                        child: FilterBar(
-                                          items: const [
-                                            Tab(text: "All"),
-                                            Tab(text: "Grades"),
-                                            Tab(text: "Messages"),
-                                            Tab(text: "Absences"),
-                                          ],
-                                          controller: _testTabController,
-                                          padding: EdgeInsets.zero,
-                                          censored: true,
-                                          disableFading: true,
-                                        ),
-                                      ),
-                                      Padding(
-                                        padding: const EdgeInsets.symmetric(
-                                            horizontal: 18.0, vertical: 8.0),
-                                        child: NewGradesSurprise(
-                                          [
-                                            Grade.fromJson(
-                                              {
-                                                "Uid": "0,Ertekeles",
-                                                "RogzitesDatuma":
-                                                    "2022-01-01T23:00:00Z",
-                                                "KeszitesDatuma":
-                                                    "2022-01-01T23:00:00Z",
-                                                "LattamozasDatuma": null,
-                                                "Tantargy": {
-                                                  "Uid": "0",
-                                                  "Nev": "reFilc szakirodalom",
-                                                  "Kategoria": {
-                                                    "Uid": "0,_",
-                                                    "Nev": "_",
-                                                    "Leiras": "Nem mondom meg"
-                                                  },
-                                                  "SortIndex": 2
-                                                },
-                                                "Tema":
-                                                    "Kupak csomag vásárlás vizsga",
-                                                "Tipus": {
-                                                  "Uid": "0,_",
-                                                  "Nev": "_",
-                                                  "Leiras":
-                                                      "Évközi jegy/értékelés",
-                                                },
-                                                "Mod": {
-                                                  "Uid": "0,_",
-                                                  "Nev": "_",
-                                                  "Leiras": "_ feladat",
-                                                },
-                                                "ErtekFajta": {
-                                                  "Uid": "1,Osztalyzat",
-                                                  "Nev": "Osztalyzat",
-                                                  "Leiras":
-                                                      "Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték"
-                                                },
-                                                "ErtekeloTanarNeve": "Premium",
-                                                "Jelleg": "Ertekeles",
-                                                "SzamErtek": 5,
-                                                "SzovegesErtek": "Jeles(5)",
-                                                "SulySzazalekErteke": 100,
-                                                "SzovegesErtekelesRovidNev":
-                                                    null,
-                                                "OsztalyCsoport": {"Uid": "0"},
-                                                "SortIndex": 2
-                                              },
-                                            ),
-                                          ],
-                                          censored: true,
-                                        ),
-                                      ),
-                                      Padding(
-                                        padding: const EdgeInsets.symmetric(
-                                            horizontal: 24.0, vertical: 6.0),
-                                        child: Panel(
-                                          child: GradeTile(
-                                            Grade.fromJson(
-                                              {
-                                                "Uid": "0,Ertekeles",
-                                                "RogzitesDatuma":
-                                                    "2022-01-01T23:00:00Z",
-                                                "KeszitesDatuma":
-                                                    "2022-01-01T23:00:00Z",
-                                                "LattamozasDatuma": null,
-                                                "Tantargy": {
-                                                  "Uid": "0",
-                                                  "Nev": "reFilc szakosztály",
-                                                  "Kategoria": {
-                                                    "Uid": "0,_",
-                                                    "Nev": "_",
-                                                    "Leiras": "Nem mondom meg"
-                                                  },
-                                                  "SortIndex": 2
-                                                },
-                                                "Tema":
-                                                    "Kupak csomag vásárlás vizsga",
-                                                "Tipus": {
-                                                  "Uid": "0,_",
-                                                  "Nev": "_",
-                                                  "Leiras":
-                                                      "Évközi jegy/értékelés",
-                                                },
-                                                "Mod": {
-                                                  "Uid": "0,_",
-                                                  "Nev": "_",
-                                                  "Leiras": "_ feladat",
-                                                },
-                                                "ErtekFajta": {
-                                                  "Uid": "1,Osztalyzat",
-                                                  "Nev": "Osztalyzat",
-                                                  "Leiras":
-                                                      "Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték"
-                                                },
-                                                "ErtekeloTanarNeve": "Premium",
-                                                "Jelleg": "Ertekeles",
-                                                "SzamErtek": 5,
-                                                "SzovegesErtek": "Jeles(5)",
-                                                "SulySzazalekErteke": 100,
-                                                "SzovegesErtekelesRovidNev":
-                                                    null,
-                                                "OsztalyCsoport": {"Uid": "0"},
-                                                "SortIndex": 2
-                                              },
-                                            ),
-                                            padding: EdgeInsets.zero,
-                                            censored: true,
-                                          ),
-                                        ),
-                                      ),
-                                      Padding(
-                                        padding: const EdgeInsets.symmetric(
-                                            horizontal: 24.0, vertical: 6.0),
-                                        child: Panel(
-                                          child: HomeworkTile(
-                                            Homework.fromJson(
-                                              {
-                                                "Uid": "0",
-                                                "Tantargy": {
-                                                  "Uid": "0",
-                                                  "Nev":
-                                                      "reFilc premium előnyei",
-                                                  "Kategoria": {
-                                                    "Uid": "0,_",
-                                                    "Nev": "_",
-                                                    "Leiras":
-                                                        "reFilc premium előnyei",
-                                                  },
-                                                  "SortIndex": 0
-                                                },
-                                                "TantargyNeve":
-                                                    "reFilc premium előnyei",
-                                                "RogzitoTanarNeve":
-                                                    "Kupak János",
-                                                "Szoveg":
-                                                    "45 perc filctollal való rajzolás",
-                                                "FeladasDatuma":
-                                                    "2022-01-01T23:00:00Z",
-                                                "HataridoDatuma":
-                                                    "2022-01-01T23:00:00Z",
-                                                "RogzitesIdopontja":
-                                                    "2022-01-01T23:00:00Z",
-                                                "IsTanarRogzitette": true,
-                                                "IsTanuloHaziFeladatEnabled":
-                                                    false,
-                                                "IsMegoldva": false,
-                                                "IsBeadhato": false,
-                                                "OsztalyCsoport": {"Uid": "0"},
-                                                "IsCsatolasEngedelyezes": false
-                                              },
-                                            ),
-                                            padding: EdgeInsets.zero,
-                                            censored: true,
-                                          ),
-                                        ),
-                                      ),
-                                      Padding(
-                                        padding: const EdgeInsets.symmetric(
-                                            horizontal: 24.0, vertical: 6.0),
-                                        child: Panel(
-                                          child: MessageTile(
-                                            Message.fromJson(
-                                              {
-                                                "azonosito": 0,
-                                                "isElolvasva": true,
-                                                "isToroltElem": false,
-                                                "tipus": {
-                                                  "azonosito": 1,
-                                                  "kod": "BEERKEZETT",
-                                                  "rovidNev":
-                                                      "Beérkezett üzenet",
-                                                  "nev": "Beérkezett üzenet",
-                                                  "leiras": "Beérkezett üzenet"
-                                                },
-                                                "uzenet": {
-                                                  "azonosito": 0,
-                                                  "kuldesDatum":
-                                                      "2022-01-01T23:00:00",
-                                                  "feladoNev": "reFilc",
-                                                  "feladoTitulus":
-                                                      "Nagyon magas szintű személy",
-                                                  "szoveg":
-                                                      "<p>Kedves Felhasználó!</p><p><br></p><p>A prémium vásárlásakor kapott filctollal 90%-al több esély van jó jegyek szerzésére.</p>",
-                                                  "targy":
-                                                      "Filctoll használati útmutató",
-                                                  "statusz": {
-                                                    "azonosito": 2,
-                                                    "kod": "KIKULDVE",
-                                                    "rovidNev": "Kiküldve",
-                                                    "nev": "Kiküldve",
-                                                    "leiras": "Kiküldve"
-                                                  },
-                                                  "cimzettLista": [
-                                                    {
-                                                      "azonosito": 0,
-                                                      "kretaAzonosito": 0,
-                                                      "nev": "Tinta Józsi",
-                                                      "tipus": {
-                                                        "azonosito": 0,
-                                                        "kod": "TANULO",
-                                                        "rovidNev": "Tanuló",
-                                                        "nev": "Tanuló",
-                                                        "leiras": "Tanuló"
-                                                      }
-                                                    },
-                                                  ],
-                                                  "csatolmanyok": [
-                                                    {
-                                                      "azonosito": 0,
-                                                      "fajlNev": "Filctoll.doc"
-                                                    }
-                                                  ]
-                                                }
-                                              },
-                                            ),
-                                            censored: true,
-                                          ),
-                                        ),
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              ),
-                            ),
-                          ),
-                        ),
-                      ),
-                    ),
-                    Align(
-                      alignment: Alignment.bottomCenter,
-                      child: Wrap(
-                        children: [
-                          Opacity(
-                            opacity: pickerContainerAnimation.value,
-                            child: SizedBox(
-                              width: double.infinity,
-                              child: Container(
-                                padding: const EdgeInsets.only(bottom: 12.0),
-                                decoration: BoxDecoration(
-                                  boxShadow: [
-                                    BoxShadow(
-                                      color: backgroundGradientBottomColor,
-                                      offset: const Offset(0, -8),
-                                      blurRadius: 16,
-                                      spreadRadius: 18,
-                                    ),
-                                  ],
-                                  gradient: LinearGradient(
-                                      begin: Alignment.topCenter,
-                                      end: Alignment.bottomCenter,
-                                      stops: const [
-                                        0.0,
-                                        0.175
-                                      ],
-                                      colors: [
-                                        backgroundGradientBottomColor,
-                                        backgroundGradientBottomColor,
-                                      ]),
-                                ),
-                                child: Column(
-                                  children: [
-                                    Padding(
-                                      padding: const EdgeInsets.symmetric(
-                                          horizontal: 8.0),
-                                      child: FilterBar(
-                                        items: [
-                                          ColorTab(
-                                              color: accentColorMap[
-                                                      settings.accentColor] ??
-                                                  unknownColor,
-                                              tab: Tab(
-                                                  text: "colorpicker_presets"
-                                                      .i18n)),
-                                          ColorTab(
-                                              color: unknownColor,
-                                              tab: Tab(text: "enter_id".i18n)),
-                                          /*ColorTab(
-                                              color:
-                                                  settings.customAccentColor ??
-                                                      unknownColor,
-                                              tab: Tab(
-                                                  text: "colorpicker_saved"
-                                                      .i18n)),*/
-                                          ColorTab(
-                                              unlocked: hasAccess,
-                                              color: settings
-                                                      .customBackgroundColor ??
-                                                  unknownColor,
-                                              tab: Tab(
-                                                  text: "colorpicker_background"
-                                                      .i18n)),
-                                          ColorTab(
-                                              unlocked: hasAccess,
-                                              color: settings
-                                                      .customHighlightColor ??
-                                                  unknownColor,
-                                              tab: Tab(
-                                                  text: "colorpicker_panels"
-                                                      .i18n)),
-                                          ColorTab(
-                                              unlocked: hasAccess,
-                                              color:
-                                                  settings.customAccentColor ??
-                                                      unknownColor,
-                                              tab: Tab(
-                                                  text: "colorpicker_accent"
-                                                      .i18n)),
-                                        ],
-                                        onTap: (index) {
-                                          if (!hasAccess) {
-                                            index = 0;
-                                            _colorsTabController.animateTo(0,
-                                                duration: Duration.zero);
-
-                                            PremiumLockedFeatureUpsell.show(
-                                                context: context,
-                                                feature: PremiumFeature
-                                                    .customcolors);
-                                          }
-
-                                          switch (index) {
-                                            case 0:
-                                              setState(() {
-                                                colorMode =
-                                                    CustomColorMode.theme;
-                                              });
-                                              break;
-                                            case 1:
-                                              setState(() {
-                                                colorMode =
-                                                    CustomColorMode.enterId;
-                                              });
-                                              break;
-                                            /*case 1:
-                                              setState(() {
-                                                colorMode =
-                                                    CustomColorMode.saved;
-                                              });
-                                              break;*/
-                                            case 2:
-                                              setState(() {
-                                                colorMode =
-                                                    CustomColorMode.background;
-                                              });
-                                              break;
-                                            case 3:
-                                              setState(() {
-                                                colorMode =
-                                                    CustomColorMode.highlight;
-                                              });
-                                              break;
-                                            case 4:
-                                              setState(() {
-                                                colorMode =
-                                                    CustomColorMode.accent;
-                                              });
-                                              break;
-                                          }
-                                        },
-                                        controller: _colorsTabController,
-                                        padding: EdgeInsets.zero,
-                                      ),
-                                    ),
-                                    Padding(
-                                      padding: const EdgeInsets.symmetric(
-                                          horizontal: 12.0),
-                                      child: SafeArea(
-                                        child: FilcColorPicker(
-                                          colorMode: colorMode,
-                                          pickerColor: colorMode ==
-                                                  CustomColorMode.accent
-                                              ? settings.customAccentColor ??
-                                                  unknownColor
-                                              : colorMode ==
-                                                      CustomColorMode.background
-                                                  ? settings
-                                                          .customBackgroundColor ??
-                                                      unknownColor
-                                                  : colorMode ==
-                                                          CustomColorMode.theme
-                                                      ? (accentColorMap[settings
-                                                              .accentColor] ??
-                                                          AppColors.of(context)
-                                                              .text) // idk what else
-                                                      : settings
-                                                              .customHighlightColor ??
-                                                          unknownColor,
-                                          onColorChanged: (c) {
-                                            setState(() {
-                                              updateCustomColor(c, false);
-                                            });
-                                            setTheme(settings.theme, false);
-                                          },
-                                          onColorChangeEnd: (c, {adaptive}) {
-                                            setState(() {
-                                              if (adaptive == true) {
-                                                settings.update(
-                                                    accentColor:
-                                                        AccentColor.adaptive);
-                                                settings.update(
-                                                    customBackgroundColor:
-                                                        AppColors.of(context)
-                                                            .background,
-                                                    store: true);
-                                                settings.update(
-                                                    customHighlightColor:
-                                                        AppColors.of(context)
-                                                            .highlight,
-                                                    store: true);
-                                              } else {
-                                                updateCustomColor(c, true);
-                                              }
-                                            });
-                                            setTheme(settings.theme, true);
-                                          },
-                                          onThemeIdProvided: (theme) {
-                                            setState(() {
-                                              updateCustomColor(
-                                                null,
-                                                true,
-                                                accent: theme.accentColor,
-                                                background:
-                                                    theme.backgroundColor,
-                                                panels: theme.panelsColor,
-                                              );
-                                            });
-                                            setTheme(settings.theme, true);
-                                          },
-                                        ),
-                                      ),
-                                    ),
-                                  ],
-                                ),
-                              ),
-                            ),
-                          ),
-                        ],
-                      ),
-                    ),
-                  ],
-                ),
-              ),
-            ),
-          );
-        },
-      ),
-    );
-  }
-}
-
-class ColorTab extends StatelessWidget {
-  const ColorTab(
-      {Key? key, required this.tab, required this.color, this.unlocked = true})
-      : super(key: key);
-
-  final Tab tab;
-  final Color color;
-  final bool unlocked;
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        Transform.translate(
-          offset: const Offset(-3, 1),
-          child: unlocked
-              ? Container(
-                  width: 15,
-                  height: 15,
-                  decoration: BoxDecoration(
-                    shape: BoxShape.circle,
-                    color: color,
-                    border: Border.all(color: Colors.black, width: 2.0),
-                  ),
-                )
-              : const Padding(
-                  padding: EdgeInsets.symmetric(horizontal: 2),
-                  child: Icon(Icons.lock,
-                      color: Color.fromARGB(255, 82, 82, 82), size: 18),
-                ),
-        ),
-        tab
-      ],
-    );
-  }
-}
-
-class PremiumColorPickerItem extends StatelessWidget {
-  const PremiumColorPickerItem(
-      {Key? key, required this.label, this.onTap, required this.color})
-      : super(key: key);
-
-  final String label;
-  final void Function()? onTap;
-  final Color color;
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      type: MaterialType.transparency,
-      child: InkWell(
-        child: Padding(
-          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
-          child: Row(
-            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-            children: [
-              Expanded(
-                child: Text(
-                  label,
-                  style: TextStyle(
-                      color: AppColors.of(context).text,
-                      fontWeight: FontWeight.w500),
-                ),
-              ),
-              Container(
-                width: 30,
-                height: 30,
-                decoration: BoxDecoration(
-                    color: color, shape: BoxShape.circle, border: Border.all()),
-              ),
-            ],
-          ),
-        ),
-        onTap: onTap,
-      ),
-    );
-  }
-}
+import 'package:refilc/models/settings.dart';
+import 'package:refilc/models/shared_theme.dart';
+import 'package:refilc/theme/colors/accent.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc/theme/observer.dart';
+import 'package:refilc/ui/widgets/grade/grade_tile.dart';
+import 'package:refilc/ui/widgets/message/message_tile.dart';
+import 'package:refilc_kreta_api/models/grade.dart';
+import 'package:refilc_kreta_api/models/homework.dart';
+import 'package:refilc_kreta_api/models/message.dart';
+import 'package:refilc_mobile_ui/common/filter_bar.dart';
+import 'package:refilc_mobile_ui/common/panel/panel.dart';
+import 'package:refilc_mobile_ui/common/widgets/grade/new_grades.dart';
+import 'package:refilc_mobile_ui/common/widgets/homework/homework_tile.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/providers/share_provider.dart';
+import 'package:refilc_premium/ui/mobile/flutter_colorpicker/colorpicker.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'theme.i18n.dart';
+import 'package:share_plus/share_plus.dart';
+
+class PremiumCustomAccentColorSetting extends StatefulWidget {
+  const PremiumCustomAccentColorSetting({Key? key}) : super(key: key);
+
+  @override
+  State<PremiumCustomAccentColorSetting> createState() =>
+      _PremiumCustomAccentColorSettingState();
+}
+
+enum CustomColorMode {
+  theme,
+  saved,
+  accent,
+  background,
+  highlight,
+  enterId,
+}
+
+class _PremiumCustomAccentColorSettingState
+    extends State<PremiumCustomAccentColorSetting>
+    with TickerProviderStateMixin {
+  late final SettingsProvider settings;
+  late final ShareProvider shareProvider;
+  bool colorSelection = false;
+  bool customColorMenu = false;
+  CustomColorMode colorMode = CustomColorMode.theme;
+  final customColorInput = TextEditingController();
+  final unknownColor = Colors.black;
+
+  late TabController _testTabController;
+  late TabController _colorsTabController;
+  late AnimationController _openAnimController;
+
+  late final Animation<double> backgroundAnimation =
+      Tween<double>(begin: 0, end: 1).animate(
+    CurvedAnimation(
+      parent: _openAnimController,
+      curve: const Interval(0.2, 1.0, curve: Curves.easeInOut),
+    ),
+  );
+
+  late final Animation<double> fullPageAnimation =
+      Tween<double>(begin: 0, end: 1).animate(
+    CurvedAnimation(
+      parent: _openAnimController,
+      curve: const Interval(0.0, 0.6, curve: Curves.easeInOut),
+    ),
+  );
+
+  late final Animation<double> backContainerAnimation =
+      Tween<double>(begin: 100, end: 0).animate(
+    CurvedAnimation(
+      parent: _openAnimController,
+      curve: const Interval(0.0, 0.9, curve: Curves.easeInOut),
+    ),
+  );
+
+  late final Animation<double> backContentAnimation =
+      Tween<double>(begin: 100, end: 0).animate(
+    CurvedAnimation(
+      parent: _openAnimController,
+      curve: const Interval(0.2, 1.0, curve: Curves.easeInOut),
+    ),
+  );
+
+  late final Animation<double> backContentScaleAnimation =
+      Tween<double>(begin: 0.8, end: 0.9).animate(
+    CurvedAnimation(
+      parent: _openAnimController,
+      curve: const Interval(0.45, 1.0, curve: Curves.easeInOut),
+    ),
+  );
+
+  late final Animation<double> pickerContainerAnimation =
+      Tween<double>(begin: 0, end: 1).animate(
+    CurvedAnimation(
+      parent: _openAnimController,
+      curve: const Interval(0.25, 0.8, curve: Curves.easeInOut),
+    ),
+  );
+
+  @override
+  void initState() {
+    super.initState();
+    _colorsTabController = TabController(length: 5, vsync: this);
+    _testTabController = TabController(length: 4, vsync: this);
+    settings = Provider.of<SettingsProvider>(context, listen: false);
+    shareProvider = Provider.of<ShareProvider>(context, listen: false);
+
+    _openAnimController = AnimationController(
+        vsync: this, duration: const Duration(milliseconds: 750));
+    _openAnimController.forward();
+  }
+
+  @override
+  void dispose() {
+    _openAnimController.dispose();
+    super.dispose();
+  }
+
+  void setTheme(ThemeMode mode, bool store) async {
+    await settings.update(theme: mode, store: store);
+    Provider.of<ThemeModeObserver>(context, listen: false)
+        .changeTheme(mode, updateNavbarColor: false);
+  }
+
+  dynamic getCustomColor() {
+    switch (colorMode) {
+      case CustomColorMode.theme:
+        return accentColorMap[settings.accentColor];
+      case CustomColorMode.saved:
+        return [
+          settings.customBackgroundColor,
+          settings.customHighlightColor,
+          settings.customAccentColor
+        ];
+      case CustomColorMode.background:
+        return settings.customBackgroundColor;
+      case CustomColorMode.highlight:
+        return settings.customHighlightColor;
+      case CustomColorMode.accent:
+        return settings.customAccentColor;
+      case CustomColorMode.enterId:
+        // do nothing here lol
+        break;
+    }
+  }
+
+  void updateCustomColor(dynamic v, bool store,
+      {Color? accent, Color? background, Color? panels}) {
+    if (colorMode != CustomColorMode.theme) {
+      settings.update(accentColor: AccentColor.custom, store: store);
+    }
+    switch (colorMode) {
+      case CustomColorMode.theme:
+        settings.update(
+            accentColor: accentColorMap.keys.firstWhere(
+                (element) => accentColorMap[element] == v,
+                orElse: () => AccentColor.filc),
+            store: store);
+        settings.update(
+            customBackgroundColor: AppColors.of(context).background,
+            store: store);
+        settings.update(
+            customHighlightColor: AppColors.of(context).highlight,
+            store: store);
+        settings.update(customAccentColor: v, store: store);
+        break;
+      case CustomColorMode.saved:
+        settings.update(customBackgroundColor: v[0], store: store);
+        settings.update(customHighlightColor: v[1], store: store);
+        settings.update(customAccentColor: v[3], store: store);
+        break;
+      case CustomColorMode.background:
+        settings.update(customBackgroundColor: v, store: store);
+        break;
+      case CustomColorMode.highlight:
+        settings.update(customHighlightColor: v, store: store);
+        break;
+      case CustomColorMode.accent:
+        settings.update(customAccentColor: v, store: store);
+        break;
+      case CustomColorMode.enterId:
+        settings.update(customBackgroundColor: background, store: store);
+        settings.update(customHighlightColor: panels, store: store);
+        settings.update(customAccentColor: accent, store: store);
+        break;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    bool hasAccess = Provider.of<PremiumProvider>(context)
+        .hasScope(PremiumScopes.customColors);
+    bool isBackgroundDifferent = Theme.of(context).colorScheme.background !=
+        AppColors.of(context).background;
+
+    ThemeMode currentTheme = Theme.of(context).brightness == Brightness.light
+        ? ThemeMode.light
+        : ThemeMode.dark;
+
+    return WillPopScope(
+      onWillPop: () async {
+        Provider.of<ThemeModeObserver>(context, listen: false)
+            .changeTheme(settings.theme, updateNavbarColor: true);
+        return true;
+      },
+      child: AnimatedBuilder(
+        animation: _openAnimController,
+        builder: (context, child) {
+          final backgroundGradientBottomColor = isBackgroundDifferent
+              ? Theme.of(context).colorScheme.background
+              : HSVColor.fromColor(Theme.of(context).colorScheme.background)
+                  .withValue(currentTheme == ThemeMode.dark
+                      ? 0.1 * _openAnimController.value
+                      : 1.0 - (0.1 * _openAnimController.value))
+                  .withAlpha(1.0)
+                  .toColor();
+
+          SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
+            systemNavigationBarColor: backgroundGradientBottomColor,
+          ));
+
+          return Container(
+            decoration: BoxDecoration(
+              gradient: LinearGradient(
+                begin: Alignment.topCenter,
+                end: Alignment.bottomCenter,
+                stops: const [0.0, 0.75],
+                colors: isBackgroundDifferent
+                    ? [
+                        Theme.of(context).colorScheme.background.withOpacity(1 -
+                            ((currentTheme == ThemeMode.dark ? 0.65 : 0.45) *
+                                backgroundAnimation.value)),
+                        backgroundGradientBottomColor,
+                      ]
+                    : [
+                        backgroundGradientBottomColor,
+                        backgroundGradientBottomColor
+                      ],
+              ),
+            ),
+            child: Opacity(
+              opacity: fullPageAnimation.value,
+              child: Scaffold(
+                backgroundColor: Colors.transparent,
+                appBar: AppBar(
+                  surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+                  leading: BackButton(color: AppColors.of(context).text),
+                  actions: [
+                    Padding(
+                      padding: const EdgeInsets.only(right: 10.0),
+                      child: IconButton(
+                        focusColor: Colors.transparent,
+                        highlightColor: Colors.transparent,
+                        splashColor: Colors.transparent,
+                        onPressed: () async {
+                          // ScaffoldMessenger.of(context).showSnackBar(
+                          //   const SnackBar(
+                          //     duration: Duration(milliseconds: 1000),
+                          //     content: Text(
+                          //       "Hamarosan...",
+                          //     ),
+                          //   ),
+                          // );
+                          SharedTheme theme =
+                              await shareProvider.shareCurrentTheme(context);
+                          Share.share(theme.id,
+                              subject: 'reFilc Téma / reFilc Theme');
+                        },
+                        icon: const Icon(
+                          FeatherIcons.share2,
+                          size: 22.0,
+                        ),
+                      ),
+                    ),
+                  ],
+                  title: Text(
+                    "theme_prev".i18n,
+                    style: TextStyle(color: AppColors.of(context).text),
+                  ),
+                  backgroundColor: Colors.transparent,
+                  elevation: 0,
+                ),
+                body: Stack(
+                  children: [
+                    Opacity(
+                      opacity: 1 - backContainerAnimation.value * (1 / 100),
+                      child: Transform.translate(
+                        offset: Offset(0, backContainerAnimation.value),
+                        child: Container(
+                          height: double.infinity,
+                          width: double.infinity,
+                          decoration: BoxDecoration(
+                            borderRadius: BorderRadius.circular(24),
+                            gradient: LinearGradient(
+                                begin: Alignment.topCenter,
+                                end: Alignment.bottomCenter,
+                                stops: const [
+                                  0.35,
+                                  0.75
+                                ],
+                                colors: [
+                                  Theme.of(context).colorScheme.background,
+                                  isBackgroundDifferent
+                                      ? HSVColor.fromColor(Theme.of(context)
+                                              .colorScheme
+                                              .background)
+                                          .withSaturation((HSVColor.fromColor(
+                                                          Theme.of(context)
+                                                              .colorScheme
+                                                              .background)
+                                                      .saturation -
+                                                  0.15)
+                                              .clamp(0.0, 1.0))
+                                          .toColor()
+                                      : backgroundGradientBottomColor,
+                                ]),
+                          ),
+                          margin: const EdgeInsets.symmetric(
+                              vertical: 30, horizontal: 20),
+                        ),
+                      ),
+                    ),
+                    Padding(
+                      padding: const EdgeInsets.only(top: 8.0),
+                      child: SizedBox(
+                        width: double.infinity,
+                        child: Padding(
+                          padding: const EdgeInsets.only(top: 24.0),
+                          child: Opacity(
+                            opacity: 1 - backContentAnimation.value * (1 / 100),
+                            child: SingleChildScrollView(
+                              physics: const BouncingScrollPhysics(),
+                              child: Transform.translate(
+                                offset:
+                                    Offset(0, -24 + backContentAnimation.value),
+                                child: Transform.scale(
+                                  scale: backContentScaleAnimation.value,
+                                  child: Column(
+                                    children: [
+                                      Padding(
+                                        padding: const EdgeInsets.symmetric(
+                                            horizontal: 32.0, vertical: 6.0),
+                                        child: FilterBar(
+                                          items: const [
+                                            Tab(text: "All"),
+                                            Tab(text: "Grades"),
+                                            Tab(text: "Messages"),
+                                            Tab(text: "Absences"),
+                                          ],
+                                          controller: _testTabController,
+                                          padding: EdgeInsets.zero,
+                                          censored: true,
+                                          disableFading: true,
+                                        ),
+                                      ),
+                                      Padding(
+                                        padding: const EdgeInsets.symmetric(
+                                            horizontal: 18.0, vertical: 8.0),
+                                        child: NewGradesSurprise(
+                                          [
+                                            Grade.fromJson(
+                                              {
+                                                "Uid": "0,Ertekeles",
+                                                "RogzitesDatuma":
+                                                    "2022-01-01T23:00:00Z",
+                                                "KeszitesDatuma":
+                                                    "2022-01-01T23:00:00Z",
+                                                "LattamozasDatuma": null,
+                                                "Tantargy": {
+                                                  "Uid": "0",
+                                                  "Nev": "reFilc szakirodalom",
+                                                  "Kategoria": {
+                                                    "Uid": "0,_",
+                                                    "Nev": "_",
+                                                    "Leiras": "Nem mondom meg"
+                                                  },
+                                                  "SortIndex": 2
+                                                },
+                                                "Tema":
+                                                    "Kupak csomag vásárlás vizsga",
+                                                "Tipus": {
+                                                  "Uid": "0,_",
+                                                  "Nev": "_",
+                                                  "Leiras":
+                                                      "Évközi jegy/értékelés",
+                                                },
+                                                "Mod": {
+                                                  "Uid": "0,_",
+                                                  "Nev": "_",
+                                                  "Leiras": "_ feladat",
+                                                },
+                                                "ErtekFajta": {
+                                                  "Uid": "1,Osztalyzat",
+                                                  "Nev": "Osztalyzat",
+                                                  "Leiras":
+                                                      "Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték"
+                                                },
+                                                "ErtekeloTanarNeve": "Premium",
+                                                "Jelleg": "Ertekeles",
+                                                "SzamErtek": 5,
+                                                "SzovegesErtek": "Jeles(5)",
+                                                "SulySzazalekErteke": 100,
+                                                "SzovegesErtekelesRovidNev":
+                                                    null,
+                                                "OsztalyCsoport": {"Uid": "0"},
+                                                "SortIndex": 2
+                                              },
+                                            ),
+                                          ],
+                                          censored: true,
+                                        ),
+                                      ),
+                                      Padding(
+                                        padding: const EdgeInsets.symmetric(
+                                            horizontal: 24.0, vertical: 6.0),
+                                        child: Panel(
+                                          child: GradeTile(
+                                            Grade.fromJson(
+                                              {
+                                                "Uid": "0,Ertekeles",
+                                                "RogzitesDatuma":
+                                                    "2022-01-01T23:00:00Z",
+                                                "KeszitesDatuma":
+                                                    "2022-01-01T23:00:00Z",
+                                                "LattamozasDatuma": null,
+                                                "Tantargy": {
+                                                  "Uid": "0",
+                                                  "Nev": "reFilc szakosztály",
+                                                  "Kategoria": {
+                                                    "Uid": "0,_",
+                                                    "Nev": "_",
+                                                    "Leiras": "Nem mondom meg"
+                                                  },
+                                                  "SortIndex": 2
+                                                },
+                                                "Tema":
+                                                    "Kupak csomag vásárlás vizsga",
+                                                "Tipus": {
+                                                  "Uid": "0,_",
+                                                  "Nev": "_",
+                                                  "Leiras":
+                                                      "Évközi jegy/értékelés",
+                                                },
+                                                "Mod": {
+                                                  "Uid": "0,_",
+                                                  "Nev": "_",
+                                                  "Leiras": "_ feladat",
+                                                },
+                                                "ErtekFajta": {
+                                                  "Uid": "1,Osztalyzat",
+                                                  "Nev": "Osztalyzat",
+                                                  "Leiras":
+                                                      "Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték"
+                                                },
+                                                "ErtekeloTanarNeve": "Premium",
+                                                "Jelleg": "Ertekeles",
+                                                "SzamErtek": 5,
+                                                "SzovegesErtek": "Jeles(5)",
+                                                "SulySzazalekErteke": 100,
+                                                "SzovegesErtekelesRovidNev":
+                                                    null,
+                                                "OsztalyCsoport": {"Uid": "0"},
+                                                "SortIndex": 2
+                                              },
+                                            ),
+                                            padding: EdgeInsets.zero,
+                                            censored: true,
+                                          ),
+                                        ),
+                                      ),
+                                      Padding(
+                                        padding: const EdgeInsets.symmetric(
+                                            horizontal: 24.0, vertical: 6.0),
+                                        child: Panel(
+                                          child: HomeworkTile(
+                                            Homework.fromJson(
+                                              {
+                                                "Uid": "0",
+                                                "Tantargy": {
+                                                  "Uid": "0",
+                                                  "Nev":
+                                                      "reFilc premium előnyei",
+                                                  "Kategoria": {
+                                                    "Uid": "0,_",
+                                                    "Nev": "_",
+                                                    "Leiras":
+                                                        "reFilc premium előnyei",
+                                                  },
+                                                  "SortIndex": 0
+                                                },
+                                                "TantargyNeve":
+                                                    "reFilc premium előnyei",
+                                                "RogzitoTanarNeve":
+                                                    "Kupak János",
+                                                "Szoveg":
+                                                    "45 perc filctollal való rajzolás",
+                                                "FeladasDatuma":
+                                                    "2022-01-01T23:00:00Z",
+                                                "HataridoDatuma":
+                                                    "2022-01-01T23:00:00Z",
+                                                "RogzitesIdopontja":
+                                                    "2022-01-01T23:00:00Z",
+                                                "IsTanarRogzitette": true,
+                                                "IsTanuloHaziFeladatEnabled":
+                                                    false,
+                                                "IsMegoldva": false,
+                                                "IsBeadhato": false,
+                                                "OsztalyCsoport": {"Uid": "0"},
+                                                "IsCsatolasEngedelyezes": false
+                                              },
+                                            ),
+                                            padding: EdgeInsets.zero,
+                                            censored: true,
+                                          ),
+                                        ),
+                                      ),
+                                      Padding(
+                                        padding: const EdgeInsets.symmetric(
+                                            horizontal: 24.0, vertical: 6.0),
+                                        child: Panel(
+                                          child: MessageTile(
+                                            Message.fromJson(
+                                              {
+                                                "azonosito": 0,
+                                                "isElolvasva": true,
+                                                "isToroltElem": false,
+                                                "tipus": {
+                                                  "azonosito": 1,
+                                                  "kod": "BEERKEZETT",
+                                                  "rovidNev":
+                                                      "Beérkezett üzenet",
+                                                  "nev": "Beérkezett üzenet",
+                                                  "leiras": "Beérkezett üzenet"
+                                                },
+                                                "uzenet": {
+                                                  "azonosito": 0,
+                                                  "kuldesDatum":
+                                                      "2022-01-01T23:00:00",
+                                                  "feladoNev": "reFilc",
+                                                  "feladoTitulus":
+                                                      "Nagyon magas szintű személy",
+                                                  "szoveg":
+                                                      "<p>Kedves Felhasználó!</p><p><br></p><p>A prémium vásárlásakor kapott filctollal 90%-al több esély van jó jegyek szerzésére.</p>",
+                                                  "targy":
+                                                      "Filctoll használati útmutató",
+                                                  "statusz": {
+                                                    "azonosito": 2,
+                                                    "kod": "KIKULDVE",
+                                                    "rovidNev": "Kiküldve",
+                                                    "nev": "Kiküldve",
+                                                    "leiras": "Kiküldve"
+                                                  },
+                                                  "cimzettLista": [
+                                                    {
+                                                      "azonosito": 0,
+                                                      "kretaAzonosito": 0,
+                                                      "nev": "Tinta Józsi",
+                                                      "tipus": {
+                                                        "azonosito": 0,
+                                                        "kod": "TANULO",
+                                                        "rovidNev": "Tanuló",
+                                                        "nev": "Tanuló",
+                                                        "leiras": "Tanuló"
+                                                      }
+                                                    },
+                                                  ],
+                                                  "csatolmanyok": [
+                                                    {
+                                                      "azonosito": 0,
+                                                      "fajlNev": "Filctoll.doc"
+                                                    }
+                                                  ]
+                                                }
+                                              },
+                                            ),
+                                            censored: true,
+                                          ),
+                                        ),
+                                      ),
+                                    ],
+                                  ),
+                                ),
+                              ),
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+                    Align(
+                      alignment: Alignment.bottomCenter,
+                      child: Wrap(
+                        children: [
+                          Opacity(
+                            opacity: pickerContainerAnimation.value,
+                            child: SizedBox(
+                              width: double.infinity,
+                              child: Container(
+                                padding: const EdgeInsets.only(bottom: 12.0),
+                                decoration: BoxDecoration(
+                                  boxShadow: [
+                                    BoxShadow(
+                                      color: backgroundGradientBottomColor,
+                                      offset: const Offset(0, -8),
+                                      blurRadius: 16,
+                                      spreadRadius: 18,
+                                    ),
+                                  ],
+                                  gradient: LinearGradient(
+                                      begin: Alignment.topCenter,
+                                      end: Alignment.bottomCenter,
+                                      stops: const [
+                                        0.0,
+                                        0.175
+                                      ],
+                                      colors: [
+                                        backgroundGradientBottomColor,
+                                        backgroundGradientBottomColor,
+                                      ]),
+                                ),
+                                child: Column(
+                                  children: [
+                                    Padding(
+                                      padding: const EdgeInsets.symmetric(
+                                          horizontal: 8.0),
+                                      child: FilterBar(
+                                        items: [
+                                          ColorTab(
+                                              color: accentColorMap[
+                                                      settings.accentColor] ??
+                                                  unknownColor,
+                                              tab: Tab(
+                                                  text: "colorpicker_presets"
+                                                      .i18n)),
+                                          ColorTab(
+                                              color: unknownColor,
+                                              tab: Tab(text: "enter_id".i18n)),
+                                          /*ColorTab(
+                                              color:
+                                                  settings.customAccentColor ??
+                                                      unknownColor,
+                                              tab: Tab(
+                                                  text: "colorpicker_saved"
+                                                      .i18n)),*/
+                                          ColorTab(
+                                              unlocked: hasAccess,
+                                              color: settings
+                                                      .customBackgroundColor ??
+                                                  unknownColor,
+                                              tab: Tab(
+                                                  text: "colorpicker_background"
+                                                      .i18n)),
+                                          ColorTab(
+                                              unlocked: hasAccess,
+                                              color: settings
+                                                      .customHighlightColor ??
+                                                  unknownColor,
+                                              tab: Tab(
+                                                  text: "colorpicker_panels"
+                                                      .i18n)),
+                                          ColorTab(
+                                              unlocked: hasAccess,
+                                              color:
+                                                  settings.customAccentColor ??
+                                                      unknownColor,
+                                              tab: Tab(
+                                                  text: "colorpicker_accent"
+                                                      .i18n)),
+                                        ],
+                                        onTap: (index) {
+                                          if (!hasAccess) {
+                                            index = 0;
+                                            _colorsTabController.animateTo(0,
+                                                duration: Duration.zero);
+
+                                            PremiumLockedFeatureUpsell.show(
+                                                context: context,
+                                                feature: PremiumFeature
+                                                    .customcolors);
+                                          }
+
+                                          switch (index) {
+                                            case 0:
+                                              setState(() {
+                                                colorMode =
+                                                    CustomColorMode.theme;
+                                              });
+                                              break;
+                                            case 1:
+                                              setState(() {
+                                                colorMode =
+                                                    CustomColorMode.enterId;
+                                              });
+                                              break;
+                                            /*case 1:
+                                              setState(() {
+                                                colorMode =
+                                                    CustomColorMode.saved;
+                                              });
+                                              break;*/
+                                            case 2:
+                                              setState(() {
+                                                colorMode =
+                                                    CustomColorMode.background;
+                                              });
+                                              break;
+                                            case 3:
+                                              setState(() {
+                                                colorMode =
+                                                    CustomColorMode.highlight;
+                                              });
+                                              break;
+                                            case 4:
+                                              setState(() {
+                                                colorMode =
+                                                    CustomColorMode.accent;
+                                              });
+                                              break;
+                                          }
+                                        },
+                                        controller: _colorsTabController,
+                                        padding: EdgeInsets.zero,
+                                      ),
+                                    ),
+                                    Padding(
+                                      padding: const EdgeInsets.symmetric(
+                                          horizontal: 12.0),
+                                      child: SafeArea(
+                                        child: FilcColorPicker(
+                                          colorMode: colorMode,
+                                          pickerColor: colorMode ==
+                                                  CustomColorMode.accent
+                                              ? settings.customAccentColor ??
+                                                  unknownColor
+                                              : colorMode ==
+                                                      CustomColorMode.background
+                                                  ? settings
+                                                          .customBackgroundColor ??
+                                                      unknownColor
+                                                  : colorMode ==
+                                                          CustomColorMode.theme
+                                                      ? (accentColorMap[settings
+                                                              .accentColor] ??
+                                                          AppColors.of(context)
+                                                              .text) // idk what else
+                                                      : settings
+                                                              .customHighlightColor ??
+                                                          unknownColor,
+                                          onColorChanged: (c) {
+                                            setState(() {
+                                              updateCustomColor(c, false);
+                                            });
+                                            setTheme(settings.theme, false);
+                                          },
+                                          onColorChangeEnd: (c, {adaptive}) {
+                                            setState(() {
+                                              if (adaptive == true) {
+                                                settings.update(
+                                                    accentColor:
+                                                        AccentColor.adaptive);
+                                                settings.update(
+                                                    customBackgroundColor:
+                                                        AppColors.of(context)
+                                                            .background,
+                                                    store: true);
+                                                settings.update(
+                                                    customHighlightColor:
+                                                        AppColors.of(context)
+                                                            .highlight,
+                                                    store: true);
+                                              } else {
+                                                updateCustomColor(c, true);
+                                              }
+                                            });
+                                            setTheme(settings.theme, true);
+                                          },
+                                          onThemeIdProvided: (theme) {
+                                            setState(() {
+                                              updateCustomColor(
+                                                null,
+                                                true,
+                                                accent: theme.accentColor,
+                                                background:
+                                                    theme.backgroundColor,
+                                                panels: theme.panelsColor,
+                                              );
+                                            });
+                                            setTheme(settings.theme, true);
+                                          },
+                                        ),
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            ),
+                          ),
+                        ],
+                      ),
+                    ),
+                  ],
+                ),
+              ),
+            ),
+          );
+        },
+      ),
+    );
+  }
+}
+
+class ColorTab extends StatelessWidget {
+  const ColorTab(
+      {Key? key, required this.tab, required this.color, this.unlocked = true})
+      : super(key: key);
+
+  final Tab tab;
+  final Color color;
+  final bool unlocked;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        Transform.translate(
+          offset: const Offset(-3, 1),
+          child: unlocked
+              ? Container(
+                  width: 15,
+                  height: 15,
+                  decoration: BoxDecoration(
+                    shape: BoxShape.circle,
+                    color: color,
+                    border: Border.all(color: Colors.black, width: 2.0),
+                  ),
+                )
+              : const Padding(
+                  padding: EdgeInsets.symmetric(horizontal: 2),
+                  child: Icon(Icons.lock,
+                      color: Color.fromARGB(255, 82, 82, 82), size: 18),
+                ),
+        ),
+        tab
+      ],
+    );
+  }
+}
+
+class PremiumColorPickerItem extends StatelessWidget {
+  const PremiumColorPickerItem(
+      {Key? key, required this.label, this.onTap, required this.color})
+      : super(key: key);
+
+  final String label;
+  final void Function()? onTap;
+  final Color color;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      type: MaterialType.transparency,
+      child: InkWell(
+        child: Padding(
+          padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
+          child: Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              Expanded(
+                child: Text(
+                  label,
+                  style: TextStyle(
+                      color: AppColors.of(context).text,
+                      fontWeight: FontWeight.w500),
+                ),
+              ),
+              Container(
+                width: 30,
+                height: 30,
+                decoration: BoxDecoration(
+                    color: color, shape: BoxShape.circle, border: Border.all()),
+              ),
+            ],
+          ),
+        ),
+        onTap: onTap,
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart b/refilc_premium/lib/ui/mobile/settings/theme.i18n.dart
similarity index 97%
rename from filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart
rename to refilc_premium/lib/ui/mobile/settings/theme.i18n.dart
index 40ac863..5b958a4 100644
--- a/filcnaplo_premium/lib/ui/mobile/settings/theme.i18n.dart
+++ b/refilc_premium/lib/ui/mobile/settings/theme.i18n.dart
@@ -1,49 +1,49 @@
-import 'package:i18n_extension/i18n_extension.dart';
-
-extension SettingsLocalization on String {
-  static final _t = Translations.byLocale("hu_hu") +
-      {
-        "en_en": {
-          "theme_prev": "Preview",
-          "colorpicker_presets": "Presets",
-          "colorpicker_background": "Background",
-          "colorpicker_panels": "Panels",
-          "colorpicker_accent": "Accent",
-          "need_sub": "You need Kupak subscription to use modify this.",
-          "advanced": "Advanced",
-          "enter_id": "Enter ID",
-          "theme_id": "Theme ID...",
-          "theme_not_found": "Theme not found!",
-        },
-        "hu_hu": {
-          "theme_prev": "Előnézet",
-          "colorpicker_presets": "Téma",
-          "colorpicker_background": "Háttér",
-          "colorpicker_panels": "Panelek",
-          "colorpicker_accent": "Színtónus",
-          "need_sub": "A módosításhoz Kupak szintű támogatás szükséges.",
-          "advanced": "Haladó",
-          "enter_id": "ID megadása",
-          "theme_id": "Téma azonosító...",
-          "theme_not_found": "A téma nem található!",
-        },
-        "de_de": {
-          "theme_prev": "Vorschau",
-          "colorpicker_presets": "Farben",
-          "colorpicker_background": "Hintergrund",
-          "colorpicker_panels": "Tafeln",
-          "colorpicker_accent": "Akzent",
-          "need_sub":
-              "Sie benötigen ein Kupak-Abonnement, um diese Funktion zu ändern.",
-          "advanced": "Fortschrittlich",
-          "enter_id": "Geben Sie die ID ein",
-          "theme_id": "Themen-ID...",
-          "theme_not_found": "Thema nicht gefunden!",
-        },
-      };
-
-  String get i18n => localize(this, _t);
-  String fill(List<Object> params) => localizeFill(this, params);
-  String plural(int value) => localizePlural(value, this, _t);
-  String version(Object modifier) => localizeVersion(modifier, this, _t);
-}
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension SettingsLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "theme_prev": "Preview",
+          "colorpicker_presets": "Presets",
+          "colorpicker_background": "Background",
+          "colorpicker_panels": "Panels",
+          "colorpicker_accent": "Accent",
+          "need_sub": "You need Kupak subscription to use modify this.",
+          "advanced": "Advanced",
+          "enter_id": "Enter ID",
+          "theme_id": "Theme ID...",
+          "theme_not_found": "Theme not found!",
+        },
+        "hu_hu": {
+          "theme_prev": "Előnézet",
+          "colorpicker_presets": "Téma",
+          "colorpicker_background": "Háttér",
+          "colorpicker_panels": "Panelek",
+          "colorpicker_accent": "Színtónus",
+          "need_sub": "A módosításhoz Kupak szintű támogatás szükséges.",
+          "advanced": "Haladó",
+          "enter_id": "ID megadása",
+          "theme_id": "Téma azonosító...",
+          "theme_not_found": "A téma nem található!",
+        },
+        "de_de": {
+          "theme_prev": "Vorschau",
+          "colorpicker_presets": "Farben",
+          "colorpicker_background": "Hintergrund",
+          "colorpicker_panels": "Tafeln",
+          "colorpicker_accent": "Akzent",
+          "need_sub":
+              "Sie benötigen ein Kupak-Abonnement, um diese Funktion zu ändern.",
+          "advanced": "Fortschrittlich",
+          "enter_id": "Geben Sie die ID ein",
+          "theme_id": "Themen-ID...",
+          "theme_not_found": "Thema nicht gefunden!",
+        },
+      };
+
+  String get i18n => localize(this, _t);
+  String fill(List<Object> params) => localizeFill(this, params);
+  String plural(int value) => localizePlural(value, this, _t);
+  String version(Object modifier) => localizeVersion(modifier, this, _t);
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/timetable/fs_timetable.dart b/refilc_premium/lib/ui/mobile/timetable/fs_timetable.dart
similarity index 90%
rename from filcnaplo_premium/lib/ui/mobile/timetable/fs_timetable.dart
rename to refilc_premium/lib/ui/mobile/timetable/fs_timetable.dart
index a19f9ff..87d54d8 100644
--- a/filcnaplo_premium/lib/ui/mobile/timetable/fs_timetable.dart
+++ b/refilc_premium/lib/ui/mobile/timetable/fs_timetable.dart
@@ -1,212 +1,210 @@
-import 'package:filcnaplo/helpers/subject.dart';
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
-import 'package:filcnaplo_mobile_ui/common/empty.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:filcnaplo/utils/format.dart';
-import 'dart:math' as math;
-import 'package:intl/intl.dart';
-import 'package:i18n_extension/i18n_widget.dart';
-
-class PremiumFSTimetable extends StatefulWidget {
-  const PremiumFSTimetable({Key? key, required this.controller})
-      : super(key: key);
-
-  final TimetableController controller;
-
-  @override
-  State<PremiumFSTimetable> createState() => _PremiumFSTimetableState();
-}
-
-class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
-  @override
-  void initState() {
-    super.initState();
-
-    SystemChrome.setPreferredOrientations([
-      DeviceOrientation.landscapeLeft,
-    ]);
-    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
-    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
-      statusBarColor: Colors.transparent,
-      systemNavigationBarColor: Colors.transparent,
-    ));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    if (widget.controller.days == null || widget.controller.days!.isEmpty) {
-      return const Center(child: Empty());
-    }
-
-    final days = widget.controller.days!;
-    final everyLesson = days.expand((x) => x).toList();
-    everyLesson.sort((a, b) => a.start.compareTo(b.start));
-
-    final int maxLessonCount = days.fold(
-        0,
-        (a, b) => math.max(
-            a, b.where((l) => l.subject.id != "" || l.isEmpty).length));
-
-    const prefixw = 40;
-    const padding = prefixw + 6 * 2;
-    final colw = (MediaQuery.of(context).size.width - padding) / days.length;
-
-    return Scaffold(
-      appBar: AppBar(
-        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
-        leading: BackButton(color: AppColors.of(context).text),
-        shadowColor: Colors.transparent,
-      ),
-      body: ListView.builder(
-        physics: const BouncingScrollPhysics(),
-        padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 24.0),
-        itemCount: maxLessonCount + 1,
-        itemBuilder: (context, index) {
-          List<Widget> columns = [];
-          for (int dayIndex = -1; dayIndex < days.length; dayIndex++) {
-            if (dayIndex == -1) {
-              if (index >= 1) {
-                columns.add(SizedBox(
-                  width: prefixw.toDouble(),
-                  height: 40.0,
-                  child: Padding(
-                    padding: const EdgeInsets.symmetric(horizontal: 8.0),
-                    child: Text(
-                      (index).toString()+".",
-                      style: TextStyle(
-                          fontWeight: FontWeight.bold,
-                          color: Theme.of(context).colorScheme.secondary),
-                    ),
-                  ),
-                ));
-              } else {
-                columns.add(SizedBox(width: prefixw.toDouble()));
-              }
-              continue;
-            }
-
-            final lessons = days[dayIndex]
-                .where((l) => l.subject.id != "" || l.isEmpty)
-                .toList();
-
-            if (lessons.isEmpty) continue;
-
-            final dayOffset = int.tryParse(lessons.first.lessonIndex) ?? 0;
-
-            if (index == 0 && dayIndex >= 0) {
-              columns.add(
-                SizedBox(
-                  width: colw,
-                  height: 40.0,
-                  child: Text(
-                    DateFormat("EEEE", I18n.of(context).locale.languageCode)
-                        .format(lessons.first.date)
-                        .capital(),
-                    style: const TextStyle(
-                      fontSize: 24.0,
-                      fontWeight: FontWeight.bold,
-                    ),
-                  ),
-                ),
-              );
-              continue;
-            }
-
-            final lessonIndex = index - dayOffset;
-
-            if (lessonIndex < 0 || lessonIndex >= lessons.length) {
-              columns.add(SizedBox(width: colw));
-              continue;
-            }
-
-            if (lessons[lessonIndex].isEmpty) {
-              columns.add(
-                SizedBox(
-                  width: colw,
-                  child: Row(
-                    crossAxisAlignment: CrossAxisAlignment.start,
-                    children: [
-                      Icon(
-                        FeatherIcons.slash,
-                        size: 18.0,
-                        color: AppColors.of(context).text.withOpacity(.3),
-                      ),
-                      const SizedBox(width: 8.0),
-                      Text(
-                        "Lyukas óra",
-                        style: TextStyle(
-                          color: AppColors.of(context).text.withOpacity(.3),
-                        ),
-                      ),
-                    ],
-                  ),
-                ),
-              );
-              continue;
-            }
-
-            columns.add(
-              SizedBox(
-                width: colw,
-                child: Column(
-                  mainAxisSize: MainAxisSize.min,
-                  crossAxisAlignment: CrossAxisAlignment.start,
-                  children: [
-                    Row(
-                      children: [
-                        Icon(
-                          SubjectIcon.resolveVariant(
-                            context: context,
-                            subject: lessons[lessonIndex].subject,
-                          ),
-                          size: 18.0,
-                          color: AppColors.of(context).text.withOpacity(.7),
-                        ),
-                        const SizedBox(width: 8.0),
-                        Expanded(
-                          child: Text(
-                            lessons[lessonIndex].subject.renamedTo ??
-                                lessons[lessonIndex].subject.name.capital(),
-                            maxLines: 1,
-                            style: TextStyle(
-                              fontStyle: lessons[lessonIndex]
-                                      .subject
-                                      .isRenamed
-                                  ? FontStyle.italic
-                                  : null,
-                            ),
-                            overflow: TextOverflow.clip,
-                            softWrap: false,
-                          ),
-                        ),
-                        const SizedBox(width: 15),
-                      ],
-                    ),
-                    Padding(
-                      padding: const EdgeInsets.only(left: 26.0),
-                      child: Text(
-                        lessons[lessonIndex].room,
-                        style: TextStyle(
-                          color: AppColors.of(context).text.withOpacity(.5),
-                          overflow: TextOverflow.ellipsis,
-                        ),
-                      ),
-                    ),
-                  ],
-                ),
-              ),
-            );
-          }
-
-          return Row(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: columns,
-          );
-        },
-      ),
-    );
-  }
-}
+import 'package:refilc/helpers/subject.dart';
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
+import 'package:refilc_mobile_ui/common/empty.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:refilc/utils/format.dart';
+import 'dart:math' as math;
+import 'package:intl/intl.dart';
+import 'package:i18n_extension/i18n_widget.dart';
+
+class PremiumFSTimetable extends StatefulWidget {
+  const PremiumFSTimetable({Key? key, required this.controller})
+      : super(key: key);
+
+  final TimetableController controller;
+
+  @override
+  State<PremiumFSTimetable> createState() => _PremiumFSTimetableState();
+}
+
+class _PremiumFSTimetableState extends State<PremiumFSTimetable> {
+  @override
+  void initState() {
+    super.initState();
+
+    SystemChrome.setPreferredOrientations([
+      DeviceOrientation.landscapeLeft,
+    ]);
+    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
+    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
+      statusBarColor: Colors.transparent,
+      systemNavigationBarColor: Colors.transparent,
+    ));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (widget.controller.days == null || widget.controller.days!.isEmpty) {
+      return const Center(child: Empty());
+    }
+
+    final days = widget.controller.days!;
+    final everyLesson = days.expand((x) => x).toList();
+    everyLesson.sort((a, b) => a.start.compareTo(b.start));
+
+    final int maxLessonCount = days.fold(
+        0,
+        (a, b) => math.max(
+            a, b.where((l) => l.subject.id != "" || l.isEmpty).length));
+
+    const prefixw = 40;
+    const padding = prefixw + 6 * 2;
+    final colw = (MediaQuery.of(context).size.width - padding) / days.length;
+
+    return Scaffold(
+      appBar: AppBar(
+        surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
+        leading: BackButton(color: AppColors.of(context).text),
+        shadowColor: Colors.transparent,
+      ),
+      body: ListView.builder(
+        physics: const BouncingScrollPhysics(),
+        padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 24.0),
+        itemCount: maxLessonCount + 1,
+        itemBuilder: (context, index) {
+          List<Widget> columns = [];
+          for (int dayIndex = -1; dayIndex < days.length; dayIndex++) {
+            if (dayIndex == -1) {
+              if (index >= 1) {
+                columns.add(SizedBox(
+                  width: prefixw.toDouble(),
+                  height: 40.0,
+                  child: Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 8.0),
+                    child: Text(
+                      (index).toString() + ".",
+                      style: TextStyle(
+                          fontWeight: FontWeight.bold,
+                          color: Theme.of(context).colorScheme.secondary),
+                    ),
+                  ),
+                ));
+              } else {
+                columns.add(SizedBox(width: prefixw.toDouble()));
+              }
+              continue;
+            }
+
+            final lessons = days[dayIndex]
+                .where((l) => l.subject.id != "" || l.isEmpty)
+                .toList();
+
+            if (lessons.isEmpty) continue;
+
+            final dayOffset = int.tryParse(lessons.first.lessonIndex) ?? 0;
+
+            if (index == 0 && dayIndex >= 0) {
+              columns.add(
+                SizedBox(
+                  width: colw,
+                  height: 40.0,
+                  child: Text(
+                    DateFormat("EEEE", I18n.of(context).locale.languageCode)
+                        .format(lessons.first.date)
+                        .capital(),
+                    style: const TextStyle(
+                      fontSize: 24.0,
+                      fontWeight: FontWeight.bold,
+                    ),
+                  ),
+                ),
+              );
+              continue;
+            }
+
+            final lessonIndex = index - dayOffset;
+
+            if (lessonIndex < 0 || lessonIndex >= lessons.length) {
+              columns.add(SizedBox(width: colw));
+              continue;
+            }
+
+            if (lessons[lessonIndex].isEmpty) {
+              columns.add(
+                SizedBox(
+                  width: colw,
+                  child: Row(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      Icon(
+                        FeatherIcons.slash,
+                        size: 18.0,
+                        color: AppColors.of(context).text.withOpacity(.3),
+                      ),
+                      const SizedBox(width: 8.0),
+                      Text(
+                        "Lyukas óra",
+                        style: TextStyle(
+                          color: AppColors.of(context).text.withOpacity(.3),
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              );
+              continue;
+            }
+
+            columns.add(
+              SizedBox(
+                width: colw,
+                child: Column(
+                  mainAxisSize: MainAxisSize.min,
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    Row(
+                      children: [
+                        Icon(
+                          SubjectIcon.resolveVariant(
+                            context: context,
+                            subject: lessons[lessonIndex].subject,
+                          ),
+                          size: 18.0,
+                          color: AppColors.of(context).text.withOpacity(.7),
+                        ),
+                        const SizedBox(width: 8.0),
+                        Expanded(
+                          child: Text(
+                            lessons[lessonIndex].subject.renamedTo ??
+                                lessons[lessonIndex].subject.name.capital(),
+                            maxLines: 1,
+                            style: TextStyle(
+                              fontStyle: lessons[lessonIndex].subject.isRenamed
+                                  ? FontStyle.italic
+                                  : null,
+                            ),
+                            overflow: TextOverflow.clip,
+                            softWrap: false,
+                          ),
+                        ),
+                        const SizedBox(width: 15),
+                      ],
+                    ),
+                    Padding(
+                      padding: const EdgeInsets.only(left: 26.0),
+                      child: Text(
+                        lessons[lessonIndex].room,
+                        style: TextStyle(
+                          color: AppColors.of(context).text.withOpacity(.5),
+                          overflow: TextOverflow.ellipsis,
+                        ),
+                      ),
+                    ),
+                  ],
+                ),
+              ),
+            );
+          }
+
+          return Row(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: columns,
+          );
+        },
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/lib/ui/mobile/timetable/fs_timetable_button.dart b/refilc_premium/lib/ui/mobile/timetable/fs_timetable_button.dart
similarity index 74%
rename from filcnaplo_premium/lib/ui/mobile/timetable/fs_timetable_button.dart
rename to refilc_premium/lib/ui/mobile/timetable/fs_timetable_button.dart
index db5e22d..8932ab1 100644
--- a/filcnaplo_premium/lib/ui/mobile/timetable/fs_timetable_button.dart
+++ b/refilc_premium/lib/ui/mobile/timetable/fs_timetable_button.dart
@@ -1,62 +1,62 @@
-import 'package:filcnaplo/theme/colors/colors.dart';
-import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
-import 'package:filcnaplo_mobile_ui/common/system_chrome.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:filcnaplo_premium/ui/mobile/timetable/fs_timetable.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_feather_icons/flutter_feather_icons.dart';
-import 'package:provider/provider.dart';
-import 'package:filcnaplo_mobile_ui/pages/timetable/timetable_page.i18n.dart';
-
-class PremiumFSTimetableButton extends StatelessWidget {
-  const PremiumFSTimetableButton(
-      {Key? key, required this.controller, required this.tabcontroller})
-      : super(key: key);
-
-  final TimetableController controller;
-  final TabController tabcontroller;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.all(8.0),
-      child: IconButton(
-        splashRadius: 24.0,
-        onPressed: () {
-          if (!Provider.of<PremiumProvider>(context, listen: false)
-              .hasScope(PremiumScopes.fsTimetable)) {
-            PremiumLockedFeatureUpsell.show(
-                context: context, feature: PremiumFeature.weeklytimetable);
-            return;
-          }
-
-          // If timetable empty, show empty
-          if (tabcontroller.length == 0) {
-            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-              content: Text("empty_timetable".i18n),
-              duration: const Duration(seconds: 2),
-            ));
-            return;
-          }
-
-          Navigator.of(context, rootNavigator: true)
-              .push(PageRouteBuilder(
-            pageBuilder: (context, animation, secondaryAnimation) =>
-                PremiumFSTimetable(
-              controller: controller,
-            ),
-          ))
-              .then((_) {
-            SystemChrome.setPreferredOrientations(
-                [DeviceOrientation.portraitUp]);
-            setSystemChrome(context);
-          });
-        },
-        icon: Icon(FeatherIcons.trello, color: AppColors.of(context).text),
-      ),
-    );
-  }
-}
+import 'package:refilc/theme/colors/colors.dart';
+import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
+import 'package:refilc_mobile_ui/common/system_chrome.dart';
+import 'package:refilc_premium/models/premium_scopes.dart';
+import 'package:refilc_premium/providers/premium_provider.dart';
+import 'package:refilc_premium/ui/mobile/premium/upsell.dart';
+import 'package:refilc_premium/ui/mobile/timetable/fs_timetable.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:provider/provider.dart';
+import 'package:refilc_mobile_ui/pages/timetable/timetable_page.i18n.dart';
+
+class PremiumFSTimetableButton extends StatelessWidget {
+  const PremiumFSTimetableButton(
+      {Key? key, required this.controller, required this.tabcontroller})
+      : super(key: key);
+
+  final TimetableController controller;
+  final TabController tabcontroller;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.all(8.0),
+      child: IconButton(
+        splashRadius: 24.0,
+        onPressed: () {
+          if (!Provider.of<PremiumProvider>(context, listen: false)
+              .hasScope(PremiumScopes.fsTimetable)) {
+            PremiumLockedFeatureUpsell.show(
+                context: context, feature: PremiumFeature.weeklytimetable);
+            return;
+          }
+
+          // If timetable empty, show empty
+          if (tabcontroller.length == 0) {
+            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+              content: Text("empty_timetable".i18n),
+              duration: const Duration(seconds: 2),
+            ));
+            return;
+          }
+
+          Navigator.of(context, rootNavigator: true)
+              .push(PageRouteBuilder(
+            pageBuilder: (context, animation, secondaryAnimation) =>
+                PremiumFSTimetable(
+              controller: controller,
+            ),
+          ))
+              .then((_) {
+            SystemChrome.setPreferredOrientations(
+                [DeviceOrientation.portraitUp]);
+            setSystemChrome(context);
+          });
+        },
+        icon: Icon(FeatherIcons.trello, color: AppColors.of(context).text),
+      ),
+    );
+  }
+}
diff --git a/filcnaplo_premium/pubspec.yaml b/refilc_premium/pubspec.yaml
similarity index 68%
rename from filcnaplo_premium/pubspec.yaml
rename to refilc_premium/pubspec.yaml
index 1244ef7..cae5e0c 100644
--- a/filcnaplo_premium/pubspec.yaml
+++ b/refilc_premium/pubspec.yaml
@@ -1,38 +1,38 @@
-name: filcnaplo_premium
-publish_to: "none"
-
-environment:
-  sdk: ">=2.17.0 <3.0.0"
-
-dependencies:
-  flutter:
-    sdk: flutter
-  cupertino_icons: ^1.0.2
-
-  # Filcnaplo main dep
-  filcnaplo:
-    path: ../filcnaplo/
-  filcnaplo_kreta_api:
-    path: ../filcnaplo_kreta_api/
-  filcnaplo_mobile_ui:
-    path: "../filcnaplo_mobile_ui/"
-
-  provider: ^5.0.0
-  flutter_feather_icons: ^2.0.0+1
-  uni_links: ^0.5.1
-  url_launcher: ^6.1.6
-  dropdown_button2: ^1.8.9
-  home_widget: ^0.1.6
-  image_picker: ^0.8.6
-  image_crop:
-    git:
-      url: https://github.com/kimaah/image_crop.git
-  lottie: ^1.4.3
-  animations: ^2.0.1
-  flutter_svg: ^1.1.6
-
-dev_dependencies:
-  flutter_lints: ^1.0.0
-
-flutter:
-  uses-material-design: true
+name: refilc_premium
+publish_to: "none"
+
+environment:
+  sdk: ">=2.17.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  cupertino_icons: ^1.0.2
+
+  # refilc main dep
+  refilc:
+    path: ../refilc/
+  refilc_kreta_api:
+    path: ../refilc_kreta_api/
+  refilc_mobile_ui:
+    path: "../refilc_mobile_ui/"
+
+  provider: ^5.0.0
+  flutter_feather_icons: ^2.0.0+1
+  uni_links: ^0.5.1
+  url_launcher: ^6.1.6
+  dropdown_button2: ^1.8.9
+  home_widget: ^0.1.6
+  image_picker: ^0.8.6
+  image_crop:
+    git:
+      url: https://github.com/kimaah/image_crop.git
+  lottie: ^1.4.3
+  animations: ^2.0.1
+  flutter_svg: ^1.1.6
+
+dev_dependencies:
+  flutter_lints: ^1.0.0
+
+flutter:
+  uses-material-design: true