Skip to content

Commit e2a923b

Browse files
committed
Updated build.yml and Changelogs format in MainScreen.kt
- The changelog now includes both the title and the full description of every commit since the last release. - The changelog will now include the author name as well. - The app now supports bold, italic, inline code, bullet points (- or *), and blockquotes (>). - Horizontal rules (---) are now rendered as thin lines to separate sections. - Bullet points and quotes now have proper indentation and visual markers (like the "┃" bar for quotes).
1 parent 02d6b56 commit e2a923b

2 files changed

Lines changed: 161 additions & 36 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,15 @@ jobs:
3434
run: |
3535
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > app/release.keystore
3636
37-
- name: Get Version Info & Changelog
37+
- name: Get Version Info & Changelogs
3838
run: |
39-
echo "COMMIT_COUNT=$(git rev-list --count HEAD)" >> $GITHUB_ENV
39+
COMMIT_COUNT=$(git rev-list --count HEAD)
40+
echo "COMMIT_COUNT=$COMMIT_COUNT" >> $GITHUB_ENV
4041
VERSION_NAME=$(grep -oP 'versionName\s*=\s*"\K[^"]+' app/build.gradle.kts || echo "1.0")
4142
echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV
4243
43-
if [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ] || [ -z "${{ github.event.before }}" ]; then
44-
CHANGES=$(git log -5 --pretty=format:"- %s")
45-
else
46-
CHANGES=$(git log ${{ github.event.before }}..${{ github.sha }} --pretty=format:"- %s")
47-
fi
44+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
45+
CHANGES=$(git log $PREV_TAG..HEAD --pretty=format:"- **%s** by @%an%n%w(0,2,2)%b")
4846
4947
echo "CHANGELOG<<EOF" >> $GITHUB_ENV
5048
echo "$CHANGES" >> $GITHUB_ENV

‎app/src/main/kotlin/build/bytes/romshifter/ui/screens/MainScreen.kt‎

