Deprecate canary channel

This commit is contained in:
topjohnwu 2025-06-20 00:22:17 -07:00
parent 39f2940bd1
commit 04008949b8
7 changed files with 53 additions and 63 deletions

View File

@ -14,9 +14,8 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.BuildConfig.APP_VERSION_CODE
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.ContentResultCallback
import com.topjohnwu.magisk.core.ktx.toast
@ -70,17 +69,16 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
init {
viewModelScope.launch(Dispatchers.IO) {
try {
val file = File(AppContext.cacheDir, "${BuildConfig.APP_VERSION_CODE}.md")
val text = when {
file.exists() -> file.readText()
val noteFile = File(AppContext.cacheDir, "${APP_VERSION_CODE}.md")
val noteText = when {
noteFile.exists() -> noteFile.readText()
else -> {
val str = if (Const.APP_IS_CANARY) Info.update.note
else svc.fetchString(Const.Url.CHANGELOG_URL)
file.writeText(str)
str
val note = svc.fetchUpdate(APP_VERSION_CODE).note
noteFile.writeText(note)
note
}
}
val spanned = markwon.toMarkdown(text)
val spanned = markwon.toMarkdown(noteText)
withContext(Dispatchers.Main) {
notes = spanned
}

View File

@ -151,15 +151,7 @@ object UpdateChannel : BaseSettingsItem.Selector() {
}
override val title = CoreR.string.settings_update_channel_title.asText()
override val entryRes = CoreR.array.update_channel
override fun entries(res: Resources): Array<String> {
return super.entries(res).let {
if (!Const.APP_IS_CANARY && !BuildConfig.DEBUG)
it.copyOfRange(0, Config.Value.CANARY_CHANNEL)
else it
}
}
}
object UpdateChannelUrl : BaseSettingsItem.Input() {

View File

@ -33,7 +33,7 @@ object Config : PreferenceConfig, DBConfig {
const val SU_REAUTH = "su_reauth"
const val SU_TAPJACK = "su_tapjack"
const val CHECK_UPDATES = "check_update"
const val UPDATE_CHANNEL = "update_channel"
const val RELEASE_CHANNEL = "release_channel"
const val CUSTOM_CHANNEL = "custom_channel"
const val LOCALE = "locale"
const val DARK_THEME = "dark_theme_extended"
@ -48,7 +48,7 @@ object Config : PreferenceConfig, DBConfig {
SU_AUTO_RESPONSE, SU_REAUTH, SU_TAPJACK)
}
object Value {
object OldValue {
// Update channels
const val DEFAULT_CHANNEL = -1
const val STABLE_CHANNEL = 0
@ -56,6 +56,15 @@ object Config : PreferenceConfig, DBConfig {
const val CUSTOM_CHANNEL = 2
const val CANARY_CHANNEL = 3
const val DEBUG_CHANNEL = 4
}
object Value {
// Update channels
const val DEFAULT_CHANNEL = -1
const val STABLE_CHANNEL = 0
const val BETA_CHANNEL = 1
const val DEBUG_CHANNEL = 2
const val CUSTOM_CHANNEL = 3
// root access mode
const val ROOT_ACCESS_DISABLED = 0
@ -86,14 +95,6 @@ object Config : PreferenceConfig, DBConfig {
val TIMEOUT_LIST = longArrayOf(0, -1, 10, 20, 30, 60)
}
private val defaultChannel =
if (BuildConfig.DEBUG)
Value.DEBUG_CHANNEL
else if (Const.APP_IS_CANARY)
Value.CANARY_CHANNEL
else
Value.DEFAULT_CHANNEL
@JvmField var keepVerity = false
@JvmField var keepEnc = false
@JvmField var recovery = false
@ -109,7 +110,7 @@ object Config : PreferenceConfig, DBConfig {
private var checkUpdatePrefs by preference(Key.CHECK_UPDATES, true)
private var localePrefs by preference(Key.LOCALE, "")
var doh by preference(Key.DOH, false)
var updateChannel by preferenceStrInt(Key.UPDATE_CHANNEL, defaultChannel)
var updateChannel by preference(Key.RELEASE_CHANNEL, Value.DEFAULT_CHANNEL)
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
var downloadDir by preference(Key.DOWNLOAD_DIR, "")
var randName by preference(Key.RAND_NAME, true)
@ -148,6 +149,7 @@ object Config : PreferenceConfig, DBConfig {
var suTapjack by preference(Key.SU_TAPJACK, true)
private const val SU_FINGERPRINT = "su_fingerprint"
private const val UPDATE_CHANNEL = "update_channel"
fun toBundle(): Bundle {
val map = prefs.all - Key.NO_MIGRATION
@ -183,17 +185,23 @@ object Config : PreferenceConfig, DBConfig {
}
prefs.edit {
// Settings migration
// Migrate su_fingerprint
if (prefs.getBoolean(SU_FINGERPRINT, false))
suBiometric = true
remove(SU_FINGERPRINT)
prefs.getString(Key.UPDATE_CHANNEL, null).also {
if (it == null ||
it.toInt() > Value.DEBUG_CHANNEL ||
it.toInt() < Value.DEFAULT_CHANNEL) {
putString(Key.UPDATE_CHANNEL, defaultChannel.toString())
// Migrate update_channel
prefs.getString(UPDATE_CHANNEL, null)?.let {
val channel = when (it.toInt()) {
OldValue.STABLE_CHANNEL -> Value.STABLE_CHANNEL
OldValue.CANARY_CHANNEL, OldValue.BETA_CHANNEL -> Value.BETA_CHANNEL
OldValue.DEBUG_CHANNEL -> Value.DEBUG_CHANNEL
OldValue.CUSTOM_CHANNEL -> Value.CUSTOM_CHANNEL
else -> Value.DEFAULT_CHANNEL
}
putInt(Key.RELEASE_CHANNEL, channel)
}
remove(UPDATE_CHANNEL)
}
}
}

View File

@ -21,18 +21,14 @@ object Const {
// Misc
val USER_ID = Process.myUid() / 100000
val APP_IS_CANARY get() = Version.isCanary(APP_VERSION_CODE)
object Version {
const val MIN_VERSION = "v22.0"
const val MIN_VERCODE = 22000
fun atLeast_24_0() = Info.env.versionCode >= 24000 || isCanary()
fun atLeast_25_0() = Info.env.versionCode >= 25000 || isCanary()
fun atLeast_28_0() = Info.env.versionCode >= 28000 || isCanary()
fun isCanary() = isCanary(Info.env.versionCode)
fun isCanary(ver: Int) = ver > 0 && ver % 100 != 0
fun atLeast_24_0() = Info.env.versionCode >= 24000
fun atLeast_25_0() = Info.env.versionCode >= 25000
fun atLeast_28_0() = Info.env.versionCode >= 28000
}
object ID {
@ -44,8 +40,6 @@ object Const {
const val PATREON_URL = "https://www.patreon.com/topjohnwu"
const val SOURCE_CODE_URL = "https://github.com/topjohnwu/Magisk"
const val CHANGELOG_URL = "https://topjohnwu.github.io/Magisk/releases/${APP_VERSION_CODE}.md"
const val GITHUB_API_URL = "https://api.github.com/"
const val GITHUB_PAGE_URL = "https://topjohnwu.github.io/magisk-files/"
const val INVALID_URL = "https://example.com/"

View File

@ -1,8 +1,8 @@
package com.topjohnwu.magisk.core.repository
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Config.Value.BETA_CHANNEL
import com.topjohnwu.magisk.core.Config.Value.CANARY_CHANNEL
import com.topjohnwu.magisk.core.Config.Value.CUSTOM_CHANNEL
import com.topjohnwu.magisk.core.Config.Value.DEBUG_CHANNEL
import com.topjohnwu.magisk.core.Config.Value.DEFAULT_CHANNEL
@ -24,21 +24,25 @@ class NetworkService(
) {
suspend fun fetchUpdate() = safe {
var info = when (Config.updateChannel) {
DEFAULT_CHANNEL, STABLE_CHANNEL -> fetchStableUpdate()
DEFAULT_CHANNEL -> if (BuildConfig.DEBUG) fetchDebugUpdate() else fetchStableUpdate()
STABLE_CHANNEL -> fetchStableUpdate()
BETA_CHANNEL -> fetchBetaUpdate()
CANARY_CHANNEL -> fetchCanaryUpdate()
DEBUG_CHANNEL -> fetchDebugUpdate()
CUSTOM_CHANNEL -> fetchCustomUpdate(Config.customChannelUrl)
else -> throw IllegalArgumentException()
}
if (info.versionCode < Info.env.versionCode &&
Config.updateChannel == DEFAULT_CHANNEL) {
Config.updateChannel == DEFAULT_CHANNEL &&
!BuildConfig.DEBUG
) {
Config.updateChannel = BETA_CHANNEL
info = fetchBetaUpdate()
}
info
}
suspend fun fetchUpdate(version: Int) = findRelease { it.versionCode == version }.asInfo()
// Keep going through all release pages until we find a match
private suspend inline fun findRelease(predicate: (Release) -> Boolean): Release? {
var page = 1
@ -58,14 +62,13 @@ class NetworkService(
}
}
suspend fun fetchUpdate(version: Int) = findRelease { it.versionCode == version }?.asInfo()
private inline fun Release.asInfo(
private inline fun Release?.asInfo(
selector: (ReleaseAssets) -> Boolean = {
// Default selector picks the non-debug APK
it.name.run { endsWith(".apk") && !contains("debug") }
}): UpdateInfo {
return if (tag[0] == 'v') asPublicInfo(selector)
return if (this == null) UpdateInfo()
else if (tag[0] == 'v') asPublicInfo(selector)
else asCanaryInfo(selector)
}
@ -89,20 +92,16 @@ class NetworkService(
)
}
// Version number: canary == debug >= beta >= stable
// Version number: debug == beta >= stable
// Find the latest non-prerelease
private suspend fun fetchStableUpdate() = api.fetchLatestRelease().asInfo()
// Find the latest non-canary release
private suspend fun fetchBetaUpdate() = findRelease { it.tag[0] == 'v' }!!.asInfo()
// Find the latest release, regardless whether it's prerelease
private suspend fun fetchCanary() = findRelease { true }!!
private suspend fun fetchBetaUpdate() = findRelease { true }.asInfo()
private suspend fun fetchCanaryUpdate() = fetchCanary().asInfo()
private suspend fun fetchDebugUpdate() = fetchCanary().asInfo { it.name == "app-debug.apk" }
private suspend fun fetchDebugUpdate() =
findRelease { true }.asInfo { it.name == "app-debug.apk" }
private suspend fun fetchCustomUpdate(url: String): UpdateInfo {
val info = raw.fetchUpdateJson(url).magisk

View File

@ -63,9 +63,7 @@
<string-array name="update_channel">
<item>@string/settings_update_stable</item>
<item>@string/settings_update_beta</item>
<item>@string/settings_update_debug</item>
<item>@string/settings_update_custom</item>
<item>Canary</item>
<item>Debug</item>
</string-array>
</resources>

View File

@ -139,6 +139,7 @@
<string name="settings_update_channel_title">Update Channel</string>
<string name="settings_update_stable">Stable</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_debug">Debug</string>
<string name="settings_update_custom">Custom</string>
<string name="settings_update_custom_msg">Insert a custom channel URL</string>
<string name="settings_zygisk_summary">Run parts of Magisk in the zygote daemon</string>