Add in-app app update check
This commit is contained in:
parent
96a64c7bd2
commit
f23f22ab01
8 changed files with 97 additions and 68 deletions
|
@ -269,6 +269,7 @@ class PreferencesHelper(val context: Context) {
|
||||||
|
|
||||||
fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0)
|
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 lastExtCheck() = flowPrefs.getLong("last_ext_check", 0)
|
||||||
|
|
||||||
fun searchPinnedSourcesOnly() = prefs.getBoolean(Keys.searchPinnedSourcesOnly, false)
|
fun searchPinnedSourcesOnly() = prefs.getBoolean(Keys.searchPinnedSourcesOnly, false)
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
package eu.kanade.tachiyomi.data.updater
|
package eu.kanade.tachiyomi.data.updater
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
class GithubUpdateChecker {
|
class AppUpdateChecker {
|
||||||
|
|
||||||
private val networkService: NetworkHelper by injectLazy()
|
private val networkService: NetworkHelper by injectLazy()
|
||||||
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
private val repo: String by lazy {
|
private val repo: String by lazy {
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
|
@ -20,18 +23,20 @@ class GithubUpdateChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkForUpdate(): GithubUpdateResult {
|
suspend fun checkForUpdate(): AppUpdateResult {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
networkService.client
|
networkService.client
|
||||||
.newCall(GET("https://api.github.com/repos/$repo/releases/latest"))
|
.newCall(GET("https://api.github.com/repos/$repo/releases/latest"))
|
||||||
.await()
|
.await()
|
||||||
.parseAs<GithubRelease>()
|
.parseAs<GithubRelease>()
|
||||||
.let {
|
.let {
|
||||||
|
preferences.lastAppCheck().set(Date().time)
|
||||||
|
|
||||||
// Check if latest version is different from current version
|
// Check if latest version is different from current version
|
||||||
if (isNewVersion(it.version)) {
|
if (isNewVersion(it.version)) {
|
||||||
GithubUpdateResult.NewUpdate(it)
|
AppUpdateResult.NewUpdate(it)
|
||||||
} else {
|
} else {
|
||||||
GithubUpdateResult.NoNewUpdate
|
AppUpdateResult.NoNewUpdate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package eu.kanade.tachiyomi.data.updater
|
||||||
|
|
||||||
|
sealed class AppUpdateResult {
|
||||||
|
class NewUpdate(val release: GithubRelease) : AppUpdateResult()
|
||||||
|
object NoNewUpdate : AppUpdateResult()
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.data.updater
|
|
||||||
|
|
||||||
sealed class GithubUpdateResult {
|
|
||||||
class NewUpdate(val release: GithubRelease) : GithubUpdateResult()
|
|
||||||
object NoNewUpdate : GithubUpdateResult()
|
|
||||||
}
|
|
|
@ -16,9 +16,9 @@ class UpdaterJob(private val context: Context, workerParams: WorkerParameters) :
|
||||||
|
|
||||||
override fun doWork() = runBlocking {
|
override fun doWork() = runBlocking {
|
||||||
try {
|
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())
|
UpdaterNotifier(context).promptUpdate(result.release.getDownloadLink())
|
||||||
}
|
}
|
||||||
Result.success()
|
Result.success()
|
||||||
|
|
|
@ -35,6 +35,8 @@ import eu.kanade.tachiyomi.Migrations
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
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.databinding.MainActivityBinding
|
||||||
import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
|
import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseViewBindingActivity
|
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.library.LibraryController
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.ui.more.MoreController
|
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.history.HistoryController
|
||||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
||||||
|
@ -334,19 +337,32 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
getExtensionUpdates()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setExtensionsBadge() {
|
checkForExtensionUpdates()
|
||||||
val updates = preferences.extensionUpdatesCount().get()
|
if (BuildConfig.INCLUDE_UPDATER) {
|
||||||
if (updates > 0) {
|
checkForAppUpdates()
|
||||||
nav.getOrCreateBadge(R.id.nav_browse).number = updates
|
|
||||||
} else {
|
|
||||||
nav.removeBadge(R.id.nav_browse)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Limit checks to once a day at most
|
||||||
if (Date().time < preferences.lastExtCheck().get() + TimeUnit.DAYS.toMillis(1)) {
|
if (Date().time < preferences.lastExtCheck().get() + TimeUnit.DAYS.toMillis(1)) {
|
||||||
return
|
return
|
||||||
|
@ -362,6 +378,15 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
private fun handleIntentAction(intent: Intent): Boolean {
|
||||||
val notificationId = intent.getIntExtra("notificationId", -1)
|
val notificationId = intent.getIntExtra("notificationId", -1)
|
||||||
if (notificationId > -1) {
|
if (notificationId > -1) {
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.ui.more
|
package eu.kanade.tachiyomi.ui.more
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.core.os.bundleOf
|
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
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.AppUpdateChecker
|
||||||
import eu.kanade.tachiyomi.data.updater.GithubUpdateResult
|
import eu.kanade.tachiyomi.data.updater.AppUpdateResult
|
||||||
import eu.kanade.tachiyomi.data.updater.UpdaterService
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
|
import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
|
@ -33,12 +27,10 @@ import java.util.TimeZone
|
||||||
|
|
||||||
class AboutController : SettingsController(), NoToolbarElevationController {
|
class AboutController : SettingsController(), NoToolbarElevationController {
|
||||||
|
|
||||||
private val updateChecker by lazy { GithubUpdateChecker() }
|
private val updateChecker by lazy { AppUpdateChecker() }
|
||||||
|
|
||||||
private val dateFormat: DateFormat = preferences.dateFormat()
|
private val dateFormat: DateFormat = preferences.dateFormat()
|
||||||
|
|
||||||
private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER
|
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||||
titleRes = R.string.pref_category_about
|
titleRes = R.string.pref_category_about
|
||||||
|
|
||||||
|
@ -60,7 +52,7 @@ class AboutController : SettingsController(), NoToolbarElevationController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isUpdaterEnabled) {
|
if (BuildConfig.INCLUDE_UPDATER) {
|
||||||
preference {
|
preference {
|
||||||
key = "pref_about_check_for_updates"
|
key = "pref_about_check_for_updates"
|
||||||
titleRes = R.string.check_for_updates
|
titleRes = R.string.check_for_updates
|
||||||
|
@ -103,14 +95,10 @@ class AboutController : SettingsController(), NoToolbarElevationController {
|
||||||
launchNow {
|
launchNow {
|
||||||
try {
|
try {
|
||||||
when (val result = updateChecker.checkForUpdate()) {
|
when (val result = updateChecker.checkForUpdate()) {
|
||||||
is GithubUpdateResult.NewUpdate -> {
|
is AppUpdateResult.NewUpdate -> {
|
||||||
val body = result.release.info
|
NewUpdateDialogController(result).showDialog(router)
|
||||||
val url = result.release.getDownloadLink()
|
|
||||||
|
|
||||||
// Create confirmation window
|
|
||||||
NewUpdateDialogController(body, url).showDialog(router)
|
|
||||||
}
|
}
|
||||||
is GithubUpdateResult.NoNewUpdate -> {
|
is AppUpdateResult.NoNewUpdate -> {
|
||||||
activity?.toast(R.string.update_check_no_new_updates)
|
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 {
|
private fun getFormattedBuildTime(): String {
|
||||||
return try {
|
return try {
|
||||||
val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US)
|
val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US)
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue