Gitnuro/src/main/kotlin/CommitChanges.kt

227 lines
7.5 KiB
Kotlin

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.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.useResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
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.primaryTextColor
import theme.secondaryTextColor
import java.net.HttpURLConnection
import java.net.URL
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
@Composable
fun CommitChanges(commitDiff: Pair<RevCommit, List<DiffEntry>>, 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)
Card(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth()
.height(120.dp)
) {
Box {
Text(
text = commit.fullMessage,
modifier = Modifier
.fillMaxSize()
.padding(8.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
) {
Row {
Text(
text = commit.authorIdent.name,
color = MaterialTheme.colors.primaryTextColor,
maxLines = 1,
)
Text(
text = commit.authorIdent.emailAddress,
color = MaterialTheme.colors.secondaryTextColor,
modifier = Modifier.padding(horizontal = 4.dp),
maxLines = 1,
)
}
val systemLocale = System.getProperty("user.language")
val locale = Locale(systemLocale)
val sdf = DateFormat.getDateInstance(DateFormat.MEDIUM, locale)
Text(
text = sdf.format(commit.authorIdent.`when`),
color = MaterialTheme.colors.secondaryTextColor,
maxLines = 1,
)
}
}
}
}
Card(
modifier = Modifier
.fillMaxWidth()
.weight(1f, fill = true)
.padding(horizontal = 16.dp, vertical = 8.dp)
) {
Column {
Text(
modifier = Modifier
.padding(vertical = 16.dp)
.fillMaxWidth(),
text = "Files changed",
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
color = MaterialTheme.colors.primary,
)
Divider(modifier = Modifier.fillMaxWidth())
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<ImageBitmap>(
useResource("image.jpg") {
makeFromEncoded(it.toByteArray()).asImageBitmap()
}
)
}
LaunchedEffect(url) {
loadImage(url).let {
image = makeFromEncoded(it).asImageBitmap()
}
}
return image
}
@Composable
fun CommitLogChanges(diffEntries: List<DiffEntry>, onDiffSelected: (DiffEntry) -> Unit) {
val selectedIndex = remember(diffEntries) { mutableStateOf(-1) }
LazyColumn(
modifier = Modifier
.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()
}
}
}
}