Compare commits

...

2 Commits

Author SHA1 Message Date
Ushie
95cd097519 bleh 2026-03-01 02:55:15 +03:00
Ushie
d685382277 feat: Display more than the latest changelog 2026-02-27 08:34:40 +03:00
5 changed files with 142 additions and 27 deletions

View File

@@ -20,16 +20,23 @@ class ReVancedAPI(
) {
private suspend fun apiUrl() = prefs.api.get()
private suspend inline fun <reified T> request(api: String, route: String): APIResponse<T> =
private suspend inline fun <reified T> request(
api: String,
route: String,
version: String? = "v4"
): APIResponse<T> =
withContext(
Dispatchers.IO
) {
client.request {
url("$api/v4/$route")
url("$api/$version/$route")
}
}
private suspend inline fun <reified T> request(route: String) = request<T>(apiUrl(), route)
private suspend inline fun <reified T> request(
route: String,
version: String = "v4"
) = request<T>(apiUrl(), route, version)
suspend fun getAnnouncements() = request<List<ReVancedAnnouncement>>("announcements")
@@ -41,6 +48,8 @@ class ReVancedAPI(
suspend fun getLatestAppInfo() =
request<ReVancedAsset>("manager?prerelease=${prefs.useManagerPrereleases.get()}")
suspend fun getAppHistory() = request<ReVancedAsset>("patches/history", "dev")
suspend fun getPatchesUpdate() = request<ReVancedAsset>("patches?prerelease=${prefs.usePatchesPrereleases.get()}")
suspend fun getContributors() = request<List<ReVancedGitRepository>>("contributors")

View File

@@ -7,7 +7,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.outlined.CalendarToday
import androidx.compose.material.icons.outlined.Campaign
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -21,7 +22,7 @@ import app.revanced.manager.ui.component.Markdown
@Composable
fun Changelog(
markdown: String,
description: String,
version: String,
publishDate: String
) {
@@ -34,22 +35,32 @@ fun Changelog(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Outlined.NewReleases,
imageVector = Icons.Outlined.Campaign,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.size(32.dp)
)
Text(
"${version.removePrefix("v")} ($publishDate)",
version.removePrefix("v"),
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight(800)),
color = MaterialTheme.colorScheme.primary,
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier
.fillMaxWidth()
) {
Tag(
Icons.Outlined.CalendarToday,
publishDate
)
}
Markdown(
description.removeVersionHeaderIfMatches(version),
)
}
Markdown(
markdown,
)
}
@Composable
@@ -70,4 +81,16 @@ private fun Tag(icon: ImageVector, text: String) {
color = MaterialTheme.colorScheme.outline,
)
}
}
fun String.removeVersionHeaderIfMatches(version: String): String {
val firstNewlineIndex = indexOf('\n')
if (firstNewlineIndex == -1) return this
val firstLine = substring(0, firstNewlineIndex).trim()
val versionWithoutPrefix = version.removePrefix("v")
if (!firstLine.contains(versionWithoutPrefix)) return this
return substring(firstNewlineIndex + 1).trimStart()
}

View File

