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 23cdc5645e5d2d1bde9fb371187471b419224986..de5563cee1ba39c0162ee0549d17af312bd98400 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 @@ -60,7 +60,6 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO import de.kuschku.libquassel.util.flag.and import de.kuschku.libquassel.util.flag.hasFlag -import de.kuschku.libquassel.util.flag.minus import de.kuschku.libquassel.util.flag.or import de.kuschku.libquassel.util.helper.combineLatest import de.kuschku.libquassel.util.helper.invoke @@ -359,41 +358,26 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } }) - val maxBufferActivity = combineLatest( - modelHelper.bufferList, + val filtered = combineLatest( database.filtered().listenRx(accountId).toObservable().map { it.associateBy(Filtered::bufferId, Filtered::filtered) }, accountDatabase.accounts().listenDefaultFiltered(accountId, 0).toObservable() - ).map { (info, filteredList, defaultFiltered) -> - val (config, bufferList) = info + ) - val minimumActivity = config?.minimumActivity()?.enabledValues()?.max() - ?: Buffer_Activity.NoActivity + val maxBufferActivity = modelHelper.processRawBufferList(modelHelper.bufferViewConfig, + filtered).map { (config, bufferList) -> + val minimumActivity: Buffer_Activity = config?.minimumActivity()?.enabledValues()?.max() + ?: Buffer_Activity.NoActivity - val maxActivity = bufferList.asSequence().map { props -> - val activity = props.activity - Message_Type.of(filteredList[props.info.bufferId]?.toUInt() - ?: defaultFiltered?.toUInt() - ?: 0u) - when { - props.highlights > 0 -> Buffer_Activity.Highlight - activity.hasFlag(Message_Type.Plain) || - activity.hasFlag(Message_Type.Notice) || - activity.hasFlag(Message_Type.Action) -> Buffer_Activity.NewMessage - activity.isNotEmpty() -> Buffer_Activity.OtherActivity - else -> Buffer_Activity.NoActivity - } + val maxActivity: Buffer_Activity = bufferList.mapNotNull { + it.bufferActivity.enabledValues().max() }.max() ?: Buffer_Activity.NoActivity val hasNotifications = bufferList.any { props -> - val activity = props.activity - Message_Type.of(filteredList[props.info.bufferId]?.toUInt() - ?: defaultFiltered?.toUInt() - ?: 0u) when { props.info.type hasFlag Buffer_Type.QueryBuffer -> - activity.hasFlag(Message_Type.Plain) || - activity.hasFlag(Message_Type.Notice) || - activity.hasFlag(Message_Type.Action) + props.bufferActivity hasFlag Buffer_Activity.NewMessage props.info.type hasFlag Buffer_Type.ChannelBuffer -> props.highlights > 0 else -> false diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/archive/ArchiveFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/archive/ArchiveFragment.kt index 4e9ea04b6b32c08b2e0a2cf42f88c1871f1c9720..720a49cc1859e9bf6fb4beba106f89c39ddeb112 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/archive/ArchiveFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/archive/ArchiveFragment.kt @@ -34,6 +34,7 @@ import de.kuschku.libquassel.util.helper.value import de.kuschku.quasseldroid.R 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.settings.MessageSettings import de.kuschku.quasseldroid.ui.chat.ChatActivity import de.kuschku.quasseldroid.ui.chat.buffers.BufferListAdapter @@ -146,13 +147,16 @@ class ArchiveFragment : ServiceBoundFragment() { listPermanently.layoutManager = LinearLayoutManager(listPermanently.context) listPermanently.itemAnimator = DefaultItemAnimator() + val filtered = combineLatest( + database.filtered().listenRx(accountId).toObservable().map { + it.associateBy(Filtered::bufferId, Filtered::filtered) + }, + accountDatabase.accounts().listenDefaultFiltered(accountId, 0).toObservable() + ) + fun processArchiveBufferList(bufferListType: BufferHiddenState, showHandle: Boolean) = - combineLatest( - modelHelper.processArchiveBufferList(bufferListType, showHandle), - database.filtered().listenRx(accountId).toObservable(), - accountDatabase.accounts().listenDefaultFiltered(accountId, 0).toObservable() - ).map { (buffers, filteredList, defaultFiltered) -> - bufferPresenter.render(buffers, filteredList, defaultFiltered.toUInt()) + modelHelper.processArchiveBufferList(bufferListType, showHandle, filtered).map { buffers -> + bufferPresenter.render(buffers) } processArchiveBufferList(BufferHiddenState.HIDDEN_TEMPORARY, false) 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 60762a55a99c149f9ebf53654b13628dae97e7b2..6078091b10159ab6a23fe7d6b112c9ce5807a77f 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 @@ -46,6 +46,7 @@ import de.kuschku.quasseldroid.BuildConfig import de.kuschku.quasseldroid.R 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.settings.AppearanceSettings import de.kuschku.quasseldroid.settings.MessageSettings import de.kuschku.quasseldroid.ui.chat.ChatActivity @@ -226,12 +227,15 @@ class BufferViewConfigFragment : ServiceBoundFragment() { ) }) - combineLatest( - modelHelper.processedBufferList, - database.filtered().listenRx(accountId).toObservable(), + val filtered = combineLatest( + database.filtered().listenRx(accountId).toObservable().map { + it.associateBy(Filtered::bufferId, Filtered::filtered) + }, accountDatabase.accounts().listenDefaultFiltered(accountId, 0).toObservable() - ).map { (buffers, filteredList, defaultFiltered) -> - bufferPresenter.render(buffers, filteredList, defaultFiltered.toUInt()) + ) + + modelHelper.processChatBufferList(filtered).map { buffers -> + bufferPresenter.render(buffers) }.toLiveData().observe(this, Observer { processedList -> if (hasRestoredChatListState) { chatListState = chatList.layoutManager?.onSaveInstanceState() diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/presenter/BufferPresenter.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/presenter/BufferPresenter.kt index 7777d3499891cd49bd1b6fd94291824b4830d661..61c970bd0cb496793cc030070053d8abd209298e 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/presenter/BufferPresenter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/presenter/BufferPresenter.kt @@ -19,13 +19,8 @@ package de.kuschku.quasseldroid.util.ui.presenter -import de.kuschku.libquassel.protocol.BufferId -import de.kuschku.libquassel.protocol.Buffer_Activity import de.kuschku.libquassel.protocol.Buffer_Type -import de.kuschku.libquassel.protocol.Message_Type import de.kuschku.libquassel.util.flag.hasFlag -import de.kuschku.libquassel.util.flag.minus -import de.kuschku.quasseldroid.persistence.models.Filtered import de.kuschku.quasseldroid.settings.AppearanceSettings import de.kuschku.quasseldroid.settings.MessageSettings import de.kuschku.quasseldroid.util.ColorContext @@ -42,30 +37,12 @@ class BufferPresenter @Inject constructor( val ircFormatDeserializer: IrcFormatDeserializer, val colorContext: ColorContext ) { - fun render(props: BufferProps, - activities: Map<BufferId, UInt>, - defaultFiltered: UInt - ): BufferProps { - val activity = props.activity - (activities[props.info.bufferId] - ?: defaultFiltered - ?: 0u) - + fun render(props: BufferProps): BufferProps { return props.copy( - activity = activity, description = ircFormatDeserializer.formatString( props.description.toString(), colorize = messageSettings.colorizeMirc ), - bufferActivity = Buffer_Activity.of( - when { - props.highlights > 0 -> Buffer_Activity.Highlight - activity.hasFlag(Message_Type.Plain) || - activity.hasFlag(Message_Type.Notice) || - activity.hasFlag(Message_Type.Action) -> Buffer_Activity.NewMessage - activity.isNotEmpty() -> Buffer_Activity.OtherActivity - else -> Buffer_Activity.NoActivity - } - ), fallbackDrawable = if (props.info.type.hasFlag(Buffer_Type.QueryBuffer)) { props.ircUser?.let { val nickName = it.nick() @@ -90,12 +67,8 @@ class BufferPresenter @Inject constructor( ) } - fun render(buffers: List<BufferListItem>, filteredList: List<Filtered>, defaultFiltered: UInt) = + fun render(buffers: List<BufferListItem>) = buffers.map { - it.copy(props = render( - it.props, - filteredList.associate { it.bufferId to it.filtered.toUInt() }, - defaultFiltered - )) + it.copy(props = render(it.props)) } } diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ArchiveViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ArchiveViewModelHelper.kt index 2f555d87fc78d80d28bd90757054ab34549a287f..08ec7fc989a114e7ea08c2ebca3c706ef96a14ca 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ArchiveViewModelHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ArchiveViewModelHelper.kt @@ -20,24 +20,13 @@ package de.kuschku.quasseldroid.viewmodel.helper import de.kuschku.libquassel.protocol.BufferId -import de.kuschku.libquassel.protocol.Buffer_Type -import de.kuschku.libquassel.protocol.Message_Type -import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.BufferViewConfig -import de.kuschku.libquassel.quassel.syncables.Network -import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork import de.kuschku.libquassel.util.Optional -import de.kuschku.libquassel.util.flag.hasFlag -import de.kuschku.libquassel.util.helper.combineLatest import de.kuschku.libquassel.util.helper.flatMapSwitchMap import de.kuschku.libquassel.util.helper.mapSwitchMap -import de.kuschku.libquassel.util.helper.safeSwitchMap -import de.kuschku.libquassel.util.irc.IrcCaseMappers import de.kuschku.quasseldroid.viewmodel.ArchiveViewModel import de.kuschku.quasseldroid.viewmodel.QuasselViewModel import de.kuschku.quasseldroid.viewmodel.data.BufferHiddenState -import de.kuschku.quasseldroid.viewmodel.data.BufferProps -import de.kuschku.quasseldroid.viewmodel.data.BufferStatus import io.reactivex.Observable import javax.inject.Inject @@ -51,128 +40,12 @@ open class ArchiveViewModelHelper @Inject constructor( }.mapSwitchMap(BufferViewConfig::liveUpdates) } - fun processBufferList(bufferListType: BufferHiddenState) = - combineLatest(connectedSession, bufferViewConfig) - .safeSwitchMap { (sessionOptional, configOptional) -> - val session = sessionOptional.orNull() - val bufferSyncer = session?.bufferSyncer - val config = configOptional.orNull() - if (bufferSyncer != null && config != null) { - session.liveNetworks().safeSwitchMap { networks -> - config.liveUpdates() - .safeSwitchMap { currentConfig -> - combineLatest<Collection<BufferId>>( - listOf( - config.liveBuffers(), - config.liveTemporarilyRemovedBuffers(), - config.liveRemovedBuffers() - ) - ).safeSwitchMap { (ids, temp, perm) -> - fun missingStatusBuffers( - list: Collection<BufferId> - ): Sequence<Observable<BufferProps>?> { - val buffers = list.asSequence().mapNotNull { id -> - bufferSyncer.bufferInfo(id) - } - - val totalNetworks = buffers.filter { - !it.type.hasFlag(Buffer_Type.StatusBuffer) - }.map { - it.networkId - }.toList() - - val availableNetworks = buffers.filter { - it.type.hasFlag(Buffer_Type.StatusBuffer) - }.map { - it.networkId - }.toList() - - val wantedNetworks = if (!currentConfig.networkId().isValidId()) totalNetworks - else listOf(currentConfig.networkId()) - - val missingNetworks = wantedNetworks - availableNetworks - - return missingNetworks.asSequence().filter { - !currentConfig.networkId().isValidId() || currentConfig.networkId() == it - }.filter { - currentConfig.allowedBufferTypes().hasFlag(Buffer_Type.StatusBuffer) - }.mapNotNull { - networks[it] - }.filter { - !config.hideInactiveNetworks() || it.isConnected() - }.map<Network, Observable<BufferProps>?> { network -> - network.liveNetworkInfo().safeSwitchMap { networkInfo -> - network.liveConnectionState().map { connectionState -> - BufferProps( - info = BufferInfo( - bufferId = BufferId(-networkInfo.networkId.id), - networkId = networkInfo.networkId, - groupId = 0, - bufferName = networkInfo.networkName, - type = Buffer_Type.of(Buffer_Type.StatusBuffer) - ), - network = networkInfo, - networkConnectionState = connectionState, - bufferStatus = BufferStatus.OFFLINE, - description = "", - activity = Message_Type.of(), - highlights = 0, - hiddenState = BufferHiddenState.VISIBLE - ) - } - } - } - } - - fun transformIds(ids: Collection<BufferId>, state: BufferHiddenState) = - processRawBufferList(ids, state, bufferSyncer, networks, currentConfig) + - missingStatusBuffers(ids) - - bufferSyncer.liveBufferInfos().safeSwitchMap { - val buffers = when (bufferListType) { - BufferHiddenState.VISIBLE -> - transformIds(ids, BufferHiddenState.VISIBLE) - BufferHiddenState.HIDDEN_TEMPORARY -> - transformIds(temp - ids, BufferHiddenState.HIDDEN_TEMPORARY) - BufferHiddenState.HIDDEN_PERMANENT -> - transformIds(perm - temp - ids, BufferHiddenState.HIDDEN_PERMANENT) - } - - combineLatest<BufferProps>(buffers.toList()).map { list -> - Pair<BufferViewConfig?, List<BufferProps>>( - config, - list.asSequence().filter { - !config.hideInactiveNetworks() || - it.networkConnectionState == INetwork.ConnectionState.Initialized - }.filter { - (!config.hideInactiveBuffers()) || - it.bufferStatus != BufferStatus.OFFLINE || - it.info.type.hasFlag(Buffer_Type.StatusBuffer) - }.let { - if (config.sortAlphabetically()) - it.sortedBy { IrcCaseMappers.unicode.toLowerCaseNullable(it.info.bufferName) } - .sortedBy { it.matchMode.priority } - .sortedByDescending { it.hiddenState == BufferHiddenState.VISIBLE } - else it - }.distinctBy { - it.info.bufferId - }.toList() - ) - } - } - } - } - } - } else { - Observable.just(Pair<BufferViewConfig?, List<BufferProps>>(null, emptyList())) - } - } - fun processArchiveBufferList( bufferListType: BufferHiddenState, - showHandle: Boolean - ) = processInternalBufferList( - processBufferList(bufferListType), + showHandle: Boolean, + filtered: Observable<Pair<Map<BufferId, Int>, Int>> + ) = filterBufferList( + processRawBufferList(bufferViewConfig, filtered, bufferListType = bufferListType), when (bufferListType) { BufferHiddenState.VISIBLE -> archive.visibleExpandedNetworks BufferHiddenState.HIDDEN_TEMPORARY -> archive.temporarilyExpandedNetworks diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt index a5ec65d1d22a06908ab0751da873ca7fdf2fbf7e..7dfb92e1473c5748ad1e7d10ee3e6458c55f0a6e 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt @@ -21,20 +21,17 @@ package de.kuschku.quasseldroid.viewmodel.helper import de.kuschku.libquassel.protocol.BufferId import de.kuschku.libquassel.protocol.Buffer_Type -import de.kuschku.libquassel.protocol.Message_Type import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.BufferViewConfig import de.kuschku.libquassel.quassel.syncables.IrcChannel import de.kuschku.libquassel.quassel.syncables.IrcUser -import de.kuschku.libquassel.quassel.syncables.Network -import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork import de.kuschku.libquassel.util.Optional import de.kuschku.libquassel.util.flag.hasFlag import de.kuschku.libquassel.util.helper.* -import de.kuschku.libquassel.util.irc.IrcCaseMappers import de.kuschku.quasseldroid.viewmodel.ChatViewModel import de.kuschku.quasseldroid.viewmodel.QuasselViewModel -import de.kuschku.quasseldroid.viewmodel.data.* +import de.kuschku.quasseldroid.viewmodel.data.BufferData +import de.kuschku.quasseldroid.viewmodel.data.IrcUserItem import io.reactivex.Observable import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -175,125 +172,10 @@ open class ChatViewModelHelper @Inject constructor( val selectedBuffer = processSelectedBuffer(chat.selectedBufferId, bufferViewConfig) - val bufferList: Observable<Pair<BufferViewConfig?, List<BufferProps>>> = - combineLatest(connectedSession, bufferViewConfig, chat.showHidden, chat.bufferSearch) - .safeSwitchMap { (sessionOptional, configOptional, showHiddenRaw, bufferSearch) -> - val session = sessionOptional.orNull() - val bufferSyncer = session?.bufferSyncer - val showHidden = showHiddenRaw ?: false - val config = configOptional.orNull() - if (bufferSyncer != null && config != null) { - session.liveNetworks().safeSwitchMap { networks -> - config.liveUpdates() - .safeSwitchMap { currentConfig -> - combineLatest<Collection<BufferId>>( - listOf( - config.liveBuffers(), - config.liveTemporarilyRemovedBuffers(), - config.liveRemovedBuffers() - ) - ).safeSwitchMap { (ids, temp, perm) -> - fun transformIds(ids: Collection<BufferId>, state: BufferHiddenState) = - processRawBufferList( - ids, - state, - bufferSyncer, - networks, - currentConfig, - bufferSearch - ) - - fun missingStatusBuffers( - list: Collection<BufferId>): Sequence<Observable<BufferProps>?> { - val totalNetworks = networks.keys - val wantedNetworks = if (!currentConfig.networkId().isValidId()) totalNetworks - else listOf(currentConfig.networkId()) - - val availableNetworks = list.asSequence().mapNotNull { id -> - bufferSyncer.bufferInfo(id) - }.filter { - it.type.hasFlag(Buffer_Type.StatusBuffer) - }.map { - it.networkId - } - - val missingNetworks = wantedNetworks - availableNetworks - - return missingNetworks.asSequence().filter { - !currentConfig.networkId().isValidId() || currentConfig.networkId() == it - }.filter { - currentConfig.allowedBufferTypes().hasFlag(Buffer_Type.StatusBuffer) - }.mapNotNull { - networks[it] - }.filter { - !config.hideInactiveNetworks() || it.isConnected() - }.map<Network, Observable<BufferProps>?> { network -> - network.liveNetworkInfo().safeSwitchMap { networkInfo -> - network.liveConnectionState().map { connectionState -> - BufferProps( - info = BufferInfo( - bufferId = BufferId(-networkInfo.networkId.id), - networkId = networkInfo.networkId, - groupId = 0, - bufferName = networkInfo.networkName, - type = Buffer_Type.of(Buffer_Type.StatusBuffer) - ), - network = networkInfo, - networkConnectionState = connectionState, - bufferStatus = BufferStatus.OFFLINE, - description = "", - activity = Message_Type.of(), - highlights = 0, - hiddenState = BufferHiddenState.VISIBLE - ) - } - } - } - } - - bufferSyncer.liveBufferInfos().safeSwitchMap { - val buffers = if (showHidden || bufferSearch.isNotBlank()) { - transformIds(ids, BufferHiddenState.VISIBLE) + - transformIds(temp - ids, BufferHiddenState.HIDDEN_TEMPORARY) + - transformIds(perm - temp - ids, BufferHiddenState.HIDDEN_PERMANENT) + - missingStatusBuffers(ids + temp + perm) - } else { - transformIds(ids, BufferHiddenState.VISIBLE) + - missingStatusBuffers(ids) - } - - combineLatest<BufferProps>(buffers.toList()).map { list -> - Pair<BufferViewConfig?, List<BufferProps>>( - config, - list.asSequence().filter { - !config.hideInactiveNetworks() || - it.networkConnectionState == INetwork.ConnectionState.Initialized - }.filter { - (!config.hideInactiveBuffers()) || - it.bufferStatus != BufferStatus.OFFLINE || - it.info.type.hasFlag(Buffer_Type.StatusBuffer) - }.let { - if (config.sortAlphabetically()) - it.sortedBy { IrcCaseMappers.unicode.toLowerCaseNullable(it.info.bufferName) } - .sortedBy { it.matchMode.priority } - .sortedByDescending { it.hiddenState == BufferHiddenState.VISIBLE } - else it - }.distinctBy { - it.info.bufferId - }.toList() - ) - } - } - } - } - } - } else { - Observable.just(Pair<BufferViewConfig?, List<BufferProps>>(null, emptyList())) - } - } - - val processedBufferList = processInternalBufferList( - bufferList, + fun processChatBufferList( + filtered: Observable<Pair<Map<BufferId, Int>, Int>> + ) = filterBufferList( + processRawBufferList(bufferViewConfig, filtered), chat.expandedNetworks, chat.selectedBufferId, false diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt index e4db3b366ee2af2eab5092ac48375ac6b8fa46a9..9390ec1c82b3018986e105fa66a6b43aaab81167 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt @@ -172,13 +172,15 @@ open class EditorViewModelHelper @Inject constructor( Observable.just(it) } - processResults(when (lastWord.first.firstOrNull()) { + processResults( + when (lastWord.first.firstOrNull()) { '/' -> getAliases() '@' -> getNicks() '#' -> getBuffers() ':' -> getEmojis() else -> getAliases() + getNicks() + getBuffers() + getEmojis() - }) + } + ) } } } diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt index dc8c062f210401ad45b071aea0e2357b7c5e6420..f57a19ac525269d17f1be22a3e76ebec65cb91f5 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt @@ -21,10 +21,7 @@ package de.kuschku.quasseldroid.viewmodel.helper import de.kuschku.libquassel.connection.ConnectionState import de.kuschku.libquassel.connection.Features -import de.kuschku.libquassel.protocol.BufferId -import de.kuschku.libquassel.protocol.Buffer_Activity -import de.kuschku.libquassel.protocol.Buffer_Type -import de.kuschku.libquassel.protocol.NetworkId +import de.kuschku.libquassel.protocol.* import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.* import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork @@ -34,7 +31,9 @@ import de.kuschku.libquassel.ssl.X509Helper import de.kuschku.libquassel.util.Optional import de.kuschku.libquassel.util.flag.and import de.kuschku.libquassel.util.flag.hasFlag +import de.kuschku.libquassel.util.flag.minus import de.kuschku.libquassel.util.helper.* +import de.kuschku.libquassel.util.irc.IrcCaseMappers import de.kuschku.quasseldroid.Backend import de.kuschku.quasseldroid.viewmodel.QuasselViewModel import de.kuschku.quasseldroid.viewmodel.data.* @@ -129,9 +128,16 @@ open class QuasselViewModelHelper @Inject constructor( }.orElse(Observable.empty()) } - fun processRawBufferList(ids: Collection<BufferId>, state: BufferHiddenState, - bufferSyncer: BufferSyncer, networks: Map<NetworkId, Network>, - currentConfig: BufferViewConfig, bufferSearch: String = "") = + fun generateBufferProps( + ids: Collection<BufferId>, + state: BufferHiddenState, + bufferSyncer: BufferSyncer, + networks: Map<NetworkId, Network>, + currentConfig: BufferViewConfig, + filtered: Map<BufferId, Int>, + defaultFiltered: Int, + bufferSearch: String = "" + ) = ids.asSequence().mapNotNull { id -> bufferSyncer.bufferInfo(id) }.filter { @@ -153,9 +159,9 @@ open class QuasselViewModelHelper @Inject constructor( }.map<Pair<BufferInfo, Network>, Observable<BufferProps>?> { (info, network) -> bufferSyncer.liveActivity(info.bufferId).safeSwitchMap { activity -> bufferSyncer.liveHighlightCount(info.bufferId).map { highlights -> - activity to highlights + Pair(activity, highlights) } - }.safeSwitchMap { (activity, highlights) -> + }.safeSwitchMap { (rawActivity, highlights) -> val name = info.bufferName?.trim() ?: "" val search = bufferSearch.trim() val matchMode = when { @@ -163,6 +169,8 @@ open class QuasselViewModelHelper @Inject constructor( name.startsWith(search, ignoreCase = true) -> MatchMode.START else -> MatchMode.CONTAINS } + val activity = rawActivity - Message_Type.of(filtered[info.bufferId]?.toUInt() + ?: defaultFiltered.toUInt()) when (info.type.toInt()) { BufferInfo.Type.QueryBuffer.toInt() -> { network.liveNetworkInfo().safeSwitchMap { networkInfo -> @@ -181,6 +189,18 @@ open class QuasselViewModelHelper @Inject constructor( description = user?.realName() ?: "", activity = activity, highlights = highlights, + bufferActivity = when { + highlights > 0 -> + Buffer_Activity.of(Buffer_Activity.Highlight) + activity hasFlag Message_Type.Plain || + activity hasFlag Message_Type.Notice || + activity hasFlag Message_Type.Action -> + Buffer_Activity.of(Buffer_Activity.NewMessage) + activity.isNotEmpty() -> + Buffer_Activity.of(Buffer_Activity.OtherActivity) + else -> + Buffer_Activity.of(Buffer_Activity.NoActivity) + }, hiddenState = state, ircUser = user, matchMode = matchMode @@ -206,6 +226,18 @@ open class QuasselViewModelHelper @Inject constructor( description = it?.topic() ?: "", activity = activity, highlights = highlights, + bufferActivity = when { + highlights > 0 -> + Buffer_Activity.of(Buffer_Activity.Highlight) + activity hasFlag Message_Type.Plain || + activity hasFlag Message_Type.Notice || + activity hasFlag Message_Type.Action -> + Buffer_Activity.of(Buffer_Activity.NewMessage) + activity.isNotEmpty() -> + Buffer_Activity.of(Buffer_Activity.OtherActivity) + else -> + Buffer_Activity.of(Buffer_Activity.NoActivity) + }, hiddenState = state, matchMode = matchMode ) @@ -225,6 +257,18 @@ open class QuasselViewModelHelper @Inject constructor( description = "", activity = activity, highlights = highlights, + bufferActivity = when { + highlights > 0 -> + Buffer_Activity.of(Buffer_Activity.Highlight) + activity hasFlag Message_Type.Plain || + activity hasFlag Message_Type.Notice || + activity hasFlag Message_Type.Action -> + Buffer_Activity.of(Buffer_Activity.NewMessage) + activity.isNotEmpty() -> + Buffer_Activity.of(Buffer_Activity.OtherActivity) + else -> + Buffer_Activity.of(Buffer_Activity.NoActivity) + }, hiddenState = state, matchMode = matchMode ) @@ -236,7 +280,138 @@ open class QuasselViewModelHelper @Inject constructor( } } - fun processInternalBufferList( + fun processRawBufferList( + bufferViewConfig: Observable<Optional<BufferViewConfig>>, + filteredTypes: Observable<Pair<Map<BufferId, Int>, Int>>, + bufferSearch: Observable<String> = Observable.just(""), + bufferListType: BufferHiddenState = BufferHiddenState.VISIBLE + ): Observable<Pair<BufferViewConfig?, List<BufferProps>>> = + combineLatest(connectedSession, bufferViewConfig, filteredTypes, bufferSearch) + .safeSwitchMap { (sessionOptional, configOptional, rawFiltered, bufferSearch) -> + val session = sessionOptional.orNull() + val bufferSyncer = session?.bufferSyncer + val config = configOptional.orNull() + val (filtered, defaultFiltered) = rawFiltered + if (bufferSyncer != null && config != null) { + session.liveNetworks().safeSwitchMap { networks -> + config.liveUpdates() + .safeSwitchMap { currentConfig -> + combineLatest<Collection<BufferId>>( + listOf( + config.liveBuffers(), + config.liveTemporarilyRemovedBuffers(), + config.liveRemovedBuffers() + ) + ).safeSwitchMap { (ids, temp, perm) -> + fun transformIds(ids: Collection<BufferId>, state: BufferHiddenState) = + generateBufferProps( + ids, + state, + bufferSyncer, + networks, + currentConfig, + filtered, + defaultFiltered, + bufferSearch + ) + + fun missingStatusBuffers( + list: Collection<BufferId>): Sequence<Observable<BufferProps>?> { + val totalNetworks = networks.keys + val wantedNetworks = if (!currentConfig.networkId().isValidId()) totalNetworks + else listOf(currentConfig.networkId()) + + val availableNetworks = list.asSequence().mapNotNull { id -> + bufferSyncer.bufferInfo(id) + }.filter { + it.type.hasFlag(Buffer_Type.StatusBuffer) + }.map { + it.networkId + } + + val missingNetworks = wantedNetworks - availableNetworks + + return missingNetworks.asSequence().filter { + !currentConfig.networkId().isValidId() || currentConfig.networkId() == it + }.filter { + currentConfig.allowedBufferTypes().hasFlag(Buffer_Type.StatusBuffer) + }.mapNotNull { + networks[it] + }.filter { + !config.hideInactiveNetworks() || it.isConnected() + }.map<Network, Observable<BufferProps>?> { network -> + network.liveNetworkInfo().safeSwitchMap { networkInfo -> + network.liveConnectionState().map { connectionState -> + BufferProps( + info = BufferInfo( + bufferId = BufferId(-networkInfo.networkId.id), + networkId = networkInfo.networkId, + groupId = 0, + bufferName = networkInfo.networkName, + type = Buffer_Type.of(Buffer_Type.StatusBuffer) + ), + network = networkInfo, + networkConnectionState = connectionState, + bufferStatus = BufferStatus.OFFLINE, + description = "", + activity = Message_Type.of(), + highlights = 0, + hiddenState = BufferHiddenState.VISIBLE + ) + } + } + } + } + + bufferSyncer.liveBufferInfos().safeSwitchMap { + val buffers = if (bufferSearch.isNotBlank()) { + transformIds(ids, BufferHiddenState.VISIBLE) + + transformIds(temp - ids, BufferHiddenState.HIDDEN_TEMPORARY) + + transformIds(perm - temp - ids, BufferHiddenState.HIDDEN_PERMANENT) + + missingStatusBuffers(ids + temp + perm) + } else when (bufferListType) { + BufferHiddenState.VISIBLE -> + transformIds(ids, BufferHiddenState.VISIBLE) + + missingStatusBuffers(ids) + BufferHiddenState.HIDDEN_TEMPORARY -> + transformIds(temp - ids, BufferHiddenState.HIDDEN_TEMPORARY) + + missingStatusBuffers(temp - ids) + BufferHiddenState.HIDDEN_PERMANENT -> + transformIds(perm - temp - ids, BufferHiddenState.HIDDEN_PERMANENT) + + missingStatusBuffers(perm - temp - ids) + } + + combineLatest<BufferProps>(buffers.toList()).map { list -> + Pair<BufferViewConfig?, List<BufferProps>>( + config, + list.asSequence().filter { + !config.hideInactiveNetworks() || + it.networkConnectionState == INetwork.ConnectionState.Initialized + }.filter { + (!config.hideInactiveBuffers()) || + it.bufferStatus != BufferStatus.OFFLINE || + it.info.type.hasFlag(Buffer_Type.StatusBuffer) + }.let { + if (config.sortAlphabetically()) + it.sortedBy { IrcCaseMappers.unicode.toLowerCaseNullable(it.info.bufferName) } + .sortedBy { it.matchMode.priority } + .sortedByDescending { it.hiddenState == BufferHiddenState.VISIBLE } + else it + }.distinctBy { + it.info.bufferId + }.toList() + ) + } + } + } + } + } + } else { + Observable.just(Pair<BufferViewConfig?, List<BufferProps>>(null, emptyList())) + } + } + + fun filterBufferList( buffers: Observable<Pair<BufferViewConfig?, List<BufferProps>>>, expandedNetworks: Observable<Map<NetworkId, Boolean>>, selected: Observable<BufferId>,