diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 3a5ba7e54fee8d11c2e76f70a1111547ee10080e..3c5f51e32f65a5229e52fe76c9397286cefaf09f 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -104,13 +104,13 @@ android {
   }
 
   compileOptions {
-    setSourceCompatibility(JavaVersion.VERSION_1_8)
+    sourceCompatibility = JavaVersion.VERSION_1_8
     setTargetCompatibility(JavaVersion.VERSION_1_8)
   }
 
   lintOptions {
     isWarningsAsErrors = true
-    lintConfig = file("../lint.xml")
+    setLintConfig(file("../lint.xml"))
   }
 }
 
diff --git a/app/src/debug/res/values/strings_constants.xml b/app/src/debug/res/values/strings_constants.xml
index a53dfac109846e3efc1d6858eb577b8dc3cf8d99..fb13b0aa1775742591e5312ff67f07016eac30ab 100644
--- a/app/src/debug/res/values/strings_constants.xml
+++ b/app/src/debug/res/values/strings_constants.xml
@@ -1,4 +1,22 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?><!--
+  Quasseldroid - Quassel client for Android
+
+  Copyright (c) 2019 Janne Koschinski
+  Copyright (c) 2019 The Quassel Project
+
+  This program is free software: you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 3 as published
+  by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program. If not, see <http://www.gnu.org/licenses/>.
+  -->
+
 <resources>
   <string name="package_name" translatable="false">com.iskrembilen.quasseldroid.debug</string>
 </resources>
diff --git a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt
index ddcfb2d31b38c47c84c7c89228c16b6676afd085..a054d13686ab86a4a5e67eab7358537543e26b57 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt
@@ -83,6 +83,7 @@ class Quasseldroid : DaggerApplication() {
               host = it.host,
               port = it.port,
               user = it.user,
+              requireSsl = false,
               pass = it.pass,
               name = it.name,
               lastUsed = 0,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt
index 1f03c03c03a0c6aa91daad9dda9bbcd6da8b3ad3..8613fdf86f6c68bd4296f7d8b2f52d6720c643ed 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt
@@ -77,7 +77,7 @@ import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigFragme
 import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerActivity
 import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerFragmentProvider
 import de.kuschku.quasseldroid.ui.setup.accounts.edit.AccountEditActivity
-import de.kuschku.quasseldroid.ui.setup.accounts.edit.AccountEditModule
+import de.kuschku.quasseldroid.ui.setup.accounts.edit.AccountEditFragmentProvider
 import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionActivity
 import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionFragmentProvider
 import de.kuschku.quasseldroid.ui.setup.accounts.setup.AccountSetupActivity
@@ -204,7 +204,7 @@ abstract class ActivityModule {
   abstract fun bindAccountSelectionActivity(): AccountSelectionActivity
 
   @ActivityScope
-  @ContributesAndroidInjector(modules = [AccountEditModule::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class])
+  @ContributesAndroidInjector(modules = [AccountEditFragmentProvider::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class])
   abstract fun bindAccountEditActivity(): AccountEditActivity
 
   @ActivityScope
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
index 56bd24f3b9bc8234637463f819604861bac3c03d..1068e7be8df103d40465901ca933f2af4e26c38b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
@@ -40,15 +40,16 @@ class AsyncBackend(
   }
 
   override fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
-                                      reconnect: Boolean) {
+                                      requireSsl: Boolean, reconnect: Boolean) {
     handler.backend {
-      backend.connectUnlessConnected(address, user, pass, reconnect)
+      backend.connectUnlessConnected(address, user, pass, requireSsl, reconnect)
     }
   }
 
-  override fun connect(address: SocketAddress, user: String, pass: String, reconnect: Boolean) {
+  override fun connect(address: SocketAddress, user: String, pass: String, requireSsl: Boolean,
+                       reconnect: Boolean) {
     handler.backend {
-      backend.connect(address, user, pass, reconnect)
+      backend.connect(address, user, pass, requireSsl, reconnect)
     }
   }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
index 70419e7a9ee23a5b0d3fc31d73ec40c69fc3be0f..8a990c698ecdd7c5915bcf1442cb2ce294d0efad 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
@@ -117,6 +117,7 @@ class QuasselService : DaggerLifecycleService(),
             SocketAddress(account.host, account.port),
             account.user,
             account.pass,
+            account.requireSsl,
             true
           )
         }
@@ -273,19 +274,20 @@ class QuasselService : DaggerLifecycleService(),
     override fun sessionManager() = service?.sessionManager
 
     override fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
-                                        reconnect: Boolean) {
+                                        requireSsl: Boolean, reconnect: Boolean) {
       service?.apply {
         sessionManager.ifDisconnected {
-          connect(address, user, pass, reconnect)
+          connect(address, user, pass, requireSsl, reconnect)
         }
       }
     }
 
