mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-21 20:27:06 +03:00
parent
a2a445fdc5
commit
eeddf17691
75 changed files with 35062 additions and 20360 deletions
|
@ -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
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
)
|
)
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) }
|
||||||
|
|
|
@ -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) }
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue