Implemented stage/unstage by hunks
This commit is contained in:
parent
86fd61d0d7
commit
a8ed01784d
@ -28,4 +28,9 @@ val String.dirPath: String
|
|||||||
parts.joinToString("/")
|
parts.joinToString("/")
|
||||||
} else
|
} else
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val String.withoutLineEnding: String
|
||||||
|
get() = this
|
||||||
|
.removeSuffix("\n")
|
||||||
|
.removeSuffix("\r\n")
|
@ -173,6 +173,18 @@ class GitManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun stageHunk(diffEntry: DiffEntry, hunk: Hunk) = managerScope.launch {
|
||||||
|
runOperation {
|
||||||
|
statusManager.stageHunk(safeGit, diffEntry, hunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unstageHunk(diffEntry: DiffEntry, hunk: Hunk) = managerScope.launch {
|
||||||
|
runOperation {
|
||||||
|
statusManager.unstageHunk(safeGit, diffEntry, hunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun unstage(diffEntry: DiffEntry) = managerScope.launch {
|
fun unstage(diffEntry: DiffEntry) = managerScope.launch {
|
||||||
runOperation {
|
runOperation {
|
||||||
statusManager.unstage(safeGit, diffEntry)
|
statusManager.unstage(safeGit, diffEntry)
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
package app.git
|
package app.git
|
||||||
|
|
||||||
|
import app.di.RawFileManagerFactory
|
||||||
import app.extensions.filePath
|
import app.extensions.filePath
|
||||||
import app.extensions.hasUntrackedChanges
|
import app.extensions.hasUntrackedChanges
|
||||||
|
import app.extensions.isMerging
|
||||||
|
import app.extensions.withoutLineEnding
|
||||||
|
import app.git.diff.Hunk
|
||||||
|
import app.git.diff.LineType
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@ -9,12 +14,21 @@ import kotlinx.coroutines.flow.StateFlow
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import org.eclipse.jgit.diff.DiffEntry
|
import org.eclipse.jgit.diff.DiffEntry
|
||||||
import org.eclipse.jgit.lib.RepositoryState
|
import org.eclipse.jgit.diff.RawText
|
||||||
|
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit
|
||||||
|
import org.eclipse.jgit.dircache.DirCacheEntry
|
||||||
|
import org.eclipse.jgit.lib.*
|
||||||
import org.eclipse.jgit.treewalk.EmptyTreeIterator
|
import org.eclipse.jgit.treewalk.EmptyTreeIterator
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
class StatusManager @Inject constructor(
|
class StatusManager @Inject constructor(
|
||||||
private val branchesManager: BranchesManager,
|
private val branchesManager: BranchesManager,
|
||||||
|
private val rawFileManagerFactory: RawFileManagerFactory,
|
||||||
) {
|
) {
|
||||||
private val _stageStatus = MutableStateFlow<StageStatus>(StageStatus.Loaded(listOf(), listOf()))
|
private val _stageStatus = MutableStateFlow<StageStatus>(StageStatus.Loaded(listOf(), listOf()))
|
||||||
val stageStatus: StateFlow<StageStatus> = _stageStatus
|
val stageStatus: StateFlow<StageStatus> = _stageStatus
|
||||||
@ -53,7 +67,7 @@ class StatusManager @Inject constructor(
|
|||||||
val currentBranch = branchesManager.currentBranchRef(git)
|
val currentBranch = branchesManager.currentBranchRef(git)
|
||||||
val repositoryState = git.repository.repositoryState
|
val repositoryState = git.repository.repositoryState
|
||||||
val staged = git.diff().apply {
|
val staged = git.diff().apply {
|
||||||
if(currentBranch == null && repositoryState != RepositoryState.MERGING && !repositoryState.isRebasing )
|
if (currentBranch == null && !repositoryState.isMerging && !repositoryState.isRebasing)
|
||||||
setOldTree(EmptyTreeIterator()) // Required if the repository is empty
|
setOldTree(EmptyTreeIterator()) // Required if the repository is empty
|
||||||
|
|
||||||
setCached(true)
|
setCached(true)
|
||||||
@ -64,7 +78,7 @@ class StatusManager @Inject constructor(
|
|||||||
.map {
|
.map {
|
||||||
val entries = it.value
|
val entries = it.value
|
||||||
|
|
||||||
if(entries.count() > 1)
|
if (entries.count() > 1 && (repositoryState.isMerging || repositoryState.isRebasing))
|
||||||
entries.filter { entry -> entry.oldPath != "/dev/null" }
|
entries.filter { entry -> entry.oldPath != "/dev/null" }
|
||||||
else
|
else
|
||||||
entries
|
entries
|
||||||
@ -79,7 +93,7 @@ class StatusManager @Inject constructor(
|
|||||||
.map {
|
.map {
|
||||||
val entries = it.value
|
val entries = it.value
|
||||||
|
|
||||||
if(entries.count() > 1)
|
if (entries.count() > 1 && (repositoryState.isMerging || repositoryState.isRebasing))
|
||||||
entries.filter { entry -> entry.newPath != "/dev/null" }
|
entries.filter { entry -> entry.newPath != "/dev/null" }
|
||||||
else
|
else
|
||||||
entries
|
entries
|
||||||
@ -108,12 +122,121 @@ class StatusManager @Inject constructor(
|
|||||||
loadStatus(git)
|
loadStatus(git)
|
||||||
}
|
}
|
||||||
|
|
||||||
// suspend fun stageHunk(git: Git) {
|
suspend fun stageHunk(git: Git, diffEntry: DiffEntry, hunk: Hunk) = withContext(Dispatchers.IO) {
|
||||||
//// val repository = git.repository
|
val repository = git.repository
|
||||||
//// val objectInserter = repository.newObjectInserter()
|
val dirCache = repository.lockDirCache()
|
||||||
//
|
val dirCacheEditor = dirCache.editor()
|
||||||
//// objectInserter.insert(Constants.OBJ_BLOB,)
|
var completedWithErrors = true
|
||||||
// }
|
|
||||||
|
try {
|
||||||
|
val rawFileManager = rawFileManagerFactory.create(git.repository)
|
||||||
|
val rawFile = rawFileManager.getRawContent(DiffEntry.Side.OLD, diffEntry)
|
||||||
|
val textLines = getTextLines(rawFile).toMutableList()
|
||||||
|
|
||||||
|
val hunkLines = hunk.lines.filter { it.lineType != LineType.CONTEXT }
|
||||||
|
|
||||||
|
var linesAdded = 0
|
||||||
|
for (line in hunkLines) {
|
||||||
|
when (line.lineType) {
|
||||||
|
LineType.ADDED -> {
|
||||||
|
textLines.add(line.oldLineNumber + linesAdded, line.text.withoutLineEnding)
|
||||||
|
linesAdded++
|
||||||
|
}
|
||||||
|
LineType.REMOVED -> {
|
||||||
|
textLines.removeAt(line.oldLineNumber + linesAdded)
|
||||||
|
linesAdded--
|
||||||
|
}
|
||||||
|
else -> throw NotImplementedError("Line type not implemented for stage hunk")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val stagedFileText = textLines.joinToString(rawFile.lineDelimiter)
|
||||||
|
dirCacheEditor.add(HunkEdit(diffEntry.newPath, repository, ByteBuffer.wrap(stagedFileText.toByteArray())))
|
||||||
|
dirCacheEditor.commit()
|
||||||
|
|
||||||
|
completedWithErrors = false
|
||||||
|
|
||||||
|
loadStatus(git)
|
||||||
|
} finally {
|
||||||
|
if (completedWithErrors)
|
||||||
|
dirCache.unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun unstageHunk(git: Git, diffEntry: DiffEntry, hunk: Hunk) = withContext(Dispatchers.IO) {
|
||||||
|
val repository = git.repository
|
||||||
|
val dirCache = repository.lockDirCache()
|
||||||
|
val dirCacheEditor = dirCache.editor()
|
||||||
|
|
||||||
|
val rawFileManager = rawFileManagerFactory.create(git.repository)
|
||||||
|
val rawFile = rawFileManager.getRawContent(DiffEntry.Side.NEW, diffEntry)
|
||||||
|
val textLines = getTextLines(rawFile).toMutableList()
|
||||||
|
|
||||||
|
val hunkLines = hunk.lines.filter { it.lineType != LineType.CONTEXT }
|
||||||
|
|
||||||
|
val addedLines = hunkLines
|
||||||
|
.filter { it.lineType == LineType.ADDED }
|
||||||
|
.sortedBy { it.newLineNumber }
|
||||||
|
val removedLines = hunkLines
|
||||||
|
.filter { it.lineType == LineType.REMOVED }
|
||||||
|
.sortedBy { it.newLineNumber }
|
||||||
|
|
||||||
|
var linesRemoved = 0
|
||||||
|
|
||||||
|
// Start by removing the added lines to the index
|
||||||
|
for (line in addedLines) {
|
||||||
|
textLines.removeAt(line.newLineNumber + linesRemoved)
|
||||||
|
linesRemoved--
|
||||||
|
}
|
||||||
|
|
||||||
|
var linesAdded = 0
|
||||||
|
|
||||||
|
// Restore previously removed lines to the index
|
||||||
|
for (line in removedLines) {
|
||||||
|
textLines.add(line.newLineNumber + linesAdded, line.text.withoutLineEnding)
|
||||||
|
linesAdded++
|
||||||
|
}
|
||||||
|
|
||||||
|
val stagedFileText = textLines.joinToString(rawFile.lineDelimiter)
|
||||||
|
dirCacheEditor.add(HunkEdit(diffEntry.newPath, repository, ByteBuffer.wrap(stagedFileText.toByteArray())))
|
||||||
|
dirCacheEditor.commit()
|
||||||
|
|
||||||
|
loadStatus(git)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTextLines(rawFile: RawText): List<String> {
|
||||||
|
val content = rawFile.rawContent.toString(Charsets.UTF_8)
|
||||||
|
return content.split(rawFile.lineDelimiter).toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HunkEdit(
|
||||||
|
path: String?,
|
||||||
|
private val repo: Repository,
|
||||||
|
private val content: ByteBuffer,
|
||||||
|
) : PathEdit(path) {
|
||||||
|
override fun apply(ent: DirCacheEntry) {
|
||||||
|
val inserter: ObjectInserter = repo.newObjectInserter()
|
||||||
|
if (ent.rawMode and FileMode.TYPE_MASK != FileMode.TYPE_FILE) {
|
||||||
|
ent.fileMode = FileMode.REGULAR_FILE
|
||||||
|
}
|
||||||
|
ent.length = content.limit()
|
||||||
|
ent.setLastModified(Instant.now())
|
||||||
|
try {
|
||||||
|
val `in` = ByteArrayInputStream(
|
||||||
|
content.array(), 0, content.limit()
|
||||||
|
)
|
||||||
|
ent.setObjectId(
|
||||||
|
inserter.insert(
|
||||||
|
Constants.OBJ_BLOB, content.limit().toLong(),
|
||||||
|
`in`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
inserter.flush()
|
||||||
|
} catch (ex: IOException) {
|
||||||
|
throw RuntimeException(ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun unstage(git: Git, diffEntry: DiffEntry) = withContext(Dispatchers.IO) {
|
suspend fun unstage(git: Git, diffEntry: DiffEntry) = withContext(Dispatchers.IO) {
|
||||||
git.reset()
|
git.reset()
|
||||||
|
@ -2,8 +2,10 @@ package app.git.diff
|
|||||||
|
|
||||||
data class Hunk(val header: String, val lines: List<Line>)
|
data class Hunk(val header: String, val lines: List<Line>)
|
||||||
|
|
||||||
sealed class Line(val content: String) {
|
data class Line(val text: String, val oldLineNumber: Int, val newLineNumber: Int, val lineType: LineType)
|
||||||
class ContextLine(content: String, val oldLineNumber: Int, val newLineNumber: Int): Line(content)
|
|
||||||
class AddedLine(content: String, val oldLineNumber: Int, val newLineNumber: Int): Line(content)
|
enum class LineType {
|
||||||
class RemovedLine(content: String, val lineNumber: Int): Line(content)
|
CONTEXT,
|
||||||
|
ADDED,
|
||||||
|
REMOVED,
|
||||||
}
|
}
|
@ -72,18 +72,18 @@ class HunkDiffGenerator @AssistedInject constructor(
|
|||||||
while (oldCurrentLine < oldEndLine || newCurrentLine < newEndLine) {
|
while (oldCurrentLine < oldEndLine || newCurrentLine < newEndLine) {
|
||||||
if (oldCurrentLine < curEdit.beginA || endIdx + 1 < curIdx) {
|
if (oldCurrentLine < curEdit.beginA || endIdx + 1 < curIdx) {
|
||||||
val lineText = oldRawText.lineAt(oldCurrentLine)
|
val lineText = oldRawText.lineAt(oldCurrentLine)
|
||||||
lines.add(Line.ContextLine(lineText, oldCurrentLine, newCurrentLine))
|
lines.add(Line(lineText, oldCurrentLine, newCurrentLine, LineType.CONTEXT))
|
||||||
|
|
||||||
oldCurrentLine++
|
oldCurrentLine++
|
||||||
newCurrentLine++
|
newCurrentLine++
|
||||||
} else if (oldCurrentLine < curEdit.endA) {
|
} else if (oldCurrentLine < curEdit.endA) {
|
||||||
val lineText = oldRawText.lineAt(oldCurrentLine)
|
val lineText = oldRawText.lineAt(oldCurrentLine)
|
||||||
lines.add(Line.RemovedLine(lineText, oldCurrentLine))
|
lines.add(Line(lineText, oldCurrentLine, newCurrentLine, LineType.REMOVED))
|
||||||
|
|
||||||
oldCurrentLine++
|
oldCurrentLine++
|
||||||
} else if (newCurrentLine < curEdit.endB) {
|
} else if (newCurrentLine < curEdit.endB) {
|
||||||
val lineText = newRawText.lineAt(newCurrentLine)
|
val lineText = newRawText.lineAt(newCurrentLine)
|
||||||
lines.add(Line.AddedLine(lineText, oldCurrentLine, newCurrentLine))
|
lines.add(Line(lineText, oldCurrentLine, newCurrentLine, LineType.ADDED))
|
||||||
|
|
||||||
newCurrentLine++
|
newCurrentLine++
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package app.ui
|
package app.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.material.ButtonDefaults
|
import androidx.compose.material.ButtonDefaults
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
@ -21,9 +18,11 @@ import androidx.compose.ui.unit.sp
|
|||||||
import app.git.DiffEntryType
|
import app.git.DiffEntryType
|
||||||
import app.git.GitManager
|
import app.git.GitManager
|
||||||
import app.git.diff.Hunk
|
import app.git.diff.Hunk
|
||||||
import app.git.diff.Line
|
import app.git.diff.LineType
|
||||||
import app.theme.primaryTextColor
|
import app.theme.primaryTextColor
|
||||||
import app.ui.components.ScrollableLazyColumn
|
import app.ui.components.ScrollableLazyColumn
|
||||||
|
import app.ui.components.SecondaryButton
|
||||||
|
import org.eclipse.jgit.diff.DiffEntry
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Diff(gitManager: GitManager, diffEntryType: DiffEntryType, onCloseDiffView: () -> Unit) {
|
fun Diff(gitManager: GitManager, diffEntryType: DiffEntryType, onCloseDiffView: () -> Unit) {
|
||||||
@ -54,39 +53,78 @@ fun Diff(gitManager: GitManager, diffEntryType: DiffEntryType, onCloseDiffView:
|
|||||||
) {
|
) {
|
||||||
Text("Close diff")
|
Text("Close diff")
|
||||||
}
|
}
|
||||||
SelectionContainer {
|
|
||||||
ScrollableLazyColumn(
|
ScrollableLazyColumn(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(16.dp)
|
// .padding(16.dp)
|
||||||
) {
|
) {
|
||||||
items(text) { hunk ->
|
itemsIndexed(text) { index, hunk ->
|
||||||
|
val hunksSeparation = if (index == 0)
|
||||||
|
0.dp
|
||||||
|
else
|
||||||
|
16.dp
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = hunksSeparation)
|
||||||
|
.background(MaterialTheme.colors.surface)
|
||||||
|
.padding(vertical = 4.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = hunk.header,
|
text = hunk.header,
|
||||||
color = MaterialTheme.colors.primaryTextColor,
|
color = MaterialTheme.colors.primaryTextColor,
|
||||||
modifier = Modifier
|
|
||||||
.background(MaterialTheme.colors.surface)
|
|
||||||
.fillMaxWidth(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
if (
|
||||||
|
(diffEntryType is DiffEntryType.StagedDiff || diffEntryType is DiffEntryType.UnstagedDiff) &&
|
||||||
|
diffEntryType.diffEntry.changeType == DiffEntry.ChangeType.MODIFY
|
||||||
|
) {
|
||||||
|
val buttonText: String
|
||||||
|
val color: Color
|
||||||
|
if (diffEntryType is DiffEntryType.StagedDiff) {
|
||||||
|
buttonText = "Unstage"
|
||||||
|
color = MaterialTheme.colors.error
|
||||||
|
} else {
|
||||||
|
buttonText = "Stage"
|
||||||
|
color = MaterialTheme.colors.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
SecondaryButton(
|
||||||
|
text = buttonText,
|
||||||
|
backgroundButton = color,
|
||||||
|
onClick = {
|
||||||
|
if (diffEntryType is DiffEntryType.StagedDiff) {
|
||||||
|
gitManager.unstageHunk(diffEntryType.diffEntry, hunk)
|
||||||
|
} else {
|
||||||
|
gitManager.stageHunk(diffEntryType.diffEntry, hunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectionContainer {
|
||||||
Column {
|
Column {
|
||||||
hunk.lines.forEach { line ->
|
hunk.lines.forEach { line ->
|
||||||
val backgroundColor = when (line) {
|
val backgroundColor = when (line.lineType) {
|
||||||
is Line.AddedLine -> {
|
LineType.ADDED -> {
|
||||||
Color(0x77a9d49b)
|
Color(0x77a9d49b)
|
||||||
}
|
}
|
||||||
is Line.RemovedLine -> {
|
LineType.REMOVED -> {
|
||||||
Color(0x77dea2a2)
|
Color(0x77dea2a2)
|
||||||
}
|
}
|
||||||
is Line.ContextLine -> {
|
LineType.CONTEXT -> {
|
||||||
MaterialTheme.colors.background
|
MaterialTheme.colors.background
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = line.content,
|
text = line.text,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
|
.padding(start = 16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
color = MaterialTheme.colors.primaryTextColor,
|
color = MaterialTheme.colors.primaryTextColor,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
|
@ -9,13 +9,11 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.foundation.*
|
import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.input.key.Key
|
import androidx.compose.ui.input.key.Key
|
||||||
@ -38,6 +36,7 @@ import app.theme.headerBackground
|
|||||||
import app.theme.headerText
|
import app.theme.headerText
|
||||||
import app.theme.primaryTextColor
|
import app.theme.primaryTextColor
|
||||||
import app.ui.components.ScrollableLazyColumn
|
import app.ui.components.ScrollableLazyColumn
|
||||||
|
import app.ui.components.SecondaryButton
|
||||||
import org.eclipse.jgit.diff.DiffEntry
|
import org.eclipse.jgit.diff.DiffEntry
|
||||||
|
|
||||||
@OptIn(ExperimentalAnimationApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class)
|
@OptIn(ExperimentalAnimationApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class)
|
||||||
@ -50,6 +49,7 @@ fun UncommitedChanges(
|
|||||||
val stageStatusState = gitManager.stageStatus.collectAsState()
|
val stageStatusState = gitManager.stageStatus.collectAsState()
|
||||||
val stageStatus = stageStatusState.value
|
val stageStatus = stageStatusState.value
|
||||||
val lastCheck by gitManager.lastTimeChecked.collectAsState()
|
val lastCheck by gitManager.lastTimeChecked.collectAsState()
|
||||||
|
val repositoryState by gitManager.repositoryState.collectAsState()
|
||||||
|
|
||||||
LaunchedEffect(lastCheck) {
|
LaunchedEffect(lastCheck) {
|
||||||
gitManager.loadStatus()
|
gitManager.loadStatus()
|
||||||
@ -201,22 +201,12 @@ private fun EntriesList(
|
|||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(
|
SecondaryButton(
|
||||||
modifier = Modifier
|
modifier = Modifier.align(Alignment.CenterEnd),
|
||||||
.padding(horizontal = 16.dp)
|
text = allActionTitle,
|
||||||
.align(Alignment.CenterEnd)
|
backgroundButton = actionColor,
|
||||||
.clip(RoundedCornerShape(5.dp))
|
onClick = onAllAction
|
||||||
.background(actionColor)
|
)
|
||||||
.clickable { onAllAction() },
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = allActionTitle,
|
|
||||||
fontSize = 12.sp,
|
|
||||||
color = MaterialTheme.colors.contentColorFor(actionColor),
|
|
||||||
modifier = Modifier.padding(vertical = 4.dp, horizontal = 16.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollableLazyColumn(
|
ScrollableLazyColumn(
|
||||||
|
39
src/main/kotlin/app/ui/components/SecondaryButton.kt
Normal file
39
src/main/kotlin/app/ui/components/SecondaryButton.kt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package app.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.contentColorFor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SecondaryButton(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
text: String,
|
||||||
|
backgroundButton: Color,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = modifier
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.clip(RoundedCornerShape(5.dp))
|
||||||
|
.background(backgroundButton)
|
||||||
|
.clickable { onClick() },
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = MaterialTheme.colors.contentColorFor(backgroundButton),
|
||||||
|
modifier = Modifier.padding(vertical = 4.dp, horizontal = 16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user