diff --git a/filcnaplo/.metadata b/filcnaplo/.metadata
index ebe4e24..6b7daaf 100644
--- a/filcnaplo/.metadata
+++ b/filcnaplo/.metadata
@@ -1,30 +1,33 @@
-# This file tracks properties of this Flutter project.
-# Used by Flutter tool to assess capabilities and perform upgrades etc.
-#
-# This file should be version controlled.
-
-version:
-  revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
-  channel: beta
-
-project_type: app
-
-# Tracks metadata for the flutter migrate command
-migration:
-  platforms:
-    - platform: root
-      create_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
-      base_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
-    - platform: macos
-      create_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
-      base_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
-
-  # User provided section
-
-  # List of Local paths (relative to this file) that should be
-  # ignored by the migrate tool.
-  #
-  # Files that are not part of the templates will be ignored by default.
-  unmanaged_files:
-    - 'lib/main.dart'
-    - 'ios/Runner.xcodeproj/project.pbxproj'
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+  revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+  channel: stable
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+  platforms:
+    - platform: root
+      create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+      base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+    - platform: linux
+      create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+      base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+    - platform: windows
+      create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+      base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
+
+  # User provided section
+
+  # List of Local paths (relative to this file) that should be
+  # ignored by the migrate tool.
+  #
+  # Files that are not part of the templates will be ignored by default.
+  unmanaged_files:
+    - 'lib/main.dart'
+    - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/filcnaplo/pubspec.yaml b/filcnaplo/pubspec.yaml
index 183792a..5cd1e2d 100644
--- a/filcnaplo/pubspec.yaml
+++ b/filcnaplo/pubspec.yaml
@@ -66,6 +66,7 @@ dependencies:
   flutter_local_notifications: ^14.1.0
   package_info_plus: ^4.0.2
   screenshot: ^2.1.0
+  flutter_staggered_grid_view: ^0.7.0
 
 dev_dependencies:
   flutter_lints: ^2.0.1
