From 67d410fd1207a2652640b8bfcadf9a98770646ca Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Fri, 24 Sep 2021 16:46:01 +0200 Subject: [PATCH] Added author to commit and UI improvements --- src/main/kotlin/CommitChanges.kt | 176 ++++++++++++++++++ src/main/kotlin/RepositorySelected.kt | 79 +------- .../extensions/InputStreamExtensions.kt | 12 ++ .../kotlin/extensions/StringExtensions.kt | 10 + src/main/kotlin/theme/Color.kt | 4 +- src/main/kotlin/theme/Theme.kt | 3 +- src/main/resources/image.jpg | Bin 0 -> 5658 bytes 7 files changed, 206 insertions(+), 78 deletions(-) create mode 100644 src/main/kotlin/CommitChanges.kt create mode 100644 src/main/kotlin/extensions/InputStreamExtensions.kt create mode 100644 src/main/kotlin/extensions/StringExtensions.kt create mode 100644 src/main/resources/image.jpg diff --git a/src/main/kotlin/CommitChanges.kt b/src/main/kotlin/CommitChanges.kt new file mode 100644 index 0000000..780d96c --- /dev/null +++ b/src/main/kotlin/CommitChanges.kt @@ -0,0 +1,176 @@ +import androidx.compose.foundation.* +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.res.useResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import extensions.filePath +import extensions.icon +import extensions.md5 +import extensions.toByteArray +import kotlinx.coroutines.* +import org.eclipse.jgit.diff.DiffEntry +import org.eclipse.jgit.revwalk.RevCommit +import org.jetbrains.skija.Image.makeFromEncoded +import theme.backgroundColorLight +import theme.primaryTextColor +import java.net.HttpURLConnection +import java.net.URL + +@Composable +fun CommitChanges(commitDiff: Pair>, onDiffSelected: (DiffEntry) -> Unit) { + val commit = commitDiff.first + val diff = commitDiff.second + + Column( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colors.background), + ) { + Column( + modifier = Modifier + .padding(all = 8.dp) + .fillMaxWidth(), + ) { + val scroll = rememberScrollState(0) + Text( + text = commit.fullMessage, + modifier = Modifier + .padding(8.dp) + .fillMaxWidth() + .background(MaterialTheme.colors.surface) + .height(120.dp) + .verticalScroll(scroll), + + ) + + Card( + modifier = Modifier + .padding(horizontal = 8.dp, vertical = 8.dp) + .fillMaxWidth() + .height(72.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + val url = "https://www.gravatar.com/avatar/${commit.authorIdent.emailAddress.md5}" + Image( + bitmap = rememberNetworkImage(url), + modifier = Modifier + .padding(horizontal = 16.dp) + .height(40.dp) + .clip(CircleShape), + contentDescription = null, + ) + + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.Center + ) { + Text(commit.authorIdent.name) + } + } + + } + + + } + + + CommitLogChanges(diff, onDiffSelected = onDiffSelected) + } +} + +suspend fun loadImage(link: String): ByteArray = withContext(Dispatchers.IO) { + val url = URL(link) + val connection = url.openConnection() as HttpURLConnection + connection.connect() + + connection.inputStream.toByteArray() +} + +@Composable +fun rememberNetworkImage(url: String): ImageBitmap { + var image by remember(url) { + mutableStateOf( + useResource("image.jpg") { + makeFromEncoded(it.toByteArray()).asImageBitmap() + } + ) + } + + LaunchedEffect(url) { + loadImage(url).let { + image = makeFromEncoded(it).asImageBitmap() + } + } + + return image +} + +@Composable +fun CommitLogChanges(diffEntries: List, onDiffSelected: (DiffEntry) -> Unit) { + val selectedIndex = remember(diffEntries) { mutableStateOf(-1) } + + LazyColumn( + modifier = Modifier + .background(backgroundColorLight) + .fillMaxSize() + ) { + itemsIndexed(items = diffEntries) { index, diffEntry -> + val textColor = if (selectedIndex.value == index) { + MaterialTheme.colors.primary + } else + MaterialTheme.colors.primaryTextColor + + Column( + modifier = Modifier + .height(56.dp) + .fillMaxWidth() + .clickable { + selectedIndex.value = index + onDiffSelected(diffEntry) + }, + verticalArrangement = Arrangement.Center, + ) { + Spacer(modifier = Modifier.weight(2f)) + + + Row { + Icon( + modifier = Modifier + .padding(start = 16.dp) + .size(24.dp), + imageVector = diffEntry.icon, + contentDescription = null, + tint = MaterialTheme.colors.primary, + ) + + Text( + text = diffEntry.filePath, + modifier = Modifier.padding(horizontal = 16.dp), + color = textColor, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + + Spacer(modifier = Modifier.weight(2f)) + + Divider() + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/RepositorySelected.kt b/src/main/kotlin/RepositorySelected.kt index d227e5f..b3a115e 100644 --- a/src/main/kotlin/RepositorySelected.kt +++ b/src/main/kotlin/RepositorySelected.kt @@ -13,10 +13,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import extensions.filePath -import extensions.icon import git.LogStatus import org.eclipse.jgit.api.Git import org.eclipse.jgit.diff.DiffEntry @@ -26,7 +24,7 @@ import org.eclipse.jgit.revwalk.RevTree import org.eclipse.jgit.revwalk.RevWalk import org.eclipse.jgit.treewalk.AbstractTreeIterator import org.eclipse.jgit.treewalk.CanonicalTreeParser -import theme.backgroundColor +import theme.backgroundColorLight import theme.primaryTextColor import theme.secondaryTextColor import java.io.IOException @@ -170,22 +168,6 @@ fun prepareTreeParser(repository: Repository, commit: RevCommit): AbstractTreeIt } } -@Composable -fun CommitChanges(commitDiff: Pair>, onDiffSelected: (DiffEntry) -> Unit) { - val commit = commitDiff.first - val diff = commitDiff.second - - Column( - modifier = Modifier - .fillMaxSize(), - ) { - Text(commit.fullMessage) - Text(commit.commitTime.toString()) - - CommitLogChanges(diff, onDiffSelected = onDiffSelected) - } -} - @Composable fun Log( gitManager: GitManager, @@ -207,7 +189,7 @@ fun Log( LazyColumn( modifier = Modifier - .background(backgroundColor) + .background(MaterialTheme.colors.surface) .fillMaxSize() ) { if (gitManager.hasUncommitedChanges()) @@ -282,59 +264,4 @@ fun Log( } } } -} - -@Composable -fun CommitLogChanges(diffEntries: List, onDiffSelected: (DiffEntry) -> Unit) { - val selectedIndex = remember(diffEntries) { mutableStateOf(-1) } - - LazyColumn( - modifier = Modifier - .background(backgroundColor) - .fillMaxSize() - ) { - itemsIndexed(items = diffEntries) { index, diffEntry -> - val textColor = if (selectedIndex.value == index) { - MaterialTheme.colors.primary - } else - MaterialTheme.colors.primaryTextColor - - Column( - modifier = Modifier - .height(56.dp) - .fillMaxWidth() - .clickable { - selectedIndex.value = index - onDiffSelected(diffEntry) - }, - verticalArrangement = Arrangement.Center, - ) { - Spacer(modifier = Modifier.weight(2f)) - - - Row { - Icon( - modifier = Modifier - .padding(start = 16.dp) - .size(24.dp), - imageVector = diffEntry.icon, - contentDescription = null, - tint = MaterialTheme.colors.primary, - ) - - Text( - text = diffEntry.filePath, - modifier = Modifier.padding(horizontal = 16.dp), - color = textColor, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - - Spacer(modifier = Modifier.weight(2f)) - - Divider() - } - } - } -} +} \ No newline at end of file diff --git a/src/main/kotlin/extensions/InputStreamExtensions.kt b/src/main/kotlin/extensions/InputStreamExtensions.kt new file mode 100644 index 0000000..9619ba3 --- /dev/null +++ b/src/main/kotlin/extensions/InputStreamExtensions.kt @@ -0,0 +1,12 @@ +package extensions + +import java.io.ByteArrayOutputStream +import java.io.InputStream + +fun InputStream.toByteArray(): ByteArray { + val byteArrayOutputStream = ByteArrayOutputStream() + return byteArrayOutputStream.use { byteArrayOutStream -> + this.transferTo(byteArrayOutStream) + byteArrayOutStream.toByteArray() + } +} \ No newline at end of file diff --git a/src/main/kotlin/extensions/StringExtensions.kt b/src/main/kotlin/extensions/StringExtensions.kt new file mode 100644 index 0000000..97744db --- /dev/null +++ b/src/main/kotlin/extensions/StringExtensions.kt @@ -0,0 +1,10 @@ +package extensions + +import java.math.BigInteger +import java.security.MessageDigest + +val String.md5: String +get() { + val md = MessageDigest.getInstance("MD5") + return BigInteger(1, md.digest(this.toByteArray())).toString(16).padStart(32, '0') +} \ No newline at end of file diff --git a/src/main/kotlin/theme/Color.kt b/src/main/kotlin/theme/Color.kt index 6413910..1cff6a3 100644 --- a/src/main/kotlin/theme/Color.kt +++ b/src/main/kotlin/theme/Color.kt @@ -14,4 +14,6 @@ val errorColor = Color(0xFFFA4B4B) val primaryGrayLight = Color(0xFF464646) val accentGrayLight = Color(0xFFCCCCCC) -val backgroundColor = Color(0xFFf9f9f9) \ No newline at end of file +//val backgroundColorLight = Color(0xFFE8E8E8) +val backgroundColorLight = Color(0xFFC2C2C2) +val surfaceColorLight = Color(0xFFf9f9f9) \ No newline at end of file diff --git a/src/main/kotlin/theme/Theme.kt b/src/main/kotlin/theme/Theme.kt index 4fc08de..d1febd8 100644 --- a/src/main/kotlin/theme/Theme.kt +++ b/src/main/kotlin/theme/Theme.kt @@ -14,7 +14,8 @@ private val LightColorPalette = lightColors( primary = primary, primaryVariant = primaryDark, secondary = secondary, - background = backgroundColor, + background = backgroundColorLight, + surface = surfaceColorLight, error = errorColor /* Other default colors to override diff --git a/src/main/resources/image.jpg b/src/main/resources/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..514f3f20b4ad119b969c7f370a4dac67cddeac36 GIT binary patch literal 5658 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 Pkn~jKy?YU(m(%|PcZZSV literal 0 HcmV?d00001