diff --git a/app/build.gradle b/app/build.gradle
index 621eea77..7aafa75a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -94,7 +94,7 @@ dependencies {
 
     implementation "androidx.cardview:cardview:1.0.0"
     implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
-    implementation "com.google.android.material:material:1.0.0"
+    implementation "com.google.android.material:material:1.1.0-alpha05"
     implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f'
     implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
 
@@ -124,7 +124,7 @@ dependencies {
     implementation "com.jakewharton.threetenabp:threetenabp:1.2.0"
     implementation "com.jakewharton.timber:timber:4.7.1"
     implementation "at.favre.lib:slf4j-timber:1.0.1"
-    implementation "com.squareup.okhttp3:logging-interceptor:3.14.1"
+    implementation "com.squareup.okhttp3:logging-interceptor:3.12.1"
 
     implementation "com.mikepenz:aboutlibraries:6.2.3"
     implementation 'com.takisoft.preferencex:preferencex:1.0.0'
diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
index 5ff9b3d4..5f592078 100644
--- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
+++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
@@ -1,7 +1,6 @@
 package io.github.wulkanowy
 
 import android.content.Context
-import androidx.appcompat.app.AppCompatDelegate
 import androidx.multidex.MultiDex
 import androidx.work.Configuration
 import androidx.work.WorkManager
@@ -13,8 +12,8 @@ import dagger.android.support.DaggerApplication
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.davidea.flexibleadapter.utils.Log
 import io.fabric.sdk.android.Fabric
+import io.github.wulkanowy.BuildConfig.CRASHLYTICS_ENABLED
 import io.github.wulkanowy.BuildConfig.DEBUG
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
 import io.github.wulkanowy.di.DaggerAppComponent
 import io.github.wulkanowy.services.sync.SyncWorkerFactory
 import io.github.wulkanowy.utils.CrashlyticsTree
@@ -27,9 +26,6 @@ import javax.inject.Inject
 
 class WulkanowyApp : DaggerApplication() {
 
-    @Inject
-    lateinit var prefRepository: PreferencesRepository
-
     @Inject
     lateinit var workerFactory: SyncWorkerFactory
 
@@ -41,29 +37,32 @@ class WulkanowyApp : DaggerApplication() {
     override fun onCreate() {
         super.onCreate()
         AndroidThreeTen.init(this)
-        initializeFabric()
-        if (DEBUG) enableDebugLog()
-        AppCompatDelegate.setDefaultNightMode(prefRepository.currentTheme)
         WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(workerFactory).build())
         RxJavaPlugins.setErrorHandler(::onError)
+
+        initCrashlytics()
+        initLogging()
     }
 
-    private fun enableDebugLog() {
-        Timber.plant(DebugLogTree())
-        FlexibleAdapter.enableLogs(Log.Level.DEBUG)
+    private fun initLogging() {
+        if (DEBUG) {
+            Timber.plant(DebugLogTree())
+            FlexibleAdapter.enableLogs(Log.Level.DEBUG)
+        } else {
+            Timber.plant(CrashlyticsTree())
+        }
     }
 
-    private fun initializeFabric() {
+    private fun initCrashlytics() {
         Fabric.with(Fabric.Builder(this).kits(
-            Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(!BuildConfig.CRASHLYTICS_ENABLED).build()).build()
+            Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(!CRASHLYTICS_ENABLED).build()).build()
         ).debuggable(DEBUG).build())
-        Timber.plant(CrashlyticsTree())
     }
 
-    private fun onError(t: Throwable) {
-        if (t is UndeliverableException && t.cause is IOException || t.cause is InterruptedException) {
-            Timber.e(t.cause, "An undeliverable error occurred")
-        } else throw t
+    private fun onError(error: Throwable) {
+        if (error is UndeliverableException && error.cause is IOException || error.cause is InterruptedException) {
+            Timber.e(error.cause, "An undeliverable error occurred")
+        } else throw error
     }
 
     override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
index b29e5143..91717ed7 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
@@ -23,9 +23,9 @@ class PreferencesRepository @Inject constructor(
     val isGradeExpandable: Boolean
         get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false)
 
-    val currentThemeKey: String = context.getString(R.string.pref_key_theme)
-    val currentTheme: Int
-        get() = sharedPref.getString(currentThemeKey, "1")?.toIntOrNull() ?: 1
+    val appThemeKey: String = context.getString(R.string.pref_key_app_theme)
+    val appTheme: String
+        get() = sharedPref.getString(appThemeKey, "light") ?: "light"
 
     val gradeColorTheme: String
         get() = sharedPref.getString(context.getString(R.string.pref_key_grade_color_scheme), "vulcan") ?: "vulcan"
diff --git a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
index eb3b18f9..b8e1249e 100644
--- a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
@@ -34,7 +34,7 @@ internal class AppModule {
 
     @Singleton
     @Provides
-    fun provideAppWidgetManager(context: Context) = AppWidgetManager.getInstance(context)
+    fun provideAppWidgetManager(context: Context): AppWidgetManager = AppWidgetManager.getInstance(context)
 
     @Singleton
     @Named("isDebug")
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt
index ca7aaac6..6f57063f 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt
@@ -48,8 +48,7 @@ class LuckyNumberWork @Inject constructor(
             .setColor(context.getCompatColor(R.color.colorPrimary))
             .setContentIntent(
                 PendingIntent.getActivity(context, 0,
-                    MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU_INDEX, 4), FLAG_UPDATE_CURRENT)
-            )
+                    MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU_INDEX, 4), FLAG_UPDATE_CURRENT))
             .build())
     }
 }
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
index 7ab2c8d4..7250544b 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
@@ -48,8 +48,8 @@ class MessageWork @Inject constructor(
             .setPriority(PRIORITY_HIGH)
             .setColor(context.getCompatColor(R.color.colorPrimary))
             .setContentIntent(
-                PendingIntent.getActivity(context, 0,
-                    MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU_INDEX, 4), FLAG_UPDATE_CURRENT)
+                PendingIntent.getActivity(context, 0, MainActivity.getStartIntent(context)
+                    .putExtra(EXTRA_START_MENU_INDEX, 4), FLAG_UPDATE_CURRENT)
             )
             .setStyle(NotificationCompat.InboxStyle().run {
                 setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size))
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt
index d0e8fe21..a9567f5a 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt
@@ -48,8 +48,7 @@ class NoteWork @Inject constructor(
             .setColor(context.getCompatColor(R.color.colorPrimary))
             .setContentIntent(
                 PendingIntent.getActivity(context, 0,
-                    MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU_INDEX, 4), FLAG_UPDATE_CURRENT)
-            )
+                    MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU_INDEX, 4), FLAG_UPDATE_CURRENT))
             .setStyle(NotificationCompat.InboxStyle().run {
                 setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size))
                 notes.forEach { addLine("${it.teacher}: ${it.category}") }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
