Gitnuro/src/main/kotlin/app/ui/WelcomePage.kt

316 lines
9.4 KiB
Kotlin

@file:OptIn(ExperimentalComposeUiApi::class)
package app.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.AppConstants
import app.AppStateManager
import app.extensions.dirName
import app.extensions.dirPath
import app.extensions.openUrlInBrowser
import app.theme.primaryTextColor
import app.theme.secondaryTextColor
import app.theme.textButtonColors
import app.ui.dialogs.AppInfoDialog
import app.ui.dialogs.CloneDialog
import app.updates.Update
import app.viewmodels.TabViewModel
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun WelcomePage(
tabViewModel: TabViewModel,
) {
val appStateManager = tabViewModel.appStateManager
var showCloneView by remember { mutableStateOf(false) }
var showAdditionalInfo by remember { mutableStateOf(false) }
var newUpdate by remember { mutableStateOf<Update?>(null) }
LaunchedEffect(Unit) {
val latestRelease = tabViewModel.latestRelease()
if (latestRelease != null && latestRelease.appCode > AppConstants.APP_VERSION_CODE) {
newUpdate = latestRelease
}
}
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background),
) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.Top,
modifier = Modifier.align(BiasAlignment(0f, -0.5f))
) {
HomeButtons(
newUpdate = newUpdate,
tabViewModel = tabViewModel,
onShowCloneView = { showCloneView = true },
onShowAdditionalInfo = { showAdditionalInfo = true },
)
RecentRepositories(appStateManager, tabViewModel)
}
Text(
"Version ${AppConstants.APP_VERSION}",
color = MaterialTheme.colors.primaryTextColor,
fontSize = 12.sp,
maxLines = 1,
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(bottom = 16.dp, end = 16.dp)
)
}
LaunchedEffect(showCloneView) {
if (showCloneView) {
tabViewModel.cloneViewModel.reset() // Reset dialog before showing it
}
}
if (showCloneView) {
CloneDialog(
tabViewModel.cloneViewModel,
onClose = {
showCloneView = false
tabViewModel.cloneViewModel.reset()
},
onOpenRepository = { dir ->
tabViewModel.openRepository(dir)
},
)
}
if (showAdditionalInfo) {
AppInfoDialog(
onClose = { showAdditionalInfo = false },
)
}
}
@Composable
fun HomeButtons(
newUpdate: Update?,
tabViewModel: TabViewModel,
onShowCloneView: () -> Unit,
onShowAdditionalInfo: () -> Unit,
) {
Column(
modifier = Modifier.padding(end = 32.dp),
) {
Text(
text = AppConstants.APP_NAME,
fontSize = 32.sp,
maxLines = 1,
color = MaterialTheme.colors.primaryTextColor,
modifier = Modifier.padding(bottom = 16.dp),
)
ButtonTile(
modifier = Modifier.padding(bottom = 8.dp),
title = "Open a repository",
painter = painterResource("open.svg"),
onClick = { openRepositoryDialog(tabViewModel) })
ButtonTile(
modifier = Modifier.padding(bottom = 8.dp),
title = "Clone a repository",
painter = painterResource("download.svg"),
onClick = onShowCloneView
)
ButtonTile(
modifier = Modifier.padding(bottom = 8.dp),
title = "Start a local repository",
painter = painterResource("open.svg"),
onClick = {
val dir = openDirectoryDialog()
if (dir != null) tabViewModel.initLocalRepository(dir)
}
)
Text(
text = "About Gitnuro",
fontSize = 18.sp,
color = MaterialTheme.colors.primaryTextColor,
modifier = Modifier.padding(top = 16.dp, bottom = 8.dp),
)
IconTextButton(
title = "Source code",
painter = painterResource("code.svg"),
onClick = {
openUrlInBrowser("https://github.com/JetpackDuba/Gitnuro")
}
)
IconTextButton(
title = "Report a bug",
painter = painterResource("bug.svg"),
onClick = {
openUrlInBrowser("https://github.com/JetpackDuba/Gitnuro/issues")
}
)
IconTextButton(
title = "Additional information",
painter = painterResource("info.svg"),
onClick = onShowAdditionalInfo
)
if (newUpdate != null) {
IconTextButton(
title = "New update ${newUpdate.appVersion} available ",
painter = painterResource("grade.svg"),
iconColor = MaterialTheme.colors.secondary,
onClick = {
openUrlInBrowser(newUpdate.downloadUrl)
}
)
}
}
}
@Composable
fun RecentRepositories(appStateManager: AppStateManager, tabViewModel: TabViewModel) {
Column(
modifier = Modifier
.padding(start = 32.dp),
) {
val latestOpenedRepositoriesPaths = appStateManager.latestOpenedRepositoriesPaths
Text(
text = "Recent",
fontSize = 18.sp,
modifier = Modifier.padding(top = 48.dp, bottom = 8.dp),
color = MaterialTheme.colors.primaryTextColor,
)
if (latestOpenedRepositoriesPaths.isEmpty()) {
Text(
"Nothing to see here, open a repository first!",
color = MaterialTheme.colors.secondaryTextColor,
fontSize = 14.sp,
modifier = Modifier.padding(top = 16.dp)
)
} else {
LazyColumn {
items(items = latestOpenedRepositoriesPaths) { repo ->
val repoDirName = repo.dirName
val repoDirPath = repo.dirPath
Row(
verticalAlignment = Alignment.CenterVertically,
) {
TextButton(
onClick = {
tabViewModel.openRepository(repo)
},
colors = textButtonColors(),
) {
Text(
text = repoDirName,
fontSize = 14.sp,
maxLines = 1,
)
}
Text(
text = repoDirPath,
fontSize = 14.sp,
modifier = Modifier.padding(start = 4.dp),
maxLines = 1,
color = MaterialTheme.colors.secondaryTextColor
)
}
}
}
}
}
}
@Composable
fun ButtonTile(
modifier: Modifier = Modifier,
title: String,
painter: Painter,
onClick: () -> Unit,
) {
OutlinedButton(
onClick = onClick,
modifier = modifier.size(width = 280.dp, height = 56.dp)
) {
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
modifier = Modifier
.padding(end = 8.dp)
.size(24.dp),
painter = painter,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colors.primaryVariant),
)
Text(
text = title,
maxLines = 1,
color = MaterialTheme.colors.primaryVariant,
)
}
}
}
@Composable
fun IconTextButton(
modifier: Modifier = Modifier,
title: String,
painter: Painter,
iconColor: Color = MaterialTheme.colors.primaryVariant,
onClick: () -> Unit,
) {
TextButton(
onClick = onClick,
modifier = modifier.size(width = 280.dp, height = 40.dp),
colors = textButtonColors(),
) {
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
modifier = Modifier.padding(end = 8.dp).size(24.dp),
painter = painter,
contentDescription = null,
colorFilter = ColorFilter.tint(iconColor),
)
Text(
text = title,
maxLines = 1,
)
}
}
}