-
Notifications
You must be signed in to change notification settings - Fork 26
/
SourceHomeScreenViewModel.kt
118 lines (104 loc) · 3.88 KB
/
SourceHomeScreenViewModel.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.ui.sources.home
import androidx.compose.ui.text.intl.Locale
import ca.gosyer.jui.core.lang.displayName
import ca.gosyer.jui.data.source.SourceRepositoryImpl
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.CatalogPreferences
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import me.tatarka.inject.annotations.Inject
import org.lighthousegames.logging.logging
class SourceHomeScreenViewModel @Inject constructor(
private val sourceHandler: SourceRepositoryImpl,
catalogPreferences: CatalogPreferences,
contextWrapper: ContextWrapper
) : ViewModel(contextWrapper) {
private val _isLoading = MutableStateFlow(true)
val isLoading = _isLoading.asStateFlow()
private val installedSources = MutableStateFlow(emptyList<Source>())
private val _languages = catalogPreferences.languages().asStateFlow()
val languages = _languages.asStateFlow()
val sources = combine(installedSources, languages) { installedSources, languages ->
val all = MR.strings.all.toPlatformString()
val other = MR.strings.other.toPlatformString()
installedSources
.distinctBy { it.id }
.filter {
it.lang in languages || it.id == Source.LOCAL_SOURCE_ID
}
.groupBy(Source::displayLang)
.mapValues {
it.value.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER, Source::name))
.map(SourceUI::SourceItem)
}
.mapKeys { (key) ->
when (key) {
"all" -> all
"other" -> other
else -> Locale(key).displayName
}
}
.toList()
.sortedWith(
compareBy<Pair<String, *>> { (key) ->
when (key) {
all -> 1
other -> 3
else -> 2
}
}.thenBy(String.CASE_INSENSITIVE_ORDER, Pair<String, *>::first)
)
.flatMap { (key, value) ->
listOf(SourceUI.Header(key)) + value
}
}.stateIn(scope, SharingStarted.Eagerly, emptyList())
val sourceLanguages = installedSources.map { sources ->
sources.map { it.lang }.distinct() - Source.LOCAL_SOURCE_LANG
}.stateIn(scope, SharingStarted.Eagerly, emptyList())
private val _query = MutableStateFlow("")
val query = _query.asStateFlow()
init {
getSources()
}
private fun getSources() {
sourceHandler.getSourceList()
.onEach {
installedSources.value = it
_isLoading.value = false
}
.catch {
log.warn(it) { "Error getting sources" }
_isLoading.value = false
}
.launchIn(scope)
}
fun setEnabledLanguages(langs: Set<String>) {
log.info { langs }
_languages.value = langs
}
fun setQuery(query: String) {
_query.value = query
}
private companion object {
private val log = logging()
}
}
sealed class SourceUI {
data class Header(val header: String) : SourceUI()
data class SourceItem(val source: Source) : SourceUI()
}