Changed side panel headers to be expandables and improved its UI

This commit is contained in:
Abdelilah El Aissaoui 2022-02-03 14:47:25 +01:00
parent 09d4184c40
commit 832189e91e
7 changed files with 166 additions and 106 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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)
}
)
}
} }
} )
} }

View File

@ -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)

View 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()
}
}
}

View File

@ -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),
)
} }
} }

View 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)
}
}
}
}