Fixed rebase interactive check being executed when changing between tabs even if not rebasing

This commit is contained in:
Abdelilah El Aissaoui 2023-08-28 17:58:37 +02:00
parent 804b83769f
commit c78d7f1c3d
No known key found for this signature in database
GPG Key ID: 7587FC860F594869
13 changed files with 218 additions and 128 deletions

View File

@ -20,6 +20,7 @@ object AppIcons {
const val DESCRIPTION = "description.svg"
const val DONE = "done.svg"
const val DOWNLOAD = "download.svg"
const val DRAG = "drag.svg"
const val DROPDOWN = "dropdown.svg"
const val ERROR = "error.svg"
const val EXPAND_MORE = "expand_more.svg"

View File

@ -250,6 +250,17 @@ class TabState @Inject constructor(
newSelectedItem(SelectedItem.None)
}
fun newSelectedCommit(revCommit: RevCommit?) = runOperation(
refreshType = RefreshType.NONE,
) { _ ->
if (revCommit == null) {
newSelectedItem(SelectedItem.None)
} else {
val newSelectedItem = SelectedItem.Commit(revCommit)
newSelectedItem(newSelectedItem)
}
}
fun newSelectedRef(objectId: ObjectId?) = runOperation(
refreshType = RefreshType.NONE,
) { git ->

View File

@ -0,0 +1,40 @@
package com.jetpackduba.gitnuro.git.rebase
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.errors.AmbiguousObjectException
import org.eclipse.jgit.lib.AbbreviatedObjectId
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.revwalk.RevCommit
import javax.inject.Inject
class GetCommitFromRebaseLineUseCase @Inject constructor() {
operator fun invoke(git: Git, commit: AbbreviatedObjectId, shortMessage: String): RevCommit? {
val resolvedList: List<ObjectId?> = try {
listOf(git.repository.resolve("${commit.name()}^{commit}"))
} catch (ex: AmbiguousObjectException) {
ex.candidates.toList()
}
if (resolvedList.isEmpty()) {
println("Commit search failed for line $commit - $shortMessage")
return null
} else if (resolvedList.count() == 1) {
val resolvedId = resolvedList.firstOrNull()
return if (resolvedId == null)
null
else
git.repository.parseCommit(resolvedId)
} else {
println("Multiple matching commits for line $commit - $shortMessage")
for (candidateId in resolvedList) {
val candidateCommit = git.repository.parseCommit(candidateId)
if (shortMessage == candidateCommit.shortMessage)
return candidateCommit
}
println("None of the matching commits has a matching short message")
return null
}
}
}

View File

@ -3,51 +3,20 @@ package com.jetpackduba.gitnuro.git.rebase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.errors.AmbiguousObjectException
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.lib.RebaseTodoLine
import org.eclipse.jgit.revwalk.RevCommit
import javax.inject.Inject
class GetRebaseLinesFullMessageUseCase @Inject constructor() {
class GetRebaseLinesFullMessageUseCase @Inject constructor(
private val getCommitFromRebaseLineUseCase: GetCommitFromRebaseLineUseCase,
) {
suspend operator fun invoke(
git: Git,
rebaseTodoLines: List<RebaseTodoLine>,
): Map<String, String> = withContext(Dispatchers.IO) {
return@withContext rebaseTodoLines.associate { line ->
val commit = getCommitFromLine(git, line)
val commit = getCommitFromRebaseLineUseCase(git, line.commit, line.shortMessage)
val fullMessage = commit?.fullMessage ?: line.shortMessage
line.commit.name() to fullMessage
}
}
private fun getCommitFromLine(git: Git, line: RebaseTodoLine): RevCommit? {
val resolvedList: List<ObjectId?> = try {
listOf(git.repository.resolve("${line.commit.name()}^{commit}"))
} catch (ex: AmbiguousObjectException) {
ex.candidates.toList()
}
if (resolvedList.isEmpty()) {
println("Commit search failed for line ${line.commit} - ${line.shortMessage}")
return null
} else if (resolvedList.count() == 1) {
val resolvedId = resolvedList.firstOrNull()
return if (resolvedId == null)
null
else
git.repository.parseCommit(resolvedId)
} else {
println("Multiple matching commits for line ${line.commit} - ${line.shortMessage}")
for (candidateId in resolvedList) {
val candidateCommit = git.repository.parseCommit(candidateId)
if (line.shortMessage == candidateCommit.shortMessage)
return candidateCommit
}
println("None of the matching commits has a matching short message")
return null
}
}
}

View File

@ -1,32 +1,40 @@
package com.jetpackduba.gitnuro.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.ui.components.AdjustableOutlinedTextField
import com.jetpackduba.gitnuro.ui.components.PrimaryButton
import com.jetpackduba.gitnuro.ui.components.ScrollableLazyColumn
import com.jetpackduba.gitnuro.ui.components.gitnuroDynamicViewModel
import com.jetpackduba.gitnuro.theme.backgroundSelected
import com.jetpackduba.gitnuro.ui.components.*
import com.jetpackduba.gitnuro.viewmodels.RebaseAction
import com.jetpackduba.gitnuro.viewmodels.RebaseInteractiveViewState
import com.jetpackduba.gitnuro.viewmodels.RebaseInteractiveViewModel
import com.jetpackduba.gitnuro.viewmodels.RebaseInteractiveViewState
import com.jetpackduba.gitnuro.viewmodels.RebaseLine
@Composable
fun RebaseInteractive(
rebaseInteractiveViewModel: RebaseInteractiveViewModel = gitnuroDynamicViewModel(),
rebaseInteractiveViewModel: RebaseInteractiveViewModel = gitnuroViewModel(),
) {
val rebaseState = rebaseInteractiveViewModel.rebaseState.collectAsState()
val rebaseStateValue = rebaseState.value
val selectedItem by rebaseInteractiveViewModel.selectedItem.collectAsState()
LaunchedEffect(rebaseInteractiveViewModel) {
rebaseInteractiveViewModel.loadRebaseInteractiveData()
}
Box(
modifier = Modifier
@ -39,6 +47,10 @@ fun RebaseInteractive(
RebaseStateLoaded(
rebaseInteractiveViewModel,
rebaseStateValue,
selectedItem,
onFocusLine = {
rebaseInteractiveViewModel.selectLine(it)
},
onCancel = {
rebaseInteractiveViewModel.cancel()
},
@ -56,6 +68,8 @@ fun RebaseInteractive(
fun RebaseStateLoaded(
rebaseInteractiveViewModel: RebaseInteractiveViewModel,
rebaseState: RebaseInteractiveViewState.Loaded,
selectedItem: SelectedItem,
onFocusLine: (RebaseLine) -> Unit,
onCancel: () -> Unit,
) {
val stepsList = rebaseState.stepsList
@ -75,7 +89,11 @@ fun RebaseStateLoaded(
RebaseCommit(
rebaseLine = rebaseTodoLine,
message = rebaseState.messages[rebaseTodoLine.commit.name()],
isSelected = selectedItem is SelectedItem.Commit && selectedItem.revCommit.id.startsWith(
rebaseTodoLine.commit
),
isFirst = stepsList.first() == rebaseTodoLine,
onFocusLine = { onFocusLine(rebaseTodoLine) },
onActionChanged = { newAction ->
rebaseInteractiveViewModel.onCommitActionChanged(rebaseTodoLine.commit, newAction)
},
@ -114,11 +132,15 @@ fun RebaseStateLoaded(
fun RebaseCommit(
rebaseLine: RebaseLine,
isFirst: Boolean,
isSelected: Boolean,
message: String?,
onFocusLine: () -> Unit,
onActionChanged: (RebaseAction) -> Unit,
onMessageChanged: (String) -> Unit,
) {
val action = rebaseLine.rebaseAction
val focusRequester = remember { FocusRequester() }
var newMessage by remember(rebaseLine.commit.name(), action) {
if (action == RebaseAction.REWORD) {
mutableStateOf(message ?: rebaseLine.shortMessage) /* if reword, use the value from the map (if possible)*/
@ -128,20 +150,45 @@ fun RebaseCommit(
Row(
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.height(IntrinsicSize.Min)
.fillMaxWidth()
.onFocusEvent {
if (it.hasFocus) {
onFocusLine()
focusRequester.requestFocus()
}
}
.clickable { onFocusLine() }
.run {
if (isSelected) {
background(MaterialTheme.colors.backgroundSelected)
} else {
this
}
}
.padding(horizontal = 16.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
painterResource(AppIcons.DRAG),
contentDescription = "Drag line",
modifier = Modifier
.size(24.dp)
.pointerHoverIcon(resizePointerIconNorth),
)
ActionDropdown(
action,
isFirst = isFirst,
onActionDropDownClicked = onFocusLine,
onActionChanged = onActionChanged,
)
AdjustableOutlinedTextField(
modifier = Modifier
.weight(1f)
.heightIn(min = 40.dp),
.heightIn(min = 40.dp)
.focusRequester(focusRequester),
enabled = action == RebaseAction.REWORD,
value = newMessage,
onValueChange = {
@ -163,12 +210,16 @@ fun RebaseCommit(
fun ActionDropdown(
action: RebaseAction,
isFirst: Boolean,
onActionDropDownClicked: () -> Unit,
onActionChanged: (RebaseAction) -> Unit,
) {
var showDropDownMenu by remember { mutableStateOf(false) }
Box {
TextButton(
onClick = { showDropDownMenu = true },
onClick = {
showDropDownMenu = true
onActionDropDownClicked()
},
modifier = Modifier
.width(120.dp)
.height(40.dp)

View File

@ -14,10 +14,7 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.AppConstants
import com.jetpackduba.gitnuro.LocalTabScope
@ -26,7 +23,6 @@ import com.jetpackduba.gitnuro.git.DiffEntryType
import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
import com.jetpackduba.gitnuro.keybindings.matchesBinding
import com.jetpackduba.gitnuro.ui.components.PrimaryButton
import com.jetpackduba.gitnuro.ui.components.SecondaryButton
import com.jetpackduba.gitnuro.ui.components.gitnuroDynamicViewModel
import com.jetpackduba.gitnuro.ui.dialogs.*
@ -40,7 +36,6 @@ import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi
import org.jetbrains.compose.splitpane.HorizontalSplitPane
import org.jetbrains.compose.splitpane.SplitterScope
import org.jetbrains.compose.splitpane.rememberSplitPaneState
import java.awt.Cursor
@Composable
fun RepositoryOpenPage(
@ -54,7 +49,6 @@ fun RepositoryOpenPage(
val blameState by tabViewModel.blameState.collectAsState()
val showHistory by tabViewModel.showHistory.collectAsState()
val showAuthorInfo by tabViewModel.showAuthorInfo.collectAsState()
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
var showNewBranchDialog by remember { mutableStateOf(false) }
var showStashWithMessageDialog by remember { mutableStateOf(false) }
@ -131,39 +125,35 @@ fun RepositoryOpenPage(
}
}
) {
if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction) {
RebaseInteractive()
} else {
val currentTabInformation = LocalTabScope.current
Column(modifier = Modifier.weight(1f)) {
Menu(
modifier = Modifier
.padding(
vertical = 4.dp
)
.fillMaxWidth(),
onCreateBranch = { showNewBranchDialog = true },
onStashWithMessage = { showStashWithMessageDialog = true },
onOpenAnotherRepository = {
val repo = tabViewModel.openDirectoryPicker()
val currentTabInformation = LocalTabScope.current
Column(modifier = Modifier.weight(1f)) {
Menu(
modifier = Modifier
.padding(
vertical = 4.dp
)
.fillMaxWidth(),
onCreateBranch = { showNewBranchDialog = true },
onStashWithMessage = { showStashWithMessageDialog = true },
onOpenAnotherRepository = {
val repo = tabViewModel.openDirectoryPicker()
if (repo != null) {
tabViewModel.openAnotherRepository(repo, currentTabInformation)
}
},
onQuickActions = { showQuickActionsDialog = true },
onShowSettingsDialog = onShowSettingsDialog
)
if (repo != null) {
tabViewModel.openAnotherRepository(repo, currentTabInformation)
}
},
onQuickActions = { showQuickActionsDialog = true },
onShowSettingsDialog = onShowSettingsDialog
)
RepoContent(
tabViewModel = tabViewModel,
diffSelected = diffSelected,
selectedItem = selectedItem,
repositoryState = repositoryState,
blameState = blameState,
showHistory = showHistory,
)
}
RepoContent(
tabViewModel = tabViewModel,
diffSelected = diffSelected,
selectedItem = selectedItem,
repositoryState = repositoryState,
blameState = blameState,
showHistory = showHistory,
)
}
}
}
@ -179,31 +169,6 @@ fun RepositoryOpenPage(
}
}
@Composable
fun RebaseInteractiveStartedExternally(
onCancelRebaseInteractive: () -> Unit,
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
"Rebase interactive started externally or Gitnuro (or this repository's tab)\nhas been restarted during the rebase.",
textAlign = TextAlign.Center,
fontWeight = FontWeight.Medium,
style = MaterialTheme.typography.body1,
)
PrimaryButton(
modifier = Modifier.padding(top = 8.dp),
text = "Abort rebase interactive",
onClick = onCancelRebaseInteractive,
backgroundColor = MaterialTheme.colors.error,
textColor = MaterialTheme.colors.onError,
)
}
}
@Composable
private fun BottomInfoBar(tabViewModel: TabViewModel) {
val userInfo by tabViewModel.authorInfoSimple.collectAsState()
@ -288,10 +253,19 @@ fun MainContentView(
repositoryState: RepositoryState,
blameState: BlameState,
) {
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
println("Rebase interactive state is $rebaseInteractiveState")
HorizontalSplitPane(
splitPaneState = rememberSplitPaneState(initialPositionPercentage = 0.20f)
) {
first(minSize = 180.dp) {
val size = if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction)
1.dp
else
180.dp
first(minSize = size) {
SidePanel()
}
@ -308,7 +282,9 @@ fun MainContentView(
modifier = Modifier
.fillMaxSize()
) {
if (blameState is BlameState.Loaded && !blameState.isMinimized) {
if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction) {
RebaseInteractive()
} else if (blameState is BlameState.Loaded && !blameState.isMinimized) {
Blame(
filePath = blameState.filePath,
blameResult = blameState.blameResult,
@ -391,6 +367,7 @@ fun MainContentView(
onHistoryFile = { tabViewModel.fileHistory(it) }
)
}
is SelectedItem.CommitBasedItem -> {
CommitChanges(
selectedItem = selectedItem,
@ -403,6 +380,7 @@ fun MainContentView(
onHistory = { tabViewModel.fileHistory(it) },
)
}
SelectedItem.None -> {}
}
}
@ -425,7 +403,7 @@ fun SplitterScope.repositorySplitter() {
Box(
Modifier
.markAsHandle()
.pointerHoverIcon(PointerIcon(Cursor(Cursor.E_RESIZE_CURSOR)))
.pointerHoverIcon(resizePointerIconEast)
.background(Color.Transparent)
.width(8.dp)
.fillMaxHeight()

View File

@ -0,0 +1,7 @@
package com.jetpackduba.gitnuro.ui
import androidx.compose.ui.input.pointer.PointerIcon
import java.awt.Cursor
val resizePointerIconEast = PointerIcon(Cursor(Cursor.E_RESIZE_CURSOR))
val resizePointerIconNorth = PointerIcon(Cursor(Cursor.N_RESIZE_CURSOR))

View File

@ -50,6 +50,7 @@ import com.jetpackduba.gitnuro.ui.dialogs.NewBranchDialog
import com.jetpackduba.gitnuro.ui.dialogs.NewTagDialog
import com.jetpackduba.gitnuro.ui.dialogs.ResetBranchDialog
import com.jetpackduba.gitnuro.ui.dialogs.SetDefaultUpstreamBranchDialog
import com.jetpackduba.gitnuro.ui.resizePointerIconEast
import com.jetpackduba.gitnuro.viewmodels.LogSearch
import com.jetpackduba.gitnuro.viewmodels.LogStatus
import com.jetpackduba.gitnuro.viewmodels.LogViewModel
@ -917,7 +918,7 @@ fun DividerLog(modifier: Modifier, graphWidth: Dp) {
.padding(start = graphWidth)
.width(DIVIDER_WIDTH.dp)
.then(modifier)
.pointerHoverIcon(PointerIcon(Cursor(Cursor.E_RESIZE_CURSOR)))
.pointerHoverIcon(resizePointerIconEast)
) {
Box(
modifier = Modifier

View File

@ -333,7 +333,7 @@ class LogViewModel @Inject constructor(
fun selectLogLine(commit: GraphNode) = tabState.runOperation(
refreshType = RefreshType.NONE,
) {
tabState.newSelectedItem(SelectedItem.Commit(commit))
tabState.newSelectedCommit(commit)
val searchValue = _logSearchFilterResults.value
if (searchValue is LogSearch.SearchResults) {

View File

@ -5,13 +5,13 @@ import com.jetpackduba.gitnuro.exceptions.RebaseCancelledException
import com.jetpackduba.gitnuro.git.RefreshType
import com.jetpackduba.gitnuro.git.TabState
import com.jetpackduba.gitnuro.git.rebase.*
import com.jetpackduba.gitnuro.git.repository.GetRepositoryStateUseCase
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler
import org.eclipse.jgit.lib.AbbreviatedObjectId
import org.eclipse.jgit.lib.RebaseTodoLine
import org.eclipse.jgit.lib.RebaseTodoLine.Action
import org.eclipse.jgit.revwalk.RevCommit
import javax.inject.Inject
private const val TAG = "RebaseInteractiveViewMo"
@ -19,18 +19,17 @@ private const val TAG = "RebaseInteractiveViewMo"
class RebaseInteractiveViewModel @Inject constructor(
private val tabState: TabState,
private val getRebaseLinesFullMessageUseCase: GetRebaseLinesFullMessageUseCase,
private val getCommitFromRebaseLineUseCase: GetCommitFromRebaseLineUseCase,
private val getRebaseInteractiveTodoLinesUseCase: GetRebaseInteractiveTodoLinesUseCase,
private val abortRebaseUseCase: AbortRebaseUseCase,
private val resumeRebaseInteractiveUseCase: ResumeRebaseInteractiveUseCase,
private val getRepositoryStateUseCase: GetRepositoryStateUseCase,
) {
private lateinit var commit: RevCommit
private val _rebaseState = MutableStateFlow<RebaseInteractiveViewState>(RebaseInteractiveViewState.Loading)
val rebaseState: StateFlow<RebaseInteractiveViewState> = _rebaseState
var rewordSteps = ArrayDeque<RebaseLine>()
init {
loadRebaseInteractiveData()
}
val selectedItem = tabState.selectedItem
var rewordSteps = ArrayDeque<RebaseLine>()
private var interactiveHandlerContinue = object : InteractiveHandler {
override fun prepareSteps(steps: MutableList<RebaseTodoLine>) {
@ -64,9 +63,16 @@ class RebaseInteractiveViewModel @Inject constructor(
}
}
private fun loadRebaseInteractiveData() = tabState.safeProcessing(
fun loadRebaseInteractiveData() = tabState.safeProcessing(
refreshType = RefreshType.NONE,
) { git ->
val state = getRepositoryStateUseCase(git)
if (!state.isRebasing) {
_rebaseState.value = RebaseInteractiveViewState.Loading
return@safeProcessing
}
try {
val lines = getRebaseInteractiveTodoLinesUseCase(git)
val messages = getRebaseLinesFullMessageUseCase(tabState.git, lines)
@ -78,7 +84,17 @@ class RebaseInteractiveViewModel @Inject constructor(
)
}
_rebaseState.value = RebaseInteractiveViewState.Loaded(rebaseLines, messages)
val isSameRebase = isSameRebase(rebaseLines, _rebaseState.value)
if (!isSameRebase) {
_rebaseState.value = RebaseInteractiveViewState.Loaded(rebaseLines, messages)
val firstLine = rebaseLines.firstOrNull()
if (firstLine != null) {
val fullCommit = getCommitFromRebaseLineUseCase(git, firstLine.commit, firstLine.shortMessage)
tabState.newSelectedCommit(fullCommit)
}
}
} catch (ex: Exception) {
if (ex is RebaseCancelledException) {
@ -90,10 +106,25 @@ class RebaseInteractiveViewModel @Inject constructor(
}
}
private fun isSameRebase(rebaseLines: List<RebaseLine>, state: RebaseInteractiveViewState): Boolean {
if (state is RebaseInteractiveViewState.Loaded) {
val stepsList = state.stepsList
if (rebaseLines.count() != stepsList.count()) {
return false
}
return rebaseLines.map { it.commit.name() } == stepsList.map { it.commit.name() }
}
return false
}
fun continueRebaseInteractive() = tabState.safeProcessing(
refreshType = RefreshType.ALL_DATA,
) { git ->
resumeRebaseInteractiveUseCase(git, interactiveHandlerContinue)
_rebaseState.value = RebaseInteractiveViewState.Loading
}
fun onCommitMessageChanged(commit: AbbreviatedObjectId, message: String) {
@ -139,6 +170,12 @@ class RebaseInteractiveViewModel @Inject constructor(
refreshType = RefreshType.ALL_DATA,
) { git ->
abortRebaseUseCase(git)
_rebaseState.value = RebaseInteractiveViewState.Loading
}
fun selectLine(line: RebaseLine) = tabState.safeProcessing(refreshType = RefreshType.NONE) { git ->
val fullCommit = getCommitFromRebaseLineUseCase(git, line.commit, line.shortMessage)
tabState.newSelectedCommit(fullCommit)
}
}

View File

@ -397,13 +397,7 @@ class TabViewModel @Inject constructor(
fun selectCommit(commit: RevCommit) = tabState.runOperation(
refreshType = RefreshType.NONE,
) {
tabState.newSelectedItem(SelectedItem.Commit(commit))
}
fun selectUncommitedChanges() = tabState.runOperation(
refreshType = RefreshType.NONE,
) {
tabState.newSelectedItem(SelectedItem.UncommitedChanges, true)
tabState.newSelectedCommit(commit)
}
fun fileHistory(filePath: String) {

View File

@ -16,9 +16,9 @@ class TabViewModelsHolder @Inject constructor(
cloneViewModel: CloneViewModel,
settingsViewModel: SettingsViewModel,
sidePanelViewModel: SidePanelViewModel,
rebaseInteractiveViewModel: RebaseInteractiveViewModel,
// Dynamic VM
private val diffViewModelProvider: Provider<DiffViewModel>,
private val rebaseInteractiveViewModelProvider: Provider<RebaseInteractiveViewModel>,
private val historyViewModelProvider: Provider<HistoryViewModel>,
private val authorViewModelProvider: Provider<AuthorViewModel>,
private val changeDefaultUpstreamBranchViewModelProvider: Provider<ChangeDefaultUpstreamBranchViewModel>,
@ -33,13 +33,13 @@ class TabViewModelsHolder @Inject constructor(
commitChangesViewModel::class to commitChangesViewModel,
cloneViewModel::class to cloneViewModel,
settingsViewModel::class to settingsViewModel,
rebaseInteractiveViewModel::class to rebaseInteractiveViewModel,
)
// TODO Call this when required
fun dynamicViewModel(type: KClass<*>): Any {
return when(type) {
DiffViewModel::class -> diffViewModelProvider.get()
RebaseInteractiveViewModel::class -> rebaseInteractiveViewModelProvider.get()
HistoryViewModel::class -> historyViewModelProvider.get()
AuthorViewModel::class -> authorViewModelProvider.get()
ChangeDefaultUpstreamBranchViewModel::class -> changeDefaultUpstreamBranchViewModelProvider.get()

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M160-390v-60h640v60H160Zm0-120v-60h640v60H160Z"/></svg>

After

Width:  |  Height:  |  Size: 152 B