diff --git a/src/main/kotlin/app/ui/components/AdjustableOutlinedTextField.kt b/src/main/kotlin/app/ui/components/AdjustableOutlinedTextField.kt index 16b6c99..887491d 100644 --- a/src/main/kotlin/app/ui/components/AdjustableOutlinedTextField.kt +++ b/src/main/kotlin/app/ui/components/AdjustableOutlinedTextField.kt @@ -15,6 +15,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment 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.takeOrElse import androidx.compose.ui.text.TextStyle @@ -28,11 +31,13 @@ fun AdjustableOutlinedTextField( modifier: Modifier = Modifier, enabled: Boolean = true, isError: Boolean = false, + singleLine: Boolean = false, colors: TextFieldColors = outlinedTextFieldColors(), maxLines: Int = Int.MAX_VALUE, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, textStyle: TextStyle = LocalTextStyle.current.copy(fontSize = MaterialTheme.typography.body1.fontSize), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + shape: Shape = RoundedCornerShape(4.dp), ) { val textColor = textStyle.color.takeOrElse { colors.textColor(enabled).value @@ -51,13 +56,14 @@ fun AdjustableOutlinedTextField( interactionSource = interactionSource, keyboardOptions = keyboardOptions, cursorBrush = SolidColor(cursorColor), + singleLine = singleLine, decorationBox = { innerTextField -> Box( modifier = Modifier .border( width = 1.dp, color = indicatorColor, - shape = RoundedCornerShape(4.dp) + shape = shape ) .padding(12.dp), contentAlignment = Alignment.CenterStart, diff --git a/src/main/kotlin/app/ui/dialogs/AuthorDialog.kt b/src/main/kotlin/app/ui/dialogs/AuthorDialog.kt index 64a8c23..7065e3e 100644 --- a/src/main/kotlin/app/ui/dialogs/AuthorDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/AuthorDialog.kt @@ -155,7 +155,7 @@ private fun TextInput( enabled = enabled, onValueChange = onValueChange, colors = outlinedTextFieldColors(), - maxLines = 1, + singleLine = true, ) } } \ No newline at end of file diff --git a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt index 30fcb45..a9f0424 100644 --- a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt @@ -12,14 +12,17 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusProperties import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.dp import app.git.CloneStatus import app.theme.outlinedTextFieldColors import app.theme.primaryTextColor import app.theme.textButtonColors +import app.ui.components.AdjustableOutlinedTextField import app.ui.components.PrimaryButton import app.ui.openDirectoryDialog import app.viewmodels.CloneViewModel @@ -37,7 +40,8 @@ fun CloneDialog( MaterialDialog(onCloseRequested = onClose) { Box( modifier = Modifier - .width(400.dp) + .width(720.dp) + .heightIn(min = 200.dp) .animateContentSize() ) { when (cloneStatusValue) { @@ -46,7 +50,7 @@ fun CloneDialog( } is CloneStatus.Cancelling -> { - onClose() +// onClose() } is CloneStatus.Completed -> { @@ -90,29 +94,24 @@ private fun CloneInput( Column( modifier = Modifier.fillMaxWidth() + .padding(horizontal = 8.dp) ) { Text( "Clone a new repository", - color = MaterialTheme.colors.primaryTextColor, + style = MaterialTheme.typography.h3, modifier = Modifier .fillMaxWidth() - .padding(vertical = 4.dp, horizontal = 8.dp) + .padding(vertical = 4.dp) ) - OutlinedTextField( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp, horizontal = 8.dp) - .focusRequester(urlFocusRequester) - .focusProperties { - previous = cancelButtonFocusRequester - next = directoryFocusRequester - }, - label = { Text("URL") }, - textStyle = MaterialTheme.typography.body1, - maxLines = 1, + TextInput( + title = "URL", value = url, - colors = outlinedTextFieldColors(), + focusRequester = urlFocusRequester, + focusProperties = { + previous = cancelButtonFocusRequester + next = directoryFocusRequester + }, onValueChange = { cloneViewModel.resetStateIfError() url = it @@ -122,37 +121,35 @@ private fun CloneInput( Row( modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp, horizontal = 8.dp), + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { - OutlinedTextField( - modifier = Modifier - .weight(1f) - .padding(end = 4.dp) - .focusRequester(directoryFocusRequester) - .focusProperties { - previous = urlFocusRequester - next = directoryButtonFocusRequester - }, - textStyle = MaterialTheme.typography.body1, - maxLines = 1, - label = { Text("Directory") }, + + TextInput( + modifier = Modifier.weight(1f), + title = "Directory", value = directory, - colors = outlinedTextFieldColors(), + focusRequester = directoryButtonFocusRequester, + focusProperties = { + previous = urlFocusRequester + next = directoryButtonFocusRequester + }, onValueChange = { cloneViewModel.resetStateIfError() directory = it cloneViewModel.directory = directory - } + }, + textFieldShape = RoundedCornerShape(topStart = 4.dp, bottomStart = 4.dp) ) IconButton( onClick = { cloneViewModel.resetStateIfError() val newDirectory = openDirectoryDialog() - if (newDirectory != null) + if (newDirectory != null) { directory = newDirectory + cloneViewModel.directory = directory + } }, modifier = Modifier .focusRequester(directoryButtonFocusRequester) @@ -160,6 +157,9 @@ private fun CloneInput( previous = directoryFocusRequester 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( Icons.Default.Search, @@ -288,4 +288,43 @@ private fun Cancelling() { 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, + ) + } } \ No newline at end of file diff --git a/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt b/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt index beda480..cc8e661 100644 --- a/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt @@ -228,7 +228,7 @@ fun EditRemotesDialog( selectedRemote = newSelectedRemoteConfig ) }, - maxLines = 1, + singleLine = true, modifier = Modifier .fillMaxWidth() .padding(vertical = 8.dp) @@ -248,7 +248,7 @@ fun EditRemotesDialog( remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig) remoteChanged = newSelectedRemoteConfig.haveUrisChanged }, - maxLines = 1, + singleLine = true, colors = outlinedTextFieldColors(), modifier = Modifier .fillMaxWidth() @@ -268,7 +268,7 @@ fun EditRemotesDialog( remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig) remoteChanged = newSelectedRemoteConfig.haveUrisChanged }, - maxLines = 1, + singleLine = true, modifier = Modifier .fillMaxWidth() .padding(vertical = 8.dp) diff --git a/src/main/kotlin/app/ui/dialogs/settings/SettingsDialog.kt b/src/main/kotlin/app/ui/dialogs/settings/SettingsDialog.kt index ed1c52f..e3e1490 100644 --- a/src/main/kotlin/app/ui/dialogs/settings/SettingsDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/settings/SettingsDialog.kt @@ -432,7 +432,7 @@ fun SettingIntInput( } }, colors = outlinedTextFieldColors(), - maxLines = 1, + singleLine = true, textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End), ) } diff --git a/src/main/kotlin/app/viewmodels/CloneViewModel.kt b/src/main/kotlin/app/viewmodels/CloneViewModel.kt index e7ee78b..33f6359 100644 --- a/src/main/kotlin/app/viewmodels/CloneViewModel.kt +++ b/src/main/kotlin/app/viewmodels/CloneViewModel.kt @@ -5,9 +5,9 @@ import app.git.TabState import app.git.remote_operations.CloneRepositoryUseCase import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flowOn import java.io.File import javax.inject.Inject @@ -83,9 +83,10 @@ class CloneViewModel @Inject constructor( directory = "" } - fun cancelClone() { - cloneJob?.cancel() + fun cancelClone() = tabState.safeProcessingWihoutGit { _cloneStatus.value = CloneStatus.Cancelling + cloneJob?.cancelAndJoin() + _cloneStatus.value = CloneStatus.None } fun resetStateIfError() {