-    override fun connect(address: SocketAddress, user: String, pass: String, reconnect: Boolean) {
+    override fun connect(address: SocketAddress, user: String, pass: String, requireSsl: Boolean,
+                         reconnect: Boolean) {
       service?.apply {
         disconnect()
         sessionManager.connect(
-          clientData, trustManager, hostnameVerifier, address, user to pass, reconnect
+          clientData, trustManager, hostnameVerifier, address, user to pass, requireSsl, reconnect
         )
       }
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
index 0caa7d3f743251fbe5ce6733abdff0358449fff2..660e893e02320edb94991acf374dd7d8d7e49895 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
@@ -417,12 +417,11 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
           }
           is Error.SslError       -> {
             it.exception.let {
-              val leafCertificate = it.certificateChain?.firstOrNull()
-              if (leafCertificate == null) {
-                // No certificate exists in the chain
+              if (it == QuasselSecurityException.NoSsl) {
+                // Ssl is required but not available
                 MaterialDialog.Builder(this)
-                  .title(R.string.label_error_certificate)
-                  .content(R.string.label_error_certificate_no_certificate)
+                  .title(R.string.label_error_ssl)
+                  .content(R.string.label_error_ssl_required_unavailable)
                   .neutralText(R.string.label_close)
                   .titleColorAttr(R.attr.colorTextPrimary)
                   .backgroundColorAttr(R.attr.colorBackgroundCard)
@@ -430,132 +429,146 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   .build()
                   .show()
               } else {
-                when {
-                  // Certificate has expired
-                  it is QuasselSecurityException.Certificate &&
-                  (it.cause is CertificateNotYetValidException ||
-                   it.cause is CertificateExpiredException)  -> {
-                    MaterialDialog.Builder(this)
-                      .title(R.string.label_error_certificate)
-                      .content(
-                        Html.fromHtml(
-                          getString(
-                            R.string.label_error_certificate_invalid,
-                            leafCertificate.fingerprint,
-                            dateTimeFormatter.format(Instant.ofEpochMilli(leafCertificate.notBefore.time)
-                                                       .atZone(ZoneId.systemDefault())),
-                            dateTimeFormatter.format(Instant.ofEpochMilli(leafCertificate.notAfter.time)
-                                                       .atZone(ZoneId.systemDefault()))
+                val leafCertificate = it.certificateChain?.firstOrNull()
+                if (leafCertificate == null) {
+                  // No certificate exists in the chain
+                  MaterialDialog.Builder(this)
+                    .title(R.string.label_error_certificate)
+                    .content(R.string.label_error_certificate_no_certificate)
+                    .neutralText(R.string.label_close)
+                    .titleColorAttr(R.attr.colorTextPrimary)
+                    .backgroundColorAttr(R.attr.colorBackgroundCard)
+                    .contentColorAttr(R.attr.colorTextPrimary)
+                    .build()
+                    .show()
+                } else {
+                  when {
+                    // Certificate has expired
+                    it is QuasselSecurityException.Certificate &&
+                    (it.cause is CertificateNotYetValidException ||
+                     it.cause is CertificateExpiredException)  -> {
+                      MaterialDialog.Builder(this)
+                        .title(R.string.label_error_certificate)
+                        .content(
+                          Html.fromHtml(
+                            getString(
+                              R.string.label_error_certificate_invalid,
+                              leafCertificate.fingerprint,
+                              dateTimeFormatter.format(Instant.ofEpochMilli(leafCertificate.notBefore.time)
+                                                         .atZone(ZoneId.systemDefault())),
+                              dateTimeFormatter.format(Instant.ofEpochMilli(leafCertificate.notAfter.time)
+                                                         .atZone(ZoneId.systemDefault()))
+                            )
                           )
                         )
-                      )
-                      .negativeText(R.string.label_disconnect)
-                      .positiveText(R.string.label_whitelist)
-                      .onNegative { _, _ ->
-                        disconnect()
-                      }
-                      .onPositive { _, _ ->
-                        runInBackground {
-                          database.validityWhitelist().save(
-                            QuasselDatabase.SslValidityWhitelistEntry(
-                              fingerprint = leafCertificate.fingerprint,
-                              ignoreDate = true
+                        .negativeText(R.string.label_disconnect)
+                        .positiveText(R.string.label_whitelist)
+                        .onNegative { _, _ ->
+                          disconnect()
+                        }
+                        .onPositive { _, _ ->
+                          runInBackground {
+                            database.validityWhitelist().save(
+                              QuasselDatabase.SslValidityWhitelistEntry(
+                                fingerprint = leafCertificate.fingerprint,
+                                ignoreDate = true
+                              )
                             )
-                          )
 
-                          runOnUiThread {
-                            backend.value.orNull()?.reconnect()
+                            runOnUiThread {
+                              backend.value.orNull()?.reconnect()
+                            }
                           }
                         }
-                      }
-                      .titleColorAttr(R.attr.colorTextPrimary)
-                      .backgroundColorAttr(R.attr.colorBackgroundCard)
-                      .contentColorAttr(R.attr.colorTextPrimary)
-                      .build()
-                      .show()
-                  }
-                  // Certificate is in any other way invalid
-                  it is QuasselSecurityException.Certificate -> {
-                    MaterialDialog.Builder(this)
-                      .title(R.string.label_error_certificate)
-                      .content(
-                        Html.fromHtml(
-                          getString(
-                            R.string.label_error_certificate_untrusted,
-                            leafCertificate.fingerprint
-                          )
-                        )
-                      )
-                      .negativeText(R.string.label_disconnect)
-                      .positiveText(R.string.label_whitelist)
-                      .onNegative { _, _ ->
-                        disconnect()
-                      }
-                      .onPositive { _, _ ->
-                        runInBackground {
-                          database.validityWhitelist().save(
-                            QuasselDatabase.SslValidityWhitelistEntry(
-                              fingerprint = leafCertificate.fingerprint,
-                              ignoreDate = !leafCertificate.isValid
+                        .titleColorAttr(R.attr.colorTextPrimary)
+                        .backgroundColorAttr(R.attr.colorBackgroundCard)
+                        .contentColorAttr(R.attr.colorTextPrimary)
+                        .build()
+                        .show()
+                    }
+                    // Certificate is in any other way invalid
+                    it is QuasselSecurityException.Certificate -> {
+                      MaterialDialog.Builder(this)
+                        .title(R.string.label_error_certificate)
+                        .content(
+                          Html.fromHtml(
+                            getString(
+                              R.string.label_error_certificate_untrusted,
+                              leafCertificate.fingerprint
                             )
                           )
-                          accountDatabase.accounts().findById(accountId)?.let {
-                            database.hostnameWhitelist().save(
-                              QuasselDatabase.SslHostnameWhitelistEntry(
+                        )
+                        .negativeText(R.string.label_disconnect)
+                        .positiveText(R.string.label_whitelist)
+                        .onNegative { _, _ ->
+                          disconnect()
+                        }
+                        .onPositive { _, _ ->
+                          runInBackground {
+                            database.validityWhitelist().save(
+                              QuasselDatabase.SslValidityWhitelistEntry(
                                 fingerprint = leafCertificate.fingerprint,
-                                hostname = it.host
+                                ignoreDate = !leafCertificate.isValid
                               )
                             )
-                          }
+                            accountDatabase.accounts().findById(accountId)?.let {
+                              database.hostnameWhitelist().save(
+                                QuasselDatabase.SslHostnameWhitelistEntry(
+                                  fingerprint = leafCertificate.fingerprint,
+                                  hostname = it.host
+                                )
+                              )
+                            }
 
-                          runOnUiThread {
-                            backend.value.orNull()?.reconnect()
+                            runOnUiThread {
+                              backend.value.orNull()?.reconnect()
+                            }
                           }
                         }
-                      }
-                      .titleColorAttr(R.attr.colorTextPrimary)
-                      .backgroundColorAttr(R.attr.colorBackgroundCard)
-                      .contentColorAttr(R.attr.colorTextPrimary)
-                      .build()
-                      .show()
-                  }
-                  // Certificate not valid for this hostname
-                  it is QuasselSecurityException.Hostname    -> {
-                    MaterialDialog.Builder(this)
-                      .title(R.string.label_error_certificate)
-                      .content(
-                        Html.fromHtml(
-                          getString(
-                            R.string.label_error_certificate_no_match,
-                            leafCertificate.fingerprint,
-                            it.address.host
+                        .titleColorAttr(R.attr.colorTextPrimary)
+                        .backgroundColorAttr(R.attr.colorBackgroundCard)
+                        .contentColorAttr(R.attr.colorTextPrimary)
+                        .build()
+                        .show()
+                    }
+                    // Certificate not valid for this hostname
+                    it is QuasselSecurityException.Hostname    -> {
+                      MaterialDialog.Builder(this)
+                        .title(R.string.label_error_certificate)
+                        .content(
+                          Html.fromHtml(
+                            getString(
+                              R.string.label_error_certificate_no_match,
+                              leafCertificate.fingerprint,
+                              it.address.host
+                            )
                           )
                         )
-                      )
-                      .negativeText(R.string.label_disconnect)
-                      .positiveText(R.string.label_whitelist)
-                      .onNegative { _, _ ->
-                        disconnect()
-                      }
-                      .onPositive { _, _ ->
-                        runInBackground {
-                          database.hostnameWhitelist().save(
-                            QuasselDatabase.SslHostnameWhitelistEntry(
-                              fingerprint = leafCertificate.fingerprint,
-                              hostname = it.address.host
+                        .negativeText(R.string.label_disconnect)
+                        .positiveText(R.string.label_whitelist)
+                        .onNegative { _, _ ->
+                          disconnect()
+                        }
+                        .onPositive { _, _ ->
+                          runInBackground {
+                            database.hostnameWhitelist().save(
+                              QuasselDatabase.SslHostnameWhitelistEntry(
+                                fingerprint = leafCertificate.fingerprint,
+                                hostname = it.address.host
+                              )
                             )
-                          )
 
-                          runOnUiThread {
-                            backend.value.orNull()?.reconnect()
+                            runOnUiThread {
+                              backend.value.orNull()?.reconnect()
+                            }
                           }
                         }
-                      }
-                      .titleColorAttr(R.attr.colorTextPrimary)
-                      .backgroundColorAttr(R.attr.colorBackgroundCard)
-                      .contentColorAttr(R.attr.colorTextPrimary)
-                      .build()
-                      .show()
+                        .titleColorAttr(R.attr.colorTextPrimary)
+                        .backgroundColorAttr(R.attr.colorBackgroundCard)
+                        .contentColorAttr(R.attr.colorTextPrimary)
+                        .build()
+                        .show()
+                    }
                   }
                 }
               }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt
index 6084ccdfabbadd204306ed48e9992fcaed395d37..48a4dd845128df7ec175a3acf3144379e104576b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt
@@ -35,15 +35,16 @@ import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.chat.input.*
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.helper.invoke
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatSerializer
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel
 import javax.inject.Inject
 
-class TopicFragment : SettingsFragment(), SettingsFragment.Savable {
+class TopicFragment : ServiceBoundSettingsFragment(), Savable {
   @BindView(R.id.chatline)
   lateinit var chatline: RichEditText
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistFragment.kt
index f4fc55739cdedaa4dcd3aea4c4842d7a349af3fb..82c89cadebb6c56160298430ea02356b250b1f91 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistFragment.kt
@@ -34,12 +34,14 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.persistence.QuasselDatabase
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.helper.visibleIf
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.SettingsFragment
 import javax.inject.Inject
 
-class WhitelistFragment : SettingsFragment(), SettingsFragment.Changeable,
-                          SettingsFragment.Savable {
+class WhitelistFragment : SettingsFragment(), Changeable,
+                          Savable {
   @BindView(R.id.certificate_whitelist)
   lateinit var certificateList: RecyclerView
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/SettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/SettingsFragment.kt
deleted file mode 100644
index 127067224aca59802079302836077e75a61d7a3f..0000000000000000000000000000000000000000
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/SettingsFragment.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2019 Janne Koschinski
- * Copyright (c) 2019 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package de.kuschku.quasseldroid.ui.coresettings
-
-import android.os.Bundle
-import android.view.Menu
-import android.view.MenuInflater
-import android.view.MenuItem
-import com.afollestad.materialdialogs.MaterialDialog
-import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
-
-abstract class SettingsFragment : ServiceBoundFragment() {
-  private var saveable: Savable? = null
-  private var deletable: Deletable? = null
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-    setHasOptionsMenu(true)
-    saveable = this as? Savable
-    deletable = this as? Deletable
-  }
-
-  override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
-    inflater?.inflate(R.menu.context_setting, menu)
-    menu?.findItem(R.id.action_save)?.isVisible = saveable != null
-    menu?.findItem(R.id.action_delete)?.isVisible = deletable != null
-    super.onCreateOptionsMenu(menu, inflater)
-  }
-
-  override fun onOptionsItemSelected(item: MenuItem?) = when (item?.itemId) {
-    R.id.action_save   -> {
-      saveable?.let {
-        if (it.onSave()) activity?.finish()
-      }
-      true
-    }
-    R.id.action_delete -> {
-      deletable?.let {
-        MaterialDialog.Builder(activity!!)
-          .content(R.string.delete_confirmation)
-          .positiveText(R.string.label_yes)
-          .negativeText(R.string.label_no)
-          .negativeColorAttr(R.attr.colorTextPrimary)
-          .backgroundColorAttr(R.attr.colorBackgroundCard)
-          .contentColorAttr(R.attr.colorTextPrimary)
-          .onPositive { _, _ ->
-            it.onDelete()
-            requireActivity().finish()
-          }
-          .build()
-          .show()
-      }
-      true
-    }
-    else               -> super.onOptionsItemSelected(item)
-  }
-
-  interface Changeable {
-    fun hasChanged(): Boolean
-  }
-
-  interface Savable {
-    fun onSave(): Boolean
-  }
-
-  interface Deletable {
-    fun onDelete()
-  }
-}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliasitem/AliasItemFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliasitem/AliasItemFragment.kt
index fb2f45e10180cf7f4e25f446f5f36a640e783849..1dfa2e2f97c3faa6a1c236df7cd690b8c4d1e178 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliasitem/AliasItemFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliasitem/AliasItemFragment.kt
@@ -38,15 +38,15 @@ import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.chat.input.*
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatSerializer
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel
 import javax.inject.Inject
 
-class AliasItemFragment : SettingsFragment(), SettingsFragment.Savable,
-                          SettingsFragment.Changeable {
-
+class AliasItemFragment : ServiceBoundSettingsFragment(), Savable, Changeable {
   @BindView(R.id.name)
   lateinit var name: EditText
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt
index 828546f43961a1b104fa0ff31b815765dbe1ba5e..433e9f01794c77eeca4779af704cbe0dfc294704 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt
@@ -34,13 +34,14 @@ import de.kuschku.libquassel.quassel.syncables.AliasManager
 import de.kuschku.libquassel.quassel.syncables.interfaces.IAliasManager
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.ui.coresettings.aliasitem.AliasItemActivity
 import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 import javax.inject.Inject
 
-class AliasListFragment : SettingsFragment(), SettingsFragment.Savable,
-                          SettingsFragment.Changeable {
+class AliasListFragment : ServiceBoundSettingsFragment(), Savable, Changeable {
   @BindView(R.id.list)
   lateinit var list: RecyclerView
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
index 557b87499ccc6ef4de92bb0e3ac89da4b8b73ea9..9070b0af0d2b60cd61cf0cc40bfb0320345acb0c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
@@ -42,12 +42,14 @@ import de.kuschku.libquassel.util.flag.minus
 import de.kuschku.libquassel.util.flag.plus
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.Defaults
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
 abstract class ChatListBaseFragment(private val initDefault: Boolean) :
-  SettingsFragment(), SettingsFragment.Savable, SettingsFragment.Changeable {
+  ServiceBoundSettingsFragment(), Savable, Changeable {
   @BindView(R.id.buffer_view_name)
   lateinit var bufferViewName: EditText
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt
index a42d6859654d477c741c3ba2b7d0ca5b1e42e7c2..2c7cc4067367df29d3d92123270c1f692947681a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt
@@ -20,9 +20,9 @@
 package de.kuschku.quasseldroid.ui.coresettings.chatlist
 
 import de.kuschku.libquassel.util.helpers.value
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
 
-class ChatListEditFragment : ChatListBaseFragment(false), SettingsFragment.Deletable {
+class ChatListEditFragment : ChatListBaseFragment(false), Deletable {
   override fun onSave() = chatlist?.let { (it, data) ->
     applyChanges(data, it)
     it?.requestUpdate(data.toVariantMap())
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt
index cba85bc753c92c7dbac2460dacd78b80a6602027..a7e1d76464a6aa9c07a0219f44eefabf379e1708 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt
@@ -40,13 +40,14 @@ import de.kuschku.libquassel.quassel.syncables.HighlightRuleManager
 import de.kuschku.libquassel.quassel.syncables.interfaces.IHighlightRuleManager
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.ui.coresettings.highlightrule.HighlightRuleActivity
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.ui.WarningBarView
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
-class HighlightListFragment : SettingsFragment(), SettingsFragment.Savable,
-                              SettingsFragment.Changeable {
+class HighlightListFragment : ServiceBoundSettingsFragment(), Savable, Changeable {
   @BindView(R.id.feature_context_coresidehighlights)
   lateinit var featureContextCoreSideHighlights: WarningBarView
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightrule/HighlightRuleFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightrule/HighlightRuleFragment.kt
index 586fefb2237486c8b5a0acc192c665d5eb0b2e04..e509d1b1f48badccd5d8643160b1a4dc607d9024 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightrule/HighlightRuleFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightrule/HighlightRuleFragment.kt
@@ -31,10 +31,12 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.libquassel.quassel.syncables.HighlightRuleManager
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
-class HighlightRuleFragment : SettingsFragment(), SettingsFragment.Savable,
-                              SettingsFragment.Changeable {
+class HighlightRuleFragment : ServiceBoundSettingsFragment(), Savable,
+                              Changeable {
   @BindView(R.id.enabled)
   lateinit var enabled: SwitchCompat
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
index 7ff7e243fa1aa627bd6002613570dc6d7df69615..9b2bfb294e9db7c36dcabe7c723ea3f039f3faf3 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
@@ -39,12 +39,14 @@ import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.Defaults
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.helper.setDependent
 import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
 abstract class IdentityBaseFragment(private val initDefault: Boolean) :
-  SettingsFragment(), SettingsFragment.Savable, SettingsFragment.Changeable {
+  ServiceBoundSettingsFragment(), Savable, Changeable {
 
   @BindView(R.id.identity_name)
   lateinit var identityName: EditText
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt
index 8b624eae1e1ad8fa86eb9d4eb85751f81dc0688c..88d913fc8dc7502f85887763248af7390a5c6213 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt
@@ -20,9 +20,9 @@
 package de.kuschku.quasseldroid.ui.coresettings.identity
 
 import de.kuschku.libquassel.util.helpers.value
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
 
-class IdentityEditFragment : IdentityBaseFragment(false), SettingsFragment.Deletable {
+class IdentityEditFragment : IdentityBaseFragment(false), Deletable {
   override fun onSave() = identity?.let { (it, data) ->
     applyChanges(data)
     it?.requestUpdate(data.toVariantMap())
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignoreitem/IgnoreItemFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignoreitem/IgnoreItemFragment.kt
index 7c4287ed6d12790c06d110275ceb026a6df4bcfb..4c9bfda8ff482671e4ef9ec574db751e93e31566 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignoreitem/IgnoreItemFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignoreitem/IgnoreItemFragment.kt
@@ -33,11 +33,13 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.ui.AnimationHelper
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
-class IgnoreItemFragment : SettingsFragment(), SettingsFragment.Savable,
-                           SettingsFragment.Changeable {
+class IgnoreItemFragment : ServiceBoundSettingsFragment(), Savable,
+                           Changeable {
   @BindView(R.id.enabled)
   lateinit var enabled: SwitchCompat
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
index 02addb034aa7852a7cd7165131c1d793197a188a..88632f9906a2aec4549663d0f7b355cbe906cbc4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
@@ -36,12 +36,14 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
 import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.ui.coresettings.ignoreitem.IgnoreItemActivity
 import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
-class IgnoreListFragment : SettingsFragment(), SettingsFragment.Savable,
-                           SettingsFragment.Changeable {
+class IgnoreListFragment : ServiceBoundSettingsFragment(), Savable,
+                           Changeable {
   @BindView(R.id.list)
   lateinit var list: RecyclerView
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
index 402dbf473decb4b0e782fb998b19c70afc722851..8c550485e0bcb92a9259f30929aad6bc25aa6d48 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
@@ -44,15 +44,17 @@ import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.helpers.nullIf
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.Defaults
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerActivity
 import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.setDependent
 import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 import kotlin.math.roundToInt
 
 abstract class NetworkBaseFragment(private val initDefault: Boolean) :
-  SettingsFragment(), SettingsFragment.Savable, SettingsFragment.Changeable {
+  ServiceBoundSettingsFragment(), Savable, Changeable {
   @BindView(R.id.network_name)
   lateinit var networkName: EditText
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt
index 92b15ea340fb14479ba2da8fe121f5bb75b543f1..6924fe05cb25297931aad45ee13d5284651cec4c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt
@@ -20,9 +20,9 @@
 package de.kuschku.quasseldroid.ui.coresettings.network
 
 import de.kuschku.libquassel.util.helpers.value
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
 
-class NetworkEditFragment : NetworkBaseFragment(false), SettingsFragment.Deletable {
+class NetworkEditFragment : NetworkBaseFragment(false), Deletable {
   override fun onSave() = network?.let { (it, data) ->
     applyChanges(data)
     it?.requestSetNetworkInfo(data.networkInfo())
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt
index f1ac6b8ed94ce76a8065e4d3ae8fe7dc441655da..7b1d1d5db61108d1a907ff59758bdae07a40569b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt
@@ -31,12 +31,14 @@ import butterknife.ButterKnife
 import de.kuschku.libquassel.quassel.syncables.NetworkConfig
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.helper.setDependent
 import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
-class NetworkConfigFragment : SettingsFragment(), SettingsFragment.Savable,
-                              SettingsFragment.Changeable {
+class NetworkConfigFragment : ServiceBoundSettingsFragment(), Savable,
+                              Changeable {
   @BindView(R.id.ping_timeout_enabled)
   lateinit var pingTimeoutEnabled: SwitchCompat
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt
index 2ad61605c2b3067c0e264cd790e9a429ed594483..af9838270f1db2040343e15b250d71fc0a2f2045 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkserver/NetworkServerFragment.kt
@@ -34,11 +34,13 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_PLAINTEXT
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_SSL
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.helper.setDependent
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
 
-class NetworkServerFragment : SettingsFragment(), SettingsFragment.Savable,
-                              SettingsFragment.Changeable {
+class NetworkServerFragment : ServiceBoundSettingsFragment(), Savable,
+                              Changeable {
   @BindView(R.id.host)
   lateinit var host: EditText
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditActivity.kt
index 6c688f675de209411abbcf25b68869c1dbb1ae08..f65e8d9cf14da1b4ff39298f07c5fc33d0dfc41c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditActivity.kt
@@ -19,188 +19,11 @@
 
 package de.kuschku.quasseldroid.ui.setup.accounts.edit
 
-import android.app.Activity
 import android.content.Context
 import android.content.Intent
-import android.os.Bundle
-import android.text.Editable
-import android.view.Menu
-import android.view.MenuItem
-import android.widget.EditText
-import butterknife.BindView
-import butterknife.ButterKnife
-import com.afollestad.materialdialogs.MaterialDialog
-import com.google.android.material.textfield.TextInputLayout
-import dagger.android.support.DaggerAppCompatActivity
-import de.kuschku.quasseldroid.Keys
-import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.AccountDatabase
-import de.kuschku.quasseldroid.util.AndroidHandlerThread
-import de.kuschku.quasseldroid.util.Patterns
-import de.kuschku.quasseldroid.util.TextValidator
-import de.kuschku.quasseldroid.util.helper.editCommit
-import javax.inject.Inject
-
-class AccountEditActivity : DaggerAppCompatActivity() {
-  @BindView(R.id.nameWrapper)
-  lateinit var nameWrapper: TextInputLayout
-  @BindView(R.id.name)
-  lateinit var name: EditText
-
-  @BindView(R.id.hostWrapper)
-  lateinit var hostWrapper: TextInputLayout
-  @BindView(R.id.host)
-  lateinit var host: EditText
-
-  @BindView(R.id.portWrapper)
-  lateinit var portWrapper: TextInputLayout
-  @BindView(R.id.port)
-  lateinit var port: EditText
-
-  @BindView(R.id.userWrapper)
-  lateinit var userWrapper: TextInputLayout
-  @BindView(R.id.user)
-  lateinit var user: EditText
-
-  @BindView(R.id.passWrapper)
-  lateinit var passWrapper: TextInputLayout
-  @BindView(R.id.pass)
-  lateinit var pass: EditText
-
-  @Inject
-  lateinit var database: AccountDatabase
-
-  private var accountId: Long = -1
-  private var account: AccountDatabase.Account? = null
-
-  private val handler = AndroidHandlerThread("AccountEdit")
-
-  override fun onCreate(savedInstanceState: Bundle?) {
-    handler.onCreate()
-    setTheme(R.style.Theme_AppTheme_Light)
-    super.onCreate(savedInstanceState)
-    setContentView(R.layout.setup_account_edit)
-    ButterKnife.bind(this)
-
-    handler.post {
-      accountId = intent.getLongExtra("account", -1)
-      if (accountId == -1L) {
-        setResult(Activity.RESULT_CANCELED)
-        finish()
-      }
-      account = database.accounts().findById(accountId)
-      if (account == null) {
-        setResult(Activity.RESULT_CANCELED)
-        finish()
-      }
-
-      name.setText(account?.name)
-      host.setText(account?.host)
-      port.setText(account?.port?.toString())
-      user.setText(account?.user)
-      pass.setText(account?.pass)
-    }
-
-    nameValidator = object : TextValidator(
-      this, nameWrapper::setError, resources.getString(R.string.hint_invalid_name)
-    ) {
-      override fun validate(text: Editable) = text.isNotBlank()
-    }
-
-    hostValidator = object : TextValidator(
-      this, hostWrapper::setError, resources.getString(R.string.hint_invalid_host)
-    ) {
-      override fun validate(text: Editable) = text.toString().matches(Patterns.DOMAIN_NAME)
-    }
-
-    portValidator = object : TextValidator(
-      this, portWrapper::setError, resources.getString(R.string.hint_invalid_port)
-    ) {
-      override fun validate(text: Editable) = text.toString().toIntOrNull() in (0 until 65536)
-    }
-
-    userValidator = object : TextValidator(
-      this, userWrapper::setError, resources.getString(R.string.hint_invalid_user)
-    ) {
-      override fun validate(text: Editable) = text.isNotBlank()
-    }
-
-    name.addTextChangedListener(nameValidator)
-    host.addTextChangedListener(hostValidator)
-    port.addTextChangedListener(portValidator)
-    user.addTextChangedListener(userValidator)
-    nameValidator.afterTextChanged(name.text)
-    hostValidator.afterTextChanged(host.text)
-    portValidator.afterTextChanged(port.text)
-    userValidator.afterTextChanged(user.text)
-  }
-
-  private lateinit var nameValidator: TextValidator
-  private lateinit var hostValidator: TextValidator
-  private lateinit var portValidator: TextValidator
-  private lateinit var userValidator: TextValidator
-
-  private val isValid
-    get() = nameValidator.isValid && hostValidator.isValid && portValidator.isValid
-            && userValidator.isValid
-
-  override fun onCreateOptionsMenu(menu: Menu?): Boolean {
-    menuInflater.inflate(R.menu.setup_edit_account, menu)
-    return super.onCreateOptionsMenu(menu)
-  }
-
-  override fun onDestroy() {
-    handler.onDestroy()
-    super.onDestroy()
-  }
-
-  override fun onOptionsItemSelected(item: MenuItem?) = when (item?.itemId) {
-    R.id.action_delete -> {
-      MaterialDialog.Builder(this)
-        .content(R.string.delete_confirmation)
-        .positiveText(R.string.label_yes)
-        .negativeText(R.string.label_no)
-        .negativeColorAttr(android.R.attr.textColorPrimary)
-        .onPositive { _, _ ->
-          val it = account
-          if (it != null)
-            handler.post {
-              val preferences = getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE)
-              if (preferences.getLong(Keys.Status.selectedAccount, -1) == it.id) {
-                preferences.editCommit {
-                  remove(Keys.Status.selectedAccount)
-                }
-              }
-              database.accounts().delete(it)
-            }
-          setResult(Activity.RESULT_OK)
-          finish()
-        }
-        .build()
-        .show()
-      true
-    }
-    R.id.action_save   -> {
-      if (isValid) {
-        val it = account
-        if (it != null) {
-          it.name = name.text.toString()
-          it.host = host.text.toString()
-          it.port = port.text.toString().toIntOrNull() ?: 4242
-          it.user = user.text.toString()
-          it.pass = pass.text.toString()
-          handler.post {
-            database.accounts().save(it)
-            setResult(Activity.RESULT_OK)
-            finish()
-          }
-        }
-      }
-      true
-    }
-    else               -> super.onOptionsItemSelected(item)
-  }
+import de.kuschku.quasseldroid.util.ui.settings.SettingsActivity
 
+class AccountEditActivity : SettingsActivity(AccountEditFragment()) {
   companion object {
     fun launch(
       context: Context,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3f6907436b2e74649bec0ecde614162defab3ee9
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditFragment.kt
@@ -0,0 +1,200 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.ui.setup.accounts.edit
+
+import android.app.Activity
+import android.content.Context
+import android.os.Bundle
+import android.os.Handler
+import android.os.HandlerThread
+import android.text.Editable
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.appcompat.widget.SwitchCompat
+import butterknife.BindView
+import butterknife.ButterKnife
+import com.google.android.material.textfield.TextInputLayout
+import de.kuschku.quasseldroid.Keys
+import de.kuschku.quasseldroid.R
+import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.util.Patterns
+import de.kuschku.quasseldroid.util.TextValidator
+import de.kuschku.quasseldroid.util.helper.editCommit
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
+import de.kuschku.quasseldroid.util.ui.settings.fragment.SettingsFragment
+import javax.inject.Inject
+
+class AccountEditFragment : SettingsFragment(), Changeable, Savable, Deletable {
+  @BindView(R.id.nameWrapper)
+  lateinit var nameWrapper: TextInputLayout
+  @BindView(R.id.name)
+  lateinit var name: EditText
+
+  @BindView(R.id.hostWrapper)
+  lateinit var hostWrapper: TextInputLayout
+  @BindView(R.id.host)
+  lateinit var host: EditText
+
+  @BindView(R.id.portWrapper)
+  lateinit var portWrapper: TextInputLayout
+  @BindView(R.id.port)
+  lateinit var port: EditText
+
+  @BindView(R.id.require_ssl)
+  lateinit var requireSsl: SwitchCompat
+
+  @BindView(R.id.userWrapper)
+  lateinit var userWrapper: TextInputLayout
+  @BindView(R.id.user)
+  lateinit var user: EditText
+
+  @BindView(R.id.passWrapper)
+  lateinit var passWrapper: TextInputLayout
+  @BindView(R.id.pass)
+  lateinit var pass: EditText
+
+  @Inject
+  lateinit var database: AccountDatabase
+
+  private var account: AccountDatabase.Account? = null
+  private var accountId: Long = -1L
+
+  private lateinit var handlerThread: HandlerThread
+  private lateinit var handler: Handler
+
+  override fun onCreate(savedInstanceState: Bundle?) {
+    super.onCreate(savedInstanceState)
+    handlerThread = HandlerThread("accountEdit")
+    handlerThread.start()
+    handler = Handler(handlerThread.looper)
+  }
+
+  override fun onDestroy() {
+    super.onDestroy()
+    handlerThread.quit()
+  }
+
+  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+                            savedInstanceState: Bundle?): View? {
+    val view = inflater.inflate(R.layout.setup_account_edit, container, false)
+    ButterKnife.bind(this, view)
+
+    setHasOptionsMenu(true)
+
+    handler.post {
+      accountId = arguments?.getLong("account", -1) ?: -1
+      if (accountId == -1L) {
+        activity?.setResult(Activity.RESULT_CANCELED)
+        activity?.finish()
+      }
+      account = database.accounts().findById(accountId)
+      if (account == null) {
+        activity?.setResult(Activity.RESULT_CANCELED)
+        activity?.finish()
+      }
+
+      name.setText(account?.name)
+      host.setText(account?.host)
+      port.setText(account?.port?.toString())
+      requireSsl.isChecked = account?.requireSsl == true
+      user.setText(account?.user)
+      pass.setText(account?.pass)
+    }
+
+    nameValidator = object : TextValidator(
+      activity, nameWrapper::setError, resources.getString(R.string.hint_invalid_name)
+    ) {
+      override fun validate(text: Editable) = text.isNotBlank()
+    }
+
+    hostValidator = object : TextValidator(
+      activity, hostWrapper::setError, resources.getString(R.string.hint_invalid_host)
+    ) {
+      override fun validate(text: Editable) = text.toString().matches(Patterns.DOMAIN_NAME)
+    }
+
+    portValidator = object : TextValidator(
+      activity, portWrapper::setError, resources.getString(R.string.hint_invalid_port)
+    ) {
+      override fun validate(text: Editable) = text.toString().toIntOrNull() in (0 until 65536)
+    }
+
+    userValidator = object : TextValidator(
+      activity, userWrapper::setError, resources.getString(R.string.hint_invalid_user)
+    ) {
+      override fun validate(text: Editable) = text.isNotBlank()
+    }
+
+    name.addTextChangedListener(nameValidator)
+    host.addTextChangedListener(hostValidator)
+    port.addTextChangedListener(portValidator)
+    user.addTextChangedListener(userValidator)
+    nameValidator.afterTextChanged(name.text)
+    hostValidator.afterTextChanged(host.text)
+    portValidator.afterTextChanged(port.text)
+    userValidator.afterTextChanged(user.text)
+    return view
+  }
+
+  private lateinit var nameValidator: TextValidator
+  private lateinit var hostValidator: TextValidator
+  private lateinit var portValidator: TextValidator
+  private lateinit var userValidator: TextValidator
+
+  private val isValid
+    get() = nameValidator.isValid && hostValidator.isValid && portValidator.isValid
+            && userValidator.isValid
+
+  fun applyChanges() = account?.copy(
+    name = name.text.toString(),
+    host = host.text.toString(),
+    port = port.text.toString().toIntOrNull() ?: 4242,
+    requireSsl = requireSsl.isChecked,
+    user = user.text.toString(),
+    pass = pass.text.toString()
+  )
+
+  override fun onSave() = applyChanges()?.let {
+    handler.post {
+      database.accounts().save(it)
+    }
+    true
+  } ?: false
+
+  override fun onDelete() {
+    handler.post {
+      account?.let {
+        val preferences = activity?.getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE)
+        if (preferences?.getLong(Keys.Status.selectedAccount, -1) == it.id) {
+          preferences.editCommit {
+            remove(Keys.Status.selectedAccount)
+          }
+        }
+        database.accounts().delete(it)
+      }
+    }
+  }
+
+  override fun hasChanged() = account != applyChanges()
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditModule.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditFragmentProvider.kt
similarity index 83%
rename from app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditModule.kt
rename to app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditFragmentProvider.kt
index 224129789943b8d551808b2380d8d64ec8905714..b87c9ba42c0f0012dd67b4ce2beff07561b8cea2 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditModule.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/edit/AccountEditFragmentProvider.kt
@@ -22,9 +22,13 @@ package de.kuschku.quasseldroid.ui.setup.accounts.edit
 import androidx.fragment.app.FragmentActivity
 import dagger.Binds
 import dagger.Module
+import dagger.android.ContributesAndroidInjector
 
 @Module
-abstract class AccountEditModule {
+abstract class AccountEditFragmentProvider {
   @Binds
   abstract fun bindFragmentActivity(activity: AccountEditActivity): FragmentActivity
+
+  @ContributesAndroidInjector
+  abstract fun bindAccountEditFragment(): AccountEditFragment
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupActivity.kt
index 73240e0a5c9d3bcdcc8705fd1a154c00d08f2a10..9a89d2fa8f4574f4083f2f8e3300ffe8dd5423e6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupActivity.kt
@@ -38,11 +38,12 @@ class AccountSetupActivity : SetupActivity() {
   override fun onDone(data: Bundle) {
     val account = AccountDatabase.Account(
       id = 0,
-      host = data.getString("host"),
+      host = data.getString("host", ""),
       port = data.getInt("port"),
-      user = data.getString("user"),
-      pass = data.getString("pass"),
-      name = data.getString("name"),
+      requireSsl = data.getBoolean("require_ssl"),
+      user = data.getString("user", ""),
+      pass = data.getString("pass", ""),
+      name = data.getString("name", ""),
       lastUsed = Instant.now().epochSecond,
       acceptedMissingFeatures = false,
       defaultFiltered = 0
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupConnectionSlide.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupConnectionSlide.kt
index 138ad6a37721832ceea8ab2fb571ea9a7c35ab4d..446d7b95a8940d715670a3c44cad018bad2ce706 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupConnectionSlide.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/setup/AccountSetupConnectionSlide.kt
@@ -25,6 +25,7 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.EditText
+import androidx.appcompat.widget.SwitchCompat
 import butterknife.BindView
 import butterknife.ButterKnife
 import com.google.android.material.textfield.TextInputLayout
@@ -46,6 +47,9 @@ class AccountSetupConnectionSlide : SlideFragment() {
   @BindView(R.id.port)
   lateinit var portField: EditText
 
+  @BindView(R.id.require_ssl)
+  lateinit var requireSsl: SwitchCompat
+
   override fun isValid(): Boolean {
     return hostValidator.isValid && portValidator.isValid
   }
@@ -58,12 +62,15 @@ class AccountSetupConnectionSlide : SlideFragment() {
       hostField.setText(data.getString("host"))
     if (data.containsKey("port"))
       portField.setText(data.getInt("port").toString())
+    if (data.containsKey("require_ssl"))
+      requireSsl.isChecked = data.getBoolean("require_ssl", false)
     updateValidity()
   }
 
   override fun getData(data: Bundle) {
     data.putString("host", hostField.text.toString())
     data.putInt("port", portField.text.toString().toIntOrNull() ?: -1)
+    data.putBoolean("require_ssl", requireSsl.isChecked)
   }
 
   override fun onCreateContent(inflater: LayoutInflater, container: ViewGroup?,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ShortcutCreationHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ShortcutCreationHelper.kt
index 81f14ce6771d435de6e1977c904d60fbca06ff25..810f85bac70c5c5a9e3f1bfd776d925deedb36f4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ShortcutCreationHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ShortcutCreationHelper.kt
@@ -4,17 +4,17 @@
  * Copyright (c) 2019 Janne Koschinski
  * Copyright (c) 2019 The Quassel Project
  *
- * context program is free software: you can redistribute it and/or modify it
+ * This program is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 3 as published
  * by the Free Software Foundation.
  *
- * context program is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License along
- * with context program. If not, see <http://www.gnu.org/licenses/>.
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 package de.kuschku.quasseldroid.util
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/ServiceBoundSettingsActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/ServiceBoundSettingsActivity.kt
index 59208565cf5dc25c1475bc702c16d8b59b64a801..af6a225b0169d6cdcec9adc494c83b6217bf1486 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/ServiceBoundSettingsActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/ServiceBoundSettingsActivity.kt
@@ -27,14 +27,14 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import com.afollestad.materialdialogs.MaterialDialog
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.service.ServiceBoundActivity
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
 
 abstract class ServiceBoundSettingsActivity(private val fragment: Fragment? = null) :
   ServiceBoundActivity() {
   protected open fun fragment(): Fragment? = null
 
-  private var changeable: SettingsFragment.Changeable? = null
+  private var changeable: Changeable? = null
 
   @BindView(R.id.toolbar)
   lateinit var toolbar: Toolbar
@@ -56,7 +56,7 @@ abstract class ServiceBoundSettingsActivity(private val fragment: Fragment? = nu
       transaction.commit()
     }
 
-    this.changeable = fragment as? SettingsFragment.Changeable
+    this.changeable = fragment as? Changeable
   }
 
   private fun shouldNavigateAway(callback: () -> Unit) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/SettingsActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/SettingsActivity.kt
index dad6e087c04e11d354a45afa859e8b0a0f15a8c0..a9ec61804ce404cc78e8e689b38cb139bc8b1866 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/SettingsActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/SettingsActivity.kt
@@ -27,13 +27,13 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import com.afollestad.materialdialogs.MaterialDialog
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
 import de.kuschku.quasseldroid.util.ui.ThemedActivity
+import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
 
 abstract class SettingsActivity(protected val fragment: Fragment? = null) : ThemedActivity() {
   protected open fun fragment(): Fragment? = null
 
-  private var changeable: SettingsFragment.Changeable? = null
+  private var changeable: Changeable? = null
 
   @BindView(R.id.toolbar)
   lateinit var toolbar: Toolbar
@@ -55,7 +55,7 @@ abstract class SettingsActivity(protected val fragment: Fragment? = null) : Them
       transaction.commit()
     }
 
-    this.changeable = fragment as? SettingsFragment.Changeable
+    this.changeable = fragment as? Changeable
   }
 
   private fun shouldNavigateAway(callback: () -> Unit) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Changeable.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Changeable.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f3c78a532151f387db9abeb85c4d59507c1f1e5f
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Changeable.kt
@@ -0,0 +1,24 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.util.ui.settings.fragment
+
+interface Changeable {
+  fun hasChanged(): Boolean
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Deletable.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Deletable.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1ca5ca7433d2e2f8bb4bbb2f6dc453c24341650b
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Deletable.kt
@@ -0,0 +1,24 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.util.ui.settings.fragment
+
+interface Deletable {
+  fun onDelete()
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Savable.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Savable.kt
new file mode 100644
index 0000000000000000000000000000000000000000..69990788a5204c4519e4886f554ca3d86bc2d837
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/Savable.kt
@@ -0,0 +1,24 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.util.ui.settings.fragment
+
+interface Savable {
+  fun onSave(): Boolean
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/ServiceBoundSettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/ServiceBoundSettingsFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..82093d63045bf0231c0e8fe6a0f08351c928bce7
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/ServiceBoundSettingsFragment.kt
@@ -0,0 +1,48 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.util.ui.settings.fragment
+
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.MenuItem
+import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
+
+abstract class ServiceBoundSettingsFragment : ServiceBoundFragment() {
+  private lateinit var helper: SettingsFragmentHelper
+
+  override fun onCreate(savedInstanceState: Bundle?) {
+    super.onCreate(savedInstanceState)
+    setHasOptionsMenu(true)
+    helper = SettingsFragmentHelper(
+      this as? Savable,
+      this as? Deletable
+    )
+  }
+
+  override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
+    helper.onCreateOptionsMenu(menu, inflater)
+    super.onCreateOptionsMenu(menu, inflater)
+  }
+
+  override fun onOptionsItemSelected(item: MenuItem?) =
+    helper.onOptionsItemSelected(activity, item)
+    ?: super.onOptionsItemSelected(item)
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/SettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/SettingsFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ed27924e4f9d91414e0735e06987d72e3797e300
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/SettingsFragment.kt
@@ -0,0 +1,48 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.util.ui.settings.fragment
+
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.MenuItem
+import dagger.android.support.DaggerFragment
+
+abstract class SettingsFragment : DaggerFragment() {
+  private lateinit var helper: SettingsFragmentHelper
+
+  override fun onCreate(savedInstanceState: Bundle?) {
+    super.onCreate(savedInstanceState)
+    setHasOptionsMenu(true)
+    helper = SettingsFragmentHelper(
+      this as? Savable,
+      this as? Deletable
+    )
+  }
+
+  override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
+    helper.onCreateOptionsMenu(menu, inflater)
+    super.onCreateOptionsMenu(menu, inflater)
+  }
+
+  override fun onOptionsItemSelected(item: MenuItem?) =
+    helper.onOptionsItemSelected(activity, item)
+    ?: super.onOptionsItemSelected(item)
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/SettingsFragmentHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/SettingsFragmentHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d54c8515e27729dc1cc44e9c67bd4b1fdda01673
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/fragment/SettingsFragmentHelper.kt
@@ -0,0 +1,68 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid.util.ui.settings.fragment
+
+import android.app.Activity
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.MenuItem
+import com.afollestad.materialdialogs.MaterialDialog
+import de.kuschku.quasseldroid.R
+
+class SettingsFragmentHelper(
+  private val saveable: Savable?,
+  private val deletable: Deletable?
+) {
+  fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
+    inflater?.inflate(R.menu.context_setting, menu)
+    menu?.findItem(R.id.action_save)?.isVisible = saveable != null
+    menu?.findItem(R.id.action_delete)?.isVisible = deletable != null
+  }
+
+  fun onOptionsItemSelected(activity: Activity?, item: MenuItem?) = when (item?.itemId) {
+    R.id.action_save   -> {
+      saveable?.let {
+        if (it.onSave()) activity?.finish()
+      }
+      true
+    }
+    R.id.action_delete -> {
+      activity?.let {
+        deletable?.let {
+          MaterialDialog.Builder(activity)
+            .content(R.string.delete_confirmation)
+            .positiveText(R.string.label_yes)
+            .negativeText(R.string.label_no)
+            .negativeColorAttr(R.attr.colorTextPrimary)
+            .backgroundColorAttr(R.attr.colorBackgroundCard)
+            .contentColorAttr(R.attr.colorTextPrimary)
+            .onPositive { _, _ ->
+              it.onDelete()
+              activity.finish()
+            }
+            .build()
+            .show()
+        }
+      }
+      true
+    }
+    else               -> null
+  }
+}
diff --git a/app/src/main/res/layout/setup_account_connection.xml b/app/src/main/res/layout/setup_account_connection.xml
index 3ab65382f497d99a6f35bfd9012268ff72871444..a559d3928834b2d08e885f846474c38adbdf8198 100644
--- a/app/src/main/res/layout/setup_account_connection.xml
+++ b/app/src/main/res/layout/setup_account_connection.xml
@@ -58,4 +58,11 @@
       android:text="@string/defaultConnectionPort" />
   </com.google.android.material.textfield.TextInputLayout>
 
+  <androidx.appcompat.widget.SwitchCompat
+    android:id="@+id/require_ssl"
+    style="@style/Widget.CoreSettings.PrimaryItemSwitch"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:text="@string/label_connection_ssl" />
+
 </LinearLayout>
diff --git a/app/src/main/res/layout/setup_account_edit.xml b/app/src/main/res/layout/setup_account_edit.xml
index a5104672ac37bd9a9fa7b4130db1c6b2be82e577..96860d8540598f0a69a303872ca36e5308a62f8e 100644
--- a/app/src/main/res/layout/setup_account_edit.xml
+++ b/app/src/main/res/layout/setup_account_edit.xml
@@ -125,6 +125,13 @@
             android:text="@string/defaultConnectionPort"
             app:errorEnabled="true" />
         </com.google.android.material.textfield.TextInputLayout>
+
+        <androidx.appcompat.widget.SwitchCompat
+          android:id="@+id/require_ssl"
+          style="@style/Widget.CoreSettings.PrimaryItemSwitch"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/label_connection_ssl" />
       </LinearLayout>
     </LinearLayout>
 
diff --git a/app/src/main/res/layout/widget_core_backend.xml b/app/src/main/res/layout/widget_core_backend.xml
index 85324d285564a52917284a0e02f67afaed78fb80..4228a1b6f85699d93ca414f943ba83a3ffc965fc 100644
--- a/app/src/main/res/layout/widget_core_backend.xml
+++ b/app/src/main/res/layout/widget_core_backend.xml
@@ -3,16 +3,16 @@
   
   Copyright (c) 2019 Janne Koschinski
   Copyright (c) 2019 The Quassel Project
-  
+
   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License version 3 as published
   by the Free Software Foundation.
-  
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.
-  
+
   You should have received a copy of the GNU General Public License along
   with this program. If not, see <http://www.gnu.org/licenses/>.
   -->
diff --git a/app/src/main/res/values/strings_constants.xml b/app/src/main/res/values/strings_constants.xml
index 171da684971bf13f3f4a8cd5a6d301d92dbe61f2..92b980cb525faffdccf3496963468d9169c21730 100644
--- a/app/src/main/res/values/strings_constants.xml
+++ b/app/src/main/res/values/strings_constants.xml
@@ -1,4 +1,22 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?><!--
+  Quasseldroid - Quassel client for Android
+
+  Copyright (c) 2019 Janne Koschinski
+  Copyright (c) 2019 The Quassel Project
+
+  This program is free software: you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 3 as published
+  by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program. If not, see <http://www.gnu.org/licenses/>.
+  -->
+
 <resources>
   <string name="package_name" translatable="false">com.iskrembilen.quasseldroid</string>
 
diff --git a/app/src/main/res/values/strings_error.xml b/app/src/main/res/values/strings_error.xml
index 2e8fd0884eb10ce9f5d5f76b386ae1327da30fa7..66ad90d7b3291934fe88d04a11995207c3f617ae 100644
--- a/app/src/main/res/values/strings_error.xml
+++ b/app/src/main/res/values/strings_error.xml
@@ -21,6 +21,8 @@
   <string name="label_error_login">Login Error</string>
   <string name="label_error_setup">Setup Error</string>
   <string name="label_error_init">Connection Error</string>
+  <string name="label_error_ssl">SSL Error</string>
+  <string name="label_error_ssl_required_unavailable">SSL is required for this connection but the core does not support it.</string>
   <string name="label_error_certificate">Certificate Error</string>
   <string name="label_error_certificate_no_certificate">No certificate available</string>
   <string name="label_error_certificate_no_hostname">No hostname available</string>
diff --git a/app/src/main/res/values/strings_setup.xml b/app/src/main/res/values/strings_setup.xml
index 728420f946301f80c1ed1389c4b324bedce979bd..e6cbc99dd7c520a47b56f5f6f16c93312b27e4c4 100644
--- a/app/src/main/res/values/strings_setup.xml
+++ b/app/src/main/res/values/strings_setup.xml
@@ -31,6 +31,7 @@
 
   <string name="label_connection_host">Host</string>
   <string name="label_connection_port">Port</string>
+  <string name="label_connection_ssl">Require SSL</string>
 
   <string name="hint_invalid_host">Not a valid hostname</string>
   <string name="hint_invalid_port">Not a valid port</string>
diff --git a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
index fd50ab783063c7520898977a67d1a1b240197d4c..668c0546f776fa46fd3ee3419b3092e4271ce1fd 100644
--- a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
@@ -55,6 +55,7 @@ import javax.net.ssl.X509TrustManager
 class CoreConnection(
   private val address: SocketAddress,
   private val clientData: ClientData = ClientData.DEFAULT,
+  private val requireSsl: Boolean = false,
   private val features: Features = Features(clientData.clientFeatures, QuasselFeatures.empty()),
   private val handlerService: HandlerService = JavaHandlerService(),
   private val trustManager: X509TrustManager = TrustManagers.default(),
@@ -139,6 +140,9 @@ class CoreConnection(
     // Wrap socket in SSL context if ssl is enabled
     if (protocol.flags.hasFlag(ProtocolFeature.TLS)) {
       channel = channel?.withSSL(trustManager, hostnameVerifier, address)
+    } else if (requireSsl) {
+      securityExceptionCallback?.invoke(QuasselSecurityException.NoSsl)
+      close()
     }
 
     // Wrap socket in deflater if compression is enabled
diff --git a/lib/src/main/java/de/kuschku/libquassel/connection/QuasselSecurityException.kt b/lib/src/main/java/de/kuschku/libquassel/connection/QuasselSecurityException.kt
index 6cfc13ae5383827c439ed0b01fd9c4fe7b9ee024..d358ba9242de62a077ae01d5d6f2778e4d928c47 100644
--- a/lib/src/main/java/de/kuschku/libquassel/connection/QuasselSecurityException.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/connection/QuasselSecurityException.kt
@@ -24,7 +24,7 @@ import java.security.cert.X509Certificate
 
 sealed class QuasselSecurityException(
   val certificateChain: Array<out X509Certificate>?,
-  cause: Throwable
+  cause: Throwable?
 ) : GeneralSecurityException(cause) {
   class Certificate(
     certificateChain: Array<out X509Certificate>?,
@@ -36,4 +36,6 @@ sealed class QuasselSecurityException(
     val address: SocketAddress,
     cause: Exception
   ) : QuasselSecurityException(certificateChain, cause)
+
+  object NoSsl : QuasselSecurityException(emptyArray(), null)
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt b/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
index eaea5680ee74f75bdf82d9711798167dd506dc38..1ebfc9b92c539815d291316fdd05fa53015d74b4 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
@@ -22,8 +22,11 @@ package de.kuschku.libquassel.session
 import de.kuschku.libquassel.connection.SocketAddress
 
 interface Backend {
-  fun connectUnlessConnected(address: SocketAddress, user: String, pass: String, reconnect: Boolean)
-  fun connect(address: SocketAddress, user: String, pass: String, reconnect: Boolean)
+  fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
+                             requireSsl: Boolean, reconnect: Boolean)
+
+  fun connect(address: SocketAddress, user: String, pass: String, requireSsl: Boolean,
+              reconnect: Boolean)
   fun reconnect()
   fun disconnect(forever: Boolean = false)
   fun sessionManager(): SessionManager?
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
index f454b3c97943cb8f73787cdeef1dff2c169898b3..6d9cbaae65d7ab6d99b4e995678c7ae19f5b194e 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -42,6 +42,7 @@ import javax.net.ssl.X509TrustManager
 class Session(
   address: SocketAddress,
   private var userData: Pair<String, String>,
+  requireSsl: Boolean = false,
   trustManager: X509TrustManager = TrustManagers.default(),
   hostnameVerifier: HostnameVerifier = BrowserCompatibleHostnameVerifier(),
   clientData: ClientData = ClientData.DEFAULT,
@@ -64,6 +65,7 @@ class Session(
   private val coreConnection = CoreConnection(
     address,
     clientData,
+    requireSsl,
     features,
     handlerService,
     trustManager,
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
index d5f18920ccf38d88d17e0d61e8a1bae3dbe3fce3..c300b207f627738384ec2249fb6889e3c89ba960 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
@@ -116,6 +116,7 @@ class SessionManager(
     hostnameVerifier: HostnameVerifier,
     address: SocketAddress,
     userData: Pair<String, String>,
+    requireSsl: Boolean,
     shouldReconnect: Boolean = false
   ) {
     log(DEBUG, "SessionManager", "Connecting")
@@ -131,6 +132,7 @@ class SessionManager(
       Session(
         address,
         userData,
+        requireSsl,
         trustManager,
         hostnameVerifier,
         clientData,
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt
index 47cc6701afc696a30d15218997479041507e3d68..762ee9808b143d472450e693ac8a7ce41a6a8115 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt
@@ -1,3 +1,22 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
 package de.kuschku.libquassel.util.helpers
 
 
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt
index e8e4389d402a0d0f629e47ca5bcd1a36cedbcdad..b770c14f726d58948fae51ce7bd504154eb7d458 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt
@@ -1,3 +1,22 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
 package de.kuschku.libquassel.quassel
 
 import de.kuschku.libquassel.protocol.Buffer_Type
diff --git a/malheur/build.gradle.kts b/malheur/build.gradle.kts
index e3a0236a695ddd297cdb3c9bccab436f6c5a8a4d..985a0aa8788c12e3ec077cb11dd999a0820d1430 100644
--- a/malheur/build.gradle.kts
+++ b/malheur/build.gradle.kts
@@ -39,7 +39,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    lintConfig = file("../lint.xml")
+    setLintConfig(file("../lint.xml"))
   }
 }
 
diff --git a/persistence/build.gradle.kts b/persistence/build.gradle.kts
index b6f8fcd14b8e41b8e8b74b9b76a00eefe4b968e0..e2b8209df5f25d14c00aa4c7687d096cd39eaf2a 100644
--- a/persistence/build.gradle.kts
+++ b/persistence/build.gradle.kts
@@ -46,7 +46,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    lintConfig = file("../lint.xml")
+    setLintConfig(file("../lint.xml"))
   }
 }
 
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt
index 08d2df1712b10f486ae6ef93930022e97a2f0856..2c1392a3b946ecd74a4a0761601cbabf91783b35 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt
@@ -25,7 +25,7 @@ import androidx.room.*
 import androidx.room.migration.Migration
 import androidx.sqlite.db.SupportSQLiteDatabase
 
-@Database(entities = [(AccountDatabase.Account::class)], version = 3)
+@Database(entities = [(AccountDatabase.Account::class)], version = 4)
 abstract class AccountDatabase : RoomDatabase() {
   abstract fun accounts(): AccountDao
 
@@ -35,6 +35,7 @@ abstract class AccountDatabase : RoomDatabase() {
     var id: Long,
     var host: String,
     var port: Int,
+    var requireSsl: Boolean,
     var user: String,
     var pass: String,
     var name: String,
@@ -93,6 +94,11 @@ abstract class AccountDatabase : RoomDatabase() {
                 override fun migrate(database: SupportSQLiteDatabase) {
                   database.execSQL("ALTER TABLE account ADD COLUMN defaultFiltered INTEGER NOT NULL DEFAULT 0;")
                 }
+              },
+              object : Migration(3, 4) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("ALTER TABLE account ADD COLUMN requireSsl INTEGER NOT NULL DEFAULT 0;")
+                }
               }
             ).allowMainThreadQueries().build()
           }
diff --git a/viewmodel/build.gradle.kts b/viewmodel/build.gradle.kts
index 8e917ce39db16173e493546fc7f94111d1f8d6bd..e7d57a2667160fbb2d3f4e8cff3626ebb9696a62 100644
--- a/viewmodel/build.gradle.kts
+++ b/viewmodel/build.gradle.kts
@@ -39,7 +39,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    lintConfig = file("../lint.xml")
+    setLintConfig(file("../lint.xml"))
   }
 }