Gitnuro/src/main/kotlin/app/ui/RebaseInteractive.kt

187 lines
5.6 KiB
Kotlin

package app.ui.dialogs
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.theme.primaryTextColor
import app.ui.components.PrimaryButton
import app.ui.components.ScrollableLazyColumn
import app.viewmodels.RebaseInteractiveState
import app.viewmodels.RebaseInteractiveViewModel
import org.eclipse.jgit.lib.RebaseTodoLine
import org.eclipse.jgit.lib.RebaseTodoLine.Action
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun RebaseInteractive(
rebaseInteractiveViewModel: RebaseInteractiveViewModel,
) {
val rebaseState = rebaseInteractiveViewModel.rebaseState.collectAsState()
val rebaseStateValue = rebaseState.value
Box(
modifier = Modifier
.background(MaterialTheme.colors.surface)
.fillMaxSize(),
) {
when (rebaseStateValue) {
is RebaseInteractiveState.Failed -> {}
is RebaseInteractiveState.Loaded -> {
RebaseStateLoaded(
rebaseInteractiveViewModel,
rebaseStateValue,
onCancel = {
rebaseInteractiveViewModel.cancel()
},
)
}
RebaseInteractiveState.Loading -> {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}
}
}
@Composable
fun RebaseStateLoaded(
rebaseInteractiveViewModel: RebaseInteractiveViewModel,
rebaseState: RebaseInteractiveState.Loaded,
onCancel: () -> Unit,
) {
Column(
modifier = Modifier.fillMaxSize()
) {
Text(
text = "Rebase interactive",
color = MaterialTheme.colors.primaryTextColor,
modifier = Modifier.padding(all = 20.dp)
)
ScrollableLazyColumn(modifier = Modifier.weight(1f)) {
items(rebaseState.stepsList) { rebaseTodoLine ->
RebaseCommit(
rebaseLine = rebaseTodoLine,
message = rebaseState.messages[rebaseTodoLine.commit.name()],
onActionChanged = { newAction ->
rebaseInteractiveViewModel.onCommitActionChanged(rebaseTodoLine.commit, newAction)
},
onMessageChanged = { newMessage ->
rebaseInteractiveViewModel.onCommitMessageChanged(rebaseTodoLine.commit, newMessage)
},
)
}
}
Row {
Spacer(modifier = Modifier.weight(1f))
TextButton(
modifier = Modifier.padding(end = 8.dp),
onClick = {
onCancel()
}
) {
Text("Cancel")
}
PrimaryButton(
modifier = Modifier.padding(end = 16.dp),
onClick = {
rebaseInteractiveViewModel.continueRebaseInteractive()
},
text = "Complete rebase"
)
}
}
}
@Composable
fun RebaseCommit(
rebaseLine: RebaseTodoLine,
message: String?,
onActionChanged: (Action) -> Unit,
onMessageChanged: (String) -> Unit,
) {
val action = rebaseLine.action
var newMessage by remember(rebaseLine.commit.name(), action) {
if (action == Action.REWORD) {
mutableStateOf(message ?: rebaseLine.shortMessage) /* if reword, use the value from the map (if possible)*/
} else
mutableStateOf(rebaseLine.shortMessage) // If it's not reword, use the original shortMessage
}
Row(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
) {
ActionDropdown(
rebaseLine.action,
onActionChanged = onActionChanged,
)
OutlinedTextField(
modifier = Modifier
.weight(1f)
.heightIn(min = 48.dp),
enabled = rebaseLine.action == Action.REWORD,
value = newMessage,
onValueChange = {
newMessage = it
onMessageChanged(it)
},
colors = TextFieldDefaults.textFieldColors(backgroundColor = MaterialTheme.colors.background),
textStyle = TextStyle.Default.copy(fontSize = 14.sp, color = MaterialTheme.colors.primaryTextColor),
)
}
}
@Composable
fun ActionDropdown(
action: Action,
onActionChanged: (Action) -> Unit,
) {
var showDropDownMenu by remember { mutableStateOf(false) }
Box {
PrimaryButton(
onClick = { showDropDownMenu = true },
modifier = Modifier
.width(120.dp)
.height(48.dp)
.padding(end = 8.dp),
text = action.toToken()
)
DropdownMenu(
expanded = showDropDownMenu,
onDismissRequest = { showDropDownMenu = false },
) {
for (dropDownOption in actions) {
DropdownMenuItem(
onClick = {
showDropDownMenu = false
onActionChanged(dropDownOption)
}
) {
Text(dropDownOption.toToken())
}
}
}
}
}
val actions = listOf(
Action.PICK,
Action.REWORD,
Action.SQUASH,
Action.FIXUP,
)