From 3a100f547be4e71b333b6cf766258b5c9b4bc172 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Mon, 6 Jun 2022 14:58:53 +0200 Subject: [PATCH] Added dialog/window closing on pressing ESC Should partially fix: https://github.com/JetpackDuba/Gitnuro/issues/9 --- src/main/kotlin/app/ui/Blame.kt | 28 ++++++++++++++++- src/main/kotlin/app/ui/Diff.kt | 31 ++++++++++++++++--- src/main/kotlin/app/ui/FileHistory.kt | 27 +++++++++++++--- .../kotlin/app/ui/dialogs/AppInfoDialog.kt | 2 +- src/main/kotlin/app/ui/dialogs/CloneDialog.kt | 2 +- .../app/ui/dialogs/EditRemotesDialog.kt | 8 +---- .../kotlin/app/ui/dialogs/MaterialDialog.kt | 30 +++++++++++++++++- src/main/kotlin/app/ui/dialogs/MergeDialog.kt | 2 +- .../kotlin/app/ui/dialogs/NewBranchDialog.kt | 2 +- .../kotlin/app/ui/dialogs/NewTagDialog.kt | 2 +- .../kotlin/app/ui/dialogs/PasswordDialog.kt | 2 +- .../kotlin/app/ui/dialogs/RebaseDialog.kt | 2 +- src/main/kotlin/app/ui/dialogs/ResetDialog.kt | 2 +- .../kotlin/app/ui/dialogs/SettingsDialog.kt | 11 ++++++- .../app/ui/dialogs/UserPasswordDialog.kt | 4 ++- 15 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/app/ui/Blame.kt b/src/main/kotlin/app/ui/Blame.kt index 4edcd0d..fb33580 100644 --- a/src/main/kotlin/app/ui/Blame.kt +++ b/src/main/kotlin/app/ui/Blame.kt @@ -4,6 +4,7 @@ package app.ui import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.selection.DisableSelection import androidx.compose.foundation.text.selection.SelectionContainer @@ -11,10 +12,17 @@ import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.res.painterResource @@ -38,7 +46,25 @@ fun Blame( onSelectCommit: (RevCommit) -> Unit, onClose: () -> Unit, ) { - Column { + + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + + Column( + modifier = Modifier + .focusRequester(focusRequester) + .focusable() + .onPreviewKeyEvent { + if (it.key == Key.Escape) { + onClose() + true + } else + false + }, + ) { Header(filePath, onClose = onClose) SelectionContainer { ScrollableLazyColumn( diff --git a/src/main/kotlin/app/ui/Diff.kt b/src/main/kotlin/app/ui/Diff.kt index 9b08e27..32c802b 100644 --- a/src/main/kotlin/app/ui/Diff.kt +++ b/src/main/kotlin/app/ui/Diff.kt @@ -4,6 +4,7 @@ package app.ui import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items @@ -13,14 +14,17 @@ import androidx.compose.material.IconButton import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.res.loadImageBitmap @@ -59,11 +63,25 @@ fun Diff( ) { val diffResultState = diffViewModel.diffResult.collectAsState() val viewDiffResult = diffResultState.value ?: return + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } Column( modifier = Modifier .background(MaterialTheme.colors.background) .fillMaxSize() + .focusRequester(focusRequester) + .focusable() + .onPreviewKeyEvent { + if (it.key == Key.Escape) { + onCloseDiffView() + true + } else + false + } ) { when (viewDiffResult) { ViewDiffResult.DiffNotFound -> { onCloseDiffView() } @@ -323,7 +341,7 @@ fun DiffHeader( Spacer(modifier = Modifier.weight(1f)) - if(diffEntryType is DiffEntryType.UncommitedDiff) { + if (diffEntryType is DiffEntryType.UncommitedDiff) { val buttonText: String val color: Color @@ -405,7 +423,10 @@ fun DiffLine( } Text( - text = line.text.replace("\t", " "), // TODO this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615 + text = line.text.replace( + "\t", + " " + ), // TODO this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615 modifier = Modifier .padding(start = 8.dp) .fillMaxSize(), diff --git a/src/main/kotlin/app/ui/FileHistory.kt b/src/main/kotlin/app/ui/FileHistory.kt index eb0bdcc..e92a548 100644 --- a/src/main/kotlin/app/ui/FileHistory.kt +++ b/src/main/kotlin/app/ui/FileHistory.kt @@ -4,20 +4,24 @@ package app.ui import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onKeyEvent +import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.res.painterResource @@ -46,9 +50,24 @@ fun FileHistory( ) { val historyState by historyViewModel.historyState.collectAsState() + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + Column( modifier = Modifier .fillMaxSize() + .focusRequester(focusRequester) + .focusable() + .onKeyEvent { + if (it.key == Key.Escape) { + onClose() + true + } else + false + }, ) { Header(filePath = historyState.filePath, onClose = onClose) diff --git a/src/main/kotlin/app/ui/dialogs/AppInfoDialog.kt b/src/main/kotlin/app/ui/dialogs/AppInfoDialog.kt index 9d09d6d..544c8e5 100644 --- a/src/main/kotlin/app/ui/dialogs/AppInfoDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/AppInfoDialog.kt @@ -22,7 +22,7 @@ import app.ui.components.TextLink fun AppInfoDialog( onClose: () -> Unit, ) { - MaterialDialog { + MaterialDialog(onCloseRequested = onClose) { Column( modifier = Modifier .width(600.dp) diff --git a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt index 54a78c6..7643284 100644 --- a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt @@ -35,7 +35,7 @@ fun CloneDialog( val cloneStatus = cloneViewModel.cloneStatus.collectAsState() val cloneStatusValue = cloneStatus.value - MaterialDialog { + MaterialDialog(onCloseRequested = onClose) { Box( modifier = Modifier .width(400.dp) diff --git a/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt b/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt index 2ac7282..d5043a4 100644 --- a/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/EditRemotesDialog.kt @@ -1,11 +1,9 @@ package app.ui.dialogs import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Clear @@ -68,6 +66,7 @@ fun EditRemotesDialog( MaterialDialog( paddingVertical = 8.dp, paddingHorizontal = 16.dp, + onCloseRequested = onDismiss ) { Column( modifier = Modifier @@ -102,11 +101,6 @@ fun EditRemotesDialog( Row( modifier = Modifier .padding(bottom = 8.dp) - .border( - width = 1.dp, - shape = RoundedCornerShape(5.dp), - color = MaterialTheme.colors.borderColor, - ) .background(MaterialTheme.colors.surface) ) { Column( diff --git a/src/main/kotlin/app/ui/dialogs/MaterialDialog.kt b/src/main/kotlin/app/ui/dialogs/MaterialDialog.kt index c471fe4..10220c7 100644 --- a/src/main/kotlin/app/ui/dialogs/MaterialDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/MaterialDialog.kt @@ -1,15 +1,26 @@ +@file:OptIn(ExperimentalComposeUiApi::class) + package app.ui.dialogs import androidx.compose.foundation.background +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.unit.* import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupPositionProvider @@ -20,6 +31,7 @@ fun MaterialDialog( alignment: Alignment = Alignment.Center, paddingHorizontal: Dp = 16.dp, paddingVertical: Dp = 16.dp, + onCloseRequested: () -> Unit = {}, content: @Composable () -> Unit ) { Popup( @@ -33,10 +45,26 @@ fun MaterialDialog( ): IntOffset = IntOffset.Zero } ) { + + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + Box( modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colors.dialogOverlay), + .background(MaterialTheme.colors.dialogOverlay) + .focusRequester(focusRequester) + .focusable() + .onPreviewKeyEvent { + if (it.key == Key.Escape) { + onCloseRequested() + true + } else + false + }, contentAlignment = alignment, ) { Box( diff --git a/src/main/kotlin/app/ui/dialogs/MergeDialog.kt b/src/main/kotlin/app/ui/dialogs/MergeDialog.kt index d8c574a..172eab5 100644 --- a/src/main/kotlin/app/ui/dialogs/MergeDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/MergeDialog.kt @@ -29,7 +29,7 @@ fun MergeDialog( ) { var fastForwardCheck by remember { mutableStateOf(fastForward) } - MaterialDialog { + MaterialDialog(onCloseRequested = onReject) { Column( modifier = Modifier .background(MaterialTheme.colors.background), diff --git a/src/main/kotlin/app/ui/dialogs/NewBranchDialog.kt b/src/main/kotlin/app/ui/dialogs/NewBranchDialog.kt index f5a8c16..1c972e4 100644 --- a/src/main/kotlin/app/ui/dialogs/NewBranchDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/NewBranchDialog.kt @@ -30,7 +30,7 @@ fun NewBranchDialog( val branchFieldFocusRequester = remember { FocusRequester() } val buttonFieldFocusRequester = remember { FocusRequester() } - MaterialDialog { + MaterialDialog(onCloseRequested = onReject) { Column( modifier = Modifier .background(MaterialTheme.colors.background), diff --git a/src/main/kotlin/app/ui/dialogs/NewTagDialog.kt b/src/main/kotlin/app/ui/dialogs/NewTagDialog.kt index c3fdb9d..2d9d562 100644 --- a/src/main/kotlin/app/ui/dialogs/NewTagDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/NewTagDialog.kt @@ -30,7 +30,7 @@ fun NewTagDialog( val tagFieldFocusRequester = remember { FocusRequester() } val buttonFieldFocusRequester = remember { FocusRequester() } - MaterialDialog { + MaterialDialog(onCloseRequested = onReject) { Column( modifier = Modifier .background(MaterialTheme.colors.background), diff --git a/src/main/kotlin/app/ui/dialogs/PasswordDialog.kt b/src/main/kotlin/app/ui/dialogs/PasswordDialog.kt index 7bdbe7e..09c9a7f 100644 --- a/src/main/kotlin/app/ui/dialogs/PasswordDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/PasswordDialog.kt @@ -30,7 +30,7 @@ fun PasswordDialog( val passwordFieldFocusRequester = remember { FocusRequester() } val buttonFieldFocusRequester = remember { FocusRequester() } - MaterialDialog { + MaterialDialog(onCloseRequested = onReject) { Column( modifier = Modifier .background(MaterialTheme.colors.background), diff --git a/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt b/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt index 6799e0e..8cf9fae 100644 --- a/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt @@ -26,7 +26,7 @@ fun RebaseDialog( onReject: () -> Unit, onAccept: () -> Unit ) { - MaterialDialog { + MaterialDialog(onCloseRequested = onReject) { Column( modifier = Modifier .background(MaterialTheme.colors.background), diff --git a/src/main/kotlin/app/ui/dialogs/ResetDialog.kt b/src/main/kotlin/app/ui/dialogs/ResetDialog.kt index 3a7a4c3..ec62f78 100644 --- a/src/main/kotlin/app/ui/dialogs/ResetDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/ResetDialog.kt @@ -27,7 +27,7 @@ fun ResetBranchDialog( ) { var resetType by remember { mutableStateOf(ResetType.MIXED) } - MaterialDialog { + MaterialDialog(onCloseRequested = onReject) { Column( modifier = Modifier .background(MaterialTheme.colors.background), diff --git a/src/main/kotlin/app/ui/dialogs/SettingsDialog.kt b/src/main/kotlin/app/ui/dialogs/SettingsDialog.kt index 7b9e17d..b7b1ad7 100644 --- a/src/main/kotlin/app/ui/dialogs/SettingsDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/SettingsDialog.kt @@ -28,7 +28,16 @@ fun SettingsDialog( val commitsLimitEnabled by appPreferences.commitsLimitEnabledFlow.collectAsState() var commitsLimit by remember { mutableStateOf(appPreferences.commitsLimit) } - MaterialDialog { + MaterialDialog( + onCloseRequested = { + savePendingSettings( + appPreferences = appPreferences, + commitsLimit = commitsLimit, + ) + + onDismiss() + } + ) { Column(modifier = Modifier.width(720.dp)) { Text( text = "Settings", diff --git a/src/main/kotlin/app/ui/dialogs/UserPasswordDialog.kt b/src/main/kotlin/app/ui/dialogs/UserPasswordDialog.kt index 260383e..943663b 100644 --- a/src/main/kotlin/app/ui/dialogs/UserPasswordDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/UserPasswordDialog.kt @@ -35,7 +35,9 @@ fun UserPasswordDialog( val acceptDialog = { onAccept(userField, passwordField) } - MaterialDialog { + MaterialDialog( + onCloseRequested = onReject + ) { Column( modifier = Modifier .background(MaterialTheme.colors.background),