Lines changed: 156 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ fun MainScreen(viewModel: MainViewModel) {
164164
modifier = Modifier
165165
.fillMaxWidth()
166166
.weight(1f, fill = false)
167+
.animateContentSize()
167168
.clip(RoundedCornerShape(16.dp))
168169
.background(MaterialTheme.colorScheme.surfaceContainerHigh)
169170
.padding(16.dp),
@@ -1191,50 +1192,85 @@ fun NoRootScreen() {
11911192

11921193
@Composable
11931194
fun formatChangelog(text: String, linkColor: Color): AnnotatedString {
1194-
val titleLargeStyle = MaterialTheme.typography.titleLarge.toSpanStyle().copy(fontWeight = FontWeight.Bold)
1195-
val titleMediumStyle = MaterialTheme.typography.titleMedium.toSpanStyle().copy(fontWeight = FontWeight.Bold)
1195+
val titleLargeStyle = MaterialTheme.typography.titleLarge.toSpanStyle().copy(
1196+
fontWeight = FontWeight.ExtraBold,
1197+
color = MaterialTheme.colorScheme.primary
1198+
)
1199+
val titleMediumStyle = MaterialTheme.typography.titleMedium.toSpanStyle().copy(
1200+
fontWeight = FontWeight.Bold,
1201+
color = MaterialTheme.colorScheme.primary
1202+
)
1203+
val codeStyle = SpanStyle(
1204+
fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace,
1205+
background = MaterialTheme.colorScheme.surfaceVariant,
1206+
color = MaterialTheme.colorScheme.onSurfaceVariant
1207+
)
1208+
val quoteStyle = SpanStyle(
1209+
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
1210+
fontStyle = androidx.compose.ui.text.font.FontStyle.Italic
1211+
)
11961212

11971213
return buildAnnotatedString {
11981214
val lines = text.split("\n")
11991215

1200-
for ((lineIndex, line) in lines.withIndex()) {
1216+
lines.forEachIndexed { index, line ->
12011217
var currentLine = line
1202-
var headingStyle: SpanStyle? = null
1203-
1204-
if (currentLine.startsWith("### ")) {
1205-
currentLine = currentLine.removePrefix("### ")
1206-
headingStyle = titleMediumStyle
1207-
} else if (currentLine.startsWith("## ")) {
1208-
currentLine = currentLine.removePrefix("## ")
1209-
headingStyle = titleLargeStyle
1210-
} else if (currentLine.startsWith("# ")) {
1211-
currentLine = currentLine.removePrefix("# ")
1212-
headingStyle = titleLargeStyle
1213-
}
1218+
var lineStyle: SpanStyle? = null
1219+
var prefix = ""
1220+
1221+
if (currentLine.matches(Regex("^-{3,}$|^\\*{3,}$|^_{3,}$"))) {
1222+
withStyle(SpanStyle(color = MaterialTheme.colorScheme.outlineVariant)) {
1223+
append("────────────────────────────────")
1224+
}
1225+
} else {
1226+
if (currentLine.startsWith("### ")) {
1227+
currentLine = currentLine.removePrefix("### ")
1228+
lineStyle = titleMediumStyle
1229+
} else if (currentLine.startsWith("## ")) {
1230+
currentLine = currentLine.removePrefix("## ")
1231+
lineStyle = titleLargeStyle
1232+
} else if (currentLine.startsWith("# ")) {
1233+
currentLine = currentLine.removePrefix("# ")
1234+
lineStyle = titleLargeStyle
1235+
}
12141236

1215-
val lineStart = length
1237+
if (currentLine.startsWith("> ")) {
1238+
currentLine = currentLine.removePrefix("> ")
1239+
lineStyle = quoteStyle
1240+
prefix = "┃ "
1241+
}
12161242

1217-
val parts = currentLine.split("**")
1218-
for ((index, part) in parts.withIndex()) {
1219-
if (index % 2 == 1) {
1220-
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { append(part) }
1221-
} else {
1222-
append(part)
1243+
if (currentLine.trimStart().startsWith("- ") || currentLine.trimStart()
1244+
.startsWith("* ")
1245+
) {
1246+
val indent = currentLine.takeWhile { it.isWhitespace() }
1247+
currentLine = currentLine.trimStart().substring(2)
1248+
prefix = "$indent• "
1249+
}
1250+
1251+
val lineStart = length
1252+
append(prefix)
1253+
1254+
parseInlineStyles(currentLine, codeStyle).forEach { part ->
1255+
val partStart = length
1256+
append(part.text)
1257+
part.styles.forEach { (style, range) ->
1258+
addStyle(style, partStart + range.first, partStart + range.last)
1259+
}
12231260
}
1224-
}
12251261

1226-
if (headingStyle != null) {
1227-
addStyle(headingStyle, lineStart, length)
1262+
if (lineStyle != null) {
1263+
addStyle(lineStyle, lineStart, length)
1264+
}
12281265
}
12291266

1230-
if (lineIndex < lines.size - 1) {
1267+
if (index < lines.size - 1) {
12311268
append("\n")
12321269
}
12331270
}
12341271

1235-
val finalStr = toAnnotatedString().text
12361272
val urlRegex = Regex("(https?://\\S+)")
1237-
urlRegex.findAll(finalStr).forEach { match ->
1273+
urlRegex.findAll(this.toAnnotatedString().text).forEach { match ->
12381274
addLink(
12391275
LinkAnnotation.Url(
12401276
url = match.value,
@@ -1250,4 +1286,95 @@ fun formatChangelog(text: String, linkColor: Color): AnnotatedString {
12501286
)
12511287
}
12521288
}
1253-
}
1289+
}
1290+
1291+
private data class StyledPart(val text: String, val styles: List<Pair<SpanStyle, IntRange>>)
1292+
1293+
private fun parseInlineStyles(text: String, codeStyle: SpanStyle): List<StyledPart> {
1294+
val result = mutableListOf<StyledPart>()
1295+
1296+
val codeRegex = Regex("`([^`]+)`")
1297+
var lastMatchEnd = 0
1298+
1299+
codeRegex.findAll(text).forEach { match ->
1300+
if (match.range.first > lastMatchEnd) {
1301+
result.add(parseBoldItalic(text.substring(lastMatchEnd, match.range.first)))
1302+
}
1303+
result.add(
1304+
StyledPart(
1305+
match.groupValues[1],
1306+
listOf(codeStyle to 0.rangeTo(match.groupValues[1].length))
1307+
)
1308+
)
1309+
lastMatchEnd = match.range.last + 1
1310+
}
1311+
1312+
if (lastMatchEnd < text.length) {
1313+
result.add(parseBoldItalic(text.substring(lastMatchEnd)))
1314+
}
1315+
1316+
return if (result.isEmpty()) listOf(parseBoldItalic(text)) else result
1317+
}
1318+
1319+
private fun parseBoldItalic(text: String): StyledPart {
1320+
val styles = mutableListOf<Pair<SpanStyle, IntRange>>()
1321+
1322+
val boldRegex = Regex("(\\*\\*|__)(.*?)\\1")
1323+
boldRegex.findAll(text).forEach { match ->
1324+
styles.add(SpanStyle(fontWeight = FontWeight.Bold) to match.range.first.rangeTo(match.range.last + 1))
1325+
}
1326+
1327+
val italicRegex =
1328+
Regex("(?<!\\*)\\*(?!\\*)(.*?)(?<!\\*)\\*(?!\\*)|(?<!_)_(?!_)(.*?)(?<!_)_(?!_)")
1329+
italicRegex.findAll(text).forEach { match ->
1330+
styles.add(
1331+
SpanStyle(fontStyle = androidx.compose.ui.text.font.FontStyle.Italic) to match.range.first.rangeTo(
1332+
match.range.last + 1
1333+
)
1334+
)
1335+
}
1336+
1337+
1338+
val finalBuilder = AnnotatedString.Builder()
1339+
var i = 0
1340+
while (i < text.length) {
1341+
when {
1342+
text.startsWith("**", i) || text.startsWith("__", i) -> {
1343+
val marker = text.substring(i, i + 2)
1344+
val end = text.indexOf(marker, i + 2)
1345+
if (end != -1) {
1346+
finalBuilder.withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
1347+
append(text.substring(i + 2, end))
1348+
}
1349+
i = end + 2
1350+
} else {
1351+
finalBuilder.append(text[i])
1352+
i++
1353+
}
1354+
}
1355+
1356+
text.startsWith("*", i) || text.startsWith("_", i) -> {
1357+
val marker = text[i].toString()
1358+
val end = text.indexOf(marker, i + 1)
1359+
if (end != -1 && (end + 1 == text.length || text[end + 1] != text[end])) {
1360+
finalBuilder.withStyle(SpanStyle(fontStyle = androidx.compose.ui.text.font.FontStyle.Italic)) {
1361+
append(text.substring(i + 1, end))
1362+
}
1363+
i = end + 1
1364+
} else {
1365+
finalBuilder.append(text[i])
1366+
i++
1367+
}
1368+
}
1369+
1370+
else -> {
1371+
finalBuilder.append(text[i])
1372+
i++
1373+
}
1374+
}
1375+
}
1376+
1377+
return StyledPart(
1378+
finalBuilder.toAnnotatedString().text,
1379+
finalBuilder.toAnnotatedString().spanStyles.map { it.item to it.start.rangeTo(it.end) })
1380+
}

0 commit comments

Comments
 (0)