Skip to content

Commit

Permalink
Fixed some issues with dialogs and improved input field code
Browse files Browse the repository at this point in the history
  • Loading branch information
Pururun committed Mar 11, 2024
1 parent e0ec175 commit 6736da9
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 113 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package net.mullvad.mullvadvpn.compose.component

import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.textfield.CustomTextField
import net.mullvad.mullvadvpn.model.CustomListsError

@Composable
fun CustomListNameTextField(
modifier: Modifier = Modifier,
name: String,
isValidName: Boolean,
error: CustomListsError?,
onValueChanged: (String) -> Unit,
onSubmit: (String) -> Unit
) {
val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current
CustomTextField(
value = name,
onValueChanged = onValueChanged,
onSubmit = {
if (isValidName) {
onSubmit(it)
}
},
// This can not be set to KeyboardType.Text because it will show the
// suggestions, this will cause an infinite loop on Android TV with Gboard
keyboardType = KeyboardType.Password,
placeholderText = null,
isValidValue = error == null,
isDigitsOnlyAllowed = false,
supportingText =
error?.let {
{
Text(
text = it.errorString(),
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodySmall
)
}
},
modifier =
modifier.focusRequester(focusRequester).onFocusChanged { focusState ->
if (focusState.hasFocus) {
keyboardController?.show()
}
}
)

LaunchedEffect(Unit) { focusRequester.requestFocus() }
}

@Composable
private fun CustomListsError.errorString() =
stringResource(
when (this) {
CustomListsError.CustomListExists -> R.string.custom_list_error_list_exists
CustomListsError.OtherError -> R.string.error_occurred
}
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.mullvad.mullvadvpn.compose.dialog

import androidx.compose.foundation.layout.Column
import android.util.Log
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
Expand All @@ -11,13 +11,8 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.ramcosta.composedestinations.annotation.Destination
Expand All @@ -27,10 +22,10 @@ import com.ramcosta.composedestinations.spec.DestinationStyle
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
import net.mullvad.mullvadvpn.compose.communication.CustomListResult
import net.mullvad.mullvadvpn.compose.component.CustomListNameTextField
import net.mullvad.mullvadvpn.compose.destinations.CustomListLocationsDestination
import net.mullvad.mullvadvpn.compose.state.CreateCustomListUiState
import net.mullvad.mullvadvpn.compose.test.CREATE_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.compose.textfield.CustomTextField
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.model.CustomListsError
import net.mullvad.mullvadvpn.viewmodel.CreateCustomListDialogSideEffect
Expand Down Expand Up @@ -83,6 +78,7 @@ fun CreateCustomList(
}
}
val state by vm.uiState.collectAsStateWithLifecycle()
Log.d("LOLZ", "CreateCustomList: $state")
CreateCustomListDialog(
state = state,
createCustomList = vm::createCustomList,
Expand All @@ -98,8 +94,7 @@ fun CreateCustomListDialog(
onInputChanged: () -> Unit = {},
onDismiss: () -> Unit = {}
) {
val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current

val name = remember { mutableStateOf("") }
val isValidName by remember { derivedStateOf { name.value.isNotBlank() } }

Expand All @@ -110,43 +105,17 @@ fun CreateCustomListDialog(
)
},
text = {
Column {
CustomTextField(
value = name.value,
onValueChanged = {
name.value = it
onInputChanged()
},
onSubmit = {
if (isValidName) {
createCustomList(it)
}
},
keyboardType = KeyboardType.Text,
placeholderText = "",
isValidValue = state.error == null,
isDigitsOnlyAllowed = false,
supportingText = {
if (state.error != null) {
Text(
text = state.error.errorString(),
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodySmall
)
}
},
modifier =
Modifier.focusRequester(focusRequester)
.onFocusChanged { focusState ->
if (focusState.hasFocus) {
keyboardController?.show()
}
}
.testTag(CREATE_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG)
)
}

LaunchedEffect(Unit) { focusRequester.requestFocus() }
CustomListNameTextField(
name = name.value,
isValidName = isValidName,
error = state.error,
onSubmit = createCustomList,
onValueChanged = {
name.value = it
onInputChanged()
},
modifier = Modifier.testTag(CREATE_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG)
)
},
containerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.onBackground,
Expand All @@ -163,12 +132,3 @@ fun CreateCustomListDialog(
}
)
}

@Composable
private fun CustomListsError.errorString() =
stringResource(
when (this) {
CustomListsError.CustomListExists -> R.string.custom_list_error_list_exists
CustomListsError.OtherError -> R.string.error_occurred
}
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.mullvad.mullvadvpn.compose.dialog

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
Expand All @@ -11,13 +10,8 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.ramcosta.composedestinations.annotation.Destination
Expand All @@ -26,11 +20,10 @@ import com.ramcosta.composedestinations.spec.DestinationStyle
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
import net.mullvad.mullvadvpn.compose.communication.CustomListResult
import net.mullvad.mullvadvpn.compose.component.CustomListNameTextField
import net.mullvad.mullvadvpn.compose.state.UpdateCustomListUiState
import net.mullvad.mullvadvpn.compose.test.EDIT_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.compose.textfield.CustomTextField
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.model.CustomListsError
import net.mullvad.mullvadvpn.viewmodel.EditCustomListNameDialogSideEffect
import net.mullvad.mullvadvpn.viewmodel.EditCustomListNameDialogViewModel
import org.koin.androidx.compose.koinViewModel
Expand Down Expand Up @@ -77,70 +70,35 @@ fun EditCustomListNameDialog(
onInputChanged: () -> Unit = {},
onDismiss: () -> Unit = {}
) {
val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current
val input = remember { mutableStateOf(state.name) }
val isValidName by remember { derivedStateOf { input.value.isNotBlank() } }
val name = remember { mutableStateOf(state.name) }
val isValidName by remember { derivedStateOf { name.value.isNotBlank() } }

AlertDialog(
title = {
Text(
text = stringResource(id = R.string.update_list_name),
)
},
text = {
Column {
CustomTextField(
value = input.value,
onValueChanged = {
input.value = it
onInputChanged()
},
onSubmit = {
if (isValidName) {
updateName(it)
}
},
keyboardType = KeyboardType.Text,
placeholderText = "",
isValidValue = state.error == null,
isDigitsOnlyAllowed = false,
supportingText = {
if (state.error != null) {
Text(
text =
stringResource(
id =
if (state.error == CustomListsError.CustomListExists) {
R.string.custom_list_error_list_exists
} else {
R.string.error_occurred
}
),
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodySmall
)
}
},
modifier =
Modifier.focusRequester(focusRequester)
.onFocusChanged { focusState ->
if (focusState.hasFocus) {
keyboardController?.show()
}
}
.testTag(EDIT_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG)
)
}

LaunchedEffect(Unit) { focusRequester.requestFocus() }
CustomListNameTextField(
name = name.value,
isValidName = isValidName,
error = state.error,
onSubmit = updateName,
onValueChanged = {
name.value = it
onInputChanged()
},
modifier = Modifier.testTag(EDIT_CUSTOM_LIST_DIALOG_INPUT_TEST_TAG)
)
},
containerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.onBackground,
onDismissRequest = onDismiss,
confirmButton = {
PrimaryButton(
text = stringResource(id = R.string.save),
onClick = { updateName(input.value) },
onClick = { updateName(name.value) },
isEnabled = isValidName
)
},
Expand Down

0 comments on commit 6736da9

Please sign in to comment.