You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.3 KiB
163 lines
5.3 KiB
package org.calculate.taigamobile.ui.screens.projectselector
|
|
|
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
import androidx.compose.foundation.Image
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.lazy.LazyItemScope
|
|
import androidx.compose.material3.*
|
|
import androidx.compose.runtime.*
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.graphics.Color
|
|
import androidx.compose.ui.graphics.ColorFilter
|
|
import androidx.compose.ui.res.painterResource
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import androidx.navigation.NavController
|
|
import androidx.paging.compose.LazyPagingItems
|
|
import org.calculate.taigamobile.R
|
|
import org.calculate.taigamobile.domain.entities.Project
|
|
import org.calculate.taigamobile.ui.components.editors.SelectorList
|
|
import org.calculate.taigamobile.ui.components.editors.SelectorListConstants
|
|
import org.calculate.taigamobile.ui.theme.TaigaMobileTheme
|
|
import org.calculate.taigamobile.ui.components.containers.ContainerBox
|
|
import org.calculate.taigamobile.ui.utils.subscribeOnError
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.launch
|
|
import retrofit2.http.Header
|
|
|
|
@Composable
|
|
fun ProjectSelectorScreen(
|
|
navController: NavController,
|
|
showMessage: (message: Int) -> Unit = {},
|
|
) {
|
|
val viewModel: ProjectSelectorViewModel = viewModel()
|
|
LaunchedEffect(Unit) {
|
|
viewModel.onOpen()
|
|
}
|
|
val coroutineScope = rememberCoroutineScope()
|
|
|
|
val projects = viewModel.projects
|
|
projects.subscribeOnError(showMessage)
|
|
|
|
val currentProjectId by viewModel.currentProjectId.collectAsState()
|
|
|
|
var isSelectorVisible by remember { mutableStateOf(true) }
|
|
val selectorAnimationDuration = SelectorListConstants.defaultAnimDurationMillis
|
|
|
|
fun navigateBack() = coroutineScope.launch {
|
|
isSelectorVisible = false
|
|
delay(selectorAnimationDuration.toLong())
|
|
navController.popBackStack()
|
|
}
|
|
|
|
ProjectSelectorScreenContent(
|
|
projects = projects,
|
|
isVisible = isSelectorVisible,
|
|
currentProjectId = currentProjectId,
|
|
selectorAnimationDuration = selectorAnimationDuration,
|
|
navigateBack = ::navigateBack,
|
|
searchProjects = { viewModel.searchProjects(it) },
|
|
selectProject = {
|
|
viewModel.selectProject(it)
|
|
navigateBack()
|
|
}
|
|
)
|
|
|
|
}
|
|
|
|
@OptIn(ExperimentalFoundationApi::class)
|
|
@Composable
|
|
fun ProjectSelectorScreenContent(
|
|
projects: LazyPagingItems<Project>? = null,
|
|
isVisible: Boolean = false,
|
|
currentProjectId: Long = -1,
|
|
selectorAnimationDuration: Int = SelectorListConstants.defaultAnimDurationMillis,
|
|
navigateBack: () -> Unit = {},
|
|
searchProjects: (String) -> Unit = {},
|
|
selectProject: (Project) -> Unit = {}
|
|
) = Box(
|
|
Modifier.fillMaxSize(),
|
|
contentAlignment = Alignment.TopStart
|
|
) {
|
|
if (projects == null) return@Box
|
|
|
|
SelectorList(
|
|
titleHintId = R.string.search_projects_hint,
|
|
itemsLazy = projects,
|
|
isVisible = isVisible,
|
|
searchData = searchProjects,
|
|
navigateBack = navigateBack,
|
|
animationDurationMillis = selectorAnimationDuration
|
|
) {
|
|
ItemProject(
|
|
project = it,
|
|
currentProjectId = currentProjectId,
|
|
onClick = { selectProject(it) }
|
|
)
|
|
}
|
|
}
|
|
|
|
@OptIn(ExperimentalFoundationApi::class)
|
|
@Composable
|
|
private fun ItemProject(
|
|
project: Project,
|
|
currentProjectId: Long,
|
|
onClick: () -> Unit = {}
|
|
) = ContainerBox(
|
|
verticalPadding = 16.dp,
|
|
onClick = onClick
|
|
) {
|
|
Row(
|
|
modifier = Modifier.fillMaxSize(),
|
|
horizontalArrangement = Arrangement.SpaceBetween,
|
|
verticalAlignment = Alignment.CenterVertically
|
|
) {
|
|
|
|
|
|
Column(Modifier.weight(0.8f)) {
|
|
project.takeIf { it.isMember || it.isAdmin || it.isOwner }?.let {
|
|
Text(
|
|
style = MaterialTheme.typography.bodyMedium,
|
|
color = MaterialTheme.colorScheme.primary,
|
|
text = stringResource(
|
|
when {
|
|
project.isOwner -> R.string.project_owner
|
|
project.isAdmin -> R.string.project_admin
|
|
project.isMember -> R.string.project_member
|
|
else -> 0
|
|
}
|
|
)
|
|
)
|
|
}
|
|
|
|
Text(
|
|
text = stringResource(R.string.project_name_template).format(
|
|
project.name,
|
|
project.slug
|
|
)
|
|
)
|
|
}
|
|
|
|
|
|
if (project.id == currentProjectId) {
|
|
Image(
|
|
painter = painterResource(R.drawable.ic_check),
|
|
contentDescription = null,
|
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary),
|
|
modifier = Modifier.weight(0.2f)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Preview(showBackground = true, backgroundColor = 0xFFFFFFFF)
|
|
@Composable
|
|
fun ProjectSelectorScreenPreview() = TaigaMobileTheme {
|
|
ProjectSelectorScreenContent(isVisible = true)
|
|
}
|
|
|