Make sure changing repo starts in a clean state & implemented tab lazy loading
Changing the open repository in the current tab will now create a new tab that replaces the current one instead of updating the TabViewModel and having to make sure that every subviewmodel handles the change of repository properly. This also allowed implementing lazy loading of a tab, so it does not load every repo at the same time. Fixes #122
This commit is contained in:
parent
8462a40733
commit
60c15131db
@ -34,6 +34,17 @@ fun AppTab(
|
||||
val repositorySelectionStatusValue = repositorySelectionStatus.value
|
||||
val processingState = tabViewModel.processing.collectAsState().value
|
||||
|
||||
LaunchedEffect(tabViewModel) {
|
||||
// Init the tab content when the tab is selected and also remove the "initialPath" to avoid opening the
|
||||
// repository everytime the user changes between tabs
|
||||
val initialPath = tabViewModel.initialPath
|
||||
tabViewModel.initialPath = null
|
||||
|
||||
if (initialPath != null) {
|
||||
tabViewModel.openRepository(initialPath)
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
@ -20,6 +20,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.*
|
||||
import com.jetpackduba.gitnuro.AppConstants
|
||||
import com.jetpackduba.gitnuro.LocalTabScope
|
||||
import com.jetpackduba.gitnuro.extensions.handMouseClickable
|
||||
import com.jetpackduba.gitnuro.git.DiffEntryType
|
||||
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
|
||||
@ -137,6 +138,7 @@ fun RepositoryOpenPage(
|
||||
onCancelRebaseInteractive = { tabViewModel.cancelRebaseInteractive() }
|
||||
)
|
||||
} else {
|
||||
val currentTabInformation = LocalTabScope.current
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Menu(
|
||||
modifier = Modifier
|
||||
@ -150,7 +152,7 @@ fun RepositoryOpenPage(
|
||||
val repo = tabViewModel.openDirectoryPicker()
|
||||
|
||||
if (repo != null) {
|
||||
tabViewModel.openRepository(repo)
|
||||
tabViewModel.openAnotherRepository(repo, currentTabInformation)
|
||||
}
|
||||
},
|
||||
onQuickActions = { showQuickActionsDialog = true },
|
||||
|
@ -42,16 +42,23 @@ class TabsManager @Inject constructor(
|
||||
_currentTab.value = _tabsFlow.value.first()
|
||||
}
|
||||
|
||||
fun addNewTabFromPath(path: String, selectTab: Boolean) {
|
||||
fun addNewTabFromPath(path: String, selectTab: Boolean, tabToBeReplaced: TabInformation? = null) {
|
||||
val newTab = newAppTab(
|
||||
tabName = mutableStateOf(""),
|
||||
path = path,
|
||||
)
|
||||
|
||||
_tabsFlow.update {
|
||||
it.toMutableList().apply {
|
||||
add(newTab)
|
||||
val newTabsList = it.toMutableList()
|
||||
|
||||
if (tabToBeReplaced != null) {
|
||||
val index = newTabsList.indexOf(tabToBeReplaced)
|
||||
newTabsList[index] = newTab
|
||||
} else {
|
||||
newTabsList.add(newTab)
|
||||
}
|
||||
|
||||
newTabsList
|
||||
}
|
||||
|
||||
if (selectTab) {
|
||||
@ -116,7 +123,7 @@ class TabsManager @Inject constructor(
|
||||
}
|
||||
|
||||
private fun newAppTab(
|
||||
tabName: MutableState<String> = mutableStateOf("New tab"),
|
||||
tabName: MutableState<String> = mutableStateOf(TabInformation.DEFAULT_NAME),
|
||||
path: String? = null,
|
||||
): TabInformation {
|
||||
return TabInformation(
|
||||
|
@ -242,20 +242,34 @@ class TabInformation(
|
||||
init {
|
||||
tabComponent.inject(this)
|
||||
|
||||
tabViewModel.onRepositoryChanged = { path ->
|
||||
this.path = path
|
||||
if (initialPath != null) {
|
||||
tabName.value = Path(initialPath).name
|
||||
}
|
||||
|
||||
tabViewModel.onRepositoryChanged = { newPath ->
|
||||
this.path = newPath
|
||||
|
||||
if (newPath == null) {
|
||||
tabName.value = TabInformation.DEFAULT_NAME
|
||||
} else {
|
||||
tabName.value = Path(newPath).name
|
||||
appStateManager.repositoryTabChanged(newPath)
|
||||
}
|
||||
|
||||
tabName.value = Path(path).name
|
||||
appStateManager.repositoryTabChanged(path)
|
||||
onTabPathChanged()
|
||||
}
|
||||
if (initialPath != null)
|
||||
tabViewModel.openRepository(initialPath)
|
||||
|
||||
// Set the path that should be loaded when the tab is selected for the first time
|
||||
tabViewModel.initialPath = initialPath
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
tabViewModel.dispose()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_NAME = "New tab"
|
||||
}
|
||||
}
|
||||
|
||||
fun emptyTabInformation() = TabInformation(mutableStateOf(""), "", {}, null)
|
||||
|
@ -22,6 +22,8 @@ import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
|
||||
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
|
||||
import com.jetpackduba.gitnuro.system.PickerType
|
||||
import com.jetpackduba.gitnuro.ui.SelectedItem
|
||||
import com.jetpackduba.gitnuro.ui.TabsManager
|
||||
import com.jetpackduba.gitnuro.ui.components.TabInformation
|
||||
import com.jetpackduba.gitnuro.updates.Update
|
||||
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
||||
import kotlinx.coroutines.*
|
||||
@ -66,8 +68,10 @@ class TabViewModel @Inject constructor(
|
||||
private val abortRebaseUseCase: AbortRebaseUseCase,
|
||||
private val openFilePickerUseCase: OpenFilePickerUseCase,
|
||||
private val openUrlInBrowserUseCase: OpenUrlInBrowserUseCase,
|
||||
private val tabsManager: TabsManager,
|
||||
private val tabScope: CoroutineScope,
|
||||
) {
|
||||
var initialPath: String? = null // Stores the path that should be opened when the tab is selected
|
||||
val errorsManager: ErrorsManager = tabState.errorsManager
|
||||
val selectedItem: StateFlow<SelectedItem> = tabState.selectedItem
|
||||
var diffViewModel: DiffViewModel? = null
|
||||
@ -163,6 +167,15 @@ class TabViewModel @Inject constructor(
|
||||
rebaseInteractiveViewModel?.startRebaseInteractive(taskEvent.revCommit)
|
||||
}
|
||||
|
||||
/**
|
||||
* To make sure the tab opens the new repository with a clean state,
|
||||
* instead of opening the repo in the same ViewModel we simply create a new tab with a new TabViewModel
|
||||
* replacing the current tab
|
||||
*/
|
||||
fun openAnotherRepository(directory: String, current: TabInformation) {
|
||||
tabsManager.addNewTabFromPath(directory, true, current)
|
||||
}
|
||||
|
||||
fun openRepository(directory: String) {
|
||||
openRepository(File(directory))
|
||||
}
|
||||
@ -197,6 +210,7 @@ class TabViewModel @Inject constructor(
|
||||
|
||||
watchRepositoryChanges(git)
|
||||
} catch (ex: Exception) {
|
||||
onRepositoryChanged(null)
|
||||
ex.printStackTrace()
|
||||
errorsManager.addError(newErrorNow(ex, ex.localizedMessage))
|
||||
_repositorySelectionStatus.value = RepositorySelectionStatus.None
|
||||
@ -324,7 +338,7 @@ class TabViewModel @Inject constructor(
|
||||
credentialsStateManager.updateState(CredentialsAccepted.SshCredentialsAccepted(password))
|
||||
}
|
||||
|
||||
var onRepositoryChanged: (path: String) -> Unit = {}
|
||||
var onRepositoryChanged: (path: String?) -> Unit = {}
|
||||
|
||||
fun dispose() {
|
||||
tabScope.cancel()
|
||||
|
Loading…
Reference in New Issue
Block a user