From 3d0d5c047228f13d8a6a7d90400f4d67f2817f24 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 30 Dec 2023 18:33:35 -0500 Subject: [PATCH] Misc refactoring - Abstract away relative date string building - Dedupe large update warning logic --- .../presentation/components/DateText.kt | 38 +++++++++++++++++++ .../components/RelativeDateHeader.kt | 30 --------------- .../presentation/history/HistoryScreen.kt | 31 ++------------- .../kanade/presentation/manga/MangaScreen.kt | 31 +-------------- .../presentation/updates/UpdatesScreen.kt | 9 ++--- .../presentation/updates/UpdatesUiItem.kt | 3 +- .../data/library/LibraryUpdateJob.kt | 19 +++------- .../data/library/LibraryUpdateNotifier.kt | 37 ++++++++++++++---- .../data/library/MetadataUpdateJob.kt | 16 ++------ .../kanade/tachiyomi/ui/manga/MangaScreen.kt | 2 - .../tachiyomi/ui/manga/MangaScreenModel.kt | 5 --- .../ui/updates/UpdatesScreenModel.kt | 17 +-------- .../kanade/tachiyomi/ui/updates/UpdatesTab.kt | 1 - 13 files changed, 88 insertions(+), 151 deletions(-) create mode 100644 app/src/main/java/eu/kanade/presentation/components/DateText.kt delete mode 100644 app/src/main/java/eu/kanade/presentation/components/RelativeDateHeader.kt diff --git a/app/src/main/java/eu/kanade/presentation/components/DateText.kt b/app/src/main/java/eu/kanade/presentation/components/DateText.kt new file mode 100644 index 000000000..c79cfac12 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/components/DateText.kt @@ -0,0 +1,38 @@ +package eu.kanade.presentation.components + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import eu.kanade.domain.ui.UiPreferences +import eu.kanade.tachiyomi.util.lang.toRelativeString +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.stringResource +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.util.Date + +@Composable +fun relativeDateText( + date: Long, +): String { + return relativeDateText(date = Date(date).takeIf { date > 0L }) +} + +@Composable +fun relativeDateText( + date: Date?, +): String { + val context = LocalContext.current + + val preferences = remember { Injekt.get() } + val relativeTime = remember { preferences.relativeTime().get() } + val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) } + + return date + ?.toRelativeString( + context, + relativeTime, + dateFormat, + ) + ?: stringResource(MR.strings.not_applicable) +} diff --git a/app/src/main/java/eu/kanade/presentation/components/RelativeDateHeader.kt b/app/src/main/java/eu/kanade/presentation/components/RelativeDateHeader.kt deleted file mode 100644 index c291890e3..000000000 --- a/app/src/main/java/eu/kanade/presentation/components/RelativeDateHeader.kt +++ /dev/null @@ -1,30 +0,0 @@ -package eu.kanade.presentation.components - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import eu.kanade.tachiyomi.util.lang.toRelativeString -import tachiyomi.presentation.core.components.ListGroupHeader -import java.text.DateFormat -import java.util.Date - -@Composable -fun RelativeDateHeader( - date: Date, - relativeTime: Boolean, - dateFormat: DateFormat, - modifier: Modifier = Modifier, -) { - val context = LocalContext.current - ListGroupHeader( - modifier = modifier, - text = remember { - date.toRelativeString( - context, - relativeTime, - dateFormat, - ) - }, - ) -} 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 ce6871e13..a4c47af5e 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -8,30 +8,26 @@ import androidx.compose.material.icons.outlined.DeleteSweep import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter -import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.AppBarTitle -import eu.kanade.presentation.components.RelativeDateHeader import eu.kanade.presentation.components.SearchToolbar +import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.history.components.HistoryItem import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.ui.history.HistoryScreenModel import kotlinx.collections.immutable.persistentListOf -import tachiyomi.core.preference.InMemoryPreferenceStore import tachiyomi.domain.history.model.HistoryWithRelations import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.FastScrollLazyColumn +import tachiyomi.presentation.core.components.ListGroupHeader import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get import java.util.Date @Composable @@ -42,7 +38,6 @@ fun HistoryScreen( onClickCover: (mangaId: Long) -> Unit, onClickResume: (mangaId: Long, chapterId: Long) -> Unit, onDialogChange: (HistoryScreenModel.Dialog?) -> Unit, - preferences: UiPreferences = Injekt.get(), ) { Scaffold( topBar = { scrollBehavior -> @@ -88,7 +83,6 @@ fun HistoryScreen( onClickCover = { history -> onClickCover(history.mangaId) }, onClickResume = { history -> onClickResume(history.mangaId, history.chapterId) }, onClickDelete = { item -> onDialogChange(HistoryScreenModel.Dialog.Delete(item)) }, - preferences = preferences, ) } } @@ -102,11 +96,7 @@ private fun HistoryScreenContent( onClickCover: (HistoryWithRelations) -> Unit, onClickResume: (HistoryWithRelations) -> Unit, onClickDelete: (HistoryWithRelations) -> Unit, - preferences: UiPreferences, ) { - val relativeTime = remember { preferences.relativeTime().get() } - val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) } - FastScrollLazyColumn( contentPadding = contentPadding, ) { @@ -122,11 +112,9 @@ private fun HistoryScreenContent( ) { item -> when (item) { is HistoryUiModel.Header -> { - RelativeDateHeader( + ListGroupHeader( modifier = Modifier.animateItemPlacement(), - date = item.date, - relativeTime = relativeTime, - dateFormat = dateFormat, + text = relativeDateText(item.date), ) } is HistoryUiModel.Item -> { @@ -163,17 +151,6 @@ internal fun HistoryScreenPreviews( onClickCover = {}, onClickResume = { _, _ -> run {} }, onDialogChange = {}, - preferences = UiPreferences( - InMemoryPreferenceStore( - sequenceOf( - InMemoryPreferenceStore.InMemoryPreference( - key = "relative_time_v2", - data = false, - defaultValue = false, - ), - ), - ), - ), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index e8d871370..7a6d8d50b 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -47,6 +47,7 @@ import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastMap +import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.manga.components.ChapterHeader import eu.kanade.presentation.manga.components.ExpandableMangaDescription @@ -61,7 +62,6 @@ import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.source.getNameForMangaInfo import eu.kanade.tachiyomi.ui.manga.ChapterList import eu.kanade.tachiyomi.ui.manga.MangaScreenModel -import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.system.copyToClipboard import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.service.missingChaptersCount @@ -78,16 +78,12 @@ import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrollingUp import tachiyomi.source.local.isLocal -import java.text.DateFormat -import java.util.Date @Composable fun MangaScreen( state: MangaScreenModel.State.Success, snackbarHostState: SnackbarHostState, fetchInterval: Int?, - dateRelativeTime: Boolean, - dateFormat: DateFormat, isTabletUi: Boolean, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, @@ -142,8 +138,6 @@ fun MangaScreen( MangaScreenSmallImpl( state = state, snackbarHostState = snackbarHostState, - dateRelativeTime = dateRelativeTime, - dateFormat = dateFormat, fetchInterval = fetchInterval, chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeEndAction = chapterSwipeEndAction, @@ -179,10 +173,8 @@ fun MangaScreen( MangaScreenLargeImpl( state = state, snackbarHostState = snackbarHostState, - dateRelativeTime = dateRelativeTime, chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeEndAction = chapterSwipeEndAction, - dateFormat = dateFormat, fetchInterval = fetchInterval, onBackClicked = onBackClicked, onChapterClicked = onChapterClicked, @@ -219,8 +211,6 @@ fun MangaScreen( private fun MangaScreenSmallImpl( state: MangaScreenModel.State.Success, snackbarHostState: SnackbarHostState, - dateRelativeTime: Boolean, - dateFormat: DateFormat, fetchInterval: Int?, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, @@ -455,8 +445,6 @@ private fun MangaScreenSmallImpl( manga = state.manga, chapters = listItem, isAnyChapterSelected = chapters.fastAny { it.selected }, - dateRelativeTime = dateRelativeTime, - dateFormat = dateFormat, chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeEndAction = chapterSwipeEndAction, onChapterClicked = onChapterClicked, @@ -474,8 +462,6 @@ private fun MangaScreenSmallImpl( fun MangaScreenLargeImpl( state: MangaScreenModel.State.Success, snackbarHostState: SnackbarHostState, - dateRelativeTime: Boolean, - dateFormat: DateFormat, fetchInterval: Int?, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, @@ -705,8 +691,6 @@ fun MangaScreenLargeImpl( manga = state.manga, chapters = listItem, isAnyChapterSelected = chapters.fastAny { it.selected }, - dateRelativeTime = dateRelativeTime, - dateFormat = dateFormat, chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeEndAction = chapterSwipeEndAction, onChapterClicked = onChapterClicked, @@ -768,8 +752,6 @@ private fun LazyListScope.sharedChapterItems( manga: Manga, chapters: List, isAnyChapterSelected: Boolean, - dateRelativeTime: Boolean, - dateFormat: DateFormat, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, onChapterClicked: (Chapter) -> Unit, @@ -788,7 +770,6 @@ private fun LazyListScope.sharedChapterItems( contentType = { MangaScreenItem.CHAPTER }, ) { item -> val haptic = LocalHapticFeedback.current - val context = LocalContext.current when (item) { is ChapterList.MissingCount -> { @@ -804,15 +785,7 @@ private fun LazyListScope.sharedChapterItems( } else { item.chapter.name }, - date = item.chapter.dateUpload - .takeIf { it > 0L } - ?.let { - Date(it).toRelativeString( - context, - dateRelativeTime, - dateFormat, - ) - }, + date = relativeDateText(item.chapter.dateUpload), readProgress = item.chapter.lastPageRead .takeIf { !item.chapter.read && it > 0L } ?.let { diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt index 3fd9cd0a4..ca1e5632c 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny import eu.kanade.presentation.components.AppBar @@ -37,6 +36,7 @@ import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen +import java.util.Date import kotlin.time.Duration.Companion.seconds @Composable @@ -44,7 +44,6 @@ fun UpdateScreen( state: UpdatesScreenModel.State, snackbarHostState: SnackbarHostState, lastUpdated: Long, - relativeTime: Boolean, onClickCover: (UpdatesItem) -> Unit, onSelectAll: (Boolean) -> Unit, onInvertSelection: () -> Unit, @@ -58,8 +57,6 @@ fun UpdateScreen( ) { BackHandler(enabled = state.selectionMode, onBack = { onSelectAll(false) }) - val context = LocalContext.current - Scaffold( topBar = { scrollBehavior -> UpdatesAppBar( @@ -113,7 +110,7 @@ fun UpdateScreen( updatesLastUpdatedItem(lastUpdated) updatesUiItems( - uiModels = state.getUiModel(context, relativeTime), + uiModels = state.getUiModel(), selectionMode = state.selectionMode, onUpdateSelected = onUpdateSelected, onClickCover = onClickCover, @@ -209,6 +206,6 @@ private fun UpdatesBottomBar( } sealed interface UpdatesUiModel { - data class Header(val date: String) : UpdatesUiModel + data class Header(val date: Date) : UpdatesUiModel data class Item(val item: UpdatesItem) : UpdatesUiModel } 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 eeaee2008..a69252ffc 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.manga.components.ChapterDownloadIndicator import eu.kanade.presentation.manga.components.DotSeparatorText @@ -91,7 +92,7 @@ internal fun LazyListScope.updatesUiItems( is UpdatesUiModel.Header -> { ListGroupHeader( modifier = Modifier.animateItemPlacement(), - text = item.date, + text = relativeDateText(item.date), ) } is UpdatesUiModel.Item -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index c7a714a01..d7384fe51 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -22,7 +22,6 @@ import eu.kanade.domain.manga.model.toSManga import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.notification.Notifications -import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.UpdateStrategy import eu.kanade.tachiyomi.util.shouldDownloadNewChapters @@ -37,7 +36,6 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.ensureActive -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import logcat.LogPriority @@ -152,8 +150,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet * * @param categoryId the ID of the category to update, or -1 if no category specified. */ - private fun addMangaToQueue(categoryId: Long) { - val libraryManga = runBlocking { getLibraryManga.await() } + private suspend fun addMangaToQueue(categoryId: Long) { + val libraryManga = getLibraryManga.await() val listToUpdate = if (categoryId != -1L) { libraryManga.filter { it.category == categoryId } @@ -179,7 +177,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet val restrictions = libraryPreferences.autoUpdateMangaRestrictions().get() val skippedUpdates = mutableListOf>() - val fetchWindow = fetchInterval.getWindow(ZonedDateTime.now()) + val (_, fetchWindowUpperBound) = fetchInterval.getWindow(ZonedDateTime.now()) mangaToUpdate = listToUpdate .filter { @@ -206,7 +204,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet false } - MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && it.manga.nextUpdate > fetchWindow.second -> { + MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && it.manga.nextUpdate > fetchWindowUpperBound -> { skippedUpdates.add( it.manga to context.stringResource(MR.strings.skipped_reason_not_in_release_period), ) @@ -218,14 +216,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet } .sortedBy { it.manga.title } - // Warn when excessively checking a single source - val maxUpdatesFromSource = mangaToUpdate - .groupBy { it.manga.source } - .filterKeys { sourceManager.get(it) !is UnmeteredSource } - .maxOfOrNull { it.value.size } ?: 0 - if (maxUpdatesFromSource > MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { - notifier.showQueueSizeWarningNotification() - } + notifier.showQueueSizeWarningNotificationIfNeeded(mangaToUpdate) if (skippedUpdates.isNotEmpty()) { // TODO: surface skipped reasons to user? diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index 06d61589d..74e6c77e5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.data.download.Downloader import eu.kanade.tachiyomi.data.notification.NotificationHandler import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications +import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.system.cancelNotification @@ -30,15 +31,22 @@ import tachiyomi.core.i18n.pluralStringResource import tachiyomi.core.i18n.stringResource import tachiyomi.core.util.lang.launchUI import tachiyomi.domain.chapter.model.Chapter +import tachiyomi.domain.library.model.LibraryManga import tachiyomi.domain.manga.model.Manga +import tachiyomi.domain.source.service.SourceManager import tachiyomi.i18n.MR -import uy.kohesive.injekt.injectLazy +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import java.math.RoundingMode import java.text.NumberFormat -class LibraryUpdateNotifier(private val context: Context) { +class LibraryUpdateNotifier( + private val context: Context, + + private val securityPreferences: SecurityPreferences = Injekt.get(), + private val sourceManager: SourceManager = Injekt.get(), +) { - private val preferences: SecurityPreferences by injectLazy() private val percentFormatter = NumberFormat.getPercentInstance().apply { roundingMode = RoundingMode.DOWN maximumFractionDigits = 0 @@ -88,7 +96,7 @@ class LibraryUpdateNotifier(private val context: Context) { ), ) - if (!preferences.hideNotificationContent().get()) { + if (!securityPreferences.hideNotificationContent().get()) { val updatingText = manga.joinToString("\n") { it.title.chop(40) } progressNotificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(updatingText)) } @@ -101,7 +109,19 @@ class LibraryUpdateNotifier(private val context: Context) { ) } - fun showQueueSizeWarningNotification() { + /** + * Warn when excessively checking any single source. + */ + fun showQueueSizeWarningNotificationIfNeeded(mangaToUpdate: List) { + val maxUpdatesFromSource = mangaToUpdate + .groupBy { it.manga.source } + .filterKeys { sourceManager.get(it) !is UnmeteredSource } + .maxOfOrNull { it.value.size } ?: 0 + + if (maxUpdatesFromSource <= MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { + return + } + context.notify( Notifications.ID_LIBRARY_SIZE_WARNING, Notifications.CHANNEL_LIBRARY_PROGRESS, @@ -151,7 +171,7 @@ class LibraryUpdateNotifier(private val context: Context) { Notifications.CHANNEL_NEW_CHAPTERS, ) { setContentTitle(context.stringResource(MR.strings.notification_new_chapters)) - if (updates.size == 1 && !preferences.hideNotificationContent().get()) { + if (updates.size == 1 && !securityPreferences.hideNotificationContent().get()) { setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) } else { setContentText( @@ -162,7 +182,7 @@ class LibraryUpdateNotifier(private val context: Context) { ), ) - if (!preferences.hideNotificationContent().get()) { + if (!securityPreferences.hideNotificationContent().get()) { setStyle( NotificationCompat.BigTextStyle().bigText( updates.joinToString("\n") { @@ -186,7 +206,7 @@ class LibraryUpdateNotifier(private val context: Context) { } // Per-manga notification - if (!preferences.hideNotificationContent().get()) { + if (!securityPreferences.hideNotificationContent().get()) { launchUI { context.notify( updates.map { (manga, chapters) -> @@ -364,3 +384,4 @@ class LibraryUpdateNotifier(private val context: Context) { private const val NOTIF_MAX_CHAPTERS = 5 private const val NOTIF_TITLE_MAX_LEN = 45 private const val NOTIF_ICON_SIZE = 192 +private const val MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 60 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt index fc8de7617..348b41ca3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt @@ -15,7 +15,6 @@ import eu.kanade.domain.manga.model.copyFrom import eu.kanade.domain.manga.model.toSManga import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.notification.Notifications -import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.system.isRunning import eu.kanade.tachiyomi.util.system.setForegroundSafely @@ -25,7 +24,6 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.ensureActive -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import logcat.LogPriority @@ -92,17 +90,9 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame /** * Adds list of manga to be updated. */ - private fun addMangaToQueue() { - mangaToUpdate = runBlocking { getLibraryManga.await() } - - // Warn when excessively checking a single source - val maxUpdatesFromSource = mangaToUpdate - .groupBy { it.manga.source } - .filterKeys { sourceManager.get(it) !is UnmeteredSource } - .maxOfOrNull { it.value.size } ?: 0 - if (maxUpdatesFromSource > MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { - notifier.showQueueSizeWarningNotification() - } + private suspend fun addMangaToQueue() { + mangaToUpdate = getLibraryManga.await() + notifier.showQueueSizeWarningNotificationIfNeeded(mangaToUpdate) } private suspend fun updateMetadata() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt index 53bae43d6..1bb46d82e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt @@ -104,8 +104,6 @@ class MangaScreen( MangaScreen( state = successState, snackbarHostState = screenModel.snackbarHostState, - dateRelativeTime = screenModel.relativeTime, - dateFormat = screenModel.dateFormat, fetchInterval = successState.manga.fetchInterval, isTabletUi = isTabletUi(), chapterSwipeStartAction = screenModel.chapterSwipeStartAction, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index 1c36d19d9..aa85aec5a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -5,7 +5,6 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.util.fastAny import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope @@ -22,7 +21,6 @@ import eu.kanade.domain.manga.model.chaptersFiltered import eu.kanade.domain.manga.model.downloadedFilter import eu.kanade.domain.manga.model.toSManga import eu.kanade.domain.track.interactor.AddTracks -import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.manga.DownloadAction import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.util.formattedMessage @@ -92,7 +90,6 @@ class MangaScreenModel( private val downloadPreferences: DownloadPreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), readerPreferences: ReaderPreferences = Injekt.get(), - uiPreferences: UiPreferences = Injekt.get(), private val trackerManager: TrackerManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(), private val downloadCache: DownloadCache = Injekt.get(), @@ -138,8 +135,6 @@ class MangaScreenModel( val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get() val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get() - val relativeTime by uiPreferences.relativeTime().asState(screenModelScope) - val dateFormat by mutableStateOf(UiPreferences.dateFormat(uiPreferences.dateFormat().get())) private val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope) val isUpdateIntervalEnabled = diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt index 9e4f31296..9574d0c7f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt @@ -1,18 +1,15 @@ package eu.kanade.tachiyomi.ui.updates import android.app.Application -import android.content.Context import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope import eu.kanade.core.preference.asState import eu.kanade.core.util.addOrRemove import eu.kanade.core.util.insertSeparators import eu.kanade.domain.chapter.interactor.SetReadStatus -import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.updates.UpdatesUiModel import eu.kanade.tachiyomi.data.download.DownloadCache @@ -20,7 +17,6 @@ import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.util.lang.toDateKey -import eu.kanade.tachiyomi.util.lang.toRelativeString import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.mutate import kotlinx.collections.immutable.persistentListOf @@ -63,14 +59,12 @@ class UpdatesScreenModel( private val getChapter: GetChapter = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), val snackbarHostState: SnackbarHostState = SnackbarHostState(), - uiPreferences: UiPreferences = Injekt.get(), ) : StateScreenModel(State()) { private val _events: Channel = Channel(Int.MAX_VALUE) val events: Flow = _events.receiveAsFlow() val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(screenModelScope) - val relativeTime by uiPreferences.relativeTime().asState(screenModelScope) // First and last selected index in list private val selectedPositions: Array = arrayOf(-1, -1) @@ -376,9 +370,7 @@ class UpdatesScreenModel( val selected = items.filter { it.selected } val selectionMode = selected.isNotEmpty() - fun getUiModel(context: Context, relativeTime: Boolean): List { - val dateFormat by mutableStateOf(UiPreferences.dateFormat(Injekt.get().dateFormat().get())) - + fun getUiModel(): List { return items .map { UpdatesUiModel.Item(it) } .insertSeparators { before, after -> @@ -386,12 +378,7 @@ class UpdatesScreenModel( val afterDate = after?.item?.update?.dateFetch?.toDateKey() ?: Date(0) when { beforeDate.time != afterDate.time && afterDate.time != 0L -> { - val text = afterDate.toRelativeString( - context = context, - relative = relativeTime, - dateFormat = dateFormat, - ) - UpdatesUiModel.Header(text) + UpdatesUiModel.Header(afterDate) } // Return null to avoid adding a separator between two items. else -> null diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt index 9703b5fcf..d84bcd38f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt @@ -59,7 +59,6 @@ object UpdatesTab : Tab { state = state, snackbarHostState = screenModel.snackbarHostState, lastUpdated = screenModel.lastUpdated, - relativeTime = screenModel.relativeTime, onClickCover = { item -> navigator.push(MangaScreen(item.update.mangaId)) }, onSelectAll = screenModel::toggleAllSelection, onInvertSelection = screenModel::invertSelection,