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 07a553b5cd7cb65f845c556cba8e586cf2ed0a0a..67b2adf824b0676ee81c65f16d6fe40b5fc3986f 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
@@ -232,13 +232,20 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       }
     })
 
+    viewModel.connectionProgress
+      .filter { (it, _, _) -> it == ConnectionState.CONNECTED }
+      .firstElement()
+      .toLiveData()
+      .observe(this, Observer {
+        if (resources.getBoolean(R.bool.buffer_drawer_exists) && viewModel.buffer.value == -1) {
+          drawerLayout.openDrawer(Gravity.START)
+        }
+      })
+
     viewModel.connectionProgress.toLiveData().observe(this, Observer {
       val (state, progress, max) = it ?: Triple(ConnectionState.DISCONNECTED, 0, 0)
       when (state) {
         ConnectionState.CONNECTED -> {
-          if (resources.getBoolean(R.bool.buffer_drawer_exists) && viewModel.buffer.value == -1) {
-            drawerLayout.openDrawer(Gravity.START)
-          }
           progressBar.visibility = View.INVISIBLE
         }
         ConnectionState.DISCONNECTED,
@@ -413,6 +420,20 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     else                        -> super.onOptionsItemSelected(item)
   }
 
+  override fun onBackPressed() {
+    if (chatlineFragment?.historyPanel?.panelState == SlidingUpPanelLayout.PanelState.EXPANDED) {
+      chatlineFragment?.historyPanel?.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
+      return
+    }
+
+    if (editorPanel.panelState == SlidingUpPanelLayout.PanelState.EXPANDED) {
+      editorPanel.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
+      return
+    }
+
+    super.onBackPressed()
+  }
+
   private fun disconnect() {
     getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editCommit {
       putBoolean(Keys.Status.reconnect, false)
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
index f40c8f2f8e6265c30e4849247c6f6cfb53a84c49..a027bde177ccab784bfa9e3b6c24f478c8ff8e80 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt
@@ -3,35 +3,26 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.quassel.syncables.interfaces.IBacklogManager
 import de.kuschku.libquassel.session.BacklogStorage
-import de.kuschku.libquassel.session.SignalProxy
-import java.util.concurrent.atomic.AtomicInteger
+import de.kuschku.libquassel.session.Session
 
 class BacklogManager(
-  proxy: SignalProxy,
+  private val session: Session,
   private val backlogStorage: BacklogStorage
-) : SyncableObject(proxy, "BacklogManager"), IBacklogManager {
+) : SyncableObject(session, "BacklogManager"), IBacklogManager {
   init {
     initialized = true
   }
 
-  private var loading = AtomicInteger(-1)
-
-  override fun requestBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int,
-                              additional: Int) {
-    if (loading.getAndSet(bufferId) != bufferId) {
-      super.requestBacklog(bufferId, first, last, limit, additional)
-    }
-  }
+  fun updateIgnoreRules() = backlogStorage.updateIgnoreRules(session)
 
   override fun receiveBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int,
                               additional: Int, messages: QVariantList) {
-    loading.compareAndSet(bufferId, -1)
-    backlogStorage.storeMessages(messages.mapNotNull(QVariant_::value), initialLoad = true)
+    backlogStorage.storeMessages(session, messages.mapNotNull(QVariant_::value), initialLoad = true)
   }
 
   override fun receiveBacklogAll(first: MsgId, last: MsgId, limit: Int, additional: Int,
                                  messages: QVariantList) {
-    backlogStorage.storeMessages(messages.mapNotNull(QVariant_::value), initialLoad = true)
+    backlogStorage.storeMessages(session, messages.mapNotNull(QVariant_::value), initialLoad = true)
   }
 
   fun removeBuffer(buffer: BufferId) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
index 5003a00ef1e4211de839a67b83f05889814e8b64..1f4b085a026002b3dc90dcb2e763e0d006ac3d58 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
@@ -2,15 +2,15 @@ package de.kuschku.libquassel.quassel.syncables
 
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.quassel.syncables.interfaces.IIgnoreListManager
-import de.kuschku.libquassel.session.SignalProxy
+import de.kuschku.libquassel.session.Session
 import de.kuschku.libquassel.util.GlobTransformer
 import de.kuschku.libquassel.util.flag.and
 import io.reactivex.subjects.BehaviorSubject
 import java.io.Serializable
 
 class IgnoreListManager constructor(
-  proxy: SignalProxy
-) : SyncableObject(proxy, "IgnoreListManager"), IIgnoreListManager {
+  private val session: Session
+) : SyncableObject(session, "IgnoreListManager"), IIgnoreListManager {
   override fun toVariantMap(): QVariantMap = mapOf(
     "IgnoreList" to QVariant.of(initIgnoreList(), Type.QVariantMap)
   )
@@ -100,7 +100,7 @@ class IgnoreListManager constructor(
 
   fun updates() = live_updates.map { this }
 
-  fun copy() = IgnoreListManager(proxy).also {
+  fun copy() = IgnoreListManager(session).also {
     it.fromVariantMap(toVariantMap())
   }
 
@@ -265,5 +265,6 @@ class IgnoreListManager constructor(
     set(value) {
       field = value
       live_updates.onNext(Unit)
+      if (initialized) session.backlogManager.updateIgnoreRules()
     }
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
index a88c48fea2f8cb5462233f140ea654de97f3a0c8..e02a481bfabe5c4ece1c9fd76ffb011bbeb20c24 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
@@ -38,7 +38,7 @@ class RpcHandler(
 
   override fun displayMsg(message: Message) {
     session.bufferSyncer.bufferInfoUpdated(message.bufferInfo)
-    backlogStorage.storeMessages(message)
+    backlogStorage.storeMessages(session, message)
   }
 
   override fun requestCreateIdentity(identity: QVariantMap, additional: QVariantMap) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt b/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt
index 6e4c080ece649f9449a662980b54ba85dc7aa909..3ce51bbae9e62dcf60bb582a25f44a7d524bfb85 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/BacklogStorage.kt
@@ -4,12 +4,14 @@ import de.kuschku.libquassel.protocol.BufferId
 import de.kuschku.libquassel.protocol.Message
 
 interface BacklogStorage {
-  fun storeMessages(vararg messages: Message, initialLoad: Boolean = false)
-  fun storeMessages(messages: Iterable<Message>, initialLoad: Boolean = false)
+  fun updateIgnoreRules(session: Session)
+
+  fun storeMessages(session: Session, vararg messages: Message, initialLoad: Boolean = false)
+  fun storeMessages(session: Session, messages: Iterable<Message>, initialLoad: Boolean = false)
 
   fun clearMessages(bufferId: BufferId, idRange: IntRange)
 
   fun clearMessages(bufferId: BufferId)
 
   fun clearMessages()
-}
\ No newline at end of file
+}
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
index 37c141583d2adca8acc0cb6eb1806d4bab563528..11a376822c46a70cd6c5ea04643733b5b768206b 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt
@@ -2,39 +2,39 @@ package de.kuschku.quasseldroid.persistence
 
 import de.kuschku.libquassel.protocol.BufferId
 import de.kuschku.libquassel.protocol.Message
+import de.kuschku.libquassel.protocol.Message_Type
+import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.session.BacklogStorage
+import de.kuschku.libquassel.session.Session
 
 class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
-  override fun storeMessages(vararg messages: Message, initialLoad: Boolean) = storeMessages(
-    messages.asIterable(), initialLoad
-  )
-
-  override fun storeMessages(messages: Iterable<Message>, initialLoad: Boolean) {
-    if (initialLoad)
-      for ((bufferId, bufferMessages) in messages.sortedBy { it.messageId }.groupBy { it.bufferInfo.bufferId }) {
-        val lastMessageId = db.message().findLastByBufferId(bufferId)?.messageId
-        val firstMessage = bufferMessages.firstOrNull()
-        if (lastMessageId == null || firstMessage == null || lastMessageId < firstMessage.messageId) {
-          db.message().clearMessages(bufferId)
-        }
-      }
-
-    for (message in messages) {
-      db.message().save(
-        QuasselDatabase.DatabaseMessage(
-          messageId = message.messageId,
-          time = message.time,
-          type = message.type.value,
-          flag = message.flag.value,
-          bufferId = message.bufferInfo.bufferId,
-          sender = message.sender,
-          senderPrefixes = message.senderPrefixes,
-          realName = message.realName,
-          avatarUrl = message.avatarUrl,
-          content = message.content
-        )
+  override fun updateIgnoreRules(session: Session) {
+    db.message().save(
+      *db.message().all().map {
+        it.copy(ignored = isIgnored(session, it))
+      }.toTypedArray()
+    )
+  }
+
+  override fun storeMessages(session: Session, vararg messages: Message, initialLoad: Boolean) =
+    storeMessages(session, messages.asIterable(), initialLoad)
+
+  override fun storeMessages(session: Session, messages: Iterable<Message>, initialLoad: Boolean) {
+    db.message().save(*messages.map {
+      QuasselDatabase.DatabaseMessage(
+        messageId = it.messageId,
+        time = it.time,
+        type = it.type.value,
+        flag = it.flag.value,
+        bufferId = it.bufferInfo.bufferId,
+        sender = it.sender,
+        senderPrefixes = it.senderPrefixes,
+        realName = it.realName,
+        avatarUrl = it.avatarUrl,
+        content = it.content,
+        ignored = isIgnored(session, it)
       )
-    }
+    }.toTypedArray())
   }
 
   override fun clearMessages(bufferId: BufferId, idRange: IntRange) {
@@ -49,4 +49,24 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
     db.message().clearMessages()
   }
 
+  private fun isIgnored(session: Session, message: Message): Boolean {
+    val bufferName = message.bufferInfo.bufferName ?: ""
+    val networkId = message.bufferInfo.networkId
+    val networkName = session.network(networkId)?.networkName() ?: ""
+
+    return session.ignoreListManager.match(
+      message.content, message.sender, message.type, networkName, bufferName
+    ) != IgnoreListManager.StrictnessType.UnmatchedStrictness
+  }
+
+  private fun isIgnored(session: Session, message: QuasselDatabase.DatabaseMessage): Boolean {
+    val bufferInfo = session.bufferSyncer.bufferInfo(message.bufferId)
+    val bufferName = bufferInfo?.bufferName ?: ""
+    val networkId = bufferInfo?.networkId ?: -1
+    val networkName = session.network(networkId)?.networkName() ?: ""
+
+    return session.ignoreListManager.match(
+      message.content, message.sender, Message_Type.of(message.type), networkName, bufferName
+    ) != IgnoreListManager.StrictnessType.UnmatchedStrictness
+  }
 }
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
index 672f16b1add585c736ce92570c9d8a935f9daea1..3730a8f67a4684d2726d254b2d36dafab54b3980 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
@@ -3,7 +3,6 @@ package de.kuschku.quasseldroid.persistence
 import android.arch.lifecycle.LiveData
 import android.arch.paging.DataSource
 import android.arch.persistence.db.SupportSQLiteDatabase
-import android.arch.persistence.db.SupportSQLiteQuery
 import android.arch.persistence.room.*
 import android.arch.persistence.room.migration.Migration
 import android.content.Context
@@ -16,13 +15,13 @@ import de.kuschku.quasseldroid.persistence.QuasselDatabase.Filtered
 import io.reactivex.Flowable
 import org.threeten.bp.Instant
 
-@Database(entities = [DatabaseMessage::class, Filtered::class], version = 6)
+@Database(entities = [DatabaseMessage::class, Filtered::class], version = 8)
 @TypeConverters(DatabaseMessage.MessageTypeConverters::class)
 abstract class QuasselDatabase : RoomDatabase() {
   abstract fun message(): MessageDao
   abstract fun filtered(): FilteredDao
 
-  @Entity(tableName = "message")
+  @Entity(tableName = "message", indices = [Index("bufferId"), Index("ignored")])
   data class DatabaseMessage(
     @PrimaryKey var messageId: Int,
     var time: Instant,
@@ -33,7 +32,8 @@ abstract class QuasselDatabase : RoomDatabase() {
     var senderPrefixes: String,
     var realName: String,
     var avatarUrl: String,
-    var content: String
+    var content: String,
+    var ignored: Boolean
   ) {
     class MessageTypeConverters {
       @TypeConverter
@@ -54,26 +54,18 @@ abstract class QuasselDatabase : RoomDatabase() {
 
   @Dao
   interface MessageDao {
+    @Query("SELECT * FROM message")
+    fun all(): List<DatabaseMessage>
+
     @Query("SELECT * FROM message WHERE messageId = :messageId")
     fun find(messageId: Int): DatabaseMessage?
 
     @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC")
     fun findByBufferId(bufferId: Int): List<DatabaseMessage>
 
-    @Query(
-      "SELECT * FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 ORDER BY messageId DESC"
-    )
+    @Query("SELECT * FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId DESC")
     fun findByBufferIdPaged(bufferId: Int, type: Int): DataSource.Factory<Int, DatabaseMessage>
 
-    @RawQuery(observedEntities = [DatabaseMessage::class])
-    fun findMessagesRawPaged(query: SupportSQLiteQuery): DataSource.Factory<Int, DatabaseMessage>
-
-    @RawQuery
-    fun findDaysRaw(query: SupportSQLiteQuery): List<Instant>
-
-    @RawQuery
-    fun findMessagesRaw(query: SupportSQLiteQuery): List<DatabaseMessage>
-
     @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
     fun findLastByBufferId(bufferId: Int): DatabaseMessage?
 
@@ -83,7 +75,7 @@ abstract class QuasselDatabase : RoomDatabase() {
     @Query("SELECT messageId FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1")
     fun firstMsgId(bufferId: Int): Flowable<MsgId>
 
-    @Query("SELECT messageId FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 ORDER BY messageId ASC LIMIT 1")
+    @Query("SELECT messageId FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId ASC LIMIT 1")
     fun firstVisibleMsgId(bufferId: Int, type: Int): MsgId?
 
     @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1")
@@ -189,6 +181,18 @@ abstract class QuasselDatabase : RoomDatabase() {
                   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);")
+                }
               }
             ).build()
           }