Fixed adding a new tab crashing

This commit is contained in:
Abdelilah El Aissaoui 2022-01-04 17:53:31 +01:00
parent 620fd1022b
commit e7de563b28
5 changed files with 92 additions and 70 deletions

View File

@ -10,7 +10,6 @@ import androidx.compose.material.Icon
import androidx.compose.material.IconButton import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -28,9 +27,11 @@ import app.theme.AppTheme
import app.ui.components.RepositoriesTabPanel import app.ui.components.RepositoriesTabPanel
import app.ui.components.TabInformation import app.ui.components.TabInformation
import app.ui.dialogs.SettingsDialog import app.ui.dialogs.SettingsDialog
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject import javax.inject.Inject
class Main { class App {
private val appComponent = DaggerAppComponent.create() private val appComponent = DaggerAppComponent.create()
@Inject @Inject
@ -39,84 +40,91 @@ class Main {
@Inject @Inject
lateinit var appPreferences: AppPreferences lateinit var appPreferences: AppPreferences
private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
init { init {
appComponent.inject(this) appComponent.inject(this)
println("AppStateManagerReference $appStateManager") println("AppStateManagerReference $appStateManager")
appStateManager.loadRepositoriesTabs()
} }
fun start() = application { private val tabsFlow = MutableStateFlow<List<TabInformation>>(emptyList())
var isOpen by remember { mutableStateOf(true) }
val theme by appPreferences.themeState.collectAsState()
if (isOpen) {
Window(
title = "Gitnuro",
onCloseRequest = {
isOpen = false
},
state = rememberWindowState(
placement = WindowPlacement.Maximized,
size = DpSize(1280.dp, 720.dp)
),
icon = painterResource("logo.svg"),
) {
var showSettingsDialog by remember { mutableStateOf(false) }
val tabs = mutableStateMapOf<Int, TabInformation>()
AppTheme(theme = theme) { fun start(){
Box(modifier = Modifier.background(MaterialTheme.colors.background)) { appStateManager.loadRepositoriesTabs()
AppTabs( loadTabs()
tabs = tabs,
onOpenSettings = {
showSettingsDialog = true
}
)
}
if (showSettingsDialog) { application {
SettingsDialog( var isOpen by remember { mutableStateOf(true) }
appPreferences = appPreferences, val theme by appPreferences.themeState.collectAsState()
onDismiss = { showSettingsDialog = false }
) if (isOpen) {
Window(
title = "Gitnuro",
onCloseRequest = {
isOpen = false
},
state = rememberWindowState(
placement = WindowPlacement.Maximized,
size = DpSize(1280.dp, 720.dp)
),
icon = painterResource("logo.svg"),
) {
var showSettingsDialog by remember { mutableStateOf(false) }
AppTheme(theme = theme) {
Box(modifier = Modifier.background(MaterialTheme.colors.background)) {
AppTabs(
onOpenSettings = {
showSettingsDialog = true
}
)
}
if (showSettingsDialog) {
SettingsDialog(
appPreferences = appPreferences,
onDismiss = { showSettingsDialog = false }
)
}
} }
} }
} else {
appScope.cancel("Closing app")
this.exitApplication()
} }
} }
} }
private fun loadTabs() {
val repositoriesSavedTabs = appStateManager.openRepositoriesPathsTabs
var repoTabs = repositoriesSavedTabs.map { repositoryTab ->
newAppTab(
key = repositoryTab.key,
path = repositoryTab.value
)
}
if (repoTabs.isEmpty()) {
repoTabs = listOf(
newAppTab()
)
}
tabsFlow.value = repoTabs
println("After reading prefs, got ${tabsFlow.value.count()} tabs")
}
@Composable @Composable
fun AppTabs( fun AppTabs(
tabs: SnapshotStateMap<Int, TabInformation>,
onOpenSettings: () -> Unit, onOpenSettings: () -> Unit,
) { ) {
val tabs by tabsFlow.collectAsState()
val tabsInformationList = tabs.map { it.value }.sortedBy { it.key } val tabsInformationList = tabs.sortedBy { it.key }
println("Tabs count ${tabs.count()}") println("Tabs count ${tabs.count()}")
LaunchedEffect(Unit) {
val repositoriesSavedTabs = appStateManager.openRepositoriesPathsTabs
var repoTabs = repositoriesSavedTabs.map { repositoryTab ->
newAppTab(
key = repositoryTab.key,
path = repositoryTab.value
)
}
if (repoTabs.isEmpty()) {
repoTabs = listOf(
newAppTab()
)
}
repoTabs.forEach {
tabs[it.key] = it
} // Store list of tabs in the map
println("After reading prefs, got ${tabs.count()} tabs")
}
val selectedTabKey = remember { mutableStateOf(0) } val selectedTabKey = remember { mutableStateOf(0) }
println("Selected tab key: ${selectedTabKey.value}") println("Selected tab key: ${selectedTabKey.value}")
@ -125,22 +133,36 @@ class Main {
modifier = Modifier.background(MaterialTheme.colors.background) modifier = Modifier.background(MaterialTheme.colors.background)
) { ) {
Tabs( Tabs(
tabs = tabs,
tabsInformationList = tabsInformationList, tabsInformationList = tabsInformationList,
selectedTabKey = selectedTabKey, selectedTabKey = selectedTabKey,
onOpenSettings = onOpenSettings onOpenSettings = onOpenSettings,
onAddedTab = { tabInfo ->
addTab(tabs, tabInfo)
},
onRemoveTab = { key ->
removeTab(tabs, key)
}
) )
TabsContent(tabsInformationList, selectedTabKey.value) TabsContent(tabsInformationList, selectedTabKey.value)
} }
} }
private fun removeTab(tabs: List<TabInformation>, key: Int) = appScope.launch(Dispatchers.IO) {
tabsFlow.value = tabs.filter { tab -> tab.key != key }
}
fun addTab(tabsList: List<TabInformation>, tabInformation: TabInformation) = appScope.launch(Dispatchers.IO) {
tabsFlow.value = tabsList.toMutableList().apply { add(tabInformation) }
}
@Composable @Composable
fun Tabs( fun Tabs(
tabs: SnapshotStateMap<Int, TabInformation>,
selectedTabKey: MutableState<Int>, selectedTabKey: MutableState<Int>,
onOpenSettings: () -> Unit, onOpenSettings: () -> Unit,
tabsInformationList: List<TabInformation>, tabsInformationList: List<TabInformation>,
onAddedTab: (TabInformation) -> Unit,
onRemoveTab: (Int) -> Unit,
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@ -162,13 +184,12 @@ class Main {
key = key key = key
) )
tabs[key] = newAppTab onAddedTab(newAppTab)
newAppTab newAppTab
}, },
onTabClosed = { key -> onTabClosed = { key ->
appStateManager.repositoryTabRemoved(key) appStateManager.repositoryTabRemoved(key)
tabs.remove(key) onRemoveTab(key)
} }
) )
IconButton( IconButton(

View File

@ -57,7 +57,7 @@ class AppStateManager @Inject constructor(
appPreferences.latestOpenedRepositoriesPath = Json.encodeToString(_latestOpenedRepositoriesPaths) appPreferences.latestOpenedRepositoriesPath = Json.encodeToString(_latestOpenedRepositoriesPaths)
} }
fun loadRepositoriesTabs() = appStateScope.launch(Dispatchers.IO) { fun loadRepositoriesTabs() {
val repositoriesSaved = appPreferences.latestTabsOpened val repositoriesSaved = appPreferences.latestTabsOpened
if (repositoriesSaved.isNotEmpty()) { if (repositoriesSaved.isNotEmpty()) {

View File

@ -1,13 +1,13 @@
package app.di package app.di
import app.AppStateManager import app.AppStateManager
import app.Main import app.App
import dagger.Component import dagger.Component
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
@Component @Component
interface AppComponent { interface AppComponent {
fun inject(main: Main) fun inject(main: App)
fun appStateManager(): AppStateManager fun appStateManager(): AppStateManager
} }

View File

@ -179,6 +179,7 @@ class TabInformation(
.build() .build()
tabComponent.inject(this) tabComponent.inject(this)
//TODO: This shouldn't be here, should be in the parent method
gitManager.onRepositoryChanged = { path -> gitManager.onRepositoryChanged = { path ->
if (path == null) { if (path == null) {
appStateManager.repositoryTabRemoved(key) appStateManager.repositoryTabRemoved(key)

View File

@ -1,8 +1,8 @@
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import app.Main import app.App
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
fun main() { fun main() {
val main = Main() val main = App()
main.start() main.start()
} }