diff --git a/filcnaplo/test/widget_test.dart b/filcnaplo/test/widget_test.dart
new file mode 100644
index 0000000..a4b75df
--- /dev/null
+++ b/filcnaplo/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility in the flutter_test package. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:filcnaplo/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(const MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}
diff --git a/filcnaplo/windows/.gitignore b/filcnaplo/windows/.gitignore
new file mode 100644
index 0000000..d492d0d
--- /dev/null
+++ b/filcnaplo/windows/.gitignore
@@ -0,0 +1,17 @@
+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/windows/runner/Runner.rc b/filcnaplo/windows/runner/Runner.rc
new file mode 100644
index 0000000..51b3032
--- /dev/null
+++ b/filcnaplo/windows/runner/Runner.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""winres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON            ICON                    "resources\\app_icon.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
+#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
+#else
+#define VERSION_AS_NUMBER 1,0,0,0
+#endif
+
+#if defined(FLUTTER_VERSION)
+#define VERSION_AS_STRING FLUTTER_VERSION
+#else
+#define VERSION_AS_STRING "1.0.0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VERSION_AS_NUMBER
+ PRODUCTVERSION VERSION_AS_NUMBER
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904e4"
+        BEGIN
+            VALUE "CompanyName", "hu.refilc" "\0"
+            VALUE "FileDescription", "filcnaplo" "\0"
+            VALUE "FileVersion", VERSION_AS_STRING "\0"
+            VALUE "InternalName", "filcnaplo" "\0"
+            VALUE "LegalCopyright", "Copyright (C) 2023 hu.refilc. All rights reserved." "\0"
+            VALUE "OriginalFilename", "filcnaplo.exe" "\0"
+            VALUE "ProductName", "filcnaplo" "\0"
+            VALUE "ProductVersion", VERSION_AS_STRING "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1252
+    END
+END
+
+#endif    // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/filcnaplo/windows/runner/flutter_window.cpp b/filcnaplo/windows/runner/flutter_window.cpp
new file mode 100644
index 0000000..b25e363
--- /dev/null
+++ b/filcnaplo/windows/runner/flutter_window.cpp
@@ -0,0 +1,66 @@
+#include "flutter_window.h"
+
+#include <optional>
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(const flutter::DartProject& project)
+    : project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+bool FlutterWindow::OnCreate() {
+  if (!Win32Window::OnCreate()) {
+    return false;
+  }
+
+  RECT frame = GetClientArea();
+
+  // The size here must match the window dimensions to avoid unnecessary surface
+  // creation / destruction in the startup path.
+  flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
+      frame.right - frame.left, frame.bottom - frame.top, project_);
+  // Ensure that basic setup of the controller was successful.
+  if (!flutter_controller_->engine() || !flutter_controller_->view()) {
+    return false;
+  }
+  RegisterPlugins(flutter_controller_->engine());
+  SetChildContent(flutter_controller_->view()->GetNativeWindow());
+
+  flutter_controller_->engine()->SetNextFrameCallback([&]() {
+    this->Show();
+  });
+
+  return true;
+}
+
+void FlutterWindow::OnDestroy() {
+  if (flutter_controller_) {
+    flutter_controller_ = nullptr;
+  }
+
+  Win32Window::OnDestroy();
+}
+
+LRESULT
+FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
+                              WPARAM const wparam,
+                              LPARAM const lparam) noexcept {
+  // Give Flutter, including plugins, an opportunity to handle window messages.
+  if (flutter_controller_) {
+    std::optional<LRESULT> result =
+        flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
+                                                      lparam);
+    if (result) {
+      return *result;
+    }
+  }
+
+  switch (message) {
+    case WM_FONTCHANGE:
+      flutter_controller_->engine()->ReloadSystemFonts();
+      break;
+  }
+
+  return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
+}
diff --git a/filcnaplo/windows/runner/flutter_window.h b/filcnaplo/windows/runner/flutter_window.h
new file mode 100644
index 0000000..6da0652
--- /dev/null
+++ b/filcnaplo/windows/runner/flutter_window.h
@@ -0,0 +1,33 @@
+#ifndef RUNNER_FLUTTER_WINDOW_H_
+#define RUNNER_FLUTTER_WINDOW_H_
+
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+
+#include <memory>
+
+#include "win32_window.h"
+
+// A window that does nothing but host a Flutter view.
+class FlutterWindow : public Win32Window {
+ public:
+  // Creates a new FlutterWindow hosting a Flutter view running |project|.
+  explicit FlutterWindow(const flutter::DartProject& project);
+  virtual ~FlutterWindow();
+
+ protected:
+  // Win32Window:
+  bool OnCreate() override;
+  void OnDestroy() override;
+  LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
+                         LPARAM const lparam) noexcept override;
+
+ private:
+  // The project to run.
+  flutter::DartProject project_;
+
+  // The Flutter instance hosted by this window.
+  std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
+};
+
+#endif  // RUNNER_FLUTTER_WINDOW_H_
diff --git a/filcnaplo/windows/runner/main.cpp b/filcnaplo/windows/runner/main.cpp
new file mode 100644
index 0000000..2847838
--- /dev/null
+++ b/filcnaplo/windows/runner/main.cpp
@@ -0,0 +1,43 @@
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+#include <windows.h>
+
+#include "flutter_window.h"
+#include "utils.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
+                      _In_ wchar_t *command_line, _In_ int show_command) {
+  // Attach to console when present (e.g., 'flutter run') or create a
+  // new console when running with a debugger.
+  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
+    CreateAndAttachConsole();
+  }
+
+  // Initialize COM, so that it is available for use in the library and/or
+  // plugins.
+  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+  flutter::DartProject project(L"data");
+
+  std::vector<std::string> command_line_arguments =
+      GetCommandLineArguments();
+
+  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
+  FlutterWindow window(project);
+  Win32Window::Point origin(10, 10);
+  Win32Window::Size size(800, 720);
+  if (!window.Create(L"reFilc", origin, size)) {
+    return EXIT_FAILURE;
+  }
+  window.SetQuitOnClose(true);
+
+  ::MSG msg;
+  while (::GetMessage(&msg, nullptr, 0, 0)) {
+    ::TranslateMessage(&msg);
+    ::DispatchMessage(&msg);
+  }
+
+  ::CoUninitialize();
+  return EXIT_SUCCESS;
+}
diff --git a/filcnaplo/windows/runner/resource.h b/filcnaplo/windows/runner/resource.h
new file mode 100644
index 0000000..66a65d1
--- /dev/null
+++ b/filcnaplo/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON                    101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/filcnaplo/windows/runner/resources/app_icon.ico b/filcnaplo/windows/runner/resources/app_icon.ico
new file mode 100644
index 0000000..49c0c16
Binary files /dev/null and b/filcnaplo/windows/runner/resources/app_icon.ico differ
diff --git a/filcnaplo/windows/runner/runner.exe.manifest b/filcnaplo/windows/runner/runner.exe.manifest
new file mode 100644
index 0000000..a42ea76
--- /dev/null
+++ b/filcnaplo/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
+    </windowsSettings>
+  </application>
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- Windows 10 and Windows 11 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+    </application>
+  </compatibility>
+</assembly>
diff --git a/filcnaplo/windows/runner/utils.cpp b/filcnaplo/windows/runner/utils.cpp
new file mode 100644
index 0000000..b2b0873
--- /dev/null
+++ b/filcnaplo/windows/runner/utils.cpp
@@ -0,0 +1,65 @@
+#include "utils.h"
+
+#include <flutter_windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include <iostream>
+
+void CreateAndAttachConsole() {
+  if (::AllocConsole()) {
+    FILE *unused;
+    if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+      _dup2(_fileno(stdout), 1);
+    }
+    if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+      _dup2(_fileno(stdout), 2);
+    }
+    std::ios::sync_with_stdio();
+    FlutterDesktopResyncOutputStreams();
+  }
+}
+
+std::vector<std::string> GetCommandLineArguments() {
+  // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+  int argc;
+  wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+  if (argv == nullptr) {
+    return std::vector<std::string>();
+  }
+
+  std::vector<std::string> command_line_arguments;
+
+  // Skip the first argument as it's the binary name.
+  for (int i = 1; i < argc; i++) {
+    command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+  }
+
+  ::LocalFree(argv);
+
+  return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+  if (utf16_string == nullptr) {
+    return std::string();
+  }
+  int target_length = ::WideCharToMultiByte(
+      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+      -1, nullptr, 0, nullptr, nullptr)
+    -1; // remove the trailing null character
+  int input_length = (int)wcslen(utf16_string);
+  std::string utf8_string;
+  if (target_length <= 0 || target_length > utf8_string.max_size()) {
+    return utf8_string;
+  }
+  utf8_string.resize(target_length);
+  int converted_length = ::WideCharToMultiByte(
+      CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+      input_length, utf8_string.data(), target_length, nullptr, nullptr);
+  if (converted_length == 0) {
+    return std::string();
+  }
+  return utf8_string;
+}
diff --git a/filcnaplo/windows/runner/utils.h b/filcnaplo/windows/runner/utils.h
new file mode 100644
index 0000000..3879d54
--- /dev/null
+++ b/filcnaplo/windows/runner/utils.h
@@ -0,0 +1,19 @@
+#ifndef RUNNER_UTILS_H_
+#define RUNNER_UTILS_H_
+
+#include <string>
+#include <vector>
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector<std::string>,
+// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
+std::vector<std::string> GetCommandLineArguments();
+
+#endif  // RUNNER_UTILS_H_
diff --git a/filcnaplo/windows/runner/win32_window.cpp b/filcnaplo/windows/runner/win32_window.cpp
new file mode 100644
index 0000000..60608d0
--- /dev/null
+++ b/filcnaplo/windows/runner/win32_window.cpp
@@ -0,0 +1,288 @@
+#include "win32_window.h"
+
+#include <dwmapi.h>
+#include <flutter_windows.h>
+
+#include "resource.h"
+
+namespace {
+
+/// Window attribute that enables dark mode window decorations.
+///
+/// Redefined in case the developer's machine has a Windows SDK older than
+/// version 10.0.22000.0.
+/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
+#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
+#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
+#endif
+
+constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
+
+/// Registry key for app theme preference.
+///
+/// A value of 0 indicates apps should use dark mode. A non-zero or missing
+/// value indicates apps should use light mode.
+constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
+  L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
+constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
+
+// The number of Win32Window objects that currently exist.
+static int g_active_window_count = 0;
+
+using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
+
+// Scale helper to convert logical scaler values to physical using passed in
+// scale factor
+int Scale(int source, double scale_factor) {
+  return static_cast<int>(source * scale_factor);
+}
+
+// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
+// This API is only needed for PerMonitor V1 awareness mode.
+void EnableFullDpiSupportIfAvailable(HWND hwnd) {
+  HMODULE user32_module = LoadLibraryA("User32.dll");
+  if (!user32_module) {
+    return;
+  }
+  auto enable_non_client_dpi_scaling =
+      reinterpret_cast<EnableNonClientDpiScaling*>(
+          GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
+  if (enable_non_client_dpi_scaling != nullptr) {
+    enable_non_client_dpi_scaling(hwnd);
+  }
+  FreeLibrary(user32_module);
+}
+
+}  // namespace
+
+// Manages the Win32Window's window class registration.
+class WindowClassRegistrar {
+ public:
+  ~WindowClassRegistrar() = default;
+
+  // Returns the singleton registrar instance.
+  static WindowClassRegistrar* GetInstance() {
+    if (!instance_) {
+      instance_ = new WindowClassRegistrar();
+    }
+    return instance_;
+  }
+
+  // Returns the name of the window class, registering the class if it hasn't
+  // previously been registered.
+  const wchar_t* GetWindowClass();
+
+  // Unregisters the window class. Should only be called if there are no
+  // instances of the window.
+  void UnregisterWindowClass();
+
+ private:
+  WindowClassRegistrar() = default;
+
+  static WindowClassRegistrar* instance_;
+
+  bool class_registered_ = false;
+};
+
+WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
+
+const wchar_t* WindowClassRegistrar::GetWindowClass() {
+  if (!class_registered_) {
+    WNDCLASS window_class{};
+    window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+    window_class.lpszClassName = kWindowClassName;
+    window_class.style = CS_HREDRAW | CS_VREDRAW;
+    window_class.cbClsExtra = 0;
+    window_class.cbWndExtra = 0;
+    window_class.hInstance = GetModuleHandle(nullptr);
+    window_class.hIcon =
+        LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
+    window_class.hbrBackground = 0;
+    window_class.lpszMenuName = nullptr;
+    window_class.lpfnWndProc = Win32Window::WndProc;
+    RegisterClass(&window_class);
+    class_registered_ = true;
+  }
+  return kWindowClassName;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass() {
+  UnregisterClass(kWindowClassName, nullptr);
+  class_registered_ = false;
+}
+
+Win32Window::Win32Window() {
+  ++g_active_window_count;
+}
+
+Win32Window::~Win32Window() {
+  --g_active_window_count;
+  Destroy();
+}
+
+bool Win32Window::Create(const std::wstring& title,
+                         const Point& origin,
+                         const Size& size) {
+  Destroy();
+
+  const wchar_t* window_class =
+      WindowClassRegistrar::GetInstance()->GetWindowClass();
+
+  const POINT target_point = {static_cast<LONG>(origin.x),
+                              static_cast<LONG>(origin.y)};
+  HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
+  UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
+  double scale_factor = dpi / 96.0;
+
+  HWND window = CreateWindow(
+      window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
+      Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
+      Scale(size.width, scale_factor), Scale(size.height, scale_factor),
+      nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+  if (!window) {
+    return false;
+  }
+
+  UpdateTheme(window);
+
+  return OnCreate();
+}
+
+bool Win32Window::Show() {
+  return ShowWindow(window_handle_, SW_SHOWNORMAL);
+}
+
+// static
+LRESULT CALLBACK Win32Window::WndProc(HWND const window,
+                                      UINT const message,
+                                      WPARAM const wparam,
+                                      LPARAM const lparam) noexcept {
+  if (message == WM_NCCREATE) {
+    auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
+    SetWindowLongPtr(window, GWLP_USERDATA,
+                     reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
+
+    auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
+    EnableFullDpiSupportIfAvailable(window);
+    that->window_handle_ = window;
+  } else if (Win32Window* that = GetThisFromHandle(window)) {
+    return that->MessageHandler(window, message, wparam, lparam);
+  }
+
+  return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd,
+                            UINT const message,
+                            WPARAM const wparam,
+                            LPARAM const lparam) noexcept {
+  switch (message) {
+    case WM_DESTROY:
+      window_handle_ = nullptr;
+      Destroy();
+      if (quit_on_close_) {
+        PostQuitMessage(0);
+      }
+      return 0;
+
+    case WM_DPICHANGED: {
+      auto newRectSize = reinterpret_cast<RECT*>(lparam);
+      LONG newWidth = newRectSize->right - newRectSize->left;
+      LONG newHeight = newRectSize->bottom - newRectSize->top;
+
+      SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
+                   newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
+
+      return 0;
+    }
+    case WM_SIZE: {
+      RECT rect = GetClientArea();
+      if (child_content_ != nullptr) {
+        // Size and position the child window.
+        MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
+                   rect.bottom - rect.top, TRUE);
+      }
+      return 0;
+    }
+
+    case WM_ACTIVATE:
+      if (child_content_ != nullptr) {
+        SetFocus(child_content_);
+      }
+      return 0;
+
+    case WM_DWMCOLORIZATIONCOLORCHANGED:
+      UpdateTheme(hwnd);
+      return 0;
+  }
+
+  return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy() {
+  OnDestroy();
+
+  if (window_handle_) {
+    DestroyWindow(window_handle_);
+    window_handle_ = nullptr;
+  }
+  if (g_active_window_count == 0) {
+    WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
+  }
+}
+
+Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
+  return reinterpret_cast<Win32Window*>(
+      GetWindowLongPtr(window, GWLP_USERDATA));
+}
+
+void Win32Window::SetChildContent(HWND content) {
+  child_content_ = content;
+  SetParent(content, window_handle_);
+  RECT frame = GetClientArea();
+
+  MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+             frame.bottom - frame.top, true);
+
+  SetFocus(child_content_);
+}
+
+RECT Win32Window::GetClientArea() {
+  RECT frame;
+  GetClientRect(window_handle_, &frame);
+  return frame;
+}
+
+HWND Win32Window::GetHandle() {
+  return window_handle_;
+}
+
+void Win32Window::SetQuitOnClose(bool quit_on_close) {
+  quit_on_close_ = quit_on_close;
+}
+
+bool Win32Window::OnCreate() {
+  // No-op; provided for subclasses.
+  return true;
+}
+
+void Win32Window::OnDestroy() {
+  // No-op; provided for subclasses.
+}
+
+void Win32Window::UpdateTheme(HWND const window) {
+  DWORD light_mode;
+  DWORD light_mode_size = sizeof(light_mode);
+  LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
+                               kGetPreferredBrightnessRegValue,
+                               RRF_RT_REG_DWORD, nullptr, &light_mode,
+                               &light_mode_size);
+
+  if (result == ERROR_SUCCESS) {
+    BOOL enable_dark_mode = light_mode == 0;
+    DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
+                          &enable_dark_mode, sizeof(enable_dark_mode));
+  }
+}
diff --git a/filcnaplo/windows/runner/win32_window.h b/filcnaplo/windows/runner/win32_window.h
new file mode 100644
index 0000000..e901dde
--- /dev/null
+++ b/filcnaplo/windows/runner/win32_window.h
@@ -0,0 +1,102 @@
+#ifndef RUNNER_WIN32_WINDOW_H_
+#define RUNNER_WIN32_WINDOW_H_
+
+#include <windows.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// rendering and input handling
+class Win32Window {
+ public:
+  struct Point {
+    unsigned int x;
+    unsigned int y;
+    Point(unsigned int x, unsigned int y) : x(x), y(y) {}
+  };
+
+  struct Size {
+    unsigned int width;
+    unsigned int height;
+    Size(unsigned int width, unsigned int height)
+        : width(width), height(height) {}
+  };
+
+  Win32Window();
+  virtual ~Win32Window();
+
+  // Creates a win32 window with |title| that is positioned and sized using
+  // |origin| and |size|. New windows are created on the default monitor. Window
+  // sizes are specified to the OS in physical pixels, hence to ensure a
+  // consistent size this function will scale the inputted width and height as
+  // as appropriate for the default monitor. The window is invisible until
+  // |Show| is called. Returns true if the window was created successfully.
+  bool Create(const std::wstring& title, const Point& origin, const Size& size);
+
+  // Show the current window. Returns true if the window was successfully shown.
+  bool Show();
+
+  // Release OS resources associated with window.
+  void Destroy();
+
+  // Inserts |content| into the window tree.
+  void SetChildContent(HWND content);
+
+  // Returns the backing Window handle to enable clients to set icon and other
+  // window properties. Returns nullptr if the window has been destroyed.
+  HWND GetHandle();
+
+  // If true, closing this window will quit the application.
+  void SetQuitOnClose(bool quit_on_close);
+
+  // Return a RECT representing the bounds of the current client area.
+  RECT GetClientArea();
+
+ protected:
+  // Processes and route salient window messages for mouse handling,
+  // size change and DPI. Delegates handling of these to member overloads that
+  // inheriting classes can handle.
+  virtual LRESULT MessageHandler(HWND window,
+                                 UINT const message,
+                                 WPARAM const wparam,
+                                 LPARAM const lparam) noexcept;
+
+  // Called when CreateAndShow is called, allowing subclass window-related
+  // setup. Subclasses should return false if setup fails.
+  virtual bool OnCreate();
+
+  // Called when Destroy is called.
+  virtual void OnDestroy();
+
+ private:
+  friend class WindowClassRegistrar;
+
+  // OS callback called by message pump. Handles the WM_NCCREATE message which
+  // is passed when the non-client area is being created and enables automatic
+  // non-client DPI scaling so that the non-client area automatically
+  // responds to changes in DPI. All other messages are handled by
+  // MessageHandler.
+  static LRESULT CALLBACK WndProc(HWND const window,
+                                  UINT const message,
+                                  WPARAM const wparam,
+                                  LPARAM const lparam) noexcept;
+
+  // Retrieves a class instance pointer for |window|
+  static Win32Window* GetThisFromHandle(HWND const window) noexcept;
+
+  // Update the window frame's theme to match the system theme.
+  static void UpdateTheme(HWND const window);
+
+  bool quit_on_close_ = false;
+
+  // window handle for top level window.
+  HWND window_handle_ = nullptr;
+
+  // window handle for hosted content.
+  HWND child_content_ = nullptr;
+};
+
+#endif  // RUNNER_WIN32_WINDOW_H_
diff --git a/filcnaplo_desktop_ui/lib/pages/home/home_page.dart b/filcnaplo_desktop_ui/lib/pages/home/home_page.dart
index d0cc653..edfc433 100644
--- a/filcnaplo_desktop_ui/lib/pages/home/home_page.dart
+++ b/filcnaplo_desktop_ui/lib/pages/home/home_page.dart
@@ -1,7 +1,7 @@
 import 'package:filcnaplo/api/providers/user_provider.dart';
 import 'package:filcnaplo/models/settings.dart';
 import 'package:filcnaplo/ui/date_widget.dart';