index f227dc19..64c804a2 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt
@@ -2,17 +2,30 @@ package io.github.wulkanowy.ui.base
 
 import android.os.Bundle
 import android.view.View
+import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.app.AppCompatDelegate
+import androidx.fragment.app.Fragment
 import com.google.android.material.snackbar.Snackbar
 import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
-import dagger.android.support.DaggerAppCompatActivity
+import dagger.android.AndroidInjection
+import dagger.android.DispatchingAndroidInjector
+import dagger.android.support.HasSupportFragmentInjector
 import io.github.wulkanowy.R
+import javax.inject.Inject
 
-abstract class BaseActivity : DaggerAppCompatActivity(), BaseView {
+abstract class BaseActivity : AppCompatActivity(), BaseView, HasSupportFragmentInjector {
+
+    @Inject
+    lateinit var supportFragmentInjector: DispatchingAndroidInjector<Fragment>
+
+    @Inject
+    lateinit var themeManager: ThemeManager
 
     protected lateinit var messageContainer: View
 
     public override fun onCreate(savedInstanceState: Bundle?) {
+        AndroidInjection.inject(this)
+        themeManager.applyTheme(this)
         super.onCreate(savedInstanceState)
         AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
     }
@@ -31,4 +44,6 @@ abstract class BaseActivity : DaggerAppCompatActivity(), BaseView {
         super.onDestroy()
         invalidateOptionsMenu()
     }
+
+    override fun supportFragmentInjector() = supportFragmentInjector
 }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
new file mode 100644
index 00000000..becb923c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
@@ -0,0 +1,24 @@
+package io.github.wulkanowy.ui.base
+
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
+import io.github.wulkanowy.R
+import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import javax.inject.Inject
+
+class ThemeManager @Inject constructor(private val preferencesRepository: PreferencesRepository) {
+
+    fun applyTheme(activity: AppCompatActivity) {
+        activity.delegate.apply {
+            when (preferencesRepository.appTheme) {
+                "light" -> setLocalNightMode(MODE_NIGHT_NO)
+                "dark" -> setLocalNightMode(MODE_NIGHT_YES)
+                "black" -> {
+                    setLocalNightMode(MODE_NIGHT_YES)
+                    activity.setTheme(R.style.WulkanowyTheme_Black)
+                }
+            }
+        }
+    }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
index f0cab7f1..7170f608 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
@@ -77,12 +77,12 @@ class AttendanceFragment : BaseSessionFragment(), AttendanceView, MainView.MainC
         attendanceNextButton.setOnClickListener { presenter.onNextDay() }
     }
 
-    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
-        inflater?.inflate(R.menu.action_menu_attendance, menu)
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.action_menu_attendance, menu)
     }
 
