Last commit merged: c9a1bd86b5
This commit is contained in:
LuftVerbot 2023-11-18 17:20:36 +01:00
parent a2a445fdc5
commit eeddf17691
75 changed files with 35062 additions and 20360 deletions

View file

@ -73,11 +73,11 @@ android {
initWith(getByName("release")) initWith(getByName("release"))
buildConfigField("boolean", "PREVIEW", "true") buildConfigField("boolean", "PREVIEW", "true")
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks.add("release")
val debugType = getByName("debug") val debugType = getByName("debug")
signingConfig = debugType.signingConfig
versionNameSuffix = debugType.versionNameSuffix versionNameSuffix = debugType.versionNameSuffix
applicationIdSuffix = debugType.applicationIdSuffix applicationIdSuffix = debugType.applicationIdSuffix
matchingFallbacks.add("release")
} }
create("benchmark") { create("benchmark") {
initWith(getByName("release")) initWith(getByName("release"))
@ -177,7 +177,6 @@ dependencies {
implementation(androidx.paging.compose) implementation(androidx.paging.compose)
implementation(libs.bundles.sqlite) implementation(libs.bundles.sqlite)
implementation(libs.sqldelight.primitive.adapters)
implementation(kotlinx.reflect) implementation(kotlinx.reflect)

File diff suppressed because it is too large Load diff

View file

@ -99,7 +99,7 @@ fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories:
title = ComicInfo.Title(chapter.name), title = ComicInfo.Title(chapter.name),
series = ComicInfo.Series(manga.title), series = ComicInfo.Series(manga.title),
number = chapter.chapterNumber.takeIf { it >= 0 }?.let { number = chapter.chapterNumber.takeIf { it >= 0 }?.let {
if ((it.rem(1) == 0.0F)) { if ((it.rem(1) == 0.0)) {
ComicInfo.Number(it.toInt().toString()) ComicInfo.Number(it.toInt().toString())
} else { } else {
ComicInfo.Number(it.toString()) ComicInfo.Number(it.toString())

View file

@ -151,9 +151,9 @@ class SyncChaptersWithSource(
val reAdded = mutableListOf<Chapter>() val reAdded = mutableListOf<Chapter>()
val deletedChapterNumbers = TreeSet<Float>() val deletedChapterNumbers = TreeSet<Double>()
val deletedReadChapterNumbers = TreeSet<Float>() val deletedReadChapterNumbers = TreeSet<Double>()
val deletedBookmarkedChapterNumbers = TreeSet<Float>() val deletedBookmarkedChapterNumbers = TreeSet<Double>()
toDelete.forEach { chapter -> toDelete.forEach { chapter ->
if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber) if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber)

View file

@ -12,7 +12,7 @@ fun Chapter.toSChapter(): SChapter {
it.url = url it.url = url
it.name = name it.name = name
it.date_upload = dateUpload it.date_upload = dateUpload
it.chapter_number = chapterNumber it.chapter_number = chapterNumber.toFloat()
it.scanlator = scanlator it.scanlator = scanlator
} }
} }
@ -22,7 +22,7 @@ fun Chapter.copyFromSChapter(sChapter: SChapter): Chapter {
name = sChapter.name, name = sChapter.name,
url = sChapter.url, url = sChapter.url,
dateUpload = sChapter.date_upload, dateUpload = sChapter.date_upload,
chapterNumber = sChapter.chapter_number, chapterNumber = sChapter.chapter_number.toDouble(),
scanlator = sChapter.scanlator?.ifBlank { null }, scanlator = sChapter.scanlator?.ifBlank { null },
) )
} }
@ -48,6 +48,6 @@ fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
it.last_page_read = lastPageRead.toInt() it.last_page_read = lastPageRead.toInt()
it.date_fetch = dateFetch it.date_fetch = dateFetch
it.date_upload = dateUpload it.date_upload = dateUpload
it.chapter_number = chapterNumber it.chapter_number = chapterNumber.toFloat()
it.source_order = sourceOrder.toInt() it.source_order = sourceOrder.toInt()
} }

View file

@ -151,9 +151,9 @@ class SyncEpisodesWithSource(
val reAdded = mutableListOf<Episode>() val reAdded = mutableListOf<Episode>()
val deletedEpisodeNumbers = TreeSet<Float>() val deletedEpisodeNumbers = TreeSet<Double>()
val deletedSeenEpisodeNumbers = TreeSet<Float>() val deletedSeenEpisodeNumbers = TreeSet<Double>()
val deletedBookmarkedEpisodeNumbers = TreeSet<Float>() val deletedBookmarkedEpisodeNumbers = TreeSet<Double>()
toDelete.forEach { episode -> toDelete.forEach { episode ->
if (episode.seen) deletedSeenEpisodeNumbers.add(episode.episodeNumber) if (episode.seen) deletedSeenEpisodeNumbers.add(episode.episodeNumber)

View file

@ -12,7 +12,7 @@ fun Episode.toSEpisode(): SEpisode {
it.url = url it.url = url
it.name = name it.name = name
it.date_upload = dateUpload it.date_upload = dateUpload
it.episode_number = episodeNumber it.episode_number = episodeNumber.toFloat()
it.scanlator = scanlator it.scanlator = scanlator
} }
} }
@ -22,7 +22,7 @@ fun Episode.copyFromSEpisode(sEpisode: SEpisode): Episode {
name = sEpisode.name, name = sEpisode.name,
url = sEpisode.url, url = sEpisode.url,
dateUpload = sEpisode.date_upload, dateUpload = sEpisode.date_upload,
episodeNumber = sEpisode.episode_number, episodeNumber = sEpisode.episode_number.toDouble(),
scanlator = sEpisode.scanlator?.ifBlank { null }, scanlator = sEpisode.scanlator?.ifBlank { null },
) )
} }
@ -49,6 +49,6 @@ fun Episode.toDbEpisode(): DbEpisode = EpisodeImpl().also {
it.total_seconds = totalSeconds it.total_seconds = totalSeconds
it.date_fetch = dateFetch it.date_fetch = dateFetch
it.date_upload = dateUpload it.date_upload = dateUpload
it.episode_number = episodeNumber it.episode_number = episodeNumber.toFloat()
it.source_order = sourceOrder.toInt() it.source_order = sourceOrder.toInt()
} }

View file

@ -22,7 +22,7 @@ fun AnimeTrack.toDbTrack(): DbAnimeTrack = eu.kanade.tachiyomi.data.database.mod
it.last_episode_seen = lastEpisodeSeen.toFloat() it.last_episode_seen = lastEpisodeSeen.toFloat()
it.total_episodes = totalEpisodes.toInt() it.total_episodes = totalEpisodes.toInt()
it.status = status.toInt() it.status = status.toInt()
it.score = score it.score = score.toFloat()
it.tracking_url = remoteUrl it.tracking_url = remoteUrl
it.started_watching_date = startDate it.started_watching_date = startDate
it.finished_watching_date = finishDate it.finished_watching_date = finishDate
@ -40,7 +40,7 @@ fun DbAnimeTrack.toDomainTrack(idRequired: Boolean = true): AnimeTrack? {
lastEpisodeSeen = last_episode_seen.toDouble(), lastEpisodeSeen = last_episode_seen.toDouble(),
totalEpisodes = total_episodes.toLong(), totalEpisodes = total_episodes.toLong(),
status = status.toLong(), status = status.toLong(),
score = score, score = score.toDouble(),
remoteUrl = tracking_url, remoteUrl = tracking_url,
startDate = started_watching_date, startDate = started_watching_date,
finishDate = finished_watching_date, finishDate = finished_watching_date,

View file

@ -22,7 +22,7 @@ fun MangaTrack.toDbTrack(): DbMangaTrack = eu.kanade.tachiyomi.data.database.mod
it.last_chapter_read = lastChapterRead.toFloat() it.last_chapter_read = lastChapterRead.toFloat()
it.total_chapters = totalChapters.toInt() it.total_chapters = totalChapters.toInt()
it.status = status.toInt() it.status = status.toInt()
it.score = score it.score = score.toFloat()
it.tracking_url = remoteUrl it.tracking_url = remoteUrl
it.started_reading_date = startDate it.started_reading_date = startDate
it.finished_reading_date = finishDate it.finished_reading_date = finishDate
@ -40,7 +40,7 @@ fun DbMangaTrack.toDomainTrack(idRequired: Boolean = true): MangaTrack? {
lastChapterRead = last_chapter_read.toDouble(), lastChapterRead = last_chapter_read.toDouble(),
totalChapters = total_chapters.toLong(), totalChapters = total_chapters.toLong(),
status = status.toLong(), status = status.toLong(),
score = score, score = score.toDouble(),
remoteUrl = tracking_url, remoteUrl = tracking_url,
startDate = started_reading_date, startDate = started_reading_date,
finishDate = finished_reading_date, finishDate = finished_reading_date,

View file

@ -487,7 +487,7 @@ private fun AnimeScreenSmallImpl(
NextEpisodeAiringListItem( NextEpisodeAiringListItem(
title = stringResource( title = stringResource(
R.string.display_mode_episode, R.string.display_mode_episode,
formatEpisodeNumber(state.airingEpisodeNumber.toFloat()), formatEpisodeNumber(state.airingEpisodeNumber),
), ),
date = formatTime(state.airingTime, useDayFormat = true), date = formatTime(state.airingTime, useDayFormat = true),
) )
@ -747,7 +747,7 @@ fun AnimeScreenLargeImpl(
NextEpisodeAiringListItem( NextEpisodeAiringListItem(
title = stringResource( title = stringResource(
R.string.display_mode_episode, R.string.display_mode_episode,
formatEpisodeNumber(state.airingEpisodeNumber.toFloat()), formatEpisodeNumber(state.airingEpisodeNumber),
), ),
date = formatTime(state.airingTime, useDayFormat = true), date = formatTime(state.airingTime, useDayFormat = true),
) )

View file

@ -358,10 +358,10 @@ object SettingsLibraryScreen : SearchableSettings {
pluralStringResource(R.plurals.pref_update_release_following_days, followMangaRange, followMangaRange), pluralStringResource(R.plurals.pref_update_release_following_days, followMangaRange, followMangaRange),
).joinToString(), ).joinToString(),
onClick = { showFetchMangaRangesDialog = true }, onClick = { showFetchMangaRangesDialog = true },
).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateMangaRestriction && isDevFlavor }, ).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateMangaRestriction},
Preference.PreferenceItem.InfoPreference( Preference.PreferenceItem.InfoPreference(
title = stringResource(R.string.pref_update_release_grace_period_info), title = stringResource(R.string.pref_update_release_grace_period_info),
).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateMangaRestriction && isDevFlavor }, ).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateMangaRestriction},
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(R.string.pref_update_anime_release_grace_period), title = stringResource(R.string.pref_update_anime_release_grace_period),
subtitle = listOf( subtitle = listOf(
@ -369,10 +369,10 @@ object SettingsLibraryScreen : SearchableSettings {
pluralStringResource(R.plurals.pref_update_release_following_days, followAnimeRange, followAnimeRange), pluralStringResource(R.plurals.pref_update_release_following_days, followAnimeRange, followAnimeRange),
).joinToString(), ).joinToString(),
onClick = { showFetchAnimeRangesDialog = true }, onClick = { showFetchAnimeRangesDialog = true },
).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateAnimeRestriction && isDevFlavor }, ).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateAnimeRestriction},
Preference.PreferenceItem.InfoPreference( Preference.PreferenceItem.InfoPreference(
title = stringResource(R.string.pref_update_release_grace_period_info), title = stringResource(R.string.pref_update_release_grace_period_info),
).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateAnimeRestriction && isDevFlavor }, ).takeIf { ENTRY_OUTSIDE_RELEASE_PERIOD in libraryUpdateAnimeRestriction},
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = libraryPreferences.newShowUpdatesCount(), pref = libraryPreferences.newShowUpdatesCount(),

View file

