Remove need for SQLDelight primitive adapters

This commit is contained in:
arkon 2023-07-29 16:14:23 -04:00
parent 6a558ad119
commit cd91ea9b77
31 changed files with 67 additions and 83 deletions

View file

@ -170,7 +170,6 @@ dependencies {
implementation(androidx.paging.compose)
implementation(libs.bundles.sqlite)
implementation(libs.sqldelight.primitive.adapters)
implementation(kotlinx.reflect)

View file

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

View file

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

View file

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

View file

@ -22,7 +22,7 @@ fun Track.toDbTrack(): DbTrack = DbTrack.create(syncId).also {
it.last_chapter_read = lastChapterRead.toFloat()
it.total_chapters = totalChapters.toInt()
it.status = status.toInt()
it.score = score
it.score = score.toFloat()
it.tracking_url = remoteUrl
it.started_reading_date = startDate
it.finished_reading_date = finishDate
@ -40,7 +40,7 @@ fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
lastChapterRead = last_chapter_read.toDouble(),
totalChapters = total_chapters.toLong(),
status = status.toLong(),
score = score,
score = score.toDouble(),
remoteUrl = tracking_url,
startDate = started_reading_date,
finishDate = finished_reading_date,

View file

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

View file

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

View file

@ -5,7 +5,6 @@ import android.os.Build
import androidx.core.content.ContextCompat
import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import app.cash.sqldelight.adapter.primitive.FloatColumnAdapter
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import eu.kanade.domain.base.BasePreferences
@ -38,15 +37,13 @@ import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.provider.AndroidBackupFolderProvider
import tachiyomi.core.provider.AndroidDownloadFolderProvider
import tachiyomi.data.AndroidDatabaseHandler
import tachiyomi.data.Chapters
import tachiyomi.data.Database
import tachiyomi.data.DatabaseHandler
import tachiyomi.data.DateColumnAdapter
import tachiyomi.data.History
import tachiyomi.data.Manga_sync
import tachiyomi.data.Mangas
import tachiyomi.data.dateAdapter
import tachiyomi.data.listOfStringsAdapter
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.service.LibraryPreferences
@ -93,18 +90,12 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory {
Database(
driver = get(),
chaptersAdapter = Chapters.Adapter(
chapter_numberAdapter = FloatColumnAdapter,
),
historyAdapter = History.Adapter(
last_readAdapter = dateAdapter,
),
manga_syncAdapter = Manga_sync.Adapter(
scoreAdapter = FloatColumnAdapter,
last_readAdapter = DateColumnAdapter,
),
mangasAdapter = Mangas.Adapter(
genreAdapter = listOfStringsAdapter,
update_strategyAdapter = updateStrategyAdapter,
genreAdapter = StringListColumnAdapter,
update_strategyAdapter = UpdateStrategyColumnAdapter,
),
)
}

View file

@ -30,12 +30,11 @@ import logcat.LogPriority
import okio.buffer
import okio.gzip
import okio.sink
import tachiyomi.core.util.lang.toLong
import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler
import tachiyomi.data.Manga_sync
import tachiyomi.data.Mangas
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
@ -415,7 +414,7 @@ class BackupManager(
track.last_chapter_read,
track.total_chapters,
track.status,
track.score.toDouble(),
track.score,
track.remote_url,
track.start_date,
track.finish_date,
@ -536,7 +535,7 @@ class BackupManager(
coverLastModified = manga.coverLastModified,
dateAdded = manga.dateAdded,
mangaId = manga.id,
updateStrategy = manga.updateStrategy.let(updateStrategyAdapter::encode),
updateStrategy = manga.updateStrategy.let(UpdateStrategyColumnAdapter::encode),
)
}
return manga.id

View file

@ -26,7 +26,7 @@ data class BackupChapter(
return Chapter.create().copy(
url = this@BackupChapter.url,
name = this@BackupChapter.name,
chapterNumber = this@BackupChapter.chapterNumber,
chapterNumber = this@BackupChapter.chapterNumber.toDouble(),
scanlator = this@BackupChapter.scanlator,
read = this@BackupChapter.read,
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(
url = url,
name = name,
chapterNumber = chapterNumber,
chapterNumber = chapterNumber.toFloat(),
scanlator = scanlator,
read = read,
bookmark = bookmark,

View file

@ -44,7 +44,7 @@ data class BackupTracking(
title = this@BackupTracking.title,
lastChapterRead = this@BackupTracking.lastChapterRead.toDouble(),
totalChapters = this@BackupTracking.totalChapters.toLong(),
score = this@BackupTracking.score,
score = this@BackupTracking.score.toDouble(),
status = this@BackupTracking.status.toLong(),
startDate = this@BackupTracking.startedReadingDate,
finishDate = this@BackupTracking.finishedReadingDate,
@ -54,7 +54,7 @@ data class BackupTracking(
}
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(
syncId = syncId.toInt(),
mediaId = mediaId,
@ -63,7 +63,7 @@ val backupTrackMapper = {
title = title,
lastChapterRead = lastChapterRead.toFloat(),
totalChapters = totalChapters.toInt(),
score = score,
score = score.toFloat(),
status = status.toInt(),
startedReadingDate = startDate,
finishedReadingDate = finishDate,

View file

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

View file

@ -65,7 +65,7 @@ abstract class TrackService(val id: Long) {
abstract fun getScoreList(): List<String>
// TODO: Store all scores as 10 point in the future maybe?
open fun get10PointScore(track: DomainTrack): Float {
open fun get10PointScore(track: DomainTrack): Double {
return track.score
}

View file

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

View file

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

View file

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

View file

@ -4,23 +4,23 @@ import app.cash.sqldelight.ColumnAdapter
import eu.kanade.tachiyomi.source.model.UpdateStrategy
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 encode(value: Date): Long = value.time
}
private const val listOfStringsSeparator = ", "
val listOfStringsAdapter = object : ColumnAdapter<List<String>, String> {
private const val LIST_OF_STRINGS_SEPARATOR = ", "
object StringListColumnAdapter : ColumnAdapter<List<String>, String> {
override fun decode(databaseValue: String) =
if (databaseValue.isEmpty()) {
emptyList()
} 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 =
UpdateStrategy.entries.getOrElse(databaseValue.toInt()) { UpdateStrategy.ALWAYS_UPDATE }

View file

@ -2,7 +2,7 @@ package tachiyomi.data.chapter
import tachiyomi.domain.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 ->
Chapter(
id = id,

View file

@ -14,7 +14,7 @@ val historyMapper: (Long, Long, Date?, Long) -> History = { id, chapterId, readA
)
}
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Float, Date?, Long) -> HistoryWithRelations = {
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Double, Date?, Long) -> HistoryWithRelations = {
historyId, mangaId, chapterId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, chapterNumber, readAt, readDuration ->
HistoryWithRelations(
id = historyId,

View file

@ -2,11 +2,10 @@ package tachiyomi.data.manga
import kotlinx.coroutines.flow.Flow
import logcat.LogPriority
import tachiyomi.core.util.lang.toLong
import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler
import tachiyomi.data.listOfStringsAdapter
import tachiyomi.data.updateStrategyAdapter
import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaUpdate
@ -129,7 +128,7 @@ class MangaRepositoryImpl(
artist = value.artist,
author = value.author,
description = value.description,
genre = value.genre?.let(listOfStringsAdapter::encode),
genre = value.genre?.let(StringListColumnAdapter::encode),
title = value.title,
status = value.status,
thumbnailUrl = value.thumbnailUrl,
@ -143,7 +142,7 @@ class MangaRepositoryImpl(
coverLastModified = value.coverLastModified,
dateAdded = value.dateAdded,
mangaId = value.id,
updateStrategy = value.updateStrategy?.let(updateStrategyAdapter::encode),
updateStrategy = value.updateStrategy?.let(UpdateStrategyColumnAdapter::encode),
)
}
}

View file

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

View file

@ -1,5 +1,4 @@
import kotlin.Boolean;
import kotlin.Float;
CREATE TABLE chapters(
_id INTEGER NOT NULL PRIMARY KEY,
@ -10,7 +9,7 @@ CREATE TABLE chapters(
read INTEGER AS Boolean NOT NULL,
bookmark INTEGER AS Boolean 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,
date_fetch INTEGER NOT NULL,
date_upload INTEGER NOT NULL,

View file

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

View file

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

View file

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

View file

@ -30,9 +30,9 @@ object ChapterRecognition {
*/
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 (chapterNumber != null && (chapterNumber == -2f || chapterNumber > -1f)) {
if (chapterNumber != null && (chapterNumber == -2.0 || chapterNumber > -1.0)) {
return chapterNumber
}
@ -57,7 +57,7 @@ object ChapterRecognition {
// Take the first number encountered.
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
* @return chapter number if found else null
*/
private fun getChapterNumberFromMatch(match: MatchResult): Float {
private fun getChapterNumberFromMatch(match: MatchResult): Double {
return match.let {
val initial = it.groups[1]?.value?.toFloat()!!
val initial = it.groups[1]?.value?.toDouble()!!
val subChapterDecimal = it.groups[2]?.value
val subChapterAlpha = it.groups[3]?.value
val addition = checkForDecimal(subChapterDecimal, subChapterAlpha)

View file

@ -3,16 +3,16 @@ package tachiyomi.domain.chapter.service
import tachiyomi.domain.chapter.model.Chapter
import kotlin.math.floor
fun List<Float>.missingChaptersCount(): Int {
fun List<Double>.missingChaptersCount(): Int {
if (this.isEmpty()) {
return 0
}
val chapters = this
// Ignore unknown chapter numbers
.filterNot { it == -1f }
.filterNot { it == -1.0 }
// 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
.distinct()
.sorted()
@ -43,7 +43,7 @@ fun calculateChapterGap(higherChapter: Chapter?, lowerChapter: Chapter?): Int {
return calculateChapterGap(higherChapter.chapterNumber, lowerChapter.chapterNumber)
}
fun calculateChapterGap(higherChapterNumber: Float, lowerChapterNumber: Float): Int {
if (higherChapterNumber < 0f || lowerChapterNumber < 0f) return 0
fun calculateChapterGap(higherChapterNumber: Double, lowerChapterNumber: Double): Int {
if (higherChapterNumber < 0.0 || lowerChapterNumber < 0.0) return 0
return floor(higherChapterNumber).toInt() - floor(lowerChapterNumber).toInt() - 1
}

View file

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

View file

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

View file

@ -80,7 +80,6 @@ leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", versi
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-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-gradle = { module = "app.cash.sqldelight:gradle-plugin", version.ref = "sqldelight" }
@ -101,7 +100,7 @@ js-engine = ["quickjs-android"]
sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"]
coil = ["coil-core", "coil-gif", "coil-compose"]
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"]
richtext = ["richtext-commonmark", "richtext-m3"]
test = ["junit", "kotest-assertions", "mockk"]

View file

@ -264,7 +264,9 @@ actual class LocalSource(
chapterFile.nameWithoutExtension
}
date_upload = chapterFile.lastModified()
chapter_number = ChapterRecognition.parseChapterNumber(manga.title, this.name, this.chapter_number)
chapter_number = ChapterRecognition
.parseChapterNumber(manga.title, this.name, this.chapter_number.toDouble())
.toFloat()
val format = Format.valueOf(chapterFile)
if (format is Format.Epub) {