-    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
-        return if (item?.itemId == R.id.attendanceMenuSummary) presenter.onSummarySwitchSelected()
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return if (item.itemId == R.id.attendanceMenuSummary) presenter.onSummarySwitchSelected()
         else false
     }
 
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt
index 20d3fad7..11b2de3f 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt
@@ -57,9 +57,9 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView,
         presenter.onAttachView(this, savedInstanceState?.getInt(SAVED_SEMESTER_KEY))
     }
 
-    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
-        inflater?.inflate(R.menu.action_menu_grade, menu)
-        semesterSwitchMenu = menu?.findItem(R.id.gradeMenuSemester)
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.action_menu_grade, menu)
+        semesterSwitchMenu = menu.findItem(R.id.gradeMenuSemester)
         presenter.onCreateMenu()
     }
 
@@ -82,8 +82,8 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView,
         gradeSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
     }
 
-    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
-        return if (item?.itemId == R.id.gradeMenuSemester) presenter.onSemesterSwitch()
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return if (item.itemId == R.id.gradeMenuSemester) presenter.onSemesterSwitch()
         else false
     }
 
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt
index 205cde77..65cd9262 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt
@@ -67,8 +67,8 @@ class GradeDetailsFragment : BaseSessionFragment(), GradeDetailsView, GradeView.
         presenter.onAttachView(this)
     }
 
-    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
-        inflater?.inflate(R.menu.action_menu_grade_details, menu)
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.action_menu_grade_details, menu)
     }
 
     override fun initView() {
@@ -88,8 +88,8 @@ class GradeDetailsFragment : BaseSessionFragment(), GradeDetailsView, GradeView.
         gradeDetailsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
     }
 
-    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
-        return if (item?.itemId == R.id.gradeDetailsMenuRead) presenter.onMarkAsReadSelected()
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return if (item.itemId == R.id.gradeDetailsMenuRead) presenter.onMarkAsReadSelected()
         else false
     }
 
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
index 4448e556..9b49e51c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
@@ -168,7 +168,7 @@ class MainActivity : BaseActivity(), MainView {
             .apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
     }
 
-    override fun onSaveInstanceState(outState: Bundle?) {
+    override fun onSaveInstanceState(outState: Bundle) {
         super.onSaveInstanceState(outState)
         navController.onSaveInstanceState(outState)
     }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
index 4a752401..12765546 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
@@ -64,16 +64,16 @@ class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainVi
         presenter.onAttachView(this, (savedInstanceState ?: arguments)?.getInt(MESSAGE_ID_KEY) ?: 0)
     }
 