@ -15,6 +15,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.text.HtmlCompat import androidx.core.text.HtmlCompat
@ -45,6 +46,7 @@ class OpenSourceLibraryLicenseScreen(
Text( Text(
text = name, text = name,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis,
) )
}, },
navigationIcon = { navigationIcon = {

View file

@ -28,9 +28,11 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
object BackupSchemaScreen : Screen() { class BackupSchemaScreen : Screen() {
const val title = "Backup file schema" companion object {
const val title = "Backup file schema"
}
@Composable @Composable
override fun Content() { override fun Content() {

View file

@ -18,7 +18,8 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import kotlinx.coroutines.guava.await import kotlinx.coroutines.guava.await
object DebugInfoScreen : Screen() { class DebugInfoScreen : Screen() {
@Composable @Composable
override fun Content() { override fun Content() {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
@ -29,11 +30,11 @@ object DebugInfoScreen : Screen() {
listOf( listOf(
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = WorkerInfoScreen.title, title = WorkerInfoScreen.title,
onClick = { navigator.push(WorkerInfoScreen) }, onClick = { navigator.push(WorkerInfoScreen()) },
), ),
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = BackupSchemaScreen.title, title = BackupSchemaScreen.title,
onClick = { navigator.push(BackupSchemaScreen) }, onClick = { navigator.push(BackupSchemaScreen()) },
), ),
getAppInfoGroup(), getAppInfoGroup(),
getDeviceInfoGroup(), getDeviceInfoGroup(),
@ -67,11 +68,15 @@ object DebugInfoScreen : Screen() {
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable
private fun getWebViewVersion(): String { private fun getWebViewVersion(): String {
val webView = WebView.getCurrentWebViewPackage() ?: return "how did you get here?" return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val pm = LocalContext.current.packageManager val webView = WebView.getCurrentWebViewPackage() ?: return "how did you get here?"
val label = webView.applicationInfo.loadLabel(pm) val pm = LocalContext.current.packageManager
val version = webView.versionName val label = webView.applicationInfo.loadLabel(pm)
return "$label $version" val version = webView.versionName
return "$label $version"
} else {
return "Unknown"
}
} }
@Composable @Composable

View file

@ -43,9 +43,11 @@ import kotlinx.coroutines.flow.stateIn
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.util.plus import tachiyomi.presentation.core.util.plus
object WorkerInfoScreen : Screen() { class WorkerInfoScreen : Screen() {
const val title = "Worker info" companion object {
const val title = "Worker info"
}
@Composable @Composable
override fun Content() { override fun Content() {

View file

@ -87,7 +87,7 @@ fun AnimeTrackInfoDialogHome(
}, },
onEpisodesClick = { onEpisodeClick(item) }, onEpisodesClick = { onEpisodeClick(item) },
score = item.service.animeService.displayScore(item.track.toDbTrack()) score = item.service.animeService.displayScore(item.track.toDbTrack())
.takeIf { supportsScoring && item.track.score != 0F }, .takeIf { supportsScoring && item.track.score != 0.0 },
onScoreClick = { onScoreClick(item) } onScoreClick = { onScoreClick(item) }
.takeIf { supportsScoring }, .takeIf { supportsScoring },
startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) } startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) }

View file

@ -98,7 +98,7 @@ fun MangaTrackInfoDialogHome(
}, },
onChaptersClick = { onChapterClick(item) }, onChaptersClick = { onChapterClick(item) },
score = item.service.mangaService.displayScore(item.track.toDbTrack()) score = item.service.mangaService.displayScore(item.track.toDbTrack())
.takeIf { supportsScoring && item.track.score != 0F }, .takeIf { supportsScoring && item.track.score != 0.0 },
onScoreClick = { onScoreClick(item) } onScoreClick = { onScoreClick(item) }
.takeIf { supportsScoring }, .takeIf { supportsScoring },
startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) } startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) }

View file

@ -8,10 +8,10 @@ private val formatter = DecimalFormat(
DecimalFormatSymbols().apply { decimalSeparator = '.' }, DecimalFormatSymbols().apply { decimalSeparator = '.' },
) )
fun formatChapterNumber(chapterNumber: Float): String { fun formatChapterNumber(chapterNumber: Double): String {
return formatter.format(chapterNumber) return formatter.format(chapterNumber)
} }
fun formatEpisodeNumber(episodeNumber: Float): String { fun formatEpisodeNumber(episodeNumber: Double): String {
return formatter.format(episodeNumber) return formatter.format(episodeNumber)
} }

View file

@ -5,16 +5,11 @@ import android.os.Build
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import app.cash.sqldelight.adapter.primitive.FloatColumnAdapter
import app.cash.sqldelight.driver.android.AndroidSqliteDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import data.Chapters
import data.History import data.History
import data.Manga_sync
import data.Mangas import data.Mangas
import dataanime.Anime_sync
import dataanime.Animehistory import dataanime.Animehistory
import dataanime.Animes import dataanime.Animes
import dataanime.Episodes
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.track.anime.store.DelayedAnimeTrackingStore import eu.kanade.domain.track.anime.store.DelayedAnimeTrackingStore
@ -55,13 +50,13 @@ import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.provider.AndroidBackupFolderProvider import tachiyomi.core.provider.AndroidBackupFolderProvider
import tachiyomi.core.provider.AndroidDownloadFolderProvider import tachiyomi.core.provider.AndroidDownloadFolderProvider
import tachiyomi.data.Database import tachiyomi.data.Database
import tachiyomi.data.dateAdapter import tachiyomi.data.DateColumnAdapter
import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.data.handlers.anime.AndroidAnimeDatabaseHandler import tachiyomi.data.handlers.anime.AndroidAnimeDatabaseHandler
import tachiyomi.data.handlers.anime.AnimeDatabaseHandler import tachiyomi.data.handlers.anime.AnimeDatabaseHandler
import tachiyomi.data.handlers.manga.AndroidMangaDatabaseHandler import tachiyomi.data.handlers.manga.AndroidMangaDatabaseHandler
import tachiyomi.data.handlers.manga.MangaDatabaseHandler import tachiyomi.data.handlers.manga.MangaDatabaseHandler
import tachiyomi.data.listOfStringsAdapter
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences
@ -136,18 +131,12 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { addSingletonFactory {
Database( Database(
driver = sqlDriverManga, driver = sqlDriverManga,
chaptersAdapter = Chapters.Adapter(
chapter_numberAdapter = FloatColumnAdapter,
),
historyAdapter = History.Adapter( historyAdapter = History.Adapter(
last_readAdapter = dateAdapter, last_readAdapter = DateColumnAdapter,
),
manga_syncAdapter = Manga_sync.Adapter(
scoreAdapter = FloatColumnAdapter,
), ),
mangasAdapter = Mangas.Adapter( mangasAdapter = Mangas.Adapter(
genreAdapter = listOfStringsAdapter, genreAdapter = StringListColumnAdapter,
update_strategyAdapter = updateStrategyAdapter, update_strategyAdapter = UpdateStrategyColumnAdapter,
), ),
) )
} }
@ -155,18 +144,12 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { addSingletonFactory {
AnimeDatabase( AnimeDatabase(
driver = sqlDriverAnime, driver = sqlDriverAnime,
episodesAdapter = Episodes.Adapter(
episode_numberAdapter = FloatColumnAdapter,
),
animehistoryAdapter = Animehistory.Adapter( animehistoryAdapter = Animehistory.Adapter(
last_seenAdapter = dateAdapter, last_seenAdapter = DateColumnAdapter,
),
anime_syncAdapter = Anime_sync.Adapter(
scoreAdapter = FloatColumnAdapter,
), ),
animesAdapter = Animes.Adapter( animesAdapter = Animes.Adapter(
genreAdapter = listOfStringsAdapter, genreAdapter = StringListColumnAdapter,
update_strategyAdapter = updateStrategyAdapter, update_strategyAdapter = UpdateStrategyColumnAdapter,
), ),
) )
} }

View file

@ -65,9 +65,9 @@ import okio.gzip
import okio.sink import okio.sink
import tachiyomi.core.util.lang.toLong import tachiyomi.core.util.lang.toLong
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.data.handlers.anime.AnimeDatabaseHandler import tachiyomi.data.handlers.anime.AnimeDatabaseHandler
import tachiyomi.data.handlers.manga.MangaDatabaseHandler import tachiyomi.data.handlers.manga.MangaDatabaseHandler
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.category.anime.interactor.GetAnimeCategories import tachiyomi.domain.category.anime.interactor.GetAnimeCategories
import tachiyomi.domain.category.manga.interactor.GetMangaCategories import tachiyomi.domain.category.manga.interactor.GetMangaCategories
@ -778,7 +778,7 @@ class BackupManager(
track.last_chapter_read, track.last_chapter_read,
track.total_chapters, track.total_chapters,
track.status, track.status,
track.score.toDouble(), track.score,
track.remote_url, track.remote_url,
track.start_date, track.start_date,
track.finish_date, track.finish_date,
@ -861,7 +861,7 @@ class BackupManager(
track.last_episode_seen, track.last_episode_seen,
track.total_episodes, track.total_episodes,
track.status, track.status,
track.score.toDouble(), track.score,
track.remote_url, track.remote_url,
track.start_date, track.start_date,
track.finish_date, track.finish_date,
@ -1050,7 +1050,7 @@ class BackupManager(
coverLastModified = manga.coverLastModified, coverLastModified = manga.coverLastModified,
dateAdded = manga.dateAdded, dateAdded = manga.dateAdded,
mangaId = manga.id!!, mangaId = manga.id!!,
updateStrategy = manga.updateStrategy.let(updateStrategyAdapter::encode), updateStrategy = manga.updateStrategy.let(UpdateStrategyColumnAdapter::encode),
) )
} }
return manga.id return manga.id
@ -1078,7 +1078,7 @@ class BackupManager(
coverLastModified = anime.coverLastModified, coverLastModified = anime.coverLastModified,
dateAdded = anime.dateAdded, dateAdded = anime.dateAdded,
animeId = anime.id!!, animeId = anime.id!!,
updateStrategy = anime.updateStrategy.let(updateStrategyAdapter::encode), updateStrategy = anime.updateStrategy.let(UpdateStrategyColumnAdapter::encode),
) )
} }
return anime.id return anime.id

View file

