From d58130a5fc82047a95663b74f48d9415f4690e96 Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Sun, 11 Oct 2026 21:45:51 +0600 Subject: [PATCH] Check for app updates every 6 hours while the app is open --- .../kanade/tachiyomi/ui/main/MainActivity.kt | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) 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 b0eca8d37..5794a4d30 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 @@ -9,6 +9,7 @@ import android.content.pm.PackageManager import android.graphics.Color import android.os.Build import android.os.Bundle +import android.os.SystemClock import android.view.View import androidx.activity.ComponentActivity import androidx.activity.SystemBarStyle @@ -59,7 +60,9 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.util.Consumer import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.LinearOutSlowInInterpolator +import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior @@ -95,6 +98,7 @@ import eu.kanade.tachiyomi.util.system.isBenchmarkBuildType import eu.kanade.tachiyomi.util.system.isNavigationBarNeedsScrim import eu.kanade.tachiyomi.util.system.updaterEnabled import eu.kanade.tachiyomi.util.view.setComposeContent +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.delay @@ -127,6 +131,7 @@ import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.util.collectAsState import kotlin.time.Clock import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.seconds import kotlin.time.Instant import kotlin.time.TimeSource @@ -352,23 +357,36 @@ class MainActivity : BaseActivity() { // App updates LaunchedEffect(Unit) { - if (updaterEnabled) { - try { - val result = context.appGraph.updateChecker.checkForUpdate() - if ( - result is GetApplicationRelease.Result.NewUpdate && - result.release.version != preferences.skippedAppUpdate.get() - ) { - val updateScreen = NewUpdateScreen( - versionName = result.release.version, - changelogInfo = result.release.info, - releaseLink = result.release.releaseLink, - downloadLink = result.release.downloadLink, - ) - navigator.push(updateScreen) + if (!updaterEnabled) return@LaunchedEffect + var lastCheck: Long? = null + // The app can stay open for days now, so a cold start alone rarely checks. + // Elapsed realtime keeps counting while the device sleeps, unlike the monotonic clock. + lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + while (true) { + lastCheck?.let { + delay(it + APP_UPDATE_CHECK_INTERVAL.inWholeMilliseconds - SystemClock.elapsedRealtime()) + } + lastCheck = SystemClock.elapsedRealtime() + try { + val result = context.appGraph.updateChecker.checkForUpdate() + if ( + result is GetApplicationRelease.Result.NewUpdate && + result.release.version != preferences.skippedAppUpdate.get() && + navigator.items.none { it is NewUpdateScreen } + ) { + val updateScreen = NewUpdateScreen( + versionName = result.release.version, + changelogInfo = result.release.info, + releaseLink = result.release.releaseLink, + downloadLink = result.release.downloadLink, + ) + navigator.push(updateScreen) + } + } catch (e: CancellationException) { + throw e + } catch (e: Exception) { + logcat(LogPriority.ERROR, e) } - } catch (e: Exception) { - logcat(LogPriority.ERROR, e) } } } @@ -653,3 +671,4 @@ private const val SPLASH_MAX_DURATION = 5000 // ms private const val SPLASH_EXIT_ANIM_DURATION = 400L // ms private val MIGRATING_SCREEN_MIN_DURATION = 1.seconds +private val APP_UPDATE_CHECK_INTERVAL = 6.hours