forked from geode-sdk/android-launcher
improved geode version selection
This commit is contained in:
6 files changed
+118
-13
No files matched your search
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.util.Log
|
||||
import com.geode.launcher.BuildConfig
|
||||
import com.geode.launcher.utils.DownloadUtils
|
||||
import com.geode.launcher.utils.GamePackageUtils
|
||||
import com.geode.launcher.utils.LaunchUtils
|
||||
import com.geode.launcher.utils.PreferenceUtils
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -22,6 +23,9 @@ import okio.source
|
||||
import java.io.File
|
||||
import java.io.InterruptedIOException
|
||||
|
||||
private const val TAG_LATEST = "latest"
|
||||
private const val TAG_BETA = "prerelease"
|
||||
|
||||
/**
|
||||
* Singleton to manage Geode updates, from update checking to downloading.
|
||||
*/
|
||||
@@ -91,11 +95,36 @@ class ReleaseManager private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBestReleaseForGameVersion(): String? {
|
||||
if (!GamePackageUtils.isGameInstalled(applicationContext.packageManager)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val gameVersion = GamePackageUtils.getGameVersionCode(applicationContext.packageManager)
|
||||
|
||||
return when {
|
||||
gameVersion >= 39L -> TAG_LATEST
|
||||
gameVersion == 38L -> "v2.0.0-beta.27"
|
||||
gameVersion == 37L -> "v2.0.0-beta.5"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getLatestRelease(): Release? {
|
||||
val sharedPreferences = PreferenceUtils.get(applicationContext)
|
||||
val useNightly = sharedPreferences.getBoolean(PreferenceUtils.Key.RELEASE_CHANNEL)
|
||||
val releaseChannel = sharedPreferences.getInt(PreferenceUtils.Key.RELEASE_CHANNEL_TAG)
|
||||
|
||||
return releaseRepository.getLatestGeodeRelease(useNightly)
|
||||
val targetTag = when (releaseChannel) {
|
||||
2 -> "nightly"
|
||||
1 -> TAG_BETA
|
||||
else -> getBestReleaseForGameVersion()
|
||||
} ?: return null
|
||||
|
||||
return when (targetTag) {
|
||||
TAG_LATEST -> releaseRepository.getLatestGeodeRelease()
|
||||
TAG_BETA -> releaseRepository.getLatestGeodePreRelease()
|
||||
else -> releaseRepository.getReleaseByTag(targetTag)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun performUpdate(release: Release) {
|
||||
|
||||
@@ -32,16 +32,74 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
||||
return getReleaseByUrl(url)
|
||||
}
|
||||
|
||||
suspend fun getLatestGeodeRelease(isNightly: Boolean = false): Release? {
|
||||
val geodeBaseUrl = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases"
|
||||
val releasePath = if (isNightly) "$geodeBaseUrl/tags/nightly"
|
||||
else "$geodeBaseUrl/latest"
|
||||
|
||||
suspend fun getLatestGeodeRelease(): Release? {
|
||||
val releasePath = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases/latest"
|
||||
val url = URL(releasePath)
|
||||
|
||||
return getReleaseByUrl(url)
|
||||
}
|
||||
|
||||
suspend fun getReleaseByTag(tag: String): Release? {
|
||||
val releasePath = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases/tags/$tag"
|
||||
val url = URL(releasePath)
|
||||
|
||||
return getReleaseByUrl(url)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
suspend fun getLatestGeodePreRelease(): Release? {
|
||||
val releasesUrl = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases?per_page=2"
|
||||
val url = URL(releasesUrl)
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.addHeader("Accept", "application/json")
|
||||
.addHeader(GITHUB_API_HEADER, GITHUB_API_VERSION)
|
||||
.build()
|
||||
|
||||
val call = httpClient.newCall(request)
|
||||
val response = call.executeCoroutine()
|
||||
|
||||
return when (response.code) {
|
||||
200 -> {
|
||||
val format = Json {
|
||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
val release = format.decodeFromBufferedSource<List<Release>>(
|
||||
response.body!!.source()
|
||||
)
|
||||
|
||||
release.find { it.tagName != "nightly" }
|
||||
}
|
||||
403 -> {
|
||||
// determine if the error code is a ratelimit
|
||||
// (github docs say it sends 429 too, but haven't seen that)
|
||||
|
||||
val limitRemaining = response.headers.get(GITHUB_RATELIMIT_REMAINING)?.toInt()
|
||||
val limitReset = response.headers.get(GITHUB_RATELIMIT_RESET)?.toLong()
|
||||
|
||||
if (limitRemaining == 0 && limitReset != null) {
|
||||
// handle ratelimit with a custom error
|
||||
// there's also a retry-after header but again, haven't seen
|
||||
val resetTime = Instant.fromEpochSeconds(limitReset, 0L)
|
||||
val msg = generateRateLimitMessage(resetTime)
|
||||
|
||||
throw IOException(msg)
|
||||
}
|
||||
|
||||
throw IOException("response 403: ${response.body!!.string()}")
|
||||
}
|
||||
404 -> {
|
||||
null
|
||||
}
|
||||
else -> {
|
||||
throw IOException("unknown response ${response.code}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateRateLimitMessage(resetTime: Instant): String {
|
||||
val currentTime = Clock.System.now()
|
||||
val resetDelay = currentTime.until(resetTime, DateTimeUnit.SECOND)
|
||||
|
||||
Reference in new issue
Block a user