diff --git a/.idea/other.xml b/.idea/other.xml
new file mode 100644
index 000000000..0d3a1fbb1
--- /dev/null
+++ b/.idea/other.xml
@@ -0,0 +1,263 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/bnyro/translate/ui/components/SearchAppBar.kt b/app/src/main/java/com/bnyro/translate/ui/components/SearchAppBar.kt
index d80fd04e5..18ad3a879 100644
--- a/app/src/main/java/com/bnyro/translate/ui/components/SearchAppBar.kt
+++ b/app/src/main/java/com/bnyro/translate/ui/components/SearchAppBar.kt
@@ -75,7 +75,7 @@ fun SearchAppBar(
Text(title)
},
actions = {
- Crossfade(isSearchViewVisible) {
+ Crossfade(isSearchViewVisible, label = "search-bar-crossfade") {
when (it) {
true -> {
Row(
diff --git a/app/src/main/java/com/bnyro/translate/ui/models/TessModel.kt b/app/src/main/java/com/bnyro/translate/ui/models/TessModel.kt
new file mode 100644
index 000000000..0385921c0
--- /dev/null
+++ b/app/src/main/java/com/bnyro/translate/ui/models/TessModel.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 You Apps
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.bnyro.translate.ui.models
+
+import android.content.Context
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.bnyro.translate.obj.TessLanguage
+import com.bnyro.translate.util.TessHelper
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class TessModel: ViewModel() {
+ var availableLanguages by mutableStateOf(emptyList())
+ var downloadedLanguages by mutableStateOf(emptyList())
+ var notYetDownloadedLanguages by mutableStateOf(emptyList())
+
+ fun init(context: Context) {
+ downloadedLanguages = TessHelper.getDownloadedLanguages(context)
+
+ viewModelScope.launch(Dispatchers.IO) {
+ availableLanguages = TessHelper.getAvailableLanguages()
+ }
+ }
+
+ fun refreshDownloadedLanguages(context: Context) {
+ downloadedLanguages = TessHelper.getDownloadedLanguages(context)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bnyro/translate/ui/views/TessSettings.kt b/app/src/main/java/com/bnyro/translate/ui/views/TessSettings.kt
index 1fade8e90..434aa4abc 100644
--- a/app/src/main/java/com/bnyro/translate/ui/views/TessSettings.kt
+++ b/app/src/main/java/com/bnyro/translate/ui/views/TessSettings.kt
@@ -40,9 +40,8 @@ import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Download
import androidx.compose.material3.CircularProgressIndicator
-import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.LargeTopAppBar
+import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
@@ -59,15 +58,17 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.viewmodel.compose.viewModel
import com.bnyro.translate.R
import com.bnyro.translate.obj.TessLanguage
import com.bnyro.translate.ui.components.DialogButton
+import com.bnyro.translate.ui.components.SearchAppBar
import com.bnyro.translate.ui.components.StyledIconButton
import com.bnyro.translate.ui.dialogs.FullscreenDialog
+import com.bnyro.translate.ui.models.TessModel
import com.bnyro.translate.util.Preferences
import com.bnyro.translate.util.TessHelper
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -75,53 +76,77 @@ fun TessSettings(
onDismissRequest: () -> Unit
) {
val context = LocalContext.current
+ val tessModel: TessModel = viewModel()
+ val topAppBarBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
- var availableLanguages by remember {
- mutableStateOf(emptyList())
- }
-
- var downloadedLanguages by remember {
- mutableStateOf(TessHelper.getDownloadedLanguages(context))
+ var query by remember {
+ mutableStateOf("")
}
var selectedLanguage by remember {
mutableStateOf(Preferences.get(Preferences.tessLanguageKey, ""))
}
+ LaunchedEffect(Unit) {
+ tessModel.init(context)
+ }
+
+ var filteredDownloadedLanguages by remember {
+ mutableStateOf(emptyList())
+ }
+ var filteredAvailableLanguages by remember {
+ mutableStateOf(emptyList())
+ }
+
+ LaunchedEffect(query, tessModel.availableLanguages, tessModel.downloadedLanguages) {
+ val lowerQuery = query.lowercase()
+
+ filteredAvailableLanguages = tessModel.availableLanguages.filter { tessLang ->
+ tessLang.path.replace(TessHelper.DATA_FILE_SUFFIX, "").contains(lowerQuery) &&
+ tessModel.downloadedLanguages.none {
+ tessLang.path.replace(TessHelper.DATA_FILE_SUFFIX, "") == it
+ }
+ }
+
+ filteredDownloadedLanguages = tessModel.downloadedLanguages.filter { lang ->
+ lowerQuery.contains(lang)
+ }
+ }
+
val onDownloadComplete = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Refresh the downloaded languages every time a download finishes
- downloadedLanguages = TessHelper.getDownloadedLanguages(context)
+ tessModel.refreshDownloadedLanguages(context)
}
}
DisposableEffect(Unit) {
- context.registerReceiver(
+ ContextCompat.registerReceiver(
+ context,
onDownloadComplete,
- IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
+ IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
+ ContextCompat.RECEIVER_EXPORTED
)
onDispose {
context.unregisterReceiver(onDownloadComplete)
}
}
- LaunchedEffect(Unit) {
- availableLanguages = withContext(Dispatchers.IO) {
- TessHelper.getAvailableLanguages()
- }
- }
-
- val topAppBarBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
-
FullscreenDialog(
onDismissRequest = onDismissRequest,
topBar = {
- LargeTopAppBar(
- title = { Text(stringResource(R.string.image_translation)) },
+ SearchAppBar(
+ title = stringResource(R.string.image_translation),
+ value = query,
+ onValueChange = { query = it },
scrollBehavior = topAppBarBehavior,
navigationIcon = {
- StyledIconButton(imageVector = Icons.Default.ArrowBack, onClick = onDismissRequest)
- }
+ StyledIconButton(
+ imageVector = Icons.Default.ArrowBack,
+ onClick = onDismissRequest
+ )
+ },
+ actions = {}
)
},
content = {
@@ -130,19 +155,22 @@ fun TessSettings(
.fillMaxWidth()
.nestedScroll(topAppBarBehavior.nestedScrollConnection)
) {
- SelectionContainer(
- modifier = Modifier.padding(horizontal = 12.dp)
- ) {
- Text(text = stringResource(R.string.tess_summary, TessHelper.tessRepoUrl))
- }
- Spacer(modifier = Modifier.height(12.dp))
-
- // downloaded languages
LazyColumn(
modifier = Modifier
.fillMaxWidth()
+ .weight(1f),
+ horizontalAlignment = Alignment.CenterHorizontally
) {
- items(downloadedLanguages) {
+ item {
+ SelectionContainer(
+ modifier = Modifier.padding(horizontal = 12.dp)
+ ) {
+ Text(text = stringResource(R.string.tess_summary, TessHelper.tessRepoUrl))
+ }
+ Spacer(modifier = Modifier.height(12.dp))
+ }
+
+ items(filteredDownloadedLanguages) {
TessSettingsRow(
packName = "$it${TessHelper.DATA_FILE_SUFFIX}",
size = null,
@@ -151,7 +179,7 @@ fun TessSettings(
) {
StyledIconButton(imageVector = Icons.Default.Delete) {
if (TessHelper.deleteLanguage(context, it)) {
- downloadedLanguages = TessHelper.getDownloadedLanguages(context)
+ tessModel.refreshDownloadedLanguages(context)
} else {
Toast.makeText(
context,
@@ -162,27 +190,18 @@ fun TessSettings(
}
}
}
- }
- Divider(
- color = MaterialTheme.colorScheme.onSurface,
- modifier = Modifier
- .align(Alignment.CenterHorizontally)
- .padding(10.dp)
- .size(70.dp, 1.dp)
- )
- // not yet downloaded languages
- LazyColumn(
- modifier = Modifier
- .fillMaxWidth()
- .weight(1f)
- ) {
- val notYetDownloadedLanguages = availableLanguages.filter { tessLang ->
- downloadedLanguages.none {
- tessLang.path.replace(TessHelper.DATA_FILE_SUFFIX, "") == it
- }
+
+ item {
+ HorizontalDivider(
+ color = MaterialTheme.colorScheme.onSurface,
+ modifier = Modifier
+ .align(Alignment.CenterHorizontally)
+ .padding(10.dp)
+ .size(70.dp, 1.dp)
+ )
}
- items(notYetDownloadedLanguages) {
+ items(filteredAvailableLanguages) {
TessSettingsRow(
packName = it.path,
size = it.size,