Fix update version check

This commit is contained in:
世界
2026-02-16 11:22:53 +08:00
parent 2ad11b7045
commit a7c18535e1
3 changed files with 64 additions and 32 deletions

View File

@@ -4,7 +4,6 @@ import android.os.Build
import io.nekohasekai.libbox.Libbox
import io.nekohasekai.sfa.BuildConfig
import io.nekohasekai.sfa.ktx.unwrap
import io.nekohasekai.sfa.update.UpdateCheckException
import io.nekohasekai.sfa.update.UpdateInfo
import io.nekohasekai.sfa.update.UpdateTrack
import io.nekohasekai.sfa.utils.HTTPClient
@@ -27,18 +26,25 @@ class GitHubUpdateChecker : Closeable {
private val json = Json { ignoreUnknownKeys = true }
fun checkUpdate(track: UpdateTrack): UpdateInfo? {
val includePrerelease = track == UpdateTrack.BETA
val release = getLatestRelease(includePrerelease) ?: return null
val releases = getReleases()
var selected: ReleaseCandidate? = null
if (!release.assets.any { it.name == METADATA_FILENAME }) {
throw UpdateCheckException.TrackNotSupported()
for (release in releases) {
if (!isReleaseInTrack(release, track)) {
continue
}
val metadata = runCatching { downloadMetadata(release) }.getOrNull() ?: continue
if (!isNewerThanCurrent(metadata.versionName)) {
continue
}
val currentBest = selected
if (currentBest == null || isBetterVersion(metadata, currentBest.metadata)) {
selected = ReleaseCandidate(release, metadata)
}
}
val metadata = downloadMetadata(release)!!
if (metadata.versionCode <= BuildConfig.VERSION_CODE) {
return null
}
val release = selected?.release ?: return null
val metadata = selected.metadata
val isLegacy = Build.VERSION.SDK_INT < Build.VERSION_CODES.M
val apkAsset = release.assets.find { asset ->
@@ -58,7 +64,7 @@ class GitHubUpdateChecker : Closeable {
)
}
private fun getLatestRelease(includePrerelease: Boolean): GitHubRelease? {
private fun getReleases(): List<GitHubRelease> {
val request = client.newRequest()
request.setURL(RELEASES_URL)
request.setHeader("Accept", "application/vnd.github.v3+json")
@@ -67,13 +73,31 @@ class GitHubUpdateChecker : Closeable {
val response = request.execute()
val content = response.content.unwrap
val releases = json.decodeFromString<List<GitHubRelease>>(content)
return if (includePrerelease) {
releases.firstOrNull()
} else {
releases.firstOrNull { !it.prerelease && !it.draft }
return json.decodeFromString(content)
}
private fun isReleaseInTrack(release: GitHubRelease, track: UpdateTrack): Boolean {
if (release.draft) {
return false
}
return when (track) {
UpdateTrack.STABLE -> !release.prerelease
UpdateTrack.BETA -> true
}
}
private fun isNewerThanCurrent(versionName: String): Boolean {
return Libbox.compareSemver(versionName, BuildConfig.VERSION_NAME)
}
private fun isBetterVersion(version: VersionMetadata, other: VersionMetadata): Boolean {
if (Libbox.compareSemver(version.versionName, other.versionName)) {
return true
}
if (Libbox.compareSemver(other.versionName, version.versionName)) {
return false
}
return version.versionCode > other.versionCode
}
private fun downloadMetadata(release: GitHubRelease): VersionMetadata? {
@@ -117,4 +141,9 @@ class GitHubUpdateChecker : Closeable {
@SerialName("version_code") val versionCode: Int = 0,
@SerialName("version_name") val versionName: String = "",
)
private data class ReleaseCandidate(
val release: GitHubRelease,
val metadata: VersionMetadata,
)
}

View File

@@ -198,6 +198,7 @@ class MainActivity :
val updateInfo = Vendor.checkUpdateAsync()
UpdateState.setUpdate(updateInfo)
} catch (_: Exception) {
UpdateState.setUpdate(null)
}
}
}
@@ -495,6 +496,7 @@ class MainActivity :
val result = Vendor.checkUpdateAsync()
UpdateState.setUpdate(result)
} catch (_: Exception) {
UpdateState.setUpdate(null)
}
}
}) {

View File

@@ -188,6 +188,7 @@ fun AppSettingsScreen(navController: NavController) {
currentTrack = currentTrack,
onTrackSelected = { track ->
currentTrack = track
UpdateState.clear()
scope.launch(Dispatchers.IO) {
Settings.updateTrack = track
}
@@ -932,9 +933,6 @@ fun AppSettingsScreen(navController: NavController) {
},
)
.clickable(enabled = !isChecking) {
if (hasUpdate && updateInfo != null) {
showUpdateAvailableDialog = true
} else {
scope.launch {
UpdateState.isChecking.value = true
withContext(Dispatchers.IO) {
@@ -943,15 +941,18 @@ fun AppSettingsScreen(navController: NavController) {
UpdateState.setUpdate(result)
if (result == null) {
showErrorDialog = R.string.no_updates_available
} else {
showUpdateAvailableDialog = true
}
} catch (_: UpdateCheckException.TrackNotSupported) {
UpdateState.setUpdate(null)
showErrorDialog = R.string.update_track_not_supported
} catch (_: Exception) {
UpdateState.setUpdate(null)
}
}
UpdateState.isChecking.value = false
}
}
},
colors =
ListItemDefaults.colors(