From f0b621dfe582b7493356bf0ccf86cab400bff72e Mon Sep 17 00:00:00 2001 From: Jobobby04 Date: Thu, 7 Nov 2024 22:21:02 -0500 Subject: [PATCH] Fix multiple issues with the E-Hentai updater --- app/build.gradle.kts | 2 +- .../data/notification/Notifications.kt | 10 ++ .../main/java/exh/eh/EHentaiUpdateNotifier.kt | 109 ++++++++++++++++++ .../main/java/exh/eh/EHentaiUpdateWorker.kt | 40 ++++++- .../java/exh/favorites/FavoritesSyncHelper.kt | 2 +- .../kotlin/exh/md/utils/MangaDexRelation.kt | 2 +- 6 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/exh/eh/EHentaiUpdateNotifier.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d5fe65137..57f3a5217 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -31,7 +31,7 @@ android { defaultConfig { applicationId = "eu.kanade.tachiyomi.sy" - versionCode = 70 + versionCode = 71 versionName = "1.11.0" buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt index 6b34d124d..87c61c90f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt @@ -30,6 +30,9 @@ object Notifications { const val ID_LIBRARY_SIZE_WARNING = -103 const val CHANNEL_LIBRARY_ERROR = "library_errors_channel" const val ID_LIBRARY_ERROR = -102 + const val CHANNEL_LIBRARY_EHENTAI = "library_ehentai_channel" + const val ID_EHENTAI_PROGRESS = -199 + const val ID_EHENTAI_ERROR = -198 /** * Notification channel and ids used by the downloader. @@ -166,6 +169,13 @@ object Notifications { setGroup(GROUP_APK_UPDATES) setName(context.stringResource(MR.strings.channel_ext_updates)) }, + // SY --> + buildNotificationChannel(CHANNEL_LIBRARY_EHENTAI, IMPORTANCE_LOW) { + setName("EHentai") + setGroup(GROUP_LIBRARY) + setShowBadge(false) + }, + //SY <-- ), ) } diff --git a/app/src/main/java/exh/eh/EHentaiUpdateNotifier.kt b/app/src/main/java/exh/eh/EHentaiUpdateNotifier.kt new file mode 100644 index 000000000..009769b21 --- /dev/null +++ b/app/src/main/java/exh/eh/EHentaiUpdateNotifier.kt @@ -0,0 +1,109 @@ +package exh.eh + +import android.content.Context +import android.graphics.BitmapFactory +import android.net.Uri +import androidx.core.app.NotificationCompat +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.core.security.SecurityPreferences +import eu.kanade.tachiyomi.data.notification.NotificationReceiver +import eu.kanade.tachiyomi.data.notification.Notifications +import eu.kanade.tachiyomi.util.lang.chop +import eu.kanade.tachiyomi.util.system.cancelNotification +import eu.kanade.tachiyomi.util.system.notificationBuilder +import eu.kanade.tachiyomi.util.system.notify +import tachiyomi.core.common.i18n.stringResource +import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR +import uy.kohesive.injekt.injectLazy +import java.math.RoundingMode +import java.text.NumberFormat + +class EHentaiUpdateNotifier(private val context: Context) { + + private val securityPreferences: SecurityPreferences by injectLazy() + + private val percentFormatter = NumberFormat.getPercentInstance().apply { + roundingMode = RoundingMode.DOWN + maximumFractionDigits = 0 + } + + /** + * Bitmap of the app for notifications. + */ + private val notificationBitmap by lazy { + BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher) + } + + /** + * Cached progress notification to avoid creating a lot. + */ + val progressNotificationBuilder by lazy { + context.notificationBuilder(Notifications.CHANNEL_LIBRARY_EHENTAI) { + setContentTitle(context.stringResource(MR.strings.app_name)) + setSmallIcon(R.drawable.ic_refresh_24dp) + setLargeIcon(notificationBitmap) + setOngoing(true) + setOnlyAlertOnce(true) + } + } + + /** + * Shows the notification containing the currently updating manga and the progress. + * + * @param manga the manga that are being updated. + * @param current the current progress. + * @param total the total progress. + */ + fun showProgressNotification(manga: Manga, current: Int, total: Int) { + progressNotificationBuilder + .setContentTitle( + context.stringResource( + MR.strings.notification_updating_progress, + percentFormatter.format(current.toFloat() / total), + ), + ) + + if (!securityPreferences.hideNotificationContent().get()) { + val updatingText = manga.title.chop(40) + progressNotificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(updatingText)) + } + + context.notify( + Notifications.ID_EHENTAI_PROGRESS, + progressNotificationBuilder + .setProgress(total, current, false) + .build(), + ) + } + + /** + * Shows notification containing update entries that failed with action to open full log. + * + * @param failed Number of entries that failed to update. + * @param uri Uri for error log file containing all titles that failed. + */ + fun showUpdateErrorNotification(failed: Int, uri: Uri) { + if (failed == 0) { + return + } + + context.notify( + Notifications.ID_EHENTAI_ERROR, + Notifications.CHANNEL_LIBRARY_EHENTAI, + ) { + setContentTitle(context.stringResource(MR.strings.notification_update_error, failed)) + setContentText(context.stringResource(MR.strings.action_show_errors)) + setSmallIcon(R.drawable.ic_tachi) + + setContentIntent(NotificationReceiver.openErrorLogPendingActivity(context, uri)) + } + } + + /** + * Cancels the progress notification. + */ + fun cancelProgressNotification() { + context.cancelNotification(Notifications.ID_EHENTAI_PROGRESS) + } +} diff --git a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt index 7422b29c7..a5cf42eec 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt @@ -1,11 +1,15 @@ package exh.eh import android.content.Context +import android.content.pm.ServiceInfo +import android.os.Build import androidx.work.Constraints import androidx.work.CoroutineWorker import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.ForegroundInfo import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.OutOfQuotaPolicy import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkerParameters import com.elvishew.xlog.Logger @@ -14,8 +18,10 @@ import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.toSManga import eu.kanade.tachiyomi.data.library.LibraryUpdateNotifier +import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.util.system.isConnectedToWifi +import eu.kanade.tachiyomi.util.system.setForegroundSafely import eu.kanade.tachiyomi.util.system.workManager import exh.debug.DebugToggles import exh.eh.EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION @@ -48,7 +54,7 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara private val preferences: UnsortedPreferences by injectLazy() private val sourceManager: SourceManager by injectLazy() private val updateHelper: EHentaiUpdateHelper by injectLazy() - private val logger: Logger = xLog() + private val logger: Logger by lazy { xLog() } private val updateManga: UpdateManga by injectLazy() private val syncChaptersWithSource: SyncChaptersWithSource by injectLazy() private val getChaptersByMangaId: GetChaptersByMangaId by injectLazy() @@ -56,22 +62,38 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara private val insertFlatMetadata: InsertFlatMetadata by injectLazy() private val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy() - private val updateNotifier by lazy { LibraryUpdateNotifier(context) } + private val updateNotifier by lazy { EHentaiUpdateNotifier(context) } + private val libraryUpdateNotifier by lazy { LibraryUpdateNotifier(context) } override suspend fun doWork(): Result { return try { if (requiresWifiConnection(preferences) && !context.isConnectedToWifi()) { Result.success() // retry again later } else { + setForegroundSafely() startUpdating() logger.d("Update job completed!") Result.success() } } catch (e: Exception) { Result.success() // retry again later + } finally { + updateNotifier.cancelProgressNotification() } } + override suspend fun getForegroundInfo(): ForegroundInfo { + return ForegroundInfo( + Notifications.ID_EHENTAI_PROGRESS, + updateNotifier.progressNotificationBuilder.build(), + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC + } else { + 0 + }, + ) + } + private suspend fun startUpdating() { logger.d("Update job started!") val startTime = System.currentTimeMillis() @@ -138,6 +160,11 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara } val (new, chapters) = try { + updateNotifier.showProgressNotification( + manga, + updatedThisIteration + failuresThisIteration, + mangaMetaToUpdateThisIter.size, + ) updateEntryAndGetChapters(manga) } catch (e: GalleryNotUpdatedException) { if (e.network) { @@ -193,8 +220,9 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara ), ) + updateNotifier.cancelProgressNotification() if (updatedManga.isNotEmpty()) { - updateNotifier.showUpdateNotifications(updatedManga) + libraryUpdateNotifier.showUpdateNotifications(updatedManga) } } } @@ -237,7 +265,11 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara private val logger by lazy { XLog.tag("EHUpdaterScheduler") } fun launchBackgroundTest(context: Context) { - context.workManager.enqueue(OneTimeWorkRequestBuilder().build()) + context.workManager.enqueue( + OneTimeWorkRequestBuilder() + .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) + .build(), + ) } fun scheduleBackground(context: Context, prefInterval: Int? = null, prefRestrictions: Set? = null) { diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index 6b4c4cc33..92db1fe96 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -445,7 +445,7 @@ class FavoritesSyncHelper(val context: Context) { } } -sealed class FavoritesSyncStatus() { +sealed class FavoritesSyncStatus { abstract val message: String data class Error(override val message: String) : FavoritesSyncStatus() diff --git a/source-api/src/commonMain/kotlin/exh/md/utils/MangaDexRelation.kt b/source-api/src/commonMain/kotlin/exh/md/utils/MangaDexRelation.kt index 9d7ee4275..14886e45e 100644 --- a/source-api/src/commonMain/kotlin/exh/md/utils/MangaDexRelation.kt +++ b/source-api/src/commonMain/kotlin/exh/md/utils/MangaDexRelation.kt @@ -24,6 +24,6 @@ enum class MangaDexRelation(val res: StringResource, val mdString: String?) { ; companion object { - fun fromDex(mdString: String) = values().find { it.mdString == mdString } + fun fromDex(mdString: String) = entries.find { it.mdString == mdString } } }