Changed side panel headers to be expandables and improved its UI
This commit is contained in:
parent
09d4184c40
commit
832189e91e
@ -2,12 +2,7 @@ package app.ui
|
|||||||
|
|
||||||
import androidx.compose.foundation.ContextMenuArea
|
import androidx.compose.foundation.ContextMenuArea
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
@ -16,9 +11,7 @@ import androidx.compose.ui.res.painterResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.extensions.isLocal
|
import app.extensions.isLocal
|
||||||
import app.extensions.simpleName
|
import app.extensions.simpleName
|
||||||
import app.maxSidePanelHeight
|
import app.ui.components.SideMenuPanel
|
||||||
import app.ui.components.ScrollableLazyColumn
|
|
||||||
import app.ui.components.SideMenuEntry
|
|
||||||
import app.ui.components.SideMenuSubentry
|
import app.ui.components.SideMenuSubentry
|
||||||
import app.ui.context_menu.branchContextMenuItems
|
import app.ui.context_menu.branchContextMenuItems
|
||||||
import app.ui.dialogs.MergeDialog
|
import app.ui.dialogs.MergeDialog
|
||||||
@ -35,29 +28,21 @@ fun Branches(
|
|||||||
val currentBranch by branchesViewModel.currentBranch.collectAsState()
|
val currentBranch by branchesViewModel.currentBranch.collectAsState()
|
||||||
val (mergeBranch, setMergeBranch) = remember { mutableStateOf<Ref?>(null) }
|
val (mergeBranch, setMergeBranch) = remember { mutableStateOf<Ref?>(null) }
|
||||||
val (rebaseBranch, setRebaseBranch) = remember { mutableStateOf<Ref?>(null) }
|
val (rebaseBranch, setRebaseBranch) = remember { mutableStateOf<Ref?>(null) }
|
||||||
val maxHeight = remember(branches) { maxSidePanelHeight(branches.count()) }
|
|
||||||
|
|
||||||
Column {
|
SideMenuPanel(
|
||||||
SideMenuEntry("Local branches")
|
title = "Local branches",
|
||||||
|
icon = painterResource("branch.svg"),
|
||||||
ScrollableLazyColumn(
|
items = branches
|
||||||
modifier = Modifier
|
) { branch ->
|
||||||
.fillMaxWidth()
|
BranchLineEntry(
|
||||||
.heightIn(max = maxHeight.dp)
|
branch = branch,
|
||||||
.background(MaterialTheme.colors.background)
|
isCurrentBranch = currentBranch == branch.name,
|
||||||
) {
|
onBranchClicked = { onBranchClicked(branch) },
|
||||||
itemsIndexed(branches) { _, branch ->
|
onCheckoutBranch = { branchesViewModel.checkoutRef(branch) },
|
||||||
BranchLineEntry(
|
onMergeBranch = { setMergeBranch(branch) },
|
||||||
branch = branch,
|
onDeleteBranch = { branchesViewModel.deleteBranch(branch) },
|
||||||
isCurrentBranch = currentBranch == branch.name,
|
onRebaseBranch = { setRebaseBranch(branch) },
|
||||||
onBranchClicked = { onBranchClicked(branch) },
|
)
|
||||||
onCheckoutBranch = { branchesViewModel.checkoutRef(branch) },
|
|
||||||
onMergeBranch = { setMergeBranch(branch) },
|
|
||||||
onDeleteBranch = { branchesViewModel.deleteBranch(branch) },
|
|
||||||
onRebaseBranch = { setRebaseBranch(branch) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mergeBranch != null) {
|
if (mergeBranch != null) {
|
||||||
|
@ -1,48 +1,36 @@
|
|||||||
package app.ui
|
package app.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.material.MaterialTheme
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.extensions.simpleVisibleName
|
import app.extensions.simpleVisibleName
|
||||||
import app.git.RemoteInfo
|
import app.git.RemoteInfo
|
||||||
import app.maxSidePanelHeight
|
import app.ui.components.SideMenuPanel
|
||||||
import app.ui.components.ScrollableLazyColumn
|
|
||||||
import app.ui.components.SideMenuEntry
|
|
||||||
import app.ui.components.SideMenuSubentry
|
import app.ui.components.SideMenuSubentry
|
||||||
import app.viewmodels.RemotesViewModel
|
import app.viewmodels.RemotesViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Remotes(remotesViewModel: RemotesViewModel) {
|
fun Remotes(remotesViewModel: RemotesViewModel) {
|
||||||
val remotes by remotesViewModel.remotes.collectAsState()
|
val remotes by remotesViewModel.remotes.collectAsState()
|
||||||
val allBranches = remotes.map { it.branchesList }.flatten()
|
|
||||||
val maxHeight = remember(remotes) { maxSidePanelHeight(allBranches.count() + remotes.count()) }
|
|
||||||
|
|
||||||
Column {
|
val itemsCount = remember(remotes) {
|
||||||
SideMenuEntry("Remotes")
|
val allBranches = remotes.map { it.branchesList }.flatten()
|
||||||
|
allBranches.count() + remotes.count()
|
||||||
ScrollableLazyColumn(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.heightIn(max = maxHeight.dp)
|
|
||||||
.background(MaterialTheme.colors.background)
|
|
||||||
) {
|
|
||||||
items(remotes) { remote ->
|
|
||||||
RemoteRow(
|
|
||||||
remote = remote,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideMenuPanel(
|
||||||
|
title = "Remotes",
|
||||||
|
icon = painterResource("cloud.svg"),
|
||||||
|
items = remotes,
|
||||||
|
itemsCountForMaxHeight = itemsCount,
|
||||||
|
itemContent = { remoteInfo ->
|
||||||
|
RemoteRow(remoteInfo)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -10,10 +10,12 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.maxSidePanelHeight
|
import app.maxSidePanelHeight
|
||||||
import app.ui.components.ScrollableLazyColumn
|
import app.ui.components.ScrollableLazyColumn
|
||||||
import app.ui.components.SideMenuEntry
|
import app.ui.components.SideMenuEntry
|
||||||
|
import app.ui.components.SideMenuPanel
|
||||||
import app.ui.components.SideMenuSubentry
|
import app.ui.components.SideMenuSubentry
|
||||||
import app.viewmodels.StashStatus
|
import app.viewmodels.StashStatus
|
||||||
import app.viewmodels.StashesViewModel
|
import app.viewmodels.StashesViewModel
|
||||||
@ -32,29 +34,18 @@ fun Stashes(
|
|||||||
else
|
else
|
||||||
listOf()
|
listOf()
|
||||||
|
|
||||||
val maxHeight = remember(stashList) { maxSidePanelHeight(stashList.count()) }
|
|
||||||
|
|
||||||
Column {
|
SideMenuPanel(
|
||||||
SideMenuEntry(
|
title = "Stashes",
|
||||||
text = "Stashes",
|
icon = painterResource("stash.svg"),
|
||||||
)
|
items = stashList,
|
||||||
|
itemContent = { stashInfo ->
|
||||||
ScrollableLazyColumn(
|
StashRow(
|
||||||
modifier = Modifier
|
stash = stashInfo,
|
||||||
.fillMaxWidth()
|
onClick = { onStashSelected(stashInfo) }
|
||||||
.heightIn(max = maxHeight.dp)
|
)
|
||||||
.background(MaterialTheme.colors.background)
|
|
||||||
) {
|
|
||||||
items(items = stashList) { stash ->
|
|
||||||
StashRow(
|
|
||||||
stash = stash,
|
|
||||||
onClick = {
|
|
||||||
onStashSelected(stash)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,11 +12,13 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.extensions.simpleName
|
import app.extensions.simpleName
|
||||||
import app.maxSidePanelHeight
|
import app.maxSidePanelHeight
|
||||||
import app.ui.components.ScrollableLazyColumn
|
import app.ui.components.ScrollableLazyColumn
|
||||||
import app.ui.components.SideMenuEntry
|
import app.ui.components.SideMenuEntry
|
||||||
|
import app.ui.components.SideMenuPanel
|
||||||
import app.ui.components.SideMenuSubentry
|
import app.ui.components.SideMenuSubentry
|
||||||
import app.ui.context_menu.tagContextMenuItems
|
import app.ui.context_menu.tagContextMenuItems
|
||||||
import app.viewmodels.TagsViewModel
|
import app.viewmodels.TagsViewModel
|
||||||
@ -29,31 +31,20 @@ fun Tags(
|
|||||||
) {
|
) {
|
||||||
val tagsState = tagsViewModel.tags.collectAsState()
|
val tagsState = tagsViewModel.tags.collectAsState()
|
||||||
val tags = tagsState.value
|
val tags = tagsState.value
|
||||||
val maxHeight = remember(tags) { maxSidePanelHeight(tags.count()) }
|
|
||||||
|
|
||||||
Column {
|
SideMenuPanel(
|
||||||
SideMenuEntry(
|
title = "Tags",
|
||||||
text = "Tags",
|
items = tags,
|
||||||
)
|
icon = painterResource("tag.svg"),
|
||||||
|
itemContent = { tag ->
|
||||||
ScrollableLazyColumn(
|
TagRow(
|
||||||
modifier = Modifier
|
tag = tag,
|
||||||
.fillMaxWidth()
|
onTagClicked = { onTagClicked(tag) },
|
||||||
.heightIn(max = maxHeight.dp)
|
onCheckoutTag = { tagsViewModel.checkoutRef(tag) },
|
||||||
.background(MaterialTheme.colors.background)
|
onDeleteTag = { tagsViewModel.deleteTag(tag) }
|
||||||
) {
|
)
|
||||||
items(items = tags) { tag ->
|
|
||||||
TagRow(
|
|
||||||
tag = tag,
|
|
||||||
onTagClicked = { onTagClicked(tag) },
|
|
||||||
onCheckoutTag = { tagsViewModel.checkoutRef(tag) },
|
|
||||||
onDeleteTag = { tagsViewModel.deleteTag(tag) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
35
src/main/kotlin/app/ui/components/Expandable.kt
Normal file
35
src/main/kotlin/app/ui/components/Expandable.kt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package app.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAnimationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun VerticalExpandable(
|
||||||
|
header: @Composable () -> Unit,
|
||||||
|
child: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
var isExpanded by remember {
|
||||||
|
mutableStateOf(true)
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
isExpanded = !isExpanded
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
header()
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(visible = isExpanded) {
|
||||||
|
child()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,15 +1,15 @@
|
|||||||
package app.ui.components
|
package app.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@ -20,6 +20,8 @@ import app.theme.secondaryTextColor
|
|||||||
@Composable
|
@Composable
|
||||||
fun SideMenuEntry(
|
fun SideMenuEntry(
|
||||||
text: String,
|
text: String,
|
||||||
|
icon: Painter? = null,
|
||||||
|
itemsCount: Int,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -28,14 +30,34 @@ fun SideMenuEntry(
|
|||||||
.background(color = MaterialTheme.colors.headerBackground),
|
.background(color = MaterialTheme.colors.headerBackground),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
if(icon != null) {
|
||||||
|
Icon(
|
||||||
|
painter = icon,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colors.primaryTextColor,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 8.dp)
|
||||||
|
.size(16.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp)
|
||||||
|
.weight(1f),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = MaterialTheme.colors.primaryTextColor,
|
color = MaterialTheme.colors.primaryTextColor,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = itemsCount.toString(),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = MaterialTheme.colors.secondaryTextColor,
|
||||||
|
modifier = Modifier.padding(end = 8.dp),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
48
src/main/kotlin/app/ui/components/SideMenuPanel.kt
Normal file
48
src/main/kotlin/app/ui/components/SideMenuPanel.kt
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package app.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import app.maxSidePanelHeight
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun <T> SideMenuPanel(
|
||||||
|
title: String,
|
||||||
|
icon: Painter? = null,
|
||||||
|
items: List<T>,
|
||||||
|
itemsCountForMaxHeight: Int = items.count(),
|
||||||
|
itemContent: @Composable (T) -> Unit,
|
||||||
|
) {
|
||||||
|
val maxHeight = remember(items) { maxSidePanelHeight(itemsCountForMaxHeight) }
|
||||||
|
|
||||||
|
VerticalExpandable(
|
||||||
|
header = {
|
||||||
|
SideMenuEntry(
|
||||||
|
text = title,
|
||||||
|
icon = icon,
|
||||||
|
itemsCount = items.count()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
ScrollableLazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.heightIn(max = maxHeight.dp)
|
||||||
|
.background(MaterialTheme.colors.background)
|
||||||
|
) {
|
||||||
|
items(items) { item ->
|
||||||
|
itemContent(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user