mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
refactor: Rewrite "new version checker"
This commit is contained in:
parent
d7d75f1642
commit
ec37c0f87d
3 changed files with 138 additions and 59 deletions
102
app/src/main/java/dev/yokai/domain/base/models/Version.kt
Normal file
102
app/src/main/java/dev/yokai/domain/base/models/Version.kt
Normal file
|
@ -0,0 +1,102 @@
|
|||
package dev.yokai.domain.base.models
|
||||
|
||||
data class Version(
|
||||
val type: Type,
|
||||
val stage: Stage,
|
||||
val major: Int,
|
||||
val minor: Int = 0,
|
||||
val patch: Int = 0,
|
||||
val hotfix: Int = 0,
|
||||
val build: Int = 0
|
||||
) {
|
||||
operator fun compareTo(other: Version): Int {
|
||||
if (type == Type.DEBUG) {
|
||||
throw IllegalStateException("Checking debug version is not allowed")
|
||||
}
|
||||
|
||||
if (type != other.type) {
|
||||
throw IllegalArgumentException("Can't compare two different version type")
|
||||
}
|
||||
|
||||
return when {
|
||||
major > other.major ||
|
||||
minor > other.minor ||
|
||||
patch > other.patch ||
|
||||
hotfix > other.hotfix ||
|
||||
build > other.build ||
|
||||
stage.weight > other.stage.weight
|
||||
-> 1
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$major.$minor.$patch" + (if (hotfix > 0) ".$hotfix" else "") + (if (build > 0) "-${type.prefix}$build" else "")
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun parse(string: String): Version {
|
||||
var type = when {
|
||||
string.startsWith("r") -> Type.NIGHTLY
|
||||
string.startsWith("d") -> Type.DEBUG
|
||||
else -> Type.STABLE
|
||||
}
|
||||
|
||||
val split = string.split("-")
|
||||
var stage = Stage.RELEASE
|
||||
val stageCandidate = split.getOrNull(1)
|
||||
if (stageCandidate != null) {
|
||||
when {
|
||||
stageCandidate.startsWith("r", true) -> type = Type.NIGHTLY
|
||||
stageCandidate.startsWith("d", true) -> type = Type.DEBUG
|
||||
}
|
||||
|
||||
if (type == Type.STABLE)
|
||||
stage = when {
|
||||
stageCandidate.startsWith("b", true) -> Stage.BETA
|
||||
stageCandidate.startsWith("a", true) -> Stage.ALPHA
|
||||
else -> Stage.RELEASE
|
||||
}
|
||||
}
|
||||
val cleanBuild = stageCandidate
|
||||
?.replace("[^\\d.-]".toRegex(), "") // remove the prefix
|
||||
?.toInt()
|
||||
val candidate = split.first()
|
||||
.replace("[^\\d.-]".toRegex(), "") // remove the prefix
|
||||
.split(".").map { it.toInt() }
|
||||
|
||||
if (candidate.size == 1 && type == Type.NIGHTLY)
|
||||
return Version(
|
||||
type,
|
||||
stage,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
candidate[0],
|
||||
)
|
||||
|
||||
return Version(
|
||||
type,
|
||||
stage,
|
||||
candidate.getOrNull(0) ?: 0,
|
||||
candidate.getOrNull(1) ?: 0,
|
||||
candidate.getOrNull(2) ?: 0,
|
||||
candidate.getOrNull(3) ?: 0,
|
||||
cleanBuild ?: 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class Stage(val weight: Int) {
|
||||
RELEASE(3),
|
||||
BETA(2),
|
||||
ALPHA(1),
|
||||
}
|
||||
|
||||
enum class Type(val prefix: String) {
|
||||
STABLE("v"),
|
||||
NIGHTLY("r"),
|
||||
DEBUG("d"),
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.updater
|
|||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import dev.yokai.domain.base.models.Version
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
|
@ -14,8 +15,8 @@ import eu.kanade.tachiyomi.util.system.withIOContext
|
|||
import kotlinx.serialization.json.Json
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
|
||||
class AppUpdateChecker(
|
||||
private val json: Json = Injekt.get(),
|
||||
|
@ -87,44 +88,11 @@ class AppUpdateChecker(
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun isNewVersion(versionTag: String, currentVersion: String = BuildConfig.VERSION_NAME, isNightly: Boolean = BuildConfig.NIGHTLY): Boolean {
|
||||
// Removes prefixes like "r" or "v"
|
||||
val newVersion = versionTag.replace("[^\\d.-]".toRegex(), "")
|
||||
val oldVersion = currentVersion.replace("[^\\d.-]".toRegex(), "")
|
||||
val newPreReleaseVer = newVersion.split("-")
|
||||
val oldPreReleaseVer = oldVersion.split("-")
|
||||
val newSemVer = newPreReleaseVer.first().split(".").map { it.toInt() }
|
||||
val isNewVersionNightly = newSemVer.size == 1 || (newPreReleaseVer.size > 1 && newPreReleaseVer[1].startsWith("r"))
|
||||
val oldSemVer = oldPreReleaseVer.first().split(".").map { it.toInt() }
|
||||
|
||||
oldSemVer.mapIndexed { index, i ->
|
||||
if (!isNewVersionNightly && !isNightly && newSemVer.getOrElse(index) { i } > i) {
|
||||
return true
|
||||
} else if (newSemVer.getOrElse(index) { i } < i) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// For cases of extreme patch versions (new: 1.2.3.1 vs old: 1.2.3, return true)
|
||||
return if (newSemVer.size > oldSemVer.size && !isNewVersionNightly && !isNightly) {
|
||||
true
|
||||
} else if (newSemVer.size < oldSemVer.size && !isNewVersionNightly) {
|
||||
fun isNewVersion(newVersion: String, currentVersion: String = BuildConfig.VERSION_NAME): Boolean =
|
||||
try {
|
||||
Version.parse(newVersion) > Version.parse(currentVersion)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
false
|
||||
} else {
|
||||
// If the version numbers match, check the beta versions
|
||||
val newPreVersion =
|
||||
newPreReleaseVer.getOrNull(if (newPreReleaseVer.size > 1) 1 else 0)?.replace("[^\\d.-]".toRegex(), "")?.toIntOrNull()
|
||||
val oldPreVersion =
|
||||
oldPreReleaseVer.getOrNull(1)?.replace("[^\\d.-]".toRegex(), "")?.toIntOrNull()
|
||||
when {
|
||||
// For prod, don't bother with betas (current: 1.2.3 vs new: 1.2.3-b1)
|
||||
oldPreVersion == null && !isNightly -> false
|
||||
// For betas, always use prod builds (current: 1.2.3-b1 vs new: 1.2.3)
|
||||
// For nightly, don't use prod builds
|
||||
newPreVersion == null -> !isNightly
|
||||
// For nightly, higher beta ver is newer (current: 1.2.3-b1 vs new: 1.2.3-b2 or r2)
|
||||
else -> (oldPreVersion ?: 0) < newPreVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import io.mockk.mockk
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
|
@ -22,55 +23,63 @@ class AppUpdateCheckerTest {
|
|||
|
||||
@Test
|
||||
fun `Check new nightly version (Tachi format)`() {
|
||||
assertTrue(isNewVersion("1.2.3-r2", "1.2.3-r1", true)) // tachi format
|
||||
assertTrue(isNewVersion("1.2.4-r1", "1.2.3", true)) // Unlikely to happened, but we should try anyway
|
||||
assertTrue(isNewVersion("1.2.3-r2", "1.2.3-r1")) // tachi format
|
||||
assertFalse(isNewVersion("1.2.4-r1", "1.2.3")) // Unlikely to happened, but we should try anyway
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Check new nightly version (Yokai format)`() {
|
||||
assertTrue(isNewVersion("r2", "1.2.3-r1", true)) // yokai format
|
||||
assertTrue(isNewVersion("r2", "1.2.3-r1")) // yokai format
|
||||
assertFalse(isNewVersion("r1", "1.2.3")) // Unlikely to happened, but we should try anyway
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Nightly shouldn't get Prod build`() {
|
||||
assertFalse(isNewVersion("1.2.3", "1.2.3-r2", true))
|
||||
assertFalse(isNewVersion("1.2.4", "1.2.3-r2", true))
|
||||
assertFalse(isNewVersion("1.2.4", "1.2.3", true))
|
||||
assertFalse(isNewVersion("1.2.4.1", "1.2.4-r2", true))
|
||||
assertFalse(isNewVersion("1.2.3", "1.2.3-r2"))
|
||||
assertFalse(isNewVersion("1.2.4", "1.2.3-r2"))
|
||||
assertFalse(isNewVersion("1.2.4", "1.2.3-r0"))
|
||||
assertFalse(isNewVersion("1.2.4.1", "1.2.4-r2"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Check new beta version`() {
|
||||
assertFalse(isNewVersion("1.2.3-b1", "1.2.3-b2"))
|
||||
assertTrue(isNewVersion("1.2.3-b3", "1.2.3-b2"))
|
||||
assertTrue(isNewVersion("1.2.4-b1", "1.2.3-b1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Beta should get Prod build`() {
|
||||
assertTrue(isNewVersion("1.2.4", "1.2.3-r2", false))
|
||||
assertTrue(isNewVersion("1.2.3", "1.2.3-r2", false))
|
||||
assertTrue(isNewVersion("1.2.4", "1.2.3-b2"))
|
||||
assertTrue(isNewVersion("1.2.3", "1.2.3-b2"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Prod should get latest Prod build`() {
|
||||
assertTrue(isNewVersion("1.2.4", "1.2.3", false))
|
||||
assertTrue(isNewVersion("1.2.4.1", "1.2.4", false))
|
||||
assertTrue(isNewVersion("1.2.4", "1.2.3"))
|
||||
assertTrue(isNewVersion("1.2.4.1", "1.2.4"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Prod should get latest Prod build (Check for Betas)`() {
|
||||
assertTrue(isNewVersion("1.2.4-r1", "1.2.3", false))
|
||||
assertTrue(isNewVersion("1.2.4-b1", "1.2.3"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Prod shouldn't get nightly build (Check for Betas)`() {
|
||||
assertFalse(isNewVersion("r1", "1.2.3", false))
|
||||
assertFalse(isNewVersion("r1", "1.2.3"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Latest version check`() {
|
||||
assertFalse(isNewVersion("1.2.3", "1.2.3", false))
|
||||
assertFalse(isNewVersion("1.2.3-r1", "1.2.3-r1", false))
|
||||
assertFalse(isNewVersion("1.2.3", "1.2.3"))
|
||||
assertFalse(isNewVersion("1.2.3-r1", "1.2.3-r1"))
|
||||
|
||||
assertFalse(isNewVersion("1.2.3-r1", "1.2.3-r1", true))
|
||||
assertFalse(isNewVersion("r1", "1.2.4-r1", true))
|
||||
assertFalse(isNewVersion("1.2.3-r1", "1.2.3-r1"))
|
||||
assertFalse(isNewVersion("r1", "1.2.4-r1"))
|
||||
}
|
||||
|
||||
private fun isNewVersion(newVersion: String, currentVersion: String, isNightly: Boolean): Boolean {
|
||||
return appUpdateChecker.isNewVersion(newVersion, currentVersion, isNightly)
|
||||
private fun isNewVersion(newVersion: String, currentVersion: String): Boolean {
|
||||
return appUpdateChecker.isNewVersion(newVersion, currentVersion)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue