diff --git a/src/main/kotlin/app/git/BranchesManager.kt b/src/main/kotlin/app/git/BranchesManager.kt index 757b0f2..8af5ea4 100644 --- a/src/main/kotlin/app/git/BranchesManager.kt +++ b/src/main/kotlin/app/git/BranchesManager.kt @@ -15,14 +15,6 @@ import org.eclipse.jgit.revwalk.RevCommit import javax.inject.Inject class BranchesManager @Inject constructor() { - private val _branches = MutableStateFlow>(listOf()) - val branches: StateFlow> - get() = _branches - - private val _currentBranch = MutableStateFlow("") - val currentBranch: StateFlow - get() = _currentBranch - /** * Returns the current branch in [Ref]. If the repository is new, the current branch will be null. */ diff --git a/src/main/kotlin/app/ui/AppTab.kt b/src/main/kotlin/app/ui/AppTab.kt index b240b9a..d70b180 100644 --- a/src/main/kotlin/app/ui/AppTab.kt +++ b/src/main/kotlin/app/ui/AppTab.kt @@ -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 diff --git a/src/main/kotlin/app/ui/Branches.kt b/src/main/kotlin/app/ui/Branches.kt index 5ff12d4..1962da0 100644 --- a/src/main/kotlin/app/ui/Branches.kt +++ b/src/main/kotlin/app/ui/Branches.kt @@ -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 diff --git a/src/main/kotlin/app/ui/CommitChanges.kt b/src/main/kotlin/app/ui/CommitChanges.kt index 193af5b..8145950 100644 --- a/src/main/kotlin/app/ui/CommitChanges.kt +++ b/src/main/kotlin/app/ui/CommitChanges.kt @@ -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 diff --git a/src/main/kotlin/app/ui/Diff.kt b/src/main/kotlin/app/ui/Diff.kt index f0786cd..667b745 100644 --- a/src/main/kotlin/app/ui/Diff.kt +++ b/src/main/kotlin/app/ui/Diff.kt @@ -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) diff --git a/src/main/kotlin/app/ui/Remotes.kt b/src/main/kotlin/app/ui/Remotes.kt index 43f9ea7..f1f3160 100644 --- a/src/main/kotlin/app/ui/Remotes.kt +++ b/src/main/kotlin/app/ui/Remotes.kt @@ -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 diff --git a/src/main/kotlin/app/ui/RepositoryOpen.kt b/src/main/kotlin/app/ui/RepositoryOpen.kt index 8f72c5f..44a5d81 100644 --- a/src/main/kotlin/app/ui/RepositoryOpen.kt +++ b/src/main/kotlin/app/ui/RepositoryOpen.kt @@ -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(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.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) } ) } diff --git a/src/main/kotlin/app/ui/Stashes.kt b/src/main/kotlin/app/ui/Stashes.kt index 29cbef0..7308c1c 100644 --- a/src/main/kotlin/app/ui/Stashes.kt +++ b/src/main/kotlin/app/ui/Stashes.kt @@ -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 diff --git a/src/main/kotlin/app/ui/SystemDialogs.kt b/src/main/kotlin/app/ui/SystemDialogs.kt index 1996cbc..9799b77 100644 --- a/src/main/kotlin/app/ui/SystemDialogs.kt +++ b/src/main/kotlin/app/ui/SystemDialogs.kt @@ -1,5 +1,5 @@ import app.extensions.runCommand -import app.git.TabViewModel +import app.viewmodels.TabViewModel import javax.swing.JFileChooser diff --git a/src/main/kotlin/app/ui/Tags.kt b/src/main/kotlin/app/ui/Tags.kt index 05546f1..e1f77d0 100644 --- a/src/main/kotlin/app/ui/Tags.kt +++ b/src/main/kotlin/app/ui/Tags.kt @@ -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 diff --git a/src/main/kotlin/app/ui/UncommitedChanges.kt b/src/main/kotlin/app/ui/UncommitedChanges.kt index a500476..c639af7 100644 --- a/src/main/kotlin/app/ui/UncommitedChanges.kt +++ b/src/main/kotlin/app/ui/UncommitedChanges.kt @@ -74,7 +74,6 @@ fun UncommitedChanges( unstaged = listOf() // 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, diff --git a/src/main/kotlin/app/ui/WelcomePage.kt b/src/main/kotlin/app/ui/WelcomePage.kt index 781f53f..69b5445 100644 --- a/src/main/kotlin/app/ui/WelcomePage.kt +++ b/src/main/kotlin/app/ui/WelcomePage.kt @@ -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 diff --git a/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt b/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt index 0b8c213..b9d5733 100644 --- a/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt +++ b/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt @@ -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 diff --git a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt index 22c4140..53a7703 100644 --- a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt @@ -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 diff --git a/src/main/kotlin/app/ui/log/Log.kt b/src/main/kotlin/app/ui/log/Log.kt index 2f6abbb..b480a3c 100644 --- a/src/main/kotlin/app/ui/log/Log.kt +++ b/src/main/kotlin/app/ui/log/Log.kt @@ -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 diff --git a/src/main/kotlin/app/viewmodels/DiffViewModel.kt b/src/main/kotlin/app/viewmodels/DiffViewModel.kt index 8dae798..7a3d868 100644 --- a/src/main/kotlin/app/viewmodels/DiffViewModel.kt +++ b/src/main/kotlin/app/viewmodels/DiffViewModel.kt @@ -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(null) val diffResult: StateFlow = _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) diff --git a/src/main/kotlin/app/viewmodels/StatusViewModel.kt b/src/main/kotlin/app/viewmodels/StatusViewModel.kt index 81df400..6a2e394 100644 --- a/src/main/kotlin/app/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/app/viewmodels/StatusViewModel.kt @@ -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 } diff --git a/src/main/kotlin/app/viewmodels/TabViewModel.kt b/src/main/kotlin/app/viewmodels/TabViewModel.kt index 9105b54..dec2bdf 100644 --- a/src/main/kotlin/app/viewmodels/TabViewModel.kt +++ b/src/main/kotlin/app/viewmodels/TabViewModel.kt @@ -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 = credentialsStateManager.credentialsState val cloneStatus: StateFlow = remoteOperationsManager.cloneStatus + private val _diffSelected = MutableStateFlow(null) + val diffSelected : StateFlow = _diffSelected + var newDiffSelected: DiffEntryType? + get() = diffSelected.value + set(value){ + _diffSelected.value = value + + updateDiffEntry() + } + private val _repositoryState = MutableStateFlow(RepositoryState.SAFE) val repositoryState: StateFlow = _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 { - 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 }