Moved amend previous commit to be a checkbox

Fixes #63
This commit is contained in:
Abdelilah El Aissaoui 2023-01-28 15:54:49 +01:00
parent ab50502ca2
commit 96cbdba8d9
3 changed files with 132 additions and 57 deletions

View File

@ -26,6 +26,19 @@ fun Modifier.handMouseClickable(onClick: () -> Unit): Modifier {
.handOnHover() .handOnHover()
} }
fun Modifier.handMouseClickable(
interactionSource: MutableInteractionSource,
indication: Indication?,
onClick: () -> Unit
): Modifier {
return this
.clickable(
interactionSource = interactionSource,
indication = indication,
) { onClick() }
.handOnHover()
}
/** /**
* Ignore keyboard events of that components. * Ignore keyboard events of that components.
* Specially useful for clickable components that may get focused and become clickable when pressing ENTER. * Specially useful for clickable components that may get focused and become clickable when pressing ENTER.

View File

@ -59,6 +59,7 @@ fun UncommitedChanges(
var commitMessage by remember(statusViewModel) { mutableStateOf(statusViewModel.savedCommitMessage.message) } var commitMessage by remember(statusViewModel) { mutableStateOf(statusViewModel.savedCommitMessage.message) }
val stagedListState by statusViewModel.stagedLazyListState.collectAsState() val stagedListState by statusViewModel.stagedLazyListState.collectAsState()
val unstagedListState by statusViewModel.unstagedLazyListState.collectAsState() val unstagedListState by statusViewModel.unstagedLazyListState.collectAsState()
val isAmend by statusViewModel.isAmend.collectAsState()
val stageStatus = stageStatusState.value val stageStatus = stageStatusState.value
val staged: List<StatusEntry> val staged: List<StatusEntry>
@ -75,16 +76,16 @@ fun UncommitedChanges(
isLoading = true isLoading = true
} }
val doCommit = { amend: Boolean -> val doCommit = {
statusViewModel.commit(commitMessage, amend) statusViewModel.commit(commitMessage)
onStagedDiffEntrySelected(null) onStagedDiffEntrySelected(null)
commitMessage = "" commitMessage = ""
} }
val canCommit = commitMessage.isNotEmpty() && staged.isNotEmpty() val canCommit = commitMessage.isNotEmpty() && staged.isNotEmpty()
val canAmend = (commitMessage.isNotEmpty() || staged.isNotEmpty()) && statusViewModel.hasPreviousCommits val canAmend = commitMessage.isNotEmpty() && statusViewModel.hasPreviousCommits
LaunchedEffect(Unit) { LaunchedEffect(statusViewModel) {
statusViewModel.commitMessageChangesFlow.collect { newCommitMessage -> statusViewModel.commitMessageChangesFlow.collect { newCommitMessage ->
commitMessage = newCommitMessage commitMessage = newCommitMessage
} }
@ -179,7 +180,7 @@ fun UncommitedChanges(
.weight(weight = 1f, fill = true) .weight(weight = 1f, fill = true)
.onPreviewKeyEvent { keyEvent -> .onPreviewKeyEvent { keyEvent ->
if (keyEvent.matchesBinding(KeybindingOption.TEXT_ACCEPT) && canCommit) { if (keyEvent.matchesBinding(KeybindingOption.TEXT_ACCEPT) && canCommit) {
doCommit(false) doCommit()
true true
} else } else
false false
@ -215,7 +216,7 @@ fun UncommitedChanges(
statusViewModel.resetRepoState() statusViewModel.resetRepoState()
statusViewModel.updateCommitMessage("") statusViewModel.updateCommitMessage("")
}, },
onMerge = { doCommit(false) } onMerge = { doCommit() }
) )
repositoryState.isRebasing -> RebasingButtons( repositoryState.isRebasing -> RebasingButtons(
@ -236,7 +237,7 @@ fun UncommitedChanges(
statusViewModel.updateCommitMessage("") statusViewModel.updateCommitMessage("")
}, },
onCommit = { onCommit = {
doCommit(false) doCommit()
} }
) )
@ -248,14 +249,18 @@ fun UncommitedChanges(
statusViewModel.updateCommitMessage("") statusViewModel.updateCommitMessage("")
}, },
onCommit = { onCommit = {
doCommit(false) doCommit()
} }
) )
else -> UncommitedChangesButtons( else -> UncommitedChangesButtons(
canCommit = canCommit, canCommit = canCommit,
canAmend = canAmend, canAmend = canAmend,
onCommit = { amend -> doCommit(amend) }, isAmend = isAmend,
onAmendChecked = { isAmend ->
statusViewModel.amend(isAmend)
},
onCommit = { doCommit() },
) )
} }
} }
@ -267,32 +272,67 @@ fun UncommitedChanges(
fun UncommitedChangesButtons( fun UncommitedChangesButtons(
canCommit: Boolean, canCommit: Boolean,
canAmend: Boolean, canAmend: Boolean,
onCommit: (Boolean) -> Unit isAmend: Boolean,
onAmendChecked: (Boolean) -> Unit,
onCommit: () -> Unit
) { ) {
var showDropDownMenu by remember { mutableStateOf(false) } var showDropDownMenu by remember { mutableStateOf(false) }
val buttonText = if (isAmend)
"Amend"
else
"Commit"
Column {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.handMouseClickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
) {
onAmendChecked(!isAmend)
}
) {
Checkbox(
checked = isAmend,
onCheckedChange = {
onAmendChecked(!isAmend)
},
modifier = Modifier
.padding(all = 8.dp)
.size(12.dp)
)
Text(
"Amend previous commit",
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onBackground,
)
}
Row( Row(
modifier = Modifier modifier = Modifier
.padding(top = 2.dp) .padding(top = 2.dp)
) { ) {
ConfirmationButton( ConfirmationButton(
text = "Commit", text = buttonText,
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.height(40.dp), .height(36.dp),
onClick = { onCommit(false) }, onClick = {
enabled = canCommit, onCommit()
},
enabled = canCommit || (canAmend && isAmend),
shape = MaterialTheme.shapes.small.copy(topEnd = CornerSize(0.dp), bottomEnd = CornerSize(0.dp)) shape = MaterialTheme.shapes.small.copy(topEnd = CornerSize(0.dp), bottomEnd = CornerSize(0.dp))
) )
Spacer( Spacer(
modifier = Modifier modifier = Modifier
.width(1.dp) .width(1.dp)
.height(40.dp), .height(36.dp),
) )
Box( Box(
modifier = Modifier modifier = Modifier
.height(40.dp) .height(36.dp)
.clip(MaterialTheme.shapes.small.copy(topStart = CornerSize(0.dp), bottomStart = CornerSize(0.dp))) .clip(MaterialTheme.shapes.small.copy(topStart = CornerSize(0.dp), bottomStart = CornerSize(0.dp)))
.background(MaterialTheme.colors.primary) .background(MaterialTheme.colors.primary)
.handMouseClickable { showDropDownMenu = true } .handMouseClickable { showDropDownMenu = true }
@ -310,20 +350,21 @@ fun UncommitedChangesButtons(
showDropDownMenu = false showDropDownMenu = false
}, },
content = { content = {
DropDownContent( /*DropDownContent(
enabled = canAmend, enabled = canAmend,
dropDownContentData = DropDownContentData( dropDownContentData = DropDownContentData(
label = "Amend previous commit", label = "Amend previous commit",
icon = null, icon = null,
onClick = { onCommit(true) } onClick = onCommit
), ),
onDismiss = { showDropDownMenu = false } onDismiss = { showDropDownMenu = false }
) )*/
}, },
expanded = showDropDownMenu, expanded = showDropDownMenu,
) )
} }
} }
}
} }
@Composable @Composable