@ -43,7 +43,7 @@ data class BackupAnimeTracking(
title = this@BackupAnimeTracking.title, title = this@BackupAnimeTracking.title,
lastEpisodeSeen = this@BackupAnimeTracking.lastEpisodeSeen.toDouble(), lastEpisodeSeen = this@BackupAnimeTracking.lastEpisodeSeen.toDouble(),
totalEpisodes = this@BackupAnimeTracking.totalEpisodes.toLong(), totalEpisodes = this@BackupAnimeTracking.totalEpisodes.toLong(),
score = this@BackupAnimeTracking.score, score = this@BackupAnimeTracking.score.toDouble(),
status = this@BackupAnimeTracking.status.toLong(), status = this@BackupAnimeTracking.status.toLong(),
startDate = this@BackupAnimeTracking.startedWatchingDate, startDate = this@BackupAnimeTracking.startedWatchingDate,
finishDate = this@BackupAnimeTracking.finishedWatchingDate, finishDate = this@BackupAnimeTracking.finishedWatchingDate,
@ -62,7 +62,7 @@ data class BackupAnimeTracking(
// convert to float for 1.x // convert to float for 1.x
lastEpisodeSeen = track.lastEpisodeSeen.toFloat(), lastEpisodeSeen = track.lastEpisodeSeen.toFloat(),
totalEpisodes = track.totalEpisodes.toInt(), totalEpisodes = track.totalEpisodes.toInt(),
score = track.score, score = track.score.toFloat(),
status = track.status.toInt(), status = track.status.toInt(),
startedWatchingDate = track.startDate, startedWatchingDate = track.startDate,
finishedWatchingDate = track.finishDate, finishedWatchingDate = track.finishDate,
@ -72,7 +72,7 @@ data class BackupAnimeTracking(
} }
} }
val backupAnimeTrackMapper = { _id: Long, anime_id: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastEpisodeSeen: Double, totalEpisodes: Long, status: Long, score: Float, remoteUrl: String, startDate: Long, finishDate: Long -> val backupAnimeTrackMapper = { _id: Long, anime_id: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastEpisodeSeen: Double, totalEpisodes: Long, status: Long, score: Double, remoteUrl: String, startDate: Long, finishDate: Long ->
BackupAnimeTracking( BackupAnimeTracking(
syncId = syncId.toInt(), syncId = syncId.toInt(),
mediaId = mediaId, mediaId = mediaId,
@ -81,7 +81,7 @@ val backupAnimeTrackMapper = { _id: Long, anime_id: Long, syncId: Long, mediaId:
title = title, title = title,
lastEpisodeSeen = lastEpisodeSeen.toFloat(), lastEpisodeSeen = lastEpisodeSeen.toFloat(),
totalEpisodes = totalEpisodes.toInt(), totalEpisodes = totalEpisodes.toInt(),
score = score, score = score.toFloat(),
status = status.toInt(), status = status.toInt(),
startedWatchingDate = startDate, startedWatchingDate = startDate,
finishedWatchingDate = finishDate, finishedWatchingDate = finishDate,

View file

@ -26,7 +26,7 @@ data class BackupChapter(
return Chapter.create().copy( return Chapter.create().copy(
url = this@BackupChapter.url, url = this@BackupChapter.url,
name = this@BackupChapter.name, name = this@BackupChapter.name,
chapterNumber = this@BackupChapter.chapterNumber, chapterNumber = this@BackupChapter.chapterNumber.toDouble(),
scanlator = this@BackupChapter.scanlator, scanlator = this@BackupChapter.scanlator,
read = this@BackupChapter.read, read = this@BackupChapter.read,
bookmark = this@BackupChapter.bookmark, bookmark = this@BackupChapter.bookmark,
@ -39,11 +39,11 @@ data class BackupChapter(
} }
} }
val backupChapterMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, read: Boolean, bookmark: Boolean, lastPageRead: Long, chapterNumber: Float, source_order: Long, dateFetch: Long, dateUpload: Long, lastModifiedAt: Long -> val backupChapterMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, read: Boolean, bookmark: Boolean, lastPageRead: Long, chapterNumber: Double, source_order: Long, dateFetch: Long, dateUpload: Long, lastModifiedAt: Long ->
BackupChapter( BackupChapter(
url = url, url = url,
name = name, name = name,
chapterNumber = chapterNumber, chapterNumber = chapterNumber.toFloat(),
scanlator = scanlator, scanlator = scanlator,
read = read, read = read,
bookmark = bookmark, bookmark = bookmark,

View file

@ -27,7 +27,7 @@ data class BackupEpisode(
return Episode.create().copy( return Episode.create().copy(
url = this@BackupEpisode.url, url = this@BackupEpisode.url,
name = this@BackupEpisode.name, name = this@BackupEpisode.name,
episodeNumber = this@BackupEpisode.episodeNumber, episodeNumber = this@BackupEpisode.episodeNumber.toDouble(),
scanlator = this@BackupEpisode.scanlator, scanlator = this@BackupEpisode.scanlator,
seen = this@BackupEpisode.seen, seen = this@BackupEpisode.seen,
bookmark = this@BackupEpisode.bookmark, bookmark = this@BackupEpisode.bookmark,
@ -41,11 +41,11 @@ data class BackupEpisode(
} }
} }
val backupEpisodeMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, seen: Boolean, bookmark: Boolean, lastSecondSeen: Long, totalSeconds: Long, episodeNumber: Float, source_order: Long, dateFetch: Long, dateUpload: Long, lastModifiedAt: Long -> val backupEpisodeMapper = { _: Long, _: Long, url: String, name: String, scanlator: String?, seen: Boolean, bookmark: Boolean, lastSecondSeen: Long, totalSeconds: Long, episodeNumber: Double, source_order: Long, dateFetch: Long, dateUpload: Long, lastModifiedAt: Long ->
BackupEpisode( BackupEpisode(
url = url, url = url,
name = name, name = name,
episodeNumber = episodeNumber, episodeNumber = episodeNumber.toFloat(),
scanlator = scanlator, scanlator = scanlator,
seen = seen, seen = seen,
bookmark = bookmark, bookmark = bookmark,

View file

@ -44,7 +44,7 @@ data class BackupTracking(
title = this@BackupTracking.title, title = this@BackupTracking.title,
lastChapterRead = this@BackupTracking.lastChapterRead.toDouble(), lastChapterRead = this@BackupTracking.lastChapterRead.toDouble(),
totalChapters = this@BackupTracking.totalChapters.toLong(), totalChapters = this@BackupTracking.totalChapters.toLong(),
score = this@BackupTracking.score, score = this@BackupTracking.score.toDouble(),
status = this@BackupTracking.status.toLong(), status = this@BackupTracking.status.toLong(),
startDate = this@BackupTracking.startedReadingDate, startDate = this@BackupTracking.startedReadingDate,
finishDate = this@BackupTracking.finishedReadingDate, finishDate = this@BackupTracking.finishedReadingDate,
@ -54,7 +54,7 @@ data class BackupTracking(
} }
val backupTrackMapper = { val backupTrackMapper = {
_: Long, _: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastChapterRead: Double, totalChapters: Long, status: Long, score: Float, remoteUrl: String, startDate: Long, finishDate: Long -> _: Long, _: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastChapterRead: Double, totalChapters: Long, status: Long, score: Double, remoteUrl: String, startDate: Long, finishDate: Long ->
BackupTracking( BackupTracking(
syncId = syncId.toInt(), syncId = syncId.toInt(),
mediaId = mediaId, mediaId = mediaId,
@ -63,7 +63,7 @@ val backupTrackMapper = {
title = title, title = title,
lastChapterRead = lastChapterRead.toFloat(), lastChapterRead = lastChapterRead.toFloat(),
totalChapters = totalChapters.toInt(), totalChapters = totalChapters.toInt(),
score = score, score = score.toFloat(),
status = status.toInt(), status = status.toInt(),
startedReadingDate = startDate, startedReadingDate = startDate,
finishedReadingDate = finishDate, finishedReadingDate = finishDate,

View file

@ -39,7 +39,7 @@ fun Episode.toDomainEpisode(): DomainEpisode? {
url = url, url = url,
name = name, name = name,
dateUpload = date_upload, dateUpload = date_upload,
episodeNumber = episode_number, episodeNumber = episode_number.toDouble(),
scanlator = scanlator, scanlator = scanlator,
lastModifiedAt = last_modified, lastModifiedAt = last_modified,
) )

View file

@ -36,7 +36,7 @@ fun Chapter.toDomainChapter(): DomainChapter? {
url = url, url = url,
name = name, name = name,
dateUpload = date_upload, dateUpload = date_upload,
chapterNumber = chapter_number, chapterNumber = chapter_number.toDouble(),
scanlator = scanlator, scanlator = scanlator,
lastModifiedAt = last_modified, lastModifiedAt = last_modified,
) )

View file

@ -39,7 +39,7 @@ interface AnimeTrackService {
fun getRewatchingStatus(): Int fun getRewatchingStatus(): Int
// TODO: Store all scores as 10 point in the future maybe? // TODO: Store all scores as 10 point in the future maybe?
fun get10PointScore(track: DomainAnimeTrack): Float { fun get10PointScore(track: DomainAnimeTrack): Double {
return track.score return track.score
} }

View file

@ -39,7 +39,7 @@ interface MangaTrackService {
fun getRereadingStatus(): Int fun getRereadingStatus(): Int
// TODO: Store all scores as 10 point in the future maybe? // TODO: Store all scores as 10 point in the future maybe?
fun get10PointScore(track: DomainTrack): Float { fun get10PointScore(track: DomainTrack): Double {
return track.score return track.score
} }

View file

@ -114,14 +114,14 @@ class Anilist(id: Long) : TrackService(id), MangaTrackService, AnimeTrackService
} }
} }
override fun get10PointScore(track: DomainTrack): Float { override fun get10PointScore(track: DomainTrack): Double {
// Score is stored in 100 point format // Score is stored in 100 point format
return track.score / 10f return track.score / 10.0
} }
override fun get10PointScore(track: DomainAnimeTrack): Float { override fun get10PointScore(track: DomainAnimeTrack): Double {
// Score is stored in 100 point format // Score is stored in 100 point format
return track.score / 10f return track.score / 10.0
} }
override fun indexToScore(index: Int): Float { override fun indexToScore(index: Int): Float {

View file

@ -238,10 +238,10 @@ class AnimeExtensionManager(
/** /**
* Uninstalls the anime extension that matches the given package name. * Uninstalls the anime extension that matches the given package name.
* *
* @param pkgName The package name of the application to uninstall. * @param extension The extension to uninstall.
*/ */
fun uninstallExtension(pkgName: String) { fun uninstallExtension(extension: AnimeExtension) {
installer.uninstallApk(pkgName) installer.uninstallApk(extension.pkgName)
} }
/** /**
@ -260,18 +260,13 @@ class AnimeExtensionManager(
val nowTrustedAnimeExtensions = _untrustedAnimeExtensionsFlow.value.filter { it.signatureHash == signature } val nowTrustedAnimeExtensions = _untrustedAnimeExtensionsFlow.value.filter { it.signatureHash == signature }
_untrustedAnimeExtensionsFlow.value -= nowTrustedAnimeExtensions _untrustedAnimeExtensionsFlow.value -= nowTrustedAnimeExtensions
val ctx = context
launchNow { launchNow {
nowTrustedAnimeExtensions nowTrustedAnimeExtensions
.map { animeextension -> .map { animeextension ->
async { AnimeExtensionLoader.loadExtensionFromPkgName(ctx, animeextension.pkgName) } async { AnimeExtensionLoader.loadExtensionFromPkgName(context, animeextension.pkgName) }.await()
}
.map { it.await() }
.forEach { result ->
if (result is AnimeLoadResult.Success) {
registerNewExtension(result.extension)
}
} }
.filterIsInstance<AnimeLoadResult.Success>()
.forEach { registerNewExtension(it.extension) }
} }
} }

View file

@ -238,10 +238,10 @@ class MangaExtensionManager(
/** /**
* Uninstalls the extension that matches the given package name. * Uninstalls the extension that matches the given package name.
* *
* @param pkgName The package name of the application to uninstall. * @param extension The extension to uninstall.
*/ */
fun uninstallExtension(pkgName: String) { fun uninstallExtension(extension: MangaExtension) {
installer.uninstallApk(pkgName) installer.uninstallApk(extension.pkgName)
} }
/** /**
@ -260,18 +260,13 @@ class MangaExtensionManager(
val nowTrustedExtensions = _untrustedExtensionsFlow.value.filter { it.signatureHash == signature } val nowTrustedExtensions = _untrustedExtensionsFlow.value.filter { it.signatureHash == signature }
_untrustedExtensionsFlow.value -= nowTrustedExtensions _untrustedExtensionsFlow.value -= nowTrustedExtensions
val ctx = context
launchNow { launchNow {
nowTrustedExtensions nowTrustedExtensions
.map { extension -> .map { extension ->
async { MangaExtensionLoader.loadMangaExtensionFromPkgName(ctx, extension.pkgName) } async { MangaExtensionLoader.loadMangaExtensionFromPkgName(context, extension.pkgName) }.await()
}
.map { it.await() }
.forEach { result ->
if (result is MangaLoadResult.Success) {
registerNewExtension(result.extension)
}
} }
.filterIsInstance<MangaLoadResult.Success>()
.forEach { registerNewExtension(it.extension) }
} }
} }

View file

@ -7,6 +7,6 @@ fun SEpisode.copyFrom(other: Episodes) {
name = other.name name = other.name
url = other.url url = other.url
date_upload = other.date_upload date_upload = other.date_upload
episode_number = other.episode_number episode_number = other.episode_number.toFloat()
scanlator = other.scanlator scanlator = other.scanlator
} }

View file

@ -7,6 +7,6 @@ fun SChapter.copyFrom(other: Chapters) {
name = other.name name = other.name
url = other.url url = other.url
date_upload = other.date_upload date_upload = other.date_upload
chapter_number = other.chapter_number chapter_number = other.chapter_number.toFloat()
scanlator = other.scanlator scanlator = other.scanlator
} }

View file

@ -171,8 +171,8 @@ class AnimeExtensionsScreenModel(
.onCompletion { removeDownloadState(extension) } .onCompletion { removeDownloadState(extension) }
.collect() .collect()
fun uninstallExtension(pkgName: String) { fun uninstallExtension(extension: AnimeExtension) {
extensionManager.uninstallExtension(pkgName) extensionManager.uninstallExtension(extension)
} }
fun findAvailableExtensions() { fun findAvailableExtensions() {

View file

@ -41,7 +41,7 @@ fun animeExtensionsTab(
onLongClickItem = { extension -> onLongClickItem = { extension ->
when (extension) { when (extension) {
is AnimeExtension.Available -> extensionsScreenModel.installExtension(extension) is AnimeExtension.Available -> extensionsScreenModel.installExtension(extension)
else -> extensionsScreenModel.uninstallExtension(extension.pkgName) else -> extensionsScreenModel.uninstallExtension(extension)
} }
}, },
onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension, onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension,
@ -49,7 +49,7 @@ fun animeExtensionsTab(
onInstallExtension = extensionsScreenModel::installExtension, onInstallExtension = extensionsScreenModel::installExtension,
onOpenExtension = { navigator.push(AnimeExtensionDetailsScreen(it.pkgName)) }, onOpenExtension = { navigator.push(AnimeExtensionDetailsScreen(it.pkgName)) },
onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) }, onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) },
onUninstallExtension = { extensionsScreenModel.uninstallExtension(it.pkgName) }, onUninstallExtension = { extensionsScreenModel.uninstallExtension(it) },
onUpdateExtension = extensionsScreenModel::updateExtension, onUpdateExtension = extensionsScreenModel::updateExtension,
onRefresh = extensionsScreenModel::findAvailableExtensions, onRefresh = extensionsScreenModel::findAvailableExtensions,
) )

View file

@ -132,7 +132,7 @@ class AnimeExtensionDetailsScreenModel(
fun uninstallExtension() { fun uninstallExtension() {
val extension = state.value.extension ?: return val extension = state.value.extension ?: return
extensionManager.uninstallExtension(extension.pkgName) extensionManager.uninstallExtension(extension)
} }
fun toggleSource(sourceId: Long) { fun toggleSource(sourceId: Long) {

View file

@ -172,8 +172,8 @@ class MangaExtensionsScreenModel(
.onCompletion { removeDownloadState(extension) } .onCompletion { removeDownloadState(extension) }
.collect() .collect()
fun uninstallExtension(pkgName: String) { fun uninstallExtension(extension: MangaExtension) {
extensionManager.uninstallExtension(pkgName) extensionManager.uninstallExtension(extension)
} }
fun findAvailableExtensions() { fun findAvailableExtensions() {

View file

@ -41,7 +41,7 @@ fun mangaExtensionsTab(
onLongClickItem = { extension -> onLongClickItem = { extension ->
when (extension) { when (extension) {
is MangaExtension.Available -> extensionsScreenModel.installExtension(extension) is MangaExtension.Available -> extensionsScreenModel.installExtension(extension)
else -> extensionsScreenModel.uninstallExtension(extension.pkgName) else -> extensionsScreenModel.uninstallExtension(extension)
} }
}, },
onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension, onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension,
@ -49,7 +49,7 @@ fun mangaExtensionsTab(
onInstallExtension = extensionsScreenModel::installExtension, onInstallExtension = extensionsScreenModel::installExtension,
onOpenExtension = { navigator.push(MangaExtensionDetailsScreen(it.pkgName)) }, onOpenExtension = { navigator.push(MangaExtensionDetailsScreen(it.pkgName)) },
onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) }, onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) },
onUninstallExtension = { extensionsScreenModel.uninstallExtension(it.pkgName) }, onUninstallExtension = { extensionsScreenModel.uninstallExtension(it) },
onUpdateExtension = extensionsScreenModel::updateExtension, onUpdateExtension = extensionsScreenModel::updateExtension,
onRefresh = extensionsScreenModel::findAvailableExtensions, onRefresh = extensionsScreenModel::findAvailableExtensions,
) )

View file

@ -132,7 +132,7 @@ class MangaExtensionDetailsScreenModel(
fun uninstallExtension() { fun uninstallExtension() {
val extension = state.value.extension ?: return val extension = state.value.extension ?: return
extensionManager.uninstallExtension(extension.pkgName) extensionManager.uninstallExtension(extension)
} }
fun toggleSource(sourceId: Long) { fun toggleSource(sourceId: Long) {

View file

@ -83,7 +83,7 @@ fun EpisodeListDialog(
val title = if (displayMode == Anime.EPISODE_DISPLAY_NUMBER) { val title = if (displayMode == Anime.EPISODE_DISPLAY_NUMBER) {
stringResource( stringResource(
R.string.display_mode_episode, R.string.display_mode_episode,
formatEpisodeNumber(episode.episode_number), formatEpisodeNumber(episode.episode_number.toDouble()),
) )
} else { } else {
episode.name episode.name

View file

@ -153,15 +153,13 @@ class AnimeStatsScreenModel(
private fun getTrackMeanScore(scoredAnimeTrackMap: Map<Long, List<AnimeTrack>>): Double { private fun getTrackMeanScore(scoredAnimeTrackMap: Map<Long, List<AnimeTrack>>): Double {
return scoredAnimeTrackMap return scoredAnimeTrackMap
.map { (_, tracks) -> .map { (_, tracks) ->
tracks.map { tracks.map(::get10PointScore).average()
get10PointScore(it)
}.average()
} }
.fastFilter { !it.isNaN() } .fastFilter { !it.isNaN() }
.average() .average()
} }
private fun get10PointScore(track: AnimeTrack): Float { private fun get10PointScore(track: AnimeTrack): Double {
val service = trackManager.getService(track.syncId)!! val service = trackManager.getService(track.syncId)!!
return service.animeService.get10PointScore(track) return service.animeService.get10PointScore(track)
} }

View file

@ -138,15 +138,13 @@ class MangaStatsScreenModel(
private fun getTrackMeanScore(scoredMangaTrackMap: Map<Long, List<MangaTrack>>): Double { private fun getTrackMeanScore(scoredMangaTrackMap: Map<Long, List<MangaTrack>>): Double {
return scoredMangaTrackMap return scoredMangaTrackMap
.map { (_, tracks) -> .map { (_, tracks) ->
tracks.map { tracks.map(::get10PointScore).average()
get10PointScore(it)
}.average()
} }
.fastFilter { !it.isNaN() } .fastFilter { !it.isNaN() }
.average() .average()
} }
private fun get10PointScore(track: MangaTrack): Float { private fun get10PointScore(track: MangaTrack): Double {
val service = trackManager.getService(track.syncId)!! val service = trackManager.getService(track.syncId)!!
return service.mangaService.get10PointScore(track) return service.mangaService.get10PointScore(track)
} }

View file

@ -4,23 +4,23 @@ import app.cash.sqldelight.ColumnAdapter
import eu.kanade.tachiyomi.source.model.UpdateStrategy import eu.kanade.tachiyomi.source.model.UpdateStrategy
import java.util.Date import java.util.Date
val dateAdapter = object : ColumnAdapter<Date, Long> { object DateColumnAdapter : ColumnAdapter<Date, Long> {
override fun decode(databaseValue: Long): Date = Date(databaseValue) override fun decode(databaseValue: Long): Date = Date(databaseValue)
override fun encode(value: Date): Long = value.time override fun encode(value: Date): Long = value.time
} }
private const val listOfStringsSeparator = ", " private const val LIST_OF_STRINGS_SEPARATOR = ", "
val listOfStringsAdapter = object : ColumnAdapter<List<String>, String> { object StringListColumnAdapter : ColumnAdapter<List<String>, String> {
override fun decode(databaseValue: String) = override fun decode(databaseValue: String) =
if (databaseValue.isEmpty()) { if (databaseValue.isEmpty()) {
emptyList() emptyList()
} else { } else {
databaseValue.split(listOfStringsSeparator) databaseValue.split(LIST_OF_STRINGS_SEPARATOR)
} }
override fun encode(value: List<String>) = value.joinToString(separator = listOfStringsSeparator) override fun encode(value: List<String>) = value.joinToString(separator = LIST_OF_STRINGS_SEPARATOR)
} }
val updateStrategyAdapter = object : ColumnAdapter<UpdateStrategy, Long> { object UpdateStrategyColumnAdapter : ColumnAdapter<UpdateStrategy, Long> {
override fun decode(databaseValue: Long): UpdateStrategy = override fun decode(databaseValue: Long): UpdateStrategy =
UpdateStrategy.entries.getOrElse(databaseValue.toInt()) { UpdateStrategy.ALWAYS_UPDATE } UpdateStrategy.entries.getOrElse(databaseValue.toInt()) { UpdateStrategy.ALWAYS_UPDATE }

View file

@ -4,9 +4,9 @@ import kotlinx.coroutines.flow.Flow
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.toLong import tachiyomi.core.util.lang.toLong
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.data.handlers.anime.AnimeDatabaseHandler import tachiyomi.data.handlers.anime.AnimeDatabaseHandler
import tachiyomi.data.listOfStringsAdapter
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.domain.entries.anime.model.Anime import tachiyomi.domain.entries.anime.model.Anime
import tachiyomi.domain.entries.anime.model.AnimeUpdate import tachiyomi.domain.entries.anime.model.AnimeUpdate
import tachiyomi.domain.entries.anime.repository.AnimeRepository import tachiyomi.domain.entries.anime.repository.AnimeRepository
@ -129,7 +129,7 @@ class AnimeRepositoryImpl(
artist = value.artist, artist = value.artist,
author = value.author, author = value.author,
description = value.description, description = value.description,
genre = value.genre?.let(listOfStringsAdapter::encode), genre = value.genre?.let(StringListColumnAdapter::encode),
title = value.title, title = value.title,
status = value.status, status = value.status,
thumbnailUrl = value.thumbnailUrl, thumbnailUrl = value.thumbnailUrl,
@ -143,7 +143,7 @@ class AnimeRepositoryImpl(
coverLastModified = value.coverLastModified, coverLastModified = value.coverLastModified,
dateAdded = value.dateAdded, dateAdded = value.dateAdded,
animeId = value.id, animeId = value.id,
updateStrategy = value.updateStrategy?.let(updateStrategyAdapter::encode), updateStrategy = value.updateStrategy?.let(UpdateStrategyColumnAdapter::encode),
) )
} }
} }

View file

@ -4,9 +4,9 @@ import kotlinx.coroutines.flow.Flow
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.toLong import tachiyomi.core.util.lang.toLong
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.data.handlers.manga.MangaDatabaseHandler import tachiyomi.data.handlers.manga.MangaDatabaseHandler
import tachiyomi.data.listOfStringsAdapter
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.domain.entries.manga.model.Manga import tachiyomi.domain.entries.manga.model.Manga
import tachiyomi.domain.entries.manga.model.MangaUpdate import tachiyomi.domain.entries.manga.model.MangaUpdate
import tachiyomi.domain.entries.manga.repository.MangaRepository import tachiyomi.domain.entries.manga.repository.MangaRepository
@ -129,7 +129,7 @@ class MangaRepositoryImpl(
artist = value.artist, artist = value.artist,
author = value.author, author = value.author,
description = value.description, description = value.description,
genre = value.genre?.let(listOfStringsAdapter::encode), genre = value.genre?.let(StringListColumnAdapter::encode),
title = value.title, title = value.title,
status = value.status, status = value.status,
thumbnailUrl = value.thumbnailUrl, thumbnailUrl = value.thumbnailUrl,
@ -143,7 +143,7 @@ class MangaRepositoryImpl(
coverLastModified = value.coverLastModified, coverLastModified = value.coverLastModified,
dateAdded = value.dateAdded, dateAdded = value.dateAdded,
mangaId = value.id, mangaId = value.id,
updateStrategy = value.updateStrategy?.let(updateStrategyAdapter::encode), updateStrategy = value.updateStrategy?.let(UpdateStrategyColumnAdapter::encode),
) )
} }
} }

View file

@ -13,7 +13,7 @@ val animeHistoryMapper: (Long, Long, Date?) -> AnimeHistory = { id, episodeId, s
) )
} }
val animeHistoryWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Float, Date?) -> AnimeHistoryWithRelations = { val animeHistoryWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Double, Date?) -> AnimeHistoryWithRelations = {
historyId, animeId, episodeId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, episodeNumber, seenAt -> historyId, animeId, episodeId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, episodeNumber, seenAt ->
AnimeHistoryWithRelations( AnimeHistoryWithRelations(
id = historyId, id = historyId,

View file

@ -14,7 +14,7 @@ val mangaHistoryMapper: (Long, Long, Date?, Long) -> MangaHistory = { id, chapte
) )
} }
val mangaHistoryWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Float, Date?, Long) -> MangaHistoryWithRelations = { val mangaHistoryWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Double, Date?, Long) -> MangaHistoryWithRelations = {
historyId, mangaId, chapterId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, chapterNumber, readAt, readDuration -> historyId, mangaId, chapterId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, chapterNumber, readAt, readDuration ->
MangaHistoryWithRelations( MangaHistoryWithRelations(
id = historyId, id = historyId,

View file

@ -2,7 +2,7 @@ package tachiyomi.data.items.chapter
import tachiyomi.domain.items.chapter.model.Chapter import tachiyomi.domain.items.chapter.model.Chapter
val chapterMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Float, Long, Long, Long, Long) -> Chapter = val chapterMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Double, Long, Long, Long, Long) -> Chapter =
{ id, mangaId, url, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt -> { id, mangaId, url, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt ->
Chapter( Chapter(
id = id, id = id,

View file

@ -2,7 +2,7 @@ package tachiyomi.data.items.episode
import tachiyomi.domain.items.episode.model.Episode import tachiyomi.domain.items.episode.model.Episode
val episodeMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Long, Float, Long, Long, Long, Long) -> Episode = val episodeMapper: (Long, Long, String, String, String?, Boolean, Boolean, Long, Long, Double, Long, Long, Long, Long) -> Episode =
{ id, animeId, url, name, scanlator, seen, bookmark, lastSecondSeen, totalSeconds, episodeNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt -> { id, animeId, url, name, scanlator, seen, bookmark, lastSecondSeen, totalSeconds, episodeNumber, sourceOrder, dateFetch, dateUpload, lastModifiedAt ->
Episode( Episode(
id = id, id = id,

View file

@ -2,7 +2,7 @@ package tachiyomi.data.track.anime
import tachiyomi.domain.track.anime.model.AnimeTrack import tachiyomi.domain.track.anime.model.AnimeTrack
val animeTrackMapper: (Long, Long, Long, Long, Long?, String, Double, Long, Long, Float, String, Long, Long) -> AnimeTrack = val animeTrackMapper: (Long, Long, Long, Long, Long?, String, Double, Long, Long, Double, String, Long, Long) -> AnimeTrack =
{ id, animeId, syncId, remoteId, libraryId, title, lastEpisodeSeen, totalEpisodes, status, score, remoteUrl, startDate, finishDate -> { id, animeId, syncId, remoteId, libraryId, title, lastEpisodeSeen, totalEpisodes, status, score, remoteUrl, startDate, finishDate ->
AnimeTrack( AnimeTrack(
id = id, id = id,

View file

@ -2,7 +2,7 @@ package tachiyomi.data.track.manga
import tachiyomi.domain.track.manga.model.MangaTrack import tachiyomi.domain.track.manga.model.MangaTrack
val mangaTrackMapper: (Long, Long, Long, Long, Long?, String, Double, Long, Long, Float, String, Long, Long) -> MangaTrack = val mangaTrackMapper: (Long, Long, Long, Long, Long?, String, Double, Long, Long, Double, String, Long, Long) -> MangaTrack =
{ id, mangaId, syncId, remoteId, libraryId, title, lastChapterRead, totalChapters, status, score, remoteUrl, startDate, finishDate -> { id, mangaId, syncId, remoteId, libraryId, title, lastChapterRead, totalChapters, status, score, remoteUrl, startDate, finishDate ->
MangaTrack( MangaTrack(
id = id, id = id,

View file

@ -1,5 +1,4 @@
import kotlin.Boolean; import kotlin.Boolean;
import kotlin.Float;
CREATE TABLE chapters( CREATE TABLE chapters(
_id INTEGER NOT NULL PRIMARY KEY, _id INTEGER NOT NULL PRIMARY KEY,
@ -10,7 +9,7 @@ CREATE TABLE chapters(
read INTEGER AS Boolean NOT NULL, read INTEGER AS Boolean NOT NULL,
bookmark INTEGER AS Boolean NOT NULL, bookmark INTEGER AS Boolean NOT NULL,
last_page_read INTEGER NOT NULL, last_page_read INTEGER NOT NULL,
chapter_number REAL AS Float NOT NULL, chapter_number REAL NOT NULL,
source_order INTEGER NOT NULL, source_order INTEGER NOT NULL,
date_fetch INTEGER NOT NULL, date_fetch INTEGER NOT NULL,
date_upload INTEGER NOT NULL, date_upload INTEGER NOT NULL,

View file

@ -1,5 +1,3 @@
import kotlin.Float;
CREATE TABLE manga_sync( CREATE TABLE manga_sync(
_id INTEGER NOT NULL PRIMARY KEY, _id INTEGER NOT NULL PRIMARY KEY,
manga_id INTEGER NOT NULL, manga_id INTEGER NOT NULL,
@ -10,7 +8,7 @@ CREATE TABLE manga_sync(
last_chapter_read REAL NOT NULL, last_chapter_read REAL NOT NULL,
total_chapters INTEGER NOT NULL, total_chapters INTEGER NOT NULL,
status INTEGER NOT NULL, status INTEGER NOT NULL,
score REAL AS Float NOT NULL, score REAL NOT NULL,
remote_url TEXT NOT NULL, remote_url TEXT NOT NULL,
start_date INTEGER NOT NULL, start_date INTEGER NOT NULL,
finish_date INTEGER NOT NULL, finish_date INTEGER NOT NULL,

View file

@ -1,5 +1,3 @@
import kotlin.Float;
CREATE TABLE anime_sync( CREATE TABLE anime_sync(
_id INTEGER NOT NULL PRIMARY KEY, _id INTEGER NOT NULL PRIMARY KEY,
anime_id INTEGER NOT NULL, anime_id INTEGER NOT NULL,
@ -10,7 +8,7 @@ CREATE TABLE anime_sync(
last_episode_seen REAL NOT NULL, last_episode_seen REAL NOT NULL,
total_episodes INTEGER NOT NULL, total_episodes INTEGER NOT NULL,
status INTEGER NOT NULL, status INTEGER NOT NULL,
score REAL AS Float NOT NULL, score REAL NOT NULL,
remote_url TEXT NOT NULL, remote_url TEXT NOT NULL,
start_date INTEGER NOT NULL, start_date INTEGER NOT NULL,
finish_date INTEGER NOT NULL, finish_date INTEGER NOT NULL,

View file

@ -1,5 +1,4 @@
import kotlin.Boolean; import kotlin.Boolean;
import kotlin.Float;
CREATE TABLE episodes( CREATE TABLE episodes(
_id INTEGER NOT NULL PRIMARY KEY, _id INTEGER NOT NULL PRIMARY KEY,
@ -11,7 +10,7 @@ CREATE TABLE episodes(
bookmark INTEGER AS Boolean NOT NULL, bookmark INTEGER AS Boolean NOT NULL,
last_second_seen INTEGER NOT NULL, last_second_seen INTEGER NOT NULL,
total_seconds INTEGER NOT NULL, total_seconds INTEGER NOT NULL,
episode_number REAL AS Float NOT NULL, episode_number REAL NOT NULL,
source_order INTEGER NOT NULL, source_order INTEGER NOT NULL,
date_fetch INTEGER NOT NULL, date_fetch INTEGER NOT NULL,
date_upload INTEGER NOT NULL, date_upload INTEGER NOT NULL,

View file

@ -8,7 +8,7 @@ data class AnimeHistoryWithRelations(
val episodeId: Long, val episodeId: Long,
val animeId: Long, val animeId: Long,
val title: String, val title: String,
val episodeNumber: Float, val episodeNumber: Double,
val seenAt: Date?, val seenAt: Date?,
val coverData: AnimeCover, val coverData: AnimeCover,
) )

View file

@ -8,7 +8,7 @@ data class MangaHistoryWithRelations(
val chapterId: Long, val chapterId: Long,
val mangaId: Long, val mangaId: Long,
val title: String, val title: String,
val chapterNumber: Float, val chapterNumber: Double,
val readAt: Date?, val readAt: Date?,
val readDuration: Long, val readDuration: Long,
val coverData: MangaCover, val coverData: MangaCover,

View file

@ -11,7 +11,7 @@ data class Chapter(
val url: String, val url: String,
val name: String, val name: String,
val dateUpload: Long, val dateUpload: Long,
val chapterNumber: Float, val chapterNumber: Double,
val scanlator: String?, val scanlator: String?,
val lastModifiedAt: Long, val lastModifiedAt: Long,
) { ) {
@ -30,7 +30,7 @@ data class Chapter(
url = "", url = "",
name = "", name = "",
dateUpload = -1, dateUpload = -1,
chapterNumber = -1f, chapterNumber = -1.0,
scanlator = null, scanlator = null,
lastModifiedAt = 0, lastModifiedAt = 0,
) )

View file

@ -11,7 +11,7 @@ data class ChapterUpdate(
val url: String? = null, val url: String? = null,
val name: String? = null, val name: String? = null,
val dateUpload: Long? = null, val dateUpload: Long? = null,
val chapterNumber: Float? = null, val chapterNumber: Double? = null,
val scanlator: String? = null, val scanlator: String? = null,
) )

View file

@ -30,9 +30,9 @@ object ChapterRecognition {
*/ */
private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""") private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""")
fun parseChapterNumber(mangaTitle: String, chapterName: String, chapterNumber: Float? = null): Float { fun parseChapterNumber(mangaTitle: String, chapterName: String, chapterNumber: Double? = null): Double {
// If chapter number is known return. // If chapter number is known return.
if (chapterNumber != null && (chapterNumber == -2f || chapterNumber > -1f)) { if (chapterNumber != null && (chapterNumber == -2.0 || chapterNumber > -1.0)) {
return chapterNumber return chapterNumber
} }
@ -57,7 +57,7 @@ object ChapterRecognition {
// Take the first number encountered. // Take the first number encountered.
number.find(name)?.let { return getChapterNumberFromMatch(it) } number.find(name)?.let { return getChapterNumberFromMatch(it) }
return chapterNumber ?: -1f return chapterNumber ?: -1.0
} }
/** /**
@ -65,9 +65,9 @@ object ChapterRecognition {
* @param match result of regex * @param match result of regex
* @return chapter number if found else null * @return chapter number if found else null
*/ */
private fun getChapterNumberFromMatch(match: MatchResult): Float { private fun getChapterNumberFromMatch(match: MatchResult): Double {
return match.let { return match.let {
val initial = it.groups[1]?.value?.toFloat()!! val initial = it.groups[1]?.value?.toDouble()!!
val subChapterDecimal = it.groups[2]?.value val subChapterDecimal = it.groups[2]?.value
val subChapterAlpha = it.groups[3]?.value val subChapterAlpha = it.groups[3]?.value
val addition = checkForDecimal(subChapterDecimal, subChapterAlpha) val addition = checkForDecimal(subChapterDecimal, subChapterAlpha)
@ -81,22 +81,22 @@ object ChapterRecognition {
* @param alpha alpha value of regex * @param alpha alpha value of regex
* @return decimal/alpha float value * @return decimal/alpha float value
*/ */
private fun checkForDecimal(decimal: String?, alpha: String?): Float { private fun checkForDecimal(decimal: String?, alpha: String?): Double {
if (!decimal.isNullOrEmpty()) { if (!decimal.isNullOrEmpty()) {
return decimal.toFloat() return decimal.toDouble()
} }
if (!alpha.isNullOrEmpty()) { if (!alpha.isNullOrEmpty()) {
if (alpha.contains("extra")) { if (alpha.contains("extra")) {
return .99f return 0.99
} }
if (alpha.contains("omake")) { if (alpha.contains("omake")) {
return .98f return 0.98
} }
if (alpha.contains("special")) { if (alpha.contains("special")) {
return .97f return 0.97
} }
val trimmedAlpha = alpha.trimStart('.') val trimmedAlpha = alpha.trimStart('.')
@ -105,15 +105,15 @@ object ChapterRecognition {
} }
} }
return .0f return 0.0
} }
/** /**
* x.a -> x.1, x.b -> x.2, etc * x.a -> x.1, x.b -> x.2, etc
*/ */
private fun parseAlphaPostFix(alpha: Char): Float { private fun parseAlphaPostFix(alpha: Char): Double {
val number = alpha.code - ('a'.code - 1) val number = alpha.code - ('a'.code - 1)
if (number >= 10) return 0f if (number >= 10) return 0.0
return number / 10f return number / 10.0
} }
} }

View file

@ -12,7 +12,7 @@ data class Episode(
val url: String, val url: String,
val name: String, val name: String,
val dateUpload: Long, val dateUpload: Long,
val episodeNumber: Float, val episodeNumber: Double,
val scanlator: String?, val scanlator: String?,
val lastModifiedAt: Long, val lastModifiedAt: Long,
) { ) {
@ -32,7 +32,7 @@ data class Episode(
url = "", url = "",
name = "", name = "",
dateUpload = -1, dateUpload = -1,
episodeNumber = -1f, episodeNumber = -1.0,
scanlator = null, scanlator = null,
lastModifiedAt = 0, lastModifiedAt = 0,
) )

View file

@ -12,7 +12,7 @@ data class EpisodeUpdate(
val url: String? = null, val url: String? = null,
val name: String? = null, val name: String? = null,
val dateUpload: Long? = null, val dateUpload: Long? = null,
val episodeNumber: Float? = null, val episodeNumber: Double? = null,
val scanlator: String? = null, val scanlator: String? = null,
) )

View file

@ -30,9 +30,9 @@ object EpisodeRecognition {
*/ */
private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""") private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""")
fun parseEpisodeNumber(animeTitle: String, episodeName: String, episodeNumber: Float? = null): Float { fun parseEpisodeNumber(animeTitle: String, episodeName: String, episodeNumber: Double? = null): Double {
// If episode number is known return. // If episode number is known return.
if (episodeNumber != null && (episodeNumber == -2f || episodeNumber > -1f)) { if (episodeNumber != null && (episodeNumber == -2.0 || episodeNumber > -1.0)) {
return episodeNumber return episodeNumber
} }
@ -57,7 +57,7 @@ object EpisodeRecognition {
// Take the first number encountered. // Take the first number encountered.
number.find(name)?.let { return getEpisodeNumberFromMatch(it) } number.find(name)?.let { return getEpisodeNumberFromMatch(it) }
return episodeNumber ?: -1f return episodeNumber ?: -1.0
} }
/** /**
@ -65,9 +65,9 @@ object EpisodeRecognition {
* @param match result of regex * @param match result of regex
* @return chapter number if found else null * @return chapter number if found else null
*/ */
private fun getEpisodeNumberFromMatch(match: MatchResult): Float { private fun getEpisodeNumberFromMatch(match: MatchResult): Double {
return match.let { return match.let {
val initial = it.groups[1]?.value?.toFloat()!! val initial = it.groups[1]?.value?.toDouble()!!
val subChapterDecimal = it.groups[2]?.value val subChapterDecimal = it.groups[2]?.value
val subChapterAlpha = it.groups[3]?.value val subChapterAlpha = it.groups[3]?.value
val addition = checkForDecimal(subChapterDecimal, subChapterAlpha) val addition = checkForDecimal(subChapterDecimal, subChapterAlpha)
@ -81,22 +81,22 @@ object EpisodeRecognition {
* @param alpha alpha value of regex * @param alpha alpha value of regex
* @return decimal/alpha float value * @return decimal/alpha float value
*/ */
private fun checkForDecimal(decimal: String?, alpha: String?): Float { private fun checkForDecimal(decimal: String?, alpha: String?): Double {
if (!decimal.isNullOrEmpty()) { if (!decimal.isNullOrEmpty()) {
return decimal.toFloat() return decimal.toDouble()
} }
if (!alpha.isNullOrEmpty()) { if (!alpha.isNullOrEmpty()) {
if (alpha.contains("extra")) { if (alpha.contains("extra")) {
return .99f return 0.99
} }
if (alpha.contains("omake")) { if (alpha.contains("omake")) {
return .98f return 0.98
} }
if (alpha.contains("special")) { if (alpha.contains("special")) {
return .97f return 0.97
} }
val trimmedAlpha = alpha.trimStart('.') val trimmedAlpha = alpha.trimStart('.')
@ -105,15 +105,15 @@ object EpisodeRecognition {
} }
} }
return .0f return 0.0
} }
/** /**
* x.a -> x.1, x.b -> x.2, etc * x.a -> x.1, x.b -> x.2, etc
*/ */
private fun parseAlphaPostFix(alpha: Char): Float { private fun parseAlphaPostFix(alpha: Char): Double {
val number = alpha.code - ('a'.code - 1) val number = alpha.code - ('a'.code - 1)
if (number >= 10) return 0f if (number >= 10) return 0.0
return number / 10f return number / 10.0
} }
} }

View file

@ -4,16 +4,16 @@ import tachiyomi.domain.items.chapter.model.Chapter
import tachiyomi.domain.items.episode.model.Episode import tachiyomi.domain.items.episode.model.Episode
import kotlin.math.floor import kotlin.math.floor
fun List<Float>.missingItemsCount(): Int { fun List<Double>.missingItemsCount(): Int {
if (this.isEmpty()) { if (this.isEmpty()) {
return 0 return 0
} }
val items = this val items = this
// Ignore unknown item numbers // Ignore unknown item numbers
.filter { it != -1f } .filter { it != -1.0 }
// Convert to integers, as we cannot check if 16.5 is missing // Convert to integers, as we cannot check if 16.5 is missing
.map(Float::toInt) .map(Double::toInt)
// Only keep unique chapters so that -1 or 16 are not counted multiple times // Only keep unique chapters so that -1 or 16 are not counted multiple times
.distinct() .distinct()
.sorted() .sorted()
@ -44,8 +44,8 @@ fun calculateChapterGap(higherChapter: Chapter?, lowerChapter: Chapter?): Int {
return calculateChapterGap(higherChapter.chapterNumber, lowerChapter.chapterNumber) return calculateChapterGap(higherChapter.chapterNumber, lowerChapter.chapterNumber)
} }
fun calculateChapterGap(higherChapterNumber: Float, lowerChapterNumber: Float): Int { fun calculateChapterGap(higherChapterNumber: Double, lowerChapterNumber: Double): Int {
if (higherChapterNumber < 0f || lowerChapterNumber < 0f) return 0 if (higherChapterNumber < 0.0 || lowerChapterNumber < 0.0) return 0
return floor(higherChapterNumber).toInt() - floor(lowerChapterNumber).toInt() - 1 return floor(higherChapterNumber).toInt() - floor(lowerChapterNumber).toInt() - 1
} }
@ -55,7 +55,7 @@ fun calculateEpisodeGap(higherEpisode: Episode?, lowerEpisode: Episode?): Int {
return calculateChapterGap(higherEpisode.episodeNumber, lowerEpisode.episodeNumber) return calculateChapterGap(higherEpisode.episodeNumber, lowerEpisode.episodeNumber)
} }
fun calculateEpisodeGap(higherEpisodeNumber: Float, lowerEpisodeNumber: Float): Int { fun calculateEpisodeGap(higherEpisodeNumber: Double, lowerEpisodeNumber: Double): Int {
if (higherEpisodeNumber < 0f || lowerEpisodeNumber < 0f) return 0 if (higherEpisodeNumber < 0.0 || lowerEpisodeNumber < 0.0) return 0
return floor(higherEpisodeNumber).toInt() - floor(lowerEpisodeNumber).toInt() - 1 return floor(higherEpisodeNumber).toInt() - floor(lowerEpisodeNumber).toInt() - 1
} }

View file

@ -10,7 +10,7 @@ data class AnimeTrack(
val lastEpisodeSeen: Double, val lastEpisodeSeen: Double,
val totalEpisodes: Long, val totalEpisodes: Long,
val status: Long, val status: Long,
val score: Float, val score: Double,
val remoteUrl: String, val remoteUrl: String,
val startDate: Long, val startDate: Long,
val finishDate: Long, val finishDate: Long,

View file

@ -10,7 +10,7 @@ data class MangaTrack(
val lastChapterRead: Double, val lastChapterRead: Double,
val totalChapters: Long, val totalChapters: Long,
val status: Long, val status: Long,
val score: Float, val score: Double,
val remoteUrl: String, val remoteUrl: String,
val startDate: Long, val startDate: Long,
val finishDate: Long, val finishDate: Long,

View file

@ -12,152 +12,152 @@ class ChapterRecognitionTest {
fun `Basic Ch prefix`() { fun `Basic Ch prefix`() {
val mangaTitle = "Mokushiroku Alice" val mangaTitle = "Mokushiroku Alice"
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4: Misrepresentation", 4f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4: Misrepresentation", 4.0)
} }
@Test @Test
fun `Basic Ch prefix with space after period`() { fun `Basic Ch prefix with space after period`() {
val mangaTitle = "Mokushiroku Alice" val mangaTitle = "Mokushiroku Alice"
assertChapter(mangaTitle, "Mokushiroku Alice Vol. 1 Ch. 4: Misrepresentation", 4f) assertChapter(mangaTitle, "Mokushiroku Alice Vol. 1 Ch. 4: Misrepresentation", 4.0)
} }
@Test @Test
fun `Basic Ch prefix with decimal`() { fun `Basic Ch prefix with decimal`() {
val mangaTitle = "Mokushiroku Alice" val mangaTitle = "Mokushiroku Alice"
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.1: Misrepresentation", 4.1f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.1: Misrepresentation", 4.1)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.4: Misrepresentation", 4.4f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.4: Misrepresentation", 4.4)
} }
@Test @Test
fun `Basic Ch prefix with alpha postfix`() { fun `Basic Ch prefix with alpha postfix`() {
val mangaTitle = "Mokushiroku Alice" val mangaTitle = "Mokushiroku Alice"
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.a: Misrepresentation", 4.1f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.a: Misrepresentation", 4.1)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.b: Misrepresentation", 4.2f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.b: Misrepresentation", 4.2)
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.extra: Misrepresentation", 4.99f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch.4.extra: Misrepresentation", 4.99)
} }
@Test @Test
fun `Name containing one number`() { fun `Name containing one number`() {
val mangaTitle = "Bleach" val mangaTitle = "Bleach"
assertChapter(mangaTitle, "Bleach 567 Down With Snowwhite", 567f) assertChapter(mangaTitle, "Bleach 567 Down With Snowwhite", 567.0)
} }
@Test @Test
fun `Name containing one number and decimal`() { fun `Name containing one number and decimal`() {
val mangaTitle = "Bleach" val mangaTitle = "Bleach"
assertChapter(mangaTitle, "Bleach 567.1 Down With Snowwhite", 567.1f) assertChapter(mangaTitle, "Bleach 567.1 Down With Snowwhite", 567.1)
assertChapter(mangaTitle, "Bleach 567.4 Down With Snowwhite", 567.4f) assertChapter(mangaTitle, "Bleach 567.4 Down With Snowwhite", 567.4)
} }
@Test @Test
fun `Name containing one number and alpha`() { fun `Name containing one number and alpha`() {
val mangaTitle = "Bleach" val mangaTitle = "Bleach"
assertChapter(mangaTitle, "Bleach 567.a Down With Snowwhite", 567.1f) assertChapter(mangaTitle, "Bleach 567.a Down With Snowwhite", 567.1)
assertChapter(mangaTitle, "Bleach 567.b Down With Snowwhite", 567.2f) assertChapter(mangaTitle, "Bleach 567.b Down With Snowwhite", 567.2)
assertChapter(mangaTitle, "Bleach 567.extra Down With Snowwhite", 567.99f) assertChapter(mangaTitle, "Bleach 567.extra Down With Snowwhite", 567.99)
} }
@Test @Test
fun `Chapter containing manga title and number`() { fun `Chapter containing manga title and number`() {
val mangaTitle = "Solanin" val mangaTitle = "Solanin"
assertChapter(mangaTitle, "Solanin 028 Vol. 2", 28f) assertChapter(mangaTitle, "Solanin 028 Vol. 2", 28.0)
} }
@Test @Test
fun `Chapter containing manga title and number decimal`() { fun `Chapter containing manga title and number decimal`() {
val mangaTitle = "Solanin" val mangaTitle = "Solanin"
assertChapter(mangaTitle, "Solanin 028.1 Vol. 2", 28.1f) assertChapter(mangaTitle, "Solanin 028.1 Vol. 2", 28.1)
assertChapter(mangaTitle, "Solanin 028.4 Vol. 2", 28.4f) assertChapter(mangaTitle, "Solanin 028.4 Vol. 2", 28.4)
} }
@Test @Test
fun `Chapter containing manga title and number alpha`() { fun `Chapter containing manga title and number alpha`() {
val mangaTitle = "Solanin" val mangaTitle = "Solanin"
assertChapter(mangaTitle, "Solanin 028.a Vol. 2", 28.1f) assertChapter(mangaTitle, "Solanin 028.a Vol. 2", 28.1)
assertChapter(mangaTitle, "Solanin 028.b Vol. 2", 28.2f) assertChapter(mangaTitle, "Solanin 028.b Vol. 2", 28.2)
assertChapter(mangaTitle, "Solanin 028.extra Vol. 2", 28.99f) assertChapter(mangaTitle, "Solanin 028.extra Vol. 2", 28.99)
} }
@Test @Test
fun `Extreme case`() { fun `Extreme case`() {
val mangaTitle = "Onepunch-Man" val mangaTitle = "Onepunch-Man"
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028", 28f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028", 28.0)
} }
@Test @Test
fun `Extreme case with decimal`() { fun `Extreme case with decimal`() {
val mangaTitle = "Onepunch-Man" val mangaTitle = "Onepunch-Man"
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.1", 28.1f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.1", 28.1)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.4", 28.4f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.4", 28.4)
} }
@Test @Test
fun `Extreme case with alpha`() { fun `Extreme case with alpha`() {
val mangaTitle = "Onepunch-Man" val mangaTitle = "Onepunch-Man"
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.a", 28.1f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.a", 28.1)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.b", 28.2f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.b", 28.2)
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.extra", 28.99f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 028.extra", 28.99)
} }
@Test @Test
fun `Chapter containing dot v2`() { fun `Chapter containing dot v2`() {
val mangaTitle = "random" val mangaTitle = "random"
assertChapter(mangaTitle, "Vol.1 Ch.5v.2: Alones", 5f) assertChapter(mangaTitle, "Vol.1 Ch.5v.2: Alones", 5.0)
} }
@Test @Test
fun `Number in manga title`() { fun `Number in manga title`() {
val mangaTitle = "Ayame 14" val mangaTitle = "Ayame 14"
assertChapter(mangaTitle, "Ayame 14 1 - The summer of 14", 1f) assertChapter(mangaTitle, "Ayame 14 1 - The summer of 14", 1.0)
} }
@Test @Test
fun `Space between ch x`() { fun `Space between ch x`() {
val mangaTitle = "Mokushiroku Alice" val mangaTitle = "Mokushiroku Alice"
assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch. 4: Misrepresentation", 4f) assertChapter(mangaTitle, "Mokushiroku Alice Vol.1 Ch. 4: Misrepresentation", 4.0)
} }
@Test @Test
fun `Chapter title with ch substring`() { fun `Chapter title with ch substring`() {
val mangaTitle = "Ayame 14" val mangaTitle = "Ayame 14"
assertChapter(mangaTitle, "Vol.1 Ch.1: March 25 (First Day Cohabiting)", 1f) assertChapter(mangaTitle, "Vol.1 Ch.1: March 25 (First Day Cohabiting)", 1.0)
} }
@Test @Test
fun `Chapter containing multiple zeros`() { fun `Chapter containing multiple zeros`() {
val mangaTitle = "random" val mangaTitle = "random"
assertChapter(mangaTitle, "Vol.001 Ch.003: Kaguya Doesn't Know Much", 3f) assertChapter(mangaTitle, "Vol.001 Ch.003: Kaguya Doesn't Know Much", 3.0)
} }
@Test @Test
fun `Chapter with version before number`() { fun `Chapter with version before number`() {
val mangaTitle = "Onepunch-Man" val mangaTitle = "Onepunch-Man"
assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 086 : Creeping Darkness [3]", 86f) assertChapter(mangaTitle, "Onepunch-Man Punch Ver002 086 : Creeping Darkness [3]", 86.0)
} }
@Test @Test
fun `Version attached to chapter number`() { fun `Version attached to chapter number`() {
val mangaTitle = "Ansatsu Kyoushitsu" val mangaTitle = "Ansatsu Kyoushitsu"
assertChapter(mangaTitle, "Ansatsu Kyoushitsu 011v002: Assembly Time", 11f) assertChapter(mangaTitle, "Ansatsu Kyoushitsu 011v002: Assembly Time", 11.0)
} }
/** /**
@ -168,99 +168,99 @@ class ChapterRecognitionTest {
fun `Number after manga title with chapter in chapter title case`() { fun `Number after manga title with chapter in chapter title case`() {
val mangaTitle = "Tokyo ESP" val mangaTitle = "Tokyo ESP"
assertChapter(mangaTitle, "Tokyo ESP 027: Part 002: Chapter 001", 027f) assertChapter(mangaTitle, "Tokyo ESP 027: Part 002: Chapter 001", 027.0)
} }
@Test @Test
fun `Unparseable chapter`() { fun `Unparseable chapter`() {
val mangaTitle = "random" val mangaTitle = "random"
assertChapter(mangaTitle, "Foo", -1f) assertChapter(mangaTitle, "Foo", -1.0)
} }
@Test @Test
fun `Chapter with time in title`() { fun `Chapter with time in title`() {
val mangaTitle = "random" val mangaTitle = "random"
assertChapter(mangaTitle, "Fairy Tail 404: 00:00", 404f) assertChapter(mangaTitle, "Fairy Tail 404: 00:00", 404.0)
} }
@Test @Test
fun `Chapter with alpha without dot`() { fun `Chapter with alpha without dot`() {
val mangaTitle = "random" val mangaTitle = "random"
assertChapter(mangaTitle, "Asu No Yoichi 19a", 19.1f) assertChapter(mangaTitle, "Asu No Yoichi 19a", 19.1)
} }
@Test @Test
fun `Chapter title containing extra and vol`() { fun `Chapter title containing extra and vol`() {
val mangaTitle = "Fairy Tail" val mangaTitle = "Fairy Tail"
assertChapter(mangaTitle, "Fairy Tail 404.extravol002", 404.99f) assertChapter(mangaTitle, "Fairy Tail 404.extravol002", 404.99)
assertChapter(mangaTitle, "Fairy Tail 404 extravol002", 404.99f) assertChapter(mangaTitle, "Fairy Tail 404 extravol002", 404.99)
} }
@Test @Test
fun `Chapter title containing omake (japanese extra) and vol`() { fun `Chapter title containing omake (japanese extra) and vol`() {
val mangaTitle = "Fairy Tail" val mangaTitle = "Fairy Tail"
assertChapter(mangaTitle, "Fairy Tail 404.omakevol002", 404.98f) assertChapter(mangaTitle, "Fairy Tail 404.omakevol002", 404.98)
assertChapter(mangaTitle, "Fairy Tail 404 omakevol002", 404.98f) assertChapter(mangaTitle, "Fairy Tail 404 omakevol002", 404.98)
} }
@Test @Test
fun `Chapter title containing special and vol`() { fun `Chapter title containing special and vol`() {
val mangaTitle = "Fairy Tail" val mangaTitle = "Fairy Tail"
assertChapter(mangaTitle, "Fairy Tail 404.specialvol002", 404.97f) assertChapter(mangaTitle, "Fairy Tail 404.specialvol002", 404.97)
assertChapter(mangaTitle, "Fairy Tail 404 specialvol002", 404.97f) assertChapter(mangaTitle, "Fairy Tail 404 specialvol002", 404.97)
} }
@Test @Test
fun `Chapter title containing commas`() { fun `Chapter title containing commas`() {
val mangaTitle = "One Piece" val mangaTitle = "One Piece"
assertChapter(mangaTitle, "One Piece 300,a", 300.1f) assertChapter(mangaTitle, "One Piece 300,a", 300.1)
assertChapter(mangaTitle, "One Piece Ch,123,extra", 123.99f) assertChapter(mangaTitle, "One Piece Ch,123,extra", 123.99)
assertChapter(mangaTitle, "One Piece the sunny, goes swimming 024,005", 24.005f) assertChapter(mangaTitle, "One Piece the sunny, goes swimming 024,005", 24.005)
} }
@Test @Test
fun `Chapter title containing hyphens`() { fun `Chapter title containing hyphens`() {
val mangaTitle = "Solo Leveling" val mangaTitle = "Solo Leveling"
assertChapter(mangaTitle, "ch 122-a", 122.1f) assertChapter(mangaTitle, "ch 122-a", 122.1)
assertChapter(mangaTitle, "Solo Leveling Ch.123-extra", 123.99f) assertChapter(mangaTitle, "Solo Leveling Ch.123-extra", 123.99)
assertChapter(mangaTitle, "Solo Leveling, 024-005", 24.005f) assertChapter(mangaTitle, "Solo Leveling, 024-005", 24.005)
assertChapter(mangaTitle, "Ch.191-200 Read Online", 191.200f) assertChapter(mangaTitle, "Ch.191-200 Read Online", 191.200)
} }
@Test @Test
fun `Chapters containing season`() { fun `Chapters containing season`() {
assertChapter("D.I.C.E", "D.I.C.E[Season 001] Ep. 007", 7f) assertChapter("D.I.C.E", "D.I.C.E[Season 001] Ep. 007", 7.0)
} }
@Test @Test
fun `Chapters in format sx - chapter xx`() { fun `Chapters in format sx - chapter xx`() {
assertChapter("The Gamer", "S3 - Chapter 20", 20f) assertChapter("The Gamer", "S3 - Chapter 20", 20.0)
} }
@Test @Test
fun `Chapters ending with s`() { fun `Chapters ending with s`() {
assertChapter("One Outs", "One Outs 001", 1f) assertChapter("One Outs", "One Outs 001", 1.0)
} }
@Test @Test
fun `Chapters containing ordinals`() { fun `Chapters containing ordinals`() {
val mangaTitle = "The Sister of the Woods with a Thousand Young" val mangaTitle = "The Sister of the Woods with a Thousand Young"
assertChapter(mangaTitle, "The 1st Night", 1f) assertChapter(mangaTitle, "The 1st Night", 1.0)
assertChapter(mangaTitle, "The 2nd Night", 2f) assertChapter(mangaTitle, "The 2nd Night", 2.0)
assertChapter(mangaTitle, "The 3rd Night", 3f) assertChapter(mangaTitle, "The 3rd Night", 3.0)
assertChapter(mangaTitle, "The 4th Night", 4f) assertChapter(mangaTitle, "The 4th Night", 4.0)
} }
private fun assertChapter(mangaTitle: String, name: String, expected: Float) { private fun assertChapter(mangaTitle: String, name: String, expected: Double) {
ChapterRecognition.parseChapterNumber(mangaTitle, name) shouldBe expected ChapterRecognition.parseChapterNumber(mangaTitle, name) shouldBe expected
} }
} }

View file

@ -12,73 +12,73 @@ class MissingItemsTest {
@Test @Test
fun `missingItemsCount returns 0 when empty list`() { fun `missingItemsCount returns 0 when empty list`() {
emptyList<Float>().missingItemsCount() shouldBe 0 emptyList<Double>().missingItemsCount() shouldBe 0
} }
@Test @Test
fun `missingItemsCount returns 0 when all unknown item numbers`() { fun `missingItemsCount returns 0 when all unknown item numbers`() {
listOf(-1f, -1f, -1f).missingItemsCount() shouldBe 0 listOf(-1.0, -1.0, -1.0).missingItemsCount() shouldBe 0
} }
@Test @Test
fun `missingItemsCount handles repeated base item numbers`() { fun `missingItemsCount handles repeated base item numbers`() {
listOf(1f, 1.0f, 1.1f, 1.5f, 1.6f, 1.99f).missingItemsCount() shouldBe 0 listOf(1.0, 1.0, 1.1, 1.5, 1.6, 1.99).missingItemsCount() shouldBe 0
} }
@Test @Test
fun `missingItemsCount returns number of missing items`() { fun `missingItemsCount returns number of missing items`() {
listOf(-1f, 1f, 2f, 2.2f, 4f, 6f, 10f, 11f).missingItemsCount() shouldBe 5 listOf(-1.0, 1.0, 2.0, 2.2, 4.0, 6.0, 10.0, 10.0).missingItemsCount() shouldBe 5
} }
@Test @Test
fun `calculateChapterGap returns difference`() { fun `calculateChapterGap returns difference`() {
calculateChapterGap(chapter(10f), chapter(9f)) shouldBe 0f calculateChapterGap(chapter(10.0), chapter(9.0)) shouldBe 0f
calculateChapterGap(chapter(10f), chapter(8f)) shouldBe 1f calculateChapterGap(chapter(10.0), chapter(8.0)) shouldBe 1f
calculateChapterGap(chapter(10f), chapter(8.5f)) shouldBe 1f calculateChapterGap(chapter(10.0), chapter(8.5)) shouldBe 1f
calculateChapterGap(chapter(10f), chapter(1.1f)) shouldBe 8f calculateChapterGap(chapter(10.0), chapter(1.1)) shouldBe 8f
calculateChapterGap(10f, 9f) shouldBe 0f calculateChapterGap(10.0, 9.0) shouldBe 0f
calculateChapterGap(10f, 8f) shouldBe 1f calculateChapterGap(10.0, 8.0) shouldBe 1f
calculateChapterGap(10f, 8.5f) shouldBe 1f calculateChapterGap(10.0, 8.5) shouldBe 1f
calculateChapterGap(10f, 1.1f) shouldBe 8f calculateChapterGap(10.0, 1.1) shouldBe 8f
} }
@Test @Test
fun `calculateChapterGap returns 0 if either are not valid chapter numbers`() { fun `calculateChapterGap returns 0 if either are not valid chapter numbers`() {
calculateChapterGap(chapter(-1f), chapter(10f)) shouldBe 0 calculateChapterGap(chapter(-1.0), chapter(10.0)) shouldBe 0
calculateChapterGap(chapter(99f), chapter(-1f)) shouldBe 0 calculateChapterGap(chapter(99.0), chapter(-1.0)) shouldBe 0
calculateChapterGap(-1f, 10f) shouldBe 0 calculateChapterGap(-1.0, 10.0) shouldBe 0
calculateChapterGap(99f, -1f) shouldBe 0 calculateChapterGap(99.0, -1.0) shouldBe 0
} }
private fun chapter(number: Float) = Chapter.create().copy( private fun chapter(number: Double) = Chapter.create().copy(
chapterNumber = number, chapterNumber = number,
) )
@Test @Test
fun `calculateEpisodeGap returns difference`() { fun `calculateEpisodeGap returns difference`() {
calculateEpisodeGap(episode(10f), episode(9f)) shouldBe 0f calculateEpisodeGap(episode(10.0), episode(9.0)) shouldBe 0f
calculateEpisodeGap(episode(10f), episode(8f)) shouldBe 1f calculateEpisodeGap(episode(10.0), episode(8.0)) shouldBe 1f
calculateEpisodeGap(episode(10f), episode(8.5f)) shouldBe 1f calculateEpisodeGap(episode(10.0), episode(8.5)) shouldBe 1f
calculateEpisodeGap(episode(10f), episode(1.1f)) shouldBe 8f calculateEpisodeGap(episode(10.0), episode(1.1)) shouldBe 8f
calculateEpisodeGap(10f, 9f) shouldBe 0f calculateEpisodeGap(10.0, 9.0) shouldBe 0f
calculateEpisodeGap(10f, 8f) shouldBe 1f calculateEpisodeGap(10.0, 8.0) shouldBe 1f
calculateEpisodeGap(10f, 8.5f) shouldBe 1f calculateEpisodeGap(10.0, 8.5) shouldBe 1f
calculateEpisodeGap(10f, 1.1f) shouldBe 8f calculateEpisodeGap(10.0, 1.1) shouldBe 8f
} }
@Test @Test
fun `calculateEpisodeGap returns 0 if either are not valid episode numbers`() { fun `calculateEpisodeGap returns 0 if either are not valid episode numbers`() {
calculateEpisodeGap(episode(-1f), episode(10f)) shouldBe 0 calculateEpisodeGap(episode(-1.0), episode(10.0)) shouldBe 0
calculateEpisodeGap(episode(99f), episode(-1f)) shouldBe 0 calculateEpisodeGap(episode(99.0), episode(-1.0)) shouldBe 0
calculateEpisodeGap(-1f, 10f) shouldBe 0 calculateEpisodeGap(-1.0, 10.0) shouldBe 0
calculateEpisodeGap(99f, -1f) shouldBe 0 calculateEpisodeGap(99.0, -1.0) shouldBe 0
} }
private fun episode(number: Float) = Episode.create().copy( private fun episode(number: Double) = Episode.create().copy(
episodeNumber = number, episodeNumber = number,
) )
} }

View file

@ -26,3 +26,5 @@ android.useAndroidX=true
android.defaults.buildfeatures.buildconfig=true android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false android.nonTransitiveRClass=false
android.nonFinalResIds=false android.nonFinalResIds=false
android.experimental.useDefaultDebugSigningConfigForProfileableBuildtypes=true

View file

@ -1,5 +1,5 @@
[versions] [versions]
agp_version = "8.1.0" agp_version = "8.0.2"
lifecycle_version = "2.6.1" lifecycle_version = "2.6.1"
paging_version = "3.2.0" paging_version = "3.2.0"
@ -28,10 +28,10 @@ guava = "com.google.guava:guava:32.0.1-android"
paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging_version" } paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging_version" }
paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging_version" } paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging_version" }
benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.1.1" benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.0-beta02"
test-ext = "androidx.test.ext:junit-ktx:1.1.5" test-ext = "androidx.test.ext:junit-ktx:1.2.0-alpha01"
test-espresso-core = "androidx.test.espresso:espresso-core:3.5.1" test-espresso-core = "androidx.test.espresso:espresso-core:3.6.0-alpha01"
test-uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0" test-uiautomator = "androidx.test.uiautomator:uiautomator:2.3.0-alpha04"
[bundles] [bundles]
lifecycle = ["lifecycle-common", "lifecycle-process", "lifecycle-runtimektx"] lifecycle = ["lifecycle-common", "lifecycle-process", "lifecycle-runtimektx"]

View file

@ -79,7 +79,6 @@ leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", versi
sqldelight-android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions-jvm", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions-jvm", version.ref = "sqldelight" }
sqldelight-android-paging = { module = "app.cash.sqldelight:androidx-paging3-extensions", version.ref = "sqldelight" } sqldelight-android-paging = { module = "app.cash.sqldelight:androidx-paging3-extensions", version.ref = "sqldelight" }
sqldelight-primitive-adapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "sqldelight" }
sqldelight-dialects-sql = { module = "app.cash.sqldelight:sqlite-3-38-dialect", version.ref = "sqldelight" } sqldelight-dialects-sql = { module = "app.cash.sqldelight:sqlite-3-38-dialect", version.ref = "sqldelight" }
sqldelight-gradle = { module = "app.cash.sqldelight:gradle-plugin", version.ref = "sqldelight" } sqldelight-gradle = { module = "app.cash.sqldelight:gradle-plugin", version.ref = "sqldelight" }
@ -108,7 +107,7 @@ js-engine = ["quickjs-android"]
sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"] sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"]
coil = ["coil-core", "coil-gif", "coil-compose"] coil = ["coil-core", "coil-gif", "coil-compose"]
shizuku = ["shizuku-api", "shizuku-provider"] shizuku = ["shizuku-api", "shizuku-provider"]
sqldelight = ["sqldelight-android-driver", "sqldelight-coroutines", "sqldelight-android-paging", "sqldelight-primitive-adapters"] sqldelight = ["sqldelight-android-driver", "sqldelight-coroutines", "sqldelight-android-paging"]
voyager = ["voyager-navigator", "voyager-tab-navigator", "voyager-transitions"] voyager = ["voyager-navigator", "voyager-tab-navigator", "voyager-transitions"]
richtext = ["richtext-commonmark", "richtext-m3"] richtext = ["richtext-commonmark", "richtext-m3"]
test = ["junit", "kotest-assertions", "mockk"] test = ["junit", "kotest-assertions", "mockk"]

View file

@ -8,6 +8,7 @@ android {
defaultConfig { defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments["androidx.benchmark.enabledRules"] = "BaselineProfile"
} }
buildTypes { buildTypes {
@ -17,7 +18,7 @@ android {
create("benchmark") { create("benchmark") {
isDebuggable = true isDebuggable = true
signingConfig = getByName("debug").signingConfig signingConfig = getByName("debug").signingConfig
matchingFallbacks += listOf("release") matchingFallbacks.add("release")
} }
} }

View file

@ -1,19 +1,17 @@
package tachiyomi.macrobenchmark package tachiyomi.macrobenchmark
import androidx.benchmark.macro.ExperimentalBaselineProfilesApi
import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.uiautomator.By import androidx.test.uiautomator.By
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalBaselineProfilesApi::class)
class BaselineProfileGenerator { class BaselineProfileGenerator {
@get:Rule @get:Rule
val baselineProfileRule = BaselineProfileRule() val baselineProfileRule = BaselineProfileRule()
@Test @Test
fun generate() = baselineProfileRule.collectBaselineProfile( fun generate() = baselineProfileRule.collect(
packageName = "xyz.jmir.tachiyomi.mi.benchmark", packageName = "xyz.jmir.tachiyomi.mi.benchmark",
profileBlock = { profileBlock = {
pressHome() pressHome()

View file

@ -181,11 +181,7 @@ actual class LocalAnimeSource(
} }
date_upload = episodeFile.lastModified() date_upload = episodeFile.lastModified()
val episodeNumber = EpisodeRecognition.parseEpisodeNumber( val episodeNumber = EpisodeRecognition.parseEpisodeNumber(anime.title, this.name, this.episode_number.toDouble()).toFloat()
anime.title,
this.name,
this.episode_number,
)
episode_number = episodeNumber episode_number = episodeNumber
// Overwrite data from episodes.json file // Overwrite data from episodes.json file

View file

@ -282,11 +282,9 @@ actual class LocalMangaSource(
} }
date_upload = chapterFile.lastModified() date_upload = chapterFile.lastModified()
val chapterNumber = ChapterRecognition.parseChapterNumber( val chapterNumber = ChapterRecognition
manga.title, .parseChapterNumber(manga.title, this.name, this.chapter_number.toDouble())
this.name, .toFloat()
this.chapter_number,
)
chapter_number = chapterNumber chapter_number = chapterNumber
val format = Format.valueOf(chapterFile) val format = Format.valueOf(chapterFile)