feat(Home): Aliucord installation up-to-date check

This commit is contained in:
rushiiMachine 2025-01-25 00:35:11 -08:00
parent 7737d2aaa5
commit 56bf5219f3
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
3 changed files with 43 additions and 6 deletions

View file

@ -2,6 +2,7 @@ package com.aliucord.manager.ui.screens.home
import android.app.Application
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.provider.Settings
@ -18,15 +19,22 @@ import cafe.adriel.voyager.core.model.screenModelScope
import com.aliucord.manager.BuildConfig
import com.aliucord.manager.R
import com.aliucord.manager.domain.repository.GithubRepository
import com.aliucord.manager.network.dto.BuildInfo
import com.aliucord.manager.network.utils.fold
import com.aliucord.manager.patcher.InstallMetadata
import com.aliucord.manager.ui.util.DiscordVersion
import com.aliucord.manager.util.launchBlock
import com.aliucord.manager.util.showToast
import com.github.diamondminer88.zip.ZipReader
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
class HomeModel(
private val application: Application,
private val github: GithubRepository,
private val json: Json,
) : ScreenModel {
var supportedVersion by mutableStateOf<DiscordVersion>(DiscordVersion.None)
private set
@ -34,6 +42,8 @@ class HomeModel(
var installations by mutableStateOf<InstallsState>(InstallsState.Fetching)
private set
private var remoteDataJson: BuildInfo? = null
init {
// fetchInstallations() is called from UI
fetchSupportedVersion()
@ -115,13 +125,10 @@ class HomeModel(
val versionName = it.versionName ?: return@mapNotNull null
val applicationInfo = it.applicationInfo ?: return@mapNotNull null
val baseVersion = it.applicationInfo?.metaData?.getInt("aliucordBaseVersion")
val isBaseUpdated = /* TODO: remote data json instead */ baseVersion == 0
InstallData(
name = packageManager.getApplicationLabel(applicationInfo).toString(),
packageName = it.packageName,
baseUpdated = isBaseUpdated,
isUpToDate = isInstallationUpToDate(it),
icon = packageManager
.getApplicationIcon(applicationInfo)
.toBitmap()
@ -163,4 +170,34 @@ class HomeModel(
}
)
}
private fun isInstallationUpToDate(pkg: PackageInfo): Boolean {
// `longVersionCode` is unnecessary since Discord doesn't use `versionCodeMajor`
@Suppress("DEPRECATION")
val versionCode = pkg.versionCode
// Check if the base APK version is a mismatch
val supportedVersion = (supportedVersion as? DiscordVersion.Existing) ?: return true
if (supportedVersion.rawCode != versionCode) return false
// Try to parse install metadata. If none present, install was made via legacy installer.
val apkPath = pkg.applicationInfo?.publicSourceDir ?: return false
val installMetadata = try {
val metadataFile = ZipReader(apkPath).use { it.openEntry("aliucord.json")?.read() }
?: return false
@OptIn(ExperimentalSerializationApi::class)
json.decodeFromStream<InstallMetadata>(metadataFile.inputStream())
} catch (t: Throwable) {
Log.w(BuildConfig.TAG, "Failed to parse Aliucord install metadata from package ${pkg.packageName}", t)
return false
}
// Check that all the installation components are up-to-date
val remoteBuildData = remoteDataJson ?: return true
// TODO: check for aliuhook version too once aliuhook starts using semver
return remoteBuildData.injectorVersion > installMetadata.injectorVersion ||
remoteBuildData.patchesVersion > installMetadata.patchesVersion
}
}

View file

@ -10,5 +10,5 @@ data class InstallData(
val packageName: String,
val version: DiscordVersion,
val icon: BitmapPainter,
val baseUpdated: Boolean,
val isUpToDate: Boolean,
)

View file

@ -111,7 +111,7 @@ fun InstalledItemCard(
onClick = onOpenInfo,
)
if (data.baseUpdated) {
if (data.isUpToDate) {
SegmentedButton(
icon = painterResource(R.drawable.ic_launch),
text = stringResource(R.string.action_launch),