-    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
-        inflater?.inflate(R.menu.action_menu_message_preview, menu)
-        menuReplyButton = menu?.findItem(R.id.messagePreviewMenuReply)
-        menuForwardButton = menu?.findItem(R.id.messagePreviewMenuForward)
-        menuDeleteButton = menu?.findItem(R.id.messagePreviewMenuDelete)
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.action_menu_message_preview, menu)
+        menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply)
+        menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward)
+        menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete)
         presenter.onCreateOptionsMenu()
     }
 
-    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
-        return when (item?.itemId) {
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return when (item.itemId) {
             R.id.messagePreviewMenuReply -> presenter.onReply()
             R.id.messagePreviewMenuForward -> presenter.onForward()
             R.id.messagePreviewMenuDelete -> presenter.onMessageDelete()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt
index d82eaba7..2baad0eb 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt
@@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.modules.settings
 import android.content.Context
 import android.content.SharedPreferences
 import android.os.Bundle
-import androidx.appcompat.app.AppCompatDelegate
 import com.takisoft.preferencex.PreferenceFragmentCompat
 import dagger.android.support.AndroidSupportInjection
 import io.github.wulkanowy.BuildConfig.DEBUG
@@ -44,8 +43,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
         presenter.onSharedPreferenceChanged(key)
     }
 
-    override fun setTheme(theme: Int) {
-        AppCompatDelegate.setDefaultNightMode(theme)
+    override fun recreateView() {
         activity?.recreate()
     }
 
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt
index 65e871ea..6deb0a75 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt
@@ -31,8 +31,8 @@ class SettingsPresenter @Inject constructor(
             when (key) {
                 serviceEnableKey -> syncManager.run { if (isServiceEnabled) startSyncWorker() else stopSyncWorker() }
                 servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startSyncWorker(true)
-                currentThemeKey -> view?.setTheme(currentTheme)
                 isDebugNotificationEnableKey -> chuckCollector.showNotification(isDebugNotificationEnable)
+                appThemeKey -> view?.recreateView()
             }
         }
         analytics.logEvent("setting_changed", "name" to key)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt
index 0b3c2f70..1c4bf3b0 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt
@@ -4,7 +4,7 @@ import io.github.wulkanowy.ui.base.BaseView
 
 interface SettingsView : BaseView {
 
-    fun setTheme(theme: Int)
+    fun recreateView()
 
     fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean)
 }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt
index 2bd62533..36d7af50 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt
@@ -3,12 +3,12 @@ package io.github.wulkanowy.ui.modules.splash
 import android.os.Bundle
 import android.widget.Toast
 import android.widget.Toast.LENGTH_LONG
-import io.github.wulkanowy.ui.base.BaseActivity
+import dagger.android.support.DaggerAppCompatActivity
 import io.github.wulkanowy.ui.modules.login.LoginActivity
 import io.github.wulkanowy.ui.modules.main.MainActivity
 import javax.inject.Inject
 
-class SplashActivity : BaseActivity(), SplashView {
+class SplashActivity : DaggerAppCompatActivity(), SplashView {
 
     @Inject
     lateinit var presenter: SplashPresenter
@@ -29,6 +29,10 @@ class SplashActivity : BaseActivity(), SplashView {
     }
 
     override fun showError(text: String, error: Throwable) {
+        showMessage(text)
+    }
+
+    override fun showMessage(text: String) {
         Toast.makeText(this, text, LENGTH_LONG).show()
     }
 
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt
index 3b1259f7..fa6452b7 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt
@@ -80,12 +80,12 @@ class TimetableFragment : BaseSessionFragment(), TimetableView, MainView.MainChi
         timetableNextButton.setOnClickListener { presenter.onNextDay() }
     }
 
-    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
-        inflater?.inflate(R.menu.action_menu_timetable, menu)
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.action_menu_timetable, menu)
     }
 
-    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
-        return if (item?.itemId == R.id.timetableMenuCompletedLessons) presenter.onCompletedLessonsSwitchSelected()
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return if (item.itemId == R.id.timetableMenuCompletedLessons) presenter.onCompletedLessonsSwitchSelected()
         else false
     }
 
