diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt index 6d42ad87..9dc70dff 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt @@ -495,7 +495,10 @@ fun MessagesList( onRebaseBranch = onRebase, onRebaseInteractive = { logViewModel.rebaseInteractive(graphNode) }, onRevCommitSelected = { logViewModel.selectLogLine(graphNode) }, - onChangeDefaultUpstreamBranch = { onShowLogDialog(LogDialog.ChangeDefaultBranch(it)) } + onChangeDefaultUpstreamBranch = { onShowLogDialog(LogDialog.ChangeDefaultBranch(it)) }, + onDeleteStash = { logViewModel.deleteStash(graphNode) }, + onApplyStash = { logViewModel.applyStash(graphNode) }, + onPopStash = { logViewModel.popStash(graphNode) }, ) } @@ -737,6 +740,9 @@ fun CommitLine( showCreateNewBranch: () -> Unit, showCreateNewTag: () -> Unit, resetBranch: () -> Unit, + onApplyStash: () -> Unit, + onPopStash: () -> Unit, + onDeleteStash: () -> Unit, onMergeBranch: (Ref) -> Unit, onRebaseBranch: (Ref) -> Unit, onRevCommitSelected: () -> Unit, @@ -748,16 +754,24 @@ fun CommitLine( ContextMenu( items = { - logContextMenu( - onCheckoutCommit = { logViewModel.checkoutCommit(graphNode) }, - onCreateNewBranch = showCreateNewBranch, - onCreateNewTag = showCreateNewTag, - onRevertCommit = { logViewModel.revertCommit(graphNode) }, - onCherryPickCommit = { logViewModel.cherrypickCommit(graphNode) }, - onRebaseInteractive = onRebaseInteractive, - onResetBranch = { resetBranch() }, - isLastCommit = isLastCommitOfCurrentBranch - ) + if (graphNode.isStash) { + stashesContextMenuItems( + onApply = onApplyStash, + onPop = onPopStash, + onDelete = onDeleteStash, + ) + } else { + logContextMenu( + onCheckoutCommit = { logViewModel.checkoutCommit(graphNode) }, + onCreateNewBranch = showCreateNewBranch, + onCreateNewTag = showCreateNewTag, + onRevertCommit = { logViewModel.revertCommit(graphNode) }, + onCherryPickCommit = { logViewModel.cherrypickCommit(graphNode) }, + onRebaseInteractive = onRebaseInteractive, + onResetBranch = { resetBranch() }, + isLastCommit = isLastCommitOfCurrentBranch + ) + } }, ) { Box( diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt index bf1c3074..426274ad 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt @@ -17,6 +17,9 @@ import com.jetpackduba.gitnuro.git.rebase.StartRebaseInteractiveUseCase import com.jetpackduba.gitnuro.git.remote_operations.DeleteRemoteBranchUseCase import com.jetpackduba.gitnuro.git.remote_operations.PullFromSpecificBranchUseCase import com.jetpackduba.gitnuro.git.remote_operations.PushToSpecificBranchUseCase +import com.jetpackduba.gitnuro.git.stash.ApplyStashUseCase +import com.jetpackduba.gitnuro.git.stash.DeleteStashUseCase +import com.jetpackduba.gitnuro.git.stash.PopStashUseCase import com.jetpackduba.gitnuro.git.tags.CreateTagOnCommitUseCase import com.jetpackduba.gitnuro.git.tags.DeleteTagUseCase import com.jetpackduba.gitnuro.git.workspace.CheckHasUncommitedChangesUseCase @@ -67,10 +70,14 @@ class LogViewModel @Inject constructor( private val deleteTagUseCase: DeleteTagUseCase, private val rebaseBranchUseCase: RebaseBranchUseCase, private val startRebaseInteractiveUseCase: StartRebaseInteractiveUseCase, + private val applyStashUseCase: ApplyStashUseCase, + private val popStashUseCase: PopStashUseCase, + private val deleteStashUseCase: DeleteStashUseCase, private val tabState: TabState, private val appSettings: AppSettings, private val tabScope: CoroutineScope, -) : ViewModel { + sharedStashViewModel: SharedStashViewModel, +) : ViewModel, ISharedStashViewModel by sharedStashViewModel { private val _logStatus = MutableStateFlow(LogStatus.Loading) val logStatus: StateFlow @@ -445,7 +452,7 @@ class LogViewModel @Inject constructor( } sealed class LogStatus { - object Loading : LogStatus() + data object Loading : LogStatus() class Loaded( val hasUncommittedChanges: Boolean, val plotCommitList: GraphCommitList, @@ -456,7 +463,7 @@ sealed class LogStatus { } sealed class LogSearch { - object NotSearching : LogSearch() + data object NotSearching : LogSearch() data class SearchResults( val commits: List, val index: Int, diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SharedStashViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SharedStashViewModel.kt new file mode 100644 index 00000000..797c2749 --- /dev/null +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SharedStashViewModel.kt @@ -0,0 +1,68 @@ +package com.jetpackduba.gitnuro.viewmodels + +import com.jetpackduba.gitnuro.git.RefreshType +import com.jetpackduba.gitnuro.git.TabState +import com.jetpackduba.gitnuro.git.stash.ApplyStashUseCase +import com.jetpackduba.gitnuro.git.stash.DeleteStashUseCase +import com.jetpackduba.gitnuro.git.stash.PopStashUseCase +import com.jetpackduba.gitnuro.ui.SelectedItem +import kotlinx.coroutines.Job +import org.eclipse.jgit.revwalk.RevCommit +import javax.inject.Inject + +interface ISharedStashViewModel { + fun applyStash(stashInfo: RevCommit): Job + fun popStash(stash: RevCommit): Job + fun deleteStash(stash: RevCommit): Job + fun selectStash(stash: RevCommit): Job + fun stashDropped(stash: RevCommit): Job +} + +class SharedStashViewModel @Inject constructor( + private val applyStashUseCase: ApplyStashUseCase, + private val popStashUseCase: PopStashUseCase, + private val deleteStashUseCase: DeleteStashUseCase, + private val tabState: TabState, +) : ISharedStashViewModel { + override fun applyStash(stashInfo: RevCommit) = tabState.safeProcessing( + refreshType = RefreshType.UNCOMMITED_CHANGES_AND_LOG, + refreshEvenIfCrashes = true, + ) { git -> + applyStashUseCase(git, stashInfo) + } + + override fun popStash(stash: RevCommit) = tabState.safeProcessing( + refreshType = RefreshType.UNCOMMITED_CHANGES_AND_LOG, + refreshEvenIfCrashes = true, + ) { git -> + popStashUseCase(git, stash) + + stashDropped(stash) + } + + override fun deleteStash(stash: RevCommit) = tabState.safeProcessing( + refreshType = RefreshType.STASHES, + ) { git -> + deleteStashUseCase(git, stash) + + stashDropped(stash) + } + + override fun selectStash(stash: RevCommit) = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { + tabState.newSelectedStash(stash) + } + + override fun stashDropped(stash: RevCommit) = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { + val selectedValue = tabState.selectedItem.value + if ( + selectedValue is SelectedItem.Stash && + selectedValue.revCommit.name == stash.name + ) { + tabState.noneSelected() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/StashesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/StashesViewModel.kt index 5e1a1de7..dfd6e3e2 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/StashesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/StashesViewModel.kt @@ -8,9 +8,12 @@ import com.jetpackduba.gitnuro.git.stash.DeleteStashUseCase import com.jetpackduba.gitnuro.git.stash.GetStashListUseCase import com.jetpackduba.gitnuro.git.stash.PopStashUseCase import com.jetpackduba.gitnuro.ui.SelectedItem +import com.jetpackduba.gitnuro.viewmodels.ISharedStashViewModel +import com.jetpackduba.gitnuro.viewmodels.SharedStashViewModel import dagger.assisted.Assisted import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import org.eclipse.jgit.api.Git @@ -18,14 +21,12 @@ import org.eclipse.jgit.revwalk.RevCommit class StashesViewModel @AssistedInject constructor( private val getStashListUseCase: GetStashListUseCase, - private val applyStashUseCase: ApplyStashUseCase, - private val popStashUseCase: PopStashUseCase, - private val deleteStashUseCase: DeleteStashUseCase, private val tabState: TabState, private val tabScope: CoroutineScope, @Assisted private val filter: StateFlow, -) : SidePanelChildViewModel(true) { + sharedStashViewModel: SharedStashViewModel, +) : SidePanelChildViewModel(true), ISharedStashViewModel by sharedStashViewModel { private val stashes = MutableStateFlow>(emptyList()) val stashesState: StateFlow = combine(stashes, isExpanded, filter) { stashes, isExpanded, filter -> @@ -59,48 +60,6 @@ class StashesViewModel @AssistedInject constructor( suspend fun refresh(git: Git) { loadStashes(git) } - - fun applyStash(stashInfo: RevCommit) = tabState.safeProcessing( - refreshType = RefreshType.UNCOMMITED_CHANGES_AND_LOG, - refreshEvenIfCrashes = true, - ) { git -> - applyStashUseCase(git, stashInfo) - } - - fun popStash(stash: RevCommit) = tabState.safeProcessing( - refreshType = RefreshType.UNCOMMITED_CHANGES_AND_LOG, - refreshEvenIfCrashes = true, - ) { git -> - popStashUseCase(git, stash) - - stashDropped(stash) - } - - fun deleteStash(stash: RevCommit) = tabState.safeProcessing( - refreshType = RefreshType.STASHES, - ) { git -> - deleteStashUseCase(git, stash) - - stashDropped(stash) - } - - fun selectStash(stash: RevCommit) = tabState.runOperation( - refreshType = RefreshType.NONE, - ) { - tabState.newSelectedStash(stash) - } - - private fun stashDropped(stash: RevCommit) = tabState.runOperation( - refreshType = RefreshType.NONE, - ) { - val selectedValue = tabState.selectedItem.value - if ( - selectedValue is SelectedItem.Stash && - selectedValue.revCommit.name == stash.name - ) { - tabState.noneSelected() - } - } }