Gitnuro/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt
Abdelilah El Aissaoui 6ca1e15ce8 UI improvements
2022-01-31 15:15:05 +01:00

203 lines
6.1 KiB
Kotlin

package app.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import app.AppStateManager
import app.di.AppComponent
import app.di.DaggerTabComponent
import app.theme.primaryTextColor
import app.viewmodels.TabViewModel
import app.theme.tabColorActive
import app.theme.tabColorInactive
import app.ui.AppTab
import javax.inject.Inject
import kotlin.io.path.Path
import kotlin.io.path.name
@Composable
fun RepositoriesTabPanel(
modifier: Modifier = Modifier,
tabs: List<TabInformation>,
selectedTabKey: Int,
onTabSelected: (Int) -> Unit,
onTabClosed: (Int) -> Unit,
newTabContent: (key: Int) -> TabInformation,
) {
var tabsIdentifier by remember {
mutableStateOf(tabs.count())
}
TabPanel(
modifier = modifier,
onNewTabClicked = {
tabsIdentifier++
newTabContent(tabsIdentifier)
onTabSelected(tabsIdentifier)
}
) {
items(items = tabs) { tab ->
Tab(
title = tab.tabName,
selected = tab.key == selectedTabKey,
onClick = {
onTabSelected(tab.key)
},
onCloseTab = {
val isTabSelected = selectedTabKey == tab.key
val index = tabs.indexOf(tab)
val nextIndex = if (index == 0 && tabs.count() >= 2) {
1 // If the first tab is selected, select the next one
} else if (index == tabs.count() -1 && tabs.count() >= 2)
index - 1 // If the last tab is selected, select the previous one
else if (tabs.count() >= 2)
index + 1 // If any in between tab is selected, select the next one
else
-1 // If there aren't any additional tabs once we remove this one
val nextKey = if (nextIndex >= 0)
tabs[nextIndex].key
else
-1
if (isTabSelected) {
if (nextKey >= 0) {
onTabSelected(nextKey)
} else {
tabsIdentifier++
// Create a new tab if the tabs list is empty after removing the current one
newTabContent(tabsIdentifier)
onTabSelected(tabsIdentifier)
}
}
onTabClosed(tab.key)
}
)
}
}
}
@Composable
fun TabPanel(
modifier: Modifier = Modifier,
onNewTabClicked: () -> Unit,
tabs: LazyListScope.() -> Unit
) {
LazyRow(
modifier = modifier,
) {
this.tabs()
item {
IconButton(
onClick = onNewTabClicked,
modifier = Modifier
.size(36.dp),
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
tint = MaterialTheme.colors.primary
)
}
}
}
}
@Composable
fun Tab(title: MutableState<String>, selected: Boolean, onClick: () -> Unit, onCloseTab: () -> Unit) {
val elevation = if(selected) {
3.dp
} else
0.dp
Box {
val backgroundColor = if (selected)
MaterialTheme.colors.tabColorActive
else
MaterialTheme.colors.tabColorInactive
Box(
modifier = Modifier
.width(180.dp)
.shadow(elevation = elevation)
.padding(start = 2.dp, end = 2.dp, top = 2.dp)
.clip(RoundedCornerShape(topStart = 8.dp, topEnd = 8.dp))
.clickable { onClick() }
.background(backgroundColor),
) {
Text(
text = title.value,
modifier = Modifier
.padding(vertical = 8.dp, horizontal = 16.dp),
color = contentColorFor(backgroundColor),
)
IconButton(
onClick = onCloseTab,
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(horizontal = 8.dp)
.size(14.dp)
) {
Icon(Icons.Default.Close, contentDescription = null, tint = MaterialTheme.colors.primaryTextColor)
}
}
}
}
class TabInformation(
val tabName: MutableState<String>,
val key: Int,
val path: String?,
appComponent: AppComponent,
) {
@Inject
lateinit var tabViewModel: TabViewModel
@Inject
lateinit var appStateManager: AppStateManager
val content: @Composable (TabInformation) -> Unit
init {
val tabComponent = DaggerTabComponent.builder()
.appComponent(appComponent)
.build()
tabComponent.inject(this)
//TODO: This shouldn't be here, should be in the parent method
tabViewModel.onRepositoryChanged = { path ->
if (path == null) {
appStateManager.repositoryTabRemoved(key)
} else {
tabName.value = Path(path).name
appStateManager.repositoryTabChanged(key, path)
}
}
if(path != null)
tabViewModel.openRepository(path)
content = {
AppTab(tabViewModel)
}
}
}