improved geode version selection

This commit is contained in:
qimiko committed 2024-06-19 20:14:59 -07:00
1 parent a562f5ec75
commit bdce61d160
6 files changed
+118 -13

No files matched your search

@@ -202,6 +202,13 @@ fun displayOptionToKey(option: Int): String {
} }
} }
@Composable
fun releaseChannelToKey(option: Int): String = when (option) {
1 -> stringResource(R.string.preference_release_channel_beta)
2 -> stringResource(R.string.preference_release_channel_nightly)
else -> stringResource(R.string.preference_release_channel_stable)
}
fun updateTheme(context: Context, theme: Int) { fun updateTheme(context: Context, theme: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
@@ -336,9 +343,12 @@ fun SettingsScreen(
title = context.getString(R.string.preference_update_automatically_name), title = context.getString(R.string.preference_update_automatically_name),
preferenceKey = PreferenceUtils.Key.UPDATE_AUTOMATICALLY, preferenceKey = PreferenceUtils.Key.UPDATE_AUTOMATICALLY,
) )
SettingsCard( SettingsSelectCard(
title = context.getString(R.string.preference_release_channel_name), title = stringResource(R.string.preference_release_channel_tag_name),
preferenceKey = PreferenceUtils.Key.RELEASE_CHANNEL, dialogTitle = stringResource(R.string.preference_release_channel_select),
maxVal = 2,
preferenceKey = PreferenceUtils.Key.RELEASE_CHANNEL_TAG,
toLabel = { releaseChannelToKey(it) }
) )
OptionsCard( OptionsCard(
title = { title = {
@@ -4,6 +4,7 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.geode.launcher.BuildConfig import com.geode.launcher.BuildConfig
import com.geode.launcher.utils.DownloadUtils import com.geode.launcher.utils.DownloadUtils
import com.geode.launcher.utils.GamePackageUtils
import com.geode.launcher.utils.LaunchUtils import com.geode.launcher.utils.LaunchUtils
import com.geode.launcher.utils.PreferenceUtils import com.geode.launcher.utils.PreferenceUtils
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
@@ -22,6 +23,9 @@ import okio.source
import java.io.File import java.io.File
import java.io.InterruptedIOException 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. * 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? { private suspend fun getLatestRelease(): Release? {
val sharedPreferences = PreferenceUtils.get(applicationContext) 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) { private suspend fun performUpdate(release: Release) {
@@ -32,16 +32,74 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
return getReleaseByUrl(url) return getReleaseByUrl(url)
} }
suspend fun getLatestGeodeRelease(isNightly: Boolean = false): Release? { suspend fun getLatestGeodeRelease(): Release? {
val geodeBaseUrl = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases" val releasePath = "$GITHUB_API_BASE/repos/geode-sdk/geode/releases/latest"
val releasePath = if (isNightly) "$geodeBaseUrl/tags/nightly"
else "$geodeBaseUrl/latest"
val url = URL(releasePath) val url = URL(releasePath)
return getReleaseByUrl(url) 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 { private fun generateRateLimitMessage(resetTime: Instant): String {
val currentTime = Clock.System.now() val currentTime = Clock.System.now()
val resetDelay = currentTime.until(resetTime, DateTimeUnit.SECOND) val resetDelay = currentTime.until(resetTime, DateTimeUnit.SECOND)
@@ -13,7 +13,7 @@ object Constants {
@SuppressLint("SdCardPath") @SuppressLint("SdCardPath")
const val GJ_DATA_DIR = "/data/data/${PACKAGE_NAME}" const val GJ_DATA_DIR = "/data/data/${PACKAGE_NAME}"
const val SUPPORTED_VERSION_CODE_MIN = 38L const val SUPPORTED_VERSION_CODE_MIN = 37L
const val SUPPORTED_VERSION_CODE = 39L const val SUPPORTED_VERSION_CODE = 39L
const val SUPPORTED_VERSION_STRING = "2.2.142" const val SUPPORTED_VERSION_STRING = "2.2.142"
@@ -137,19 +137,20 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
LIMIT_ASPECT_RATIO, LIMIT_ASPECT_RATIO,
DISPLAY_MODE, DISPLAY_MODE,
FORCE_HRR, FORCE_HRR,
ENABLE_REDESIGN ENABLE_REDESIGN,
RELEASE_CHANNEL_TAG
} }
private fun defaultValueForBooleanKey(key: Key): Boolean { private fun defaultValueForBooleanKey(key: Key): Boolean {
return when (key) { return when (key) {
Key.UPDATE_AUTOMATICALLY, Key.FORCE_HRR -> true Key.UPDATE_AUTOMATICALLY, Key.FORCE_HRR -> true
Key.RELEASE_CHANNEL -> BuildConfig.DEBUG
else -> false else -> false
} }
} }
private fun defaultValueForIntKey(key: Key) = when (key) { private fun defaultValueForIntKey(key: Key) = when (key) {
Key.DISPLAY_MODE -> if (this.getBoolean(Key.LIMIT_ASPECT_RATIO)) 1 else 0 Key.DISPLAY_MODE -> if (this.getBoolean(Key.LIMIT_ASPECT_RATIO)) 1 else 0
// people wanted a reset on nightly anyways, so this is a good excuse to do so
else -> 0 else -> 0
} }
@@ -170,6 +171,7 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
Key.DISPLAY_MODE -> "PreferenceDisplayMode" Key.DISPLAY_MODE -> "PreferenceDisplayMode"
Key.FORCE_HRR -> "PreferenceForceHighRefreshRate" Key.FORCE_HRR -> "PreferenceForceHighRefreshRate"
Key.ENABLE_REDESIGN -> "PreferenceEnableRedesign" Key.ENABLE_REDESIGN -> "PreferenceEnableRedesign"
Key.RELEASE_CHANNEL_TAG -> "PreferenceReleaseChannelTag"
} }
} }
+6
View File
@@ -134,6 +134,12 @@
<string name="preference_update_automatically_name">Enable automatic updates</string> <string name="preference_update_automatically_name">Enable automatic updates</string>
<string name="preference_release_channel_name">Use nightly release channel</string> <string name="preference_release_channel_name">Use nightly release channel</string>
<string name="preference_release_channel_tag_name">Release channel</string>
<string name="preference_release_channel_select">Select release channel</string>
<string name="preference_release_channel_stable">Stable</string>
<string name="preference_release_channel_beta">Pre-release</string>
<string name="preference_release_channel_nightly">Nightly</string>
<string name="preference_check_for_updates_button">Check for updates</string> <string name="preference_check_for_updates_button">Check for updates</string>
<string name="preference_check_for_updates_description">Current loader version: %1$s</string> <string name="preference_check_for_updates_description">Current loader version: %1$s</string>
<string name="preference_launcher_version">Geode Launcher v%1$s</string> <string name="preference_launcher_version">Geode Launcher v%1$s</string>