Changed clone dialog design and improved text field behavior with long text

This commit is contained in:
Abdelilah El Aissaoui 2022-09-03 18:30:26 +02:00
parent 7148e59eeb
commit d2608f8f60
6 changed files with 89 additions and 43 deletions

View file

@ -15,6 +15,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusProperties
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
@ -28,11 +31,13 @@ fun AdjustableOutlinedTextField(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
enabled: Boolean = true, enabled: Boolean = true,
isError: Boolean = false, isError: Boolean = false,
singleLine: Boolean = false,
colors: TextFieldColors = outlinedTextFieldColors(), colors: TextFieldColors = outlinedTextFieldColors(),
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
textStyle: TextStyle = LocalTextStyle.current.copy(fontSize = MaterialTheme.typography.body1.fontSize), textStyle: TextStyle = LocalTextStyle.current.copy(fontSize = MaterialTheme.typography.body1.fontSize),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = RoundedCornerShape(4.dp),
) { ) {
val textColor = textStyle.color.takeOrElse { val textColor = textStyle.color.takeOrElse {
colors.textColor(enabled).value colors.textColor(enabled).value
@ -51,13 +56,14 @@ fun AdjustableOutlinedTextField(
interactionSource = interactionSource, interactionSource = interactionSource,
keyboardOptions = keyboardOptions, keyboardOptions = keyboardOptions,
cursorBrush = SolidColor(cursorColor), cursorBrush = SolidColor(cursorColor),
singleLine = singleLine,
decorationBox = { innerTextField -> decorationBox = { innerTextField ->
Box( Box(
modifier = Modifier modifier = Modifier
.border( .border(
width = 1.dp, width = 1.dp,
color = indicatorColor, color = indicatorColor,
shape = RoundedCornerShape(4.dp) shape = shape
) )
.padding(12.dp), .padding(12.dp),
contentAlignment = Alignment.CenterStart, contentAlignment = Alignment.CenterStart,

View file

@ -155,7 +155,7 @@ private fun TextInput(
enabled = enabled, enabled = enabled,
onValueChange = onValueChange, onValueChange = onValueChange,
colors = outlinedTextFieldColors(), colors = outlinedTextFieldColors(),
maxLines = 1, singleLine = true,
) )
} }
} }

View file

@ -12,14 +12,17 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusProperties
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.git.CloneStatus import app.git.CloneStatus
import app.theme.outlinedTextFieldColors import app.theme.outlinedTextFieldColors
import app.theme.primaryTextColor import app.theme.primaryTextColor
import app.theme.textButtonColors import app.theme.textButtonColors
import app.ui.components.AdjustableOutlinedTextField
import app.ui.components.PrimaryButton import app.ui.components.PrimaryButton
import app.ui.openDirectoryDialog import app.ui.openDirectoryDialog
import app.viewmodels.CloneViewModel import app.viewmodels.CloneViewModel
@ -37,7 +40,8 @@ fun CloneDialog(
MaterialDialog(onCloseRequested = onClose) { MaterialDialog(onCloseRequested = onClose) {
Box( Box(
modifier = Modifier modifier = Modifier
.width(400.dp) .width(720.dp)
.heightIn(min = 200.dp)
.animateContentSize() .animateContentSize()
) { ) {
when (cloneStatusValue) { when (cloneStatusValue) {
@ -46,7 +50,7 @@ fun CloneDialog(
} }
is CloneStatus.Cancelling -> { is CloneStatus.Cancelling -> {
onClose() // onClose()
} }
is CloneStatus.Completed -> { is CloneStatus.Completed -> {
@ -90,29 +94,24 @@ private fun CloneInput(
Column( Column(
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
.padding(horizontal = 8.dp)
) { ) {
Text( Text(
"Clone a new repository", "Clone a new repository",
color = MaterialTheme.colors.primaryTextColor, style = MaterialTheme.typography.h3,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 4.dp, horizontal = 8.dp) .padding(vertical = 4.dp)
) )
OutlinedTextField( TextInput(
modifier = Modifier title = "URL",
.fillMaxWidth()
.padding(vertical = 4.dp, horizontal = 8.dp)
.focusRequester(urlFocusRequester)
.focusProperties {
previous = cancelButtonFocusRequester
next = directoryFocusRequester
},
label = { Text("URL") },
textStyle = MaterialTheme.typography.body1,
maxLines = 1,
value = url, value = url,
colors = outlinedTextFieldColors(), focusRequester = urlFocusRequester,
focusProperties = {
previous = cancelButtonFocusRequester
next = directoryFocusRequester
},
onValueChange = { onValueChange = {
cloneViewModel.resetStateIfError() cloneViewModel.resetStateIfError()
url = it url = it
@ -122,37 +121,35 @@ private fun CloneInput(
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth(),
.padding(vertical = 4.dp, horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
OutlinedTextField(
modifier = Modifier TextInput(
.weight(1f) modifier = Modifier.weight(1f),
.padding(end = 4.dp) title = "Directory",
.focusRequester(directoryFocusRequester)
.focusProperties {
previous = urlFocusRequester
next = directoryButtonFocusRequester
},
textStyle = MaterialTheme.typography.body1,
maxLines = 1,
label = { Text("Directory") },
value = directory, value = directory,
colors = outlinedTextFieldColors(), focusRequester = directoryButtonFocusRequester,
focusProperties = {
previous = urlFocusRequester
next = directoryButtonFocusRequester
},
onValueChange = { onValueChange = {
cloneViewModel.resetStateIfError() cloneViewModel.resetStateIfError()
directory = it directory = it
cloneViewModel.directory = directory cloneViewModel.directory = directory
} },
textFieldShape = RoundedCornerShape(topStart = 4.dp, bottomStart = 4.dp)
) )
IconButton( IconButton(
onClick = { onClick = {
cloneViewModel.resetStateIfError() cloneViewModel.resetStateIfError()
val newDirectory = openDirectoryDialog() val newDirectory = openDirectoryDialog()
if (newDirectory != null) if (newDirectory != null) {
directory = newDirectory directory = newDirectory
cloneViewModel.directory = directory
}
}, },
modifier = Modifier modifier = Modifier
.focusRequester(directoryButtonFocusRequester) .focusRequester(directoryButtonFocusRequester)
@ -160,6 +157,9 @@ private fun CloneInput(
previous = directoryFocusRequester previous = directoryFocusRequester
next = cloneButtonFocusRequester next = cloneButtonFocusRequester
} }
.clip(RoundedCornerShape(topEnd = 4.dp, bottomEnd = 4.dp))
.background(MaterialTheme.colors.primary)
.height(44.5.dp) // Height of the AdjustableOutlinedTextField with a single line by default
) { ) {
Icon( Icon(
Icons.Default.Search, Icons.Default.Search,
@ -288,4 +288,43 @@ private fun Cancelling() {
modifier = Modifier.padding(vertical = 16.dp), modifier = Modifier.padding(vertical = 16.dp),
) )
} }
}
@Composable
private fun TextInput(
modifier: Modifier = Modifier,
title: String,
value: String,
enabled: Boolean = true,
focusRequester: FocusRequester,
focusProperties: FocusProperties.() -> Unit,
onValueChange: (String) -> Unit,
textFieldShape: Shape = RoundedCornerShape(4.dp),
) {
Row(
modifier = modifier
.padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = title,
style = MaterialTheme.typography.body1,
modifier = Modifier
.width(100.dp)
.padding(end = 16.dp),
)
AdjustableOutlinedTextField(
value = value,
modifier = Modifier
.weight(1f)
.focusRequester(focusRequester)
.focusProperties(focusProperties),
enabled = enabled,
onValueChange = onValueChange,
colors = outlinedTextFieldColors(),
singleLine = true,
shape = textFieldShape,
)
}
} }

View file

@ -228,7 +228,7 @@ fun EditRemotesDialog(
selectedRemote = newSelectedRemoteConfig selectedRemote = newSelectedRemoteConfig
) )
}, },
maxLines = 1, singleLine = true,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp) .padding(vertical = 8.dp)
@ -248,7 +248,7 @@ fun EditRemotesDialog(
remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig) remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig)
remoteChanged = newSelectedRemoteConfig.haveUrisChanged remoteChanged = newSelectedRemoteConfig.haveUrisChanged
}, },
maxLines = 1, singleLine = true,
colors = outlinedTextFieldColors(), colors = outlinedTextFieldColors(),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -268,7 +268,7 @@ fun EditRemotesDialog(
remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig) remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig)
remoteChanged = newSelectedRemoteConfig.haveUrisChanged remoteChanged = newSelectedRemoteConfig.haveUrisChanged
}, },
maxLines = 1, singleLine = true,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp) .padding(vertical = 8.dp)

View file

@ -432,7 +432,7 @@ fun SettingIntInput(
} }
}, },
colors = outlinedTextFieldColors(), colors = outlinedTextFieldColors(),
maxLines = 1, singleLine = true,
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End), textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End),
) )
} }

View file

@ -5,9 +5,9 @@ import app.git.TabState
import app.git.remote_operations.CloneRepositoryUseCase import app.git.remote_operations.CloneRepositoryUseCase
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
@ -83,9 +83,10 @@ class CloneViewModel @Inject constructor(
directory = "" directory = ""
} }
fun cancelClone() { fun cancelClone() = tabState.safeProcessingWihoutGit {
cloneJob?.cancel()
_cloneStatus.value = CloneStatus.Cancelling _cloneStatus.value = CloneStatus.Cancelling
cloneJob?.cancelAndJoin()
_cloneStatus.value = CloneStatus.None
} }
fun resetStateIfError() { fun resetStateIfError() {