-import 'package:filcnaplo_desktop_ui/common/filter_bar.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';
@@ -16,7 +16,8 @@ class HomePage extends StatefulWidget {
   State<HomePage> createState() => _HomePageState();
 }
 
-class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
+class _HomePageState extends State<HomePage>
+    with SingleTickerProviderStateMixin {
   late UserProvider user;
   late SettingsProvider settings;
 
@@ -41,11 +42,15 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
     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))) {
+    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) {
+    } 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) {
+    } 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";
@@ -81,7 +86,8 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
               children: [
                 // Greeting
                 Padding(
-                  padding: const EdgeInsets.only(left: 32.0, top: 24.0, bottom: 12.0),
+                  padding: const EdgeInsets.only(
+                      left: 32.0, top: 24.0, bottom: 12.0),
                   child: Text(
                     greeting.i18n.fill([firstName]),
                     overflow: TextOverflow.fade,
@@ -107,8 +113,10 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
                       int selectedPage = _pageController.page!.round();
 
                       if (i == selectedPage) return;
-                      if (_pageController.page?.roundToDouble() != _pageController.page) {
-                        _pageController.animateToPage(i, curve: Curves.easeIn, duration: kTabScrollDuration);
+                      if (_pageController.page?.roundToDouble() !=
+                          _pageController.page) {
+                        _pageController.animateToPage(i,
+                            curve: Curves.easeIn, duration: kTabScrollDuration);
                         return;
                       }
 
@@ -132,27 +140,34 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
                       (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
+                          future: getFilterWidgets(homeFilters[index],
+                              context: context),
+                          builder: (context, dateWidgets) => dateWidgets.data !=
+                                  null
                               ? ImplicitlyAnimatedList<Widget>(
-                                  items: sortDateWidgets(context, dateWidgets: dateWidgets.data!),
+                                  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),
+                                  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 ValueKey<String> valueKey =
+                            key as ValueKey<String>;
                         final String data = valueKey.value;
                         return listOrder.indexOf(data);
                       },
                     ),
-                    physics: const PageScrollPhysics().applyTo(const BouncingScrollPhysics()),
+                    physics: const PageScrollPhysics()
+                        .applyTo(const BouncingScrollPhysics()),
                   ),
                 ),
               ],
