mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-23 21:12:34 +01:00
Allow configuring extension languages
This commit is contained in:
@@ -8,9 +8,10 @@ package ca.gosyer.data.extension
|
||||
|
||||
import ca.gosyer.common.prefs.Preference
|
||||
import ca.gosyer.common.prefs.PreferenceStore
|
||||
import java.util.Locale
|
||||
|
||||
class ExtensionPreferences(private val preferenceStore: PreferenceStore) {
|
||||
fun languages(): Preference<Set<String>> {
|
||||
return preferenceStore.getStringSet("enabled_langs", setOf("all", "en"))
|
||||
return preferenceStore.getStringSet("enabled_langs", setOf("all", "en", Locale.getDefault().language))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
package ca.gosyer.ui.extensions
|
||||
|
||||
import androidx.compose.foundation.ScrollbarAdapter
|
||||
import androidx.compose.foundation.VerticalScrollbar
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -21,15 +22,20 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.rememberScrollbarAdapter
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Translate
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -41,12 +47,15 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ca.gosyer.BuildConfig
|
||||
import ca.gosyer.data.models.Extension
|
||||
import ca.gosyer.ui.base.WindowDialog
|
||||
import ca.gosyer.ui.base.components.ActionIcon
|
||||
import ca.gosyer.ui.base.components.KtorImage
|
||||
import ca.gosyer.ui.base.components.LoadingScreen
|
||||
import ca.gosyer.ui.base.components.Toolbar
|
||||
import ca.gosyer.ui.base.vm.viewModel
|
||||
import ca.gosyer.util.compose.ThemedWindow
|
||||
import ca.gosyer.util.compose.persistentLazyListState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import java.util.Locale
|
||||
|
||||
fun openExtensionsMenu() {
|
||||
@@ -78,6 +87,18 @@ fun ExtensionsMenu() {
|
||||
searchText = search,
|
||||
search = {
|
||||
vm.search(it)
|
||||
},
|
||||
actions = {
|
||||
ActionIcon(
|
||||
{
|
||||
val enabledLangs = MutableStateFlow(vm.enabledLangs.value)
|
||||
LanguageDialog(enabledLangs, vm.getSourceLanguages().toList()) {
|
||||
vm.setEnabledLanguages(enabledLangs.value)
|
||||
}
|
||||
},
|
||||
"Enabled languages",
|
||||
Icons.Default.Translate
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -154,3 +175,34 @@ fun ExtensionItem(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun LanguageDialog(enabledLangsFlow: MutableStateFlow<Set<String>>, availableLangs: List<String>, setLangs: () -> Unit) {
|
||||
WindowDialog(BuildConfig.NAME, onPositiveButton = setLangs) {
|
||||
val enabledLangs by enabledLangsFlow.collectAsState()
|
||||
val state = rememberLazyListState()
|
||||
Box {
|
||||
LazyColumn(Modifier.fillMaxWidth(), state) {
|
||||
items(availableLangs) { lang ->
|
||||
Row {
|
||||
val langName = remember(lang) {
|
||||
Locale.forLanguageTag(lang)?.displayName ?: lang
|
||||
}
|
||||
Text(langName)
|
||||
Switch(
|
||||
lang in enabledLangs,
|
||||
{
|
||||
if (it) {
|
||||
enabledLangsFlow.value += lang
|
||||
} else {
|
||||
enabledLangsFlow.value -= lang
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
item { Spacer(Modifier.height(70.dp)) }
|
||||
}
|
||||
VerticalScrollbar(ScrollbarAdapter(state), Modifier.align(Alignment.CenterEnd).padding(8.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ import ca.gosyer.util.lang.throwIfCancellation
|
||||
import ca.gosyer.util.system.CKLogger
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -24,6 +27,8 @@ class ExtensionsMenuViewModel @Inject constructor(
|
||||
private val extensionPreferences: ExtensionPreferences
|
||||
) : ViewModel() {
|
||||
val serverUrl = serverPreferences.serverUrl().stateIn(scope)
|
||||
private val _enabledLangs = extensionPreferences.languages().asStateFlow()
|
||||
val enabledLangs = _enabledLangs.asStateFlow()
|
||||
|
||||
private lateinit var extensionList: List<Extension>
|
||||
|
||||
@@ -33,21 +38,22 @@ class ExtensionsMenuViewModel @Inject constructor(
|
||||
private val _isLoading = MutableStateFlow(true)
|
||||
val isLoading = _isLoading.asStateFlow()
|
||||
|
||||
var searchQuery = MutableStateFlow<String?>(null)
|
||||
val searchQuery = MutableStateFlow<String?>(null)
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
getExtensions()
|
||||
}
|
||||
|
||||
enabledLangs.drop(1).onEach {
|
||||
search(searchQuery.value.orEmpty())
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
private suspend fun getExtensions() {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
val enabledLangs = extensionPreferences.languages().get()
|
||||
extensionList = extensionHandler.getExtensionList()
|
||||
.filter { it.lang in enabledLangs }
|
||||
.sortedWith(compareBy({ it.lang }, { it.pkgName }))
|
||||
search(searchQuery.value.orEmpty())
|
||||
} catch (e: Exception) {
|
||||
e.throwIfCancellation()
|
||||
@@ -93,8 +99,16 @@ class ExtensionsMenuViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun getSourceLanguages() = extensionList.map { it.lang }.toSet()
|
||||
|
||||
fun setEnabledLanguages(langs: Set<String>) {
|
||||
info { langs }
|
||||
_enabledLangs.value = langs
|
||||
}
|
||||
|
||||
fun search(searchQuery: String) {
|
||||
this.searchQuery.value = searchQuery.takeUnless { it.isBlank() }
|
||||
val extensionList = extensionList.filter { it.lang in enabledLangs.value }
|
||||
if (searchQuery.isBlank()) {
|
||||
_extensions.value = extensionList.splitSort()
|
||||
} else {
|
||||
@@ -108,10 +122,11 @@ class ExtensionsMenuViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun List<Extension>.splitSort(): List<Extension> {
|
||||
val obsolete = filter { it.obsolete }.sortedWith(compareBy({ it.lang }, { it.pkgName }))
|
||||
val updates = filter { it.hasUpdate }.sortedWith(compareBy({ it.lang }, { it.pkgName }))
|
||||
val installed = filter { it.installed && !it.hasUpdate && !it.obsolete }.sortedWith(compareBy({ it.lang }, { it.pkgName }))
|
||||
val available = filter { !it.installed }.sortedWith(compareBy({ it.lang }, { it.pkgName }))
|
||||
val comparator = compareBy<Extension>({ it.lang }, { it.pkgName })
|
||||
val obsolete = filter { it.obsolete }.sortedWith(comparator)
|
||||
val updates = filter { it.hasUpdate }.sortedWith(comparator)
|
||||
val installed = filter { it.installed && !it.hasUpdate && !it.obsolete }.sortedWith(comparator)
|
||||
val available = filter { !it.installed }.sortedWith(comparator)
|
||||
return obsolete + updates + installed + available
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user