mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-22 08:42:38 +00:00
improved geode version selection
This commit is contained in:
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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in new issue
Block a user