diff --git a/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart b/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart
index b673689..8d6e5fb 100644
--- a/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart
+++ b/filcnaplo_desktop_ui/lib/pages/timetable/timetable_page.dart
@@ -23,12 +23,14 @@ 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);
+  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}) {
+  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,
@@ -49,7 +51,8 @@ class TimetablePage extends StatefulWidget {
   _TimetablePageState createState() => _TimetablePageState();
 }
 
-class _TimetablePageState extends State<TimetablePage> with TickerProviderStateMixin {
+class _TimetablePageState extends State<TimetablePage>
+    with TickerProviderStateMixin {
   late UserProvider user;
   late TimetableProvider timetableProvider;
   late UpdateProvider updateProvider;
@@ -60,7 +63,9 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
 
   int _getDayIndex(DateTime date) {
     int index = 0;
-    if (_controller.days == null || (_controller.days?.isEmpty ?? true)) return index;
+    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));
@@ -94,11 +99,14 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
         _tabController = TabController(
           length: _controller.days!.length,
           vsync: this,
-          initialIndex: min(_tabController.index, max(_controller.days!.length - 1, 0)),
+          initialIndex:
+              min(_tabController.index, max(_controller.days!.length - 1, 0)),
         );
 
-        if (initial || _controller.previousWeekId != _controller.currentWeekId) {
-          _tabController.animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
+        if (initial ||
+            _controller.previousWeekId != _controller.currentWeekId) {
+          _tabController
+              .animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
         }
         initial = false;
 
@@ -111,7 +119,8 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
       if (widget.initialWeek != null) {
         _controller.jump(widget.initialWeek!, context: context, initial: true);
       } else {
-        _controller.jump(_controller.currentWeek, context: context, initial: true, skip: true);
+        _controller.jump(_controller.currentWeek,
+            context: context, initial: true, skip: true);
       }
     }
     // Listen for user changes
@@ -131,7 +140,8 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
     // 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);
+      return DateFormat("EEEE", I18n.of(context).locale.languageCode)
+          .format(_controller.days![index].first.date);
     } catch (e) {
       return "timetable".i18n;
     }
@@ -181,9 +191,14 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
                                   children: [
                                     // Day Title
                                     Padding(
-                                      padding: const EdgeInsets.only(left: 24.0, right: 28.0, top: 18.0, bottom: 8.0),
+                                      padding: const EdgeInsets.only(
+                                          left: 24.0,
+                                          right: 28.0,
+                                          top: 18.0,
+                                          bottom: 8.0),
                                       child: Row(
-                                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                                        mainAxisAlignment:
+                                            MainAxisAlignment.spaceBetween,
                                         children: [
                                           Text(
                                             dayTitle(tab).capital(),
@@ -193,9 +208,13 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
                                             ),
                                           ),
                                           Text(
-                                            "${_controller.days![tab].first.date.day}".padLeft(2, '0') + ".",
+                                            "${_controller.days![tab].first.date.day}"
+                                                    .padLeft(2, '0') +
+                                                ".",
                                             style: TextStyle(
-                                              color: AppColors.of(context).text.withOpacity(.5),
+                                              color: AppColors.of(context)
+                                                  .text
+                                                  .withOpacity(.5),
                                               fontWeight: FontWeight.w500,
                                             ),
                                           ),
@@ -208,35 +227,59 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
                                       child: ListView.builder(
                                         padding: EdgeInsets.zero,
                                         physics: const BouncingScrollPhysics(),
-                                        itemCount: _controller.days![tab].length + 2,
+                                        itemCount:
+                                            _controller.days![tab].length + 2,
                                         itemBuilder: (context, index) {
-                                          if (_controller.days == null) return Container();
+                                          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)),
+                                              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) {
+                                          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)),
+                                              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;
+                                          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),
+                                            padding: const EdgeInsets.symmetric(
+                                                horizontal: 24.0),
                                             child: PanelBody(
-                                              padding: const EdgeInsets.symmetric(horizontal: 10.0),
+                                              padding:
+                                                  const EdgeInsets.symmetric(
+                                                      horizontal: 10.0),
                                               child: LessonViewable(
                                                 lesson,
                                                 swapDesc: swapDescDay,
@@ -264,7 +307,8 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
               ),
             ),
             Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
+              padding:
+                  const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
               child: Row(
                 mainAxisAlignment: MainAxisAlignment.spaceBetween,
                 children: [
@@ -285,7 +329,10 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
                     onTap: () => setState(() {
                       _controller.current();
                       if (mounted) {
-                        _controller.jump(_controller.currentWeek, context: context, loader: _controller.currentWeekId != _controller.previousWeekId);
+                        _controller.jump(_controller.currentWeek,
+                            context: context,
+                            loader: _controller.currentWeekId !=
+                                _controller.previousWeekId);
                       }
                     }),
                     child: Padding(
@@ -295,12 +342,22 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
                             "week".i18n +
                             " (" +
                             // Week start
-                            DateFormat((_controller.currentWeek.start.year != DateTime.now().year ? "yy. " : "") + "MMM d.",
+                            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.",
+                            DateFormat(
+                                    (_controller.currentWeek.start.year !=
+                                                DateTime.now().year
+                                            ? "yy. "
+                                            : "") +
+                                        "MMM d.",
                                     I18n.of(context).locale.languageCode)
                                 .format(_controller.currentWeek.end) +
                             ")",
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart b/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
index 0815557..1c0f5fa 100644
--- a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
+++ b/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.dart
@@ -6,6 +6,7 @@ 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';
@@ -25,7 +26,12 @@ 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);
+  const Sidebar(
+      {Key? key,
+      required this.navigator,
+      required this.onRouteChange,
+      this.selected = "home"})
+      : super(key: key);
 
   final NavigatorState navigator;
   final String selected;
@@ -71,12 +77,12 @@ class _SidebarState extends State<Sidebar> {
     if (!settings.presentationMode) {
       firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
     } else {
-      firstName = "Béla";
+      firstName = "János";
     }
 
     List<Widget> pageWidgets = [
       SidebarAction(
-        title: const Text("Home"),
+        title: Text("Home".i18n),
         icon: const Icon(FilcIcons.home),
         selected: widget.selected == "home",
         onTap: () {
@@ -87,7 +93,7 @@ class _SidebarState extends State<Sidebar> {
         },
       ),
       SidebarAction(
-        title: const Text("Grades"),
+        title: Text("Grades".i18n),
         icon: const Icon(FeatherIcons.bookmark),
         selected: widget.selected == "grades",
         onTap: () {
@@ -98,7 +104,7 @@ class _SidebarState extends State<Sidebar> {
         },
       ),
       SidebarAction(
-        title: const Text("Timetable"),
+        title: Text("Timetable".i18n),
         icon: const Icon(FeatherIcons.calendar),
         selected: widget.selected == "timetable",
         onTap: () {
@@ -109,7 +115,7 @@ class _SidebarState extends State<Sidebar> {
         },
       ),
       SidebarAction(
-        title: const Text("Messages"),
+        title: Text("Messages".i18n),
         icon: const Icon(FeatherIcons.messageSquare),
         selected: widget.selected == "messages",
         onTap: () {
@@ -120,7 +126,7 @@ class _SidebarState extends State<Sidebar> {
         },
       ),
       SidebarAction(
-        title: const Text("Absences"),
+        title: Text("Absences".i18n),
         icon: const Icon(FeatherIcons.clock),
         selected: widget.selected == "absences",
         onTap: () {
@@ -134,12 +140,15 @@ class _SidebarState extends State<Sidebar> {
 
     List<Widget> bottomActions = [
       SidebarAction(
-        title: const Text("Settings"),
+        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 = "");
+            widget.navigator
+                .push(CupertinoPageRoute(
+                    builder: (context) => const SettingsScreen()))
+                .then((value) => topNav = "");
             topNav = "settings";
           }
         },
@@ -159,7 +168,7 @@ class _SidebarState extends State<Sidebar> {
         onPressed: () {
           Navigator.of(context).pushNamed("login_back");
         },
-        title: const Text("Add User"),
+        title: Text("adduser".i18n),
         leading: const Icon(FeatherIcons.userPlus),
       ),
       PanelButton(
@@ -169,17 +178,20 @@ class _SidebarState extends State<Sidebar> {
 
           // Delete User
           user.removeUser(userId);
-          await Provider.of<DatabaseProvider>(context, listen: false).store.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);
+            Navigator.of(context)
+                .pushNamedAndRemoveUntil("login", (_) => false);
           }
         },
-        title: const Text("Log Out"),
+        title: Text("logout".i18n),
         leading: Icon(FeatherIcons.logOut, color: AppColors.of(context).red),
       ),
     ];
@@ -190,49 +202,77 @@ class _SidebarState extends State<Sidebar> {
       child: Column(
         children: [
           Padding(
-            padding: const EdgeInsets.only(left: 18.0, top: 18.0, bottom: 24.0, right: 8.0),
-            child: Row(
-              children: [
-                Padding(
-                  padding: const EdgeInsets.only(right: 12.0),
-                  child: ProfileImage(
-                    name: firstName,
-                    radius: 18.0,
-                    backgroundColor:
-                        !settings.presentationMode ? ColorUtils.stringToColor(user.name ?? "?") : Theme.of(context).colorScheme.secondary,
-                  ),
-                ),
-                Expanded(
-                  child: Text(
-                    firstName,
-                    style: const TextStyle(
-                      fontSize: 16.0,
-                      fontWeight: FontWeight.w600,
+            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,
                     ),
                   ),
-                ),
-                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,
-                    splashRadius: 20.0,
-                    onPressed: () {
-                      setState(() {
-                        expandAccount = !expandAccount;
-                      });
-                    },
+                  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),
+                    ),
+                  ),
+                ],
+              ),
             ),
           ),
 
@@ -282,15 +322,19 @@ class _SidebarState extends State<Sidebar> {
       if (!settings.presentationMode) {
         _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
       } else {
-        _firstName = "Béla";
+        _firstName = "János";
       }
 
       accountTiles.add(AccountTile(
-        name: Text(!settings.presentationMode ? account.name : "Béla", style: const TextStyle(fontWeight: FontWeight.w500)),
-        username: Text(!settings.presentationMode ? account.username : "72469696969"),
+        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,
+          backgroundColor: !settings.presentationMode
+              ? ColorUtils.stringToColor(account.name)
+              : Theme.of(context).colorScheme.secondary,
           role: account.role,
         ),
         onTap: () {
diff --git a/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.i18n.dart b/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.i18n.dart
new file mode 100644
index 0000000..43cfb8a
--- /dev/null
+++ b/filcnaplo_desktop_ui/lib/screens/navigation/sidebar.i18n.dart
@@ -0,0 +1,42 @@
+import 'package:i18n_extension/i18n_extension.dart';
+
+extension SettingsLocalization on String {
+  static final _t = Translations.byLocale("hu_hu") +
+      {
+        "en_en": {
+          "Home": "Home",
+          "Grades": "Grades",
+          "Timetable": "Timetable",
+          "Messages": "Messages",
+          "Absences": "Absences",
+          "Settings": "Settings",
+          "adduser": "Add User",
+          "logout": "Log Out",
+        },
+        "hu_hu": {
+          "Home": "Kezdőlap",
+          "Grades": "Jegyek",
+          "Timetable": "Órarend",
+          "Messages": "Üzenetek",
+          "Absences": "Hiányzások",
+          "Settings": "Beállítások",
+          "adduser": "Fiók hozzáadása",
+          "logout": "Kilépés",
+        },
+        "de_de": {
+          "Home": "Zuhause",
+          "Grades": "Noten",
+          "Timetable": "Zeitplan",
+          "Messages": "Mitteilungen",
+          "Absences": "Fehlen",
+          "Settings": "Einstellungen",
+          "adduser": "Benutzer hinzufügen",
+          "logout": "Abmelden",
+        },
+      };
+
+  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/settings/settings_screen.dart b/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.dart
index 83504f6..aef41ff 100644
--- a/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.dart
+++ b/filcnaplo_desktop_ui/lib/screens/settings/settings_screen.dart
@@ -35,6 +35,7 @@ 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';
@@ -86,11 +87,11 @@ class _SettingsScreenState extends State<SettingsScreen>
       if (!settings.presentationMode) {
         _firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
       } else {
-        _firstName = "Béla";
+        _firstName = "János";
       }
 
       accountTiles.add(AccountTile(
-        name: Text(!settings.presentationMode ? account.name : "Béla",
+        name: Text(!settings.presentationMode ? account.name : "János",
             style: const TextStyle(fontWeight: FontWeight.w500)),
         username:
             Text(!settings.presentationMode ? account.username : "72469696969"),
@@ -164,7 +165,7 @@ class _SettingsScreenState extends State<SettingsScreen>
     if (!settings.presentationMode) {
       firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
     } else {
-      firstName = "Béla";
+      firstName = "János";
     }
 
     String startPageTitle =
@@ -206,307 +207,403 @@ class _SettingsScreenState extends State<SettingsScreen>
                 animation: _hideContainersController,
                 builder: (context, child) => Opacity(
                   opacity: 1 - _hideContainersController.value,
-                  child: SingleChildScrollView(
-                    child: Column(
-                      children: [
-                        const SizedBox(height: 32.0),
+                  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)
-                          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
-                        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)
-                          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)
-                                                            .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
-                        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],
-                                        ),
+                          // 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,
                                       ),
                                     ),
                                   ),
                                 ),
-                                Material(
+                              ),
+                            ),
+
+                          // 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:
@@ -517,8 +614,8 @@ class _SettingsScreenState extends State<SettingsScreen>
                                     title: Row(
                                       children: [
                                         Icon(
-                                          FeatherIcons.barChart,
-                                          color: settings.graphClassAvg
+                                          Icons.newspaper_outlined,
+                                          color: settings.newsEnabled
                                               ? Theme.of(context)
                                                   .colorScheme
                                                   .secondary
@@ -529,14 +626,14 @@ class _SettingsScreenState extends State<SettingsScreen>
                                         const SizedBox(width: 24.0),
                                         Expanded(
                                           child: Text(
-                                            "graph_class_avg".i18n,
+                                            "news".i18n,
                                             style: TextStyle(
                                               fontWeight: FontWeight.w600,
                                               fontSize: 16.0,
                                               color: AppColors.of(context)
                                                   .text
                                                   .withOpacity(
-                                                      settings.graphClassAvg
+                                                      settings.newsEnabled
                                                           ? 1.0
                                                           : .5),
                                             ),
@@ -545,252 +642,25 @@ class _SettingsScreenState extends State<SettingsScreen>
                                       ],
                                     ),
                                     onChanged: (v) =>
-                                        settings.update(graphClassAvg: v),
-                                    value: settings.graphClassAvg,
-                                    activeColor:
-                                        Theme.of(context).colorScheme.secondary,
-                                  ),
-                                ),
-                                const PremiumIconPackSelector(),
-                              ],
-                            ),
-                          ),
-                        ),
-
-                        // Notifications
-                        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
-                        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
-                        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",
+                                        settings.update(newsEnabled: v),
+                                    value: settings.newsEnabled,
                                     activeColor:
                                         Theme.of(context).colorScheme.secondary,
                                   ),
                                 ),
                               ),
-                            ]),
+                            ),
                           ),
