From 8fd09f92adebdd54ba1d1176d6b51dd29631e05f Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Sat, 14 Apr 2018 02:51:18 +0200 Subject: [PATCH] Allow actual usage of ignore rules --- .../quasseldroid/ui/chat/ChatActivity.kt | 27 ++++++- .../quassel/syncables/BacklogManager.kt | 21 ++--- .../quassel/syncables/IgnoreListManager.kt | 9 ++- .../quassel/syncables/RpcHandler.kt | 2 +- .../libquassel/session/BacklogStorage.kt | 8 +- .../persistence/QuasselBacklogStorage.kt | 78 ++++++++++++------- .../persistence/QuasselDatabase.kt | 38 +++++---- 7 files changed, 111 insertions(+), 72 deletions(-) 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 07a553b5c..67b2adf82 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 f40c8f2f8..a027bde17 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 5003a00ef..1f4b085a0 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 a88c48fea..e02a481bf 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 6e4c080ec..3ce51bbae 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 37c141583..11a376822 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 672f16b1a..3730a8f67 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() } -- GitLab