From 853b5ed5f2d0f22a417041291a3bb7b3b3ce1d3f Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Sat, 9 Jun 2018 00:47:14 +0200 Subject: [PATCH] Fixes #107 --- .../de/kuschku/quasseldroid/Quasseldroid.kt | 3 +- .../quasseldroid/service/BacklogRequester.kt | 9 +++- .../quasseldroid/ui/chat/ChatActivity.kt | 39 +++++++++++---- .../quasseldroid/ui/chat/ToolbarFragment.kt | 4 +- .../chat/buffers/BufferViewConfigFragment.kt | 13 +++-- .../ui/chat/messages/MessageListFragment.kt | 50 ++++++++++++------- .../accounts/setup/AccountSetupActivity.kt | 3 +- app/src/main/res/values/strings.xml | 2 + .../persistence/AccountDatabase.kt | 16 +++++- .../persistence/MessageTypeConverter.kt | 31 ++++++++++++ .../persistence/QuasselDatabase.kt | 40 +++------------ .../viewmodel/QuasselViewModel.kt | 6 --- 12 files changed, 138 insertions(+), 78 deletions(-) create mode 100644 persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt diff --git a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt index 183d0aa31..baa4c0bd3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt @@ -86,7 +86,8 @@ class Quasseldroid : DaggerApplication() { pass = it.pass, name = it.name, lastUsed = 0, - acceptedMissingFeatures = false + acceptedMissingFeatures = false, + defaultFiltered = 0 ) }.toTypedArray()) Thread(Runnable { 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 d162bb3f6..cdd9be0c8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt @@ -26,13 +26,15 @@ import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.ERROR import de.kuschku.libquassel.util.helpers.value +import de.kuschku.quasseldroid.persistence.AccountDatabase import de.kuschku.quasseldroid.persistence.QuasselBacklogStorage import de.kuschku.quasseldroid.persistence.QuasselDatabase import de.kuschku.quasseldroid.viewmodel.QuasselViewModel class BacklogRequester( private val viewModel: QuasselViewModel, - private val database: QuasselDatabase + private val database: QuasselDatabase, + private val accountDatabase: AccountDatabase ) { fun loadMore(accountId: Long, buffer: BufferId, amount: Int, pageSize: Int, lastMessageId: MsgId? = null, @@ -44,7 +46,10 @@ class BacklogRequester( var missing = amount viewModel.session.value?.orNull()?.let { session: ISession -> session.backlogManager?.let { - val filtered = database.filtered().get(accountId, buffer) ?: 0 + val filtered = database.filtered().get(accountId, + buffer, + accountDatabase.accounts().findById(accountId)?.defaultFiltered + ?: 0) it.requestBacklog( bufferId = buffer, last = lastMessageId ?: database.message().findFirstByBufferId( 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 a355dc046..e5d44e112 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 @@ -668,7 +668,11 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc R.id.action_filter_messages -> { runInBackground { viewModel.buffer { buffer -> - val filtered = Message_Type.of(database.filtered().get(accountId, buffer) ?: 0) + val filteredRaw = database.filtered().get(accountId, + buffer, + accountDatabase.accounts().findById(accountId)?.defaultFiltered + ?: 0) + val filtered = Message_Type.of(filteredRaw) val flags = intArrayOf( Message.MessageType.Join.bit or Message.MessageType.NetsplitJoin.bit, Message.MessageType.Part.bit, @@ -678,20 +682,35 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc Message.MessageType.Topic.bit ) val selectedIndices = flags.withIndex().mapNotNull { (index, flag) -> - if ((filtered and flag).isNotEmpty()) { - index - } else { - null - } + if ((filtered and flag).isNotEmpty()) index + else null }.toTypedArray() MaterialDialog.Builder(this) .title(R.string.label_filter_messages) .items(R.array.message_filter_types) .itemsIds(flags) - .itemsCallbackMultiChoice(selectedIndices, { _, _, _ -> false }) + .itemsCallbackMultiChoice(selectedIndices) { _, _, _ -> false } .positiveText(R.string.label_select) - .negativeText(R.string.label_cancel) + .negativeText(R.string.label_use_default) + .onNegative { _, _ -> + runInBackground { + database.filtered().clear(accountId, buffer) + } + } + .neutralText(R.string.label_set_default) + .onNeutral { dialog, _ -> + val selected = dialog.selectedIndices ?: emptyArray() + runInBackground { + val newlyFiltered = selected + .asSequence() + .map { flags[it] } + .fold(Message_Type.of()) { acc, i -> acc or i } + + accountDatabase.accounts().setFiltered(accountId, newlyFiltered.value) + database.filtered().setFiltered(accountId, buffer, newlyFiltered.value) + } + } .onPositive { dialog, _ -> val selected = dialog.selectedIndices ?: emptyArray() runInBackground { @@ -704,7 +723,9 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc QuasselDatabase.Filtered(accountId, buffer, newlyFiltered.value) ) } - }.negativeColorAttr(R.attr.colorTextPrimary) + } + .negativeColorAttr(R.attr.colorTextPrimary) + .neutralColor(R.attr.colorTextPrimary) .backgroundColorAttr(R.attr.colorBackgroundCard) .contentColorAttr(R.attr.colorTextPrimary) .titleColorAttr(R.attr.colorTextPrimary) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt index 16b70d323..4b5fdb6ff 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt @@ -91,10 +91,10 @@ class ToolbarFragment : ServiceBoundFragment() { description, messageSettings.colorizeMirc ) - combineLatest(viewModel.bufferData, viewModel.isSecure, viewModel.lag).toLiveData() + combineLatest(viewModel.bufferData, viewModel.lag).toLiveData() .observe(this, Observer { if (it != null) { - val (data, isSecure, lag) = it + val (data, lag) = it if (data?.info?.type?.hasFlag(Buffer_Type.StatusBuffer) == true) { this.title = data.network?.networkName() } else { 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 e75cc68a9..c39f71c70 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 @@ -40,6 +40,7 @@ import de.kuschku.libquassel.util.flag.minus 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.settings.AppearanceSettings import de.kuschku.quasseldroid.settings.MessageSettings @@ -77,6 +78,9 @@ class BufferViewConfigFragment : ServiceBoundFragment() { @Inject lateinit var database: QuasselDatabase + @Inject + lateinit var accountDatabase: AccountDatabase + @Inject lateinit var ircFormatDeserializer: IrcFormatDeserializer @@ -264,9 +268,10 @@ class BufferViewConfigFragment : ServiceBoundFragment() { } combineLatest(viewModel.bufferList, viewModel.expandedNetworks, viewModel.selectedBuffer) - .toLiveData().zip(database.filtered().listen(accountId)) + .toLiveData().zip(database.filtered().listen(accountId), + accountDatabase.accounts().listen(accountId)) .observe(this, Observer { it -> - it?.let { (data, activityList) -> + it?.let { (data, activityList, account) -> runInBackground { val (info, expandedNetworks, selected) = data val (config, list) = info ?: Pair(null, emptyList()) @@ -277,7 +282,9 @@ class BufferViewConfigFragment : ServiceBoundFragment() { }.sortedBy { props -> props.network.networkName }.map { props -> - val activity = props.activity - (activities[props.info.bufferId] ?: 0) + val activity = props.activity - (activities[props.info.bufferId] + ?: account?.defaultFiltered + ?: 0) BufferListItem( props.copy( activity = activity, 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 a1bf07eb5..ac5cb23a6 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 @@ -52,6 +52,7 @@ 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.AccountDatabase import de.kuschku.quasseldroid.persistence.QuasselDatabase import de.kuschku.quasseldroid.service.BacklogRequester import de.kuschku.quasseldroid.settings.AppearanceSettings @@ -97,6 +98,9 @@ class MessageListFragment : ServiceBoundFragment() { @Inject lateinit var database: QuasselDatabase + @Inject + lateinit var accountDatabase: AccountDatabase + @Inject lateinit var adapter: MessageAdapter @@ -213,7 +217,7 @@ class MessageListFragment : ServiceBoundFragment() { linearLayoutManager = LinearLayoutManager(context) linearLayoutManager.reverseLayout = true - backlogRequester = BacklogRequester(viewModel, database) + backlogRequester = BacklogRequester(viewModel, database, accountDatabase) adapter.setOnClickListener { msg -> if (actionMode != null) { @@ -320,20 +324,24 @@ class MessageListFragment : ServiceBoundFragment() { viewModel.expandedMessages, viewModel.markerLine) .toLiveData().switchMapNotNull { (buffer, selected, expanded, markerLine) -> - database.filtered().listen(accountId, buffer).switchMapNotNull { filtered -> - LivePagedListBuilder( - database.message().findByBufferIdPaged(buffer, filtered).mapByPage { - processMessages(it, selected.keys, expanded, markerLine.orNull()) - }, - PagedList.Config.Builder() - .setPageSize(backlogSettings.pageSize) - .setPrefetchDistance(backlogSettings.pageSize) - .setInitialLoadSizeHint(backlogSettings.pageSize) - .setEnablePlaceholders(true) + accountDatabase.accounts().listen(accountId).switchMap { + database.filtered().listen(accountId, + buffer, + it.defaultFiltered).switchMapNotNull { filtered -> + LivePagedListBuilder( + database.message().findByBufferIdPaged(buffer, filtered).mapByPage { + processMessages(it, selected.keys, expanded, markerLine.orNull()) + }, + PagedList.Config.Builder() + .setPageSize(backlogSettings.pageSize) + .setPrefetchDistance(backlogSettings.pageSize) + .setInitialLoadSizeHint(backlogSettings.pageSize) + .setEnablePlaceholders(true) + .build() + ).setBoundaryCallback(boundaryCallback) + .setInitialLoadKey(previousLoadKey) .build() - ).setBoundaryCallback(boundaryCallback) - .setInitialLoadKey(previousLoadKey) - .build() + } } } @@ -350,9 +358,12 @@ class MessageListFragment : ServiceBoundFragment() { if (it?.orNull() == ConnectionState.CONNECTED) { runInBackgroundDelayed(16) { viewModel.buffer { bufferId -> - val filtered = database.filtered().get(accountId, bufferId) + val filtered = database.filtered().get(accountId, + bufferId, + accountDatabase.accounts().findById(accountId)?.defaultFiltered + ?: 0) // Try loading messages when switching to isEmpty buffer - val hasVisibleMessages = database.message().hasVisibleMessages(bufferId, filtered ?: 0) + val hasVisibleMessages = database.message().hasVisibleMessages(bufferId, filtered) if (!hasVisibleMessages) { if (bufferId > 0 && bufferId != Int.MAX_VALUE) { loadMore(initial = true) @@ -465,8 +476,11 @@ class MessageListFragment : ServiceBoundFragment() { bufferSyncer.requestSetMarkerLine(previous, lastMessageId) } // Try loading messages when switching to isEmpty buffer - val filtered = database.filtered().get(accountId, current) - val hasVisibleMessages = database.message().hasVisibleMessages(current, filtered ?: 0) + val filtered = database.filtered().get(accountId, + current, + accountDatabase.accounts().findById(accountId)?.defaultFiltered + ?: 0) + val hasVisibleMessages = database.message().hasVisibleMessages(current, filtered) if (!hasVisibleMessages) { if (current > 0 && current != Int.MAX_VALUE) { loadMore(initial = true) 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 25156ece6..9057c9a77 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 @@ -44,7 +44,8 @@ class AccountSetupActivity : SetupActivity() { pass = data.getString("pass"), name = data.getString("name"), lastUsed = Instant.now().epochSecond, - acceptedMissingFeatures = false + acceptedMissingFeatures = false, + defaultFiltered = 0 ) handler.post { database.accounts().create(account) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2fd0242cf..9e0cbfc0c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -92,6 +92,7 @@ <string name="label_rename">Rename</string> <string name="label_save">Save</string> <string name="label_select">Select</string> + <string name="label_set_default">Set Default</string> <string name="label_settings">Settings</string> <string name="label_settings_client">Client Settings</string> <string name="label_settings_core">Core Settings</string> @@ -101,6 +102,7 @@ <string name="label_topic">Channel Topic</string> <string name="label_translators">Translators</string> <string name="label_unhide">Make Visible</string> + <string name="label_use_default">Use Default</string> <string name="label_website">Website</string> <string name="label_whitelist">Ignore</string> <string name="label_whitelist_ignore_date">Expiration date is ignored for this certificate</string> diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt index 9b9819bc3..dd9b27a80 100644 --- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/AccountDatabase.kt @@ -25,7 +25,7 @@ import android.arch.persistence.room.* import android.arch.persistence.room.migration.Migration import android.content.Context -@Database(entities = [(AccountDatabase.Account::class)], version = 2) +@Database(entities = [(AccountDatabase.Account::class)], version = 3) abstract class AccountDatabase : RoomDatabase() { abstract fun accounts(): AccountDao @@ -39,7 +39,8 @@ abstract class AccountDatabase : RoomDatabase() { var pass: String, var name: String, var lastUsed: Long, - var acceptedMissingFeatures: Boolean + var acceptedMissingFeatures: Boolean, + var defaultFiltered: Int ) @Dao @@ -53,12 +54,18 @@ abstract class AccountDatabase : RoomDatabase() { @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() } @@ -81,6 +88,11 @@ abstract class AccountDatabase : RoomDatabase() { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("ALTER TABLE account ADD COLUMN acceptedMissingFeatures INTEGER NOT NULL DEFAULT 0;") } + }, + object : Migration(2, 3) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE account ADD COLUMN defaultFiltered INTEGER NOT NULL DEFAULT 0;") + } } ).allowMainThreadQueries().build() } diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt new file mode 100644 index 000000000..19dce40bc --- /dev/null +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/MessageTypeConverter.kt @@ -0,0 +1,31 @@ +package de.kuschku.quasseldroid.persistence + +import android.arch.persistence.room.TypeConverter +import de.kuschku.libquassel.protocol.* +import org.threeten.bp.Instant + +class MessageTypeConverter { + @TypeConverter + fun convertInstant(value: Long): Instant = Instant.ofEpochMilli(value) + + @TypeConverter + fun convertInstant(value: Instant) = value.toEpochMilli() + + @TypeConverter + fun convertBufferTypes(value: Buffer_Types) = value.toShort() + + @TypeConverter + fun convertBufferTypes(value: Short) = Buffer_Type.of(value) + + @TypeConverter + fun convertMessageTypes(value: Message_Types) = value.toInt() + + @TypeConverter + fun convertMessageTypes(value: Int) = Message.MessageType.of(value) + + @TypeConverter + fun convertMessageFlags(value: Message_Flags) = value.toInt() + + @TypeConverter + fun convertMessageFlags(value: Int) = Message.MessageFlag.of(value) +} 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 7a6433b8a..f2bf858a6 100644 --- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt @@ -41,32 +41,6 @@ abstract class QuasselDatabase : RoomDatabase() { abstract fun hostnameWhitelist(): SslHostnameWhitelistDao abstract fun notifications(): NotificationDao - class MessageTypeConverter { - @TypeConverter - fun convertInstant(value: Long): Instant = Instant.ofEpochMilli(value) - - @TypeConverter - fun convertInstant(value: Instant) = value.toEpochMilli() - - @TypeConverter - fun convertBufferTypes(value: Buffer_Types) = value.toShort() - - @TypeConverter - fun convertBufferTypes(value: Short) = Buffer_Type.of(value) - - @TypeConverter - fun convertMessageTypes(value: Message_Types) = value.toInt() - - @TypeConverter - fun convertMessageTypes(value: Int) = Message_Type.of(value) - - @TypeConverter - fun convertMessageFlags(value: Message_Flags) = value.toInt() - - @TypeConverter - fun convertMessageFlags(value: Int) = Message_Flag.of(value) - } - @Entity(tableName = "message", indices = [Index("bufferId"), Index("ignored")]) data class MessageData( @PrimaryKey var messageId: MsgId, @@ -147,20 +121,18 @@ abstract class QuasselDatabase : RoomDatabase() { @Insert(onConflict = OnConflictStrategy.REPLACE) fun replace(vararg entities: Filtered) - @Query( - "SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT 0 as filtered ORDER BY filtered DESC LIMIT 1" - ) - fun get(accountId: Long, bufferId: Int): Int? + @Query("UPDATE filtered SET filtered = :filtered WHERE accountId = :accountId AND bufferId = :bufferId") + fun setFiltered(accountId: Long, bufferId: Int, filtered: Int) @Query( - "SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT 0 as filtered ORDER BY filtered DESC LIMIT 1" + "SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT :default as filtered ORDER BY filtered DESC LIMIT 1" ) - fun listen(accountId: Long, bufferId: Int): LiveData<Int> + fun get(accountId: Long, bufferId: Int, default: Int): Int @Query( - "SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT 0 as filtered ORDER BY filtered DESC LIMIT 1" + "SELECT filtered FROM filtered WHERE bufferId = :bufferId AND accountId = :accountId UNION SELECT :default as filtered ORDER BY filtered DESC LIMIT 1" ) - fun listenRx(accountId: Long, bufferId: Int): Flowable<Int> + fun listen(accountId: Long, bufferId: Int, default: Int): LiveData<Int> @Query("SELECT * FROM filtered WHERE accountId = :accountId") fun listen(accountId: Long): LiveData<List<Filtered>> diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt index 19e4d5422..2c12beb4a 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt @@ -145,12 +145,6 @@ class QuasselViewModel : ViewModel() { // Remove orElse val lag: Observable<Long> = session.mapSwitchMap(ISession::lag).mapOrElse(0) - val isSecure: Observable<Boolean> = session.mapSwitchMap { session -> - session.state.map { _ -> - session.sslSession != null - } - }.mapOrElse(false) - val bufferData = combineLatest(session, buffer).switchMap { (sessionOptional, id) -> val session = sessionOptional.orNull() val bufferSyncer = session?.bufferSyncer -- GitLab