-                        ),
-                        if (settings.developerMode)
-                          Padding(
-                            padding: const EdgeInsets.symmetric(
-                                vertical: 12.0, horizontal: 24.0),
-                            child: Panel(
-                              title: const Text("Developer Settings"),
-                              child: Column(
-                                children: [
+
+                          // 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(
@@ -799,88 +669,280 @@ class _SettingsScreenState extends State<SettingsScreen>
                                       shape: RoundedRectangleBorder(
                                           borderRadius:
                                               BorderRadius.circular(12.0)),
-                                      title: const Text("Developer Mode",
-                                          style: TextStyle(
-                                              fontWeight: FontWeight.w500)),
+                                      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(developerMode: false),
-                                      value: settings.developerMode,
+                                          settings.update(gradeOpeningFun: v),
+                                      value: settings.gradeOpeningFun,
                                       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);
-                                      },
-                                    ),
-                                ],
+                                ]),
                               ),
                             ),
                           ),
-                        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--);
-                                }
-                              },
+                          // 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--);
+                              }
+                            },
+                          ),
                         ),
-                      ],
-                    ),
+                      ),
+                    ],
                   ),
                 ),
               ),
-            )
+            ),
           ],
         ),
       ),
diff --git a/filcnaplo_desktop_ui/pubspec.yaml b/filcnaplo_desktop_ui/pubspec.yaml
index 676f882..2a1645a 100644
--- a/filcnaplo_desktop_ui/pubspec.yaml
+++ b/filcnaplo_desktop_ui/pubspec.yaml
@@ -25,6 +25,7 @@ dependencies:
   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
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart b/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
index 9207f72..8ba3974 100755
--- a/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
+++ b/filcnaplo_mobile_ui/lib/common/widgets/absence_group/absence_group_tile.dart
@@ -8,7 +8,9 @@ import 'package:flutter/material.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);
+  const AbsenceGroupTile(this.absences,
+      {Key? key, this.showDate = false, this.padding})
+      : super(key: key);
 
   final List<AbsenceViewable> absences;
   final bool showDate;
