Log full cleanup

- Refactored log function into multiple sub functions
- Removed use of DialogManager from Log
- Merge branch now shows current branch instead of hardcoded "HEAD"
This commit is contained in:
Abdelilah El Aissaoui 2021-12-04 07:02:40 +01:00
parent f9a2917bbd
commit 6c1dc32928
8 changed files with 374 additions and 316 deletions

View File

@ -20,6 +20,15 @@ class BranchesManager @Inject constructor() {
val currentBranch: StateFlow<String>
get() = _currentBranch
suspend fun currentBranchRef(git: Git): Ref? {
val branchList = getBranches(git)
val branchName = git
.repository
.fullBranch
return branchList.firstOrNull { it.name == branchName }
}
suspend fun loadBranches(git: Git) = withContext(Dispatchers.IO) {
val branchList = getBranches(git)
@ -58,7 +67,7 @@ class BranchesManager @Inject constructor() {
}
suspend fun mergeBranch(git: Git, branch: Ref, fastForward: Boolean) = withContext(Dispatchers.IO) {
val fastForwardMode = if(fastForward)
val fastForwardMode = if (fastForward)
MergeCommand.FastForwardMode.FF
else
MergeCommand.FastForwardMode.NO_FF

View File

@ -21,6 +21,7 @@ import javax.inject.Inject
class LogManager @Inject constructor(
private val statusManager: StatusManager,
private val branchesManager: BranchesManager,
) {
private val _logStatus = MutableStateFlow<LogStatus>(LogStatus.Loading)
@ -49,7 +50,7 @@ class LogManager @Inject constructor(
ensureActive()
val loadedStatus = LogStatus.Loaded(commitList)
val loadedStatus = LogStatus.Loaded(commitList, branchesManager.currentBranchRef(git))
_logStatus.value = loadedStatus
}
@ -102,5 +103,5 @@ enum class ResetType {
sealed class LogStatus {
object Loading : LogStatus()
class Loaded(val plotCommitList: GraphCommitList) : LogStatus()
class Loaded(val plotCommitList: GraphCommitList, val currentBranch: Ref?) : LogStatus()
}

View File

@ -4,22 +4,18 @@ import androidx.compose.animation.Crossfade
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.PointerIconDefaults
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.unit.dp
import app.DialogManager
import app.credentials.CredentialsState
import app.git.DiffEntryType
import app.git.GitManager
import app.ui.dialogs.NewBranchDialog
import app.ui.dialogs.PasswordDialog
import app.ui.dialogs.UserPasswordDialog
import app.ui.log.Log
import openRepositoryDialog
import org.eclipse.jgit.revwalk.RevCommit
import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi

View File

@ -27,6 +27,7 @@ fun MergeDialog(
) {
var fastForwardCheck by remember { mutableStateOf(fastForward) }
MaterialDialog {
Column(
modifier = Modifier
.background(MaterialTheme.colors.background),
@ -59,7 +60,7 @@ fun MergeDialog(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.mouseClickable {
if(this.buttons.isPrimaryPressed) {
if (this.buttons.isPrimaryPressed) {
fastForwardCheck = !fastForwardCheck
}
}
@ -100,4 +101,5 @@ fun MergeDialog(
}
}
}
}
}

View File

@ -26,6 +26,7 @@ fun NewTagDialog(
val tagFieldFocusRequester = remember { FocusRequester() }
val buttonFieldFocusRequester = remember { FocusRequester() }
MaterialDialog {
Column(
modifier = Modifier
.background(MaterialTheme.colors.background),
@ -39,7 +40,7 @@ fun NewTagDialog(
}
.width(300.dp)
.onPreviewKeyEvent {
if(it.key == Key.Enter) {
if (it.key == Key.Enter) {
onAccept(tagField)
true
} else {
@ -85,4 +86,5 @@ fun NewTagDialog(
LaunchedEffect(Unit) {
tagFieldFocusRequester.requestFocus()
}
}
}

View File

@ -24,6 +24,7 @@ fun ResetBranchDialog(
) {
var resetType by remember { mutableStateOf(ResetType.MIXED) }
MaterialDialog {
Column(
modifier = Modifier
.background(MaterialTheme.colors.background),
@ -72,6 +73,7 @@ fun ResetBranchDialog(
}
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)

View File

@ -2,7 +2,7 @@
@file:Suppress("UNUSED_PARAMETER")
package app.ui
package app.ui.log
import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.Orientation
@ -32,7 +32,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.DialogManager
import app.extensions.*
import app.git.GitManager
import app.git.LogStatus
@ -46,6 +45,7 @@ import app.ui.dialogs.MergeDialog
import app.ui.dialogs.NewBranchDialog
import app.ui.dialogs.NewTagDialog
import app.ui.dialogs.ResetBranchDialog
import app.ui.rememberNetworkImage
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.revwalk.RevCommit
@ -69,7 +69,6 @@ private const val CANVAS_MIN_WIDTH = 100
@Composable
fun Log(
gitManager: GitManager,
dialogManager: DialogManager,
onRevCommitSelected: (RevCommit) -> Unit,
onUncommitedChangesSelected: () -> Unit,
selectedIndex: MutableState<Int> = remember { mutableStateOf(-1) }
@ -78,11 +77,20 @@ fun Log(
val logStatus = logStatusState.value
val selectedUncommited = remember { mutableStateOf(false) }
val showLogDialog = remember { mutableStateOf<LogDialog>(LogDialog.None) }
if (logStatus is LogStatus.Loaded) {
val commitList = logStatus.plotCommitList
Box(
LogDialogs(
gitManager,
currentBranch = logStatus.currentBranch,
onResetShowLogDialog = { showLogDialog.value = LogDialog.None },
showLogDialog = showLogDialog.value,
)
Column(
modifier = Modifier
.padding(8.dp)
.background(MaterialTheme.colors.background)
@ -95,13 +103,108 @@ fun Log(
if (graphWidth.value < CANVAS_MIN_WIDTH)
graphWidth = CANVAS_MIN_WIDTH.dp
GraphHeader(
graphWidth = graphWidth,
weightMod = weightMod,
)
ScrollableLazyColumn(
modifier = Modifier
.background(MaterialTheme.colors.background)
.fillMaxSize(),
) {
if (hasUncommitedChanges)
item {
UncommitedChangesLine(
selected = selectedUncommited.value,
hasPreviousCommits = commitList.count() > 0,
graphWidth = graphWidth,
weightMod = weightMod,
onUncommitedChangesSelected = {
selectedIndex.value = -1
selectedUncommited.value = true
onUncommitedChangesSelected()
}
)
}
stickyHeader {
itemsIndexed(items = commitList) { index, graphNode ->
CommitLine(
gitManager = gitManager,
graphNode = graphNode,
selected = selectedIndex.value == index,
weightMod = weightMod,
graphWidth = graphWidth,
showCreateNewBranch = { showLogDialog.value = LogDialog.NewBranch(graphNode) },
showCreateNewTag = { showLogDialog.value = LogDialog.NewTag(graphNode) },
resetBranch = { showLogDialog.value = LogDialog.ResetBranch(graphNode) },
onMergeBranch = { ref -> showLogDialog.value = LogDialog.MergeBranch(ref) },
onRevCommitSelected = {
selectedIndex.value = index
selectedUncommited.value = false
onRevCommitSelected(it)
}
)
}
}
}
}
}
@Composable
fun LogDialogs(
gitManager: GitManager,
onResetShowLogDialog: () -> Unit,
showLogDialog: LogDialog,
currentBranch: Ref?,
) {
when(showLogDialog) {
is LogDialog.NewBranch -> {
NewBranchDialog(
onReject = onResetShowLogDialog,
onAccept = { branchName ->
gitManager.createBranchOnCommit(branchName, showLogDialog.graphNode)
onResetShowLogDialog()
}
)
}
is LogDialog.NewTag -> {
NewTagDialog(
onReject = onResetShowLogDialog,
onAccept = { tagName ->
gitManager.createTagOnCommit(tagName, showLogDialog.graphNode)
onResetShowLogDialog()
}
)
}
is LogDialog.MergeBranch -> {
if(currentBranch != null)
MergeDialog(
currentBranchName = currentBranch.simpleName,
mergeBranchName = showLogDialog.ref.simpleName,
onReject = onResetShowLogDialog,
onAccept = { ff ->
gitManager.mergeBranch(showLogDialog.ref, ff)
onResetShowLogDialog()
}
)
}
is LogDialog.ResetBranch -> ResetBranchDialog(
onReject = onResetShowLogDialog,
onAccept = { resetType ->
gitManager.resetToCommit(showLogDialog.graphNode, resetType)
onResetShowLogDialog()
}
)
LogDialog.None -> {}
}
}
@Composable
fun GraphHeader(
graphWidth: Dp,
weightMod: MutableState<Float>,
) {
Row(
modifier = Modifier
.fillMaxWidth()
@ -137,11 +240,17 @@ fun Log(
maxLines = 1,
)
}
}
}
if (hasUncommitedChanges)
item {
val textColor = if (selectedUncommited.value) {
@Composable
fun UncommitedChangesLine(
selected: Boolean,
hasPreviousCommits: Boolean,
graphWidth: Dp,
weightMod: MutableState<Float>,
onUncommitedChangesSelected: () -> Unit
) {
val textColor = if (selected) {
MaterialTheme.colors.primary
} else
MaterialTheme.colors.primaryTextColor
@ -151,13 +260,9 @@ fun Log(
.height(40.dp)
.fillMaxWidth()
.clickable {
selectedIndex.value = -1
selectedUncommited.value = true
onUncommitedChangesSelected()
},
) {
val hasPreviousCommits = commitList.count() > 0
UncommitedChangesGraphLine(
modifier = Modifier
.width(graphWidth),
@ -191,51 +296,22 @@ fun Log(
Spacer(modifier = Modifier.weight(2f))
}
}
}
itemsIndexed(items = commitList) { index, graphNode ->
CommitLine(
gitManager = gitManager,
dialogManager = dialogManager,
graphNode = graphNode,
selected = selectedIndex.value == index,
weightMod = weightMod,
graphWidth = graphWidth,
onRevCommitSelected = {
selectedIndex.value = index
selectedUncommited.value = false
onRevCommitSelected(it)
}
)
}
}
}
}
}
@Composable
fun CommitLine(
gitManager: GitManager,
dialogManager: DialogManager,
graphNode: GraphNode,
selected: Boolean,
weightMod: MutableState<Float>,
graphWidth: Dp,
showCreateNewBranch: () -> Unit,
showCreateNewTag: () -> Unit,
resetBranch: (GraphNode) -> Unit,
onMergeBranch: (Ref) -> Unit,
onRevCommitSelected: (GraphNode) -> Unit,
) {
val commitRefs = graphNode.refs
var showCreateBranchDialog by remember(graphNode.id.name) { mutableStateOf(false) }
if(showCreateBranchDialog)
NewBranchDialog(
onReject = {
showCreateBranchDialog = false
},
onAccept = { branchName ->
gitManager.createBranchOnCommit(branchName, graphNode)
showCreateBranchDialog = false
}
)
Box(modifier = Modifier
.clickable {
@ -252,48 +328,20 @@ fun CommitLine(
}),
ContextMenuItem(
label = "Create branch",
onClick = {
showCreateBranchDialog = true
}
onClick = showCreateNewBranch
),
ContextMenuItem(
label = "Create tag",
onClick = {
dialogManager.show {
NewTagDialog(
onReject = {
dialogManager.dismiss()
},
onAccept = { tagName ->
gitManager.createTagOnCommit(tagName, graphNode)
dialogManager.dismiss()
}
)
}
}
onClick = showCreateNewTag
),
ContextMenuItem(
label = "Revert commit",
onClick = {
gitManager.revertCommit(graphNode)
}
onClick = { gitManager.revertCommit(graphNode) }
),
ContextMenuItem(
label = "Reset current branch to this commit",
onClick = {
dialogManager.show {
ResetBranchDialog(
onReject = {
dialogManager.dismiss()
},
onAccept = { resetType ->
dialogManager.dismiss()
gitManager.resetToCommit(graphNode, resetType)
}
)
}
}
onClick = { resetBranch(graphNode) }
)
)
},
@ -326,21 +374,7 @@ fun CommitLine(
selected = selected,
refs = commitRefs,
onCheckoutRef = { ref -> gitManager.checkoutRef(ref) },
onMergeBranch = { ref ->
dialogManager.show {
MergeDialog(
currentBranchName = "HEAD",
mergeBranchName = ref.simpleName,
onReject = {
dialogManager.dismiss()
},
onAccept = { fastForward ->
dialogManager.dismiss()
gitManager.mergeBranch(ref, fastForward)
}
)
}
},
onMergeBranch = { ref -> onMergeBranch(ref) },
onDeleteBranch = { ref -> gitManager.deleteBranch(ref) }
)
}

View File

@ -0,0 +1,12 @@
package app.ui.log
import app.git.graph.GraphNode
import org.eclipse.jgit.lib.Ref
sealed class LogDialog {
object None: LogDialog()
data class NewBranch(val graphNode: GraphNode): LogDialog()
data class NewTag(val graphNode: GraphNode): LogDialog()
data class ResetBranch(val graphNode: GraphNode): LogDialog()
data class MergeBranch(val ref: Ref): LogDialog()
}