Added basic tabs support

This commit is contained in:
Abdelilah El Aissaoui 2021-10-04 19:55:03 +02:00
parent 1433c0f601
commit 68917c40c9
4 changed files with 269 additions and 8 deletions

View File

@ -1,7 +1,8 @@
package git
import credentials.CredentialsState
import credentials.CredentialsStateManager import kotlinx.coroutines.*
import credentials.CredentialsStateManager
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import org.eclipse.jgit.api.Git
@ -15,6 +16,8 @@ import java.io.File
class GitManager {
val repositoryName: String
get() = safeGit.repository.directory.parentFile.name
private val preferences = GPreferences()
private val statusManager = StatusManager()
private val logManager = LogManager()
@ -71,7 +74,8 @@ class GitManager {
return git
}
init {
fun loadLatestOpenedRepository() {
val latestOpenedRepositoryPath = preferences.latestOpenedRepositoryPath
if (latestOpenedRepositoryPath.isNotEmpty()) {
openRepository(File(latestOpenedRepositoryPath))

View File

@ -1,12 +1,21 @@
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
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.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.painter.Painter
@ -15,18 +24,19 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.*
import androidx.compose.ui.zIndex
import git.GitManager
import git.RepositorySelectionStatus
import theme.*
import ui.RepositoryOpenPage
import ui.WelcomePage
import ui.components.RepositoriesTabPanel
import ui.components.TabInformation
import javax.swing.JFileChooser
@OptIn(ExperimentalComposeUiApi::class)
fun main() = application {
var isOpen by remember { mutableStateOf(true) }
val gitManager = GitManager()
if (isOpen) {
Window(
title = "Gitnuro",
@ -36,18 +46,87 @@ fun main() = application {
state = rememberWindowState(placement = WindowPlacement.Maximized, size = WindowSize(1280.dp, 720.dp))
) {
GitnuroTheme {
Gitnuro(gitManager)
val tabs = remember {
val tabName = mutableStateOf("New tab")
mutableStateOf(
listOf(
TabInformation(tabName, key = 0) {
Gitnuro(false, tabName)
},
)
)
}
var selectedTabKey by remember { mutableStateOf(0) }
Column {
RepositoriesTabPanel(
modifier = Modifier
.padding(top = 4.dp, bottom = 2.dp, start = 4.dp, end = 4.dp)
.fillMaxWidth(),
tabs = tabs.value,
selectedTabKey = selectedTabKey,
onTabSelected = { newSelectedTabKey ->
selectedTabKey = newSelectedTabKey
},
newTabContent = { tabName ->
Gitnuro(true, tabName)
},
onTabsUpdated = { tabInformationList ->
tabs.value = tabInformationList
}
)
LazyColumn(
modifier = Modifier
.fillMaxSize()
.background(Color.Cyan)
) {
items(items = tabs.value, key = { it.key }) {
val isItemSelected = it.key == selectedTabKey
var tabMod: Modifier = if (!isItemSelected)
Modifier.size(0.dp)
else
Modifier
.fillParentMaxSize()
tabMod = tabMod.background(MaterialTheme.colors.primary)
.alpha(if (isItemSelected) 1f else -1f)
.zIndex(if (isItemSelected) 1f else -1f)
Box(
modifier = tabMod,
) {
it.content()
}
}
}
}
}
}
}
}
@Composable
fun Gitnuro(gitManager: GitManager) {
fun Gitnuro(isNewTab: Boolean, tabName: MutableState<String>) {
val gitManager = remember {
GitManager().apply {
if (!isNewTab)
loadLatestOpenedRepository()
}
}
val repositorySelectionStatus by gitManager.repositorySelectionStatus.collectAsState()
if (repositorySelectionStatus is RepositorySelectionStatus.Open) {
tabName.value = gitManager.repositoryName
}
Column(
modifier = Modifier.background(MaterialTheme.colors.background)
modifier = Modifier
.background(MaterialTheme.colors.background)
.fillMaxSize()
) {
GMenu(
onRepositoryOpen = {

View File

@ -32,6 +32,26 @@ fun WelcomePage() {
Text("Open repository")
}
Button(onClick = {}) {
Image(
painter = painterResource("open.svg"),
contentDescription = null,
colorFilter = ColorFilter.tint(contentColorFor(MaterialTheme.colors.primary))
)
Text("Clone repository")
}
Button(onClick = {}) {
Image(
painter = painterResource("open.svg"),
contentDescription = null,
colorFilter = ColorFilter.tint(contentColorFor(MaterialTheme.colors.primary))
)
Text("Init a new repository")
}
}
}
}

View File

@ -0,0 +1,158 @@
package ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
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.graphics.Color
import androidx.compose.ui.unit.dp
import theme.primaryLight
@Composable
fun RepositoriesTabPanel(
modifier: Modifier = Modifier,
tabs: List<TabInformation>,
selectedTabKey: Int,
onTabSelected: (Int) -> Unit,
onTabsUpdated: (List<TabInformation>) -> Unit,
newTabContent: @Composable (tabTitle: MutableState<String>) -> Unit,
) {
var tabsIdentifier by remember { mutableStateOf(0) }
TabPanel(
modifier = modifier,
onNewTabClicked = {
val tabsCopy = tabs.toMutableList()
tabsIdentifier++
val tabName = mutableStateOf("New tab")
tabsCopy.add(
TabInformation(tabName, key = tabsIdentifier) {
newTabContent(tabName)
}
)
onTabSelected(tabsIdentifier)
onTabsUpdated(tabsCopy)
}
) {
tabs.forEach { tab ->
Tab(
title = tab.title,
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) {
0
} else if (tabs.count() >= 2)
index - 1
else
-1
val tabsCopy = tabs.toMutableList()
tabsCopy.remove(tab)
val nextKey = if (nextIndex >= 0)
tabsCopy[nextIndex].key
else
-1
if (isTabSelected) {
if (nextKey >= 0) {
onTabSelected(nextKey)
} else {
tabsIdentifier++
val tabName = mutableStateOf("New tab")
tabsCopy.add(
TabInformation(tabName, key = tabsIdentifier) {
newTabContent(tabName)
}
)
onTabSelected(tabsIdentifier)
}
}
onTabsUpdated(tabsCopy)
}
)
}
}
}
@Composable
fun TabPanel(
modifier: Modifier = Modifier,
onNewTabClicked: () -> Unit,
tabs: @Composable RowScope.() -> Unit
) {
Row(modifier = modifier) {
this.tabs()
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) {
Card {
Box(
modifier = Modifier
.padding(horizontal = 1.dp)
.height(36.dp)
.clip(RoundedCornerShape(5.dp))
.background(if (selected) MaterialTheme.colors.primary else primaryLight)
.clickable { onClick() },
) {
Text(
text = title.value,
modifier = Modifier
.padding(vertical = 8.dp, horizontal = 32.dp),
color = contentColorFor(MaterialTheme.colors.primary),
)
IconButton(
onClick = onCloseTab,
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(horizontal = 8.dp)
.size(16.dp)
) {
Icon(Icons.Default.Close, contentDescription = null, tint = Color.White)
}
}
}
}
class TabInformation(
val title: MutableState<String>,
val key: Int,
val content: @Composable () -> Unit
)