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,62 +272,98 @@ 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) }
Row( val buttonText = if (isAmend)
modifier = Modifier "Amend"
.padding(top = 2.dp) else
) { "Commit"
ConfirmationButton(
text = "Commit",
modifier = Modifier
.weight(1f)
.height(40.dp),
onClick = { onCommit(false) },
enabled = canCommit,
shape = MaterialTheme.shapes.small.copy(topEnd = CornerSize(0.dp), bottomEnd = CornerSize(0.dp))
)
Spacer(
modifier = Modifier
.width(1.dp)
.height(40.dp),
)
Box( Column {
modifier = Modifier Row(
.height(40.dp) verticalAlignment = Alignment.CenterVertically,
.clip(MaterialTheme.shapes.small.copy(topStart = CornerSize(0.dp), bottomStart = CornerSize(0.dp))) modifier = Modifier.handMouseClickable(
.background(MaterialTheme.colors.primary) interactionSource = remember { MutableInteractionSource() },
.handMouseClickable { showDropDownMenu = true } indication = null,
) {
onAmendChecked(!isAmend)
}
) { ) {
Icon( Checkbox(
Icons.Default.ArrowDropDown, checked = isAmend,
contentDescription = null, onCheckedChange = {
tint = Color.White, onAmendChecked(!isAmend)
},
modifier = Modifier modifier = Modifier
.padding(horizontal = 8.dp) .padding(all = 8.dp)
.align(Alignment.Center), .size(12.dp)
) )
DropdownMenu(
onDismissRequest = { Text(
showDropDownMenu = false "Amend previous commit",
}, style = MaterialTheme.typography.caption,
content = { color = MaterialTheme.colors.onBackground,
DropDownContent(
enabled = canAmend,
dropDownContentData = DropDownContentData(
label = "Amend previous commit",
icon = null,
onClick = { onCommit(true) }
),
onDismiss = { showDropDownMenu = false }
)
},
expanded = showDropDownMenu,
) )
} }
Row(
modifier = Modifier
.padding(top = 2.dp)
) {
ConfirmationButton(
text = buttonText,
modifier = Modifier
.weight(1f)
.height(36.dp),
onClick = {
onCommit()
},
enabled = canCommit || (canAmend && isAmend),
shape = MaterialTheme.shapes.small.copy(topEnd = CornerSize(0.dp), bottomEnd = CornerSize(0.dp))
)
Spacer(
modifier = Modifier
.width(1.dp)
.height(36.dp),
)
Box(
modifier = Modifier
.height(36.dp)
.clip(MaterialTheme.shapes.small.copy(topStart = CornerSize(0.dp), bottomStart = CornerSize(0.dp)))
.background(MaterialTheme.colors.primary)
.handMouseClickable { showDropDownMenu = true }
) {
Icon(
Icons.Default.ArrowDropDown,
contentDescription = null,
tint = Color.White,
modifier = Modifier
.padding(horizontal = 8.dp)
.align(Alignment.Center),
)
DropdownMenu(
onDismissRequest = {
showDropDownMenu = false
},
content = {
/*DropDownContent(
enabled = canAmend,
dropDownContentData = DropDownContentData(
label = "Amend previous commit",
icon = null,
onClick = onCommit
),
onDismiss = { showDropDownMenu = false }
)*/
},
expanded = showDropDownMenu,
)
}
}
} }
} }

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 {