Add automatic updates for dev builds (#2128)

This commit is contained in:
Eugene 2019-07-13 13:36:30 -04:00 committed by inorichi
parent e8638cb0b3
commit d5f5ba95bb
13 changed files with 147 additions and 34 deletions

View File

@ -1,7 +0,0 @@
package eu.kanade.tachiyomi.data.updater
sealed class GithubUpdateResult {
class NewUpdate(val release: GithubRelease): GithubUpdateResult()
class NoNewUpdate : GithubUpdateResult()
}

View File

@ -0,0 +1,13 @@
package eu.kanade.tachiyomi.data.updater
interface Release {
val info: String
/**
* Get download link of latest release.
* @return download link of latest release.
*/
val downloadLink: String
}

View File

@ -0,0 +1,25 @@
package eu.kanade.tachiyomi.data.updater
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.updater.devrepo.DevRepoUpdateChecker
import eu.kanade.tachiyomi.data.updater.github.GithubUpdateChecker
import rx.Observable
abstract class UpdateChecker {
companion object {
fun getUpdateChecker(): UpdateChecker {
return if (BuildConfig.DEBUG) {
DevRepoUpdateChecker()
} else {
GithubUpdateChecker()
}
}
}
/**
* Returns observable containing release information
*/
abstract fun checkForUpdate(): Observable<UpdateResult>
}

View File

@ -0,0 +1,8 @@
package eu.kanade.tachiyomi.data.updater
abstract class UpdateResult {
open class NewUpdate<T : Release>(val release: T): UpdateResult()
open class NoNewUpdate: UpdateResult()
}

View File

@ -13,10 +13,10 @@ import eu.kanade.tachiyomi.util.notificationManager
class UpdaterJob : Job() { class UpdaterJob : Job() {
override fun onRunJob(params: Params): Result { override fun onRunJob(params: Params): Result {
return GithubUpdateChecker() return UpdateChecker.getUpdateChecker()
.checkForUpdate() .checkForUpdate()
.map { result -> .map { result ->
if (result is GithubUpdateResult.NewUpdate) { if (result is UpdateResult.NewUpdate<*>) {
val url = result.release.downloadLink val url = result.release.downloadLink
val intent = Intent(context, UpdaterService::class.java).apply { val intent = Intent(context, UpdaterService::class.java).apply {
@ -33,9 +33,9 @@ class UpdaterJob : Job() {
PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)) PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
} }
} }
Job.Result.SUCCESS Result.SUCCESS
} }
.onErrorReturn { Job.Result.FAILURE } .onErrorReturn { Result.FAILURE }
// Sadly, the task needs to be synchronous. // Sadly, the task needs to be synchronous.
.toBlocking() .toBlocking()
.single() .single()

View File

@ -0,0 +1,14 @@
package eu.kanade.tachiyomi.data.updater.devrepo
import eu.kanade.tachiyomi.data.updater.Release
class DevRepoRelease(override val info: String) : Release {
override val downloadLink: String
get() = LATEST_URL
companion object {
const val LATEST_URL = "https://tachiyomi.kanade.eu/latest"
}
}

View File

@ -0,0 +1,40 @@
package eu.kanade.tachiyomi.data.updater.devrepo
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.updater.UpdateChecker
import eu.kanade.tachiyomi.data.updater.UpdateResult
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.asObservable
import okhttp3.OkHttpClient
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class DevRepoUpdateChecker : UpdateChecker() {
private val client: OkHttpClient by lazy {
Injekt.get<NetworkHelper>().client.newBuilder()
.followRedirects(false)
.build()
}
private val versionRegex: Regex by lazy {
Regex("tachiyomi-r(\\d+).apk")
}
override fun checkForUpdate(): Observable<UpdateResult> {
return client.newCall(GET(DevRepoRelease.LATEST_URL)).asObservable()
.map { response ->
// Get latest repo version number from header in format "Location: tachiyomi-r1512.apk"
val latestVersionNumber: String = versionRegex.find(response.header("Location")!!)!!.groupValues[1]
if (latestVersionNumber.toInt() > BuildConfig.COMMIT_COUNT.toInt()) {
DevRepoUpdateResult.NewUpdate(DevRepoRelease("v$latestVersionNumber"))
} else {
DevRepoUpdateResult.NoNewUpdate()
}
}
}
}

View File

@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.data.updater.devrepo
import eu.kanade.tachiyomi.data.updater.UpdateResult
sealed class DevRepoUpdateResult : UpdateResult() {
class NewUpdate(release: DevRepoRelease): UpdateResult.NewUpdate<DevRepoRelease>(release)
class NoNewUpdate: UpdateResult.NoNewUpdate()
}

View File

@ -1,24 +1,25 @@
package eu.kanade.tachiyomi.data.updater package eu.kanade.tachiyomi.data.updater.github
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import eu.kanade.tachiyomi.data.updater.Release
/** /**
* Release object. * Release object.
* Contains information about the latest release from Github. * Contains information about the latest release from Github.
* *
* @param version version of latest release. * @param version version of latest release.
* @param changeLog log of latest release. * @param info log of latest release.
* @param assets assets of latest release. * @param assets assets of latest release.
*/ */
class GithubRelease(@SerializedName("tag_name") val version: String, class GithubRelease(@SerializedName("tag_name") val version: String,
@SerializedName("body") val changeLog: String, @SerializedName("body") override val info: String,
@SerializedName("assets") private val assets: List<Assets>) { @SerializedName("assets") private val assets: List<Assets>): Release {
/** /**
* Get download link of latest release from the assets. * Get download link of latest release from the assets.
* @return download link of latest release. * @return download link of latest release.
*/ */
val downloadLink: String override val downloadLink: String
get() = assets[0].downloadLink get() = assets[0].downloadLink
/** /**

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.updater package eu.kanade.tachiyomi.data.updater.github
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import retrofit2.Retrofit import retrofit2.Retrofit

View File

@ -1,16 +1,15 @@
package eu.kanade.tachiyomi.data.updater package eu.kanade.tachiyomi.data.updater.github
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.updater.UpdateChecker
import eu.kanade.tachiyomi.data.updater.UpdateResult
import rx.Observable import rx.Observable
class GithubUpdateChecker { class GithubUpdateChecker : UpdateChecker() {
private val service: GithubService = GithubService.create() private val service: GithubService = GithubService.create()
/** override fun checkForUpdate(): Observable<UpdateResult> {
* Returns observable containing release information
*/
fun checkForUpdate(): Observable<GithubUpdateResult> {
return service.getLatestVersion().map { release -> return service.getLatestVersion().map { release ->
val newVersion = release.version.replace("[^\\d.]".toRegex(), "") val newVersion = release.version.replace("[^\\d.]".toRegex(), "")
@ -22,4 +21,5 @@ class GithubUpdateChecker {
} }
} }
} }
} }

View File

@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.data.updater.github
import eu.kanade.tachiyomi.data.updater.UpdateResult
sealed class GithubUpdateResult : UpdateResult() {
class NewUpdate(release: GithubRelease): UpdateResult.NewUpdate<GithubRelease>(release)
class NoNewUpdate : UpdateResult.NoNewUpdate()
}

View File

@ -9,8 +9,8 @@ import android.view.View
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker import eu.kanade.tachiyomi.data.updater.UpdateChecker
import eu.kanade.tachiyomi.data.updater.GithubUpdateResult import eu.kanade.tachiyomi.data.updater.UpdateResult
import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.data.updater.UpdaterJob
import eu.kanade.tachiyomi.data.updater.UpdaterService import eu.kanade.tachiyomi.data.updater.UpdaterService
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
@ -26,20 +26,19 @@ import java.util.Locale
import java.util.TimeZone import java.util.TimeZone
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsAboutController : SettingsController() { class SettingsAboutController : SettingsController() {
/** /**
* Checks for new releases * Checks for new releases
*/ */
private val updateChecker by lazy { GithubUpdateChecker() } private val updateChecker by lazy { UpdateChecker.getUpdateChecker() }
/** /**
* The subscribtion service of the obtained release object * The subscribtion service of the obtained release object
*/ */
private var releaseSubscription: Subscription? = null private var releaseSubscription: Subscription? = null
private val isUpdaterEnabled = !BuildConfig.DEBUG && BuildConfig.INCLUDE_UPDATER private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
titleRes = R.string.pref_category_about titleRes = R.string.pref_category_about
@ -124,14 +123,14 @@ class SettingsAboutController : SettingsController() {
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ result -> .subscribe({ result ->
when (result) { when (result) {
is GithubUpdateResult.NewUpdate -> { is UpdateResult.NewUpdate<*> -> {
val body = result.release.changeLog val body = result.release.info
val url = result.release.downloadLink val url = result.release.downloadLink
// Create confirmation window // Create confirmation window
NewUpdateDialogController(body, url).showDialog(router) NewUpdateDialogController(body, url).showDialog(router)
} }
is GithubUpdateResult.NoNewUpdate -> { is UpdateResult.NoNewUpdate -> {
activity?.toast(R.string.update_check_no_new_updates) activity?.toast(R.string.update_check_no_new_updates)
} }
} }