diff --git a/app/src/main/res/drawable/ic_login_outlined_border.xml b/app/src/main/res/drawable/ic_login_outlined_border.xml
index 359bea5e..c5d3c686 100644
--- a/app/src/main/res/drawable/ic_login_outlined_border.xml
+++ b/app/src/main/res/drawable/ic_login_outlined_border.xml
@@ -2,7 +2,7 @@
     <solid android:color="@null" />
     <stroke
         android:width="1dip"
-        android:color="#61000000" />
+        android:color="@color/spinner_stroke" />
     <corners android:radius="4dip" />
     <padding
         android:bottom="0dip"
diff --git a/app/src/main/res/layout/fragment_login_form.xml b/app/src/main/res/layout/fragment_login_form.xml
index 34f1f995..553c8726 100644
--- a/app/src/main/res/layout/fragment_login_form.xml
+++ b/app/src/main/res/layout/fragment_login_form.xml
@@ -130,7 +130,7 @@
                 android:layout_marginStart="7dp"
                 android:layout_marginLeft="7dp"
                 android:layout_marginBottom="48dp"
-                android:background="?android:colorBackground"
+                android:background="?android:windowBackground"
                 android:paddingLeft="4dp"
                 android:paddingRight="4dp"
                 android:text="@string/login_host_hint"
diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
new file mode 100644
index 00000000..31a48159
--- /dev/null
+++ b/app/src/main/res/values-night/colors.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="spinner_stroke">#61FFFFFF</color>
+</resources>
diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml
index 33d26afd..76347d54 100644
--- a/app/src/main/res/values-night/styles.xml
+++ b/app/src/main/res/values-night/styles.xml
@@ -1,6 +1,6 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
 
-    <style name="WulkanowyTheme" parent="@style/Theme.AppCompat.DayNight">
+    <style name="WulkanowyTheme" parent="@style/Theme.MaterialComponents.Bridge">
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorPrimary</item>
@@ -9,6 +9,7 @@
         <item name="android:navigationBarColor" tools:targetApi="21">@color/bottom_nav_background</item>
         <item name="dividerColor">@color/divider_inverse</item>
         <item name="chip_backgroundColor">@color/chip_backgroundColor_inverse</item>
+        <item name="android:textColorTertiary">?android:textColorPrimary</item>
         <item name="chip_labelColor">@color/chip_labelColor_inverse</item>
         <item name="chip_detailed_backgroundColor">@color/chip_backgroundColor_inverse</item>
         <item name="filterable_list_backgroundColor">@color/filterable_list_backgroundColor_inverse</item>
@@ -24,4 +25,10 @@
         <item name="about_libraries_dividerDark_openSource">@color/about_libraries_dividerDark_openSource_dark</item>
         <item name="about_libraries_dividerLight_openSource">@color/about_libraries_dividerLight_openSource_dark</item>
     </style>
+
+    <style name="WulkanowyTheme.Black" parent="WulkanowyTheme.NoActionBar">
+        <item name="android:windowBackground">@android:color/black</item>
+        <item name="android:navigationBarColor" tools:targetApi="21">@android:color/black</item>
+        <item name="bottomNavBackground">@android:color/black</item>
+    </style>
 </resources>
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index b2689133..268ec2cb 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -242,7 +242,7 @@
     <string name="pref_view_list">Domyślny widok</string>
     <string name="pref_view_grade_average_mode">Obliczanie średniej końcoworocznej</string>
     <string name="pref_view_present">Pokazuj obecność we frekwencji</string>
-    <string name="pref_view_theme_dark">Ciemny motyw (Beta)</string>
+    <string name="pref_view_app_theme">Motyw apliakcji</string>
     <string name="pref_view_expand_grade">Rozwiń oceny</string>
     <string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string>
 
diff --git a/app/src/main/res/values-pl/value_prefernces.xml b/app/src/main/res/values-pl/value_prefernces.xml
index 34a10909..19268ef1 100644
--- a/app/src/main/res/values-pl/value_prefernces.xml
+++ b/app/src/main/res/values-pl/value_prefernces.xml
@@ -10,11 +10,10 @@
         <item>24 godzin</item>
     </string-array>
 
