mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Use coroutines for updater
This commit is contained in:
		@@ -53,12 +53,11 @@ class TrackSearch : Track {
 | 
			
		||||
        result = 31 * result + media_id
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun create(serviceId: Int): TrackSearch = TrackSearch().apply {
 | 
			
		||||
            sync_id = serviceId
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ 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 {
 | 
			
		||||
 | 
			
		||||
@@ -20,6 +19,6 @@ abstract class UpdateChecker {
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns observable containing release information
 | 
			
		||||
     */
 | 
			
		||||
    abstract fun checkForUpdate(): Observable<UpdateResult>
 | 
			
		||||
    abstract suspend fun checkForUpdate(): UpdateResult
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,36 +9,37 @@ import com.evernote.android.job.JobRequest
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.notification.Notifications
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.notificationManager
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
 | 
			
		||||
class UpdaterJob : Job() {
 | 
			
		||||
 | 
			
		||||
    override fun onRunJob(params: Params): Result {
 | 
			
		||||
        return UpdateChecker.getUpdateChecker()
 | 
			
		||||
                .checkForUpdate()
 | 
			
		||||
                .map { result ->
 | 
			
		||||
                    if (result is UpdateResult.NewUpdate<*>) {
 | 
			
		||||
                        val url = result.release.downloadLink
 | 
			
		||||
        return runBlocking {
 | 
			
		||||
            try {
 | 
			
		||||
                val result = UpdateChecker.getUpdateChecker().checkForUpdate()
 | 
			
		||||
 | 
			
		||||
                        val intent = Intent(context, UpdaterService::class.java).apply {
 | 
			
		||||
                            putExtra(UpdaterService.EXTRA_DOWNLOAD_URL, url)
 | 
			
		||||
                        }
 | 
			
		||||
                if (result is UpdateResult.NewUpdate<*>) {
 | 
			
		||||
                    val url = result.release.downloadLink
 | 
			
		||||
 | 
			
		||||
                        NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON).update {
 | 
			
		||||
                            setContentTitle(context.getString(R.string.app_name))
 | 
			
		||||
                            setContentText(context.getString(R.string.update_check_notification_update_available))
 | 
			
		||||
                            setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
                            // Download action
 | 
			
		||||
                            addAction(android.R.drawable.stat_sys_download_done,
 | 
			
		||||
                                    context.getString(R.string.action_download),
 | 
			
		||||
                                    PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
 | 
			
		||||
                        }
 | 
			
		||||
                    val intent = Intent(context, UpdaterService::class.java).apply {
 | 
			
		||||
                        putExtra(UpdaterService.EXTRA_DOWNLOAD_URL, url)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON).update {
 | 
			
		||||
                        setContentTitle(context.getString(R.string.app_name))
 | 
			
		||||
                        setContentText(context.getString(R.string.update_check_notification_update_available))
 | 
			
		||||
                        setSmallIcon(android.R.drawable.stat_sys_download_done)
 | 
			
		||||
                        // Download action
 | 
			
		||||
                        addAction(android.R.drawable.stat_sys_download_done,
 | 
			
		||||
                                context.getString(R.string.action_download),
 | 
			
		||||
                                PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
 | 
			
		||||
                    }
 | 
			
		||||
                    Result.SUCCESS
 | 
			
		||||
                }
 | 
			
		||||
                .onErrorReturn { Result.FAILURE }
 | 
			
		||||
                // Sadly, the task needs to be synchronous.
 | 
			
		||||
                .toBlocking()
 | 
			
		||||
                .single()
 | 
			
		||||
                Result.SUCCESS
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                Result.FAILURE
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun NotificationCompat.Builder.update(block: NotificationCompat.Builder.() -> Unit) {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,8 @@ 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 eu.kanade.tachiyomi.network.await
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
@@ -23,18 +22,17 @@ class DevRepoUpdateChecker : UpdateChecker() {
 | 
			
		||||
        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]
 | 
			
		||||
    override suspend fun checkForUpdate(): UpdateResult {
 | 
			
		||||
        val response = client.newCall(GET(DevRepoRelease.LATEST_URL)).await(assertSuccess = false)
 | 
			
		||||
 | 
			
		||||
                    if (latestVersionNumber.toInt() > BuildConfig.COMMIT_COUNT.toInt()) {
 | 
			
		||||
                        DevRepoUpdateResult.NewUpdate(DevRepoRelease("v$latestVersionNumber"))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        DevRepoUpdateResult.NoNewUpdate()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
        // Get latest repo version number from header in format "Location: tachiyomi-r1512.apk"
 | 
			
		||||
        val latestVersionNumber: String = versionRegex.find(response.header("Location")!!)!!.groupValues[1]
 | 
			
		||||
 | 
			
		||||
        return if (latestVersionNumber.toInt() > BuildConfig.COMMIT_COUNT.toInt()) {
 | 
			
		||||
            DevRepoUpdateResult.NewUpdate(DevRepoRelease("v$latestVersionNumber"))
 | 
			
		||||
        } else {
 | 
			
		||||
            DevRepoUpdateResult.NoNewUpdate()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import retrofit2.Retrofit
 | 
			
		||||
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
 | 
			
		||||
import retrofit2.converter.gson.GsonConverterFactory
 | 
			
		||||
import retrofit2.http.GET
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +27,6 @@ interface GithubService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GET("/repos/inorichi/tachiyomi/releases/latest")
 | 
			
		||||
    fun getLatestVersion(): Observable<GithubRelease>
 | 
			
		||||
    suspend fun getLatestVersion(): GithubRelease
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,22 +3,21 @@ package eu.kanade.tachiyomi.data.updater.github
 | 
			
		||||
import eu.kanade.tachiyomi.BuildConfig
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.UpdateChecker
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.UpdateResult
 | 
			
		||||
import rx.Observable
 | 
			
		||||
 | 
			
		||||
class GithubUpdateChecker : UpdateChecker() {
 | 
			
		||||
 | 
			
		||||
    private val service: GithubService = GithubService.create()
 | 
			
		||||
 | 
			
		||||
    override fun checkForUpdate(): Observable<UpdateResult> {
 | 
			
		||||
        return service.getLatestVersion().map { release ->
 | 
			
		||||
            val newVersion = release.version.replace("[^\\d.]".toRegex(), "")
 | 
			
		||||
    override suspend fun checkForUpdate(): UpdateResult {
 | 
			
		||||
        val release = service.getLatestVersion()
 | 
			
		||||
 | 
			
		||||
            // Check if latest version is different from current version
 | 
			
		||||
            if (newVersion != BuildConfig.VERSION_NAME) {
 | 
			
		||||
                GithubUpdateResult.NewUpdate(release)
 | 
			
		||||
            } else {
 | 
			
		||||
                GithubUpdateResult.NoNewUpdate()
 | 
			
		||||
            }
 | 
			
		||||
        val newVersion = release.version.replace("[^\\d.]".toRegex(), "")
 | 
			
		||||
 | 
			
		||||
        // Check if latest version is different from current version
 | 
			
		||||
        return if (newVersion != BuildConfig.VERSION_NAME) {
 | 
			
		||||
            GithubUpdateResult.NewUpdate(release)
 | 
			
		||||
        } else {
 | 
			
		||||
            GithubUpdateResult.NoNewUpdate()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -48,11 +48,11 @@ fun Call.asObservable(): Observable<Response> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Based on https://github.com/gildor/kotlin-coroutines-okhttp
 | 
			
		||||
suspend fun Call.await(): Response {
 | 
			
		||||
suspend fun Call.await(assertSuccess: Boolean = false): Response {
 | 
			
		||||
    return suspendCancellableCoroutine { continuation ->
 | 
			
		||||
        enqueue(object : Callback {
 | 
			
		||||
            override fun onResponse(call: Call, response: Response) {
 | 
			
		||||
                if (!response.isSuccessful) {
 | 
			
		||||
                if (assertSuccess && !response.isSuccessful) {
 | 
			
		||||
                    continuation.resumeWithException(Exception("HTTP error ${response.code}"))
 | 
			
		||||
                    return
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ import android.app.Dialog
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.View
 | 
			
		||||
import androidx.preference.PreferenceScreen
 | 
			
		||||
import com.afollestad.materialdialogs.MaterialDialog
 | 
			
		||||
import eu.kanade.tachiyomi.BuildConfig
 | 
			
		||||
@@ -17,12 +16,11 @@ import eu.kanade.tachiyomi.data.updater.UpdaterJob
 | 
			
		||||
import eu.kanade.tachiyomi.data.updater.UpdaterService
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.main.ChangelogDialogController
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchIO
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchUI
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.toTimestampString
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.*
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toast
 | 
			
		||||
import rx.Subscription
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
import rx.schedulers.Schedulers
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import java.text.DateFormat
 | 
			
		||||
@@ -43,11 +41,6 @@ class SettingsAboutController : SettingsController() {
 | 
			
		||||
 | 
			
		||||
    private val dateFormat: DateFormat = userPreferences.dateFormat().getOrDefault()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The subscribtion service of the obtained release object
 | 
			
		||||
     */
 | 
			
		||||
    private var releaseSubscription: Subscription? = null
 | 
			
		||||
 | 
			
		||||
    private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER
 | 
			
		||||
 | 
			
		||||
    override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
 | 
			
		||||
@@ -118,12 +111,6 @@ class SettingsAboutController : SettingsController() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onDestroyView(view: View) {
 | 
			
		||||
        super.onDestroyView(view)
 | 
			
		||||
        releaseSubscription?.unsubscribe()
 | 
			
		||||
        releaseSubscription = null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks version and shows a user prompt if an update is available.
 | 
			
		||||
     */
 | 
			
		||||
@@ -131,11 +118,11 @@ class SettingsAboutController : SettingsController() {
 | 
			
		||||
        if (activity == null) return
 | 
			
		||||
 | 
			
		||||
        activity?.toast(R.string.update_check_look_for_updates)
 | 
			
		||||
        releaseSubscription?.unsubscribe()
 | 
			
		||||
        releaseSubscription = updateChecker.checkForUpdate()
 | 
			
		||||
                .subscribeOn(Schedulers.io())
 | 
			
		||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                .subscribe({ result ->
 | 
			
		||||
 | 
			
		||||
        launchIO {
 | 
			
		||||
            try {
 | 
			
		||||
                val result = updateChecker.checkForUpdate()
 | 
			
		||||
                launchUI {
 | 
			
		||||
                    when (result) {
 | 
			
		||||
                        is UpdateResult.NewUpdate<*> -> {
 | 
			
		||||
                            val body = result.release.info
 | 
			
		||||
@@ -148,10 +135,14 @@ class SettingsAboutController : SettingsController() {
 | 
			
		||||
                            activity?.toast(R.string.update_check_no_new_updates)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }, { error ->
 | 
			
		||||
                }
 | 
			
		||||
            } catch (error: Exception) {
 | 
			
		||||
                launchUI {
 | 
			
		||||
                    activity?.toast(error.message)
 | 
			
		||||
                    Timber.e(error)
 | 
			
		||||
                })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class NewUpdateDialogController(bundle: Bundle? = null) : DialogController(bundle) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user