@@ -16,10 +18,12 @@ class AbsenceGroupTile extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    Justification state = getState(absences.map((e) => e.absence.state).toList());
+    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);
+    absences.sort((a, b) =>
+        a.absence.lessonIndex?.compareTo(b.absence.lessonIndex ?? 0) ?? -1);
 
     return ClipRRect(
       borderRadius: BorderRadius.circular(14.0),
@@ -29,6 +33,8 @@ class AbsenceGroupTile extends StatelessWidget {
           padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
           child: AbsenceGroupContainer(
             child: ExpansionTile(
+              shape: RoundedRectangleBorder(
+                  borderRadius: BorderRadius.circular(10)),
               tilePadding: const EdgeInsets.symmetric(horizontal: 8.0),
               backgroundColor: Colors.transparent,
               leading: Container(
@@ -38,22 +44,33 @@ class AbsenceGroupTile extends StatelessWidget {
                   shape: BoxShape.circle,
                   color: color.withOpacity(.25),
                 ),
-                child: Center(child: Icon(AbsenceTile.justificationIcon(state), color: color)),
+                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),
+                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),
+                    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)),
+                      absences.first.absence.date
+                          .format(context, weekday: true),
+                      style: TextStyle(
+                          fontWeight: FontWeight.w500,
+                          color: AppColors.of(context).text.withOpacity(0.8)),
                     )
                   : null,
               children: absences,