- show Git editor file paths instead of the submitted git command - surface follow-up commit message editors during interactive rebase reword - add rename-commit UI tests for editor and amend-message solution paths - add broader embedded level solution scenarios for alternate Git workflows
174 lines
6.7 KiB
Kotlin
174 lines
6.7 KiB
Kotlin
package solutions.tretter.githugandroid
|
|
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.horizontalScroll
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
import androidx.compose.foundation.layout.Box
|
|
import androidx.compose.foundation.layout.Column
|
|
import androidx.compose.foundation.layout.Row
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
import androidx.compose.foundation.layout.heightIn
|
|
import androidx.compose.foundation.layout.imePadding
|
|
import androidx.compose.foundation.layout.padding
|
|
import androidx.compose.foundation.layout.sizeIn
|
|
import androidx.compose.foundation.rememberScrollState
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
import androidx.compose.foundation.text.BasicTextField
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.foundation.verticalScroll
|
|
import androidx.compose.material3.Button
|
|
import androidx.compose.material3.ButtonDefaults
|
|
import androidx.compose.material3.Surface
|
|
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.graphics.SolidColor
|
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
import androidx.compose.ui.platform.testTag
|
|
import androidx.compose.ui.text.TextStyle
|
|
import androidx.compose.ui.text.font.FontFamily
|
|
import androidx.compose.ui.text.font.FontWeight
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.compose.ui.unit.sp
|
|
import androidx.compose.ui.window.Dialog
|
|
import androidx.compose.ui.window.DialogProperties
|
|
|
|
data class GitMessageEditorState(
|
|
val invocation: GitEditorInvocation,
|
|
val content: String,
|
|
)
|
|
|
|
@Composable
|
|
fun GitMessageEditorDialog(
|
|
state: GitMessageEditorState,
|
|
onContentChange: (String) -> Unit,
|
|
onClose: () -> Unit,
|
|
onSave: () -> Unit,
|
|
) {
|
|
val horizontalScroll = rememberScrollState()
|
|
val verticalScroll = rememberScrollState()
|
|
val dialogScroll = rememberScrollState()
|
|
val contentFocusRequester = remember { FocusRequester() }
|
|
val keyboardController = LocalSoftwareKeyboardController.current
|
|
|
|
LaunchedEffect(state.invocation.command) {
|
|
runCatching { contentFocusRequester.requestFocus() }
|
|
keyboardController?.show()
|
|
}
|
|
|
|
Dialog(
|
|
onDismissRequest = onClose,
|
|
properties = DialogProperties(usePlatformDefaultWidth = false),
|
|
) {
|
|
Box(
|
|
modifier = Modifier
|
|
.fillMaxSize()
|
|
.imePadding()
|
|
.verticalScroll(dialogScroll)
|
|
.padding(12.dp),
|
|
) {
|
|
Surface(
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.heightIn(min = 360.dp, max = 720.dp),
|
|
color = PanelPrimary,
|
|
shape = RoundedCornerShape(8.dp),
|
|
) {
|
|
Column(
|
|
modifier = Modifier.padding(12.dp),
|
|
verticalArrangement = Arrangement.spacedBy(10.dp),
|
|
) {
|
|
Text(
|
|
text = state.invocation.title,
|
|
modifier = Modifier.testTag("git-message-editor-title"),
|
|
color = TextPrimary,
|
|
fontWeight = FontWeight.Bold,
|
|
fontSize = 20.sp,
|
|
)
|
|
Row(
|
|
modifier = Modifier.fillMaxWidth(),
|
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
|
) {
|
|
EditorButton(
|
|
label = "Save",
|
|
enabled = state.content.isNotBlank(),
|
|
modifier = Modifier.testTag("git-message-editor-save"),
|
|
onClick = onSave,
|
|
)
|
|
EditorButton(
|
|
label = "Dismiss",
|
|
modifier = Modifier.testTag("git-message-editor-dismiss"),
|
|
onClick = onClose,
|
|
)
|
|
}
|
|
Text(
|
|
text = state.invocation.displayPath,
|
|
modifier = Modifier.testTag("git-message-editor-path"),
|
|
color = TextSecondary,
|
|
fontFamily = FontFamily.Monospace,
|
|
fontSize = 13.sp,
|
|
)
|
|
Box(
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.weight(1f)
|
|
.heightIn(min = 260.dp)
|
|
.background(TerminalBackground, RoundedCornerShape(6.dp))
|
|
.padding(10.dp)
|
|
.horizontalScroll(horizontalScroll)
|
|
.verticalScroll(verticalScroll),
|
|
) {
|
|
BasicTextField(
|
|
value = state.content,
|
|
onValueChange = onContentChange,
|
|
modifier = Modifier
|
|
.sizeIn(minWidth = 1200.dp, minHeight = 1200.dp)
|
|
.focusRequester(contentFocusRequester)
|
|
.testTag("git-message-editor-content"),
|
|
textStyle = TextStyle(
|
|
color = TextPrimary,
|
|
fontFamily = FontFamily.Monospace,
|
|
fontSize = 14.sp,
|
|
),
|
|
cursorBrush = SolidColor(Accent),
|
|
keyboardOptions = KeyboardOptions(
|
|
autoCorrect = false,
|
|
keyboardType = KeyboardType.Ascii,
|
|
),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun EditorButton(
|
|
label: String,
|
|
enabled: Boolean = true,
|
|
modifier: Modifier = Modifier,
|
|
onClick: () -> Unit,
|
|
) {
|
|
Button(
|
|
onClick = onClick,
|
|
enabled = enabled,
|
|
modifier = modifier,
|
|
colors = ButtonDefaults.buttonColors(
|
|
containerColor = Accent,
|
|
contentColor = AppBackground,
|
|
disabledContainerColor = PanelTertiary,
|
|
disabledContentColor = TextMuted,
|
|
),
|
|
) {
|
|
Text(label)
|
|
}
|
|
}
|