Skip to content
Snippets Groups Projects
Verified Commit 4f781879 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Fixes buffer search not working

parent fc4fdf28
No related branches found
No related tags found
No related merge requests found
Pipeline #494 canceled
......@@ -365,7 +365,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
accountDatabase.accounts().listenDefaultFiltered(accountId, 0).toObservable()
)
val maxBufferActivity = modelHelper.processRawBufferList(modelHelper.bufferViewConfig,
val maxBufferActivity = modelHelper.processBufferList(modelHelper.bufferViewConfig,
filtered).map { (config, bufferList) ->
val minimumActivity: Buffer_Activity = config?.minimumActivity()?.enabledValues()?.max()
?: Buffer_Activity.NoActivity
......
......@@ -66,7 +66,6 @@ import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
import de.kuschku.quasseldroid.util.ui.BetterLinkMovementMethod
import de.kuschku.quasseldroid.util.ui.LinkLongClickMenuHelper
import de.kuschku.quasseldroid.viewmodel.data.Avatar
import de.kuschku.quasseldroid.viewmodel.data.BufferHiddenState
import de.kuschku.quasseldroid.viewmodel.data.BufferProps
import de.kuschku.quasseldroid.viewmodel.data.BufferStatus
import de.kuschku.quasseldroid.viewmodel.helper.EditorViewModelHelper
......@@ -241,7 +240,6 @@ class UserInfoFragment : ServiceBoundFragment() {
description = it.topic(),
activity = Message_Type.of(),
bufferStatus = bufferStatus,
hiddenState = BufferHiddenState.VISIBLE,
networkConnectionState = user.network().connectionState(),
fallbackDrawable = fallbackDrawable
)
......
......@@ -37,7 +37,6 @@ data class BufferProps(
val bufferActivity: Buffer_Activities = BufferInfo.Activity.of(
BufferInfo.Activity.NoActivity
),
val hiddenState: BufferHiddenState,
val ircUser: IrcUser? = null,
val avatarUrls: List<Avatar> = emptyList(),
val fallbackDrawable: Drawable? = null,
......@@ -57,7 +56,6 @@ data class BufferProps(
if (activity != other.activity) return false
if (highlights != other.highlights) return false
if (bufferActivity != other.bufferActivity) return false
if (hiddenState != other.hiddenState) return false
if (ircUser != other.ircUser) return false
if (avatarUrls != other.avatarUrls) return false
......@@ -73,7 +71,6 @@ data class BufferProps(
result = 31 * result + activity.hashCode()
result = 31 * result + highlights
result = 31 * result + bufferActivity.hashCode()
result = 31 * result + hiddenState.hashCode()
result = 31 * result + (ircUser?.hashCode() ?: 0)
result = 31 * result + avatarUrls.hashCode()
return result
......
......@@ -45,7 +45,7 @@ open class ArchiveViewModelHelper @Inject constructor(
showHandle: Boolean,
filtered: Observable<Pair<Map<BufferId, Int>, Int>>
) = filterBufferList(
processRawBufferList(
processBufferList(
bufferViewConfig,
filtered,
bufferListType = bufferListType,
......@@ -60,5 +60,5 @@ open class ArchiveViewModelHelper @Inject constructor(
showHandle
)
val selectedBuffer = processSelectedBuffer(archive.selectedBufferId, bufferViewConfig)
val selectedBuffer = processSelectedBuffer(archive.selectedBufferId)
}
......@@ -170,14 +170,18 @@ open class ChatViewModelHelper @Inject constructor(
val nickDataThrottled =
nickData.distinctUntilChanged().throttleLast(100, TimeUnit.MILLISECONDS)
val selectedBuffer = processSelectedBuffer(chat.selectedBufferId, bufferViewConfig)
val selectedBuffer = processSelectedBuffer(chat.selectedBufferId)
fun processChatBufferList(
filtered: Observable<Pair<Map<BufferId, Int>, Int>>
) = filterBufferList(
processRawBufferList(bufferViewConfig, filtered),
processBufferList(
bufferViewConfig,
filtered,
bufferSearch = chat.bufferSearch
),
chat.expandedNetworks,
chat.selectedBufferId,
false
showHandle = false
)
}
......@@ -128,27 +128,54 @@ open class QuasselViewModelHelper @Inject constructor(
}.orElse(Observable.empty())
}
fun generateBufferProps(
ids: Collection<BufferId>,
state: BufferHiddenState,
bufferSyncer: BufferSyncer,
networks: Map<NetworkId, Network>,
currentConfig: BufferViewConfig,
filtered: Map<BufferId, Int>,
defaultFiltered: Int,
bufferSearch: String = ""
): Sequence<Observable<BufferProps>> = ids.asSequence().mapNotNull { id ->
bufferSyncer.bufferInfo(id)
/**
* Builds a buffer list for a given bufferViewConfig
*/
fun processBufferList(
bufferViewConfig: Observable<Optional<BufferViewConfig>>,
filteredTypes: Observable<Pair<Map<BufferId, Int>, Int>>,
bufferSearch: Observable<String> = Observable.just(""),
bufferListType: BufferHiddenState = BufferHiddenState.VISIBLE,
showAllNetworks: Boolean = true
): Observable<Pair<BufferViewConfig?, List<BufferProps>>> =
combineLatest(connectedSession, bufferViewConfig, filteredTypes, bufferSearch)
.safeSwitchMap { (sessionOptional, configOptional, rawFiltered, bufferSearch) ->
val session = sessionOptional.orNull()
val bufferView = configOptional.orNull()
val (filtered, defaultFiltered) = rawFiltered
val search = bufferSearch.trim()
if (session != null && bufferView != null) {
bufferView.liveUpdates().safeSwitchMap { config ->
val minimumActivity = config.minimumActivity()
combineLatest<Collection<BufferId>>(listOf(
config.liveBuffers(),
config.liveTemporarilyRemovedBuffers(),
config.liveRemovedBuffers()
)).safeSwitchMap { (ids, temp, perm) ->
val bufferIds = if (search.isNotBlank()) {
ids + temp + perm
} else when (bufferListType) {
BufferHiddenState.VISIBLE -> ids
BufferHiddenState.HIDDEN_TEMPORARY -> temp - ids
BufferHiddenState.HIDDEN_PERMANENT -> perm - temp - ids
}
combineLatest(
session.bufferSyncer.liveBufferInfos(),
session.liveNetworks()
).safeSwitchMap { (bufferInfos, networks) ->
val prefiltered = bufferIds.asSequence().mapNotNull { id ->
bufferInfos[id]
}.filter {
bufferSearch.isBlank() ||
search.isBlank() ||
it.type.hasFlag(Buffer_Type.StatusBuffer) ||
it.bufferName?.contains(bufferSearch, ignoreCase = true) == true
}.filter {
!currentConfig.networkId().isValidId() || currentConfig.networkId() == it.networkId
}.filter {
(currentConfig.allowedBufferTypes() and it.type).isNotEmpty() ||
(it.type.hasFlag(Buffer_Type.StatusBuffer) && !currentConfig.networkId().isValidId())
}.mapNotNull {
it.bufferName?.contains(search, ignoreCase = true) == true
}
fun transformIds(
ids: Sequence<BufferInfo>
): Sequence<Observable<BufferProps>> = ids.mapNotNull {
val network = networks[it.networkId]
if (network == null) {
null
......@@ -156,13 +183,12 @@ open class QuasselViewModelHelper @Inject constructor(
it to network
}
}.mapNotNull<Pair<BufferInfo, Network>, Observable<BufferProps>> { (info, network) ->
bufferSyncer.liveActivity(info.bufferId).safeSwitchMap { activity ->
bufferSyncer.liveHighlightCount(info.bufferId).map { highlights ->
session.bufferSyncer.liveActivity(info.bufferId).safeSwitchMap { activity ->
session.bufferSyncer.liveHighlightCount(info.bufferId).map { highlights ->
Pair(activity, highlights)
}
}.safeSwitchMap { (rawActivity, highlights) ->
val name = info.bufferName?.trim() ?: ""
val search = bufferSearch.trim()
val matchMode = when {
name.equals(search, ignoreCase = true) -> MatchMode.EXACT
name.startsWith(search, ignoreCase = true) -> MatchMode.START
......@@ -200,7 +226,6 @@ open class QuasselViewModelHelper @Inject constructor(
else ->
Buffer_Activity.of(Buffer_Activity.NoActivity)
},
hiddenState = state,
ircUser = user,
matchMode = matchMode
)
......@@ -237,7 +262,6 @@ open class QuasselViewModelHelper @Inject constructor(
else ->
Buffer_Activity.of(Buffer_Activity.NoActivity)
},
hiddenState = state,
matchMode = matchMode
)
}
......@@ -268,7 +292,6 @@ open class QuasselViewModelHelper @Inject constructor(
else ->
Buffer_Activity.of(Buffer_Activity.NoActivity)
},
hiddenState = state,
matchMode = matchMode
)
}
......@@ -279,51 +302,19 @@ open class QuasselViewModelHelper @Inject constructor(
}
}
fun processRawBufferList(
bufferViewConfig: Observable<Optional<BufferViewConfig>>,
filteredTypes: Observable<Pair<Map<BufferId, Int>, Int>>,
bufferSearch: Observable<String> = Observable.just(""),
bufferListType: BufferHiddenState = BufferHiddenState.VISIBLE,
showAllNetworks: Boolean = true
): 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
)
/**
* Takes a list of buffers and determines if the status buffers for the networks
* each buffer belongs to exist, if not, adds pseudo-buffers for them.
*/
/**
* Takes a list of buffers and determines if the status buffers for the networks
* each buffer belongs to exist, if not, adds pseudo-buffers for them.
*/
fun missingStatusBuffers(
list: Collection<BufferId>
buffers: Sequence<BufferInfo>
): Sequence<Observable<BufferProps>> {
val buffers = list.asSequence().mapNotNull { id ->
bufferSyncer.bufferInfo(id)
}
val totalNetworks =
if (showAllNetworks) networks.keys
if (showAllNetworks && search.isEmpty()) networks.keys
else buffers.filter {
!it.type.hasFlag(Buffer_Type.StatusBuffer)
}.map {
......@@ -336,15 +327,15 @@ open class QuasselViewModelHelper @Inject constructor(
it.networkId
}.toList()
val wantedNetworks = if (!currentConfig.networkId().isValidId()) totalNetworks
else listOf(currentConfig.networkId())
val wantedNetworks = if (!config.networkId().isValidId()) totalNetworks
else listOf(config.networkId())
val missingNetworks = wantedNetworks - availableNetworks
return missingNetworks.asSequence().filter {
!currentConfig.networkId().isValidId() || currentConfig.networkId() == it
!config.networkId().isValidId() || config.networkId() == it
}.filter {
currentConfig.allowedBufferTypes().hasFlag(Buffer_Type.StatusBuffer)
config.allowedBufferTypes().hasFlag(Buffer_Type.StatusBuffer)
}.mapNotNull {
networks[it]
}.filter {
......@@ -365,53 +356,65 @@ open class QuasselViewModelHelper @Inject constructor(
bufferStatus = BufferStatus.OFFLINE,
description = "",
activity = Message_Type.of(),
highlights = 0,
hiddenState = BufferHiddenState.VISIBLE
highlights = 0
)
}
}
}
}
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)
}
val buffers = transformIds(prefiltered) + missingStatusBuffers(prefiltered)
combineLatest(buffers.toList()).map { list ->
val wantedNetworks = list.filter {
!it.info.type.hasFlag(Buffer_Type.StatusBuffer)
}.map {
it.info.networkId
}.toList()
combineLatest<BufferProps>(buffers.toList()).map { list ->
Pair<BufferViewConfig?, List<BufferProps>>(
config,
list.asSequence().filter {
// Only show the currently selected network
!config.networkId().isValidId() ||
config.networkId() == it.info.networkId
}.filter {
// Only show buffers which are allowed, or network status buffers
(!config.networkId().isValidId() && it.info.type.hasFlag(Buffer_Type.StatusBuffer)) ||
(config.allowedBufferTypes() and it.info.type).isNotEmpty()
}.filter {
// If we’re searching for buffers, only include the networks with results
search.isEmpty() ||
it.info.networkId in wantedNetworks
}.filter {
// If the config is set to hide inactive networks, only show initialized
// networks
!config.hideInactiveNetworks() ||
it.networkConnectionState == INetwork.ConnectionState.Initialized
}.filter {
(!config.hideInactiveBuffers()) ||
// If the config is set to hide inactive buffers, only show ones that are
// online or are network status buffers
!config.hideInactiveBuffers() ||
it.bufferStatus != BufferStatus.OFFLINE ||
it.info.type.hasFlag(Buffer_Type.StatusBuffer)
}.filter {
// Only show buffers which fulfill the minimum activity requirement or are
// network status buffers
minimumActivity.toInt() <= it.bufferActivity.toInt() ||
it.info.type.hasFlag(Buffer_Type.StatusBuffer)
}.let {
// If the config is set to sort buffers, they are sorted by matchmode, and
// within of each match mode, by name (case insensitive)
if (config.sortAlphabetically())
it.sortedBy { IrcCaseMappers.unicode.toLowerCaseNullable(it.info.bufferName) }
.sortedBy { it.matchMode.priority }
.sortedByDescending { it.hiddenState == BufferHiddenState.VISIBLE }
else it
}.distinctBy {
}.sortedBy { props ->
!props.info.type.hasFlag(Buffer_Type.StatusBuffer)
}.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { props ->
props.network.networkName
}).distinctBy {
it.info.bufferId
}.toList()
)
}
}.map {
Pair<BufferViewConfig?, List<BufferProps>>(config, it)
}
}
}
......@@ -421,6 +424,10 @@ open class QuasselViewModelHelper @Inject constructor(
}
}
/**
* Prepares a buffer list for display by configuring the current expansion and selection state as
* well as UI elements
*/
fun filterBufferList(
buffers: Observable<Pair<BufferViewConfig?, List<BufferProps>>>,
expandedNetworks: Observable<Map<NetworkId, Boolean>>,
......@@ -433,12 +440,7 @@ open class QuasselViewModelHelper @Inject constructor(
selected
).map { (info, expandedNetworks, selected) ->
val (config, list) = info ?: Pair(null, emptyList())
val minimumActivity = config?.minimumActivity() ?: Buffer_Activity.NONE
list.asSequence().sortedBy { props ->
!props.info.type.hasFlag(Buffer_Type.StatusBuffer)
}.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { props ->
props.network.networkName
}).map { props ->
list.asSequence().map { props ->
BufferListItem(
props,
BufferState(
......@@ -449,31 +451,18 @@ open class QuasselViewModelHelper @Inject constructor(
)
)
}.filter { (props, state) ->
(props.info.type.hasFlag(BufferInfo.Type.StatusBuffer) || state.networkExpanded) &&
(minimumActivity.toInt() <= props.bufferActivity.toInt() ||
props.info.type.hasFlag(Buffer_Type.StatusBuffer))
(props.info.type.hasFlag(BufferInfo.Type.StatusBuffer) || state.networkExpanded)
}.toList()
}
fun processSelectedBuffer(
selectedBufferId: Observable<BufferId>,
bufferViewConfig: Observable<Optional<BufferViewConfig>>
) = combineLatest(connectedSession, selectedBufferId, bufferViewConfig)
.safeSwitchMap { (sessionOptional, buffer, bufferViewConfigOptional) ->
selectedBufferId: Observable<BufferId>
) = combineLatest(connectedSession, selectedBufferId)
.safeSwitchMap { (sessionOptional, buffer) ->
val session = sessionOptional.orNull()
val bufferSyncer = session?.bufferSyncer
val bufferViewConfig = bufferViewConfigOptional.orNull()
if (bufferSyncer != null && bufferViewConfig != null) {
if (bufferSyncer != null) {
session.liveNetworks().safeSwitchMap { networks ->
val hiddenState = when {
bufferViewConfig.removedBuffers().contains(buffer) ->
BufferHiddenState.HIDDEN_PERMANENT
bufferViewConfig.temporarilyRemovedBuffers().contains(buffer) ->
BufferHiddenState.HIDDEN_TEMPORARY
else ->
BufferHiddenState.VISIBLE
}
val info = if (!buffer.isValidId()) networks[NetworkId(-buffer.id)]?.let {
BufferInfo(
bufferId = buffer,
......@@ -490,22 +479,20 @@ open class QuasselViewModelHelper @Inject constructor(
network?.liveConnectionState()?.map {
SelectedBufferItem(
info,
connectionState = it,
hiddenState = hiddenState
connectionState = it
)
} ?: Observable.just(SelectedBufferItem(info, hiddenState = hiddenState))
} ?: Observable.just(SelectedBufferItem(info))
}
Buffer_Type.ChannelBuffer -> {
network?.liveIrcChannel(info.bufferName)?.mapNullable(IrcChannel.NULL) {
SelectedBufferItem(
info,
joined = it != null,
hiddenState = hiddenState
joined = it != null
)
} ?: Observable.just(SelectedBufferItem(info, hiddenState = hiddenState))
} ?: Observable.just(SelectedBufferItem(info))
}
else ->
Observable.just(SelectedBufferItem(info, hiddenState = hiddenState))
Observable.just(SelectedBufferItem(info))
}
} else {
Observable.just(SelectedBufferItem())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment