Added additional info dialog

This commit is contained in:
Abdelilah El Aissaoui 2022-04-04 18:32:06 +02:00
parent d85574fe6a
commit 27e8efcaf7
7 changed files with 210 additions and 24 deletions

View File

@ -34,7 +34,7 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
kapt("com.google.dagger:dagger-compiler:2.41") kapt("com.google.dagger:dagger-compiler:2.41")
testImplementation(platform("org.junit:junit-bom:5.8.2")) testImplementation(platform("org.junit:junit-bom:5.8.2"))
testImplementation("org.junit.jupiter:junit-jupiter") testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")
testImplementation("io.mockk:mockk:1.12.3") testImplementation("io.mockk:mockk:1.12.3")
implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-scalars:2.9.0") implementation("com.squareup.retrofit2:converter-scalars:2.9.0")

View File

@ -1,8 +1,30 @@
package app package app
object AppConstants { object AppConstants {
val openSourceProjects = listOf(
Project("Apache SSHD", "https://mina.apache.org/sshd-project/", apache__2_0),
Project("Google/Dagger", "https://dagger.dev/", apache__2_0),
Project("Jetbrains Compose", "https://www.jetbrains.com/lp/compose-mpp/", apache__2_0),
Project("JGit", "https://www.eclipse.org/jgit/", edl),
Project("JUnit 5", "https://junit.org/junit5/", edl),
Project("Kotlin", "https://kotlinlang.org/", apache__2_0),
Project("Kotlinx.serialization", "https://kotlinlang.org/docs/serialization.html#example-json-serialization", apache__2_0),
Project("Mockk", "https://mockk.io/", apache__2_0),
Project("Retrofit2", "https://square.github.io/retrofit/", apache__2_0),
)
// Remember to update build.gradle when changing this // Remember to update build.gradle when changing this
const val APP_NAME = "Gitnuro"
const val APP_DESCRIPTION = "Gitnuro is a Git client that allows you to manage multiple repositories with a modern experience and live visual representation of your repository's state."
const val APP_VERSION = "0.1.0" const val APP_VERSION = "0.1.0"
const val APP_VERSION_CODE = 1 const val APP_VERSION_CODE = 1
const val VERSION_CHECK_URL = "https://raw.githubusercontent.com/JetpackDuba/Gitnuro/main/latest.json" const val VERSION_CHECK_URL = "https://raw.githubusercontent.com/JetpackDuba/Gitnuro/main/latest.json"
} }
private val apache__2_0 = License("Apache 2.0", "https://www.apache.org/licenses/LICENSE-2.0")
private val edl = License("EDL", "https://www.eclipse.org/org/documents/edl-v10.php")
data class License(val name: String, val url: String)
data class Project(val name: String, val url: String, val license: License)

View File

@ -1,7 +1,13 @@
package app.extensions package app.extensions
import java.awt.Desktop
import java.net.URI
import java.nio.file.FileSystems import java.nio.file.FileSystems
val systemSeparator: String by lazy { val systemSeparator: String by lazy {
FileSystems.getDefault().separator FileSystems.getDefault().separator
} }
fun openUrlInBrowser(url: String) {
Desktop.getDesktop().browse(URI(url))
}

View File

