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 fc2b7accc0..22ef88cbcc 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -65,6 +65,7 @@ import eu.kanade.tachiyomi.ui.manga.chapterDecimalFormat 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.countMissingChapters import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.model.StubSource import tachiyomi.presentation.core.components.LazyColumn @@ -393,6 +394,7 @@ private fun MangaScreenSmallImpl( ChapterHeader( enabled = chapters.fastAll { !it.selected }, chapterCount = chapters.size, + missingChapters = countMissingChapters(chapters.map { it.chapter.chapterNumber }), onClick = onFilterClicked, ) } @@ -604,6 +606,7 @@ fun MangaScreenLargeImpl( ChapterHeader( enabled = chapters.fastAll { !it.selected }, chapterCount = chapters.size, + missingChapters = countMissingChapters(chapters.map { it.chapter.chapterNumber }), onClick = onFilterButtonClicked, ) } diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt b/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt index edb10131ed..60a4ec7a2f 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt @@ -4,6 +4,9 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material3.AssistChip +import androidx.compose.material3.AssistChipDefaults.assistChipColors +import androidx.compose.material3.AssistChipDefaults.assistChipElevation import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -11,6 +14,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import eu.kanade.tachiyomi.R @@ -18,6 +22,7 @@ import eu.kanade.tachiyomi.R fun ChapterHeader( enabled: Boolean, chapterCount: Int?, + missingChapters: Int?, onClick: () -> Unit, ) { Row( @@ -40,5 +45,42 @@ fun ChapterHeader( modifier = Modifier.weight(1f), color = MaterialTheme.colorScheme.onBackground, ) + + // Missing chapters + if (missingChapters == null) { + DrawWarning( + text = stringResource(R.string.missing_chapters_unknown), + ) + } else if (missingChapters > 0) { + DrawWarning( + text = pluralStringResource( + id = R.plurals.missing_chapters, + count = missingChapters, + missingChapters, + ), + ) + } } } + +@Composable +private fun DrawWarning(text: String) { + AssistChip( + onClick = { + // TODO Show missing chapters + }, + label = { + Text( + text = text, + overflow = TextOverflow.Ellipsis, + color = MaterialTheme.colorScheme.primary, + ) + }, + shape = MaterialTheme.shapes.small, + border = null, + colors = assistChipColors( + containerColor = MaterialTheme.colorScheme.surface, + ), + elevation = assistChipElevation(1.dp), + ) +} diff --git a/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt b/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt new file mode 100644 index 0000000000..783d7e6c46 --- /dev/null +++ b/domain/src/main/java/tachiyomi/domain/chapter/service/MissingChapters.kt @@ -0,0 +1,37 @@ +package tachiyomi.domain.chapter.service + +import kotlin.math.floor + +fun countMissingChapters(chaptersInput: List): Int? { + if (chaptersInput.isEmpty()) { + return 0 + } + + val chapters = chaptersInput + // Remove any invalid chapters + .filter { it != -1f } + // Convert to integers, as we cannot check if 16.5 is missing + .map { floor(it.toDouble()).toInt() } + // Only keep unique chapters so that -1 or 16 are not counted multiple times + .distinct() + .sortedBy { it } + + if (chapters.isEmpty()) { + return null + } + + var missingChaptersCount = 0 + var previousChapter = 0 // The actual chapter number, not the array index + + // We go from 0 to lastChapter - Make sure to use the current index instead of the value + for (i in chapters.indices) { + val currentChapter = chapters[i] + if (currentChapter > previousChapter + 1) { + // Add the amount of missing chapters + missingChaptersCount += currentChapter - previousChapter - 1 + } + previousChapter = currentChapter + } + + return missingChaptersCount +} diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 32f6f34a1b..e37db94c0a 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -612,6 +612,11 @@ Date + + Missing %1$s chapter + Missing %1$s chapters + + Might be missing chapters Ongoing Unknown Unknown author