Added basic tabs support
This commit is contained in:
parent
1433c0f601
commit
68917c40c9
@ -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))
|
||||
|
@ -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 = {
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
158
src/main/kotlin/ui/components/RepositoriesTabPanel.kt
Normal file
158
src/main/kotlin/ui/components/RepositoriesTabPanel.kt
Normal 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
|
||||
)
|
Loading…
Reference in New Issue
Block a user