From 8ce8b600922410a4eb64da35a1850840a2f28669 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Thu, 30 Nov 2023 04:34:07 +0700 Subject: [PATCH 1/5] Migrate downloader service to WorkManager (#10190) --- app/build.gradle.kts | 1 - app/src/main/AndroidManifest.xml | 11 +- .../tachiyomi/data/download/DownloadJob.kt | 121 ++++++++++++++ .../data/download/DownloadManager.kt | 13 +- .../data/download/DownloadService.kt | 151 ------------------ .../tachiyomi/data/download/Downloader.kt | 7 +- .../ui/download/DownloadQueueScreenModel.kt | 6 +- gradle/libs.versions.toml | 1 - 8 files changed, 142 insertions(+), 169 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadJob.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0f0917a05..0fd4cd1fa 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -196,7 +196,6 @@ dependencies { // RxJava implementation(libs.rxjava) - implementation(libs.flowreactivenetwork) // Networking implementation(libs.bundles.okhttp) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5c903960f..9eddc43a2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,6 +21,8 @@ + + - - @@ -154,6 +152,11 @@ android:value="true" /> + + = Build.VERSION_CODES.Q) { + ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC + } else { + 0 + }, + ) + } + + override suspend fun doWork(): Result { + try { + setForeground(getForegroundInfo()) + } catch (e: IllegalStateException) { + logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" } + } + + var networkCheck = checkConnectivity() + var active = networkCheck + downloadManager.downloaderStart() + + // Keep the worker running when needed + while (active) { + delay(100) + networkCheck = checkConnectivity() + active = !isStopped && networkCheck && downloadManager.isRunning + } + + return Result.success() + } + + private fun checkConnectivity(): Boolean { + return with(applicationContext) { + if (isOnline()) { + val noWifi = downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi() + if (noWifi) { + downloadManager.downloaderStop( + applicationContext.getString(R.string.download_notifier_text_only_wifi), + ) + } + !noWifi + } else { + downloadManager.downloaderStop(applicationContext.getString(R.string.download_notifier_no_network)) + false + } + } + } + + companion object { + private const val TAG = "Downloader" + + fun start(context: Context) { + val request = OneTimeWorkRequestBuilder() + .addTag(TAG) + .build() + WorkManager.getInstance(context) + .enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, request) + } + + fun stop(context: Context) { + WorkManager.getInstance(context) + .cancelUniqueWork(TAG) + } + + fun isRunning(context: Context): Boolean { + return WorkManager.getInstance(context) + .getWorkInfosForUniqueWork(TAG) + .get() + .let { list -> list.count { it.state == WorkInfo.State.RUNNING } == 1 } + } + + fun isRunningFlow(context: Context): Flow { + return WorkManager.getInstance(context) + .getWorkInfosForUniqueWorkLiveData(TAG) + .asFlow() + .map { list -> list.count { it.state == WorkInfo.State.RUNNING } == 1 } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index ba5c4d81a..dca4fac23 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -46,6 +46,9 @@ class DownloadManager( */ private val downloader = Downloader(context, provider, cache) + val isRunning: Boolean + get() = downloader.isRunning + /** * Queue to delay the deletion of a list of chapters until triggered. */ @@ -59,13 +62,13 @@ class DownloadManager( fun downloaderStop(reason: String? = null) = downloader.stop(reason) val isDownloaderRunning - get() = DownloadService.isRunning + get() = DownloadJob.isRunningFlow(context) /** * Tells the downloader to begin downloads. */ fun startDownloads() { - DownloadService.start(context) + DownloadJob.start(context) } /** @@ -104,10 +107,10 @@ class DownloadManager( queue.add(0, toAdd) reorderQueue(queue) if (!downloader.isRunning) { - if (DownloadService.isRunning(context)) { + if (DownloadJob.isRunning(context)) { downloader.start() } else { - DownloadService.start(context) + DownloadJob.start(context) } } } @@ -143,7 +146,7 @@ class DownloadManager( addAll(0, downloads) reorderQueue(this) } - if (!DownloadService.isRunning(context)) DownloadService.start(context) + if (!DownloadJob.isRunning(context)) DownloadJob.start(context) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt deleted file mode 100644 index 9ce5c5b2a..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt +++ /dev/null @@ -1,151 +0,0 @@ -package eu.kanade.tachiyomi.data.download - -import android.app.Notification -import android.app.Service -import android.content.Context -import android.content.Intent -import android.os.IBinder -import android.os.PowerManager -import androidx.core.content.ContextCompat -import dev.icerock.moko.resources.StringResource -import eu.kanade.tachiyomi.data.notification.Notifications -import eu.kanade.tachiyomi.util.system.acquireWakeLock -import eu.kanade.tachiyomi.util.system.isConnectedToWifi -import eu.kanade.tachiyomi.util.system.isOnline -import eu.kanade.tachiyomi.util.system.isServiceRunning -import eu.kanade.tachiyomi.util.system.notificationBuilder -import eu.kanade.tachiyomi.util.system.toast -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import logcat.LogPriority -import ru.beryukhov.reactivenetwork.ReactiveNetwork -import tachiyomi.core.i18n.stringResource -import tachiyomi.core.util.lang.withUIContext -import tachiyomi.core.util.system.logcat -import tachiyomi.domain.download.service.DownloadPreferences -import tachiyomi.i18n.MR -import uy.kohesive.injekt.injectLazy - -/** - * This service is used to manage the downloader. The system can decide to stop the service, in - * which case the downloader is also stopped. It's also stopped while there's no network available. - * While the downloader is running, a wake lock will be held. - */ -class DownloadService : Service() { - - companion object { - - private val _isRunning = MutableStateFlow(false) - val isRunning = _isRunning.asStateFlow() - - /** - * Starts this service. - * - * @param context the application context. - */ - fun start(context: Context) { - val intent = Intent(context, DownloadService::class.java) - ContextCompat.startForegroundService(context, intent) - } - - /** - * Stops this service. - * - * @param context the application context. - */ - fun stop(context: Context) { - context.stopService(Intent(context, DownloadService::class.java)) - } - - /** - * Returns the status of the service. - * - * @param context the application context. - * @return true if the service is running, false otherwise. - */ - fun isRunning(context: Context): Boolean { - return context.isServiceRunning(DownloadService::class.java) - } - } - - private val downloadManager: DownloadManager by injectLazy() - private val downloadPreferences: DownloadPreferences by injectLazy() - - /** - * Wake lock to prevent the device to enter sleep mode. - */ - private lateinit var wakeLock: PowerManager.WakeLock - - private lateinit var scope: CoroutineScope - - override fun onCreate() { - scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - startForeground(Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS, getPlaceholderNotification()) - wakeLock = acquireWakeLock(javaClass.name) - _isRunning.value = true - listenNetworkChanges() - } - - override fun onDestroy() { - scope.cancel() - _isRunning.value = false - downloadManager.downloaderStop() - if (wakeLock.isHeld) { - wakeLock.release() - } - } - - // Not used - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_NOT_STICKY - } - - // Not used - override fun onBind(intent: Intent): IBinder? { - return null - } - - private fun downloaderStop(string: StringResource) { - downloadManager.downloaderStop(stringResource(string)) - } - - private fun listenNetworkChanges() { - ReactiveNetwork() - .observeNetworkConnectivity(applicationContext) - .onEach { - withUIContext { - if (isOnline()) { - if (downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()) { - downloaderStop(MR.strings.download_notifier_text_only_wifi) - } else { - val started = downloadManager.downloaderStart() - if (!started) stopSelf() - } - } else { - downloaderStop(MR.strings.download_notifier_no_network) - } - } - } - .catch { error -> - withUIContext { - logcat(LogPriority.ERROR, error) - toast(MR.strings.download_queue_error) - stopSelf() - } - } - .launchIn(scope) - } - - private fun getPlaceholderNotification(): Notification { - return notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) { - setContentTitle(stringResource(MR.strings.download_notifier_downloader_title)) - }.build() - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index 5e58d4f6a..1dd117f41 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -161,10 +161,7 @@ class Downloader( isPaused = false - // Prevent recursion when DownloadService.onDestroy() calls downloader.stop() - if (DownloadService.isRunning.value) { - DownloadService.stop(context) - } + DownloadJob.stop(context) } /** @@ -310,7 +307,7 @@ class Downloader( ) } } - DownloadService.start(context) + DownloadJob.start(context) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreenModel.kt index 3cfb3ff1a..3f8896632 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreenModel.kt @@ -11,12 +11,14 @@ import eu.kanade.tachiyomi.source.model.Page import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import uy.kohesive.injekt.Injekt @@ -137,8 +139,8 @@ class DownloadQueueScreenModel( adapter = null } - val isDownloaderRunning - get() = downloadManager.isDownloaderRunning + val isDownloaderRunning = downloadManager.isDownloaderRunning + .stateIn(screenModelScope, SharingStarted.WhileSubscribed(5000), false) fun getDownloadStatusFlow() = downloadManager.statusFlow() fun getDownloadProgressFlow() = downloadManager.progressFlow() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 889ac693d..fa08d896a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,6 @@ android-shortcut-gradle = "com.github.zellius:android-shortcut-gradle-plugin:0.1 google-services-gradle = "com.google.gms:google-services:4.4.0" rxjava = "io.reactivex:rxjava:1.3.8" -flowreactivenetwork = "ru.beryukhov:flowreactivenetwork:1.0.4" okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp_version" } okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp_version" } From 5dda32bb8143abe4e495fb7a5693299ac9f4da41 Mon Sep 17 00:00:00 2001 From: arkon Date: Wed, 29 Nov 2023 16:44:49 -0500 Subject: [PATCH 2/5] Bump dependencies --- .github/workflows/build_pull_request.yml | 2 +- .github/workflows/build_push.yml | 2 +- .../settings/screen/debug/DebugInfoScreen.kt | 1 - .../settings/screen/debug/WorkerInfoScreen.kt | 25 +++++++++++++------ .../ui/browse/migration/MigrationFlags.kt | 1 - gradle/androidx.versions.toml | 2 +- gradle/compose.versions.toml | 2 +- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 9 files changed, 24 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml index da79440dc..5a7bfdd10 100644 --- a/.github/workflows/build_pull_request.yml +++ b/.github/workflows/build_pull_request.yml @@ -28,7 +28,7 @@ jobs: uses: actions/dependency-review-action@v3 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: adopt diff --git a/.github/workflows/build_push.yml b/.github/workflows/build_push.yml index e43c229a0..6127d3f30 100644 --- a/.github/workflows/build_push.yml +++ b/.github/workflows/build_push.yml @@ -23,7 +23,7 @@ jobs: uses: gradle/wrapper-validation-action@v1 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: adopt diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt index b4be0ebd9..3eecee438 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/DebugInfoScreen.kt @@ -13,7 +13,6 @@ import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.PreferenceScaffold import eu.kanade.presentation.more.settings.screen.about.AboutScreen import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.WebViewUtil import kotlinx.coroutines.guava.await diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/WorkerInfoScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/WorkerInfoScreen.kt index 2c891e271..ea8db81e8 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/WorkerInfoScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/debug/WorkerInfoScreen.kt @@ -18,17 +18,18 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach -import androidx.lifecycle.asFlow import androidx.work.WorkInfo import androidx.work.WorkQuery import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow +import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.ioCoroutineScope +import eu.kanade.tachiyomi.util.lang.toDateTimestampString import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.workManager import kotlinx.collections.immutable.persistentListOf @@ -39,6 +40,9 @@ import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.util.plus +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.util.Date class WorkerInfoScreen : Screen() { @@ -116,22 +120,19 @@ class WorkerInfoScreen : Screen() { private val workManager = context.workManager val finished = workManager - .getWorkInfosLiveData( + .getWorkInfosFlow( WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED), ) - .asFlow() .map(::constructString) .stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "") val running = workManager - .getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.RUNNING)) - .asFlow() + .getWorkInfosFlow(WorkQuery.fromStates(WorkInfo.State.RUNNING)) .map(::constructString) .stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "") val enqueued = workManager - .getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.ENQUEUED)) - .asFlow() + .getWorkInfosFlow(WorkQuery.fromStates(WorkInfo.State.ENQUEUED)) .map(::constructString) .stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "") @@ -146,6 +147,16 @@ class WorkerInfoScreen : Screen() { appendLine(" - $it") } appendLine("State: ${workInfo.state}") + if (workInfo.state == WorkInfo.State.ENQUEUED) { + appendLine( + "Next scheduled run: ${Date(workInfo.nextScheduleTimeMillis).toDateTimestampString( + UiPreferences.dateFormat( + Injekt.get().dateFormat().get(), + ), + )}", + ) + appendLine("Attempt #${workInfo.runAttemptCount + 1}") + } appendLine() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt index c79c111fc..3064ad60f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt @@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadCache import tachiyomi.domain.manga.model.Manga import tachiyomi.i18n.MR -import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy data class MigrationFlag( diff --git a/gradle/androidx.versions.toml b/gradle/androidx.versions.toml index 7ef758874..5d7aead08 100644 --- a/gradle/androidx.versions.toml +++ b/gradle/androidx.versions.toml @@ -20,7 +20,7 @@ lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle_version" } lifecycle-runtimektx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle_version" } -workmanager = "androidx.work:work-runtime-ktx:2.8.1" +workmanager = "androidx.work:work-runtime:2.9.0" paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging_version" } paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging_version" } diff --git a/gradle/compose.versions.toml b/gradle/compose.versions.toml index ce7b074bf..6ccce2b06 100644 --- a/gradle/compose.versions.toml +++ b/gradle/compose.versions.toml @@ -1,5 +1,5 @@ [versions] -compiler = "1.5.4" +compiler = "1.5.5" compose-bom = "2023.12.00-alpha02" accompanist = "0.33.2-alpha" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fa08d896a..3cd0e3da7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,7 +26,7 @@ conscrypt-android = "org.conscrypt:conscrypt-android:2.5.2" quickjs-android = "app.cash.quickjs:quickjs-android:0.9.2" -jsoup = "org.jsoup:jsoup:1.16.2" +jsoup = "org.jsoup:jsoup:1.17.1" disklrucache = "com.jakewharton:disklrucache:2.0.2" unifile = "com.github.tachiyomiorg:unifile:7c257e1c64" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3fa8f862f..1af9e0930 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 162b6397050e1577c113a88e7b7cfe9f98e6a45c Mon Sep 17 00:00:00 2001 From: arkon Date: Thu, 30 Nov 2023 22:19:38 -0500 Subject: [PATCH 3/5] Remove unused resources --- .../util/system/ContextExtensions.kt | 30 ------------------- .../main/res/color/ripple_toolbar_fainter.xml | 5 ---- .../main/res/color/slider_active_track.xml | 5 ---- .../main/res/color/slider_inactive_track.xml | 5 ---- app/src/main/res/drawable/ic_blank_24dp.xml | 7 ----- .../main/res/drawable/ic_offline_pin_24dp.xml | 9 ------ app/src/main/res/drawable/ic_webview_24dp.xml | 7 ----- .../drawable/transparent_tabs_background.xml | 16 ---------- app/src/main/res/values-sw720dp/dimens.xml | 3 -- app/src/main/res/values/dimens.xml | 2 -- 10 files changed, 89 deletions(-) delete mode 100644 app/src/main/res/color/ripple_toolbar_fainter.xml delete mode 100644 app/src/main/res/color/slider_active_track.xml delete mode 100644 app/src/main/res/color/slider_inactive_track.xml delete mode 100644 app/src/main/res/drawable/ic_blank_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_offline_pin_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_webview_24dp.xml delete mode 100644 app/src/main/res/drawable/transparent_tabs_background.xml delete mode 100644 app/src/main/res/values-sw720dp/dimens.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt index 5f91bfbac..44635e98d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt @@ -1,13 +1,11 @@ package eu.kanade.tachiyomi.util.system -import android.app.ActivityManager import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration -import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build import android.os.PowerManager @@ -68,26 +66,6 @@ fun Context.hasPermission( val Context.powerManager: PowerManager get() = getSystemService()!! -/** - * Convenience method to acquire a partial wake lock. - */ -fun Context.acquireWakeLock(tag: String): PowerManager.WakeLock { - val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "$tag:WakeLock") - wakeLock.acquire() - return wakeLock -} - -/** - * Returns true if the given service class is running. - */ -fun Context.isServiceRunning(serviceClass: Class<*>): Boolean { - val className = serviceClass.name - val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - @Suppress("DEPRECATION") - return manager.getRunningServices(Integer.MAX_VALUE) - .any { className == it.service.className } -} - fun Context.openInBrowser(url: String, forceDefaultBrowser: Boolean = false) { this.openInBrowser(url.toUri(), forceDefaultBrowser) } @@ -200,11 +178,3 @@ fun Context.isInstalledFromFDroid(): Boolean { // F-Droid builds typically disable the updater (!BuildConfig.INCLUDE_UPDATER && !isDevFlavor) } - -fun Context.getApplicationIcon(pkgName: String): Drawable? { - return try { - packageManager.getApplicationIcon(pkgName) - } catch (e: PackageManager.NameNotFoundException) { - null - } -} diff --git a/app/src/main/res/color/ripple_toolbar_fainter.xml b/app/src/main/res/color/ripple_toolbar_fainter.xml deleted file mode 100644 index e7fb4ba66..000000000 --- a/app/src/main/res/color/ripple_toolbar_fainter.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/color/slider_active_track.xml b/app/src/main/res/color/slider_active_track.xml deleted file mode 100644 index 764d21bf3..000000000 --- a/app/src/main/res/color/slider_active_track.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/slider_inactive_track.xml b/app/src/main/res/color/slider_inactive_track.xml deleted file mode 100644 index 0f624c117..000000000 --- a/app/src/main/res/color/slider_inactive_track.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_blank_24dp.xml b/app/src/main/res/drawable/ic_blank_24dp.xml deleted file mode 100644 index 940db069f..000000000 --- a/app/src/main/res/drawable/ic_blank_24dp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_offline_pin_24dp.xml b/app/src/main/res/drawable/ic_offline_pin_24dp.xml deleted file mode 100644 index f3dcb3625..000000000 --- a/app/src/main/res/drawable/ic_offline_pin_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_webview_24dp.xml b/app/src/main/res/drawable/ic_webview_24dp.xml deleted file mode 100644 index 9400f45ed..000000000 --- a/app/src/main/res/drawable/ic_webview_24dp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/transparent_tabs_background.xml b/app/src/main/res/drawable/transparent_tabs_background.xml deleted file mode 100644 index a503ef698..000000000 --- a/app/src/main/res/drawable/transparent_tabs_background.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/src/main/res/values-sw720dp/dimens.xml b/app/src/main/res/values-sw720dp/dimens.xml deleted file mode 100644 index 5cb983dc4..000000000 --- a/app/src/main/res/values-sw720dp/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 24dp - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index e82288767..af52b6c3d 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,6 +1,4 @@ - 16dp - 16dp 12dp From 296201d6b7a14427014c24801fec2d931b2860e5 Mon Sep 17 00:00:00 2001 From: arkon Date: Thu, 30 Nov 2023 22:23:30 -0500 Subject: [PATCH 4/5] Replace ReaderOrientation icon resources --- .../reader/OrientationSelectDialog.kt | 4 +-- .../reader/appbars/BottomReaderBar.kt | 2 +- .../ui/reader/setting/ReaderOrientation.kt | 25 +++++++++++-------- .../ic_screen_lock_landscape_24dp.xml | 9 ------- .../drawable/ic_screen_lock_portrait_24dp.xml | 9 ------- .../res/drawable/ic_screen_rotation_24dp.xml | 9 ------- .../ic_stay_current_landscape_24dp.xml | 9 ------- .../ic_stay_current_portrait_24dp.xml | 9 ------- 8 files changed, 17 insertions(+), 59 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_screen_lock_landscape_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_screen_rotation_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_stay_current_landscape_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_stay_current_portrait_24dp.xml diff --git a/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt index ea6f3d58f..22a02444c 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt @@ -11,8 +11,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.PreviewLightDark import dev.icerock.moko.resources.StringResource import eu.kanade.domain.manga.model.readerOrientation @@ -72,7 +70,7 @@ private fun DialogContent( selected = mode }, modifier = Modifier.fillMaxWidth(), - imageVector = ImageVector.vectorResource(mode.iconRes), + imageVector = mode.icon, title = stringResource(mode.stringRes), ) } diff --git a/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt b/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt index b1f7189ed..8d0cae57b 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt @@ -49,7 +49,7 @@ fun BottomReaderBar( IconButton(onClick = onClickOrientation) { Icon( - painter = painterResource(orientation.iconRes), + imageVector = orientation.icon, contentDescription = stringResource(MR.strings.rotation_type), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt index 01073cd60..ad0e58a15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt @@ -1,57 +1,62 @@ package eu.kanade.tachiyomi.ui.reader.setting import android.content.pm.ActivityInfo -import androidx.annotation.DrawableRes +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ScreenLockLandscape +import androidx.compose.material.icons.filled.ScreenLockPortrait +import androidx.compose.material.icons.filled.ScreenRotation +import androidx.compose.material.icons.filled.StayCurrentLandscape +import androidx.compose.material.icons.filled.StayCurrentPortrait +import androidx.compose.ui.graphics.vector.ImageVector import dev.icerock.moko.resources.StringResource -import eu.kanade.tachiyomi.R import tachiyomi.i18n.MR enum class ReaderOrientation( val flag: Int, val stringRes: StringResource, - @DrawableRes val iconRes: Int, + val icon: ImageVector, val flagValue: Int, ) { DEFAULT( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, MR.strings.label_default, - R.drawable.ic_screen_rotation_24dp, + Icons.Default.ScreenRotation, 0x00000000, ), FREE( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, MR.strings.rotation_free, - R.drawable.ic_screen_rotation_24dp, + Icons.Default.ScreenRotation, 0x00000008, ), PORTRAIT( ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, MR.strings.rotation_portrait, - R.drawable.ic_stay_current_portrait_24dp, + Icons.Default.StayCurrentPortrait, 0x00000010, ), LANDSCAPE( ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, MR.strings.rotation_landscape, - R.drawable.ic_stay_current_landscape_24dp, + Icons.Default.StayCurrentLandscape, 0x00000018, ), LOCKED_PORTRAIT( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, MR.strings.rotation_force_portrait, - R.drawable.ic_screen_lock_portrait_24dp, + Icons.Default.ScreenLockPortrait, 0x00000020, ), LOCKED_LANDSCAPE( ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, MR.strings.rotation_force_landscape, - R.drawable.ic_screen_lock_landscape_24dp, + Icons.Default.ScreenLockLandscape, 0x00000028, ), REVERSE_PORTRAIT( ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT, MR.strings.rotation_reverse_portrait, - R.drawable.ic_stay_current_portrait_24dp, + Icons.Default.StayCurrentPortrait, 0x00000030, ), ; diff --git a/app/src/main/res/drawable/ic_screen_lock_landscape_24dp.xml b/app/src/main/res/drawable/ic_screen_lock_landscape_24dp.xml deleted file mode 100644 index 6c46c7b8a..000000000 --- a/app/src/main/res/drawable/ic_screen_lock_landscape_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml b/app/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml deleted file mode 100644 index c7ee82f6b..000000000 --- a/app/src/main/res/drawable/ic_screen_lock_portrait_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_screen_rotation_24dp.xml b/app/src/main/res/drawable/ic_screen_rotation_24dp.xml deleted file mode 100644 index 04460bd85..000000000 --- a/app/src/main/res/drawable/ic_screen_rotation_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_stay_current_landscape_24dp.xml b/app/src/main/res/drawable/ic_stay_current_landscape_24dp.xml deleted file mode 100644 index a36b366c4..000000000 --- a/app/src/main/res/drawable/ic_stay_current_landscape_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_stay_current_portrait_24dp.xml b/app/src/main/res/drawable/ic_stay_current_portrait_24dp.xml deleted file mode 100644 index 25ce49739..000000000 --- a/app/src/main/res/drawable/ic_stay_current_portrait_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - From 7a52afd223332819d462365138f65ad8bcd8b3d9 Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 1 Dec 2023 22:27:15 -0500 Subject: [PATCH 5/5] Bump dependencies --- .../eu/kanade/presentation/browse/ExtensionDetailsScreen.kt | 1 + .../eu/kanade/presentation/browse/ExtensionFilterScreen.kt | 1 + .../java/eu/kanade/presentation/browse/ExtensionsScreen.kt | 3 +++ .../eu/kanade/presentation/browse/MigrateSourceScreen.kt | 1 + .../eu/kanade/presentation/browse/SourcesFilterScreen.kt | 2 ++ .../java/eu/kanade/presentation/browse/SourcesScreen.kt | 2 ++ .../java/eu/kanade/presentation/category/CategoryScreen.kt | 1 + .../java/eu/kanade/presentation/history/HistoryScreen.kt | 2 ++ .../java/eu/kanade/presentation/updates/UpdatesUiItem.kt | 3 +++ gradle/androidx.versions.toml | 6 +++--- gradle/compose.versions.toml | 2 +- gradle/libs.versions.toml | 2 +- 12 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt index abb893572..c94a687c2 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt @@ -190,6 +190,7 @@ private fun ExtensionDetails( key = { it.source.id }, ) { source -> SourceSwitchPreference( + modifier = Modifier.animateItemPlacement(), source = source, onClickSourcePreferences = onClickSourcePreferences, onClickSource = onClickSource, diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt index 51acdfccf..c65f0d0b1 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt @@ -58,6 +58,7 @@ private fun ExtensionFilterContent( ) { items(state.languages) { language -> SwitchPreferenceWidget( + modifier = Modifier.animateItemPlacement(), title = LocaleHelper.getSourceDisplayName(language, context), checked = language in state.enabledLanguages, onCheckedChanged = { onClickLang(language) }, diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt index 3469af6ca..2e4c6fc0b 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt @@ -148,12 +148,14 @@ private fun ExtensionContent( } ExtensionHeader( textRes = header.textRes, + modifier = Modifier.animateItemPlacement(), action = action, ) } is ExtensionUiModel.Header.Text -> { ExtensionHeader( text = header.text, + modifier = Modifier.animateItemPlacement(), ) } } @@ -165,6 +167,7 @@ private fun ExtensionContent( key = { "extension-${it.hashCode()}" }, ) { item -> ExtensionItem( + modifier = Modifier.animateItemPlacement(), item = item, onClickItem = { when (it) { diff --git a/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt index b7dc70ebb..e45ca5189 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt @@ -132,6 +132,7 @@ private fun MigrateSourceList( key = { (source, _) -> "migrate-${source.id}" }, ) { (source, count) -> MigrateSourceItem( + modifier = Modifier.animateItemPlacement(), source = source, count = count, onClickItem = { onClickItem(source) }, diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt index 6306800b8..e334a451e 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt @@ -68,6 +68,7 @@ private fun SourcesFilterContent( contentType = "source-filter-header", ) { SourcesFilterHeader( + modifier = Modifier.animateItemPlacement(), language = language, enabled = enabled, onClickItem = onClickLanguage, @@ -80,6 +81,7 @@ private fun SourcesFilterContent( contentType = { "source-filter-item" }, ) { source -> SourcesFilterItem( + modifier = Modifier.animateItemPlacement(), source = source, enabled = "${source.id}" !in state.disabledSources, onClickItem = onClickSource, diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt index 94cca357d..d0411b7a8 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt @@ -74,10 +74,12 @@ fun SourcesScreen( when (model) { is SourceUiModel.Header -> { SourceHeader( + modifier = Modifier.animateItemPlacement(), language = model.language, ) } is SourceUiModel.Item -> SourceItem( + modifier = Modifier.animateItemPlacement(), source = model.source, onClickItem = onClickItem, onLongClickItem = onLongClickItem, diff --git a/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt b/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt index 471ec7fc9..34a6a1217 100644 --- a/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt @@ -107,6 +107,7 @@ private fun CategoryContent( key = { _, category -> "category-${category.id}" }, ) { index, category -> CategoryListItem( + modifier = Modifier.animateItemPlacement(), category = category, canMoveUp = index != 0, canMoveDown = index != categories.lastIndex, diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt index ec6416480..ce6871e13 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -123,6 +123,7 @@ private fun HistoryScreenContent( when (item) { is HistoryUiModel.Header -> { RelativeDateHeader( + modifier = Modifier.animateItemPlacement(), date = item.date, relativeTime = relativeTime, dateFormat = dateFormat, @@ -131,6 +132,7 @@ private fun HistoryScreenContent( is HistoryUiModel.Item -> { val value = item.item HistoryItem( + modifier = Modifier.animateItemPlacement(), history = value, onClickCover = { onClickCover(value) }, onClickResume = { onClickResume(value) }, diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt index ad2e0dbc3..eeaee2008 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt @@ -53,6 +53,7 @@ internal fun LazyListScope.updatesLastUpdatedItem( item(key = "updates-lastUpdated") { Box( modifier = Modifier + .animateItemPlacement() .padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small), ) { Text( @@ -89,12 +90,14 @@ internal fun LazyListScope.updatesUiItems( when (item) { is UpdatesUiModel.Header -> { ListGroupHeader( + modifier = Modifier.animateItemPlacement(), text = item.date, ) } is UpdatesUiModel.Item -> { val updatesItem = item.item UpdatesUiItem( + modifier = Modifier.animateItemPlacement(), update = updatesItem.update, selected = updatesItem.selected, readProgress = updatesItem.update.lastPageRead diff --git a/gradle/androidx.versions.toml b/gradle/androidx.versions.toml index 5d7aead08..cc110cdf6 100644 --- a/gradle/androidx.versions.toml +++ b/gradle/androidx.versions.toml @@ -25,9 +25,9 @@ workmanager = "androidx.work:work-runtime:2.9.0" paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging_version" } paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging_version" } -benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.1" -test-ext = "androidx.test.ext:junit-ktx:1.2.0-alpha01" -test-espresso-core = "androidx.test.espresso:espresso-core:3.6.0-alpha01" +benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.2" +test-ext = "androidx.test.ext:junit-ktx:1.2.0-alpha02" +test-espresso-core = "androidx.test.espresso:espresso-core:3.6.0-alpha02" test-uiautomator = "androidx.test.uiautomator:uiautomator:2.3.0-alpha05" [bundles] diff --git a/gradle/compose.versions.toml b/gradle/compose.versions.toml index 6ccce2b06..6bfad292f 100644 --- a/gradle/compose.versions.toml +++ b/gradle/compose.versions.toml @@ -1,6 +1,6 @@ [versions] compiler = "1.5.5" -compose-bom = "2023.12.00-alpha02" +compose-bom = "2023.12.00-alpha03" accompanist = "0.33.2-alpha" [libraries] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3cd0e3da7..8724b39d2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -93,7 +93,7 @@ voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version. voyager-tab-navigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" } voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" } -ktlint = "org.jlleitschuh.gradle:ktlint-gradle:11.6.1" +ktlint = "org.jlleitschuh.gradle:ktlint-gradle:12.0.2" [bundles] okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"]