Tweak the app updater logic and add FOSS build support (mihonapp/mihon#1843)
(cherry picked from commit 28093935d867e5d1a95944e67c6d1eb46cab4a37)
This commit is contained in:
parent
ad090eac85
commit
cde9a34238
11 changed files with 132 additions and 111 deletions
|
|
@ -134,7 +134,7 @@ object AboutScreen : Screen() {
|
|||
versionName = result.release.version,
|
||||
changelogInfo = result.release.info,
|
||||
releaseLink = result.release.releaseLink,
|
||||
downloadLink = result.release.getDownloadLink(),
|
||||
downloadLink = result.release.downloadLink,
|
||||
)
|
||||
navigator.push(updateScreen)
|
||||
},
|
||||
|
|
@ -211,7 +211,7 @@ object AboutScreen : Screen() {
|
|||
versionName = result.release.version,
|
||||
changelogInfo = result.release.info,
|
||||
releaseLink = result.release.releaseLink,
|
||||
downloadLink = result.release.getDownloadLink(),
|
||||
downloadLink = result.release.downloadLink,
|
||||
)
|
||||
navigator.push(updateScreen)
|
||||
},
|
||||
|
|
@ -352,7 +352,7 @@ object AboutScreen : Screen() {
|
|||
val updateChecker = AppUpdateChecker()
|
||||
withUIContext {
|
||||
try {
|
||||
when (val result = withIOContext { updateChecker.getReleaseNotes(context) }) {
|
||||
when (val result = withIOContext { updateChecker.getReleaseNotes() }) {
|
||||
is GetApplicationRelease.Result.NewUpdate -> {
|
||||
onAvailableUpdate(result)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.updater
|
|||
import android.content.Context
|
||||
import android.os.Build
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.util.system.isFossBuildType
|
||||
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.UnsortedPreferences
|
||||
|
|
@ -34,6 +35,7 @@ class AppUpdateChecker(
|
|||
return withIOContext {
|
||||
val result = getApplicationRelease.await(
|
||||
GetApplicationRelease.Arguments(
|
||||
isFoss = isFossBuildType,
|
||||
isPreview = isPreviewBuildType || peekIntoPreview,
|
||||
commitCount = BuildConfig.COMMIT_COUNT.toInt(),
|
||||
versionName = BuildConfig.VERSION_NAME,
|
||||
|
|
@ -61,7 +63,7 @@ class AppUpdateChecker(
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
AppUpdateDownloadJob.start(
|
||||
context = context,
|
||||
url = result.release.getDownloadLink(),
|
||||
url = result.release.downloadLink,
|
||||
title = result.release.version,
|
||||
scheduled = true,
|
||||
)
|
||||
|
|
@ -75,10 +77,11 @@ class AppUpdateChecker(
|
|||
}
|
||||
|
||||
// KMK -->
|
||||
suspend fun getReleaseNotes(context: Context): GetApplicationRelease.Result {
|
||||
suspend fun getReleaseNotes(): GetApplicationRelease.Result {
|
||||
return withIOContext {
|
||||
getApplicationRelease.awaitReleaseNotes(
|
||||
GetApplicationRelease.Arguments(
|
||||
isFoss = isFossBuildType,
|
||||
isPreview = isPreviewBuildType || peekIntoPreview,
|
||||
commitCount = BuildConfig.COMMIT_COUNT.toInt(),
|
||||
versionName = BuildConfig.VERSION_NAME,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ internal class AppUpdateNotifier(private val context: Context) {
|
|||
fun promptUpdate(release: Release) {
|
||||
val updateIntent = NotificationReceiver.downloadAppUpdatePendingBroadcast(
|
||||
context,
|
||||
release.getDownloadLink(),
|
||||
release.downloadLink,
|
||||
release.version,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ class MainActivity : BaseActivity() {
|
|||
versionName = result.release.version,
|
||||
changelogInfo = result.release.info,
|
||||
releaseLink = result.release.releaseLink,
|
||||
downloadLink = result.release.getDownloadLink(),
|
||||
downloadLink = result.release.downloadLink,
|
||||
)
|
||||
navigator.push(updateScreen)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,3 +18,6 @@ val isPreviewBuildType: Boolean
|
|||
|
||||
val isReleaseBuildType: Boolean
|
||||
inline get() = BuildConfig.BUILD_TYPE == "release"
|
||||
|
||||
val isFossBuildType: Boolean
|
||||
inline get() = BuildConfig.BUILD_TYPE == "foss"
|
||||
|
|
|
|||
|
|
@ -2,78 +2,34 @@ package tachiyomi.data.release
|
|||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import tachiyomi.domain.release.model.Release
|
||||
|
||||
/**
|
||||
* Contains information about the latest release from GitHub.
|
||||
*/
|
||||
@Serializable
|
||||
data class GithubRelease(
|
||||
@SerialName("tag_name") val version: String,
|
||||
@SerialName("body") val info: String,
|
||||
@SerialName("html_url") val releaseLink: String,
|
||||
@SerialName("assets") val assets: List<GitHubAssets>,
|
||||
@SerialName("tag_name")
|
||||
val version: String,
|
||||
@SerialName("body")
|
||||
val info: String,
|
||||
@SerialName("html_url")
|
||||
val releaseLink: String,
|
||||
@SerialName("assets")
|
||||
val assets: List<GitHubAsset>,
|
||||
// KMK -->
|
||||
@SerialName("prerelease") val preRelease: Boolean = false,
|
||||
@SerialName("draft") val draft: Boolean = false,
|
||||
@SerialName("prerelease")
|
||||
val preRelease: Boolean = false,
|
||||
@SerialName("draft")
|
||||
val draft: Boolean = false,
|
||||
// KMK <--
|
||||
)
|
||||
|
||||
/**
|
||||
* Assets class containing download url.
|
||||
* Asset class containing asset name and download url.
|
||||
*/
|
||||
@Serializable
|
||||
data class GitHubAssets(@SerialName("browser_download_url") val downloadLink: String)
|
||||
|
||||
/**
|
||||
* Regular expression that matches a mention to a valid GitHub username, like it's
|
||||
* done in GitHub Flavored Markdown. It follows these constraints:
|
||||
*
|
||||
* - Alphanumeric with single hyphens (no consecutive hyphens)
|
||||
* - Cannot begin or end with a hyphen
|
||||
* - Max length of 39 characters
|
||||
*
|
||||
* Convert '(@cuong-tran)' to '([@cuong-tran](https://github.com/cuong-tran))'
|
||||
*
|
||||
* Reference: https://stackoverflow.com/a/30281147
|
||||
*/
|
||||
val gitHubUsernameMentionRegex =
|
||||
"""\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))""".toRegex(
|
||||
RegexOption.IGNORE_CASE,
|
||||
)
|
||||
|
||||
// KMK -->
|
||||
/**
|
||||
* Convert from: https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6
|
||||
* to: [komikku-app/komikku@23d862d17...48fb4a2e6](https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6)
|
||||
*/
|
||||
val gitHubCommitsCompareRegex =
|
||||
"""(\[[^]]+]\()?https://github.com/(?<owner>[^/]+)/(?<repo>[^/]+)/compare/(?<from>[0-9a-f.rv]+)\.\.\.(?<to>[0-9a-f.rv]+)\)?"""
|
||||
.toRegex(RegexOption.IGNORE_CASE)
|
||||
// KMK <--
|
||||
|
||||
val releaseMapper: (GithubRelease) -> Release = {
|
||||
Release(
|
||||
it.version,
|
||||
it.info
|
||||
.replace(gitHubUsernameMentionRegex) { mention ->
|
||||
"[${mention.value}](https://github.com/${mention.value.substring(1)})"
|
||||
}
|
||||
// KMK -->
|
||||
.replace(gitHubCommitsCompareRegex) { matchResult ->
|
||||
val owner = matchResult.groups["owner"]!!.value
|
||||
val repo = matchResult.groups["repo"]!!.value
|
||||
val from = matchResult.groups["from"]!!.value
|
||||
val to = matchResult.groups["to"]!!.value
|
||||
|
||||
"[$owner/$repo@$from...$to](https://github.com/$owner/$repo/compare/$from...$to)"
|
||||
},
|
||||
// KMK <--
|
||||
it.releaseLink,
|
||||
it.assets.map(GitHubAssets::downloadLink),
|
||||
// KMK -->
|
||||
preRelease = it.preRelease,
|
||||
draft = it.draft,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
data class GitHubAsset(
|
||||
val name: String,
|
||||
@SerialName("browser_download_url")
|
||||
val downloadLink: String,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package tachiyomi.data.release
|
||||
|
||||
import android.os.Build
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import tachiyomi.domain.release.interactor.GetApplicationRelease
|
||||
import tachiyomi.domain.release.model.Release
|
||||
import tachiyomi.domain.release.service.ReleaseService
|
||||
|
||||
|
|
@ -13,26 +15,101 @@ class ReleaseServiceImpl(
|
|||
private val json: Json,
|
||||
) : ReleaseService {
|
||||
|
||||
override suspend fun latest(repository: String): Release {
|
||||
return with(json) {
|
||||
override suspend fun latest(arguments: GetApplicationRelease.Arguments): Release? {
|
||||
val release = with(json) {
|
||||
networkService.client
|
||||
.newCall(GET("https://api.github.com/repos/$repository/releases/latest"))
|
||||
.newCall(GET("https://api.github.com/repos/${arguments.repository}/releases/latest"))
|
||||
.awaitSuccess()
|
||||
.parseAs<GithubRelease>()
|
||||
.let(releaseMapper)
|
||||
}
|
||||
|
||||
val downloadLink = getDownloadLink(release = release, isFoss = arguments.isFoss) ?: return null
|
||||
|
||||
return Release(
|
||||
version = release.version,
|
||||
info = release.info.replace(gitHubUsernameMentionRegex) { mention ->
|
||||
"[${mention.value}](https://github.com/${mention.value.substring(1)})"
|
||||
},
|
||||
releaseLink = release.releaseLink,
|
||||
downloadLink = downloadLink,
|
||||
)
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
override suspend fun releaseNotes(repository: String): List<Release> {
|
||||
val releases = "https://api.github.com/repos/$repository/releases"
|
||||
override suspend fun releaseNotes(arguments: GetApplicationRelease.Arguments): List<Release> {
|
||||
return with(json) {
|
||||
networkService.client
|
||||
.newCall(GET(releases))
|
||||
.newCall(GET("https://api.github.com/repos/${arguments.repository}/releases/latest"))
|
||||
.awaitSuccess()
|
||||
.parseAs<List<GithubRelease>>()
|
||||
.map(releaseMapper)
|
||||
.mapNotNull { release ->
|
||||
val downloadLink = getDownloadLink(release = release, isFoss = arguments.isFoss) ?: return@mapNotNull null
|
||||
|
||||
Release(
|
||||
version = release.version,
|
||||
info = release.info.replace(gitHubUsernameMentionRegex) { mention ->
|
||||
"[${mention.value}](https://github.com/${mention.value.substring(1)})"
|
||||
}
|
||||
// KMK -->
|
||||
.replace(gitHubCommitsCompareRegex) { matchResult ->
|
||||
val owner = matchResult.groups["owner"]!!.value
|
||||
val repo = matchResult.groups["repo"]!!.value
|
||||
val from = matchResult.groups["from"]!!.value
|
||||
val to = matchResult.groups["to"]!!.value
|
||||
|
||||
"[$owner/$repo@$from...$to](https://github.com/$owner/$repo/compare/$from...$to)"
|
||||
},
|
||||
// KMK <--
|
||||
releaseLink = release.releaseLink,
|
||||
downloadLink = downloadLink,
|
||||
// KMK -->
|
||||
preRelease = release.preRelease,
|
||||
draft = release.draft,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
private fun getDownloadLink(release: GithubRelease, isFoss: Boolean): String? {
|
||||
val map = release.assets.associate { asset ->
|
||||
BUILD_TYPES.find { "-$it" in asset.name } to asset.downloadLink
|
||||
}
|
||||
|
||||
return if (!isFoss) {
|
||||
map[Build.SUPPORTED_ABIS[0]] ?: map[null]
|
||||
} else {
|
||||
map[FOSS]
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FOSS = "foss"
|
||||
private val BUILD_TYPES = listOf(FOSS, "arm64-v8a", "armeabi-v7a", "x86_64", "x86")
|
||||
|
||||
/**
|
||||
* Regular expression that matches a mention to a valid GitHub username, like it's
|
||||
* done in GitHub Flavored Markdown. It follows these constraints:
|
||||
*
|
||||
* - Alphanumeric with single hyphens (no consecutive hyphens)
|
||||
* - Cannot begin or end with a hyphen
|
||||
* - Max length of 39 characters
|
||||
*
|
||||
* Convert '(@cuong-tran)' to '([@cuong-tran](https://github.com/cuong-tran))'
|
||||
*
|
||||
* Reference: https://stackoverflow.com/a/30281147
|
||||
*/
|
||||
private val gitHubUsernameMentionRegex = """\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))"""
|
||||
.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
// KMK -->
|
||||
/**
|
||||
* Convert from: https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6
|
||||
* to: [komikku-app/komikku@23d862d17...48fb4a2e6](https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6)
|
||||
*/
|
||||
private val gitHubCommitsCompareRegex = """(\[[^]]+]\()?https://github\.com/(?<owner>[^/]+)/(?<repo>[^/]+)/compare/(?<from>[0-9a-f.rv]+)\.\.\.(?<to>[0-9a-f.rv]+)\)?"""
|
||||
.toRegex(RegexOption.IGNORE_CASE)
|
||||
// KMK <--
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class GetApplicationRelease(
|
|||
}
|
||||
|
||||
// KMK -->
|
||||
val releases = service.releaseNotes(arguments.repository)
|
||||
val releases = service.releaseNotes(arguments)
|
||||
.filter {
|
||||
!it.preRelease &&
|
||||
isNewVersion(
|
||||
|
|
@ -57,7 +57,7 @@ class GetApplicationRelease(
|
|||
|
||||
// KMK -->
|
||||
suspend fun awaitReleaseNotes(arguments: Arguments): Result {
|
||||
val releases = service.releaseNotes(arguments.repository)
|
||||
val releases = service.releaseNotes(arguments)
|
||||
.filter { !it.preRelease }
|
||||
val checksumRegex = """---(\R|.)*Checksums(\R|.)*""".toRegex()
|
||||
|
||||
|
|
@ -114,6 +114,7 @@ class GetApplicationRelease(
|
|||
}
|
||||
|
||||
data class Arguments(
|
||||
val isFoss: Boolean,
|
||||
/** If current version is Preview (beta) build */
|
||||
val isPreview: Boolean,
|
||||
/** Commit count of current version */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package tachiyomi.domain.release.model
|
||||
|
||||
import android.os.Build
|
||||
|
||||
/**
|
||||
* Contains information about the latest release.
|
||||
*/
|
||||
|
|
@ -9,31 +7,9 @@ data class Release(
|
|||
val version: String,
|
||||
val info: String,
|
||||
val releaseLink: String,
|
||||
private val assets: List<String>,
|
||||
val downloadLink: String,
|
||||
// KMK -->
|
||||
val preRelease: Boolean = false,
|
||||
val draft: Boolean = false,
|
||||
// KMK <--
|
||||
) {
|
||||
|
||||
/**
|
||||
* Get download link of latest release from the assets.
|
||||
* @return download link of latest release.
|
||||
*/
|
||||
fun getDownloadLink(): String {
|
||||
val apkVariant = when (Build.SUPPORTED_ABIS[0]) {
|
||||
"arm64-v8a" -> "-arm64-v8a"
|
||||
"armeabi-v7a" -> "-armeabi-v7a"
|
||||
"x86" -> "-x86"
|
||||
"x86_64" -> "-x86_64"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
return assets.find { it.contains("Komikku$apkVariant-") } ?: assets[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Assets class containing download url.
|
||||
*/
|
||||
data class Assets(val downloadLink: String)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
package tachiyomi.domain.release.service
|
||||
|
||||
import tachiyomi.domain.release.interactor.GetApplicationRelease
|
||||
import tachiyomi.domain.release.model.Release
|
||||
|
||||
interface ReleaseService {
|
||||
|
||||
suspend fun latest(repository: String): Release
|
||||
suspend fun latest(arguments: GetApplicationRelease.Arguments): Release?
|
||||
|
||||
// KMK -->
|
||||
suspend fun releaseNotes(repository: String): List<Release>
|
||||
suspend fun releaseNotes(arguments: GetApplicationRelease.Arguments): List<Release>
|
||||
// KMK <--
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class GetApplicationReleaseTest {
|
|||
"r2000",
|
||||
"info",
|
||||
"http://example.com/release_link",
|
||||
listOf("http://example.com/assets"),
|
||||
"http://example.com/release_link.apk",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -48,6 +48,7 @@ class GetApplicationReleaseTest {
|
|||
|
||||
val result = getApplicationRelease.await(
|
||||
GetApplicationRelease.Arguments(
|
||||
isFoss = false,
|
||||
isPreview = true,
|
||||
commitCount = 1000,
|
||||
versionName = "",
|
||||
|
|
@ -70,7 +71,7 @@ class GetApplicationReleaseTest {
|
|||
"v2.0.0",
|
||||
"info",
|
||||
"http://example.com/release_link",
|
||||
listOf("http://example.com/assets"),
|
||||
"http://example.com/release_link.apk",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -78,6 +79,7 @@ class GetApplicationReleaseTest {
|
|||
|
||||
val result = getApplicationRelease.await(
|
||||
GetApplicationRelease.Arguments(
|
||||
isFoss = false,
|
||||
isPreview = false,
|
||||
commitCount = 0,
|
||||
versionName = "v1.0.0",
|
||||
|
|
@ -99,7 +101,7 @@ class GetApplicationReleaseTest {
|
|||
"v1.0.0",
|
||||
"info",
|
||||
"http://example.com/release_link",
|
||||
listOf("http://example.com/assets"),
|
||||
"http://example.com/release_link.apk",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -107,6 +109,7 @@ class GetApplicationReleaseTest {
|
|||
|
||||
val result = getApplicationRelease.await(
|
||||
GetApplicationRelease.Arguments(
|
||||
isFoss = false,
|
||||
isPreview = false,
|
||||
commitCount = 0,
|
||||
versionName = "v2.0.0",
|
||||
|
|
@ -127,7 +130,7 @@ class GetApplicationReleaseTest {
|
|||
"v2.0.0",
|
||||
"info",
|
||||
"http://example.com/release_link",
|
||||
listOf("http://example.com/assets"),
|
||||
"http://example.com/release_link.apk",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -135,6 +138,7 @@ class GetApplicationReleaseTest {
|
|||
|
||||
val result = getApplicationRelease.await(
|
||||
GetApplicationRelease.Arguments(
|
||||
isFoss = false,
|
||||
isPreview = false,
|
||||
commitCount = 0,
|
||||
versionName = "v1.0.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue