Diff scroll is now preserved when changing the diff entry
The scroll is stored in the view model and only resetted when changing to a different file or state (staged/unstaged version of the same file).
This commit is contained in:
parent
9c53ce726e
commit
e6619cbd4b
@ -15,14 +15,6 @@ import org.eclipse.jgit.revwalk.RevCommit
|
||||
import javax.inject.Inject
|
||||
|
||||
class BranchesManager @Inject constructor() {
|
||||
private val _branches = MutableStateFlow<List<Ref>>(listOf())
|
||||
val branches: StateFlow<List<Ref>>
|
||||
get() = _branches
|
||||
|
||||
private val _currentBranch = MutableStateFlow<String>("")
|
||||
val currentBranch: StateFlow<String>
|
||||
get() = _currentBranch
|
||||
|
||||
/**
|
||||
* Returns the current branch in [Ref]. If the repository is new, the current branch will be null.
|
||||
*/
|
||||
|
@ -21,8 +21,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.LoadingRepository
|
||||
import app.credentials.CredentialsState
|
||||
import app.git.TabViewModel
|
||||
import app.git.RepositorySelectionStatus
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.viewmodels.RepositorySelectionStatus
|
||||
import app.ui.dialogs.PasswordDialog
|
||||
import app.ui.dialogs.UserPasswordDialog
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -13,7 +13,6 @@ import androidx.compose.ui.unit.dp
|
||||
import app.MAX_SIDE_PANEL_ITEMS_HEIGHT
|
||||
import app.extensions.isLocal
|
||||
import app.extensions.simpleName
|
||||
import app.git.TabViewModel
|
||||
import app.ui.components.ScrollableLazyColumn
|
||||
import app.ui.components.SideMenuEntry
|
||||
import app.ui.components.SideMenuSubentry
|
||||
|
@ -17,7 +17,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.extensions.*
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.theme.headerBackground
|
||||
import app.theme.headerText
|
||||
import app.theme.primaryTextColor
|
||||
|
@ -16,8 +16,6 @@ import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.git.DiffEntryType
|
||||
import app.git.TabViewModel
|
||||
import app.git.diff.Hunk
|
||||
import app.git.diff.LineType
|
||||
import app.theme.primaryTextColor
|
||||
import app.ui.components.ScrollableLazyColumn
|
||||
@ -55,10 +53,11 @@ fun Diff(
|
||||
Text("Close diff")
|
||||
}
|
||||
|
||||
val scrollState by diffViewModel.lazyListState.collectAsState()
|
||||
ScrollableLazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
// .padding(16.dp)
|
||||
.fillMaxSize(),
|
||||
state = scrollState
|
||||
) {
|
||||
itemsIndexed(hunks) { index, hunk ->
|
||||
val hunksSeparation = if (index == 0)
|
||||
|
@ -12,7 +12,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.MAX_SIDE_PANEL_ITEMS_HEIGHT
|
||||
import app.extensions.simpleVisibleName
|
||||
import app.git.TabViewModel
|
||||
import app.git.RemoteInfo
|
||||
import app.ui.components.ScrollableLazyColumn
|
||||
import app.ui.components.SideMenuEntry
|
||||
|
@ -1,12 +1,11 @@
|
||||
package app.ui
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.git.DiffEntryType
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.ui.dialogs.NewBranchDialog
|
||||
import app.ui.log.Log
|
||||
import openRepositoryDialog
|
||||
@ -20,22 +19,13 @@ import org.jetbrains.compose.splitpane.rememberSplitPaneState
|
||||
@Composable
|
||||
fun RepositoryOpenPage(tabViewModel: TabViewModel) {
|
||||
val repositoryState by tabViewModel.repositoryState.collectAsState()
|
||||
|
||||
var diffSelected by remember {
|
||||
mutableStateOf<DiffEntryType?>(null)
|
||||
}
|
||||
|
||||
LaunchedEffect(diffSelected) {
|
||||
diffSelected?.let { safeDiffSelected ->
|
||||
tabViewModel.updatedDiffEntry(safeDiffSelected)
|
||||
}
|
||||
}
|
||||
val diffSelected by tabViewModel.diffSelected.collectAsState()
|
||||
|
||||
var showNewBranchDialog by remember { mutableStateOf(false) }
|
||||
|
||||
val (selectedItem, setSelectedItem) = remember { mutableStateOf<SelectedItem>(SelectedItem.None) }
|
||||
LaunchedEffect(selectedItem) {
|
||||
diffSelected = null
|
||||
tabViewModel.newDiffSelected = null
|
||||
}
|
||||
|
||||
if (showNewBranchDialog) {
|
||||
@ -104,26 +94,24 @@ fun RepositoryOpenPage(tabViewModel: TabViewModel) {
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
// Crossfade(targetState = diffSelected) { diffEntry ->
|
||||
when (diffSelected) {
|
||||
null -> {
|
||||
Log(
|
||||
tabViewModel = tabViewModel,
|
||||
repositoryState = repositoryState,
|
||||
logViewModel = tabViewModel.logViewModel,
|
||||
selectedItem = selectedItem,
|
||||
onItemSelected = {
|
||||
setSelectedItem(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Diff(
|
||||
diffViewModel = tabViewModel.diffViewModel,
|
||||
onCloseDiffView = { diffSelected = null })
|
||||
}
|
||||
when (diffSelected) {
|
||||
null -> {
|
||||
Log(
|
||||
tabViewModel = tabViewModel,
|
||||
repositoryState = repositoryState,
|
||||
logViewModel = tabViewModel.logViewModel,
|
||||
selectedItem = selectedItem,
|
||||
onItemSelected = {
|
||||
setSelectedItem(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
// }
|
||||
else -> {
|
||||
Diff(
|
||||
diffViewModel = tabViewModel.diffViewModel,
|
||||
onCloseDiffView = { tabViewModel.newDiffSelected = null })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,13 +126,13 @@ fun RepositoryOpenPage(tabViewModel: TabViewModel) {
|
||||
selectedEntryType = diffSelected,
|
||||
repositoryState = repositoryState,
|
||||
onStagedDiffEntrySelected = { diffEntry ->
|
||||
diffSelected = if (diffEntry != null)
|
||||
tabViewModel.newDiffSelected = if (diffEntry != null)
|
||||
DiffEntryType.StagedDiff(diffEntry)
|
||||
else
|
||||
null
|
||||
},
|
||||
onUnstagedDiffEntrySelected = { diffEntry ->
|
||||
diffSelected = DiffEntryType.UnstagedDiff(diffEntry)
|
||||
tabViewModel.newDiffSelected = DiffEntryType.UnstagedDiff(diffEntry)
|
||||
}
|
||||
)
|
||||
} else if (selectedItem is SelectedItem.CommitBasedItem) {
|
||||
@ -152,7 +140,7 @@ fun RepositoryOpenPage(tabViewModel: TabViewModel) {
|
||||
gitManager = tabViewModel,
|
||||
commit = selectedItem.revCommit,
|
||||
onDiffSelected = { diffEntry ->
|
||||
diffSelected = DiffEntryType.CommitDiff(diffEntry)
|
||||
tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.git.StashStatus
|
||||
import app.ui.components.ScrollableLazyColumn
|
||||
import app.ui.components.SideMenuEntry
|
||||
|
@ -1,5 +1,5 @@
|
||||
import app.extensions.runCommand
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import javax.swing.JFileChooser
|
||||
|
||||
|
||||
|
@ -13,7 +13,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.MAX_SIDE_PANEL_ITEMS_HEIGHT
|
||||
import app.extensions.simpleName
|
||||
import app.git.TabViewModel
|
||||
import app.ui.components.ScrollableLazyColumn
|
||||
import app.ui.components.SideMenuEntry
|
||||
import app.ui.components.SideMenuSubentry
|
||||
|
@ -74,7 +74,6 @@ fun UncommitedChanges(
|
||||
unstaged = listOf<StatusEntry>() // return empty lists if still loading
|
||||
}
|
||||
|
||||
|
||||
var commitMessage by remember { mutableStateOf("") }
|
||||
val doCommit = {
|
||||
statusViewModel.commit(commitMessage)
|
||||
@ -190,6 +189,7 @@ fun UncommitedChanges(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This logic should be part of the diffViewModel where it gets the latest version of the diffEntry
|
||||
fun checkIfSelectedEntryShouldBeUpdated(
|
||||
selectedEntryType: DiffEntryType,
|
||||
staged: List<StatusEntry>,
|
||||
|
@ -20,7 +20,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.extensions.dirName
|
||||
import app.extensions.dirPath
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.theme.primaryTextColor
|
||||
import app.theme.secondaryTextColor
|
||||
import app.ui.dialogs.CloneDialog
|
||||
|
@ -23,7 +23,7 @@ import androidx.compose.ui.unit.dp
|
||||
import app.AppStateManager
|
||||
import app.di.AppComponent
|
||||
import app.di.DaggerTabComponent
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.theme.tabColorActive
|
||||
import app.theme.tabColorInactive
|
||||
import app.ui.AppTab
|
||||
|
@ -12,7 +12,7 @@ import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.git.CloneStatus
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.theme.primaryTextColor
|
||||
import java.io.File
|
||||
|
||||
|
@ -34,7 +34,7 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.extensions.*
|
||||
import app.git.TabViewModel
|
||||
import app.viewmodels.TabViewModel
|
||||
import app.git.graph.GraphNode
|
||||
import app.theme.*
|
||||
import app.ui.SelectedItem
|
||||
|
@ -1,5 +1,9 @@
|
||||
package app.viewmodels
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import app.git.*
|
||||
import app.git.diff.Hunk
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -20,9 +24,30 @@ class DiffViewModel @Inject constructor(
|
||||
private val _diffResult = MutableStateFlow<DiffResult?>(null)
|
||||
val diffResult: StateFlow<DiffResult?> = _diffResult
|
||||
|
||||
val lazyListState = MutableStateFlow(
|
||||
LazyListState(
|
||||
0,
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
suspend fun updateDiff(git: Git, diffEntryType: DiffEntryType) = withContext(Dispatchers.IO) {
|
||||
val oldDiffEntryType = _diffResult.value?.diffEntryType
|
||||
|
||||
_diffResult.value = null
|
||||
|
||||
// If it's a different file or different state (index or workdir), reset the scroll state
|
||||
if(oldDiffEntryType != null &&
|
||||
(oldDiffEntryType.diffEntry.oldPath != diffEntryType.diffEntry.oldPath ||
|
||||
oldDiffEntryType.diffEntry.newPath != diffEntryType.diffEntry.newPath ||
|
||||
oldDiffEntryType::class != diffEntryType::class)
|
||||
) {
|
||||
lazyListState.value = LazyListState(
|
||||
0,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
val hunks = diffManager.diffFormat(git, diffEntryType)
|
||||
|
||||
_diffResult.value = DiffResult(diffEntryType, hunks)
|
||||
|
@ -26,32 +26,28 @@ class StatusViewModel @Inject constructor(
|
||||
|
||||
fun stage(diffEntry: DiffEntry) = tabState.runOperation { git ->
|
||||
statusManager.stage(git, diffEntry)
|
||||
loadStatus(git)
|
||||
|
||||
return@runOperation RefreshType.NONE
|
||||
return@runOperation RefreshType.UNCOMMITED_CHANGES
|
||||
}
|
||||
|
||||
fun unstage(diffEntry: DiffEntry) = tabState.runOperation { git ->
|
||||
statusManager.unstage(git, diffEntry)
|
||||
loadStatus(git)
|
||||
|
||||
return@runOperation RefreshType.NONE
|
||||
return@runOperation RefreshType.UNCOMMITED_CHANGES
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun unstageAll() = tabState.safeProcessing { git ->
|
||||
statusManager.unstageAll(git)
|
||||
loadStatus(git)
|
||||
|
||||
return@safeProcessing RefreshType.NONE
|
||||
return@safeProcessing RefreshType.UNCOMMITED_CHANGES
|
||||
}
|
||||
|
||||
fun stageAll() = tabState.safeProcessing { git ->
|
||||
statusManager.stageAll(git)
|
||||
loadStatus(git)
|
||||
|
||||
return@safeProcessing RefreshType.NONE
|
||||
return@safeProcessing RefreshType.UNCOMMITED_CHANGES
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
package app.git
|
||||
package app.viewmodels
|
||||
|
||||
import app.AppStateManager
|
||||
import app.app.ErrorsManager
|
||||
import app.app.newErrorNow
|
||||
import app.credentials.CredentialsState
|
||||
import app.credentials.CredentialsStateManager
|
||||
import app.git.diff.Hunk
|
||||
import app.viewmodels.*
|
||||
import app.git.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@ -38,6 +37,7 @@ class TabViewModel @Inject constructor(
|
||||
val appStateManager: AppStateManager,
|
||||
private val fileChangesWatcher: FileChangesWatcher,
|
||||
) {
|
||||
|
||||
val repositoryName: String
|
||||
get() = safeGit.repository.directory.parentFile.name
|
||||
|
||||
@ -57,6 +57,16 @@ class TabViewModel @Inject constructor(
|
||||
val credentialsState: StateFlow<CredentialsState> = credentialsStateManager.credentialsState
|
||||
val cloneStatus: StateFlow<CloneStatus> = remoteOperationsManager.cloneStatus
|
||||
|
||||
private val _diffSelected = MutableStateFlow<DiffEntryType?>(null)
|
||||
val diffSelected : StateFlow<DiffEntryType?> = _diffSelected
|
||||
var newDiffSelected: DiffEntryType?
|
||||
get() = diffSelected.value
|
||||
set(value){
|
||||
_diffSelected.value = value
|
||||
|
||||
updateDiffEntry()
|
||||
}
|
||||
|
||||
private val _repositoryState = MutableStateFlow(RepositoryState.SAFE)
|
||||
val repositoryState: StateFlow<RepositoryState> = _repositoryState
|
||||
|
||||
@ -153,12 +163,10 @@ class TabViewModel @Inject constructor(
|
||||
if (!operationRunning) { // Only update if there isn't any process running
|
||||
safeProcessing(showError = false) {
|
||||
println("Changes detected, loading status")
|
||||
// val hasUncommitedChanges = statusManager.hasUncommitedChanges.value
|
||||
// statusManager.loadHasUncommitedChanges(safeGit)
|
||||
// statusManager.loadStatus(safeGit)
|
||||
|
||||
statusViewModel.refresh(safeGit)
|
||||
checkUncommitedChanges()
|
||||
|
||||
updateDiffEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,16 +182,8 @@ class TabViewModel @Inject constructor(
|
||||
// Update the log only if the uncommitedChanges status has changed
|
||||
if (uncommitedChangesStateChanged)
|
||||
loadLog()
|
||||
}
|
||||
|
||||
suspend fun diffFormat(diffEntryType: DiffEntryType): List<Hunk> {
|
||||
try {
|
||||
return diffManager.diffFormat(safeGit, diffEntryType)
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
checkUncommitedChanges()
|
||||
return listOf()
|
||||
}
|
||||
updateDiffEntry()
|
||||
}
|
||||
|
||||
fun pull() = managerScope.launch {
|
||||
@ -279,8 +279,12 @@ class TabViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun updatedDiffEntry(diffSelected: DiffEntryType) = tabState.runOperation { git ->
|
||||
diffViewModel.updateDiff(git , diffSelected)
|
||||
fun updateDiffEntry() = tabState.runOperation { git ->
|
||||
val diffSelected = diffSelected.value
|
||||
|
||||
if(diffSelected != null) {
|
||||
diffViewModel.updateDiff(git, diffSelected)
|
||||
}
|
||||
|
||||
return@runOperation RefreshType.NONE
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user