@@ -189,7 +189,7 @@ private fun ColumnScope.Changelog(releaseInfo: ReVancedAsset) {
)
) {
Changelog(
markdown = releaseInfo.description.replace("`", ""),
description = releaseInfo.description.replace("`", ""),
version = releaseInfo.version,
publishDate = releaseInfo.createdAt.relativeTime(LocalContext.current)
)

View File

@@ -1,12 +1,15 @@
package app.revanced.manager.ui.screen.settings.update
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
@@ -17,10 +20,12 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.network.dto.ReVancedAsset
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.component.settings.Changelog
import app.revanced.manager.ui.viewmodel.ChangelogUiState
import app.revanced.manager.ui.viewmodel.ChangelogsViewModel
import app.revanced.manager.util.relativeTime
import org.koin.androidx.compose.koinViewModel
@@ -43,22 +48,61 @@ fun ChangelogsSettingsScreen(
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
) { paddingValues ->
ColumnWithScrollbar(
Box(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = if (vm.releaseInfo == null) Arrangement.Center else Arrangement.Top
contentAlignment = Alignment.Center
) {
vm.releaseInfo?.let { info ->
Column(modifier = Modifier.padding(16.dp)) {
Changelog(
markdown = info.description.replace("`", ""),
version = info.version,
publishDate = info.createdAt.relativeTime(LocalContext.current)
)
when (val state = vm.state) {
is ChangelogUiState.Loading -> LoadingIndicator()
is ChangelogUiState.Error -> Text(
text = state.message,
style = MaterialTheme.typography.titleLarge
)
is ChangelogUiState.Success -> {
if (state.changelogs.isEmpty()) {
Text(
text = stringResource(R.string.no_changelogs_found),
style = MaterialTheme.typography.titleLarge
)
} else {
LazyColumnWithScrollbar(modifier = Modifier.fillMaxSize()) {
items(
items = state.changelogs,
key = { it.version }
) { changelog ->
ChangelogItem(
changelog = changelog,
showDivider = changelog != state.changelogs.last()
)
}
}
}
}
} ?: LoadingIndicator()
}
}
}
}
@Composable
private fun ChangelogItem(
changelog: ReVancedAsset,
showDivider: Boolean
) {
Column(modifier = Modifier.padding(16.dp)) {
Changelog(
description = changelog.description,
version = changelog.version,
publishDate = changelog.createdAt.relativeTime(LocalContext.current)
)
if (showDivider) {
HorizontalDivider(
modifier = Modifier.padding(top = 32.dp),
color = MaterialTheme.colorScheme.outlineVariant
)
}
}
}

View File

@@ -12,18 +12,57 @@ import app.revanced.manager.network.dto.ReVancedAsset
import app.revanced.manager.network.utils.getOrThrow
import app.revanced.manager.util.uiSafe
import kotlinx.coroutines.launch
import kotlinx.datetime.LocalDateTime
import kotlinx.serialization.json.Json
sealed interface ChangelogUiState {
data object Loading : ChangelogUiState
data class Success(val changelogs: List<ReVancedAsset>) : ChangelogUiState
data class Error(val message: String) : ChangelogUiState
}
class ChangelogsViewModel(
private val api: ReVancedAPI,
private val app: Application,
) : ViewModel() {
var releaseInfo: ReVancedAsset? by mutableStateOf(null)
val mock = listOf(
ReVancedAsset(
version = "v1.25.2",
createdAt = LocalDateTime.parse("2025-07-07T13:01:12"),
description = """
## [1.25.2](https://github.com/ReVanced/revanced-manager/compare/v1.25.0...v1.25.1) (2025-07-07)
### Bug Fixes
* Disable Impeller Flutter render engine correctly to fix rendering issues
""".trimIndent(),
downloadUrl = "https://github.com/ReVanced/revanced-manager/releases/download/v1.25.1/revanced-manager-1.25.1.apk"
),
ReVancedAsset(
version = "v1.25.1",
createdAt = LocalDateTime.parse("2025-07-07T13:01:12"),
description = """
## [1.25.1](https://github.com/ReVanced/revanced-manager/compare/v1.25.0...v1.25.1) (2025-07-07)
### Bug Fixes
* Disable Impeller Flutter render engine correctly to fix rendering issues
""".trimIndent(),
downloadUrl = "https://github.com/ReVanced/revanced-manager/releases/download/v1.25.1/revanced-manager-1.25.1.apk"
)
)
var state: ChangelogUiState by mutableStateOf(ChangelogUiState.Loading)
private set
init {
viewModelScope.launch {
uiSafe(app, R.string.changelog_download_fail, "Failed to download changelog") {
releaseInfo = api.getLatestAppInfo().getOrThrow()
api.getLatestAppInfo().getOrThrow()
state = ChangelogUiState.Success(changelogs = mock)
}
if (state is ChangelogUiState.Loading) {
state = ChangelogUiState.Error(app.getString(R.string.changelog_download_fail))
}
}
}