@ -23,15 +23,15 @@ import app.AppConstants
import app.AppStateManager import app.AppStateManager
import app.extensions.dirName import app.extensions.dirName
import app.extensions.dirPath import app.extensions.dirPath
import app.extensions.openUrlInBrowser
import app.theme.primaryTextColor import app.theme.primaryTextColor
import app.theme.secondaryTextColor import app.theme.secondaryTextColor
import app.ui.dialogs.AppInfoDialog
import app.ui.dialogs.CloneDialog import app.ui.dialogs.CloneDialog
import app.updates.Update import app.updates.Update
import app.viewmodels.TabViewModel import app.viewmodels.TabViewModel
import openDirectoryDialog import openDirectoryDialog
import openRepositoryDialog import openRepositoryDialog
import java.awt.Desktop
import java.net.URI
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@ -41,12 +41,13 @@ fun WelcomePage(
) { ) {
val appStateManager = tabViewModel.appStateManager val appStateManager = tabViewModel.appStateManager
var showCloneView by remember { mutableStateOf(false) } var showCloneView by remember { mutableStateOf(false) }
var showAdditionalInfo by remember { mutableStateOf(false) }
var newUpdate by remember { mutableStateOf<Update?>(null) } var newUpdate by remember { mutableStateOf<Update?>(null) }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
val latestRelease = tabViewModel.latestRelease() val latestRelease = tabViewModel.latestRelease()
if(latestRelease != null && latestRelease.appCode > AppConstants.APP_VERSION_CODE) { if (latestRelease != null && latestRelease.appCode > AppConstants.APP_VERSION_CODE) {
newUpdate = latestRelease newUpdate = latestRelease
} }
} }
@ -64,9 +65,8 @@ fun WelcomePage(
HomeButtons( HomeButtons(
newUpdate = newUpdate, newUpdate = newUpdate,
tabViewModel = tabViewModel, tabViewModel = tabViewModel,
onShowCloneView = { onShowCloneView = { showCloneView = true },
showCloneView = true onShowAdditionalInfo = { showAdditionalInfo = true },
}
) )
RecentRepositories(appStateManager, tabViewModel) RecentRepositories(appStateManager, tabViewModel)
@ -83,11 +83,13 @@ fun WelcomePage(
} }
LaunchedEffect(showCloneView) { LaunchedEffect(showCloneView) {
if (showCloneView) tabViewModel.cloneViewModel.reset() // Reset dialog before showing it if (showCloneView) {
tabViewModel.cloneViewModel.reset() // Reset dialog before showing it
}
} }
if (showCloneView) {
if (showCloneView) CloneDialog( CloneDialog(
tabViewModel.cloneViewModel, tabViewModel.cloneViewModel,
onClose = { onClose = {
showCloneView = false showCloneView = false
@ -97,6 +99,13 @@ fun WelcomePage(
tabViewModel.openRepository(dir) tabViewModel.openRepository(dir)
}, },
) )
}
if (showAdditionalInfo) {
AppInfoDialog(
onClose = { showAdditionalInfo = false },
)
}
} }
@Composable @Composable
@ -104,6 +113,7 @@ fun HomeButtons(
newUpdate: Update?, newUpdate: Update?,
tabViewModel: TabViewModel, tabViewModel: TabViewModel,
onShowCloneView: () -> Unit, onShowCloneView: () -> Unit,
onShowAdditionalInfo: () -> Unit,
) { ) {
Column( Column(
modifier = Modifier.padding(end = 32.dp), modifier = Modifier.padding(end = 32.dp),
@ -149,7 +159,7 @@ fun HomeButtons(
title = "Source code", title = "Source code",
painter = painterResource("code.svg"), painter = painterResource("code.svg"),
onClick = { onClick = {
Desktop.getDesktop().browse(URI("https://github.com/JetpackDuba/Gitnuro")) openUrlInBrowser("https://github.com/JetpackDuba/Gitnuro")
} }
) )
@ -157,17 +167,23 @@ fun HomeButtons(
title = "Report a bug", title = "Report a bug",
painter = painterResource("bug.svg"), painter = painterResource("bug.svg"),
onClick = { onClick = {
Desktop.getDesktop().browse(URI("https://github.com/JetpackDuba/Gitnuro/issues")) openUrlInBrowser("https://github.com/JetpackDuba/Gitnuro/issues")
} }
) )
if(newUpdate != null) { IconTextButton(
title = "Additional information",
painter = painterResource("info.svg"),
onClick = onShowAdditionalInfo
)
if (newUpdate != null) {
IconTextButton( IconTextButton(
title = "New update ${newUpdate.appVersion} available ", title = "New update ${newUpdate.appVersion} available ",
painter = painterResource("grade.svg"), painter = painterResource("grade.svg"),
iconColor = MaterialTheme.colors.secondary, iconColor = MaterialTheme.colors.secondary,
onClick = { onClick = {
Desktop.getDesktop().browse(URI(newUpdate.downloadUrl)) openUrlInBrowser(newUpdate.downloadUrl)
} }
) )
} }
@ -188,7 +204,7 @@ fun RecentRepositories(appStateManager: AppStateManager, tabViewModel: TabViewMo
color = MaterialTheme.colors.primaryTextColor, color = MaterialTheme.colors.primaryTextColor,
) )
if(latestOpenedRepositoriesPaths.isEmpty()) { if (latestOpenedRepositoriesPaths.isEmpty()) {
Text( Text(
"Nothing to see here, open a repository first!", "Nothing to see here, open a repository first!",
color = MaterialTheme.colors.secondaryTextColor, color = MaterialTheme.colors.secondaryTextColor,

View File

@ -0,0 +1,42 @@
package app.ui.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.hoverable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import app.extensions.openUrlInBrowser
import app.theme.primaryTextColor
@Composable
fun TextLink(
text: String,
url: String,
modifier: Modifier = Modifier,
colorsInverted: Boolean = false,
) {
val hoverInteraction = remember { MutableInteractionSource() }
val isHovered by hoverInteraction.collectIsHoveredAsState()
val textColor = if (isHovered == colorsInverted) {
MaterialTheme.colors.primaryTextColor
} else {
MaterialTheme.colors.primary
}
Text(
text = text,
modifier = Modifier
.hoverable(hoverInteraction)
.clickable {
openUrlInBrowser(url)
}
.then(modifier),
color = textColor,
)
}

View File

@ -0,0 +1,99 @@
package app.ui.dialogs
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.AppConstants
import app.AppConstants.openSourceProjects
import app.Project
import app.theme.primaryTextColor
import app.ui.components.ScrollableLazyColumn
import app.ui.components.TextLink
@Composable
fun AppInfoDialog(
onClose: () -> Unit,
) {
MaterialDialog {
Column(
modifier = Modifier
.width(600.dp)
.height(600.dp)
) {
ScrollableLazyColumn(
modifier = Modifier
.weight(1f)
) {
item {
Column(modifier = Modifier.padding(16.dp)) {
Text(
AppConstants.APP_NAME,
fontSize = 24.sp,
color = MaterialTheme.colors.primaryTextColor,
)
Text(
AppConstants.APP_DESCRIPTION,
fontSize = 14.sp,
color = MaterialTheme.colors.primaryTextColor,
modifier = Modifier.padding(top = 16.dp)
)
Text(
"Gitnuro has been possible thanks to the following open source projects:",
fontSize = 14.sp,
color = MaterialTheme.colors.primaryTextColor,
modifier = Modifier.padding(vertical = 16.dp)
)
}
}
items(openSourceProjects) {
ProjectUsed(it)
}
}
TextButton(
modifier = Modifier
.padding(top = 16.dp, end = 8.dp)
.align(Alignment.End),
onClick = onClose
) {
Text("Close")
}
}
}
}
@Composable
fun ProjectUsed(project: Project) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 16.dp)
) {
TextLink(
text = project.name,
url = project.url,
modifier = Modifier
.padding(vertical = 8.dp)
)
Spacer(Modifier.weight(1f))
TextLink(
text = project.license.name,
url = project.license.url,
modifier = Modifier
.padding(vertical = 8.dp),
colorsInverted = true
)
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>

After

Width:  |  Height:  |  Size: 253 B