feat: support pre-release
This commit is contained in:
1
.github/workflows/android.yml
vendored
1
.github/workflows/android.yml
vendored
@@ -211,3 +211,4 @@ jobs:
|
|||||||
name: ${{ github.ref_name }}
|
name: ${{ github.ref_name }}
|
||||||
body_path: dist/RELEASE_NOTES.md
|
body_path: dist/RELEASE_NOTES.md
|
||||||
files: dist/*.apk
|
files: dist/*.apk
|
||||||
|
prerelease: ${{ contains(github.ref_name, '_pre') }}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ android {
|
|||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
versionCode = 33
|
versionCode = 33
|
||||||
versionName = "0.4.2"
|
versionName = "0.4.3_pre1"
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import java.net.URL
|
|||||||
object AppUpdateChecker {
|
object AppUpdateChecker {
|
||||||
private const val TAG = "AppUpdateChecker"
|
private const val TAG = "AppUpdateChecker"
|
||||||
const val RELEASES_API_URL =
|
const val RELEASES_API_URL =
|
||||||
"https://api.github.com/repos/Miuzarte/ScrcpyForAndroid/releases?per_page=1"
|
"https://api.github.com/repos/Miuzarte/ScrcpyForAndroid/releases?per_page=10"
|
||||||
const val RELEASES_URL =
|
const val RELEASES_URL =
|
||||||
"https://github.com/Miuzarte/ScrcpyForAndroid/releases"
|
"https://github.com/Miuzarte/ScrcpyForAndroid/releases"
|
||||||
const val REPO_URL =
|
const val REPO_URL =
|
||||||
@@ -71,44 +71,67 @@ object AppUpdateChecker {
|
|||||||
setRequestProperty("User-Agent", "ScrcpyForAndroid/$currentVersion")
|
setRequestProperty("User-Agent", "ScrcpyForAndroid/$currentVersion")
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
val responseCode = connection.responseCode
|
||||||
|
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||||
|
error("HTTP $responseCode from GitHub releases API")
|
||||||
|
}
|
||||||
val body = connection.inputStream.bufferedReader().use { it.readText() }
|
val body = connection.inputStream.bufferedReader().use { it.readText() }
|
||||||
val release = JSONArray(body).optJSONObject(0)
|
val releases = JSONArray(body)
|
||||||
?: error("GitHub releases response is empty")
|
val currentIsPre = currentVersion.contains("_pre")
|
||||||
val latestVersion = release.optString("tag_name")
|
|
||||||
.ifBlank { release.optString("name") }
|
val targetRelease = (0 until releases.length()).asSequence()
|
||||||
|
.mapNotNull { releases.optJSONObject(it) }
|
||||||
|
.firstOrNull { release ->
|
||||||
|
currentIsPre || !release.optBoolean("prerelease", false)
|
||||||
|
} ?: error("No suitable release found")
|
||||||
|
|
||||||
|
val latestVersion = targetRelease.optString("tag_name")
|
||||||
|
.ifBlank { targetRelease.optString("name") }
|
||||||
.ifBlank { error("GitHub release has no tag name") }
|
.ifBlank { error("GitHub release has no tag name") }
|
||||||
ReleaseInfo(
|
ReleaseInfo(
|
||||||
currentVersion = currentVersion,
|
currentVersion = currentVersion,
|
||||||
latestVersion = latestVersion.removePrefix("v").removePrefix("V"),
|
latestVersion = latestVersion.removePrefix("v").removePrefix("V"),
|
||||||
hasUpdate = compareVersions(currentVersion, latestVersion) < 0,
|
hasUpdate = compareVersions(currentVersion, latestVersion) < 0,
|
||||||
htmlUrl = release.optString("html_url").ifBlank { RELEASES_URL },
|
htmlUrl = targetRelease.optString("html_url").ifBlank { RELEASES_URL },
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
connection.disconnect()
|
connection.disconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class Version(
|
||||||
|
val parts: List<Int>,
|
||||||
|
val isPre: Boolean,
|
||||||
|
val preNum: Int,
|
||||||
|
)
|
||||||
|
|
||||||
private fun compareVersions(current: String, latest: String): Int {
|
private fun compareVersions(current: String, latest: String): Int {
|
||||||
val currentParts = normalizeVersion(current)
|
val cur = parseVersion(current)
|
||||||
val latestParts = normalizeVersion(latest)
|
val lte = parseVersion(latest)
|
||||||
val maxSize = maxOf(currentParts.size, latestParts.size)
|
val maxSize = maxOf(cur.parts.size, lte.parts.size)
|
||||||
for (i in 0 until maxSize) {
|
for (i in 0 until maxSize) {
|
||||||
val currentPart = currentParts.getOrElse(i) { 0 }
|
val cp = cur.parts.getOrElse(i) { 0 }
|
||||||
val latestPart = latestParts.getOrElse(i) { 0 }
|
val lp = lte.parts.getOrElse(i) { 0 }
|
||||||
if (currentPart != latestPart) {
|
if (cp != lp) return cp.compareTo(lp)
|
||||||
return currentPart.compareTo(latestPart)
|
}
|
||||||
}
|
return when {
|
||||||
|
!cur.isPre && !lte.isPre -> 0
|
||||||
|
!cur.isPre -> 1
|
||||||
|
!lte.isPre -> -1
|
||||||
|
else -> cur.preNum.compareTo(lte.preNum)
|
||||||
}
|
}
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun normalizeVersion(value: String) =
|
private fun parseVersion(value: String): Version {
|
||||||
value
|
val cleaned = value.trim().removePrefix("v").removePrefix("V")
|
||||||
.trim()
|
val preMatch = Regex("_(?:pre|rc|beta|alpha)(\\d*)$", RegexOption.IGNORE_CASE).find(cleaned)
|
||||||
.removePrefix("v")
|
val mainPart = preMatch?.range?.let { cleaned.substring(0, it.first) } ?: cleaned
|
||||||
.removePrefix("V")
|
val parts = mainPart.split(Regex("[^0-9]+"))
|
||||||
.split(Regex("[^0-9]+"))
|
|
||||||
.filter { it.isNotBlank() }
|
.filter { it.isNotBlank() }
|
||||||
.mapNotNull { it.toIntOrNull() }
|
.mapNotNull { it.toIntOrNull() }
|
||||||
.ifEmpty { listOf(0) }
|
.ifEmpty { listOf(0) }
|
||||||
|
val isPre = preMatch != null
|
||||||
|
val preNum = preMatch?.groupValues?.getOrNull(1)?.toIntOrNull() ?: 0
|
||||||
|
return Version(parts, isPre, preNum)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,7 @@
|
|||||||
<string name="pref_update_found">, found new version %1$s</string>
|
<string name="pref_update_found">, found new version %1$s</string>
|
||||||
<string name="pref_update_latest">, already the latest version</string>
|
<string name="pref_update_latest">, already the latest version</string>
|
||||||
<string name="pref_update_newer">, newer than latest release %1$s</string>
|
<string name="pref_update_newer">, newer than latest release %1$s</string>
|
||||||
|
<string name="pref_update_prerelease_latest">, on the latest prerelease</string>
|
||||||
|
|
||||||
<!-- Settings - Theme -->
|
<!-- Settings - Theme -->
|
||||||
<string name="section_theme">Theme</string>
|
<string name="section_theme">Theme</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user