mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-08 14:52:13 -04:00
feat: language fragment to jetpack compose
- further decoupled the code, shortened the functions. - fixed all detekt long method errors - removed a lot of redundant code
This commit is contained in:
parent
e6271e9977
commit
1cffeb5eac
@ -18,45 +18,121 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.language
|
package org.kiwix.kiwixmobile.language
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import org.kiwix.kiwixmobile.cachedComponent
|
import org.kiwix.kiwixmobile.cachedComponent
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
||||||
import org.kiwix.kiwixmobile.core.extensions.viewModel
|
import org.kiwix.kiwixmobile.core.extensions.viewModel
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
|
||||||
|
import org.kiwix.kiwixmobile.language.composables.AppBarNavigationIcon
|
||||||
|
import org.kiwix.kiwixmobile.language.composables.AppBarTextField
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.Action
|
import org.kiwix.kiwixmobile.language.viewmodel.Action
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.LanguageViewModel
|
import org.kiwix.kiwixmobile.language.viewmodel.LanguageViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
const val SEARCH_ICON_TESTING_TAG = "search"
|
||||||
|
const val SAVE_ICON_TESTING_TAG = "saveLanguages"
|
||||||
|
const val SEARCH_FIELD_TESTING_TAG = "searchField"
|
||||||
|
|
||||||
class LanguageFragment : BaseFragment() {
|
class LanguageFragment : BaseFragment() {
|
||||||
private val languageViewModel by lazy { viewModel<LanguageViewModel>(viewModelFactory) }
|
private val languageViewModel by lazy { viewModel<LanguageViewModel>(viewModelFactory) }
|
||||||
|
|
||||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||||
|
val activity = requireActivity() as CoreMainActivity
|
||||||
private lateinit var composeView: ComposeView
|
private lateinit var composeView: ComposeView
|
||||||
private val compositeDisposable = CompositeDisposable()
|
private val compositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
override fun inject(baseActivity: BaseActivity) {
|
override fun inject(baseActivity: BaseActivity) {
|
||||||
baseActivity.cachedComponent.inject(this)
|
baseActivity.cachedComponent.inject(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val activity = requireActivity() as CoreMainActivity
|
|
||||||
composeView.setContent {
|
composeView.setContent {
|
||||||
LanguageScreen(
|
var searchText by remember { mutableStateOf("") }
|
||||||
viewModelState = languageViewModel.state,
|
var isSearchActive by remember { mutableStateOf(false) }
|
||||||
onNavigationClick = activity.onBackPressedDispatcher::onBackPressed,
|
|
||||||
selectLanguageItem = { languageViewModel.actions.offer(Action.Select(it)) },
|
fun resetSearchState() {
|
||||||
filterText = { languageViewModel.actions.offer(Action.Filter(it)) },
|
// clears the search text and resets the filter
|
||||||
saveLanguages = { languageViewModel.actions.offer(Action.SaveAll) },
|
searchText = ""
|
||||||
)
|
languageViewModel.actions.offer(Action.Filter(searchText))
|
||||||
|
}
|
||||||
|
|
||||||
|
KiwixTheme {
|
||||||
|
Scaffold(topBar = {
|
||||||
|
KiwixAppBar(
|
||||||
|
titleId = R.string.select_languages,
|
||||||
|
navigationIcon = {
|
||||||
|
AppBarNavigationIcon(
|
||||||
|
isSearchActive = isSearchActive,
|
||||||
|
onClick = {
|
||||||
|
if (isSearchActive) {
|
||||||
|
isSearchActive = false
|
||||||
|
resetSearchState()
|
||||||
|
} else {
|
||||||
|
activity.onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actionMenuItems = appBarActionMenuList(
|
||||||
|
searchText = searchText,
|
||||||
|
isSearchActive = isSearchActive,
|
||||||
|
onSearchClick = {
|
||||||
|
isSearchActive = true
|
||||||
|
},
|
||||||
|
onClearClick = {
|
||||||
|
resetSearchState()
|
||||||
|
},
|
||||||
|
onSaveClick = {
|
||||||
|
languageViewModel.actions.offer(Action.SaveAll)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
searchBar = if (isSearchActive) {
|
||||||
|
{
|
||||||
|
AppBarTextField(
|
||||||
|
value = searchText,
|
||||||
|
onValueChange = {
|
||||||
|
searchText = it
|
||||||
|
languageViewModel.actions.offer(Action.Filter(it))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
LanguageScreen(
|
||||||
|
languageViewModel = languageViewModel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
compositeAdd(activity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun compositeAdd(activity: CoreMainActivity) {
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
languageViewModel.effects.subscribe(
|
languageViewModel.effects.subscribe(
|
||||||
{
|
{
|
||||||
@ -67,6 +143,41 @@ class LanguageFragment : BaseFragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun appBarActionMenuList(
|
||||||
|
searchText: String,
|
||||||
|
isSearchActive: Boolean,
|
||||||
|
onSearchClick: () -> Unit,
|
||||||
|
onClearClick: () -> Unit,
|
||||||
|
onSaveClick: () -> Unit
|
||||||
|
): List<ActionMenuItem> {
|
||||||
|
return listOfNotNull(
|
||||||
|
when {
|
||||||
|
!isSearchActive -> ActionMenuItem(
|
||||||
|
icon = IconItem.Drawable(R.drawable.action_search),
|
||||||
|
contentDescription = R.string.search_label,
|
||||||
|
onClick = onSearchClick,
|
||||||
|
testingTag = SEARCH_ICON_TESTING_TAG
|
||||||
|
)
|
||||||
|
|
||||||
|
searchText.isNotEmpty() -> ActionMenuItem(
|
||||||
|
icon = IconItem.Drawable(R.drawable.ic_clear_white_24dp),
|
||||||
|
contentDescription = R.string.search_label,
|
||||||
|
onClick = onClearClick,
|
||||||
|
testingTag = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> null // Handle the case when both conditions are false
|
||||||
|
},
|
||||||
|
// Second item: always included
|
||||||
|
ActionMenuItem(
|
||||||
|
icon = IconItem.Vector(Icons.Default.Check),
|
||||||
|
contentDescription = R.string.save_languages,
|
||||||
|
onClick = onSaveClick,
|
||||||
|
testingTag = SAVE_ICON_TESTING_TAG
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -18,182 +18,63 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.language
|
package org.kiwix.kiwixmobile.language
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Check
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import org.kiwix.kiwixmobile.core.R
|
|
||||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
|
|
||||||
import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon
|
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
|
||||||
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
|
|
||||||
import org.kiwix.kiwixmobile.language.composables.AppBarTextField
|
|
||||||
import org.kiwix.kiwixmobile.language.composables.LanguageList
|
import org.kiwix.kiwixmobile.language.composables.LanguageList
|
||||||
import org.kiwix.kiwixmobile.language.composables.LanguageListItem.LanguageItem
|
|
||||||
import org.kiwix.kiwixmobile.language.composables.LoadingIndicator
|
import org.kiwix.kiwixmobile.language.composables.LoadingIndicator
|
||||||
|
import org.kiwix.kiwixmobile.language.viewmodel.Action
|
||||||
|
import org.kiwix.kiwixmobile.language.viewmodel.LanguageViewModel
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.State
|
import org.kiwix.kiwixmobile.language.viewmodel.State
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.State.Content
|
import org.kiwix.kiwixmobile.language.viewmodel.State.Content
|
||||||
|
|
||||||
const val SEARCH_ICON_TESTING_TAG = "search"
|
|
||||||
const val SAVE_ICON_TESTING_TAG = "saveLanguages"
|
|
||||||
const val SEARCH_FIELD_TESTING_TAG = "searchField"
|
|
||||||
|
|
||||||
@Suppress("all")
|
|
||||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LanguageScreen(
|
fun LanguageScreen(
|
||||||
viewModelState: MutableLiveData<State>,
|
languageViewModel: LanguageViewModel
|
||||||
selectLanguageItem: (LanguageItem) -> Unit,
|
|
||||||
filterText: (String) -> Unit,
|
|
||||||
onNavigationClick: () -> Unit,
|
|
||||||
saveLanguages: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
val state by viewModelState.observeAsState(State.Loading)
|
val state by languageViewModel.state.observeAsState(State.Loading)
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var searchText by remember { mutableStateOf("") }
|
|
||||||
var isSearchActive by remember { mutableStateOf(false) }
|
|
||||||
var updateListState by remember { mutableStateOf(false) }
|
|
||||||
val listState: LazyListState = rememberLazyListState()
|
val listState: LazyListState = rememberLazyListState()
|
||||||
|
|
||||||
KiwixTheme {
|
Column(modifier = Modifier.fillMaxSize()) {
|
||||||
Scaffold(
|
// spacer to account for top app bar
|
||||||
topBar = {
|
Spacer(modifier = Modifier.height(56.dp))
|
||||||
KiwixAppBar(
|
when (state) {
|
||||||
R.string.select_languages,
|
State.Loading, State.Saving -> {
|
||||||
{
|
LoadingIndicator()
|
||||||
NavigationIcon(
|
}
|
||||||
iconItem = if (isSearchActive) {
|
|
||||||
IconItem.Vector(Icons.AutoMirrored.Filled.ArrowBack)
|
is Content -> {
|
||||||
} else {
|
val viewItem = (state as Content).viewItems
|
||||||
IconItem.Drawable(
|
|
||||||
R.drawable.ic_close_white_24dp
|
LaunchedEffect(viewItem) {
|
||||||
)
|
snapshotFlow(listState::firstVisibleItemIndex)
|
||||||
},
|
.collect {
|
||||||
onClick = {
|
if (listState.firstVisibleItemIndex == 2) {
|
||||||
if (isSearchActive) {
|
listState.animateScrollToItem(0)
|
||||||
isSearchActive = false
|
|
||||||
searchText = ""
|
|
||||||
filterText(searchText)
|
|
||||||
} else {
|
|
||||||
onNavigationClick()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
},
|
|
||||||
listOfNotNull(
|
|
||||||
// First item: conditionally include based on search state
|
|
||||||
when {
|
|
||||||
!isSearchActive -> ActionMenuItem(
|
|
||||||
icon = IconItem.Drawable(R.drawable.action_search),
|
|
||||||
contentDescription = R.string.search_label,
|
|
||||||
onClick = {
|
|
||||||
isSearchActive = true
|
|
||||||
},
|
|
||||||
iconTint = Color.White,
|
|
||||||
isEnabled = true,
|
|
||||||
testingTag = SEARCH_ICON_TESTING_TAG
|
|
||||||
)
|
|
||||||
|
|
||||||
searchText.isNotEmpty() -> ActionMenuItem(
|
|
||||||
icon = IconItem.Drawable(R.drawable.ic_clear_white_24dp),
|
|
||||||
contentDescription = R.string.search_label,
|
|
||||||
onClick = {
|
|
||||||
searchText = ""
|
|
||||||
filterText(searchText)
|
|
||||||
},
|
|
||||||
iconTint = Color.White,
|
|
||||||
isEnabled = true,
|
|
||||||
testingTag = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> null // Handle the case when both conditions are false
|
|
||||||
},
|
|
||||||
// Second item: always included
|
|
||||||
ActionMenuItem(
|
|
||||||
icon = IconItem.Vector(Icons.Default.Check),
|
|
||||||
contentDescription = R.string.save_languages,
|
|
||||||
onClick = {
|
|
||||||
saveLanguages()
|
|
||||||
updateListState = true
|
|
||||||
},
|
|
||||||
iconTint = Color.White,
|
|
||||||
isEnabled = true,
|
|
||||||
testingTag = SAVE_ICON_TESTING_TAG
|
|
||||||
)
|
|
||||||
),
|
|
||||||
searchBar = if (isSearchActive) {
|
|
||||||
{
|
|
||||||
AppBarTextField(
|
|
||||||
value = searchText,
|
|
||||||
onValueChange = {
|
|
||||||
searchText = it
|
|
||||||
filterText(it)
|
|
||||||
},
|
|
||||||
testTag = SEARCH_FIELD_TESTING_TAG,
|
|
||||||
hint = stringResource(R.string.search_label)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
null
|
LanguageList(
|
||||||
|
context = context,
|
||||||
|
listState = listState,
|
||||||
|
viewItem = viewItem,
|
||||||
|
selectLanguageItem = { languageItem ->
|
||||||
|
languageViewModel.actions.offer(Action.Select(languageItem))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.fillMaxSize()) {
|
|
||||||
// spacer to account for top app bar
|
|
||||||
Spacer(modifier = Modifier.height(56.dp))
|
|
||||||
when (state) {
|
|
||||||
State.Loading, State.Saving -> {
|
|
||||||
LoadingIndicator()
|
|
||||||
}
|
|
||||||
|
|
||||||
is Content -> {
|
|
||||||
val viewItem = if (!updateListState) {
|
|
||||||
(state as Content).viewItems
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
LaunchedEffect(viewItem) {
|
|
||||||
snapshotFlow(listState::firstVisibleItemIndex)
|
|
||||||
.collect {
|
|
||||||
if (listState.firstVisibleItemIndex == 2) {
|
|
||||||
listState.animateScrollToItem(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LanguageList(
|
|
||||||
context = context,
|
|
||||||
listState = listState,
|
|
||||||
viewItem = viewItem,
|
|
||||||
selectLanguageItem = {
|
|
||||||
selectLanguageItem(it)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2025 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.language.composables
|
||||||
|
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AppBarNavigationIcon(
|
||||||
|
isSearchActive: Boolean,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
NavigationIcon(
|
||||||
|
iconItem = if (isSearchActive) {
|
||||||
|
IconItem.Vector(Icons.AutoMirrored.Filled.ArrowBack)
|
||||||
|
} else {
|
||||||
|
IconItem.Drawable(
|
||||||
|
R.drawable.ic_close_white_24dp
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = onClick
|
||||||
|
)
|
||||||
|
}
|
@ -29,7 +29,6 @@ import androidx.compose.material3.LocalTextStyle
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.material3.TextFieldDefaults.indicatorLine
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
@ -43,18 +42,18 @@ import androidx.compose.ui.focus.focusRequester
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextRange
|
import androidx.compose.ui.text.TextRange
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.input.VisualTransformation
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
import org.kiwix.kiwixmobile.language.SEARCH_FIELD_TESTING_TAG
|
||||||
|
|
||||||
@Suppress("all")
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AppBarTextField(
|
fun AppBarTextField(
|
||||||
value: String,
|
value: String,
|
||||||
hint: String,
|
|
||||||
testTag: String,
|
|
||||||
onValueChange: (String) -> Unit
|
onValueChange: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val interactionSource = remember(::MutableInteractionSource)
|
val interactionSource = remember(::MutableInteractionSource)
|
||||||
@ -68,29 +67,20 @@ fun AppBarTextField(
|
|||||||
unfocusedContainerColor = Color.Transparent,
|
unfocusedContainerColor = Color.Transparent,
|
||||||
focusedTextColor = Color.White
|
focusedTextColor = Color.White
|
||||||
)
|
)
|
||||||
|
|
||||||
val focusRequester = FocusRequester()
|
val focusRequester = FocusRequester()
|
||||||
SideEffect(focusRequester::requestFocus)
|
SideEffect(focusRequester::requestFocus)
|
||||||
|
|
||||||
var textFieldValue by remember {
|
var textFieldValue by remember {
|
||||||
mutableStateOf(TextFieldValue(value, TextRange(value.length)))
|
mutableStateOf(TextFieldValue(value, TextRange(value.length)))
|
||||||
}
|
}
|
||||||
textFieldValue = textFieldValue.copy(text = value)
|
textFieldValue = textFieldValue.copy(text = value)
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalTextSelectionColors provides LocalTextSelectionColors.current
|
LocalTextSelectionColors provides LocalTextSelectionColors.current
|
||||||
) {
|
) {
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag(testTag)
|
.testTag(SEARCH_FIELD_TESTING_TAG)
|
||||||
.width(200.dp)
|
.width(200.dp)
|
||||||
.padding(start = 20.dp)
|
.padding(start = 20.dp)
|
||||||
.indicatorLine(
|
|
||||||
enabled = true,
|
|
||||||
isError = false,
|
|
||||||
interactionSource = interactionSource,
|
|
||||||
colors = colors
|
|
||||||
)
|
|
||||||
.focusRequester(focusRequester),
|
.focusRequester(focusRequester),
|
||||||
value = textFieldValue,
|
value = textFieldValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@ -110,10 +100,9 @@ fun AppBarTextField(
|
|||||||
singleLine = true,
|
singleLine = true,
|
||||||
visualTransformation = VisualTransformation.None,
|
visualTransformation = VisualTransformation.None,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
isError = false,
|
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
text = hint,
|
text = stringResource(R.string.search_label),
|
||||||
color = Color.LightGray
|
color = Color.LightGray
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user