View File

@ -66,6 +66,9 @@ class StatusViewModel @Inject constructor(
private val _commitMessageChangesFlow = MutableSharedFlow<String>() private val _commitMessageChangesFlow = MutableSharedFlow<String>()
val commitMessageChangesFlow: SharedFlow<String> = _commitMessageChangesFlow val commitMessageChangesFlow: SharedFlow<String> = _commitMessageChangesFlow
private val _isAmend = MutableStateFlow(false)
val isAmend: StateFlow<Boolean> = _isAmend
init { init {
tabScope.launch { tabScope.launch {
tabState.refreshFlowFiltered( tabState.refreshFlowFiltered(
@ -191,10 +194,19 @@ class StatusViewModel @Inject constructor(
private suspend fun loadHasUncommitedChanges(git: Git) = withContext(Dispatchers.IO) { private suspend fun loadHasUncommitedChanges(git: Git) = withContext(Dispatchers.IO) {
lastUncommitedChangesState = checkHasUncommitedChangedUseCase(git) lastUncommitedChangesState = checkHasUncommitedChangedUseCase(git)
} }
fun amend(isAmend: Boolean) {
_isAmend.value = isAmend
fun commit(message: String, amend: Boolean) = tabState.safeProcessing( if (isAmend && savedCommitMessage.message.isEmpty()) {
takeMessageFromPreviousCommit()
}
}
fun commit(message: String) = tabState.safeProcessing(
refreshType = RefreshType.ALL_DATA, refreshType = RefreshType.ALL_DATA,
) { git -> ) { git ->
val amend = isAmend.value
val commitMessage = if (amend && message.isBlank()) { val commitMessage = if (amend && message.isBlank()) {
getLastCommitMessageUseCase(git) getLastCommitMessageUseCase(git)
} else } else
@ -202,6 +214,7 @@ class StatusViewModel @Inject constructor(
doCommitUseCase(git, commitMessage, amend) doCommitUseCase(git, commitMessage, amend)
updateCommitMessage("") updateCommitMessage("")
_isAmend.value = false
} }
suspend fun refresh(git: Git) = withContext(Dispatchers.IO) { suspend fun refresh(git: Git) = withContext(Dispatchers.IO) {
@ -263,6 +276,14 @@ class StatusViewModel @Inject constructor(
savedCommitMessage = savedCommitMessage.copy(message = message) savedCommitMessage = savedCommitMessage.copy(message = message)
persistMessage() persistMessage()
} }
private fun takeMessageFromPreviousCommit() = tabState.runOperation(
refreshType = RefreshType.NONE,
) { git ->
savedCommitMessage = savedCommitMessage.copy(message = getLastCommitMessageUseCase(git))
persistMessage()
_commitMessageChangesFlow.emit(savedCommitMessage.message)
}
} }
sealed class StageStatus { sealed class StageStatus {