Gitnuro/src/main/kotlin/com/jetpackduba/gitnuro/ui/TabsManager.kt
2024-08-02 22:33:30 +02:00

160 lines
4.7 KiB
Kotlin

package com.jetpackduba.gitnuro.ui
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import com.jetpackduba.gitnuro.di.AppComponent
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
import com.jetpackduba.gitnuro.ui.components.TabInformation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TabsManager @Inject constructor(
private val appSettingsRepository: AppSettingsRepository
) {
lateinit var appComponent: AppComponent
private val _tabsFlow = MutableStateFlow<List<TabInformation>>(emptyList())
val tabsFlow: StateFlow<List<TabInformation>> = _tabsFlow
private val _currentTab = MutableStateFlow<TabInformation?>(null)
val currentTab: StateFlow<TabInformation?> = _currentTab
fun loadPersistedTabs() {
val repositoriesSaved = appSettingsRepository.latestTabsOpened
val repositoriesList = if (repositoriesSaved.isNotEmpty())
Json.decodeFromString<List<String>>(repositoriesSaved).map { path ->
newAppTab(
path = path,
)
}
else
listOf()
_tabsFlow.value = repositoriesList.ifEmpty { listOf(newAppTab()) }
val latestSelectedTabIndex = appSettingsRepository.latestRepositoryTabSelected
_currentTab.value = when(latestSelectedTabIndex < 0) {
true -> tabsFlow.value.first()
false -> tabsFlow.value.getOrNull(latestSelectedTabIndex) ?: tabsFlow.value.first()
}
}
fun addNewTabFromPath(path: String, selectTab: Boolean, tabToBeReplacedPath: String? = null) {
val tabToBeReplaced = tabsFlow.value.firstOrNull { it.path == tabToBeReplacedPath }
val newTab = newAppTab(
tabName = mutableStateOf(""),
path = path,
)
_tabsFlow.update {
val newTabsList = it.toMutableList()
if (tabToBeReplaced != null) {
val index = newTabsList.indexOf(tabToBeReplaced)
newTabsList[index] = newTab
} else {
newTabsList.add(newTab)
}
newTabsList
}
if (selectTab) {
_currentTab.value = newTab
}
}
fun selectTab(tab: TabInformation) {
_currentTab.value = tab
persistTabSelected(tab)
}
private fun persistTabSelected(tab: TabInformation) {
appSettingsRepository.latestRepositoryTabSelected = tabsFlow.value.indexOf(tab)
}
fun closeTab(tab: TabInformation) {
val tabsList = _tabsFlow.value.toMutableList()
var newCurrentTab: TabInformation? = null
tab.tabViewModel.dispose()
if (currentTab.value == tab) {
val index = tabsList.indexOf(tab)
if (tabsList.count() == 1) {
newCurrentTab = newAppTab()
} else if (index > 0) {
newCurrentTab = tabsList[index - 1]
} else if (index == 0) {
newCurrentTab = tabsList[1]
}
}
tab.dispose()
tabsList.remove(tab)
if (newCurrentTab != null) {
if (!tabsList.contains(newCurrentTab)) {
tabsList.add(newCurrentTab)
}
_tabsFlow.value = tabsList
_currentTab.value = newCurrentTab
} else {
_tabsFlow.value = tabsList
}
updatePersistedTabs()
}
private fun updatePersistedTabs() {
val tabs = tabsFlow.value.filter { it.path != null }
appSettingsRepository.latestTabsOpened = Json.encodeToString(tabs.map { it.path })
appSettingsRepository.latestRepositoryTabSelected = tabs.indexOf(currentTab.value)
}
fun addNewEmptyTab() {
val newTab = newAppTab()
_tabsFlow.update {
it.toMutableList().apply {
add(newTab)
}
}
_currentTab.value = newTab
}
private fun newAppTab(
tabName: MutableState<String> = mutableStateOf(TabInformation.DEFAULT_NAME),
path: String? = null,
): TabInformation {
return TabInformation(
tabName = tabName,
initialPath = path,
onTabPathChanged = { updatePersistedTabs() },
appComponent = appComponent,
)
}
fun onMoveTab(fromIndex: Int, toIndex: Int) {
_tabsFlow.update {
it.toMutableList().apply {
add(toIndex, removeAt(fromIndex))
}
}
updatePersistedTabs()
}
}