From f23f22ab0139da91b4da5afcb96541c302566653 Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 13 Aug 2021 18:18:53 -0400 Subject: [PATCH] Add in-app app update check --- .../data/preference/PreferencesHelper.kt | 1 + ...ubUpdateChecker.kt => AppUpdateChecker.kt} | 13 +++-- .../tachiyomi/data/updater/AppUpdateResult.kt | 6 +++ .../data/updater/GithubUpdateResult.kt | 6 --- .../tachiyomi/data/updater/UpdaterJob.kt | 4 +- .../kanade/tachiyomi/ui/main/MainActivity.kt | 43 +++++++++++---- .../tachiyomi/ui/more/AboutController.kt | 54 +++---------------- .../ui/more/NewUpdateDialogController.kt | 38 +++++++++++++ 8 files changed, 97 insertions(+), 68 deletions(-) rename app/src/main/java/eu/kanade/tachiyomi/data/updater/{GithubUpdateChecker.kt => AppUpdateChecker.kt} (81%) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateResult.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateResult.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/more/NewUpdateDialogController.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 04a0a81fe..66442c7ba 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -269,6 +269,7 @@ class PreferencesHelper(val context: Context) { fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0) + fun lastAppCheck() = flowPrefs.getLong("last_app_check", 0) fun lastExtCheck() = flowPrefs.getLong("last_ext_check", 0) fun searchPinnedSourcesOnly() = prefs.getBoolean(Keys.searchPinnedSourcesOnly, false) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateChecker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt similarity index 81% rename from app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateChecker.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt index 7f937e7f7..f7198ae18 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateChecker.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt @@ -1,16 +1,19 @@ package eu.kanade.tachiyomi.data.updater import eu.kanade.tachiyomi.BuildConfig +import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.util.lang.withIOContext import uy.kohesive.injekt.injectLazy +import java.util.Date -class GithubUpdateChecker { +class AppUpdateChecker { private val networkService: NetworkHelper by injectLazy() + private val preferences: PreferencesHelper by injectLazy() private val repo: String by lazy { if (BuildConfig.DEBUG) { @@ -20,18 +23,20 @@ class GithubUpdateChecker { } } - suspend fun checkForUpdate(): GithubUpdateResult { + suspend fun checkForUpdate(): AppUpdateResult { return withIOContext { networkService.client .newCall(GET("https://api.github.com/repos/$repo/releases/latest")) .await() .parseAs() .let { + preferences.lastAppCheck().set(Date().time) + // Check if latest version is different from current version if (isNewVersion(it.version)) { - GithubUpdateResult.NewUpdate(it) + AppUpdateResult.NewUpdate(it) } else { - GithubUpdateResult.NoNewUpdate + AppUpdateResult.NoNewUpdate } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateResult.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateResult.kt new file mode 100644 index 000000000..7a40a3d3d --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateResult.kt @@ -0,0 +1,6 @@ +package eu.kanade.tachiyomi.data.updater + +sealed class AppUpdateResult { + class NewUpdate(val release: GithubRelease) : AppUpdateResult() + object NoNewUpdate : AppUpdateResult() +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateResult.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateResult.kt deleted file mode 100644 index ac0581739..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/GithubUpdateResult.kt +++ /dev/null @@ -1,6 +0,0 @@ -package eu.kanade.tachiyomi.data.updater - -sealed class GithubUpdateResult { - class NewUpdate(val release: GithubRelease) : GithubUpdateResult() - object NoNewUpdate : GithubUpdateResult() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt index 8abfce7b2..0a48282d1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt @@ -16,9 +16,9 @@ class UpdaterJob(private val context: Context, workerParams: WorkerParameters) : override fun doWork() = runBlocking { try { - val result = GithubUpdateChecker().checkForUpdate() + val result = AppUpdateChecker().checkForUpdate() - if (result is GithubUpdateResult.NewUpdate) { + if (result is AppUpdateResult.NewUpdate) { UpdaterNotifier(context).promptUpdate(result.release.getDownloadLink()) } Result.success() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index ee7eda7ae..f80bb3c5c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -35,6 +35,8 @@ import eu.kanade.tachiyomi.Migrations import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.preference.asImmediateFlow +import eu.kanade.tachiyomi.data.updater.AppUpdateChecker +import eu.kanade.tachiyomi.data.updater.AppUpdateResult import eu.kanade.tachiyomi.databinding.MainActivityBinding import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi import eu.kanade.tachiyomi.ui.base.activity.BaseViewBindingActivity @@ -52,6 +54,7 @@ import eu.kanade.tachiyomi.ui.download.DownloadController import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.more.MoreController +import eu.kanade.tachiyomi.ui.more.NewUpdateDialogController import eu.kanade.tachiyomi.ui.recent.history.HistoryController import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController import eu.kanade.tachiyomi.ui.setting.SettingsMainController @@ -334,19 +337,32 @@ class MainActivity : BaseViewBindingActivity() { override fun onResume() { super.onResume() - getExtensionUpdates() - } - private fun setExtensionsBadge() { - val updates = preferences.extensionUpdatesCount().get() - if (updates > 0) { - nav.getOrCreateBadge(R.id.nav_browse).number = updates - } else { - nav.removeBadge(R.id.nav_browse) + checkForExtensionUpdates() + if (BuildConfig.INCLUDE_UPDATER) { + checkForAppUpdates() } } - private fun getExtensionUpdates() { + private fun checkForAppUpdates() { + // Limit checks to once a day at most + if (Date().time < preferences.lastAppCheck().get() + TimeUnit.DAYS.toMillis(1)) { + return + } + + lifecycleScope.launchIO { + try { + val result = AppUpdateChecker().checkForUpdate() + if (result is AppUpdateResult.NewUpdate) { + NewUpdateDialogController(result).showDialog(router) + } + } catch (e: Exception) { + Timber.e(e) + } + } + } + + private fun checkForExtensionUpdates() { // Limit checks to once a day at most if (Date().time < preferences.lastExtCheck().get() + TimeUnit.DAYS.toMillis(1)) { return @@ -362,6 +378,15 @@ class MainActivity : BaseViewBindingActivity() { } } + private fun setExtensionsBadge() { + val updates = preferences.extensionUpdatesCount().get() + if (updates > 0) { + nav.getOrCreateBadge(R.id.nav_browse).number = updates + } else { + nav.removeBadge(R.id.nav_browse) + } + } + private fun handleIntentAction(intent: Intent): Boolean { val notificationId = intent.getIntExtra("notificationId", -1) if (notificationId > -1) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index 09abe7672..babd399a3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -1,16 +1,10 @@ package eu.kanade.tachiyomi.ui.more -import android.app.Dialog -import android.os.Bundle -import androidx.core.os.bundleOf import androidx.preference.PreferenceScreen -import com.google.android.material.dialog.MaterialAlertDialogBuilder import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker -import eu.kanade.tachiyomi.data.updater.GithubUpdateResult -import eu.kanade.tachiyomi.data.updater.UpdaterService -import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.data.updater.AppUpdateChecker +import eu.kanade.tachiyomi.data.updater.AppUpdateResult import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController import eu.kanade.tachiyomi.ui.base.controller.openInBrowser import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction @@ -33,12 +27,10 @@ import java.util.TimeZone class AboutController : SettingsController(), NoToolbarElevationController { - private val updateChecker by lazy { GithubUpdateChecker() } + private val updateChecker by lazy { AppUpdateChecker() } private val dateFormat: DateFormat = preferences.dateFormat() - private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER - override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_about @@ -60,7 +52,7 @@ class AboutController : SettingsController(), NoToolbarElevationController { } } } - if (isUpdaterEnabled) { + if (BuildConfig.INCLUDE_UPDATER) { preference { key = "pref_about_check_for_updates" titleRes = R.string.check_for_updates @@ -103,14 +95,10 @@ class AboutController : SettingsController(), NoToolbarElevationController { launchNow { try { when (val result = updateChecker.checkForUpdate()) { - is GithubUpdateResult.NewUpdate -> { - val body = result.release.info - val url = result.release.getDownloadLink() - - // Create confirmation window - NewUpdateDialogController(body, url).showDialog(router) + is AppUpdateResult.NewUpdate -> { + NewUpdateDialogController(result).showDialog(router) } - is GithubUpdateResult.NoNewUpdate -> { + is AppUpdateResult.NoNewUpdate -> { activity?.toast(R.string.update_check_no_new_updates) } } @@ -121,34 +109,6 @@ class AboutController : SettingsController(), NoToolbarElevationController { } } - class NewUpdateDialogController(bundle: Bundle? = null) : DialogController(bundle) { - - constructor(body: String, url: String) : this( - bundleOf(BODY_KEY to body, URL_KEY to url) - ) - - override fun onCreateDialog(savedViewState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(activity!!) - .setTitle(R.string.update_check_notification_update_available) - .setMessage(args.getString(BODY_KEY) ?: "") - .setPositiveButton(R.string.update_check_confirm) { _, _ -> - val appContext = applicationContext - if (appContext != null) { - // Start download - val url = args.getString(URL_KEY) ?: "" - UpdaterService.start(appContext, url) - } - } - .setNegativeButton(R.string.update_check_ignore, null) - .create() - } - - private companion object { - const val BODY_KEY = "NewUpdateDialogController.body" - const val URL_KEY = "NewUpdateDialogController.key" - } - } - private fun getFormattedBuildTime(): String { return try { val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/NewUpdateDialogController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/NewUpdateDialogController.kt new file mode 100644 index 000000000..7a52904a9 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/NewUpdateDialogController.kt @@ -0,0 +1,38 @@ +package eu.kanade.tachiyomi.ui.more + +import android.app.Dialog +import android.os.Bundle +import androidx.core.os.bundleOf +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.updater.AppUpdateResult +import eu.kanade.tachiyomi.data.updater.UpdaterService +import eu.kanade.tachiyomi.ui.base.controller.DialogController + +class NewUpdateDialogController(bundle: Bundle? = null) : DialogController(bundle) { + + constructor(update: AppUpdateResult.NewUpdate) : this( + bundleOf(BODY_KEY to update.release.info, URL_KEY to update.release.getDownloadLink()) + ) + + override fun onCreateDialog(savedViewState: Bundle?): Dialog { + return MaterialAlertDialogBuilder(activity!!) + .setTitle(R.string.update_check_notification_update_available) + .setMessage(args.getString(BODY_KEY) ?: "") + .setPositiveButton(R.string.update_check_confirm) { _, _ -> + val appContext = applicationContext + if (appContext != null) { + // Start download + val url = args.getString(URL_KEY) ?: "" + UpdaterService.start(appContext, url) + } + } + .setNegativeButton(R.string.update_check_ignore, null) + .create() + } + + private companion object { + const val BODY_KEY = "NewUpdateDialogController.body" + const val URL_KEY = "NewUpdateDialogController.key" + } +}