diff --git a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt
index a1c31e5203a1bd5013793b5e23118210b165a357..505d431ca2e0e708ff36a9784d4912363db33ba9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt
@@ -27,8 +27,9 @@ import dagger.android.AndroidInjector
 import dagger.android.support.DaggerApplication
 import de.kuschku.malheur.CrashHandler
 import de.kuschku.quasseldroid.dagger.DaggerAppComponent
-import de.kuschku.quasseldroid.persistence.AccountDatabase
-import de.kuschku.quasseldroid.persistence.LegacyAccountDatabase
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.LegacyAccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.SettingsMigration
 import de.kuschku.quasseldroid.settings.SettingsMigrationManager
@@ -76,7 +77,7 @@ open class Quasseldroid : DaggerApplication() {
 
           val accountDatabase = AccountDatabase.Creator.init(this)
           accountDatabase.accounts().create(*accounts.map {
-            AccountDatabase.Account(
+            Account(
               id = it.id,
               host = it.host,
               port = it.port,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/dagger/DatabaseModule.kt b/app/src/main/java/de/kuschku/quasseldroid/dagger/DatabaseModule.kt
index 8b1934affa5346f3123ce338be96646e9dd728db..6adf83b3f5ffd2bb7ec0d4d878cb55c1f2e2002a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/dagger/DatabaseModule.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/dagger/DatabaseModule.kt
@@ -22,8 +22,8 @@ package de.kuschku.quasseldroid.dagger
 import android.content.Context
 import dagger.Module
 import dagger.Provides
-import de.kuschku.quasseldroid.persistence.AccountDatabase
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
 
 @Module
 class DatabaseModule {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt
index 01e9893cd1c0c56fe6f2f5464dc9fd501ede0f90..41cfe8e370ea8cfa52f538735acb8d3a240a565a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt
@@ -26,7 +26,11 @@ import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 import de.kuschku.libquassel.util.helpers.value
-import de.kuschku.quasseldroid.persistence.*
+import de.kuschku.quasseldroid.persistence.dao.findFirstByBufferId
+import de.kuschku.quasseldroid.persistence.dao.get
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.util.QuasselBacklogStorage
 import de.kuschku.quasseldroid.viewmodel.QuasselViewModel
 
 class BacklogRequester(
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
index c3b1ae0e3d1441d1d396b10e3426eb5e2ef32260..c5876e6bac5338c70cec8665404f4080336216bc 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
@@ -37,10 +37,11 @@ import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.GlideApp
 import de.kuschku.quasseldroid.GlideRequest
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
-import de.kuschku.quasseldroid.persistence.all
-import de.kuschku.quasseldroid.persistence.buffers
-import de.kuschku.quasseldroid.persistence.markRead
+import de.kuschku.quasseldroid.persistence.dao.all
+import de.kuschku.quasseldroid.persistence.dao.buffers
+import de.kuschku.quasseldroid.persistence.dao.markRead
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.NotificationData
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.settings.NotificationSettings
@@ -227,7 +228,7 @@ class QuasselNotificationBackend @Inject constructor(
     }.map {
       val network = session.network(it.bufferInfo.networkId)
       val me = network?.me()
-      QuasselDatabase.NotificationData.of(
+      NotificationData.of(
         messageId = it.messageId,
         creationTime = now,
         time = it.time,
@@ -254,7 +255,7 @@ class QuasselNotificationBackend @Inject constructor(
     if (show) {
       executor.schedule(
         {
-          results.map(QuasselDatabase.NotificationData::bufferId).distinct().forEach { buffer ->
+          results.map(NotificationData::bufferId).distinct().forEach { buffer ->
             this.showNotification(buffer)
           }
         },
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 a4fd817e3ea524bd61013cf20dae65d6eb5a1cd4..f4e038caccb410002aa654f774b2ade3a1b6a4ac 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
@@ -45,7 +45,13 @@ import de.kuschku.quasseldroid.BuildConfig
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.Defaults
-import de.kuschku.quasseldroid.persistence.*
+import de.kuschku.quasseldroid.persistence.dao.buffers
+import de.kuschku.quasseldroid.persistence.dao.clear
+import de.kuschku.quasseldroid.persistence.dao.markHidden
+import de.kuschku.quasseldroid.persistence.dao.markReadNormal
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.util.QuasselBacklogStorage
 import de.kuschku.quasseldroid.settings.ConnectionSettings
 import de.kuschku.quasseldroid.settings.NotificationSettings
 import de.kuschku.quasseldroid.settings.Settings
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselCertificateManager.kt b/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselCertificateManager.kt
index da115f23f24f75be8654657c44ed2ba1e4238158..5832ba71b771a3b527de6e41d90759ee0d9a8426 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselCertificateManager.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselCertificateManager.kt
@@ -19,13 +19,13 @@
 
 package de.kuschku.quasseldroid.ssl.custom
 
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.dao.SslValidityWhitelistDao
 import de.kuschku.quasseldroid.util.helper.isValid
 import de.kuschku.quasseldroid.util.helper.sha1Fingerprint
 import java.security.cert.X509Certificate
 
 class QuasselCertificateManager(
-  private val validityWhitelist: QuasselDatabase.SslValidityWhitelistDao
+  private val validityWhitelist: SslValidityWhitelistDao
 ) {
   fun isServerTrusted(chain: Array<out X509Certificate>?): Boolean {
     // Verify input conditions
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselHostnameManager.kt b/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselHostnameManager.kt
index 7472b5cdff1d5c6df64180ed3c4799164ae6406c..94eff4c6e7e11c8eb942b4f24f21faf9aab4e870 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselHostnameManager.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ssl/custom/QuasselHostnameManager.kt
@@ -20,12 +20,12 @@
 package de.kuschku.quasseldroid.ssl.custom
 
 import de.kuschku.libquassel.connection.SocketAddress
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.dao.SslHostnameWhitelistDao
 import de.kuschku.quasseldroid.util.helper.sha1Fingerprint
 import java.security.cert.X509Certificate
 
 class QuasselHostnameManager(
-  private val hostnameWhitelist: QuasselDatabase.SslHostnameWhitelistDao
+  private val hostnameWhitelist: SslHostnameWhitelistDao
 ) {
   fun isValid(address: SocketAddress, chain: Array<out X509Certificate>): Boolean {
     val leafCertificate = chain.firstOrNull() ?: return false
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 cf52ec8cc42ed2c05d4b014b3d7a02fe0518025a..61c4db0e197f26a3d0115ff12aa1552c4f553c60 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
@@ -64,7 +64,14 @@ import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.DefaultNetworkServer
-import de.kuschku.quasseldroid.persistence.*
+import de.kuschku.quasseldroid.persistence.dao.clear
+import de.kuschku.quasseldroid.persistence.dao.get
+import de.kuschku.quasseldroid.persistence.dao.setFiltered
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.Filtered
+import de.kuschku.quasseldroid.persistence.models.SslHostnameWhitelistEntry
+import de.kuschku.quasseldroid.persistence.models.SslValidityWhitelistEntry
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.settings.Settings
@@ -465,7 +472,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                         .onPositive { _, _ ->
                           runInBackground {
                             database.validityWhitelist().save(
-                              QuasselDatabase.SslValidityWhitelistEntry(
+                              SslValidityWhitelistEntry(
                                 fingerprint = leafCertificate.sha1Fingerprint,
                                 ignoreDate = true
                               )
@@ -502,14 +509,14 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                         .onPositive { _, _ ->
                           runInBackground {
                             database.validityWhitelist().save(
-                              QuasselDatabase.SslValidityWhitelistEntry(
+                              SslValidityWhitelistEntry(
                                 fingerprint = leafCertificate.sha1Fingerprint,
                                 ignoreDate = !leafCertificate.isValid
                               )
                             )
                             accountDatabase.accounts().findById(accountId)?.let {
                               database.hostnameWhitelist().save(
-                                QuasselDatabase.SslHostnameWhitelistEntry(
+                                SslHostnameWhitelistEntry(
                                   fingerprint = leafCertificate.sha1Fingerprint,
                                   hostname = it.host
                                 )
@@ -548,7 +555,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                         .onPositive { _, _ ->
                           runInBackground {
                             database.hostnameWhitelist().save(
-                              QuasselDatabase.SslHostnameWhitelistEntry(
+                              SslHostnameWhitelistEntry(
                                 fingerprint = leafCertificate.sha1Fingerprint,
                                 hostname = it.address.host
                               )
@@ -892,7 +899,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   .fold(Message_Type.of()) { acc, i -> acc or i }
 
                 database.filtered().replace(
-                  QuasselDatabase.Filtered.of(accountId, buffer, newlyFiltered.value.toInt())
+                  Filtered.of(accountId, buffer, newlyFiltered.value.toInt())
                 )
               }
             }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt
index 122e7c9a7b64c331121fba246cffd47deb6bc46d..80ebec8a88cc5892b5e10b1fb9c5e9b04294a687 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt
@@ -51,8 +51,8 @@ import de.kuschku.libquassel.util.helpers.mapOrElse
 import de.kuschku.libquassel.util.helpers.nullIf
 import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.AccountDatabase
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.chat.ChatActivity
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt
index 945d7b63587b1f57d85cc0ee37baf3f7ac61f8e1..f1bb904e5bb48274b176d083b6c8abbb75b3eb31 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/DisplayMessage.kt
@@ -22,10 +22,10 @@ package de.kuschku.quasseldroid.ui.chat.messages
 import de.kuschku.libquassel.protocol.Message_Flag
 import de.kuschku.libquassel.protocol.MsgId
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 
 data class DisplayMessage(
-  val content: QuasselDatabase.MessageData,
+  val content: MessageData,
   val hasDayChange: Boolean,
   val isFollowUp: Boolean,
   val isSelected: Boolean,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
index 95e31b7966b6b164ac0f29af95418c903a3e5929..bbee9923ab078486aa37698818cf953ed891dd07 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
@@ -35,7 +35,7 @@ import de.kuschku.libquassel.protocol.Message_Flag
 import de.kuschku.libquassel.protocol.Message_Type
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.util.helper.getOrPut
 import de.kuschku.quasseldroid.util.helper.loadAvatars
@@ -58,9 +58,9 @@ class MessageAdapter @Inject constructor(
   private val movementMethod = BetterLinkMovementMethod.newInstance()
   private var clickListener: ((FormattedMessage) -> Unit)? = null
   private var longClickListener: ((FormattedMessage) -> Unit)? = null
-  private var doubleClickListener: ((QuasselDatabase.MessageData) -> Unit)? = null
-  private var senderIconClickListener: ((QuasselDatabase.MessageData) -> Unit)? = null
-  private var expansionListener: ((QuasselDatabase.MessageData) -> Unit)? = null
+  private var doubleClickListener: ((MessageData) -> Unit)? = null
+  private var senderIconClickListener: ((MessageData) -> Unit)? = null
+  private var expansionListener: ((MessageData) -> Unit)? = null
   private var urlLongClickListener: ((TextView, String) -> Boolean)? = null
 
   fun setOnClickListener(listener: ((FormattedMessage) -> Unit)?) {
@@ -71,15 +71,15 @@ class MessageAdapter @Inject constructor(
     this.longClickListener = listener
   }
 
-  fun setOnDoubleClickListener(listener: ((QuasselDatabase.MessageData) -> Unit)?) {
+  fun setOnDoubleClickListener(listener: ((MessageData) -> Unit)?) {
     this.doubleClickListener = listener
   }
 
-  fun setOnSenderIconClickListener(listener: ((QuasselDatabase.MessageData) -> Unit)?) {
+  fun setOnSenderIconClickListener(listener: ((MessageData) -> Unit)?) {
     this.senderIconClickListener = listener
   }
 
-  fun setOnExpansionListener(listener: ((QuasselDatabase.MessageData) -> Unit)?) {
+  fun setOnExpansionListener(listener: ((MessageData) -> Unit)?) {
     this.expansionListener = listener
   }
 
@@ -180,9 +180,9 @@ class MessageAdapter @Inject constructor(
     itemView: View,
     clickListener: ((FormattedMessage) -> Unit)? = null,
     longClickListener: ((FormattedMessage) -> Unit)? = null,
-    doubleClickListener: ((QuasselDatabase.MessageData) -> Unit)? = null,
-    senderIconClickListener: ((QuasselDatabase.MessageData) -> Unit)? = null,
-    expansionListener: ((QuasselDatabase.MessageData) -> Unit)? = null,
+    doubleClickListener: ((MessageData) -> Unit)? = null,
+    senderIconClickListener: ((MessageData) -> Unit)? = null,
+    expansionListener: ((MessageData) -> Unit)? = null,
     movementMethod: BetterLinkMovementMethod
   ) : RecyclerView.ViewHolder(itemView) {
     @BindView(R.id.daychange_container)
@@ -226,7 +226,7 @@ class MessageAdapter @Inject constructor(
     var combined: TextView? = null
 
     private var message: FormattedMessage? = null
-    private var original: QuasselDatabase.MessageData? = null
+    private var original: MessageData? = null
 
     private val localClickListener = View.OnClickListener {
       message?.let {
@@ -266,7 +266,7 @@ class MessageAdapter @Inject constructor(
       avatar?.setOnClickListener(localSenderIconClickListener)
     }
 
-    fun bind(message: FormattedMessage, original: QuasselDatabase.MessageData,
+    fun bind(message: FormattedMessage, original: MessageData,
              hasDayChange: Boolean, messageSettings: MessageSettings) {
       this.message = message
       this.original = original
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
index 6e6ab231d71a597840ce75b508bfa10329e93da8..d129255f30457e11a0f24330e644a9a404b9154d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
@@ -55,7 +55,10 @@ import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.quasseldroid.GlideApp
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.*
+import de.kuschku.quasseldroid.persistence.dao.*
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 import de.kuschku.quasseldroid.service.BacklogRequester
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
@@ -333,9 +336,9 @@ class MessageListFragment : ServiceBoundFragment() {
       }
     })
 
-    fun processMessages(list: List<QuasselDatabase.MessageData>, selected: Set<MsgId>,
+    fun processMessages(list: List<MessageData>, selected: Set<MsgId>,
                         expanded: Set<MsgId>, markerLine: MsgId?): List<DisplayMessage> {
-      var previous: QuasselDatabase.MessageData? = null
+      var previous: MessageData? = null
       var previousDate: ZonedDateTime? = null
       return list.mapReverse {
         val date = it.time.atZone(ZoneId.systemDefault()).truncatedTo(ChronoUnit.DAYS)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt
index 811d18de4b22e919091548d14215fcf945276916..989603fe349859dec7f44b8e0b20e40ca97f54fd 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt
@@ -22,7 +22,7 @@ package de.kuschku.quasseldroid.ui.chat.messages
 import android.content.Context
 import androidx.annotation.LayoutRes
 import de.kuschku.libquassel.protocol.Message_Type
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 import de.kuschku.quasseldroid.viewmodel.data.FormattedMessage
 
 interface MessageRenderer {
@@ -34,7 +34,7 @@ interface MessageRenderer {
              isSelf: Boolean): Int
 
   fun bind(holder: MessageAdapter.QuasselMessageViewHolder, message: FormattedMessage,
-           original: QuasselDatabase.MessageData)
+           original: MessageData)
 
   fun render(context: Context, message: DisplayMessage): FormattedMessage
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
index 10de33940a827296e6fc66e2629a265cfadf77e4..c1a442171f58d2c4e0c2eec0701459bfb3747c30 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
@@ -37,7 +37,7 @@ import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
@@ -228,7 +228,7 @@ class QuasselMessageRenderer @Inject constructor(
   }
 
   override fun bind(holder: MessageAdapter.QuasselMessageViewHolder, message: FormattedMessage,
-                    original: QuasselDatabase.MessageData) =
+                    original: MessageData) =
     holder.bind(message,
                 original,
                 hasDayChange = message.hasDayChange,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/Whitelist.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/Whitelist.kt
index b330c7fba2815a29601c8e624d1f8e62a808c026..fff99e69454066aefb3850edc298e9510804b511 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/Whitelist.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/Whitelist.kt
@@ -19,9 +19,10 @@
 
 package de.kuschku.quasseldroid.ui.clientsettings.whitelist
 
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.SslHostnameWhitelistEntry
+import de.kuschku.quasseldroid.persistence.models.SslValidityWhitelistEntry
 
 data class Whitelist(
-  val certificates: List<QuasselDatabase.SslValidityWhitelistEntry>,
-  val hostnames: List<QuasselDatabase.SslHostnameWhitelistEntry>
+  val certificates: List<SslValidityWhitelistEntry>,
+  val hostnames: List<SslHostnameWhitelistEntry>
 )
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistCertificateAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistCertificateAdapter.kt
index 2e64005e9bba2708505f5026fd5a7b8ff5a1e8a0..6b8c16b3b4f54c4a3bad0384d982d14e91c935cd 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistCertificateAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistCertificateAdapter.kt
@@ -28,25 +28,25 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.SslValidityWhitelistEntry
 import de.kuschku.quasseldroid.util.helper.setTooltip
 import de.kuschku.quasseldroid.util.helper.visibleIf
 
 class WhitelistCertificateAdapter :
   RecyclerView.Adapter<WhitelistCertificateAdapter.WhitelistItemViewHolder>() {
-  private var clickListener: ((QuasselDatabase.SslValidityWhitelistEntry) -> Unit)? = null
-  private var updateListener: ((List<QuasselDatabase.SslValidityWhitelistEntry>) -> Unit)? = null
+  private var clickListener: ((SslValidityWhitelistEntry) -> Unit)? = null
+  private var updateListener: ((List<SslValidityWhitelistEntry>) -> Unit)? = null
 
-  fun setOnClickListener(listener: ((QuasselDatabase.SslValidityWhitelistEntry) -> Unit)?) {
+  fun setOnClickListener(listener: ((SslValidityWhitelistEntry) -> Unit)?) {
     clickListener = listener
   }
 
-  fun setOnUpdateListener(listener: ((List<QuasselDatabase.SslValidityWhitelistEntry>) -> Unit)?) {
+  fun setOnUpdateListener(listener: ((List<SslValidityWhitelistEntry>) -> Unit)?) {
     updateListener = listener
   }
 
-  private val data = mutableListOf<QuasselDatabase.SslValidityWhitelistEntry>()
-  var list: List<QuasselDatabase.SslValidityWhitelistEntry>
+  private val data = mutableListOf<SslValidityWhitelistEntry>()
+  var list: List<SslValidityWhitelistEntry>
     get() = data
     set(value) {
       val length = data.size
@@ -57,20 +57,20 @@ class WhitelistCertificateAdapter :
       updateListener?.invoke(list)
     }
 
-  fun add(item: QuasselDatabase.SslValidityWhitelistEntry) {
+  fun add(item: SslValidityWhitelistEntry) {
     val index = data.size
     data.add(item)
     notifyItemInserted(index)
     updateListener?.invoke(list)
   }
 
-  fun replace(index: Int, item: QuasselDatabase.SslValidityWhitelistEntry) {
+  fun replace(index: Int, item: SslValidityWhitelistEntry) {
     data[index] = item
     notifyItemChanged(index)
     updateListener?.invoke(list)
   }
 
-  fun indexOf(item: QuasselDatabase.SslValidityWhitelistEntry) = data.indexOf(item)
+  fun indexOf(item: SslValidityWhitelistEntry) = data.indexOf(item)
 
   fun remove(index: Int) {
     data.removeAt(index)
@@ -78,7 +78,7 @@ class WhitelistCertificateAdapter :
     updateListener?.invoke(list)
   }
 
-  fun remove(item: QuasselDatabase.SslValidityWhitelistEntry) = remove(indexOf(item))
+  fun remove(item: SslValidityWhitelistEntry) = remove(indexOf(item))
 
   override fun getItemCount() = data.size
 
@@ -95,7 +95,7 @@ class WhitelistCertificateAdapter :
 
   class WhitelistItemViewHolder(
     itemView: View,
-    clickListener: ((QuasselDatabase.SslValidityWhitelistEntry) -> Unit)?
+    clickListener: ((SslValidityWhitelistEntry) -> Unit)?
   ) : RecyclerView.ViewHolder(itemView) {
     @BindView(R.id.fingerprint)
     lateinit var fingerprint: TextView
@@ -106,7 +106,7 @@ class WhitelistCertificateAdapter :
     @BindView(R.id.action_delete)
     lateinit var delete: AppCompatImageButton
 
-    private var item: QuasselDatabase.SslValidityWhitelistEntry? = null
+    private var item: SslValidityWhitelistEntry? = null
 
     init {
       ButterKnife.bind(this, itemView)
@@ -118,7 +118,7 @@ class WhitelistCertificateAdapter :
       delete.setTooltip()
     }
 
-    fun bind(item: QuasselDatabase.SslValidityWhitelistEntry) {
+    fun bind(item: SslValidityWhitelistEntry) {
       this.item = item
       fingerprint.text = item.fingerprint
       ignoreDate.visibleIf(item.ignoreDate)
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 82c89cadebb6c56160298430ea02356b250b1f91..354a8d9796c0612ea8cfb42d171adfdf3c4a5cac 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
@@ -33,7 +33,7 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
 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
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistHostnameAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistHostnameAdapter.kt
index 9f48103209db59c1fc0ef4d0f8478ccb2a454561..d90a89ff70516cf9c6d7de9277aeee931f3603d0 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistHostnameAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/clientsettings/whitelist/WhitelistHostnameAdapter.kt
@@ -28,19 +28,19 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.SslHostnameWhitelistEntry
 import de.kuschku.quasseldroid.util.helper.setTooltip
 
 class WhitelistHostnameAdapter :
   RecyclerView.Adapter<WhitelistHostnameAdapter.WhitelistItemViewHolder>() {
-  private var updateListener: ((List<QuasselDatabase.SslHostnameWhitelistEntry>) -> Unit)? = null
+  private var updateListener: ((List<SslHostnameWhitelistEntry>) -> Unit)? = null
 
-  fun setOnUpdateListener(listener: ((List<QuasselDatabase.SslHostnameWhitelistEntry>) -> Unit)?) {
+  fun setOnUpdateListener(listener: ((List<SslHostnameWhitelistEntry>) -> Unit)?) {
     updateListener = listener
   }
 
-  private val data = mutableListOf<QuasselDatabase.SslHostnameWhitelistEntry>()
-  var list: List<QuasselDatabase.SslHostnameWhitelistEntry>
+  private val data = mutableListOf<SslHostnameWhitelistEntry>()
+  var list: List<SslHostnameWhitelistEntry>
     get() = data
     set(value) {
       val length = data.size
@@ -51,20 +51,20 @@ class WhitelistHostnameAdapter :
       updateListener?.invoke(list)
     }
 
-  fun add(item: QuasselDatabase.SslHostnameWhitelistEntry) {
+  fun add(item: SslHostnameWhitelistEntry) {
     val index = data.size
     data.add(item)
     notifyItemInserted(index)
     updateListener?.invoke(list)
   }
 
-  fun replace(index: Int, item: QuasselDatabase.SslHostnameWhitelistEntry) {
+  fun replace(index: Int, item: SslHostnameWhitelistEntry) {
     data[index] = item
     notifyItemChanged(index)
     updateListener?.invoke(list)
   }
 
-  fun indexOf(item: QuasselDatabase.SslHostnameWhitelistEntry) = data.indexOf(item)
+  fun indexOf(item: SslHostnameWhitelistEntry) = data.indexOf(item)
 
   fun remove(index: Int) {
     data.removeAt(index)
@@ -72,7 +72,7 @@ class WhitelistHostnameAdapter :
     updateListener?.invoke(list)
   }
 
-  fun remove(item: QuasselDatabase.SslHostnameWhitelistEntry) = remove(indexOf(item))
+  fun remove(item: SslHostnameWhitelistEntry) = remove(indexOf(item))
 
   override fun getItemCount() = data.size
 
@@ -89,7 +89,7 @@ class WhitelistHostnameAdapter :
 
   class WhitelistItemViewHolder(
     itemView: View,
-    clickListener: ((QuasselDatabase.SslHostnameWhitelistEntry) -> Unit)?
+    clickListener: ((SslHostnameWhitelistEntry) -> Unit)?
   ) : RecyclerView.ViewHolder(itemView) {
     @BindView(R.id.hostname)
     lateinit var hostname: TextView
@@ -100,7 +100,7 @@ class WhitelistHostnameAdapter :
     @BindView(R.id.action_delete)
     lateinit var delete: AppCompatImageButton
 
-    private var item: QuasselDatabase.SslHostnameWhitelistEntry? = null
+    private var item: SslHostnameWhitelistEntry? = null
 
     init {
       ButterKnife.bind(this, itemView)
@@ -112,7 +112,7 @@ class WhitelistHostnameAdapter :
       delete.setTooltip()
     }
 
-    fun bind(item: QuasselDatabase.SslHostnameWhitelistEntry) {
+    fun bind(item: SslHostnameWhitelistEntry) {
       this.item = item
       hostname.text = item.hostname
       fingerprint.text = item.fingerprint
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt
index a109cc96dab4afaa19002d2e673add95fdaa44ce..63c62f011d0154aedf1ee4e773be440dd2a7927f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt
@@ -38,7 +38,8 @@ import de.kuschku.libquassel.util.helpers.mapMapNullable
 import de.kuschku.libquassel.util.helpers.mapSwitchMap
 import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.util.TextValidator
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
@@ -76,7 +77,7 @@ class PasswordChangeFragment : ServiceBoundFragment() {
   @Inject
   lateinit var accountDatabase: AccountDatabase
 
-  private var waiting: AccountDatabase.Account? = null
+  private var waiting: Account? = null
 
   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                             savedInstanceState: Bundle?): View? {
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
index 3f6907436b2e74649bec0ecde614162defab3ee9..2e1007e69ba8e9f6fa5b3f4f9412ed87d3006078 100644
--- 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
@@ -35,7 +35,8 @@ 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.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.util.Patterns
 import de.kuschku.quasseldroid.util.TextValidator
 import de.kuschku.quasseldroid.util.helper.editCommit
@@ -77,7 +78,7 @@ class AccountEditFragment : SettingsFragment(), Changeable, Savable, Deletable {
   @Inject
   lateinit var database: AccountDatabase
 
-  private var account: AccountDatabase.Account? = null
+  private var account: Account? = null
   private var accountId: Long = -1L
 
   private lateinit var handlerThread: HandlerThread
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt
index b33801a6d1538cfa89b44698163847ed9842f12f..dc922c52ddce93d68c08fad8855ff14bcba5e183 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt
@@ -35,12 +35,12 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.util.helper.zip
 
 class AccountAdapter(
   owner: LifecycleOwner,
-  liveData: LiveData<List<AccountDatabase.Account>>,
+  liveData: LiveData<List<Account>>,
   private val selectedItem: MutableLiveData<Pair<Long, Long>>
 ) : RecyclerView.Adapter<AccountAdapter.AccountViewHolder>() {
   private val actionListeners = mutableSetOf<(Long) -> Unit>()
@@ -77,7 +77,7 @@ class AccountAdapter(
   val selectedItemId
     get() = selectedItem.value?.second
 
-  private var list: List<Pair<Boolean, AccountDatabase.Account>> = emptyList()
+  private var list: List<Pair<Boolean, Account>> = emptyList()
 
   init {
     selectedItem.value = Pair(-1, -1)
@@ -88,7 +88,7 @@ class AccountAdapter(
       val selected = it?.second?.second ?: -1
 
       val oldList = this.list
-      val newList: List<Pair<Boolean, AccountDatabase.Account>> = list.orEmpty().map {
+      val newList: List<Pair<Boolean, Account>> = list.orEmpty().map {
         Pair(selected == it.id, it)
       }
       this.list = newList
@@ -220,7 +220,7 @@ class AccountAdapter(
         }
       }
 
-      fun bind(account: AccountDatabase.Account, selected: Boolean) {
+      fun bind(account: Account, selected: Boolean) {
         id = account.id
         accountName.text = account.name
         accountDescription.text = itemView.context.resources.getString(
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountSelectionSlide.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountSelectionSlide.kt
index 7bdd23ca8eb340078130661d3d1856867a99a700..d6aa6bd165b7f4bb9c147a274ab22ac21fcd848d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountSelectionSlide.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountSelectionSlide.kt
@@ -32,7 +32,7 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.ui.setup.SlideFragment
 import de.kuschku.quasseldroid.ui.setup.accounts.edit.AccountEditActivity
 import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionActivity.Companion.REQUEST_CREATE_FIRST
@@ -66,8 +66,8 @@ class AccountSelectionSlide : SlideFragment() {
                                savedInstanceState: Bundle?): View {
     val view = inflater.inflate(R.layout.setup_select_account, container, false)
     ButterKnife.bind(this, view)
-    val firstObserver = object : Observer<List<AccountDatabase.Account>?> {
-      override fun onChanged(t: List<AccountDatabase.Account>?) {
+    val firstObserver = object : Observer<List<Account>?> {
+      override fun onChanged(t: List<Account>?) {
         if (t?.isEmpty() != false)
           startActivityForResult(
             AccountSetupActivity.intent(requireContext()),
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountViewModel.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountViewModel.kt
index 49aa2ce2ccd7f24243e8641c03eac3d38a424755..f268e8b8f97ca1dba2d00d203538c67f07990ee9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountViewModel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountViewModel.kt
@@ -23,12 +23,13 @@ import android.app.Application
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 
 class AccountViewModel(application: Application) : AndroidViewModel(application) {
   private val database: AccountDatabase = AccountDatabase.Creator.init(
     getApplication()
   )
-  val accounts: LiveData<List<AccountDatabase.Account>> = database.accounts().all()
+  val accounts: LiveData<List<Account>> = database.accounts().all()
   val selectedItem = MutableLiveData<Pair<Long, Long>>()
 }
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 9a89d2fa8f4574f4083f2f8e3300ffe8dd5423e6..dab21b1e747d45327dcbf4573cf4a0ea2d719597 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
@@ -23,7 +23,8 @@ import android.app.Activity
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.db.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.ui.setup.SetupActivity
 import de.kuschku.quasseldroid.util.AndroidHandlerThread
 import org.threeten.bp.Instant
@@ -36,7 +37,7 @@ class AccountSetupActivity : SetupActivity() {
   lateinit var database: AccountDatabase
 
   override fun onDone(data: Bundle) {
-    val account = AccountDatabase.Account(
+    val account = Account(
       id = 0,
       host = data.getString("host", ""),
       port = data.getInt("port"),
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt
index 571d6278b2ee92462cfebca90545906bcde87c61..b77644f34379a399e5af0dfc52bca6a0389a33b5 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt
@@ -29,7 +29,7 @@ import de.kuschku.libquassel.protocol.coresetup.CoreSetupData
 import de.kuschku.libquassel.protocol.message.HandshakeMessage
 import de.kuschku.libquassel.quassel.ExtendedFeature
 import de.kuschku.libquassel.util.helpers.value
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.ui.setup.ServiceBoundSetupActivity
 
 class CoreSetupActivity : ServiceBoundSetupActivity() {
@@ -84,13 +84,13 @@ class CoreSetupActivity : ServiceBoundSetupActivity() {
   companion object {
     fun launch(
       context: Context,
-      account: AccountDatabase.Account? = null,
+      account: Account? = null,
       data: CoreSetupData? = null
     ) = context.startActivity(intent(context, account, data))
 
     fun intent(
       context: Context,
-      account: AccountDatabase.Account? = null,
+      account: Account? = null,
       data: CoreSetupData? = null
     ) = Intent(context, CoreSetupActivity::class.java).apply {
       if (account != null) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt
index cd6c36f16032006428a15c533c9b4311c201e090..09b536b35aca9960bb0d185f0eeba16fcdbd7e51 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt
@@ -22,7 +22,8 @@ package de.kuschku.quasseldroid.util.avatars
 import de.kuschku.libquassel.quassel.syncables.IrcUser
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
+import de.kuschku.quasseldroid.persistence.models.NotificationData
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.info.user.IrcUserInfo
 import de.kuschku.quasseldroid.util.Patterns
@@ -50,11 +51,11 @@ object AvatarHelper {
       }
     ).flatten()
 
-  fun avatar(settings: MessageSettings, message: QuasselDatabase.NotificationData,
+  fun avatar(settings: MessageSettings, message: NotificationData,
              size: Int? = null) =
     avatar(settings, HostmaskHelper.user(message.sender), message.realName, message.avatarUrl, size)
 
-  fun avatar(settings: MessageSettings, message: QuasselDatabase.MessageData, size: Int? = null) =
+  fun avatar(settings: MessageSettings, message: MessageData, size: Int? = null) =
     avatar(settings, HostmaskHelper.user(message.sender), message.realName, message.avatarUrl, size)
 
   fun avatar(settings: MessageSettings, user: IrcUserItem, size: Int? = null) =
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/helper/AccountDaoHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/helper/AccountDaoHelper.kt
index 100d42672834a01ac9fc7e07738fe20ca8a1c96b..27586108c0798459033c60649afea254e823e2ef 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/helper/AccountDaoHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/helper/AccountDaoHelper.kt
@@ -19,9 +19,10 @@
 
 package de.kuschku.quasseldroid.util.helper
 
-import de.kuschku.quasseldroid.persistence.AccountDatabase
+import de.kuschku.quasseldroid.persistence.dao.AccountDao
+import de.kuschku.quasseldroid.persistence.models.Account
 
-fun AccountDatabase.AccountDao.new(vararg entities: AccountDatabase.Account) {
+fun AccountDao.new(vararg entities: Account) {
   val ids = create(*entities)
   for (i in 0 until entities.size) {
     entities[i].id = ids[i]
diff --git a/app/src/test/java/de/kuschku/quasseldroid/util/AvatarHelperTest.kt b/app/src/test/java/de/kuschku/quasseldroid/util/AvatarHelperTest.kt
index 0f2f6743d0d995684da3c3db9e77d9f67bee0415..33a3df31989bf6fbb91334633cd1a8b420748a98 100644
--- a/app/src/test/java/de/kuschku/quasseldroid/util/AvatarHelperTest.kt
+++ b/app/src/test/java/de/kuschku/quasseldroid/util/AvatarHelperTest.kt
@@ -20,7 +20,7 @@
 package de.kuschku.quasseldroid.util
 
 import de.kuschku.libquassel.protocol.*
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
 import de.kuschku.quasseldroid.viewmodel.data.Avatar
@@ -30,7 +30,7 @@ import org.threeten.bp.Instant
 class AvatarHelperTest {
   @Test
   fun testGravatarAvatars() {
-    val message = QuasselDatabase.MessageData.of(
+    val message = MessageData.of(
       messageId = MsgId(1),
       time = Instant.now(),
       type = Message_Type.of(Message_Type.Plain),
@@ -70,7 +70,7 @@ class AvatarHelperTest {
 
   @Test
   fun testIrcCloudAvatars() {
-    val message = QuasselDatabase.MessageData.of(
+    val message = MessageData.of(
       messageId = MsgId(1),
       time = Instant.now(),
       type = Message_Type.of(Message_Type.Plain),
@@ -110,7 +110,7 @@ class AvatarHelperTest {
 
   @Test
   fun testActualAvatars() {
-    val message = QuasselDatabase.MessageData.of(
+    val message = MessageData.of(
       messageId = MsgId(1),
       time = Instant.now(),
       type = Message_Type.of(Message_Type.Plain),
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
deleted file mode 100644
index fbe433e5ea26c5f2c51d6b0cd1572dd93c9e56b3..0000000000000000000000000000000000000000
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
+++ /dev/null
@@ -1,501 +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/>.
- */
-@file:Suppress("NOTHING_TO_INLINE")
-package de.kuschku.quasseldroid.persistence
-
-import android.content.Context
-import androidx.lifecycle.LiveData
-import androidx.paging.DataSource
-import androidx.room.*
-import androidx.room.migration.Migration
-import androidx.sqlite.db.SupportSQLiteDatabase
-import de.kuschku.libquassel.protocol.*
-import de.kuschku.quasseldroid.persistence.QuasselDatabase.*
-import io.reactivex.Flowable
-import org.threeten.bp.Instant
-
-@Database(entities = [MessageData::class, Filtered::class, SslValidityWhitelistEntry::class, SslHostnameWhitelistEntry::class, NotificationData::class],
-          version = 19)
-@TypeConverters(MessageTypeConverter::class)
-abstract class QuasselDatabase : RoomDatabase() {
-  abstract fun message(): MessageDao
-  abstract fun filtered(): FilteredDao
-  abstract fun validityWhitelist(): SslValidityWhitelistDao
-  abstract fun hostnameWhitelist(): SslHostnameWhitelistDao
-  abstract fun notifications(): NotificationDao
-
-  @Entity(tableName = "message", indices = [Index("bufferId"), Index("ignored")])
-  data class MessageData(
-    @PrimaryKey
-    @ColumnInfo(name = "messageId")
-    var rawMessageId: MsgId_Type,
-    var time: Instant,
-    var type: Message_Types,
-    var flag: Message_Flags,
-    @ColumnInfo(name = "bufferId")
-    var rawBufferId: BufferId_Type,
-    @ColumnInfo(name = "networkId")
-    var rawNetworkId: NetworkId_Type,
-    var sender: String,
-    var senderPrefixes: String,
-    var realName: String,
-    var avatarUrl: String,
-    var content: String,
-    var ignored: Boolean
-  ) {
-    inline val messageId
-      get() = MsgId(rawMessageId)
-    inline val bufferId
-      get() = BufferId(rawBufferId)
-    inline val networkId
-      get() = NetworkId(rawNetworkId)
-
-    companion object {
-      inline fun of(
-        messageId: MsgId,
-        time: Instant,
-        type: Message_Types,
-        flag: Message_Flags,
-        bufferId: BufferId,
-        networkId: NetworkId,
-        sender: String,
-        senderPrefixes: String,
-        realName: String,
-        avatarUrl: String,
-        content: String,
-        ignored: Boolean
-      ) = MessageData(
-        messageId.id,
-        time,
-        type,
-        flag,
-        bufferId.id,
-        networkId.id,
-        sender,
-        senderPrefixes,
-        realName,
-        avatarUrl,
-        content,
-        ignored
-      )
-    }
-  }
-
-  @Dao
-  interface MessageDao {
-    @Query("SELECT * FROM message")
-    fun all(): List<MessageData>
-
-    @Query("SELECT DISTINCT bufferId FROM message")
-    fun _buffers(): List<BufferId_Type>
-
-    @Query("SELECT * FROM message WHERE messageId = :messageId")
-    fun find(messageId: MsgId_Type): MessageData?
-
-    @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC")
-    fun _findByBufferId(bufferId: BufferId_Type): List<MessageData>
-
-    @Query("SELECT * FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId DESC")
-    fun _findByBufferIdPaged(bufferId: BufferId_Type,
-                             type: Int): DataSource.Factory<Int, MessageData>
-
-    @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
-    fun _findLastByBufferId(bufferId: BufferId_Type): MessageData?
-
-    @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
-    fun _lastMsgId(bufferId: BufferId_Type): LiveData<MessageData>
-
-    @Query("SELECT messageId FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1")
-    fun _firstMsgId(bufferId: BufferId_Type): Flowable<MsgId_Type>
-
-    @Query("SELECT messageId FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId ASC LIMIT 1")
-    fun _firstVisibleMsgId(bufferId: BufferId_Type, type: Int): MsgId_Type?
-
-    @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1")
-    fun _findFirstByBufferId(bufferId: BufferId_Type): MessageData?
-
-    @Query("SELECT EXISTS(SELECT 1 FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0)")
-    fun _hasVisibleMessages(bufferId: BufferId_Type, type: Int): Boolean
-
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    fun save(vararg entities: MessageData)
-
-    @Query("UPDATE message SET bufferId = :bufferId1 WHERE bufferId = :bufferId2")
-    fun _merge(bufferId1: BufferId_Type, bufferId2: BufferId_Type)
-
-    @Query("SELECT count(*) FROM message WHERE bufferId = :bufferId")
-    fun _bufferSize(bufferId: BufferId_Type): Int
-
-    @Query("DELETE FROM message")
-    fun clearMessages()
-
-    @Query("DELETE FROM message WHERE bufferId = :bufferId")
-    fun clearMessages(bufferId: BufferId_Type)
-
-    @Query(
-      "DELETE FROM message WHERE bufferId = :bufferId AND messageId >= :first AND messageId <= :last"
-    )
-    fun clearMessages(bufferId: BufferId_Type, first: MsgId_Type, last: MsgId_Type)
-  }
-
-  @Entity(tableName = "filtered", primaryKeys = ["accountId", "bufferId"])
-  data class Filtered(
-    var accountId: Long,
-    @ColumnInfo(name = "bufferId")
-    var rawBufferId: BufferId_Type,
-    var filtered: Int
-  ) {
-    inline val bufferId
-      get() = BufferId(rawBufferId)
-
-    companion object {
-      inline fun of(
-        accountId: Long,
-        bufferId: BufferId,
-        filtered: Int
-      ) = Filtered(
-        accountId,
-        bufferId.id,
-        filtered
-      )
-    }
-  }
-
-  @Dao
-  interface FilteredDao {
-    @Query("SELECT DISTINCT bufferId FROM filtered WHERE accountId = :accountId")
-    fun _buffers(accountId: Long): List<BufferId_Type>
-
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    fun replace(vararg entities: Filtered)
-
-    @Query("UPDATE filtered SET filtered = :filtered WHERE accountId = :accountId AND bufferId = :bufferId")
-    fun _setFiltered(accountId: Long, bufferId: BufferId_Type, filtered: Int)
-
-    @Query("SELECT IFNULL(t.filtered, :defaultValue) FROM (SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT NULL ORDER BY filtered DESC LIMIT 1) t")
-    fun _get(accountId: Long, bufferId: BufferId_Type, defaultValue: Int): Int
-
-    @Query("SELECT IFNULL(t.filtered, :defaultValue) FROM (SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT NULL ORDER BY filtered DESC LIMIT 1) t")
-    fun _listen(accountId: Long, bufferId: BufferId_Type, defaultValue: Int): LiveData<Int>
-
-    @Query("SELECT * FROM filtered WHERE accountId = :accountId")
-    fun listen(accountId: Long): LiveData<List<Filtered>>
-
-    @Query("DELETE FROM filtered")
-    fun clear()
-
-    @Query("DELETE FROM filtered WHERE accountId = :accountId")
-    fun clear(accountId: Long)
-
-    @Query("DELETE FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId")
-    fun _clear(accountId: Long, bufferId: BufferId_Type)
-  }
-
-  @Entity(tableName = "ssl_validity_whitelist")
-  data class SslValidityWhitelistEntry(
-    @PrimaryKey
-    var fingerprint: String,
-    var ignoreDate: Boolean
-  )
-
-  @Dao
-  interface SslValidityWhitelistDao {
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    fun save(vararg entities: SslValidityWhitelistEntry)
-
-    @Query("SELECT * FROM ssl_validity_whitelist")
-    fun all(): List<SslValidityWhitelistEntry>
-
-    @Query("SELECT * FROM ssl_validity_whitelist WHERE fingerprint = :fingerprint")
-    fun find(fingerprint: String): SslValidityWhitelistEntry?
-
-    @Query("DELETE FROM ssl_validity_whitelist WHERE fingerprint = :fingerprint")
-    fun delete(fingerprint: String)
-
-    @Query("DELETE FROM ssl_validity_whitelist")
-    fun clear()
-  }
-
-  @Entity(tableName = "ssl_hostname_whitelist", primaryKeys = ["fingerprint", "hostname"])
-  data class SslHostnameWhitelistEntry(
-    var fingerprint: String,
-    var hostname: String
-  )
-
-  @Dao
-  interface SslHostnameWhitelistDao {
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    fun save(vararg entities: SslHostnameWhitelistEntry)
-
-    @Query("SELECT * FROM ssl_hostname_whitelist")
-    fun all(): List<SslHostnameWhitelistEntry>
-
-    @Query("SELECT * FROM ssl_hostname_whitelist WHERE fingerprint = :fingerprint AND hostname = :hostname")
-    fun find(fingerprint: String, hostname: String): SslHostnameWhitelistEntry?
-
-    @Query("DELETE FROM ssl_hostname_whitelist WHERE fingerprint = :fingerprint AND hostname = :hostname")
-    fun delete(fingerprint: String, hostname: String)
-
-    @Query("DELETE FROM ssl_hostname_whitelist")
-    fun clear()
-  }
-
-  @Entity(tableName = "notification", indices = [Index("bufferId")])
-  data class NotificationData(
-    @PrimaryKey
-    @ColumnInfo(name = "messageId")
-    var rawMessageId: MsgId_Type,
-    var creationTime: Instant,
-    var time: Instant,
-    var type: Message_Types,
-    var flag: Message_Flags,
-    @ColumnInfo(name = "bufferId")
-    var rawBufferId: BufferId_Type,
-    var bufferName: String,
-    var bufferType: Buffer_Types,
-    @ColumnInfo(name = "networkId")
-    var rawNetworkId: NetworkId_Type,
-    var networkName: String,
-    var sender: String,
-    var senderPrefixes: String,
-    var realName: String,
-    var avatarUrl: String,
-    var content: String,
-    var ownNick: String,
-    var ownIdent: String,
-    var ownRealName: String,
-    var ownAvatarUrl: String,
-    var hidden: Boolean
-  ) {
-    inline val messageId
-      get() = MsgId(rawMessageId)
-
-    inline val bufferId
-      get() = BufferId(rawBufferId)
-
-    inline val networkId
-      get() = NetworkId(rawNetworkId)
-
-    companion object {
-      inline fun of(
-        messageId: MsgId,
-        creationTime: Instant,
-        time: Instant,
-        type: Message_Types,
-        flag: Message_Flags,
-        bufferId: BufferId,
-        bufferName: String,
-        bufferType: Buffer_Types,
-        networkId: NetworkId,
-        networkName: String,
-        sender: String,
-        senderPrefixes: String,
-        realName: String,
-        avatarUrl: String,
-        content: String,
-        ownNick: String,
-        ownIdent: String,
-        ownRealName: String,
-        ownAvatarUrl: String,
-        hidden: Boolean
-      ) = NotificationData(
-        messageId.id,
-        creationTime,
-        time,
-        type,
-        flag,
-        bufferId.id,
-        bufferName,
-        bufferType,
-        networkId.id,
-        networkName,
-        sender,
-        senderPrefixes,
-        realName,
-        avatarUrl,
-        content,
-        ownNick,
-        ownIdent,
-        ownRealName,
-        ownAvatarUrl,
-        hidden
-      )
-    }
-  }
-
-  @Dao
-  interface NotificationDao {
-    @Insert(onConflict = OnConflictStrategy.IGNORE)
-    fun save(vararg entities: NotificationData)
-
-    @Query("SELECT DISTINCT bufferId FROM notification")
-    fun _buffers(): List<BufferId_Type>
-
-    @Query("SELECT * FROM notification WHERE hidden = 0 ORDER BY time ASC")
-    fun all(): List<NotificationData>
-
-    @Query("SELECT * FROM notification WHERE bufferId = :bufferId AND hidden = 0 ORDER BY time ASC")
-    fun _all(bufferId: BufferId_Type): List<NotificationData>
-
-    @Query("UPDATE notification SET hidden = 1 WHERE bufferId = :bufferId AND messageId <= :messageId")
-    fun _markHidden(bufferId: BufferId_Type, messageId: MsgId_Type)
-
-    @Query("UPDATE notification SET hidden = 1 WHERE bufferId = :bufferId AND flag & 2 = 0")
-    fun _markHiddenNormal(bufferId: BufferId_Type)
-
-    @Query("DELETE FROM notification WHERE bufferId = :bufferId AND messageId <= :messageId")
-    fun _markRead(bufferId: BufferId_Type, messageId: MsgId_Type)
-
-    @Query("DELETE FROM notification WHERE bufferId = :bufferId AND flag & 2 = 0")
-    fun _markReadNormal(bufferId: BufferId_Type)
-
-    @Query("DELETE FROM notification")
-    fun clear()
-  }
-
-  object Creator {
-    private var database: QuasselDatabase? = null
-
-    // For Singleton instantiation
-    private val LOCK = Any()
-
-    fun init(context: Context): QuasselDatabase {
-      if (database == null) {
-        synchronized(LOCK) {
-          if (database == null) {
-            database = Room.databaseBuilder(
-              context.applicationContext,
-              QuasselDatabase::class.java, DATABASE_NAME
-            ).addMigrations(
-              object : Migration(2, 3) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL(
-                    "CREATE TABLE filtered(bufferId INTEGER, accountId INTEGER, filtered INTEGER, PRIMARY KEY(accountId, bufferId));"
-                  )
-                }
-              },
-              object : Migration(3, 4) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL(
-                    "ALTER TABLE message ADD followUp INT DEFAULT 0 NOT NULL;"
-                  )
-                }
-              },
-              object : Migration(4, 5) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table message;")
-                  database.execSQL("create table message (messageId INTEGER not null primary key, time INTEGER not null, type INTEGER not null, flag INTEGER not null, bufferId INTEGER not null, sender TEXT not null, senderPrefixes TEXT not null, content TEXT not null);")
-                }
-              },
-              object : Migration(5, 6) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table message;")
-                  database.execSQL("create table message (messageId INTEGER not null primary key, time INTEGER not null, type INTEGER not null, flag INTEGER not null, bufferId INTEGER not null, sender TEXT not null, senderPrefixes TEXT not null, realName TEXT not null, avatarUrl TEXT not null, content TEXT not null);")
-                }
-              },
-              object : Migration(6, 7) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table message;")
-                  database.execSQL("create table message (messageId INTEGER not null primary key, time INTEGER not null, type INTEGER not null, flag INTEGER not null, bufferId INTEGER not null, sender TEXT not null, senderPrefixes TEXT not null, realName TEXT not null, avatarUrl TEXT not null, content TEXT not null, ignored INTEGER not null);")
-                }
-              },
-              object : Migration(7, 8) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("CREATE INDEX index_message_bufferId ON message(bufferId);")
-                  database.execSQL("CREATE INDEX index_message_ignored ON message(ignored);")
-                }
-              },
-              object : Migration(8, 9) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("create table ssl_exception (accountId INTEGER not null, certificateFingerprint TEXT not null, ignoreValidityDate INTEGER not null, primary key(accountId, certificateFingerprint));")
-                }
-              },
-              object : Migration(9, 10) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table ssl_exception;")
-                  database.execSQL("create table ssl_exception (accountId INTEGER not null, hostName TEXT not null, certificateFingerprint TEXT not null, ignoreValidityDate INTEGER not null, primary key(accountId, hostName, certificateFingerprint));")
-                }
-              },
-              object : Migration(10, 11) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table ssl_exception;")
-                  database.execSQL("create table ssl_exception (accountId INTEGER not null, certificateFingerprint TEXT not null, ignoreValidityDate INTEGER not null, primary key(accountId, certificateFingerprint));")
-                }
-              },
-              object : Migration(11, 12) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table ssl_exception;")
-                  database.execSQL("create table ssl_validity_whitelist (fingerprint TEXT not null, ignoreDate INTEGER not null, primary key(fingerprint));")
-                  database.execSQL("create table ssl_hostname_whitelist (fingerprint TEXT not null, hostname TEXT not null, primary key(fingerprint, hostname));")
-                }
-              },
-              object : Migration(12, 13) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("drop table ssl_validity_whitelist;")
-                  database.execSQL("drop table ssl_hostname_whitelist;")
-                  database.execSQL("create table ssl_validity_whitelist (fingerprint TEXT not null, ignoreDate INTEGER not null, primary key(fingerprint));")
-                  database.execSQL("create table ssl_hostname_whitelist (fingerprint TEXT not null, hostname TEXT not null, primary key(fingerprint, hostname));")
-                }
-              },
-              object : Migration(13, 14) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("CREATE TABLE IF NOT EXISTS `notification` (`messageId` INTEGER NOT NULL, `time` INTEGER NOT NULL, `type` INTEGER NOT NULL, `flag` INTEGER NOT NULL, `bufferId` INTEGER NOT NULL, `bufferName` TEXT NOT NULL, `bufferType` INTEGER NOT NULL, `networkId` INTEGER NOT NULL, `sender` TEXT NOT NULL, `senderPrefixes` TEXT NOT NULL, `realName` TEXT NOT NULL, `avatarUrl` TEXT NOT NULL, `content` TEXT NOT NULL, PRIMARY KEY(`messageId`));")
-                  database.execSQL("CREATE  INDEX `index_notification_bufferId` ON `notification` (`bufferId`);")
-                }
-              },
-              object : Migration(14, 15) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("ALTER TABLE message ADD networkId INT DEFAULT 0 NOT NULL;")
-                }
-              },
-              object : Migration(15, 16) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("ALTER TABLE `notification` ADD `creationTime` INT DEFAULT 0 NOT NULL;")
-                }
-              },
-              object : Migration(16, 17) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("ALTER TABLE `notification` ADD `ownNick` TEXT DEFAULT '' NOT NULL;")
-                  database.execSQL("ALTER TABLE `notification` ADD `ownIdent` TEXT DEFAULT '' NOT NULL;")
-                  database.execSQL("ALTER TABLE `notification` ADD `ownRealName` TEXT DEFAULT '' NOT NULL;")
-                  database.execSQL("ALTER TABLE `notification` ADD `ownAvatarUrl` TEXT DEFAULT '' NOT NULL;")
-                }
-              },
-              object : Migration(17, 18) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("ALTER TABLE `notification` ADD `hidden` INT DEFAULT 0 NOT NULL;")
-                }
-              },
-              object : Migration(18, 19) {
-                override fun migrate(database: SupportSQLiteDatabase) {
-                  database.execSQL("ALTER TABLE `notification` ADD `networkName` TEXT DEFAULT '' NOT NULL;")
-                }
-              }
-            ).build()
-          }
-        }
-      }
-      return database!!
-    }
-  }
-
-  companion object {
-    const val DATABASE_NAME = "persistence-clientData"
-  }
-}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt
deleted file mode 100644
index 952d4e7fdb8c3d60b38c30178e1b21d13f5aeb28..0000000000000000000000000000000000000000
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt
+++ /dev/null
@@ -1,91 +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/>.
- */
-@file:Suppress("NOTHING_TO_INLINE")
-package de.kuschku.quasseldroid.persistence
-
-import de.kuschku.libquassel.protocol.BufferId
-import de.kuschku.libquassel.protocol.MsgId
-
-inline fun QuasselDatabase.MessageDao.buffers() =
-  _buffers().map { BufferId(it) }
-
-inline fun QuasselDatabase.MessageDao.findByBufferId(bufferId: BufferId) =
-  _findByBufferId(bufferId.id)
-
-inline fun QuasselDatabase.MessageDao.findByBufferIdPaged(bufferId: BufferId, type: Int) =
-  _findByBufferIdPaged(bufferId.id, type)
-
-inline fun QuasselDatabase.MessageDao.findLastByBufferId(bufferId: BufferId) =
-  _findLastByBufferId(bufferId.id)
-
-inline fun QuasselDatabase.MessageDao.lastMsgId(bufferId: BufferId) =
-  _lastMsgId(bufferId.id)
-
-inline fun QuasselDatabase.MessageDao.firstMsgId(bufferId: BufferId) =
-  _firstMsgId(bufferId.id).map(::MsgId)
-
-inline fun QuasselDatabase.MessageDao.firstVisibleMsgId(bufferId: BufferId, type: Int) =
-  _firstVisibleMsgId(bufferId.id, type)?.let(::MsgId)
-
-inline fun QuasselDatabase.MessageDao.findFirstByBufferId(bufferId: BufferId) =
-  _findFirstByBufferId(bufferId.id)
-
-inline fun QuasselDatabase.MessageDao.hasVisibleMessages(bufferId: BufferId, type: Int) =
-  _hasVisibleMessages(bufferId.id, type)
-
-inline fun QuasselDatabase.MessageDao.merge(bufferId1: BufferId, bufferId2: BufferId) =
-  _merge(bufferId1.id, bufferId2.id)
-
-inline fun QuasselDatabase.MessageDao.bufferSize(bufferId: BufferId) =
-  _bufferSize(bufferId.id)
-
-inline fun QuasselDatabase.NotificationDao.buffers() =
-  _buffers().map(::BufferId)
-
-inline fun QuasselDatabase.NotificationDao.all(bufferId: BufferId) =
-  _all(bufferId.id)
-
-inline fun QuasselDatabase.NotificationDao.markHidden(bufferId: BufferId, messageId: MsgId) =
-  _markHidden(bufferId.id, messageId.id)
-
-inline fun QuasselDatabase.NotificationDao.markHiddenNormal(bufferId: BufferId) =
-  _markHiddenNormal(bufferId.id)
-
-inline fun QuasselDatabase.NotificationDao.markRead(bufferId: BufferId, messageId: MsgId) =
-  _markRead(bufferId.id, messageId.id)
-
-inline fun QuasselDatabase.NotificationDao.markReadNormal(bufferId: BufferId) =
-  _markReadNormal(bufferId.id)
-
-inline fun QuasselDatabase.FilteredDao.buffers(accountId: Long) =
-  _buffers(accountId).map(::BufferId)
-
-inline fun QuasselDatabase.FilteredDao.setFiltered(accountId: Long, bufferId: BufferId,
-                                                   filtered: Int) =
-  _setFiltered(accountId, bufferId.id, filtered)
-
-inline fun QuasselDatabase.FilteredDao.get(accountId: Long, bufferId: BufferId, defaultValue: Int) =
-  _get(accountId, bufferId.id, defaultValue)
-
-inline fun QuasselDatabase.FilteredDao.listen(accountId: Long, bufferId: BufferId,
-                                              defaultValue: Int) =
-  _listen(accountId, bufferId.id, defaultValue)
-
-inline fun QuasselDatabase.FilteredDao.clear(accountId: Long, bufferId: BufferId) =
-  _clear(accountId, bufferId.id)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/AccountDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/AccountDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0489423b53b0eabe093f144cd3d46cc78e49647a
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/AccountDao.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.persistence.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.*
+import de.kuschku.quasseldroid.persistence.models.Account
+
+@Dao
+interface AccountDao {
+  @Insert(onConflict = OnConflictStrategy.REPLACE)
+  fun save(vararg entities: Account)
+
+  @Insert(onConflict = OnConflictStrategy.IGNORE)
+  fun create(vararg entities: Account): Array<Long>
+
+  @Query("SELECT * FROM account WHERE id = :id")
+  fun findById(id: Long): Account?
+
+  @Query("SELECT * FROM account WHERE id = :id")
+  fun listen(id: Long): LiveData<Account?>
+
+  @Query("SELECT * FROM account ORDER BY lastUsed DESC")
+  fun all(): LiveData<List<Account>>
+
+  @Delete
+  fun delete(account: Account)
+
+  @Query("UPDATE account SET defaultFiltered = :defaultFiltered WHERE id = :id")
+  fun setFiltered(id: Long, defaultFiltered: Int)
+
+  @Query("DELETE FROM account")
+  fun clear()
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/FilteredDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/FilteredDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..186346c194459dc249917666d14772b34498560b
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/FilteredDao.kt
@@ -0,0 +1,75 @@
+/*
+ * 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/>.
+ */
+@file:Suppress("NOTHING_TO_INLINE")
+
+package de.kuschku.quasseldroid.persistence.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.protocol.BufferId_Type
+import de.kuschku.quasseldroid.persistence.models.Filtered
+
+@Dao
+interface FilteredDao {
+  @Query("SELECT DISTINCT bufferId FROM filtered WHERE accountId = :accountId")
+  fun _buffers(accountId: Long): List<BufferId_Type>
+
+  @Insert(onConflict = OnConflictStrategy.REPLACE)
+  fun replace(vararg entities: Filtered)
+
+  @Query("UPDATE filtered SET filtered = :filtered WHERE accountId = :accountId AND bufferId = :bufferId")
+  fun _setFiltered(accountId: Long, bufferId: BufferId_Type, filtered: Int)
+
+  @Query("SELECT IFNULL(t.filtered, :defaultValue) FROM (SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT NULL ORDER BY filtered DESC LIMIT 1) t")
+  fun _get(accountId: Long, bufferId: BufferId_Type, defaultValue: Int): Int
+
+  @Query("SELECT IFNULL(t.filtered, :defaultValue) FROM (SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT NULL ORDER BY filtered DESC LIMIT 1) t")
+  fun _listen(accountId: Long, bufferId: BufferId_Type, defaultValue: Int): LiveData<Int>
+
+  @Query("SELECT * FROM filtered WHERE accountId = :accountId")
+  fun listen(accountId: Long): LiveData<List<Filtered>>
+
+  @Query("DELETE FROM filtered")
+  fun clear()
+
+  @Query("DELETE FROM filtered WHERE accountId = :accountId")
+  fun clear(accountId: Long)
+
+  @Query("DELETE FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId")
+  fun _clear(accountId: Long, bufferId: BufferId_Type)
+}
+
+inline fun FilteredDao.buffers(accountId: Long) =
+  _buffers(accountId).map(::BufferId)
+
+inline fun FilteredDao.setFiltered(accountId: Long, bufferId: BufferId, filtered: Int) =
+  _setFiltered(accountId, bufferId.id, filtered)
+
+inline fun FilteredDao.get(accountId: Long, bufferId: BufferId, defaultValue: Int) =
+  _get(accountId, bufferId.id, defaultValue)
+
+inline fun FilteredDao.listen(accountId: Long, bufferId: BufferId, defaultValue: Int) =
+  _listen(accountId, bufferId.id, defaultValue)
+
+inline fun FilteredDao.clear(accountId: Long, bufferId: BufferId) =
+  _clear(accountId, bufferId.id)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/LegacyAccountDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/LegacyAccountDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1df8578be1e1643d26bf3a5c84f66d5c097eaf6
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/LegacyAccountDao.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.persistence.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import de.kuschku.quasseldroid.persistence.models.LegacyAccount
+
+@Dao
+interface LegacyAccountDao {
+  @Query("SELECT * FROM account")
+  fun all(): List<LegacyAccount>
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/MessageDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/MessageDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9880dcf9da6267cc7fc26d9ea1b1732598d431f3
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/MessageDao.kt
@@ -0,0 +1,124 @@
+/*
+ * 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/>.
+ */
+@file:Suppress("NOTHING_TO_INLINE")
+
+package de.kuschku.quasseldroid.persistence.dao
+
+import androidx.lifecycle.LiveData
+import androidx.paging.DataSource
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.protocol.BufferId_Type
+import de.kuschku.libquassel.protocol.MsgId
+import de.kuschku.libquassel.protocol.MsgId_Type
+import de.kuschku.quasseldroid.persistence.models.MessageData
+import io.reactivex.Flowable
+
+@Dao
+interface MessageDao {
+  @Query("SELECT * FROM message")
+  fun all(): List<MessageData>
+
+  @Query("SELECT DISTINCT bufferId FROM message")
+  fun _buffers(): List<BufferId_Type>
+
+  @Query("SELECT * FROM message WHERE messageId = :messageId")
+  fun find(messageId: MsgId_Type): MessageData?
+
+  @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC")
+  fun _findByBufferId(bufferId: BufferId_Type): List<MessageData>
+
+  @Query("SELECT * FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId DESC")
+  fun _findByBufferIdPaged(bufferId: BufferId_Type,
+                           type: Int): DataSource.Factory<Int, MessageData>
+
+  @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
+  fun _findLastByBufferId(bufferId: BufferId_Type): MessageData?
+
+  @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
+  fun _lastMsgId(bufferId: BufferId_Type): LiveData<MessageData>
+
+  @Query("SELECT messageId FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1")
+  fun _firstMsgId(bufferId: BufferId_Type): Flowable<MsgId_Type>
+
+  @Query("SELECT messageId FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId ASC LIMIT 1")
+  fun _firstVisibleMsgId(bufferId: BufferId_Type, type: Int): MsgId_Type?
+
+  @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1")
+  fun _findFirstByBufferId(bufferId: BufferId_Type): MessageData?
+
+  @Query("SELECT EXISTS(SELECT 1 FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0)")
+  fun _hasVisibleMessages(bufferId: BufferId_Type, type: Int): Boolean
+
+  @Insert(onConflict = OnConflictStrategy.REPLACE)
+  fun save(vararg entities: MessageData)
+
+  @Query("UPDATE message SET bufferId = :bufferId1 WHERE bufferId = :bufferId2")
+  fun _merge(bufferId1: BufferId_Type, bufferId2: BufferId_Type)
+
+  @Query("SELECT count(*) FROM message WHERE bufferId = :bufferId")
+  fun _bufferSize(bufferId: BufferId_Type): Int
+
+  @Query("DELETE FROM message")
+  fun clearMessages()
+
+  @Query("DELETE FROM message WHERE bufferId = :bufferId")
+  fun clearMessages(bufferId: BufferId_Type)
+
+  @Query(
+    "DELETE FROM message WHERE bufferId = :bufferId AND messageId >= :first AND messageId <= :last"
+  )
+  fun clearMessages(bufferId: BufferId_Type, first: MsgId_Type, last: MsgId_Type)
+}
+
+inline fun MessageDao.buffers() =
+  _buffers().map { BufferId(it) }
+
+inline fun MessageDao.findByBufferId(bufferId: BufferId) =
+  _findByBufferId(bufferId.id)
+
+inline fun MessageDao.findByBufferIdPaged(bufferId: BufferId, type: Int) =
+  _findByBufferIdPaged(bufferId.id, type)
+
+inline fun MessageDao.findLastByBufferId(bufferId: BufferId) =
+  _findLastByBufferId(bufferId.id)
+
+inline fun MessageDao.lastMsgId(bufferId: BufferId) =
+  _lastMsgId(bufferId.id)
+
+inline fun MessageDao.firstMsgId(bufferId: BufferId) =
+  _firstMsgId(bufferId.id).map(::MsgId)
+
+inline fun MessageDao.firstVisibleMsgId(bufferId: BufferId, type: Int) =
+  _firstVisibleMsgId(bufferId.id, type)?.let(::MsgId)
+
+inline fun MessageDao.findFirstByBufferId(bufferId: BufferId) =
+  _findFirstByBufferId(bufferId.id)
+
+inline fun MessageDao.hasVisibleMessages(bufferId: BufferId, type: Int) =
+  _hasVisibleMessages(bufferId.id, type)
+
+inline fun MessageDao.merge(bufferId1: BufferId, bufferId2: BufferId) =
+  _merge(bufferId1.id, bufferId2.id)
+
+inline fun MessageDao.bufferSize(bufferId: BufferId) =
+  _bufferSize(bufferId.id)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/NotificationDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/NotificationDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..53e1bf0f2fe47871fa858ee12f86cca68bedbedd
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/NotificationDao.kt
@@ -0,0 +1,79 @@
+/*
+ * 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/>.
+ */
+@file:Suppress("NOTHING_TO_INLINE")
+
+package de.kuschku.quasseldroid.persistence.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.protocol.BufferId_Type
+import de.kuschku.libquassel.protocol.MsgId
+import de.kuschku.libquassel.protocol.MsgId_Type
+import de.kuschku.quasseldroid.persistence.models.NotificationData
+
+@Dao
+interface NotificationDao {
+  @Insert(onConflict = OnConflictStrategy.IGNORE)
+  fun save(vararg entities: NotificationData)
+
+  @Query("SELECT DISTINCT bufferId FROM notification")
+  fun _buffers(): List<BufferId_Type>
+
+  @Query("SELECT * FROM notification WHERE hidden = 0 ORDER BY time ASC")
+  fun all(): List<NotificationData>
+
+  @Query("SELECT * FROM notification WHERE bufferId = :bufferId AND hidden = 0 ORDER BY time ASC")
+  fun _all(bufferId: BufferId_Type): List<NotificationData>
+
+  @Query("UPDATE notification SET hidden = 1 WHERE bufferId = :bufferId AND messageId <= :messageId")
+  fun _markHidden(bufferId: BufferId_Type, messageId: MsgId_Type)
+
+  @Query("UPDATE notification SET hidden = 1 WHERE bufferId = :bufferId AND flag & 2 = 0")
+  fun _markHiddenNormal(bufferId: BufferId_Type)
+
+  @Query("DELETE FROM notification WHERE bufferId = :bufferId AND messageId <= :messageId")
+  fun _markRead(bufferId: BufferId_Type, messageId: MsgId_Type)
+
+  @Query("DELETE FROM notification WHERE bufferId = :bufferId AND flag & 2 = 0")
+  fun _markReadNormal(bufferId: BufferId_Type)
+
+  @Query("DELETE FROM notification")
+  fun clear()
+}
+
+inline fun NotificationDao.buffers() =
+  _buffers().map(::BufferId)
+
+inline fun NotificationDao.all(bufferId: BufferId) =
+  _all(bufferId.id)
+
+inline fun NotificationDao.markHidden(bufferId: BufferId, messageId: MsgId) =
+  _markHidden(bufferId.id, messageId.id)
+
+inline fun NotificationDao.markHiddenNormal(bufferId: BufferId) =
+  _markHiddenNormal(bufferId.id)
+
+inline fun NotificationDao.markRead(bufferId: BufferId, messageId: MsgId) =
+  _markRead(bufferId.id, messageId.id)
+
+inline fun NotificationDao.markReadNormal(bufferId: BufferId) =
+  _markReadNormal(bufferId.id)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/SslHostnameWhitelistDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/SslHostnameWhitelistDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..23d0894d366b5a0c96347a8ab1e56b3752927476
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/SslHostnameWhitelistDao.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.persistence.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import de.kuschku.quasseldroid.persistence.models.SslHostnameWhitelistEntry
+
+@Dao
+interface SslHostnameWhitelistDao {
+  @Insert(onConflict = OnConflictStrategy.REPLACE)
+  fun save(vararg entities: SslHostnameWhitelistEntry)
+
+  @Query("SELECT * FROM ssl_hostname_whitelist")
+  fun all(): List<SslHostnameWhitelistEntry>
+
+  @Query("SELECT * FROM ssl_hostname_whitelist WHERE fingerprint = :fingerprint AND hostname = :hostname")
+  fun find(fingerprint: String, hostname: String): SslHostnameWhitelistEntry?
+
+  @Query("DELETE FROM ssl_hostname_whitelist WHERE fingerprint = :fingerprint AND hostname = :hostname")
+  fun delete(fingerprint: String, hostname: String)
+
+  @Query("DELETE FROM ssl_hostname_whitelist")
+  fun clear()
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/SslValidityWhitelistDao.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/SslValidityWhitelistDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..084225e2f46ac436bfc20afd38c5354b7ebccbb8
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/dao/SslValidityWhitelistDao.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.persistence.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import de.kuschku.quasseldroid.persistence.models.SslValidityWhitelistEntry
+
+@Dao
+interface SslValidityWhitelistDao {
+  @Insert(onConflict = OnConflictStrategy.REPLACE)
+  fun save(vararg entities: SslValidityWhitelistEntry)
+
+  @Query("SELECT * FROM ssl_validity_whitelist")
+  fun all(): List<SslValidityWhitelistEntry>
+
+  @Query("SELECT * FROM ssl_validity_whitelist WHERE fingerprint = :fingerprint")
+  fun find(fingerprint: String): SslValidityWhitelistEntry?
+
+  @Query("DELETE FROM ssl_validity_whitelist WHERE fingerprint = :fingerprint")
+  fun delete(fingerprint: String)
+
+  @Query("DELETE FROM ssl_validity_whitelist")
+  fun clear()
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/AccountDatabase.kt
similarity index 62%
rename from persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt
rename to persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/AccountDatabase.kt
index 2c1392a3b946ecd74a4a0761601cbabf91783b35..24220ba8a1cc4d94ec20a14cc53b7a6280e9e438 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/AccountDatabase.kt
@@ -17,60 +17,21 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.persistence
+package de.kuschku.quasseldroid.persistence.db
 
 import android.content.Context
-import androidx.lifecycle.LiveData
-import androidx.room.*
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
 import androidx.room.migration.Migration
 import androidx.sqlite.db.SupportSQLiteDatabase
+import de.kuschku.quasseldroid.persistence.dao.AccountDao
+import de.kuschku.quasseldroid.persistence.models.Account
 
-@Database(entities = [(AccountDatabase.Account::class)], version = 4)
+@Database(entities = [(Account::class)], version = 4)
 abstract class AccountDatabase : RoomDatabase() {
   abstract fun accounts(): AccountDao
 
-  @Entity
-  data class Account(
-    @PrimaryKey(autoGenerate = true)
-    var id: Long,
-    var host: String,
-    var port: Int,
-    var requireSsl: Boolean,
-    var user: String,
-    var pass: String,
-    var name: String,
-    var lastUsed: Long,
-    var acceptedMissingFeatures: Boolean,
-    var defaultFiltered: Int
-  )
-
-  @Dao
-  interface AccountDao {
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    fun save(vararg entities: AccountDatabase.Account)
-
-    @Insert(onConflict = OnConflictStrategy.IGNORE)
-    fun create(vararg entities: AccountDatabase.Account): Array<Long>
-
-    @Query("SELECT * FROM account WHERE id = :id")
-    fun findById(id: Long): AccountDatabase.Account?
-
-    @Query("SELECT * FROM account WHERE id = :id")
-    fun listen(id: Long): LiveData<AccountDatabase.Account?>
-
-    @Query("SELECT * FROM account ORDER BY lastUsed DESC")
-    fun all(): LiveData<List<Account>>
-
-    @Delete
-    fun delete(account: AccountDatabase.Account)
-
-    @Query("UPDATE account SET defaultFiltered = :defaultFiltered WHERE id = :id")
-    fun setFiltered(id: Long, defaultFiltered: Int)
-
-    @Query("DELETE FROM account")
-    fun clear()
-  }
-
   object Creator {
     private var database: AccountDatabase? = null
 
@@ -83,7 +44,8 @@ abstract class AccountDatabase : RoomDatabase() {
           if (database == null) {
             database = Room.databaseBuilder(
               context.applicationContext,
-              AccountDatabase::class.java, DATABASE_NAME
+              AccountDatabase::class.java,
+              DATABASE_NAME
             ).addMigrations(
               object : Migration(1, 2) {
                 override fun migrate(database: SupportSQLiteDatabase) {
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/LegacyAccountDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/LegacyAccountDatabase.kt
similarity index 87%
rename from persistence/src/main/java/de/kuschku/quasseldroid/persistence/LegacyAccountDatabase.kt
rename to persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/LegacyAccountDatabase.kt
index fe370442c944ccf99b4900f9850ac93c4aacad4c..c92245adf745c0876e075583ce27c4a1c499ff3f 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/LegacyAccountDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/LegacyAccountDatabase.kt
@@ -17,33 +17,20 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.persistence
+package de.kuschku.quasseldroid.persistence.db
 
 import android.content.Context
-import androidx.room.*
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
 import androidx.room.migration.Migration
 import androidx.sqlite.db.SupportSQLiteDatabase
+import de.kuschku.quasseldroid.persistence.dao.LegacyAccountDao
+import de.kuschku.quasseldroid.persistence.models.LegacyAccount
 
-@Database(entities = [(LegacyAccountDatabase.Account::class)], version = 4)
+@Database(entities = [(LegacyAccount::class)], version = 4)
 abstract class LegacyAccountDatabase : RoomDatabase() {
-  abstract fun accounts(): AccountDao
-
-  @Entity
-  data class Account(
-    @PrimaryKey
-    var id: Long,
-    var host: String,
-    var port: Int,
-    var user: String,
-    var pass: String,
-    var name: String
-  )
-
-  @Dao
-  interface AccountDao {
-    @Query("SELECT * FROM account")
-    fun all(): List<Account>
-  }
+  abstract fun accounts(): LegacyAccountDao
 
   object Creator {
     private var database: LegacyAccountDatabase? = null
@@ -57,7 +44,8 @@ abstract class LegacyAccountDatabase : RoomDatabase() {
           if (database == null) {
             database = Room.databaseBuilder(
               context.applicationContext,
-              LegacyAccountDatabase::class.java, DATABASE_NAME
+              LegacyAccountDatabase::class.java,
+              DATABASE_NAME
             ).addMigrations(
               object : Migration(0, 1) {
                 override fun migrate(database: SupportSQLiteDatabase) {
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/QuasselDatabase.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e4d64c0ae26fa47bc904d278a08bc23e344c6975
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/db/QuasselDatabase.kt
@@ -0,0 +1,172 @@
+/*
+ * 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.persistence.db
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.room.TypeConverters
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+import de.kuschku.quasseldroid.persistence.dao.*
+import de.kuschku.quasseldroid.persistence.models.*
+import de.kuschku.quasseldroid.persistence.util.MessageTypeConverter
+
+@Database(entities = [MessageData::class, Filtered::class, SslValidityWhitelistEntry::class, SslHostnameWhitelistEntry::class, NotificationData::class],
+          version = 19)
+@TypeConverters(MessageTypeConverter::class)
+abstract class QuasselDatabase : RoomDatabase() {
+  abstract fun message(): MessageDao
+  abstract fun filtered(): FilteredDao
+  abstract fun validityWhitelist(): SslValidityWhitelistDao
+  abstract fun hostnameWhitelist(): SslHostnameWhitelistDao
+  abstract fun notifications(): NotificationDao
+
+  object Creator {
+    private var database: QuasselDatabase? = null
+
+    // For Singleton instantiation
+    private val LOCK = Any()
+
+    fun init(context: Context): QuasselDatabase {
+      if (database == null) {
+        synchronized(LOCK) {
+          if (database == null) {
+            database = Room.databaseBuilder(
+              context.applicationContext,
+              QuasselDatabase::class.java,
+              DATABASE_NAME
+            ).addMigrations(
+              object : Migration(2, 3) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL(
+                    "CREATE TABLE filtered(bufferId INTEGER, accountId INTEGER, filtered INTEGER, PRIMARY KEY(accountId, bufferId));"
+                  )
+                }
+              },
+              object : Migration(3, 4) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL(
+                    "ALTER TABLE message ADD followUp INT DEFAULT 0 NOT NULL;"
+                  )
+                }
+              },
+              object : Migration(4, 5) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table message;")
+                  database.execSQL("create table message (messageId INTEGER not null primary key, time INTEGER not null, type INTEGER not null, flag INTEGER not null, bufferId INTEGER not null, sender TEXT not null, senderPrefixes TEXT not null, content TEXT not null);")
+                }
+              },
+              object : Migration(5, 6) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table message;")
+                  database.execSQL("create table message (messageId INTEGER not null primary key, time INTEGER not null, type INTEGER not null, flag INTEGER not null, bufferId INTEGER not null, sender TEXT not null, senderPrefixes TEXT not null, realName TEXT not null, avatarUrl TEXT not null, content TEXT not null);")
+                }
+              },
+              object : Migration(6, 7) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table message;")
+                  database.execSQL("create table message (messageId INTEGER not null primary key, time INTEGER not null, type INTEGER not null, flag INTEGER not null, bufferId INTEGER not null, sender TEXT not null, senderPrefixes TEXT not null, realName TEXT not null, avatarUrl TEXT not null, content TEXT not null, ignored INTEGER not null);")
+                }
+              },
+              object : Migration(7, 8) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("CREATE INDEX index_message_bufferId ON message(bufferId);")
+                  database.execSQL("CREATE INDEX index_message_ignored ON message(ignored);")
+                }
+              },
+              object : Migration(8, 9) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("create table ssl_exception (accountId INTEGER not null, certificateFingerprint TEXT not null, ignoreValidityDate INTEGER not null, primary key(accountId, certificateFingerprint));")
+                }
+              },
+              object : Migration(9, 10) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table ssl_exception;")
+                  database.execSQL("create table ssl_exception (accountId INTEGER not null, hostName TEXT not null, certificateFingerprint TEXT not null, ignoreValidityDate INTEGER not null, primary key(accountId, hostName, certificateFingerprint));")
+                }
+              },
+              object : Migration(10, 11) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table ssl_exception;")
+                  database.execSQL("create table ssl_exception (accountId INTEGER not null, certificateFingerprint TEXT not null, ignoreValidityDate INTEGER not null, primary key(accountId, certificateFingerprint));")
+                }
+              },
+              object : Migration(11, 12) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table ssl_exception;")
+                  database.execSQL("create table ssl_validity_whitelist (fingerprint TEXT not null, ignoreDate INTEGER not null, primary key(fingerprint));")
+                  database.execSQL("create table ssl_hostname_whitelist (fingerprint TEXT not null, hostname TEXT not null, primary key(fingerprint, hostname));")
+                }
+              },
+              object : Migration(12, 13) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("drop table ssl_validity_whitelist;")
+                  database.execSQL("drop table ssl_hostname_whitelist;")
+                  database.execSQL("create table ssl_validity_whitelist (fingerprint TEXT not null, ignoreDate INTEGER not null, primary key(fingerprint));")
+                  database.execSQL("create table ssl_hostname_whitelist (fingerprint TEXT not null, hostname TEXT not null, primary key(fingerprint, hostname));")
+                }
+              },
+              object : Migration(13, 14) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("CREATE TABLE IF NOT EXISTS `notification` (`messageId` INTEGER NOT NULL, `time` INTEGER NOT NULL, `type` INTEGER NOT NULL, `flag` INTEGER NOT NULL, `bufferId` INTEGER NOT NULL, `bufferName` TEXT NOT NULL, `bufferType` INTEGER NOT NULL, `networkId` INTEGER NOT NULL, `sender` TEXT NOT NULL, `senderPrefixes` TEXT NOT NULL, `realName` TEXT NOT NULL, `avatarUrl` TEXT NOT NULL, `content` TEXT NOT NULL, PRIMARY KEY(`messageId`));")
+                  database.execSQL("CREATE  INDEX `index_notification_bufferId` ON `notification` (`bufferId`);")
+                }
+              },
+              object : Migration(14, 15) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("ALTER TABLE message ADD networkId INT DEFAULT 0 NOT NULL;")
+                }
+              },
+              object : Migration(15, 16) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("ALTER TABLE `notification` ADD `creationTime` INT DEFAULT 0 NOT NULL;")
+                }
+              },
+              object : Migration(16, 17) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("ALTER TABLE `notification` ADD `ownNick` TEXT DEFAULT '' NOT NULL;")
+                  database.execSQL("ALTER TABLE `notification` ADD `ownIdent` TEXT DEFAULT '' NOT NULL;")
+                  database.execSQL("ALTER TABLE `notification` ADD `ownRealName` TEXT DEFAULT '' NOT NULL;")
+                  database.execSQL("ALTER TABLE `notification` ADD `ownAvatarUrl` TEXT DEFAULT '' NOT NULL;")
+                }
+              },
+              object : Migration(17, 18) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("ALTER TABLE `notification` ADD `hidden` INT DEFAULT 0 NOT NULL;")
+                }
+              },
+              object : Migration(18, 19) {
+                override fun migrate(database: SupportSQLiteDatabase) {
+                  database.execSQL("ALTER TABLE `notification` ADD `networkName` TEXT DEFAULT '' NOT NULL;")
+                }
+              }
+            ).build()
+          }
+        }
+      }
+      return database!!
+    }
+  }
+
+  companion object {
+    const val DATABASE_NAME = "persistence-clientData"
+  }
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/Account.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/Account.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e1c521e72167cd10357b59c68ec997ccd139b413
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/Account.kt
@@ -0,0 +1,38 @@
+/*
+ * 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.persistence.models
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "Account")
+data class Account(
+  @PrimaryKey(autoGenerate = true)
+  var id: Long,
+  var host: String,
+  var port: Int,
+  var requireSsl: Boolean,
+  var user: String,
+  var pass: String,
+  var name: String,
+  var lastUsed: Long,
+  var acceptedMissingFeatures: Boolean,
+  var defaultFiltered: Int
+)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/Filtered.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/Filtered.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3c6653dfa713f1f195bd6656da0f1f388de6b4d9
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/Filtered.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.persistence.models
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.protocol.BufferId_Type
+
+@Entity(tableName = "filtered", primaryKeys = ["accountId", "bufferId"])
+data class Filtered(
+  var accountId: Long,
+  @ColumnInfo(name = "bufferId")
+  var rawBufferId: BufferId_Type,
+  var filtered: Int
+) {
+  inline val bufferId
+    get() = BufferId(rawBufferId)
+
+  companion object {
+    inline fun of(
+      accountId: Long,
+      bufferId: BufferId,
+      filtered: Int
+    ) = Filtered(
+      accountId,
+      bufferId.id,
+      filtered
+    )
+  }
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/LegacyAccount.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/LegacyAccount.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5f14ddd671e0e3b1870303b4f10b1022d7c16d43
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/LegacyAccount.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.persistence.models
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "Account")
+data class LegacyAccount(
+  @PrimaryKey
+  var id: Long,
+  var host: String,
+  var port: Int,
+  var user: String,
+  var pass: String,
+  var name: String
+)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/MessageData.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/MessageData.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3233e80b6fb172778c81b9334a5fa57eff957491
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/MessageData.kt
@@ -0,0 +1,85 @@
+/*
+ * 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/>.
+ */
+@file:Suppress("NOTHING_TO_INLINE")
+
+package de.kuschku.quasseldroid.persistence.models
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Index
+import androidx.room.PrimaryKey
+import de.kuschku.libquassel.protocol.*
+import org.threeten.bp.Instant
+
+@Entity(tableName = "message", indices = [Index("bufferId"), Index("ignored")])
+data class MessageData(
+  @PrimaryKey
+  @ColumnInfo(name = "messageId")
+  var rawMessageId: MsgId_Type,
+  var time: Instant,
+  var type: Message_Types,
+  var flag: Message_Flags,
+  @ColumnInfo(name = "bufferId")
+  var rawBufferId: BufferId_Type,
+  @ColumnInfo(name = "networkId")
+  var rawNetworkId: NetworkId_Type,
+  var sender: String,
+  var senderPrefixes: String,
+  var realName: String,
+  var avatarUrl: String,
+  var content: String,
+  var ignored: Boolean
+) {
+  inline val messageId
+    get() = MsgId(rawMessageId)
+  inline val bufferId
+    get() = BufferId(rawBufferId)
+  inline val networkId
+    get() = NetworkId(rawNetworkId)
+
+  companion object {
+    inline fun of(
+      messageId: MsgId,
+      time: Instant,
+      type: Message_Types,
+      flag: Message_Flags,
+      bufferId: BufferId,
+      networkId: NetworkId,
+      sender: String,
+      senderPrefixes: String,
+      realName: String,
+      avatarUrl: String,
+      content: String,
+      ignored: Boolean
+    ) = MessageData(
+      messageId.id,
+      time,
+      type,
+      flag,
+      bufferId.id,
+      networkId.id,
+      sender,
+      senderPrefixes,
+      realName,
+      avatarUrl,
+      content,
+      ignored
+    )
+  }
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/NotificationData.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/NotificationData.kt
new file mode 100644
index 0000000000000000000000000000000000000000..78e496330fc48e3a60ada38f3fa1837d04b13157
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/NotificationData.kt
@@ -0,0 +1,110 @@
+/*
+ * 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.persistence.models
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Index
+import androidx.room.PrimaryKey
+import de.kuschku.libquassel.protocol.*
+import org.threeten.bp.Instant
+
+@Entity(tableName = "notification", indices = [Index("bufferId")])
+data class NotificationData(
+  @PrimaryKey
+  @ColumnInfo(name = "messageId")
+  var rawMessageId: MsgId_Type,
+  var creationTime: Instant,
+  var time: Instant,
+  var type: Message_Types,
+  var flag: Message_Flags,
+  @ColumnInfo(name = "bufferId")
+  var rawBufferId: BufferId_Type,
+  var bufferName: String,
+  var bufferType: Buffer_Types,
+  @ColumnInfo(name = "networkId")
+  var rawNetworkId: NetworkId_Type,
+  var networkName: String,
+  var sender: String,
+  var senderPrefixes: String,
+  var realName: String,
+  var avatarUrl: String,
+  var content: String,
+  var ownNick: String,
+  var ownIdent: String,
+  var ownRealName: String,
+  var ownAvatarUrl: String,
+  var hidden: Boolean
+) {
+  inline val messageId
+    get() = MsgId(rawMessageId)
+
+  inline val bufferId
+    get() = BufferId(rawBufferId)
+
+  inline val networkId
+    get() = NetworkId(rawNetworkId)
+
+  companion object {
+    inline fun of(
+      messageId: MsgId,
+      creationTime: Instant,
+      time: Instant,
+      type: Message_Types,
+      flag: Message_Flags,
+      bufferId: BufferId,
+      bufferName: String,
+      bufferType: Buffer_Types,
+      networkId: NetworkId,
+      networkName: String,
+      sender: String,
+      senderPrefixes: String,
+      realName: String,
+      avatarUrl: String,
+      content: String,
+      ownNick: String,
+      ownIdent: String,
+      ownRealName: String,
+      ownAvatarUrl: String,
+      hidden: Boolean
+    ) = NotificationData(
+      messageId.id,
+      creationTime,
+      time,
+      type,
+      flag,
+      bufferId.id,
+      bufferName,
+      bufferType,
+      networkId.id,
+      networkName,
+      sender,
+      senderPrefixes,
+      realName,
+      avatarUrl,
+      content,
+      ownNick,
+      ownIdent,
+      ownRealName,
+      ownAvatarUrl,
+      hidden
+    )
+  }
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/SslHostnameWhitelistEntry.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/SslHostnameWhitelistEntry.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8457af9efbe476a3e0674f3d4219fc9fb7a1311e
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/SslHostnameWhitelistEntry.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.persistence.models
+
+import androidx.room.Entity
+
+@Entity(tableName = "ssl_hostname_whitelist", primaryKeys = ["fingerprint", "hostname"])
+data class SslHostnameWhitelistEntry(
+  var fingerprint: String,
+  var hostname: String
+)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/SslValidityWhitelistEntry.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/SslValidityWhitelistEntry.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8da11729265b34c32fa5f9df83f64bca17e82f78
--- /dev/null
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/models/SslValidityWhitelistEntry.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.persistence.models
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "ssl_validity_whitelist")
+data class SslValidityWhitelistEntry(
+  @PrimaryKey
+  var fingerprint: String,
+  var ignoreDate: Boolean
+)
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/util/MessageTypeConverter.kt
similarity index 96%
rename from persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt
rename to persistence/src/main/java/de/kuschku/quasseldroid/persistence/util/MessageTypeConverter.kt
index 2a678258e90d48423316842a24f3b1537e057d49..6c97aa78254efd1073179bd9579aa1748730ddee 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/util/MessageTypeConverter.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.persistence
+package de.kuschku.quasseldroid.persistence.util
 
 import androidx.room.TypeConverter
 import de.kuschku.libquassel.protocol.*
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/util/QuasselBacklogStorage.kt
similarity index 88%
rename from persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
rename to persistence/src/main/java/de/kuschku/quasseldroid/persistence/util/QuasselBacklogStorage.kt
index 777774a6eca905a736fe8c11e6fb6e19509321cb..60b813a7e77ca82eb71d8ebf64837a2df1cf31c3 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/util/QuasselBacklogStorage.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.persistence
+package de.kuschku.quasseldroid.persistence.util
 
 import de.kuschku.libquassel.protocol.BufferId
 import de.kuschku.libquassel.protocol.Message
@@ -25,12 +25,16 @@ import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.session.BacklogStorage
 import de.kuschku.libquassel.session.ISession
+import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 
 class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
   override fun updateIgnoreRules(session: ISession) {
     db.message().save(
       *db.message().all().map {
-        it.copy(ignored = isIgnored(session, it))
+        it.copy(ignored = isIgnored(
+          session,
+          it))
       }.toTypedArray()
     )
   }
@@ -40,7 +44,7 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
 
   override fun storeMessages(session: ISession, messages: Iterable<Message>) {
     db.message().save(*messages.map {
-      QuasselDatabase.MessageData.of(
+      MessageData.of(
         messageId = it.messageId,
         time = it.time,
         type = it.type,
@@ -52,7 +56,9 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
         realName = it.realName,
         avatarUrl = it.avatarUrl,
         content = it.content,
-        ignored = isIgnored(session, it)
+        ignored = isIgnored(
+          session,
+          it)
       )
     }.toTypedArray())
   }
@@ -80,7 +86,7 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
       ) != IgnoreListManager.StrictnessType.UnmatchedStrictness
     }
 
-    fun isIgnored(session: ISession, message: QuasselDatabase.MessageData): Boolean {
+    fun isIgnored(session: ISession, message: MessageData): Boolean {
       val bufferInfo = session.bufferSyncer.bufferInfo(message.bufferId)
       val bufferName = bufferInfo?.bufferName ?: ""
       val networkId = bufferInfo?.networkId ?: NetworkId(-1)
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt
index 73fad333b9660badafdddff35889b816a7729c4b..b946cbc38b03fcb9f9f9e216d42b69c5e3f14fd8 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt
@@ -20,10 +20,10 @@
 package de.kuschku.quasseldroid.viewmodel.data
 
 import android.graphics.drawable.Drawable
-import de.kuschku.quasseldroid.persistence.QuasselDatabase
+import de.kuschku.quasseldroid.persistence.models.MessageData
 
 class FormattedMessage(
-  val original: QuasselDatabase.MessageData,
+  val original: MessageData,
   val time: CharSequence,
   val dayChange: CharSequence? = null,
   val name: CharSequence? = null,