-    <string-array name="theme_entries">
-        <item>Wyłączony</item>
-        <item>Włączony</item>
-        <item>Automatyczny</item>
-        <item>Używaj ustawień systemowych</item>
+    <string-array name="app_theme_entries">
+        <item>Jasny</item>
+        <item>Ciemny</item>
+        <item>Czarny (AMOLED)</item>
     </string-array>
 
     <string-array name="grade_modifier_entries">
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 49854955..1b1fc7a0 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -40,4 +40,6 @@
 
     <color name="divider">#cccccc</color>
     <color name="divider_inverse">#777777</color>
+
+    <color name="spinner_stroke">#61000000</color>
 </resources>
diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml
index d03b4fbb..b09ee51b 100644
--- a/app/src/main/res/values/preferences_keys.xml
+++ b/app/src/main/res/values/preferences_keys.xml
@@ -2,7 +2,7 @@
 <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
     <string name="pref_key_start_menu">start_menu</string>
     <string name="pref_key_attendance_present">attendance_present</string>
-    <string name="pref_key_theme">theme</string>
+    <string name="pref_key_app_theme">app_theme</string>
     <string name="pref_key_grade_color_scheme">grade_color_scheme</string>
     <string name="pref_key_expand_grade">expand_grade</string>
     <string name="pref_key_grade_average_mode">grade_average_mode</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6195c36c..704bb35b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -227,7 +227,7 @@
     <string name="pref_view_list">Default view</string>
     <string name="pref_view_grade_average_mode">Calculation of the end-of-year average</string>
     <string name="pref_view_present">Show presence in attendance</string>
-    <string name="pref_view_theme_dark">Dark theme (Beta)</string>
+    <string name="pref_view_app_theme">Application theme</string>
     <string name="pref_view_expand_grade">Expand grades</string>
     <string name="pref_view_grade_color_scheme">Grades color scheme</string>
 
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 58cd99eb..685bda9f 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,6 +1,6 @@
 <resources>
 
-    <style name="WulkanowyTheme" parent="@style/Theme.AppCompat.DayNight">
+    <style name="WulkanowyTheme" parent="@style/Theme.MaterialComponents.Light.Bridge">
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorPrimary</item>
diff --git a/app/src/main/res/values/value_prefernces.xml b/app/src/main/res/values/value_prefernces.xml
index 3921b4e2..97396baa 100644
--- a/app/src/main/res/values/value_prefernces.xml
+++ b/app/src/main/res/values/value_prefernces.xml
@@ -13,17 +13,15 @@
         <item>3</item>
     </string-array>
 
-    <string-array name="theme_entries">
-        <item>Off</item>
-        <item>On</item>
-        <item>Auto</item>
-        <item>Follow system settings</item>
+    <string-array name="app_theme_entries">
+        <item>Light</item>
+        <item>Dark</item>
+        <item>Black (AMOLED)</item>
     </string-array>
-    <string-array name="theme_values" translatable="false">
-        <item>1</item>
-        <item>2</item>
-        <item>0</item>
-        <item>-1</item>
+    <string-array name="app_theme_values" translatable="false">
+        <item>light</item>
+        <item>dark</item>
+        <item>black</item>
     </string-array>
 
     <string-array name="services_interval_entries">
diff --git a/app/src/main/res/xml/scheme_preferences.xml b/app/src/main/res/xml/scheme_preferences.xml
index 5c2a8dda..149024c0 100644
--- a/app/src/main/res/xml/scheme_preferences.xml
+++ b/app/src/main/res/xml/scheme_preferences.xml
@@ -13,12 +13,12 @@
             android:title="@string/pref_view_list"
             app:iconSpaceReserved="false" />
         <ListPreference
-            android:defaultValue="1"
-            android:entries="@array/theme_entries"
-            android:entryValues="@array/theme_values"
-            android:key="theme"
+            android:defaultValue="light"
+            android:entries="@array/app_theme_entries"
+            android:entryValues="@array/app_theme_values"
+            android:key="@string/pref_key_app_theme"
             android:summary="%s"
-            android:title="@string/pref_view_theme_dark"
+            android:title="@string/pref_view_app_theme"
             app:iconSpaceReserved="false" />
         <SwitchPreference
             android:defaultValue="true"