From e8bcf660d94adb70eebe508f6bbf1cc397003494 Mon Sep 17 00:00:00 2001 From: Joe Tretter Date: Tue, 12 May 2026 18:02:39 -0500 Subject: [PATCH] Add git pushing after every commit. Improve hardware keyboard and editor focus handling - Map physical Tab, arrow, and Enter keys to the terminal actions used by the on-screen controls. - Keep focus in the terminal input after command submission. - Focus editor content fields when editor dialogs open. --- AndroidProjectTooling.sh | 1 + app/build.gradle.kts | 4 +- .../githugandroid/GitMessageEditorDialog.kt | 16 +++++- .../tretter/githugandroid/Terminal.kt | 53 +++++++++++++++++-- .../tretter/githugandroid/TextEditorDialog.kt | 18 ++++++- 5 files changed, 83 insertions(+), 9 deletions(-) diff --git a/AndroidProjectTooling.sh b/AndroidProjectTooling.sh index f9e33c2..83e8270 100755 --- a/AndroidProjectTooling.sh +++ b/AndroidProjectTooling.sh @@ -118,6 +118,7 @@ auto_commit_if_needed() { git -C "$PROJECT_DIR" commit -m "Misc Changes" fi : > "$COMMIT_SUMMARY_FILE" + git push } download_if_missing() { diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 59f4e64..3b4f5fa 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -19,8 +19,8 @@ android { applicationId = "solutions.tretter.githugandroid" minSdk = 26 targetSdk = 35 - versionCode = 137 - versionName = "0.1.136" + versionCode = 138 + versionName = "0.1.137" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/solutions/tretter/githugandroid/GitMessageEditorDialog.kt b/app/src/main/java/solutions/tretter/githugandroid/GitMessageEditorDialog.kt index 06fdd7d..021520a 100644 --- a/app/src/main/java/solutions/tretter/githugandroid/GitMessageEditorDialog.kt +++ b/app/src/main/java/solutions/tretter/githugandroid/GitMessageEditorDialog.kt @@ -23,8 +23,13 @@ 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.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight @@ -49,6 +54,13 @@ fun GitMessageEditorDialog( val horizontalScroll = rememberScrollState() val verticalScroll = rememberScrollState() val dialogScroll = rememberScrollState() + val contentFocusRequester = remember { FocusRequester() } + val keyboardController = LocalSoftwareKeyboardController.current + + LaunchedEffect(state.invocation.command) { + contentFocusRequester.requestFocus() + keyboardController?.show() + } Dialog( onDismissRequest = onClose, @@ -104,7 +116,9 @@ fun GitMessageEditorDialog( BasicTextField( value = state.content, onValueChange = onContentChange, - modifier = Modifier.sizeIn(minWidth = 1000.dp, minHeight = 700.dp), + modifier = Modifier + .sizeIn(minWidth = 1000.dp, minHeight = 700.dp) + .focusRequester(contentFocusRequester), textStyle = TextStyle( color = TextPrimary, fontFamily = FontFamily.Monospace, diff --git a/app/src/main/java/solutions/tretter/githugandroid/Terminal.kt b/app/src/main/java/solutions/tretter/githugandroid/Terminal.kt index 99ad2b3..6a204bc 100644 --- a/app/src/main/java/solutions/tretter/githugandroid/Terminal.kt +++ b/app/src/main/java/solutions/tretter/githugandroid/Terminal.kt @@ -41,8 +41,12 @@ import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.layout.boundsInRoot import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent +import androidx.compose.ui.input.key.type import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily @@ -73,7 +77,6 @@ fun TerminalPane( ) { val configuration = LocalConfiguration.current val focusRequester = remember { FocusRequester() } - val focusManager = LocalFocusManager.current val keyboardController = LocalSoftwareKeyboardController.current val outputHorizontalScroll = rememberScrollState() val outputVerticalScroll = rememberScrollState() @@ -86,6 +89,8 @@ fun TerminalPane( LaunchedEffect(inputFieldVersion) { outputHorizontalScroll.scrollTo(0) + focusRequester.requestFocus() + keyboardController?.show() } LaunchedEffect(output.size) { @@ -93,8 +98,6 @@ fun TerminalPane( } fun submitCommand() { - focusManager.clearFocus(force = true) - keyboardController?.hide() onRun() } @@ -184,6 +187,11 @@ fun TerminalPane( keyboardController = keyboardController, onFocused = onInputHintDismiss, onSubmit = { submitCommand() }, + onTab = onTab, + onCursorLeft = onCursorLeft, + onCursorRight = onCursorRight, + onHistoryUp = onHistoryUp, + onHistoryDown = onHistoryDown, ) } } @@ -200,6 +208,11 @@ private fun RowScope.TerminalInputField( keyboardController: androidx.compose.ui.platform.SoftwareKeyboardController?, onFocused: () -> Unit, onSubmit: () -> Unit, + onTab: () -> Unit, + onCursorLeft: () -> Unit, + onCursorRight: () -> Unit, + onHistoryUp: () -> Unit, + onHistoryDown: () -> Unit, ) { key(inputFieldVersion) { BasicTextField( @@ -213,6 +226,38 @@ private fun RowScope.TerminalInputField( onFocused() keyboardController?.show() } + } + .onPreviewKeyEvent { event -> + if (event.type != KeyEventType.KeyDown) { + return@onPreviewKeyEvent false + } + when (event.key) { + Key.Tab -> { + onTab() + true + } + Key.DirectionLeft -> { + onCursorLeft() + true + } + Key.DirectionRight -> { + onCursorRight() + true + } + Key.DirectionUp -> { + onHistoryUp() + true + } + Key.DirectionDown -> { + onHistoryDown() + true + } + Key.Enter -> { + onSubmit() + true + } + else -> false + } }, singleLine = true, textStyle = TextStyle( diff --git a/app/src/main/java/solutions/tretter/githugandroid/TextEditorDialog.kt b/app/src/main/java/solutions/tretter/githugandroid/TextEditorDialog.kt index 395564e..86d6698 100644 --- a/app/src/main/java/solutions/tretter/githugandroid/TextEditorDialog.kt +++ b/app/src/main/java/solutions/tretter/githugandroid/TextEditorDialog.kt @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.widthIn 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 @@ -24,8 +25,13 @@ import androidx.compose.material3.OutlinedTextField 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.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight @@ -35,7 +41,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties -import androidx.compose.foundation.text.KeyboardOptions data class TextEditorState( val editor: String, @@ -56,6 +61,13 @@ fun TextEditorDialog( val editorHorizontalScroll = rememberScrollState() val editorVerticalScroll = rememberScrollState() val dialogScroll = rememberScrollState() + val contentFocusRequester = remember { FocusRequester() } + val keyboardController = LocalSoftwareKeyboardController.current + + LaunchedEffect(state.originalCommand, state.path) { + contentFocusRequester.requestFocus() + keyboardController?.show() + } Dialog( onDismissRequest = onClose, @@ -122,7 +134,9 @@ fun TextEditorDialog( BasicTextField( value = state.content, onValueChange = onContentChange, - modifier = Modifier.sizeIn(minWidth = 1200.dp, minHeight = 1200.dp), + modifier = Modifier + .sizeIn(minWidth = 1200.dp, minHeight = 1200.dp) + .focusRequester(contentFocusRequester), textStyle = TextStyle( color = TextPrimary, fontFamily = FontFamily.Monospace,