Minor tracking cleanups

This commit is contained in:
arkon 2023-12-24 22:25:22 -05:00
parent 6d74a86711
commit 6887d98f15
24 changed files with 64 additions and 69 deletions

View file

@ -25,7 +25,7 @@ class RefreshTracks(
suspend fun await(mangaId: Long): List<Pair<Tracker?, Throwable>> { suspend fun await(mangaId: Long): List<Pair<Tracker?, Throwable>> {
return supervisorScope { return supervisorScope {
return@supervisorScope getTracks.await(mangaId) return@supervisorScope getTracks.await(mangaId)
.map { it to trackerManager.get(it.syncId) } .map { it to trackerManager.get(it.trackerId) }
.filter { (_, service) -> service?.isLoggedIn == true } .filter { (_, service) -> service?.isLoggedIn == true }
.map { (track, service) -> .map { (track, service) ->
async { async {

View file

@ -27,7 +27,7 @@ class TrackChapter(
if (tracks.isEmpty()) return@withNonCancellableContext if (tracks.isEmpty()) return@withNonCancellableContext
tracks.mapNotNull { track -> tracks.mapNotNull { track ->
val service = trackerManager.get(track.syncId) val service = trackerManager.get(track.trackerId)
if (service == null || !service.isLoggedIn || chapterNumber <= track.lastChapterRead) { if (service == null || !service.isLoggedIn || chapterNumber <= track.lastChapterRead) {
return@mapNotNull null return@mapNotNull null
} }

View file

@ -13,7 +13,7 @@ fun Track.copyPersonalFrom(other: Track): Track {
) )
} }
fun Track.toDbTrack(): DbTrack = DbTrack.create(syncId).also { fun Track.toDbTrack(): DbTrack = DbTrack.create(trackerId).also {
it.id = id it.id = id
it.manga_id = mangaId it.manga_id = mangaId
it.remote_id = remoteId it.remote_id = remoteId
@ -33,7 +33,7 @@ fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
return Track( return Track(
id = trackId, id = trackId,
mangaId = manga_id, mangaId = manga_id,
syncId = sync_id.toLong(), trackerId = tracker_id.toLong(),
remoteId = remote_id, remoteId = remote_id,
libraryId = library_id, libraryId = library_id,
title = title, title = title,

View file

@ -9,26 +9,24 @@ class TrackPreferences(
private val preferenceStore: PreferenceStore, private val preferenceStore: PreferenceStore,
) { ) {
fun trackUsername(sync: Tracker) = preferenceStore.getString(trackUsername(sync.id), "") fun trackUsername(tracker: Tracker) = preferenceStore.getString(
Preference.privateKey("pref_mangasync_username_${tracker.id}"),
"",
)
fun trackPassword(sync: Tracker) = preferenceStore.getString(trackPassword(sync.id), "") fun trackPassword(tracker: Tracker) = preferenceStore.getString(
Preference.privateKey("pref_mangasync_password_${tracker.id}"),
"",
)
fun setCredentials(sync: Tracker, username: String, password: String) { fun setCredentials(tracker: Tracker, username: String, password: String) {
trackUsername(sync).set(username) trackUsername(tracker).set(username)
trackPassword(sync).set(password) trackPassword(tracker).set(password)
} }
fun trackToken(sync: Tracker) = preferenceStore.getString(trackToken(sync.id), "") fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "")
fun anilistScoreType() = preferenceStore.getString("anilist_score_type", Anilist.POINT_10) fun anilistScoreType() = preferenceStore.getString("anilist_score_type", Anilist.POINT_10)
fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true) fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true)
companion object {
fun trackUsername(syncId: Long) = Preference.privateKey("pref_mangasync_username_$syncId")
private fun trackPassword(syncId: Long) = Preference.privateKey("pref_mangasync_password_$syncId")
private fun trackToken(syncId: Long) = Preference.privateKey("track_token_$syncId")
}
} }

View file

@ -21,7 +21,6 @@ import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.presentation.core.components.SliderItem import tachiyomi.presentation.core.components.SliderItem
import tachiyomi.presentation.core.util.collectAsState import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -157,8 +156,8 @@ internal fun PreferenceItem(
) )
} }
is Preference.PreferenceItem.TrackerPreference -> { is Preference.PreferenceItem.TrackerPreference -> {
val uName by Injekt.get<PreferenceStore>() val uName by Injekt.get<TrackPreferences>()
.getString(TrackPreferences.trackUsername(item.tracker.id)) .trackUsername(item.tracker)
.collectAsState() .collectAsState()
item.tracker.run { item.tracker.run {
TrackingPreferenceWidget( TrackingPreferenceWidget(

View file

@ -34,11 +34,10 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.data.database.models.toDomainChapter import eu.kanade.tachiyomi.data.database.models.toDomainChapter
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.service.calculateChapterGap import tachiyomi.domain.chapter.service.calculateChapterGap
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.pluralStringResource import tachiyomi.presentation.core.i18n.pluralStringResource
@ -51,8 +50,8 @@ fun ChapterTransition(
currChapterDownloaded: Boolean, currChapterDownloaded: Boolean,
goingToChapterDownloaded: Boolean, goingToChapterDownloaded: Boolean,
) { ) {
val currChapter = transition.from.chapter val currChapter = transition.from.chapter.toDomainChapter()
val goingToChapter = transition.to?.chapter val goingToChapter = transition.to?.chapter?.toDomainChapter()
ProvideTextStyle(MaterialTheme.typography.bodyMedium) { ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
when (transition) { when (transition) {
@ -65,7 +64,7 @@ fun ChapterTransition(
bottomChapter = currChapter, bottomChapter = currChapter,
bottomChapterDownloaded = currChapterDownloaded, bottomChapterDownloaded = currChapterDownloaded,
fallbackLabel = stringResource(MR.strings.transition_no_previous), fallbackLabel = stringResource(MR.strings.transition_no_previous),
chapterGap = calculateChapterGap(currChapter.toDomainChapter(), goingToChapter?.toDomainChapter()), chapterGap = calculateChapterGap(currChapter, goingToChapter),
) )
} }
is ChapterTransition.Next -> { is ChapterTransition.Next -> {
@ -77,7 +76,7 @@ fun ChapterTransition(
bottomChapter = goingToChapter, bottomChapter = goingToChapter,
bottomChapterDownloaded = goingToChapterDownloaded, bottomChapterDownloaded = goingToChapterDownloaded,
fallbackLabel = stringResource(MR.strings.transition_no_next), fallbackLabel = stringResource(MR.strings.transition_no_next),
chapterGap = calculateChapterGap(goingToChapter?.toDomainChapter(), currChapter.toDomainChapter()), chapterGap = calculateChapterGap(goingToChapter, currChapter),
) )
} }
} }
@ -275,24 +274,23 @@ private val CardColor: CardColors
private val VerticalSpacerSize = 24.dp private val VerticalSpacerSize = 24.dp
private const val DownloadedIconContentId = "downloaded" private const val DownloadedIconContentId = "downloaded"
private fun previewChapter(name: String, scanlator: String, chapterNumber: Float) = ChapterImpl().apply { private fun previewChapter(name: String, scanlator: String, chapterNumber: Double) = Chapter.create().copy(
this.name = name id = 0L,
this.scanlator = scanlator mangaId = 0L,
this.chapter_number = chapterNumber url = "",
name = name,
this.id = 0 scanlator = scanlator,
this.manga_id = 0 chapterNumber = chapterNumber,
this.url = "" )
}
private val FakeChapter = previewChapter( private val FakeChapter = previewChapter(
name = "Vol.1, Ch.1 - Fake Chapter Title", name = "Vol.1, Ch.1 - Fake Chapter Title",
scanlator = "Scanlator Name", scanlator = "Scanlator Name",
chapterNumber = 1f, chapterNumber = 1.0,
) )
private val FakeGapChapter = previewChapter( private val FakeGapChapter = previewChapter(
name = "Vol.5, Ch.44 - Fake Gap Chapter Title", name = "Vol.5, Ch.44 - Fake Gap Chapter Title",
scanlator = "Scanlator Name", scanlator = "Scanlator Name",
chapterNumber = 44f, chapterNumber = 44.0,
) )
private val FakeChapterLongTitle = previewChapter( private val FakeChapterLongTitle = previewChapter(
name = "Vol.1, Ch.0 - The Mundane Musings of a Metafictional Manga: A Chapter About a Chapter, Featuring" + name = "Vol.1, Ch.0 - The Mundane Musings of a Metafictional Manga: A Chapter About a Chapter, Featuring" +
@ -301,7 +299,7 @@ private val FakeChapterLongTitle = previewChapter(
"Fictional Realities and Reality-Bending Fiction, Where the Fourth Wall is Always in Danger of Being Broken " + "Fictional Realities and Reality-Bending Fiction, Where the Fourth Wall is Always in Danger of Being Broken " +
"and the Line Between Author and Character is Forever Blurred.", "and the Line Between Author and Character is Forever Blurred.",
scanlator = "Long Long Funny Scanlator Sniper Group Name Reborn", scanlator = "Long Long Funny Scanlator Sniper Group Name Reborn",
chapterNumber = 1f, chapterNumber = 1.0,
) )
@PreviewLightDark @PreviewLightDark

View file

@ -13,7 +13,7 @@ internal class TrackInfoDialogHomePreviewProvider :
private val aTrack = Track( private val aTrack = Track(
id = 1L, id = 1L,
mangaId = 2L, mangaId = 2L,
syncId = 3L, trackerId = 3L,
remoteId = 4L, remoteId = 4L,
libraryId = null, libraryId = null,
title = "Manage Name On Tracker Site", title = "Manage Name On Tracker Site",

View file

@ -62,7 +62,7 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
private fun randTrackSearch() = TrackSearch().let { private fun randTrackSearch() = TrackSearch().let {
it.id = Random.nextLong() it.id = Random.nextLong()
it.manga_id = Random.nextLong() it.manga_id = Random.nextLong()
it.sync_id = Random.nextInt() it.tracker_id = Random.nextInt()
it.remote_id = Random.nextLong() it.remote_id = Random.nextLong()
it.library_id = Random.nextLong() it.library_id = Random.nextLong()
it.title = lorem((1..10).random()).joinToString() it.title = lorem((1..10).random()).joinToString()

View file

@ -346,12 +346,12 @@ class MangaRestorer(
} }
private suspend fun restoreTracking(manga: Manga, backupTracks: List<BackupTracking>) { private suspend fun restoreTracking(manga: Manga, backupTracks: List<BackupTracking>) {
val dbTrackBySyncId = getTracks.await(manga.id).associateBy { it.syncId } val dbTrackByTrackerId = getTracks.await(manga.id).associateBy { it.trackerId }
val (existingTracks, newTracks) = backupTracks val (existingTracks, newTracks) = backupTracks
.mapNotNull { .mapNotNull {
val track = it.getTrackImpl() val track = it.getTrackImpl()
val dbTrack = dbTrackBySyncId[track.syncId] val dbTrack = dbTrackByTrackerId[track.trackerId]
?: // New track ?: // New track
return@mapNotNull track.copy( return@mapNotNull track.copy(
id = 0, // Let DB assign new ID id = 0, // Let DB assign new ID
@ -380,7 +380,7 @@ class MangaRestorer(
existingTracks.forEach { track -> existingTracks.forEach { track ->
manga_syncQueries.update( manga_syncQueries.update(
track.mangaId, track.mangaId,
track.syncId, track.trackerId,
track.remoteId, track.remoteId,
track.libraryId, track.libraryId,
track.title, track.title,

View file

@ -8,7 +8,7 @@ interface Track : Serializable {
var manga_id: Long var manga_id: Long
var sync_id: Int var tracker_id: Int
var remote_id: Long var remote_id: Long
@ -40,7 +40,7 @@ interface Track : Serializable {
companion object { companion object {
fun create(serviceId: Long): Track = TrackImpl().apply { fun create(serviceId: Long): Track = TrackImpl().apply {
sync_id = serviceId.toInt() tracker_id = serviceId.toInt()
} }
} }
} }

View file

@ -6,7 +6,7 @@ class TrackImpl : Track {
override var manga_id: Long = 0 override var manga_id: Long = 0
override var sync_id: Int = 0 override var tracker_id: Int = 0
override var remote_id: Long = 0 override var remote_id: Long = 0

View file

@ -33,6 +33,4 @@ class TrackerManager {
fun loggedInTrackers() = trackers.filter { it.isLoggedIn } fun loggedInTrackers() = trackers.filter { it.isLoggedIn }
fun get(id: Long) = trackers.find { it.id == id } fun get(id: Long) = trackers.find { it.id == id }
fun hasLoggedIn() = trackers.any { it.isLoggedIn }
} }

View file

@ -8,7 +8,7 @@ class TrackSearch : Track {
override var manga_id: Long = 0 override var manga_id: Long = 0
override var sync_id: Int = 0 override var tracker_id: Int = 0
override var remote_id: Long = 0 override var remote_id: Long = 0
@ -47,7 +47,7 @@ class TrackSearch : Track {
other as TrackSearch other as TrackSearch
if (manga_id != other.manga_id) return false if (manga_id != other.manga_id) return false
if (sync_id != other.sync_id) return false if (tracker_id != other.tracker_id) return false
if (remote_id != other.remote_id) return false if (remote_id != other.remote_id) return false
return true return true
@ -55,14 +55,14 @@ class TrackSearch : Track {
override fun hashCode(): Int { override fun hashCode(): Int {
var result = manga_id.hashCode() var result = manga_id.hashCode()
result = 31 * result + sync_id result = 31 * result + tracker_id
result = 31 * result + remote_id.hashCode() result = 31 * result + remote_id.hashCode()
return result return result
} }
companion object { companion object {
fun create(serviceId: Long): TrackSearch = TrackSearch().apply { fun create(serviceId: Long): TrackSearch = TrackSearch().apply {
sync_id = serviceId.toInt() tracker_id = serviceId.toInt()
} }
} }
} }

View file

@ -217,7 +217,7 @@ class LibraryScreenModel(
if (isNotLoggedInAnyTrack || trackFiltersIsIgnored) return@tracking true if (isNotLoggedInAnyTrack || trackFiltersIsIgnored) return@tracking true
val mangaTracks = trackMap val mangaTracks = trackMap
.mapValues { entry -> entry.value.map { it.syncId } }[item.libraryManga.id] .mapValues { entry -> entry.value.map { it.trackerId } }[item.libraryManga.id]
.orEmpty() .orEmpty()
val isExcluded = excludedTracks.isNotEmpty() && mangaTracks.fastAny { it in excludedTracks } val isExcluded = excludedTracks.isNotEmpty() && mangaTracks.fastAny { it in excludedTracks }
@ -257,7 +257,7 @@ class LibraryScreenModel(
entry.value.isEmpty() -> null entry.value.isEmpty() -> null
else -> else ->
entry.value entry.value
.mapNotNull { trackerMap[it.syncId]?.get10PointScore(it) } .mapNotNull { trackerMap[it.trackerId]?.get10PointScore(it) }
.average() .average()
} }
} }

View file

@ -983,7 +983,7 @@ class MangaScreenModel(
.map { tracks -> .map { tracks ->
loggedInTrackers loggedInTrackers
// Map to TrackItem // Map to TrackItem
.map { service -> TrackItem(tracks.find { it.syncId == service.id }, service) } .map { service -> TrackItem(tracks.find { it.trackerId == service.id }, service) }
// Show only if the service supports this manga's source // Show only if the service supports this manga's source
.filter { (it.tracker as? EnhancedTracker)?.accept(source!!) ?: true } .filter { (it.tracker as? EnhancedTracker)?.accept(source!!) ?: true }
} }

View file

@ -244,7 +244,7 @@ data class TrackInfoDialogHomeScreen(
val source = Injekt.get<SourceManager>().getOrStub(sourceId) val source = Injekt.get<SourceManager>().getOrStub(sourceId)
return loggedInTrackers return loggedInTrackers
// Map to TrackItem // Map to TrackItem
.map { service -> TrackItem(find { it.syncId == service.id }, service) } .map { service -> TrackItem(find { it.trackerId == service.id }, service) }
// Show only if the service supports this manga's source // Show only if the service supports this manga's source
.filter { (it.tracker as? EnhancedTracker)?.accept(source) ?: true } .filter { (it.tracker as? EnhancedTracker)?.accept(source) ?: true }
} }

View file

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.reader.model package eu.kanade.tachiyomi.ui.reader.model
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.ui.reader.loader.PageLoader import eu.kanade.tachiyomi.ui.reader.loader.PageLoader
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -23,6 +24,8 @@ data class ReaderChapter(val chapter: Chapter) {
private var references = 0 private var references = 0
constructor(chapter: tachiyomi.domain.chapter.model.Chapter) : this(chapter.toDbChapter())
fun ref() { fun ref() {
references++ references++
} }

View file

@ -118,7 +118,7 @@ class StatsScreenModel(
val loggedInTrackerIds = loggedInTrackers.map { it.id }.toHashSet() val loggedInTrackerIds = loggedInTrackers.map { it.id }.toHashSet()
return libraryManga.associate { manga -> return libraryManga.associate { manga ->
val tracks = getTracks.await(manga.id) val tracks = getTracks.await(manga.id)
.fastFilter { it.syncId in loggedInTrackerIds } .fastFilter { it.trackerId in loggedInTrackerIds }
manga.id to tracks manga.id to tracks
} }
@ -144,7 +144,7 @@ class StatsScreenModel(
} }
private fun get10PointScore(track: Track): Double { private fun get10PointScore(track: Track): Double {
val service = trackerManager.get(track.syncId)!! val service = trackerManager.get(track.trackerId)!!
return service.get10PointScore(track) return service.get10PointScore(track)
} }
} }

View file

@ -20,7 +20,7 @@ object TrackMapper {
): Track = Track( ): Track = Track(
id = id, id = id,
mangaId = mangaId, mangaId = mangaId,
syncId = syncId, trackerId = syncId,
remoteId = remoteId, remoteId = remoteId,
libraryId = libraryId, libraryId = libraryId,
title = title, title = title,

View file

@ -31,11 +31,11 @@ class TrackRepositoryImpl(
} }
} }
override suspend fun delete(mangaId: Long, syncId: Long) { override suspend fun delete(mangaId: Long, trackerId: Long) {
handler.await { handler.await {
manga_syncQueries.delete( manga_syncQueries.delete(
mangaId = mangaId, mangaId = mangaId,
syncId = syncId, syncId = trackerId,
) )
} }
} }
@ -53,7 +53,7 @@ class TrackRepositoryImpl(
tracks.forEach { mangaTrack -> tracks.forEach { mangaTrack ->
manga_syncQueries.insert( manga_syncQueries.insert(
mangaId = mangaTrack.mangaId, mangaId = mangaTrack.mangaId,
syncId = mangaTrack.syncId, syncId = mangaTrack.trackerId,
remoteId = mangaTrack.remoteId, remoteId = mangaTrack.remoteId,
libraryId = mangaTrack.libraryId, libraryId = mangaTrack.libraryId,
title = mangaTrack.title, title = mangaTrack.title,

View file

@ -7,7 +7,6 @@ import tachiyomi.domain.track.model.Track
@Serializable @Serializable
data class BackupTracking( data class BackupTracking(
// in 1.x some of these values have different types or names // in 1.x some of these values have different types or names
// syncId is called siteId in 1,x
@ProtoNumber(1) var syncId: Int, @ProtoNumber(1) var syncId: Int,
// LibraryId is not null in 1.x // LibraryId is not null in 1.x
@ProtoNumber(2) var libraryId: Long, @ProtoNumber(2) var libraryId: Long,
@ -34,7 +33,7 @@ data class BackupTracking(
return Track( return Track(
id = -1, id = -1,
mangaId = -1, mangaId = -1,
syncId = this@BackupTracking.syncId.toLong(), trackerId = this@BackupTracking.syncId.toLong(),
remoteId = if (this@BackupTracking.mediaIdInt != 0) { remoteId = if (this@BackupTracking.mediaIdInt != 0) {
this@BackupTracking.mediaIdInt.toLong() this@BackupTracking.mediaIdInt.toLong()
} else { } else {

View file

@ -8,9 +8,9 @@ class DeleteTrack(
private val trackRepository: TrackRepository, private val trackRepository: TrackRepository,
) { ) {
suspend fun await(mangaId: Long, syncId: Long) { suspend fun await(mangaId: Long, trackerId: Long) {
try { try {
trackRepository.delete(mangaId, syncId) trackRepository.delete(mangaId, trackerId)
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.ERROR, e) logcat(LogPriority.ERROR, e)
} }

View file

@ -3,7 +3,7 @@ package tachiyomi.domain.track.model
data class Track( data class Track(
val id: Long, val id: Long,
val mangaId: Long, val mangaId: Long,
val syncId: Long, val trackerId: Long,
val remoteId: Long, val remoteId: Long,
val libraryId: Long?, val libraryId: Long?,
val title: String, val title: String,

View file

@ -13,7 +13,7 @@ interface TrackRepository {
fun getTracksByMangaIdAsFlow(mangaId: Long): Flow<List<Track>> fun getTracksByMangaIdAsFlow(mangaId: Long): Flow<List<Track>>
suspend fun delete(mangaId: Long, syncId: Long) suspend fun delete(mangaId: Long, trackerId: Long)
suspend fun insert(track: Track) suspend fun insert(track: Track)