Introduce AppUpdater

This commit is contained in:
FooIbar authored and tarsin committed 2023-07-11 06:53:09 +08:00
1 parent 5570933be4
commit a8c96fa7df
4 files changed
+96 -81

No files matched your search

@@ -29,34 +29,21 @@ import com.hippo.ehviewer.AppConfig
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.execute
import com.hippo.ehviewer.client.executeAndParseAs
import com.hippo.ehviewer.ui.LICENSE_SCREEN
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.rememberDialogState
import com.hippo.ehviewer.ui.tools.toAnnotatedString
import com.hippo.ehviewer.updater.AppUpdater
import com.hippo.ehviewer.util.ExceptionUtils
import com.hippo.ehviewer.util.installPackage
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.util.encodeBase64
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.Request
import okio.sink
import org.json.JSONObject
import tachiyomi.data.release.GithubArtifacts
import tachiyomi.data.release.GithubCommitComparison
import tachiyomi.data.release.GithubRelease
import tachiyomi.data.release.GithubWorkflowRuns
import java.io.File
import java.util.zip.ZipInputStream
private const val REPO_NAME = BuildConfig.REPO_NAME
private const val REPO_URL = "https://github.com/$REPO_NAME"
private const val API_URL = "https://api.github.com/repos/$REPO_NAME"
private const val REPO_URL = "https://github.com/${BuildConfig.REPO_NAME}"
private const val RELEASE_URL = "$REPO_URL/releases"
@Composable
@@ -97,7 +84,7 @@ fun AboutScreen() {
}
}
if (download) {
val file = File(AppConfig.tempDir, "tmp.apk").apply { delete() }
val file = File(AppConfig.tempDir, "update.apk").apply { delete() }
downloadTo(file)
withUIContext { context.installPackage(file) }
}
@@ -146,58 +133,11 @@ fun AboutScreen() {
)
WorkPreference(title = stringResource(id = R.string.settings_about_check_for_updates)) {
runSuspendCatching {
if (Settings.useCIUpdateChannel) {
val curSha = BuildConfig.COMMIT_SHA
val branch = ghRequest(API_URL).execute {
JSONObject(body.string()).getString("default_branch")
AppUpdater.checkForUpdate(true)?.run {
dialogState.showNewVersion(version, changelog) { file ->
AppUpdater.downloadUpdate(downloadLink, file)
}
val workflowRunsUrl = "$API_URL/actions/workflows/ci.yml/runs?branch=$branch&per_page=1"
val workflowRun = ghRequest(workflowRunsUrl).executeAndParseAs<GithubWorkflowRuns>().workflowRuns[0]
val shortSha = workflowRun.headSha.take(7)
if (shortSha != curSha) {
val artifacts = ghRequest(workflowRun.artifactsUrl).executeAndParseAs<GithubArtifacts>()
if (artifacts.artifacts.isNotEmpty()) {
val archiveUrl = artifacts.getDownloadLink()
val changelog = runSuspendCatching {
val commitComparisonUrl = "$API_URL/compare/$curSha...$shortSha"
val result = ghRequest(commitComparisonUrl).executeAndParseAs<GithubCommitComparison>()
result.commits.joinToString("\n") { "${it.commit.message} (@${it.author.name})" }
}.getOrDefault(workflowRun.title)
dialogState.showNewVersion(shortSha, changelog) { file ->
ghRequest(archiveUrl).execute {
ZipInputStream(body.byteStream()).use { zip ->
zip.nextEntry
file.outputStream().use {
zip.copyTo(it)
}
}
}
}
} else {
launchSnackBar(context.getString(R.string.ci_is_running))
}
} else {
launchSnackBar(context.getString(R.string.already_latest_ci_build))
}
} else {
val curVersion = BuildConfig.VERSION_NAME
val releaseUrl = "$API_URL/releases/latest"
val release = ghRequest(releaseUrl).executeAndParseAs<GithubRelease>()
val latestVersion = release.version
val description = release.info
val downloadUrl = release.getDownloadLink()
if (latestVersion != curVersion) {
dialogState.showNewVersion(latestVersion, description) { file ->
ghRequest(downloadUrl).execute {
file.sink().use {
body.source().readAll(it)
}
}
}
} else {
launchSnackBar(context.getString(R.string.already_latest_release, latestVersion))
}
}
} ?: launchSnackBar(context.getString(R.string.already_latest_version))
}.onFailure {
launchSnackBar(ExceptionUtils.getReadableString(it))
}
@@ -205,11 +145,3 @@ fun AboutScreen() {
}
}
}
private inline fun ghRequest(url: String, builder: Request.Builder.() -> Unit = {}) = Request.Builder().url(url).apply {
logcat { url }
val token = "github_" + "pat_11AXZS" + "T4A0k3TArCGakP3t_7DzUE5S" + "mr1zw8rmmzVtCeRq62" + "A4qkuDMw6YQm5ZUtHSLZ2MLI3J4VSifLXZ"
val user = "nullArrayList"
val base64 = "$user:$token".encodeBase64()
addHeader("Authorization", "Basic $base64")
}.apply(builder).build()
@@ -0,0 +1,87 @@
package com.hippo.ehviewer.updater
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.execute
import com.hippo.ehviewer.client.executeAndParseAs
import eu.kanade.tachiyomi.util.system.logcat
import io.ktor.util.encodeBase64
import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.Request
import okio.sink
import org.json.JSONObject
import tachiyomi.data.release.GithubArtifacts
import tachiyomi.data.release.GithubCommitComparison
import tachiyomi.data.release.GithubRelease
import tachiyomi.data.release.GithubWorkflowRuns
import java.io.File
import java.util.zip.ZipInputStream
private const val API_URL = "https://api.github.com/repos/${BuildConfig.REPO_NAME}"
private const val LATEST_RELEASE_URL = "$API_URL/releases/latest"
object AppUpdater {
suspend fun checkForUpdate(forceCheck: Boolean = false): Release? {
if (forceCheck) {
if (Settings.useCIUpdateChannel) {
val curSha = BuildConfig.COMMIT_SHA
val branch = ghRequest(API_URL).execute {
JSONObject(body.string()).getString("default_branch")
}
val workflowRunsUrl = "$API_URL/actions/workflows/ci.yml/runs?branch=$branch&status=success&per_page=1"
val workflowRun = ghRequest(workflowRunsUrl).executeAndParseAs<GithubWorkflowRuns>().workflowRuns[0]
val shortSha = workflowRun.headSha.take(7)
if (shortSha != curSha) {
val artifacts = ghRequest(workflowRun.artifactsUrl).executeAndParseAs<GithubArtifacts>()
val archiveUrl = artifacts.getDownloadLink()
val changelog = runSuspendCatching {
val commitComparisonUrl = "$API_URL/compare/$curSha...$shortSha"
val result = ghRequest(commitComparisonUrl).executeAndParseAs<GithubCommitComparison>()
result.commits.joinToString("\n") { "${it.commit.message} (@${it.author.name})" }
}.getOrDefault(workflowRun.title)
return Release(shortSha, changelog, archiveUrl)
}
} else {
val curVersion = BuildConfig.VERSION_NAME
val release = ghRequest(LATEST_RELEASE_URL).executeAndParseAs<GithubRelease>()
val latestVersion = release.version
val description = release.info
val downloadUrl = release.getDownloadLink()
if (latestVersion != curVersion) {
return Release(latestVersion, description, downloadUrl)
}
}
}
return null
}
suspend fun downloadUpdate(url: String, file: File) =
ghRequest(url).execute {
if (url.endsWith("zip")) {
ZipInputStream(body.byteStream()).use { zip ->
zip.nextEntry
file.outputStream().use {
zip.copyTo(it)
}
}
} else {
file.sink().use {
body.source().readAll(it)
}
}
}
}
private inline fun ghRequest(url: String, builder: Request.Builder.() -> Unit = {}) = Request.Builder().url(url).apply {
logcat { url }
val token = "github_" + "pat_11AXZS" + "T4A0k3TArCGakP3t_7DzUE5S" + "mr1zw8rmmzVtCeRq62" + "A4qkuDMw6YQm5ZUtHSLZ2MLI3J4VSifLXZ"
val user = "nullArrayList"
val base64 = "$user:$token".encodeBase64()
addHeader("Authorization", "Basic $base64")
}.apply(builder).build()
data class Release(
val version: String,
val changelog: String,
val downloadLink: String,
)
+1 -3
View File
@@ -511,9 +511,7 @@
<string name="account_name">账户</string>
<string name="preload_thumb_aggressively">激进地预载缩略图</string>
<string name="new_version_available">有新版本!</string>
<string name="ci_is_running">CI 正在运行,请稍候</string>
<string name="already_latest_ci_build">已是最新 CI 构建</string>
<string name="already_latest_release">已是最新版本 %s</string>
<string name="already_latest_version">已是最新版本</string>
<!-- Tachiyomi Reader Start-->
<string name="action_settings">设置</string>
<string name="action_retry">重试</string>
+1 -3
View File
@@ -574,9 +574,7 @@
<string name="account_name">Account</string>
<string name="preload_thumb_aggressively">Preload thumbs aggressively</string>
<string name="new_version_available">New version available!</string>
<string name="ci_is_running">CI is still running, please wait</string>
<string name="already_latest_ci_build">Already latest CI build</string>
<string name="already_latest_release">Already latest Release %s</string>
<string name="already_latest_version">Already the latest version</string>
<!-- Tachiyomi Reader Start-->
<string name="action_settings">Settings</string>
<string name="pref_rotation_type">Default rotation type</string>