Tracker-related cleanup
This commit is contained in:
parent
86edce0d87
commit
c8e226acb2
54 changed files with 417 additions and 395 deletions
|
@ -1,7 +1,6 @@
|
||||||
package eu.kanade.domain
|
package eu.kanade.domain
|
||||||
|
|
||||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.download.interactor.DeleteDownload
|
import eu.kanade.domain.download.interactor.DeleteDownload
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
||||||
|
@ -16,7 +15,9 @@ import eu.kanade.domain.source.interactor.SetMigrateSorting
|
||||||
import eu.kanade.domain.source.interactor.ToggleLanguage
|
import eu.kanade.domain.source.interactor.ToggleLanguage
|
||||||
import eu.kanade.domain.source.interactor.ToggleSource
|
import eu.kanade.domain.source.interactor.ToggleSource
|
||||||
import eu.kanade.domain.source.interactor.ToggleSourcePin
|
import eu.kanade.domain.source.interactor.ToggleSourcePin
|
||||||
|
import eu.kanade.domain.track.interactor.AddTracks
|
||||||
import eu.kanade.domain.track.interactor.RefreshTracks
|
import eu.kanade.domain.track.interactor.RefreshTracks
|
||||||
|
import eu.kanade.domain.track.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.track.interactor.TrackChapter
|
import eu.kanade.domain.track.interactor.TrackChapter
|
||||||
import tachiyomi.data.category.CategoryRepositoryImpl
|
import tachiyomi.data.category.CategoryRepositoryImpl
|
||||||
import tachiyomi.data.chapter.ChapterRepositoryImpl
|
import tachiyomi.data.chapter.ChapterRepositoryImpl
|
||||||
|
@ -114,11 +115,13 @@ class DomainModule : InjektModule {
|
||||||
|
|
||||||
addSingletonFactory<TrackRepository> { TrackRepositoryImpl(get()) }
|
addSingletonFactory<TrackRepository> { TrackRepositoryImpl(get()) }
|
||||||
addFactory { TrackChapter(get(), get(), get(), get()) }
|
addFactory { TrackChapter(get(), get(), get(), get()) }
|
||||||
|
addFactory { AddTracks(get(), get(), get()) }
|
||||||
addFactory { RefreshTracks(get(), get(), get(), get()) }
|
addFactory { RefreshTracks(get(), get(), get(), get()) }
|
||||||
addFactory { DeleteTrack(get()) }
|
addFactory { DeleteTrack(get()) }
|
||||||
addFactory { GetTracksPerManga(get()) }
|
addFactory { GetTracksPerManga(get()) }
|
||||||
addFactory { GetTracks(get()) }
|
addFactory { GetTracks(get()) }
|
||||||
addFactory { InsertTrack(get()) }
|
addFactory { InsertTrack(get()) }
|
||||||
|
addFactory { SyncChapterProgressWithTrack(get(), get(), get()) }
|
||||||
|
|
||||||
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
|
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
|
||||||
addFactory { GetChapter(get()) }
|
addFactory { GetChapter(get()) }
|
||||||
|
@ -127,7 +130,6 @@ class DomainModule : InjektModule {
|
||||||
addFactory { SetReadStatus(get(), get(), get(), get()) }
|
addFactory { SetReadStatus(get(), get(), get(), get()) }
|
||||||
addFactory { ShouldUpdateDbChapter() }
|
addFactory { ShouldUpdateDbChapter() }
|
||||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) }
|
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) }
|
||||||
addFactory { SyncChapterProgressWithTrack(get(), get(), get()) }
|
|
||||||
|
|
||||||
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
||||||
addFactory { GetHistory(get()) }
|
addFactory { GetHistory(get()) }
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package eu.kanade.domain.track.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.track.model.toDomainTrack
|
||||||
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
import logcat.LogPriority
|
||||||
|
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||||
|
import tachiyomi.core.util.system.logcat
|
||||||
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
|
import tachiyomi.domain.track.interactor.InsertTrack
|
||||||
|
|
||||||
|
class AddTracks(
|
||||||
|
private val getTracks: GetTracks,
|
||||||
|
private val insertTrack: InsertTrack,
|
||||||
|
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun bindEnhancedTracks(manga: Manga, source: Source) {
|
||||||
|
withNonCancellableContext {
|
||||||
|
getTracks.await(manga.id)
|
||||||
|
.filterIsInstance<EnhancedTracker>()
|
||||||
|
.filter { it.accept(source) }
|
||||||
|
.forEach { service ->
|
||||||
|
try {
|
||||||
|
service.match(manga)?.let { track ->
|
||||||
|
track.manga_id = manga.id
|
||||||
|
(service as Tracker).bind(track)
|
||||||
|
insertTrack.await(track.toDomainTrack()!!)
|
||||||
|
|
||||||
|
syncChapterProgressWithTrack.await(
|
||||||
|
manga.id,
|
||||||
|
track.toDomainTrack()!!,
|
||||||
|
service,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(
|
||||||
|
LogPriority.WARN,
|
||||||
|
e,
|
||||||
|
) { "Could not match manga: ${manga.title} with service $service" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
package eu.kanade.domain.track.interactor
|
package eu.kanade.domain.track.interactor
|
||||||
|
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
import eu.kanade.domain.track.model.toDomainTrack
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
|
@ -13,7 +12,7 @@ import tachiyomi.domain.track.interactor.InsertTrack
|
||||||
|
|
||||||
class RefreshTracks(
|
class RefreshTracks(
|
||||||
private val getTracks: GetTracks,
|
private val getTracks: GetTracks,
|
||||||
private val trackManager: TrackManager,
|
private val trackerManager: TrackerManager,
|
||||||
private val insertTrack: InsertTrack,
|
private val insertTrack: InsertTrack,
|
||||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
||||||
) {
|
) {
|
||||||
|
@ -23,18 +22,17 @@ class RefreshTracks(
|
||||||
*
|
*
|
||||||
* @return Failed updates.
|
* @return Failed updates.
|
||||||
*/
|
*/
|
||||||
suspend fun await(mangaId: Long): List<Pair<TrackService?, 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 { track ->
|
.map { it to trackerManager.get(it.syncId) }
|
||||||
|
.filter { (_, service) -> service?.isLoggedIn == true }
|
||||||
|
.map { (track, service) ->
|
||||||
async {
|
async {
|
||||||
val service = trackManager.getService(track.syncId)
|
|
||||||
return@async try {
|
return@async try {
|
||||||
if (service?.isLoggedIn == true) {
|
val updatedTrack = service!!.refresh(track.toDbTrack())
|
||||||
val updatedTrack = service.refresh(track.toDbTrack())
|
|
||||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||||
syncChapterProgressWithTrack.await(mangaId, track, service)
|
syncChapterProgressWithTrack.await(mangaId, track, service)
|
||||||
}
|
|
||||||
null
|
null
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
service to e
|
service to e
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package eu.kanade.domain.chapter.interactor
|
package eu.kanade.domain.track.interactor
|
||||||
|
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
import tachiyomi.domain.chapter.interactor.GetChapterByMangaId
|
import tachiyomi.domain.chapter.interactor.GetChapterByMangaId
|
||||||
|
@ -20,9 +20,9 @@ class SyncChapterProgressWithTrack(
|
||||||
suspend fun await(
|
suspend fun await(
|
||||||
mangaId: Long,
|
mangaId: Long,
|
||||||
remoteTrack: Track,
|
remoteTrack: Track,
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
) {
|
) {
|
||||||
if (service !is EnhancedTrackService) {
|
if (tracker !is EnhancedTracker) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ class SyncChapterProgressWithTrack(
|
||||||
val updatedTrack = remoteTrack.copy(lastChapterRead = localLastRead.toDouble())
|
val updatedTrack = remoteTrack.copy(lastChapterRead = localLastRead.toDouble())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
service.update(updatedTrack.toDbTrack())
|
tracker.update(updatedTrack.toDbTrack())
|
||||||
updateChapter.awaitAll(chapterUpdates)
|
updateChapter.awaitAll(chapterUpdates)
|
||||||
insertTrack.await(updatedTrack)
|
insertTrack.await(updatedTrack)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
|
@ -4,30 +4,29 @@ import android.content.Context
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.service.DelayedTrackingUpdateJob
|
import eu.kanade.domain.track.service.DelayedTrackingUpdateJob
|
||||||
import eu.kanade.domain.track.store.DelayedTrackingStore
|
import eu.kanade.domain.track.store.DelayedTrackingStore
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.coroutineScope
|
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.util.lang.launchNonCancellable
|
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
import tachiyomi.domain.track.interactor.GetTracks
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
import tachiyomi.domain.track.interactor.InsertTrack
|
import tachiyomi.domain.track.interactor.InsertTrack
|
||||||
|
|
||||||
class TrackChapter(
|
class TrackChapter(
|
||||||
private val getTracks: GetTracks,
|
private val getTracks: GetTracks,
|
||||||
private val trackManager: TrackManager,
|
private val trackerManager: TrackerManager,
|
||||||
private val insertTrack: InsertTrack,
|
private val insertTrack: InsertTrack,
|
||||||
private val delayedTrackingStore: DelayedTrackingStore,
|
private val delayedTrackingStore: DelayedTrackingStore,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) = coroutineScope {
|
suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) {
|
||||||
launchNonCancellable {
|
withNonCancellableContext {
|
||||||
val tracks = getTracks.await(mangaId)
|
val tracks = getTracks.await(mangaId)
|
||||||
if (tracks.isEmpty()) return@launchNonCancellable
|
if (tracks.isEmpty()) return@withNonCancellableContext
|
||||||
|
|
||||||
tracks.mapNotNull { track ->
|
tracks.mapNotNull { track ->
|
||||||
val service = trackManager.getService(track.syncId)
|
val service = trackerManager.get(track.syncId)
|
||||||
if (service == null || !service.isLoggedIn || chapterNumber <= track.lastChapterRead) {
|
if (service == null || !service.isLoggedIn || chapterNumber <= track.lastChapterRead) {
|
||||||
return@mapNotNull null
|
return@mapNotNull null
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.store.DelayedTrackingStore
|
import eu.kanade.domain.track.store.DelayedTrackingStore
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.util.system.workManager
|
import eu.kanade.tachiyomi.util.system.workManager
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
|
@ -33,7 +33,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
|
||||||
val getTracks = Injekt.get<GetTracks>()
|
val getTracks = Injekt.get<GetTracks>()
|
||||||
val insertTrack = Injekt.get<InsertTrack>()
|
val insertTrack = Injekt.get<InsertTrack>()
|
||||||
|
|
||||||
val trackManager = Injekt.get<TrackManager>()
|
val trackerManager = Injekt.get<TrackerManager>()
|
||||||
val delayedTrackingStore = Injekt.get<DelayedTrackingStore>()
|
val delayedTrackingStore = Injekt.get<DelayedTrackingStore>()
|
||||||
|
|
||||||
withIOContext {
|
withIOContext {
|
||||||
|
@ -47,7 +47,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
|
||||||
}
|
}
|
||||||
.forEach { track ->
|
.forEach { track ->
|
||||||
try {
|
try {
|
||||||
val service = trackManager.getService(track.syncId)
|
val service = trackerManager.get(track.syncId)
|
||||||
if (service != null && service.isLoggedIn) {
|
if (service != null && service.isLoggedIn) {
|
||||||
logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.id}, last chapter read: ${track.lastChapterRead}" }
|
logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.id}, last chapter read: ${track.lastChapterRead}" }
|
||||||
service.update(track.toDbTrack(), true)
|
service.update(track.toDbTrack(), true)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.domain.track.service
|
package eu.kanade.domain.track.service
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
||||||
import tachiyomi.core.preference.PreferenceStore
|
import tachiyomi.core.preference.PreferenceStore
|
||||||
|
|
||||||
|
@ -8,16 +8,16 @@ class TrackPreferences(
|
||||||
private val preferenceStore: PreferenceStore,
|
private val preferenceStore: PreferenceStore,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun trackUsername(sync: TrackService) = preferenceStore.getString(trackUsername(sync.id), "")
|
fun trackUsername(sync: Tracker) = preferenceStore.getString(trackUsername(sync.id), "")
|
||||||
|
|
||||||
fun trackPassword(sync: TrackService) = preferenceStore.getString(trackPassword(sync.id), "")
|
fun trackPassword(sync: Tracker) = preferenceStore.getString(trackPassword(sync.id), "")
|
||||||
|
|
||||||
fun setTrackCredentials(sync: TrackService, username: String, password: String) {
|
fun setCredentials(sync: Tracker, username: String, password: String) {
|
||||||
trackUsername(sync).set(username)
|
trackUsername(sync).set(username)
|
||||||
trackPassword(sync).set(password)
|
trackPassword(sync).set(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trackToken(sync: TrackService) = preferenceStore.getString(trackToken(sync.id), "")
|
fun trackToken(sync: Tracker) = preferenceStore.getString(trackToken(sync.id), "")
|
||||||
|
|
||||||
fun anilistScoreType() = preferenceStore.getString("anilist_score_type", Anilist.POINT_10)
|
fun anilistScoreType() = preferenceStore.getString("anilist_score_type", Anilist.POINT_10)
|
||||||
|
|
||||||
|
|
|
@ -108,13 +108,13 @@ private fun ColumnScope.FilterPage(
|
||||||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompleted) },
|
onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompleted) },
|
||||||
)
|
)
|
||||||
|
|
||||||
val trackServices = remember { screenModel.trackServices }
|
val trackers = remember { screenModel.trackers }
|
||||||
when (trackServices.size) {
|
when (trackers.size) {
|
||||||
0 -> {
|
0 -> {
|
||||||
// No trackers
|
// No trackers
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
val service = trackServices[0]
|
val service = trackers[0]
|
||||||
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
|
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
|
||||||
TriStateItem(
|
TriStateItem(
|
||||||
label = stringResource(R.string.action_filter_tracked),
|
label = stringResource(R.string.action_filter_tracked),
|
||||||
|
@ -124,7 +124,7 @@ private fun ColumnScope.FilterPage(
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
HeadingItem(R.string.action_filter_tracked)
|
HeadingItem(R.string.action_filter_tracked)
|
||||||
trackServices.map { service ->
|
trackers.map { service ->
|
||||||
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
|
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
|
||||||
TriStateItem(
|
TriStateItem(
|
||||||
label = service.name,
|
label = service.name,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import tachiyomi.core.preference.Preference as PreferenceData
|
import tachiyomi.core.preference.Preference as PreferenceData
|
||||||
|
|
||||||
sealed class Preference {
|
sealed class Preference {
|
||||||
|
@ -132,10 +132,10 @@ sealed class Preference {
|
||||||
) : PreferenceItem<String>()
|
) : PreferenceItem<String>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [PreferenceItem] for individual tracking service.
|
* A [PreferenceItem] for individual tracker.
|
||||||
*/
|
*/
|
||||||
data class TrackingPreference(
|
data class TrackerPreference(
|
||||||
val service: TrackService,
|
val tracker: Tracker,
|
||||||
override val title: String,
|
override val title: String,
|
||||||
val login: () -> Unit,
|
val login: () -> Unit,
|
||||||
val logout: () -> Unit,
|
val logout: () -> Unit,
|
||||||
|
|
|
@ -156,13 +156,13 @@ internal fun PreferenceItem(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is Preference.PreferenceItem.TrackingPreference -> {
|
is Preference.PreferenceItem.TrackerPreference -> {
|
||||||
val uName by Injekt.get<PreferenceStore>()
|
val uName by Injekt.get<PreferenceStore>()
|
||||||
.getString(TrackPreferences.trackUsername(item.service.id))
|
.getString(TrackPreferences.trackUsername(item.tracker.id))
|
||||||
.collectAsState()
|
.collectAsState()
|
||||||
item.service.run {
|
item.tracker.run {
|
||||||
TrackingPreferenceWidget(
|
TrackingPreferenceWidget(
|
||||||
service = this,
|
tracker = this,
|
||||||
checked = uName.isNotEmpty(),
|
checked = uName.isNotEmpty(),
|
||||||
onClick = { if (isLoggedIn) item.logout() else item.login() },
|
onClick = { if (isLoggedIn) item.logout() else item.login() },
|
||||||
)
|
)
|
||||||
|
|
|
@ -34,7 +34,7 @@ import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||||
import eu.kanade.tachiyomi.network.PREF_DOH_360
|
import eu.kanade.tachiyomi.network.PREF_DOH_360
|
||||||
|
@ -328,7 +328,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||||
private fun getLibraryGroup(): Preference.PreferenceGroup {
|
private fun getLibraryGroup(): Preference.PreferenceGroup {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val trackManager = remember { Injekt.get<TrackManager>() }
|
val trackerManager = remember { Injekt.get<TrackerManager>() }
|
||||||
|
|
||||||
return Preference.PreferenceGroup(
|
return Preference.PreferenceGroup(
|
||||||
title = stringResource(R.string.label_library),
|
title = stringResource(R.string.label_library),
|
||||||
|
@ -340,7 +340,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = stringResource(R.string.pref_refresh_library_tracking),
|
title = stringResource(R.string.pref_refresh_library_tracking),
|
||||||
subtitle = stringResource(R.string.pref_refresh_library_tracking_summary),
|
subtitle = stringResource(R.string.pref_refresh_library_tracking_summary),
|
||||||
enabled = trackManager.hasLoggedServices(),
|
enabled = trackerManager.hasLoggedIn(),
|
||||||
onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.TRACKING) },
|
onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.TRACKING) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
|
|
|
@ -23,7 +23,7 @@ import eu.kanade.presentation.more.settings.Preference
|
||||||
import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
@ -199,7 +199,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
pref = libraryPreferences.autoUpdateTrackers(),
|
pref = libraryPreferences.autoUpdateTrackers(),
|
||||||
enabled = Injekt.get<TrackManager>().hasLoggedServices(),
|
enabled = Injekt.get<TrackerManager>().hasLoggedIn(),
|
||||||
title = stringResource(R.string.pref_library_update_refresh_trackers),
|
title = stringResource(R.string.pref_library_update_refresh_trackers),
|
||||||
subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
|
subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,9 +44,9 @@ import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.domain.track.service.TrackPreferences
|
import eu.kanade.domain.track.service.TrackPreferences
|
||||||
import eu.kanade.presentation.more.settings.Preference
|
import eu.kanade.presentation.more.settings.Preference
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.data.track.anilist.AnilistApi
|
import eu.kanade.tachiyomi.data.track.anilist.AnilistApi
|
||||||
import eu.kanade.tachiyomi.data.track.bangumi.BangumiApi
|
import eu.kanade.tachiyomi.data.track.bangumi.BangumiApi
|
||||||
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeListApi
|
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeListApi
|
||||||
|
@ -82,7 +82,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
override fun getPreferences(): List<Preference> {
|
override fun getPreferences(): List<Preference> {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val trackPreferences = remember { Injekt.get<TrackPreferences>() }
|
val trackPreferences = remember { Injekt.get<TrackPreferences>() }
|
||||||
val trackManager = remember { Injekt.get<TrackManager>() }
|
val trackerManager = remember { Injekt.get<TrackerManager>() }
|
||||||
val sourceManager = remember { Injekt.get<SourceManager>() }
|
val sourceManager = remember { Injekt.get<SourceManager>() }
|
||||||
|
|
||||||
var dialog by remember { mutableStateOf<Any?>(null) }
|
var dialog by remember { mutableStateOf<Any?>(null) }
|
||||||
|
@ -90,24 +90,24 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
when (this) {
|
when (this) {
|
||||||
is LoginDialog -> {
|
is LoginDialog -> {
|
||||||
TrackingLoginDialog(
|
TrackingLoginDialog(
|
||||||
service = service,
|
tracker = tracker,
|
||||||
uNameStringRes = uNameStringRes,
|
uNameStringRes = uNameStringRes,
|
||||||
onDismissRequest = { dialog = null },
|
onDismissRequest = { dialog = null },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is LogoutDialog -> {
|
is LogoutDialog -> {
|
||||||
TrackingLogoutDialog(
|
TrackingLogoutDialog(
|
||||||
service = service,
|
tracker = tracker,
|
||||||
onDismissRequest = { dialog = null },
|
onDismissRequest = { dialog = null },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val enhancedTrackers = trackManager.services
|
val enhancedTrackers = trackerManager.trackers
|
||||||
.filter { it is EnhancedTrackService }
|
.filter { it is EnhancedTracker }
|
||||||
.partition { service ->
|
.partition { service ->
|
||||||
val acceptedSources = (service as EnhancedTrackService).getAcceptedSources()
|
val acceptedSources = (service as EnhancedTracker).getAcceptedSources()
|
||||||
sourceManager.getCatalogueSources().any { it::class.qualifiedName in acceptedSources }
|
sourceManager.getCatalogueSources().any { it::class.qualifiedName in acceptedSources }
|
||||||
}
|
}
|
||||||
var enhancedTrackerInfo = stringResource(R.string.enhanced_tracking_info)
|
var enhancedTrackerInfo = stringResource(R.string.enhanced_tracking_info)
|
||||||
|
@ -127,41 +127,41 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
Preference.PreferenceGroup(
|
Preference.PreferenceGroup(
|
||||||
title = stringResource(R.string.services),
|
title = stringResource(R.string.services),
|
||||||
preferenceItems = listOf(
|
preferenceItems = listOf(
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = trackManager.myAnimeList.name,
|
title = trackerManager.myAnimeList.name,
|
||||||
service = trackManager.myAnimeList,
|
tracker = trackerManager.myAnimeList,
|
||||||
login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.myAnimeList) },
|
logout = { dialog = LogoutDialog(trackerManager.myAnimeList) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = trackManager.aniList.name,
|
title = trackerManager.aniList.name,
|
||||||
service = trackManager.aniList,
|
tracker = trackerManager.aniList,
|
||||||
login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.aniList) },
|
logout = { dialog = LogoutDialog(trackerManager.aniList) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = trackManager.kitsu.name,
|
title = trackerManager.kitsu.name,
|
||||||
service = trackManager.kitsu,
|
tracker = trackerManager.kitsu,
|
||||||
login = { dialog = LoginDialog(trackManager.kitsu, R.string.email) },
|
login = { dialog = LoginDialog(trackerManager.kitsu, R.string.email) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.kitsu) },
|
logout = { dialog = LogoutDialog(trackerManager.kitsu) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = trackManager.mangaUpdates.name,
|
title = trackerManager.mangaUpdates.name,
|
||||||
service = trackManager.mangaUpdates,
|
tracker = trackerManager.mangaUpdates,
|
||||||
login = { dialog = LoginDialog(trackManager.mangaUpdates, R.string.username) },
|
login = { dialog = LoginDialog(trackerManager.mangaUpdates, R.string.username) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.mangaUpdates) },
|
logout = { dialog = LogoutDialog(trackerManager.mangaUpdates) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = trackManager.shikimori.name,
|
title = trackerManager.shikimori.name,
|
||||||
service = trackManager.shikimori,
|
tracker = trackerManager.shikimori,
|
||||||
login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.shikimori) },
|
logout = { dialog = LogoutDialog(trackerManager.shikimori) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = trackManager.bangumi.name,
|
title = trackerManager.bangumi.name,
|
||||||
service = trackManager.bangumi,
|
tracker = trackerManager.bangumi,
|
||||||
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.bangumi) },
|
logout = { dialog = LogoutDialog(trackerManager.bangumi) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.tracking_info)),
|
Preference.PreferenceItem.InfoPreference(stringResource(R.string.tracking_info)),
|
||||||
),
|
),
|
||||||
|
@ -170,10 +170,10 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
title = stringResource(R.string.enhanced_services),
|
title = stringResource(R.string.enhanced_services),
|
||||||
preferenceItems = enhancedTrackers.first
|
preferenceItems = enhancedTrackers.first
|
||||||
.map { service ->
|
.map { service ->
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackerPreference(
|
||||||
title = service.name,
|
title = service.name,
|
||||||
service = service,
|
tracker = service,
|
||||||
login = { (service as EnhancedTrackService).loginNoop() },
|
login = { (service as EnhancedTracker).loginNoop() },
|
||||||
logout = service::logout,
|
logout = service::logout,
|
||||||
)
|
)
|
||||||
} + listOf(Preference.PreferenceItem.InfoPreference(enhancedTrackerInfo)),
|
} + listOf(Preference.PreferenceItem.InfoPreference(enhancedTrackerInfo)),
|
||||||
|
@ -183,15 +183,15 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TrackingLoginDialog(
|
private fun TrackingLoginDialog(
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
@StringRes uNameStringRes: Int,
|
@StringRes uNameStringRes: Int,
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
var username by remember { mutableStateOf(TextFieldValue(service.getUsername())) }
|
var username by remember { mutableStateOf(TextFieldValue(tracker.getUsername())) }
|
||||||
var password by remember { mutableStateOf(TextFieldValue(service.getPassword())) }
|
var password by remember { mutableStateOf(TextFieldValue(tracker.getPassword())) }
|
||||||
var processing by remember { mutableStateOf(false) }
|
var processing by remember { mutableStateOf(false) }
|
||||||
var inputError by remember { mutableStateOf(false) }
|
var inputError by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
title = {
|
title = {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.login_title, service.name),
|
text = stringResource(R.string.login_title, tracker.name),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
IconButton(onClick = onDismissRequest) {
|
IconButton(onClick = onDismissRequest) {
|
||||||
|
@ -264,7 +264,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
processing = true
|
processing = true
|
||||||
val result = checkLogin(
|
val result = checkLogin(
|
||||||
context = context,
|
context = context,
|
||||||
service = service,
|
tracker = tracker,
|
||||||
username = username.text,
|
username = username.text,
|
||||||
password = password.text,
|
password = password.text,
|
||||||
)
|
)
|
||||||
|
@ -283,16 +283,16 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
|
|
||||||
private suspend fun checkLogin(
|
private suspend fun checkLogin(
|
||||||
context: Context,
|
context: Context,
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return try {
|
return try {
|
||||||
service.login(username, password)
|
tracker.login(username, password)
|
||||||
withUIContext { context.toast(R.string.login_success) }
|
withUIContext { context.toast(R.string.login_success) }
|
||||||
true
|
true
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
service.logout()
|
tracker.logout()
|
||||||
withUIContext { context.toast(e.message.toString()) }
|
withUIContext { context.toast(e.message.toString()) }
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TrackingLogoutDialog(
|
private fun TrackingLogoutDialog(
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
@ -308,7 +308,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.logout_title, service.name),
|
text = stringResource(R.string.logout_title, tracker.name),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
@ -324,7 +324,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
onClick = {
|
onClick = {
|
||||||
service.logout()
|
tracker.logout()
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
context.toast(R.string.logout_success)
|
context.toast(R.string.logout_success)
|
||||||
},
|
},
|
||||||
|
@ -342,10 +342,10 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class LoginDialog(
|
private data class LoginDialog(
|
||||||
val service: TrackService,
|
val tracker: Tracker,
|
||||||
@StringRes val uNameStringRes: Int,
|
@StringRes val uNameStringRes: Int,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class LogoutDialog(
|
private data class LogoutDialog(
|
||||||
val service: TrackService,
|
val tracker: Tracker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,12 +20,12 @@ import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
|
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
|
||||||
import eu.kanade.presentation.track.components.TrackLogoIcon
|
import eu.kanade.presentation.track.components.TrackLogoIcon
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TrackingPreferenceWidget(
|
fun TrackingPreferenceWidget(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
|
@ -38,9 +38,9 @@ fun TrackingPreferenceWidget(
|
||||||
.padding(horizontal = PrefsHorizontalPadding, vertical = 8.dp),
|
.padding(horizontal = PrefsHorizontalPadding, vertical = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
TrackLogoIcon(service)
|
TrackLogoIcon(tracker)
|
||||||
Text(
|
Text(
|
||||||
text = service.name,
|
text = tracker.name,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
|
|
|
@ -49,7 +49,7 @@ import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.presentation.components.DropdownMenu
|
import eu.kanade.presentation.components.DropdownMenu
|
||||||
import eu.kanade.presentation.track.components.TrackLogoIcon
|
import eu.kanade.presentation.track.components.TrackLogoIcon
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
|
@ -80,12 +80,12 @@ fun TrackInfoDialogHome(
|
||||||
) {
|
) {
|
||||||
trackItems.forEach { item ->
|
trackItems.forEach { item ->
|
||||||
if (item.track != null) {
|
if (item.track != null) {
|
||||||
val supportsScoring = item.service.getScoreList().isNotEmpty()
|
val supportsScoring = item.tracker.getScoreList().isNotEmpty()
|
||||||
val supportsReadingDates = item.service.supportsReadingDates
|
val supportsReadingDates = item.tracker.supportsReadingDates
|
||||||
TrackInfoItem(
|
TrackInfoItem(
|
||||||
title = item.track.title,
|
title = item.track.title,
|
||||||
service = item.service,
|
tracker = item.tracker,
|
||||||
status = item.service.getStatus(item.track.status.toInt()),
|
status = item.tracker.getStatus(item.track.status.toInt()),
|
||||||
onStatusClick = { onStatusClick(item) },
|
onStatusClick = { onStatusClick(item) },
|
||||||
chapters = "${item.track.lastChapterRead.toInt()}".let {
|
chapters = "${item.track.lastChapterRead.toInt()}".let {
|
||||||
val totalChapters = item.track.totalChapters
|
val totalChapters = item.track.totalChapters
|
||||||
|
@ -97,7 +97,7 @@ fun TrackInfoDialogHome(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onChaptersClick = { onChapterClick(item) },
|
onChaptersClick = { onChapterClick(item) },
|
||||||
score = item.service.displayScore(item.track.toDbTrack())
|
score = item.tracker.displayScore(item.track.toDbTrack())
|
||||||
.takeIf { supportsScoring && item.track.score != 0.0 },
|
.takeIf { supportsScoring && item.track.score != 0.0 },
|
||||||
onScoreClick = { onScoreClick(item) }
|
onScoreClick = { onScoreClick(item) }
|
||||||
.takeIf { supportsScoring },
|
.takeIf { supportsScoring },
|
||||||
|
@ -115,7 +115,7 @@ fun TrackInfoDialogHome(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
TrackInfoItemEmpty(
|
TrackInfoItemEmpty(
|
||||||
service = item.service,
|
tracker = item.tracker,
|
||||||
onNewSearch = { onNewSearch(item) },
|
onNewSearch = { onNewSearch(item) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ fun TrackInfoDialogHome(
|
||||||
@Composable
|
@Composable
|
||||||
private fun TrackInfoItem(
|
private fun TrackInfoItem(
|
||||||
title: String,
|
title: String,
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
@StringRes status: Int?,
|
@StringRes status: Int?,
|
||||||
onStatusClick: () -> Unit,
|
onStatusClick: () -> Unit,
|
||||||
chapters: String,
|
chapters: String,
|
||||||
|
@ -147,7 +147,7 @@ private fun TrackInfoItem(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
TrackLogoIcon(
|
TrackLogoIcon(
|
||||||
service = service,
|
tracker = tracker,
|
||||||
onClick = onOpenInBrowser,
|
onClick = onOpenInBrowser,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
|
@ -260,13 +260,13 @@ private fun TrackDetailsItem(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TrackInfoItemEmpty(
|
private fun TrackInfoItemEmpty(
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
onNewSearch: () -> Unit,
|
onNewSearch: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
TrackLogoIcon(service)
|
TrackLogoIcon(tracker)
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = onNewSearch,
|
onClick = onNewSearch,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
|
@ -70,7 +70,7 @@ import tachiyomi.presentation.core.util.runOnEnterKeyPressed
|
||||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TrackServiceSearch(
|
fun TrackerSearch(
|
||||||
query: TextFieldValue,
|
query: TextFieldValue,
|
||||||
onQueryChange: (TextFieldValue) -> Unit,
|
onQueryChange: (TextFieldValue) -> Unit,
|
||||||
onDispatchQuery: () -> Unit,
|
onDispatchQuery: () -> Unit,
|
|
@ -12,12 +12,12 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import tachiyomi.presentation.core.util.clickableNoIndication
|
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TrackLogoIcon(
|
fun TrackLogoIcon(
|
||||||
service: TrackService,
|
tracker: Tracker,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val modifier = if (onClick != null) {
|
val modifier = if (onClick != null) {
|
||||||
|
@ -29,13 +29,13 @@ fun TrackLogoIcon(
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.size(48.dp)
|
.size(48.dp)
|
||||||
.background(color = Color(service.getLogoColor()), shape = MaterialTheme.shapes.medium)
|
.background(color = Color(tracker.getLogoColor()), shape = MaterialTheme.shapes.medium)
|
||||||
.padding(4.dp),
|
.padding(4.dp),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(service.getLogo()),
|
painter = painterResource(tracker.getLogo()),
|
||||||
contentDescription = service.name,
|
contentDescription = tracker.name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
||||||
import eu.kanade.tachiyomi.data.saver.ImageSaver
|
import eu.kanade.tachiyomi.data.saver.ImageSaver
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||||
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
@ -132,7 +132,7 @@ class AppModule(val app: Application) : InjektModule {
|
||||||
addSingletonFactory { DownloadManager(app) }
|
addSingletonFactory { DownloadManager(app) }
|
||||||
addSingletonFactory { DownloadCache(app) }
|
addSingletonFactory { DownloadCache(app) }
|
||||||
|
|
||||||
addSingletonFactory { TrackManager(app) }
|
addSingletonFactory { TrackerManager() }
|
||||||
addSingletonFactory { DelayedTrackingStore(app) }
|
addSingletonFactory { DelayedTrackingStore(app) }
|
||||||
|
|
||||||
addSingletonFactory { ImageSaver(app) }
|
addSingletonFactory { ImageSaver(app) }
|
||||||
|
|
|
@ -9,7 +9,7 @@ import eu.kanade.domain.ui.UiPreferences
|
||||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||||
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
||||||
|
@ -47,7 +47,7 @@ object Migrations {
|
||||||
libraryPreferences: LibraryPreferences,
|
libraryPreferences: LibraryPreferences,
|
||||||
readerPreferences: ReaderPreferences,
|
readerPreferences: ReaderPreferences,
|
||||||
backupPreferences: BackupPreferences,
|
backupPreferences: BackupPreferences,
|
||||||
trackManager: TrackManager,
|
trackerManager: TrackerManager,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val lastVersionCode = preferenceStore.getInt("last_version_code", 0)
|
val lastVersionCode = preferenceStore.getInt("last_version_code", 0)
|
||||||
val oldVersion = lastVersionCode.get()
|
val oldVersion = lastVersionCode.get()
|
||||||
|
@ -135,8 +135,8 @@ object Migrations {
|
||||||
// Force MAL log out due to login flow change
|
// Force MAL log out due to login flow change
|
||||||
// v52: switched from scraping to WebView
|
// v52: switched from scraping to WebView
|
||||||
// v53: switched from WebView to OAuth
|
// v53: switched from WebView to OAuth
|
||||||
if (trackManager.myAnimeList.isLoggedIn) {
|
if (trackerManager.myAnimeList.isLoggedIn) {
|
||||||
trackManager.myAnimeList.logout()
|
trackerManager.myAnimeList.logout()
|
||||||
context.toast(R.string.myanimelist_relogin)
|
context.toast(R.string.myanimelist_relogin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ object Migrations {
|
||||||
"pref_filter_library_started",
|
"pref_filter_library_started",
|
||||||
"pref_filter_library_bookmarked",
|
"pref_filter_library_bookmarked",
|
||||||
"pref_filter_library_completed",
|
"pref_filter_library_completed",
|
||||||
) + trackManager.services.map { "pref_filter_library_tracked_${it.id}" }
|
) + trackerManager.trackers.map { "pref_filter_library_tracked_${it.id}" }
|
||||||
|
|
||||||
prefKeys.forEach { key ->
|
prefKeys.forEach { key ->
|
||||||
val pref = preferenceStore.getInt(key, 0)
|
val pref = preferenceStore.getInt(key, 0)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.backup
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.util.BackupUtil
|
import eu.kanade.tachiyomi.util.BackupUtil
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
@ -11,7 +11,7 @@ import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class BackupFileValidator(
|
class BackupFileValidator(
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackerManager: TrackerManager = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +50,7 @@ class BackupFileValidator(
|
||||||
.map { it.syncId }
|
.map { it.syncId }
|
||||||
.distinct()
|
.distinct()
|
||||||
val missingTrackers = trackers
|
val missingTrackers = trackers
|
||||||
.mapNotNull { trackManager.getService(it.toLong()) }
|
.mapNotNull { trackerManager.get(it.toLong()) }
|
||||||
.filter { !it.isLoggedIn }
|
.filter { !it.isLoggedIn }
|
||||||
.map { it.name }
|
.map { it.name }
|
||||||
.sorted()
|
.sorted()
|
||||||
|
|
|
@ -3,9 +3,9 @@ package eu.kanade.tachiyomi.data.track
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For track services api that support deleting a manga entry for a user's list
|
* Tracker that support deleting am entry from a user's list.
|
||||||
*/
|
*/
|
||||||
interface DeletableTrackService {
|
interface DeletableTracker {
|
||||||
|
|
||||||
suspend fun delete(track: Track): Track
|
suspend fun delete(track: Track): Track
|
||||||
}
|
}
|
|
@ -6,31 +6,32 @@ import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.track.model.Track
|
import tachiyomi.domain.track.model.Track
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Enhanced Track Service will never prompt the user to match a manga with the remote.
|
* A tracker that will never prompt the user to manually bind an entry.
|
||||||
* It is expected that such Track Service can only work with specific sources and unique IDs.
|
* It is expected that such tracker can only work with specific sources and unique IDs.
|
||||||
*/
|
*/
|
||||||
interface EnhancedTrackService {
|
interface EnhancedTracker {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This TrackService will only work with the sources that are accepted by this filter function.
|
* This tracker will only work with the sources that are accepted by this filter function.
|
||||||
*/
|
*/
|
||||||
fun accept(source: Source): Boolean {
|
fun accept(source: Source): Boolean {
|
||||||
return source::class.qualifiedName in getAcceptedSources()
|
return source::class.qualifiedName in getAcceptedSources()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fully qualified source classes that this track service is compatible with.
|
* Fully qualified source classes that this tracker is compatible with.
|
||||||
*/
|
*/
|
||||||
fun getAcceptedSources(): List<String>
|
fun getAcceptedSources(): List<String>
|
||||||
|
|
||||||
fun loginNoop()
|
fun loginNoop()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* match is similar to TrackService.search, but only return zero or one match.
|
* Similar to [Tracker].search, but only returns zero or one match.
|
||||||
*/
|
*/
|
||||||
suspend fun match(manga: Manga): TrackSearch?
|
suspend fun match(manga: Manga): TrackSearch?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the provided source/track/manga triplet is from this TrackService
|
* Checks whether the provided source/track/manga triplet is from this [Tracker]
|
||||||
*/
|
*/
|
||||||
fun isTrackFrom(track: Track, manga: Manga, source: Source?): Boolean
|
fun isTrackFrom(track: Track, manga: Manga, source: Source?): Boolean
|
||||||
|
|
|
@ -5,7 +5,7 @@ import androidx.annotation.CallSuper
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
import eu.kanade.domain.track.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
import eu.kanade.domain.track.model.toDomainTrack
|
||||||
import eu.kanade.domain.track.service.TrackPreferences
|
import eu.kanade.domain.track.service.TrackPreferences
|
||||||
|
@ -28,7 +28,7 @@ import uy.kohesive.injekt.injectLazy
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
abstract class TrackService(val id: Long, val name: String) {
|
abstract class Tracker(val id: Long, val name: String) {
|
||||||
|
|
||||||
val trackPreferences: TrackPreferences by injectLazy()
|
val trackPreferences: TrackPreferences by injectLazy()
|
||||||
val networkService: NetworkHelper by injectLazy()
|
val networkService: NetworkHelper by injectLazy()
|
||||||
|
@ -83,7 +83,7 @@ abstract class TrackService(val id: Long, val name: String) {
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
open fun logout() {
|
open fun logout() {
|
||||||
trackPreferences.setTrackCredentials(this, "", "")
|
trackPreferences.setCredentials(this, "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
open val isLoggedIn: Boolean
|
open val isLoggedIn: Boolean
|
||||||
|
@ -95,7 +95,7 @@ abstract class TrackService(val id: Long, val name: String) {
|
||||||
fun getPassword() = trackPreferences.trackPassword(this).get()
|
fun getPassword() = trackPreferences.trackPassword(this).get()
|
||||||
|
|
||||||
fun saveCredentials(username: String, password: String) {
|
fun saveCredentials(username: String, password: String) {
|
||||||
trackPreferences.setTrackCredentials(this, username, password)
|
trackPreferences.setCredentials(this, username, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this to an interactor, and update all trackers based on common data
|
// TODO: move this to an interactor, and update all trackers based on common data
|
||||||
|
@ -111,7 +111,7 @@ abstract class TrackService(val id: Long, val name: String) {
|
||||||
|
|
||||||
insertTrack.await(track)
|
insertTrack.await(track)
|
||||||
|
|
||||||
// TODO: merge into SyncChaptersWithTrackServiceTwoWay?
|
// TODO: merge into [SyncChapterProgressWithTrack]?
|
||||||
// Update chapter progress if newer chapters marked read locally
|
// Update chapter progress if newer chapters marked read locally
|
||||||
if (hasReadChapters) {
|
if (hasReadChapters) {
|
||||||
val latestLocalReadChapterNumber = allChapters
|
val latestLocalReadChapterNumber = allChapters
|
||||||
|
@ -143,7 +143,7 @@ abstract class TrackService(val id: Long, val name: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
syncChapterProgressWithTrack.await(mangaId, track, this@TrackService)
|
syncChapterProgressWithTrack.await(mangaId, track, this@Tracker)
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
withUIContext { Injekt.get<Application>().toast(e.message) }
|
withUIContext { Injekt.get<Application>().toast(e.message) }
|
|
@ -1,6 +1,5 @@
|
||||||
package eu.kanade.tachiyomi.data.track
|
package eu.kanade.tachiyomi.data.track
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
||||||
import eu.kanade.tachiyomi.data.track.bangumi.Bangumi
|
import eu.kanade.tachiyomi.data.track.bangumi.Bangumi
|
||||||
import eu.kanade.tachiyomi.data.track.kavita.Kavita
|
import eu.kanade.tachiyomi.data.track.kavita.Kavita
|
||||||
|
@ -11,33 +10,27 @@ import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
|
||||||
import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
|
import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
|
||||||
import eu.kanade.tachiyomi.data.track.suwayomi.Suwayomi
|
import eu.kanade.tachiyomi.data.track.suwayomi.Suwayomi
|
||||||
|
|
||||||
class TrackManager(context: Context) {
|
class TrackerManager {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MYANIMELIST = 1L
|
|
||||||
const val ANILIST = 2L
|
const val ANILIST = 2L
|
||||||
const val KITSU = 3L
|
const val KITSU = 3L
|
||||||
const val SHIKIMORI = 4L
|
|
||||||
const val BANGUMI = 5L
|
|
||||||
const val KOMGA = 6L
|
|
||||||
const val MANGA_UPDATES = 7L
|
|
||||||
const val KAVITA = 8L
|
const val KAVITA = 8L
|
||||||
const val SUWAYOMI = 9L
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val myAnimeList = MyAnimeList(MYANIMELIST)
|
val myAnimeList = MyAnimeList(1L)
|
||||||
val aniList = Anilist(ANILIST)
|
val aniList = Anilist(ANILIST)
|
||||||
val kitsu = Kitsu(KITSU)
|
val kitsu = Kitsu(KITSU)
|
||||||
val shikimori = Shikimori(SHIKIMORI)
|
val shikimori = Shikimori(4L)
|
||||||
val bangumi = Bangumi(BANGUMI)
|
val bangumi = Bangumi(5L)
|
||||||
val komga = Komga(KOMGA)
|
val komga = Komga(6L)
|
||||||
val mangaUpdates = MangaUpdates(MANGA_UPDATES)
|
val mangaUpdates = MangaUpdates(7L)
|
||||||
val kavita = Kavita(context, KAVITA)
|
val kavita = Kavita(KAVITA)
|
||||||
val suwayomi = Suwayomi(SUWAYOMI)
|
val suwayomi = Suwayomi(9L)
|
||||||
|
|
||||||
val services = listOf(myAnimeList, aniList, kitsu, shikimori, bangumi, komga, mangaUpdates, kavita, suwayomi)
|
val trackers = listOf(myAnimeList, aniList, kitsu, shikimori, bangumi, komga, mangaUpdates, kavita, suwayomi)
|
||||||
|
|
||||||
fun getService(id: Long) = services.find { it.id == id }
|
fun get(id: Long) = trackers.find { it.id == id }
|
||||||
|
|
||||||
fun hasLoggedServices() = services.any { it.isLoggedIn }
|
fun hasLoggedIn() = trackers.any { it.isLoggedIn }
|
||||||
}
|
}
|
|
@ -4,15 +4,15 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.DeletableTrackService
|
import eu.kanade.tachiyomi.data.track.DeletableTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Anilist(id: Long) : TrackService(id, "AniList"), DeletableTrackService {
|
class Anilist(id: Long) : Tracker(id, "AniList"), DeletableTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.track.anilist
|
||||||
|
|
||||||
import eu.kanade.domain.track.service.TrackPreferences
|
import eu.kanade.domain.track.service.TrackPreferences
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
@ -20,7 +20,7 @@ data class ALManga(
|
||||||
val total_chapters: Int,
|
val total_chapters: Int,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun toTrack() = TrackSearch.create(TrackManager.ANILIST).apply {
|
fun toTrack() = TrackSearch.create(TrackerManager.ANILIST).apply {
|
||||||
media_id = this@ALManga.media_id
|
media_id = this@ALManga.media_id
|
||||||
title = title_user_pref
|
title = title_user_pref
|
||||||
total_chapters = this@ALManga.total_chapters
|
total_chapters = this@ALManga.total_chapters
|
||||||
|
@ -50,7 +50,7 @@ data class ALUserManga(
|
||||||
val manga: ALManga,
|
val manga: ALManga,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun toTrack() = Track.create(TrackManager.ANILIST).apply {
|
fun toTrack() = Track.create(TrackerManager.ANILIST).apply {
|
||||||
media_id = manga.media_id
|
media_id = manga.media_id
|
||||||
title = manga.title_user_pref
|
title = manga.title_user_pref
|
||||||
status = toTrackStatus()
|
status = toTrackStatus()
|
||||||
|
@ -62,7 +62,7 @@ data class ALUserManga(
|
||||||
total_chapters = manga.total_chapters
|
total_chapters = manga.total_chapters
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toTrackStatus() = when (list_status) {
|
private fun toTrackStatus() = when (list_status) {
|
||||||
"CURRENT" -> Anilist.READING
|
"CURRENT" -> Anilist.READING
|
||||||
"COMPLETED" -> Anilist.COMPLETED
|
"COMPLETED" -> Anilist.COMPLETED
|
||||||
"PAUSED" -> Anilist.ON_HOLD
|
"PAUSED" -> Anilist.ON_HOLD
|
||||||
|
|
|
@ -4,19 +4,19 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class Bangumi(id: Long) : TrackService(id, "Bangumi") {
|
class Bangumi(id: Long) : Tracker(id, "Bangumi") {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
private val interceptor by lazy { BangumiInterceptor(this) }
|
private val interceptor by lazy { BangumiInterceptor(this) }
|
||||||
|
|
||||||
private val api by lazy { BangumiApi(client, interceptor) }
|
private val api by lazy { BangumiApi(id, client, interceptor) }
|
||||||
|
|
||||||
override fun getScoreList(): List<String> {
|
override fun getScoreList(): List<String> {
|
||||||
return IntRange(0, 10).map(Int::toString)
|
return IntRange(0, 10).map(Int::toString)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.bangumi
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
@ -26,7 +25,11 @@ import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) {
|
class BangumiApi(
|
||||||
|
private val trackId: Long,
|
||||||
|
private val client: OkHttpClient,
|
||||||
|
interceptor: BangumiInterceptor,
|
||||||
|
) {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
@ -105,7 +108,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
return TrackSearch.create(TrackManager.BANGUMI).apply {
|
return TrackSearch.create(trackId).apply {
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
media_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["name_cn"]!!.jsonPrimitive.content
|
title = obj["name_cn"]!!.jsonPrimitive.content
|
||||||
cover_url = coverUrl
|
cover_url = coverUrl
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package eu.kanade.tachiyomi.data.track.kavita
|
package eu.kanade.tachiyomi.data.track.kavita
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita"), EnhancedTrackService {
|
class Kavita(id: Long) : Tracker(id, "Kavita"), EnhancedTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val UNREAD = 1
|
const val UNREAD = 1
|
||||||
|
@ -27,6 +28,8 @@ class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita"
|
||||||
private val interceptor by lazy { KavitaInterceptor(this) }
|
private val interceptor by lazy { KavitaInterceptor(this) }
|
||||||
val api by lazy { KavitaApi(client, interceptor) }
|
val api by lazy { KavitaApi(client, interceptor) }
|
||||||
|
|
||||||
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
|
|
||||||
override fun getLogo(): Int = R.drawable.ic_tracker_kavita
|
override fun getLogo(): Int = R.drawable.ic_tracker_kavita
|
||||||
|
|
||||||
override fun getLogoColor() = Color.rgb(74, 198, 148)
|
override fun getLogoColor() = Color.rgb(74, 198, 148)
|
||||||
|
@ -83,7 +86,7 @@ class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita"
|
||||||
saveCredentials("user", "pass")
|
saveCredentials("user", "pass")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackService.isLogged works by checking that credentials are saved.
|
// [Tracker].isLogged works by checking that credentials are saved.
|
||||||
// By saving dummy, unused credentials, we can activate the tracker simply by login/logout
|
// By saving dummy, unused credentials, we can activate the tracker simply by login/logout
|
||||||
override fun loginNoop() {
|
override fun loginNoop() {
|
||||||
saveCredentials("user", "pass")
|
saveCredentials("user", "pass")
|
||||||
|
@ -110,28 +113,29 @@ class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita"
|
||||||
|
|
||||||
fun loadOAuth() {
|
fun loadOAuth() {
|
||||||
val oauth = OAuth()
|
val oauth = OAuth()
|
||||||
for (sourceId in 1..3) {
|
for (id in 1..3) {
|
||||||
val authentication = oauth.authentications[sourceId - 1]
|
val authentication = oauth.authentications[id - 1]
|
||||||
val sourceSuffixID by lazy {
|
val sourceId by lazy {
|
||||||
val key = "kavita_$sourceId/all/1" // Hardcoded versionID to 1
|
val key = "kavita_$id/all/1" // Hardcoded versionID to 1
|
||||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }
|
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }
|
||||||
.reduce(Long::or) and Long.MAX_VALUE
|
.reduce(Long::or) and Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
val preferences: SharedPreferences by lazy {
|
val preferences = (sourceManager.get(sourceId) as ConfigurableSource).getPreferences()
|
||||||
context.getSharedPreferences("source_$sourceSuffixID", Context.MODE_PRIVATE)
|
|
||||||
}
|
val prefApiUrl = preferences.getString("APIURL", "")
|
||||||
val prefApiUrl = preferences.getString("APIURL", "")!!
|
val prefApiKey = preferences.getString("APIKEY", "")
|
||||||
if (prefApiUrl.isEmpty()) {
|
if (prefApiUrl.isNullOrEmpty() || prefApiKey.isNullOrEmpty()) {
|
||||||
// Source not configured. Skip
|
// Source not configured. Skip
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val prefApiKey = preferences.getString("APIKEY", "")!!
|
|
||||||
val token = api.getNewToken(apiUrl = prefApiUrl, apiKey = prefApiKey)
|
val token = api.getNewToken(apiUrl = prefApiUrl, apiKey = prefApiKey)
|
||||||
if (token.isNullOrEmpty()) {
|
if (token.isNullOrEmpty()) {
|
||||||
// Source is not accessible. Skip
|
// Source is not accessible. Skip
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
authentication.apiUrl = prefApiUrl
|
authentication.apiUrl = prefApiUrl
|
||||||
authentication.jwtToken = token.toString()
|
authentication.jwtToken = token.toString()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.data.track.kavita
|
package eu.kanade.tachiyomi.data.track.kavita
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ data class SeriesDto(
|
||||||
val libraryId: Int,
|
val libraryId: Int,
|
||||||
val libraryName: String? = "",
|
val libraryName: String? = "",
|
||||||
) {
|
) {
|
||||||
fun toTrack(): TrackSearch = TrackSearch.create(TrackManager.KAVITA).also {
|
fun toTrack(): TrackSearch = TrackSearch.create(TrackerManager.KAVITA).also {
|
||||||
it.title = name
|
it.title = name
|
||||||
it.summary = ""
|
it.summary = ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,15 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.DeletableTrackService
|
import eu.kanade.tachiyomi.data.track.DeletableTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
class Kitsu(id: Long) : TrackService(id, "Kitsu"), DeletableTrackService {
|
class Kitsu(id: Long) : Tracker(id, "Kitsu"), DeletableTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.track.kitsu
|
||||||
|
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
@ -35,7 +35,7 @@ class KitsuSearchManga(obj: JsonObject) {
|
||||||
private val endDate = obj["endDate"]?.jsonPrimitive?.contentOrNull
|
private val endDate = obj["endDate"]?.jsonPrimitive?.contentOrNull
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
fun toTrack() = TrackSearch.create(TrackManager.KITSU).apply {
|
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
|
||||||
media_id = this@KitsuSearchManga.id
|
media_id = this@KitsuSearchManga.id
|
||||||
title = canonicalTitle
|
title = canonicalTitle
|
||||||
total_chapters = chapterCount ?: 0
|
total_chapters = chapterCount ?: 0
|
||||||
|
@ -67,7 +67,7 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
|
||||||
private val ratingTwenty = obj["attributes"]!!.jsonObject["ratingTwenty"]?.jsonPrimitive?.contentOrNull
|
private val ratingTwenty = obj["attributes"]!!.jsonObject["ratingTwenty"]?.jsonPrimitive?.contentOrNull
|
||||||
val progress = obj["attributes"]!!.jsonObject["progress"]!!.jsonPrimitive.int
|
val progress = obj["attributes"]!!.jsonObject["progress"]!!.jsonPrimitive.int
|
||||||
|
|
||||||
fun toTrack() = TrackSearch.create(TrackManager.KITSU).apply {
|
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
|
||||||
media_id = libraryId
|
media_id = libraryId
|
||||||
title = canonicalTitle
|
title = canonicalTitle
|
||||||
total_chapters = chapterCount ?: 0
|
total_chapters = chapterCount ?: 0
|
||||||
|
|
|
@ -4,8 +4,8 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import okhttp3.Dns
|
import okhttp3.Dns
|
||||||
|
@ -13,7 +13,7 @@ import okhttp3.OkHttpClient
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Komga(id: Long) : TrackService(id, "Komga"), EnhancedTrackService {
|
class Komga(id: Long) : Tracker(id, "Komga"), EnhancedTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val UNREAD = 1
|
const val UNREAD = 1
|
||||||
|
@ -26,7 +26,7 @@ class Komga(id: Long) : TrackService(id, "Komga"), EnhancedTrackService {
|
||||||
.dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing
|
.dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val api by lazy { KomgaApi(client) }
|
val api by lazy { KomgaApi(id, client) }
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.ic_tracker_komga
|
override fun getLogo() = R.drawable.ic_tracker_komga
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ class Komga(id: Long) : TrackService(id, "Komga"), EnhancedTrackService {
|
||||||
saveCredentials("user", "pass")
|
saveCredentials("user", "pass")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackService.isLogged works by checking that credentials are saved.
|
// [Tracker].isLogged works by checking that credentials are saved.
|
||||||
// By saving dummy, unused credentials, we can activate the tracker simply by login/logout
|
// By saving dummy, unused credentials, we can activate the tracker simply by login/logout
|
||||||
override fun loginNoop() {
|
override fun loginNoop() {
|
||||||
saveCredentials("user", "pass")
|
saveCredentials("user", "pass")
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.data.track.komga
|
package eu.kanade.tachiyomi.data.track.komga
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||||
|
@ -19,7 +18,10 @@ import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
private const val READLIST_API = "/api/v1/readlists"
|
private const val READLIST_API = "/api/v1/readlists"
|
||||||
|
|
||||||
class KomgaApi(private val client: OkHttpClient) {
|
class KomgaApi(
|
||||||
|
private val trackId: Long,
|
||||||
|
private val client: OkHttpClient,
|
||||||
|
) {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
@ -85,13 +87,13 @@ class KomgaApi(private val client: OkHttpClient) {
|
||||||
return getTrackSearch(track.tracking_url)
|
return getTrackSearch(track.tracking_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SeriesDto.toTrack(): TrackSearch = TrackSearch.create(TrackManager.KOMGA).also {
|
private fun SeriesDto.toTrack(): TrackSearch = TrackSearch.create(trackId).also {
|
||||||
it.title = metadata.title
|
it.title = metadata.title
|
||||||
it.summary = metadata.summary
|
it.summary = metadata.summary
|
||||||
it.publishing_status = metadata.status
|
it.publishing_status = metadata.status
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ReadListDto.toTrack(): TrackSearch = TrackSearch.create(TrackManager.KOMGA).also {
|
private fun ReadListDto.toTrack(): TrackSearch = TrackSearch.create(trackId).also {
|
||||||
it.title = name
|
it.title = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.DeletableTrackService
|
import eu.kanade.tachiyomi.data.track.DeletableTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.copyTo
|
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.copyTo
|
||||||
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch
|
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
|
|
||||||
class MangaUpdates(id: Long) : TrackService(id, "MangaUpdates"), DeletableTrackService {
|
class MangaUpdates(id: Long) : Tracker(id, "MangaUpdates"), DeletableTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING_LIST = 0
|
const val READING_LIST = 0
|
||||||
|
|
|
@ -4,14 +4,14 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.DeletableTrackService
|
import eu.kanade.tachiyomi.data.track.DeletableTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), DeletableTrackService {
|
class MyAnimeList(id: Long) : Tracker(id, "MyAnimeList"), DeletableTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
@ -28,7 +28,7 @@ class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), DeletableTrackSer
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
private val interceptor by lazy { MyAnimeListInterceptor(this, getPassword()) }
|
private val interceptor by lazy { MyAnimeListInterceptor(this, getPassword()) }
|
||||||
private val api by lazy { MyAnimeListApi(client, interceptor) }
|
private val api by lazy { MyAnimeListApi(id, client, interceptor) }
|
||||||
|
|
||||||
override val supportsReadingDates: Boolean = true
|
override val supportsReadingDates: Boolean = true
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.myanimelist
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
@ -32,7 +31,11 @@ import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListInterceptor) {
|
class MyAnimeListApi(
|
||||||
|
private val trackId: Long,
|
||||||
|
private val client: OkHttpClient,
|
||||||
|
interceptor: MyAnimeListInterceptor,
|
||||||
|
) {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
@ -106,7 +109,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
.let {
|
.let {
|
||||||
val obj = it.jsonObject
|
val obj = it.jsonObject
|
||||||
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
TrackSearch.create(trackId).apply {
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
media_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["title"]!!.jsonPrimitive.content
|
title = obj["title"]!!.jsonPrimitive.content
|
||||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||||
|
|
|
@ -4,14 +4,14 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.DeletableTrackService
|
import eu.kanade.tachiyomi.data.track.DeletableTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class Shikimori(id: Long) : TrackService(id, "Shikimori"), DeletableTrackService {
|
class Shikimori(id: Long) : Tracker(id, "Shikimori"), DeletableTracker {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
@ -26,7 +26,7 @@ class Shikimori(id: Long) : TrackService(id, "Shikimori"), DeletableTrackService
|
||||||
|
|
||||||
private val interceptor by lazy { ShikimoriInterceptor(this) }
|
private val interceptor by lazy { ShikimoriInterceptor(this) }
|
||||||
|
|
||||||
private val api by lazy { ShikimoriApi(client, interceptor) }
|
private val api by lazy { ShikimoriApi(id, client, interceptor) }
|
||||||
|
|
||||||
override fun getScoreList(): List<String> {
|
override fun getScoreList(): List<String> {
|
||||||
return IntRange(0, 10).map(Int::toString)
|
return IntRange(0, 10).map(Int::toString)
|
||||||
|
|
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.track.shikimori
|
||||||
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.DELETE
|
import eu.kanade.tachiyomi.network.DELETE
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
@ -28,7 +27,11 @@ import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInterceptor) {
|
class ShikimoriApi(
|
||||||
|
private val trackId: Long,
|
||||||
|
private val client: OkHttpClient,
|
||||||
|
interceptor: ShikimoriInterceptor,
|
||||||
|
) {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
@ -96,7 +99,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jsonToSearch(obj: JsonObject): TrackSearch {
|
private fun jsonToSearch(obj: JsonObject): TrackSearch {
|
||||||
return TrackSearch.create(TrackManager.SHIKIMORI).apply {
|
return TrackSearch.create(trackId).apply {
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
media_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["name"]!!.jsonPrimitive.content
|
title = obj["name"]!!.jsonPrimitive.content
|
||||||
total_chapters = obj["chapters"]!!.jsonPrimitive.int
|
total_chapters = obj["chapters"]!!.jsonPrimitive.int
|
||||||
|
@ -110,7 +113,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jsonToTrack(obj: JsonObject, mangas: JsonObject): Track {
|
private fun jsonToTrack(obj: JsonObject, mangas: JsonObject): Track {
|
||||||
return Track.create(TrackManager.SHIKIMORI).apply {
|
return Track.create(trackId).apply {
|
||||||
title = mangas["name"]!!.jsonPrimitive.content
|
title = mangas["name"]!!.jsonPrimitive.content
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
media_id = obj["id"]!!.jsonPrimitive.long
|
||||||
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
|
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
|
||||||
|
|
|
@ -4,16 +4,16 @@ import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import tachiyomi.domain.manga.model.Manga as DomainManga
|
import tachiyomi.domain.manga.model.Manga as DomainManga
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Suwayomi(id: Long) : TrackService(id, "Suwayomi"), EnhancedTrackService {
|
class Suwayomi(id: Long) : Tracker(id, "Suwayomi"), EnhancedTracker {
|
||||||
|
|
||||||
val api by lazy { TachideskApi() }
|
val api by lazy { SuwayomiApi(id) }
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.ic_tracker_suwayomi
|
override fun getLogo() = R.drawable.ic_tracker_suwayomi
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
@ -24,7 +23,7 @@ import uy.kohesive.injekt.injectLazy
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
class TachideskApi {
|
class SuwayomiApi(private val trackId: Long) {
|
||||||
|
|
||||||
private val network: NetworkHelper by injectLazy()
|
private val network: NetworkHelper by injectLazy()
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
@ -62,7 +61,7 @@ class TachideskApi {
|
||||||
.parseAs<MangaDataClass>()
|
.parseAs<MangaDataClass>()
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackSearch.create(TrackManager.SUWAYOMI).apply {
|
TrackSearch.create(trackId).apply {
|
||||||
title = manga.title
|
title = manga.title
|
||||||
cover_url = "$url/thumbnail"
|
cover_url = "$url/thumbnail"
|
||||||
summary = manga.description.orEmpty()
|
summary = manga.description.orEmpty()
|
||||||
|
@ -101,26 +100,24 @@ class TachideskApi {
|
||||||
return getTrackSearch(track.tracking_url)
|
return getTrackSearch(track.tracking_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val tachideskExtensionId by lazy {
|
private val sourceId by lazy {
|
||||||
val key = "tachidesk/en/1"
|
val key = "tachidesk/en/1"
|
||||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
private val preferences: SharedPreferences by lazy {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$tachideskExtensionId", Context.MODE_PRIVATE)
|
Injekt.get<Application>().getSharedPreferences("source_$sourceId", Context.MODE_PRIVATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPrefBaseUrl(): String = preferences.getString(ADDRESS_TITLE, ADDRESS_DEFAULT)!!
|
private fun getPrefBaseUrl(): String = preferences.getString(ADDRESS_TITLE, ADDRESS_DEFAULT)!!
|
||||||
private fun getPrefBaseLogin(): String = preferences.getString(LOGIN_TITLE, LOGIN_DEFAULT)!!
|
private fun getPrefBaseLogin(): String = preferences.getString(LOGIN_TITLE, LOGIN_DEFAULT)!!
|
||||||
private fun getPrefBasePassword(): String = preferences.getString(PASSWORD_TITLE, PASSWORD_DEFAULT)!!
|
private fun getPrefBasePassword(): String = preferences.getString(PASSWORD_TITLE, PASSWORD_DEFAULT)!!
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val ADDRESS_TITLE = "Server URL Address"
|
private const val ADDRESS_TITLE = "Server URL Address"
|
||||||
private const val ADDRESS_DEFAULT = ""
|
private const val ADDRESS_DEFAULT = ""
|
||||||
private const val LOGIN_TITLE = "Login (Basic Auth)"
|
private const val LOGIN_TITLE = "Login (Basic Auth)"
|
||||||
private const val LOGIN_DEFAULT = ""
|
private const val LOGIN_DEFAULT = ""
|
||||||
private const val PASSWORD_TITLE = "Password (Basic Auth)"
|
private const val PASSWORD_TITLE = "Password (Basic Auth)"
|
||||||
private const val PASSWORD_DEFAULT = ""
|
private const val PASSWORD_DEFAULT = ""
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,8 +35,8 @@ import eu.kanade.domain.manga.model.toSManga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
|
import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
|
||||||
|
@ -177,7 +177,7 @@ internal class MigrateDialogScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val enhancedServices by lazy {
|
private val enhancedServices by lazy {
|
||||||
Injekt.get<TrackManager>().services.filterIsInstance<EnhancedTrackService>()
|
Injekt.get<TrackerManager>().trackers.filterIsInstance<EnhancedTracker>()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun migrateManga(
|
suspend fun migrateManga(
|
||||||
|
|
|
@ -15,16 +15,12 @@ import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import cafe.adriel.voyager.core.model.coroutineScope
|
import cafe.adriel.voyager.core.model.coroutineScope
|
||||||
import eu.kanade.core.preference.asState
|
import eu.kanade.core.preference.asState
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toDomainManga
|
import eu.kanade.domain.manga.model.toDomainManga
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
import eu.kanade.domain.track.interactor.AddTracks
|
||||||
import eu.kanade.presentation.util.ioCoroutineScope
|
import eu.kanade.presentation.util.ioCoroutineScope
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
|
||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
|
@ -37,11 +33,9 @@ import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import logcat.LogPriority
|
|
||||||
import tachiyomi.core.preference.CheckboxState
|
import tachiyomi.core.preference.CheckboxState
|
||||||
import tachiyomi.core.preference.mapAsCheckboxState
|
import tachiyomi.core.preference.mapAsCheckboxState
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
import tachiyomi.core.util.system.logcat
|
|
||||||
import tachiyomi.domain.category.interactor.GetCategories
|
import tachiyomi.domain.category.interactor.GetCategories
|
||||||
import tachiyomi.domain.category.interactor.SetMangaCategories
|
import tachiyomi.domain.category.interactor.SetMangaCategories
|
||||||
import tachiyomi.domain.category.model.Category
|
import tachiyomi.domain.category.model.Category
|
||||||
|
@ -54,7 +48,6 @@ import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.toMangaUpdate
|
import tachiyomi.domain.manga.model.toMangaUpdate
|
||||||
import tachiyomi.domain.source.interactor.GetRemoteManga
|
import tachiyomi.domain.source.interactor.GetRemoteManga
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.domain.track.interactor.InsertTrack
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
@ -76,12 +69,9 @@ class BrowseSourceScreenModel(
|
||||||
private val getManga: GetManga = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
private val insertTrack: InsertTrack = Injekt.get(),
|
private val addTracks: AddTracks = Injekt.get(),
|
||||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack = Injekt.get(),
|
|
||||||
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
||||||
|
|
||||||
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLoggedIn } }
|
|
||||||
|
|
||||||
var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope)
|
var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope)
|
||||||
|
|
||||||
val source = sourceManager.getOrStub(sourceId)
|
val source = sourceManager.getOrStub(sourceId)
|
||||||
|
@ -243,8 +233,7 @@ class BrowseSourceScreenModel(
|
||||||
new = new.removeCovers(coverCache)
|
new = new.removeCovers(coverCache)
|
||||||
} else {
|
} else {
|
||||||
setMangaDefaultChapterFlags.await(manga)
|
setMangaDefaultChapterFlags.await(manga)
|
||||||
|
addTracks.bindEnhancedTracks(manga, source)
|
||||||
autoAddTrack(manga)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateManga.await(new.toMangaUpdate())
|
updateManga.await(new.toMangaUpdate())
|
||||||
|
@ -281,25 +270,6 @@ class BrowseSourceScreenModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun autoAddTrack(manga: Manga) {
|
|
||||||
loggedServices
|
|
||||||
.filterIsInstance<EnhancedTrackService>()
|
|
||||||
.filter { it.accept(source) }
|
|
||||||
.forEach { service ->
|
|
||||||
try {
|
|
||||||
service.match(manga)?.let { track ->
|
|
||||||
track.manga_id = manga.id
|
|
||||||
(service as TrackService).bind(track)
|
|
||||||
insertTrack.await(track.toDomainTrack()!!)
|
|
||||||
|
|
||||||
syncChapterProgressWithTrack.await(manga.id, track.toDomainTrack()!!, service)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get user categories.
|
* Get user categories.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,7 +23,7 @@ import eu.kanade.presentation.manga.DownloadAction
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.chapter.getNextUnread
|
import eu.kanade.tachiyomi.util.chapter.getNextUnread
|
||||||
|
@ -88,7 +88,7 @@ class LibraryScreenModel(
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
private val downloadManager: DownloadManager = Injekt.get(),
|
private val downloadManager: DownloadManager = Injekt.get(),
|
||||||
private val downloadCache: DownloadCache = Injekt.get(),
|
private val downloadCache: DownloadCache = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackerManager: TrackerManager = Injekt.get(),
|
||||||
) : StateScreenModel<LibraryScreenModel.State>(State()) {
|
) : StateScreenModel<LibraryScreenModel.State>(State()) {
|
||||||
|
|
||||||
var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(coroutineScope)
|
var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(coroutineScope)
|
||||||
|
@ -101,9 +101,9 @@ class LibraryScreenModel(
|
||||||
getTracksPerManga.subscribe(),
|
getTracksPerManga.subscribe(),
|
||||||
getTrackingFilterFlow(),
|
getTrackingFilterFlow(),
|
||||||
downloadCache.changes,
|
downloadCache.changes,
|
||||||
) { searchQuery, library, tracks, loggedInTrackServices, _ ->
|
) { searchQuery, library, tracks, loggedInTrackers, _ ->
|
||||||
library
|
library
|
||||||
.applyFilters(tracks, loggedInTrackServices)
|
.applyFilters(tracks, loggedInTrackers)
|
||||||
.applySort()
|
.applySort()
|
||||||
.mapValues { (_, value) ->
|
.mapValues { (_, value) ->
|
||||||
if (searchQuery != null) {
|
if (searchQuery != null) {
|
||||||
|
@ -169,7 +169,7 @@ class LibraryScreenModel(
|
||||||
*/
|
*/
|
||||||
private suspend fun LibraryMap.applyFilters(
|
private suspend fun LibraryMap.applyFilters(
|
||||||
trackMap: Map<Long, List<Long>>,
|
trackMap: Map<Long, List<Long>>,
|
||||||
loggedInTrackServices: Map<Long, TriState>,
|
loggedInTrackers: Map<Long, TriState>,
|
||||||
): LibraryMap {
|
): LibraryMap {
|
||||||
val prefs = getLibraryItemPreferencesFlow().first()
|
val prefs = getLibraryItemPreferencesFlow().first()
|
||||||
val downloadedOnly = prefs.globalFilterDownloaded
|
val downloadedOnly = prefs.globalFilterDownloaded
|
||||||
|
@ -180,10 +180,10 @@ class LibraryScreenModel(
|
||||||
val filterBookmarked = prefs.filterBookmarked
|
val filterBookmarked = prefs.filterBookmarked
|
||||||
val filterCompleted = prefs.filterCompleted
|
val filterCompleted = prefs.filterCompleted
|
||||||
|
|
||||||
val isNotLoggedInAnyTrack = loggedInTrackServices.isEmpty()
|
val isNotLoggedInAnyTrack = loggedInTrackers.isEmpty()
|
||||||
|
|
||||||
val excludedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_NOT) it.key else null }
|
val excludedTracks = loggedInTrackers.mapNotNull { if (it.value == TriState.ENABLED_NOT) it.key else null }
|
||||||
val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null }
|
val includedTracks = loggedInTrackers.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null }
|
||||||
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
|
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
|
||||||
|
|
||||||
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
||||||
|
@ -366,14 +366,14 @@ class LibraryScreenModel(
|
||||||
* @return map of track id with the filter value
|
* @return map of track id with the filter value
|
||||||
*/
|
*/
|
||||||
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
||||||
val loggedServices = trackManager.services.filter { it.isLoggedIn }
|
val loggedInTrackers = trackerManager.trackers.filter { it.isLoggedIn }
|
||||||
return if (loggedServices.isNotEmpty()) {
|
return if (loggedInTrackers.isNotEmpty()) {
|
||||||
val prefFlows = loggedServices
|
val prefFlows = loggedInTrackers
|
||||||
.map { libraryPreferences.filterTracking(it.id.toInt()).changes() }
|
.map { libraryPreferences.filterTracking(it.id.toInt()).changes() }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
combine(*prefFlows) {
|
combine(*prefFlows) {
|
||||||
loggedServices
|
loggedInTrackers
|
||||||
.mapIndexed { index, trackService -> trackService.id to it[index] }
|
.mapIndexed { index, tracker -> tracker.id to it[index] }
|
||||||
.toMap()
|
.toMap()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.library
|
||||||
import cafe.adriel.voyager.core.model.ScreenModel
|
import cafe.adriel.voyager.core.model.ScreenModel
|
||||||
import cafe.adriel.voyager.core.model.coroutineScope
|
import cafe.adriel.voyager.core.model.coroutineScope
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import tachiyomi.core.preference.Preference
|
import tachiyomi.core.preference.Preference
|
||||||
import tachiyomi.core.preference.TriState
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.core.preference.getAndSet
|
import tachiyomi.core.preference.getAndSet
|
||||||
|
@ -22,11 +22,11 @@ class LibrarySettingsScreenModel(
|
||||||
val libraryPreferences: LibraryPreferences = Injekt.get(),
|
val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||||
private val setDisplayMode: SetDisplayMode = Injekt.get(),
|
private val setDisplayMode: SetDisplayMode = Injekt.get(),
|
||||||
private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(),
|
private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackerManager: TrackerManager = Injekt.get(),
|
||||||
) : ScreenModel {
|
) : ScreenModel {
|
||||||
|
|
||||||
val trackServices
|
val trackers
|
||||||
get() = trackManager.services.filter { it.isLoggedIn }
|
get() = trackerManager.trackers.filter { it.isLoggedIn }
|
||||||
|
|
||||||
fun toggleFilter(preference: (LibraryPreferences) -> Preference<TriState>) {
|
fun toggleFilter(preference: (LibraryPreferences) -> Preference<TriState>) {
|
||||||
preference(libraryPreferences).getAndSet {
|
preference(libraryPreferences).getAndSet {
|
||||||
|
|
|
@ -138,7 +138,7 @@ class MainActivity : BaseActivity() {
|
||||||
libraryPreferences = libraryPreferences,
|
libraryPreferences = libraryPreferences,
|
||||||
readerPreferences = Injekt.get(),
|
readerPreferences = Injekt.get(),
|
||||||
backupPreferences = Injekt.get(),
|
backupPreferences = Injekt.get(),
|
||||||
trackManager = Injekt.get(),
|
trackerManager = Injekt.get(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
|
@ -23,9 +23,9 @@ import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.network.HttpException
|
import eu.kanade.tachiyomi.network.HttpException
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||||
|
@ -84,7 +84,7 @@ class MangaScreenModel(
|
||||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||||
readerPreferences: ReaderPreferences = Injekt.get(),
|
readerPreferences: ReaderPreferences = Injekt.get(),
|
||||||
uiPreferences: UiPreferences = Injekt.get(),
|
uiPreferences: UiPreferences = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackerManager: TrackerManager = Injekt.get(),
|
||||||
private val downloadManager: DownloadManager = Injekt.get(),
|
private val downloadManager: DownloadManager = Injekt.get(),
|
||||||
private val downloadCache: DownloadCache = Injekt.get(),
|
private val downloadCache: DownloadCache = Injekt.get(),
|
||||||
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
||||||
|
@ -105,7 +105,7 @@ class MangaScreenModel(
|
||||||
private val successState: State.Success?
|
private val successState: State.Success?
|
||||||
get() = state.value as? State.Success
|
get() = state.value as? State.Success
|
||||||
|
|
||||||
private val loggedServices by lazy { trackManager.services.filter { it.isLoggedIn } }
|
private val loggedInTrackers by lazy { trackerManager.trackers.filter { it.isLoggedIn } }
|
||||||
|
|
||||||
val manga: Manga?
|
val manga: Manga?
|
||||||
get() = successState?.manga
|
get() = successState?.manga
|
||||||
|
@ -317,14 +317,14 @@ class MangaScreenModel(
|
||||||
// Finally match with enhanced tracking when available
|
// Finally match with enhanced tracking when available
|
||||||
val source = state.source
|
val source = state.source
|
||||||
state.trackItems
|
state.trackItems
|
||||||
.map { it.service }
|
.map { it.tracker }
|
||||||
.filterIsInstance<EnhancedTrackService>()
|
.filterIsInstance<EnhancedTracker>()
|
||||||
.filter { it.accept(source) }
|
.filter { it.accept(source) }
|
||||||
.forEach { service ->
|
.forEach { service ->
|
||||||
launchIO {
|
launchIO {
|
||||||
try {
|
try {
|
||||||
service.match(manga)?.let { track ->
|
service.match(manga)?.let { track ->
|
||||||
(service as TrackService).register(track, mangaId)
|
(service as Tracker).register(track, mangaId)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logcat(LogPriority.WARN, e) {
|
logcat(LogPriority.WARN, e) {
|
||||||
|
@ -949,11 +949,11 @@ class MangaScreenModel(
|
||||||
getTracks.subscribe(manga.id)
|
getTracks.subscribe(manga.id)
|
||||||
.catch { logcat(LogPriority.ERROR, it) }
|
.catch { logcat(LogPriority.ERROR, it) }
|
||||||
.map { tracks ->
|
.map { tracks ->
|
||||||
loggedServices
|
loggedInTrackers
|
||||||
// Map to TrackItem
|
// Map to TrackItem
|
||||||
.map { service -> TrackItem(tracks.find { it.syncId == service.id }, service) }
|
.map { service -> TrackItem(tracks.find { it.syncId == 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.service as? EnhancedTrackService)?.accept(source!!) ?: true }
|
.filter { (it.tracker as? EnhancedTracker)?.accept(source!!) ?: true }
|
||||||
}
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.collectLatest { trackItems ->
|
.collectLatest { trackItems ->
|
||||||
|
|
|
@ -46,14 +46,14 @@ import eu.kanade.presentation.track.TrackChapterSelector
|
||||||
import eu.kanade.presentation.track.TrackDateSelector
|
import eu.kanade.presentation.track.TrackDateSelector
|
||||||
import eu.kanade.presentation.track.TrackInfoDialogHome
|
import eu.kanade.presentation.track.TrackInfoDialogHome
|
||||||
import eu.kanade.presentation.track.TrackScoreSelector
|
import eu.kanade.presentation.track.TrackScoreSelector
|
||||||
import eu.kanade.presentation.track.TrackServiceSearch
|
|
||||||
import eu.kanade.presentation.track.TrackStatusSelector
|
import eu.kanade.presentation.track.TrackStatusSelector
|
||||||
|
import eu.kanade.presentation.track.TrackerSearch
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.track.DeletableTrackService
|
import eu.kanade.tachiyomi.data.track.DeletableTracker
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
|
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
|
||||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||||
|
@ -105,7 +105,7 @@ data class TrackInfoDialogHomeScreen(
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackStatusSelectorScreen(
|
TrackStatusSelectorScreen(
|
||||||
track = it.track!!,
|
track = it.track!!,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -113,7 +113,7 @@ data class TrackInfoDialogHomeScreen(
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackChapterSelectorScreen(
|
TrackChapterSelectorScreen(
|
||||||
track = it.track!!,
|
track = it.track!!,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -121,7 +121,7 @@ data class TrackInfoDialogHomeScreen(
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackScoreSelectorScreen(
|
TrackScoreSelectorScreen(
|
||||||
track = it.track!!,
|
track = it.track!!,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -129,7 +129,7 @@ data class TrackInfoDialogHomeScreen(
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackDateSelectorScreen(
|
TrackDateSelectorScreen(
|
||||||
track = it.track!!,
|
track = it.track!!,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
start = true,
|
start = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -138,21 +138,21 @@ data class TrackInfoDialogHomeScreen(
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackDateSelectorScreen(
|
TrackDateSelectorScreen(
|
||||||
track = it.track!!,
|
track = it.track!!,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
start = false,
|
start = false,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onNewSearch = {
|
onNewSearch = {
|
||||||
if (it.service is EnhancedTrackService) {
|
if (it.tracker is EnhancedTracker) {
|
||||||
sm.registerEnhancedTracking(it)
|
sm.registerEnhancedTracking(it)
|
||||||
} else {
|
} else {
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackServiceSearchScreen(
|
TrackerSearchScreen(
|
||||||
mangaId = mangaId,
|
mangaId = mangaId,
|
||||||
initialQuery = it.track?.title ?: mangaTitle,
|
initialQuery = it.track?.title ?: mangaTitle,
|
||||||
currentUrl = it.track?.remoteUrl,
|
currentUrl = it.track?.remoteUrl,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -160,10 +160,10 @@ data class TrackInfoDialogHomeScreen(
|
||||||
onOpenInBrowser = { openTrackerInBrowser(context, it) },
|
onOpenInBrowser = { openTrackerInBrowser(context, it) },
|
||||||
onRemoved = {
|
onRemoved = {
|
||||||
navigator.push(
|
navigator.push(
|
||||||
TrackServiceRemoveScreen(
|
TrackerRemoveScreen(
|
||||||
mangaId = mangaId,
|
mangaId = mangaId,
|
||||||
track = it.track!!,
|
track = it.track!!,
|
||||||
serviceId = it.service.id,
|
serviceId = it.tracker.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -201,12 +201,12 @@ data class TrackInfoDialogHomeScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerEnhancedTracking(item: TrackItem) {
|
fun registerEnhancedTracking(item: TrackItem) {
|
||||||
item.service as EnhancedTrackService
|
item.tracker as EnhancedTracker
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
|
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
|
||||||
try {
|
try {
|
||||||
val matchResult = item.service.match(manga) ?: throw Exception()
|
val matchResult = item.tracker.match(manga) ?: throw Exception()
|
||||||
item.service.register(matchResult, mangaId)
|
item.tracker.register(matchResult, mangaId)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
|
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
|
||||||
}
|
}
|
||||||
|
@ -236,13 +236,13 @@ data class TrackInfoDialogHomeScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<Track>.mapToTrackItem(): List<TrackItem> {
|
private fun List<Track>.mapToTrackItem(): List<TrackItem> {
|
||||||
val loggedServices = Injekt.get<TrackManager>().services.filter { it.isLoggedIn }
|
val loggedInTrackers = Injekt.get<TrackerManager>().trackers.filter { it.isLoggedIn }
|
||||||
val source = Injekt.get<SourceManager>().getOrStub(sourceId)
|
val source = Injekt.get<SourceManager>().getOrStub(sourceId)
|
||||||
return loggedServices
|
return loggedInTrackers
|
||||||
// Map to TrackItem
|
// Map to TrackItem
|
||||||
.map { service -> TrackItem(find { it.syncId == service.id }, service) }
|
.map { service -> TrackItem(find { it.syncId == 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.service as? EnhancedTrackService)?.accept(source) ?: true }
|
.filter { (it.tracker as? EnhancedTracker)?.accept(source) ?: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
@ -263,7 +263,7 @@ private data class TrackStatusSelectorScreen(
|
||||||
val sm = rememberScreenModel {
|
val sm = rememberScreenModel {
|
||||||
Model(
|
Model(
|
||||||
track = track,
|
track = track,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val state by sm.state.collectAsState()
|
val state by sm.state.collectAsState()
|
||||||
|
@ -281,11 +281,11 @@ private data class TrackStatusSelectorScreen(
|
||||||
|
|
||||||
private class Model(
|
private class Model(
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
) : StateScreenModel<Model.State>(State(track.status.toInt())) {
|
) : StateScreenModel<Model.State>(State(track.status.toInt())) {
|
||||||
|
|
||||||
fun getSelections(): Map<Int, Int?> {
|
fun getSelections(): Map<Int, Int?> {
|
||||||
return service.getStatusList().associateWith { service.getStatus(it) }
|
return tracker.getStatusList().associateWith { tracker.getStatus(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSelection(selection: Int) {
|
fun setSelection(selection: Int) {
|
||||||
|
@ -294,7 +294,7 @@ private data class TrackStatusSelectorScreen(
|
||||||
|
|
||||||
fun setStatus() {
|
fun setStatus() {
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
service.setRemoteStatus(track.toDbTrack(), state.value.selection)
|
tracker.setRemoteStatus(track.toDbTrack(), state.value.selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ private data class TrackChapterSelectorScreen(
|
||||||
val sm = rememberScreenModel {
|
val sm = rememberScreenModel {
|
||||||
Model(
|
Model(
|
||||||
track = track,
|
track = track,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val state by sm.state.collectAsState()
|
val state by sm.state.collectAsState()
|
||||||
|
@ -335,7 +335,7 @@ private data class TrackChapterSelectorScreen(
|
||||||
|
|
||||||
private class Model(
|
private class Model(
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
) : StateScreenModel<Model.State>(State(track.lastChapterRead.toInt())) {
|
) : StateScreenModel<Model.State>(State(track.lastChapterRead.toInt())) {
|
||||||
|
|
||||||
fun getRange(): Iterable<Int> {
|
fun getRange(): Iterable<Int> {
|
||||||
|
@ -353,7 +353,7 @@ private data class TrackChapterSelectorScreen(
|
||||||
|
|
||||||
fun setChapter() {
|
fun setChapter() {
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
service.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection)
|
tracker.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +375,7 @@ private data class TrackScoreSelectorScreen(
|
||||||
val sm = rememberScreenModel {
|
val sm = rememberScreenModel {
|
||||||
Model(
|
Model(
|
||||||
track = track,
|
track = track,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val state by sm.state.collectAsState()
|
val state by sm.state.collectAsState()
|
||||||
|
@ -394,11 +394,11 @@ private data class TrackScoreSelectorScreen(
|
||||||
|
|
||||||
private class Model(
|
private class Model(
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
) : StateScreenModel<Model.State>(State(service.displayScore(track.toDbTrack()))) {
|
) : StateScreenModel<Model.State>(State(tracker.displayScore(track.toDbTrack()))) {
|
||||||
|
|
||||||
fun getSelections(): List<String> {
|
fun getSelections(): List<String> {
|
||||||
return service.getScoreList()
|
return tracker.getScoreList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSelection(selection: String) {
|
fun setSelection(selection: String) {
|
||||||
|
@ -407,7 +407,7 @@ private data class TrackScoreSelectorScreen(
|
||||||
|
|
||||||
fun setScore() {
|
fun setScore() {
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
service.setRemoteScore(track.toDbTrack(), state.value.selection)
|
tracker.setRemoteScore(track.toDbTrack(), state.value.selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +486,7 @@ private data class TrackDateSelectorScreen(
|
||||||
val sm = rememberScreenModel {
|
val sm = rememberScreenModel {
|
||||||
Model(
|
Model(
|
||||||
track = track,
|
track = track,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
start = start,
|
start = start,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ private data class TrackDateSelectorScreen(
|
||||||
|
|
||||||
private class Model(
|
private class Model(
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
private val start: Boolean,
|
private val start: Boolean,
|
||||||
) : ScreenModel {
|
) : ScreenModel {
|
||||||
|
|
||||||
|
@ -534,15 +534,15 @@ private data class TrackDateSelectorScreen(
|
||||||
val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault())
|
val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault())
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
if (start) {
|
if (start) {
|
||||||
service.setRemoteStartDate(track.toDbTrack(), localMillis)
|
tracker.setRemoteStartDate(track.toDbTrack(), localMillis)
|
||||||
} else {
|
} else {
|
||||||
service.setRemoteFinishDate(track.toDbTrack(), localMillis)
|
tracker.setRemoteFinishDate(track.toDbTrack(), localMillis)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun confirmRemoveDate(navigator: Navigator) {
|
fun confirmRemoveDate(navigator: Navigator) {
|
||||||
navigator.push(TrackDateRemoverScreen(track, service.id, start))
|
navigator.push(TrackDateRemoverScreen(track, tracker.id, start))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,7 +559,7 @@ private data class TrackDateRemoverScreen(
|
||||||
val sm = rememberScreenModel {
|
val sm = rememberScreenModel {
|
||||||
Model(
|
Model(
|
||||||
track = track,
|
track = track,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
start = start,
|
start = start,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -614,25 +614,25 @@ private data class TrackDateRemoverScreen(
|
||||||
|
|
||||||
private class Model(
|
private class Model(
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
private val start: Boolean,
|
private val start: Boolean,
|
||||||
) : ScreenModel {
|
) : ScreenModel {
|
||||||
|
|
||||||
fun getServiceName() = service.name
|
fun getServiceName() = tracker.name
|
||||||
|
|
||||||
fun removeDate() {
|
fun removeDate() {
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
if (start) {
|
if (start) {
|
||||||
service.setRemoteStartDate(track.toDbTrack(), 0)
|
tracker.setRemoteStartDate(track.toDbTrack(), 0)
|
||||||
} else {
|
} else {
|
||||||
service.setRemoteFinishDate(track.toDbTrack(), 0)
|
tracker.setRemoteFinishDate(track.toDbTrack(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TrackServiceSearchScreen(
|
data class TrackerSearchScreen(
|
||||||
private val mangaId: Long,
|
private val mangaId: Long,
|
||||||
private val initialQuery: String,
|
private val initialQuery: String,
|
||||||
private val currentUrl: String?,
|
private val currentUrl: String?,
|
||||||
|
@ -647,14 +647,14 @@ data class TrackServiceSearchScreen(
|
||||||
mangaId = mangaId,
|
mangaId = mangaId,
|
||||||
currentUrl = currentUrl,
|
currentUrl = currentUrl,
|
||||||
initialQuery = initialQuery,
|
initialQuery = initialQuery,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val state by sm.state.collectAsState()
|
val state by sm.state.collectAsState()
|
||||||
|
|
||||||
var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) }
|
var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) }
|
||||||
TrackServiceSearch(
|
TrackerSearch(
|
||||||
query = textFieldValue,
|
query = textFieldValue,
|
||||||
onQueryChange = { textFieldValue = it },
|
onQueryChange = { textFieldValue = it },
|
||||||
onDispatchQuery = { sm.trackingSearch(textFieldValue.text) },
|
onDispatchQuery = { sm.trackingSearch(textFieldValue.text) },
|
||||||
|
@ -673,7 +673,7 @@ data class TrackServiceSearchScreen(
|
||||||
private val mangaId: Long,
|
private val mangaId: Long,
|
||||||
private val currentUrl: String? = null,
|
private val currentUrl: String? = null,
|
||||||
initialQuery: String,
|
initialQuery: String,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
) : StateScreenModel<Model.State>(State()) {
|
) : StateScreenModel<Model.State>(State()) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -690,7 +690,7 @@ data class TrackServiceSearchScreen(
|
||||||
|
|
||||||
val result = withIOContext {
|
val result = withIOContext {
|
||||||
try {
|
try {
|
||||||
val results = service.search(query)
|
val results = tracker.search(query)
|
||||||
Result.success(results)
|
Result.success(results)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Result.failure(e)
|
Result.failure(e)
|
||||||
|
@ -706,7 +706,7 @@ data class TrackServiceSearchScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerTracking(item: TrackSearch) {
|
fun registerTracking(item: TrackSearch) {
|
||||||
coroutineScope.launchNonCancellable { service.register(item, mangaId) }
|
coroutineScope.launchNonCancellable { tracker.register(item, mangaId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelection(selected: TrackSearch) {
|
fun updateSelection(selected: TrackSearch) {
|
||||||
|
@ -721,7 +721,7 @@ data class TrackServiceSearchScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class TrackServiceRemoveScreen(
|
private data class TrackerRemoveScreen(
|
||||||
private val mangaId: Long,
|
private val mangaId: Long,
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val serviceId: Long,
|
private val serviceId: Long,
|
||||||
|
@ -734,10 +734,10 @@ private data class TrackServiceRemoveScreen(
|
||||||
Model(
|
Model(
|
||||||
mangaId = mangaId,
|
mangaId = mangaId,
|
||||||
track = track,
|
track = track,
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val serviceName = sm.getServiceName()
|
val serviceName = sm.getName()
|
||||||
var removeRemoteTrack by remember { mutableStateOf(false) }
|
var removeRemoteTrack by remember { mutableStateOf(false) }
|
||||||
AlertDialogContent(
|
AlertDialogContent(
|
||||||
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
||||||
|
@ -758,7 +758,7 @@ private data class TrackServiceRemoveScreen(
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.track_delete_text, serviceName),
|
text = stringResource(R.string.track_delete_text, serviceName),
|
||||||
)
|
)
|
||||||
if (sm.isServiceDeletable()) {
|
if (sm.isDeletable()) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Checkbox(checked = removeRemoteTrack, onCheckedChange = { removeRemoteTrack = it })
|
Checkbox(checked = removeRemoteTrack, onCheckedChange = { removeRemoteTrack = it })
|
||||||
Text(text = stringResource(R.string.track_delete_remote_text, serviceName))
|
Text(text = stringResource(R.string.track_delete_remote_text, serviceName))
|
||||||
|
@ -798,17 +798,17 @@ private data class TrackServiceRemoveScreen(
|
||||||
private class Model(
|
private class Model(
|
||||||
private val mangaId: Long,
|
private val mangaId: Long,
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val service: TrackService,
|
private val tracker: Tracker,
|
||||||
private val deleteTrack: DeleteTrack = Injekt.get(),
|
private val deleteTrack: DeleteTrack = Injekt.get(),
|
||||||
) : ScreenModel {
|
) : ScreenModel {
|
||||||
|
|
||||||
fun getServiceName() = service.name
|
fun getName() = tracker.name
|
||||||
|
|
||||||
fun isServiceDeletable() = service is DeletableTrackService
|
fun isDeletable() = tracker is DeletableTracker
|
||||||
|
|
||||||
fun deleteMangaFromService() {
|
fun deleteMangaFromService() {
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
(service as DeletableTrackService).delete(track.toDbTrack())
|
(tracker as DeletableTracker).delete(track.toDbTrack())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.manga.track
|
package eu.kanade.tachiyomi.ui.manga.track
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.Tracker
|
||||||
import tachiyomi.domain.track.model.Track
|
import tachiyomi.domain.track.model.Track
|
||||||
|
|
||||||
data class TrackItem(val track: Track?, val service: TrackService)
|
data class TrackItem(val track: Track?, val tracker: Tracker)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.setting.track
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.util.view.setComposeContent
|
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||||
|
@ -12,7 +12,7 @@ import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
abstract class BaseOAuthLoginActivity : BaseActivity() {
|
abstract class BaseOAuthLoginActivity : BaseActivity() {
|
||||||
|
|
||||||
internal val trackManager: TrackManager by injectLazy()
|
internal val trackerManager: TrackerManager by injectLazy()
|
||||||
|
|
||||||
abstract fun handleResult(data: Uri?)
|
abstract fun handleResult(data: Uri?)
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() {
|
||||||
val matchResult = regex.find(data.fragment.toString())
|
val matchResult = regex.find(data.fragment.toString())
|
||||||
if (matchResult?.groups?.get(1) != null) {
|
if (matchResult?.groups?.get(1) != null) {
|
||||||
lifecycleScope.launchIO {
|
lifecycleScope.launchIO {
|
||||||
trackManager.aniList.login(matchResult.groups[1]!!.value)
|
trackerManager.aniList.login(matchResult.groups[1]!!.value)
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trackManager.aniList.logout()
|
trackerManager.aniList.logout()
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() {
|
||||||
val code = data.getQueryParameter("code")
|
val code = data.getQueryParameter("code")
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
lifecycleScope.launchIO {
|
lifecycleScope.launchIO {
|
||||||
trackManager.bangumi.login(code)
|
trackerManager.bangumi.login(code)
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trackManager.bangumi.logout()
|
trackerManager.bangumi.logout()
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() {
|
||||||
val code = data.getQueryParameter("code")
|
val code = data.getQueryParameter("code")
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
lifecycleScope.launchIO {
|
lifecycleScope.launchIO {
|
||||||
trackManager.myAnimeList.login(code)
|
trackerManager.myAnimeList.login(code)
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trackManager.myAnimeList.logout()
|
trackerManager.myAnimeList.logout()
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,11 +59,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() {
|
||||||
val code = data.getQueryParameter("code")
|
val code = data.getQueryParameter("code")
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
lifecycleScope.launchIO {
|
lifecycleScope.launchIO {
|
||||||
trackManager.shikimori.login(code)
|
trackerManager.shikimori.login(code)
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trackManager.shikimori.logout()
|
trackerManager.shikimori.logout()
|
||||||
returnToSettings()
|
returnToSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.kanade.core.util.fastMapNotNull
|
||||||
import eu.kanade.presentation.more.stats.StatsScreenState
|
import eu.kanade.presentation.more.stats.StatsScreenState
|
||||||
import eu.kanade.presentation.more.stats.data.StatsData
|
import eu.kanade.presentation.more.stats.data.StatsData
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
|
@ -33,10 +33,10 @@ class StatsScreenModel(
|
||||||
private val getTotalReadDuration: GetTotalReadDuration = Injekt.get(),
|
private val getTotalReadDuration: GetTotalReadDuration = Injekt.get(),
|
||||||
private val getTracks: GetTracks = Injekt.get(),
|
private val getTracks: GetTracks = Injekt.get(),
|
||||||
private val preferences: LibraryPreferences = Injekt.get(),
|
private val preferences: LibraryPreferences = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackerManager: TrackerManager = Injekt.get(),
|
||||||
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||||
|
|
||||||
private val loggedServices by lazy { trackManager.services.fastFilter { it.isLoggedIn } }
|
private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn } }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
coroutineScope.launchIO {
|
coroutineScope.launchIO {
|
||||||
|
@ -72,7 +72,7 @@ class StatsScreenModel(
|
||||||
val trackersStatData = StatsData.Trackers(
|
val trackersStatData = StatsData.Trackers(
|
||||||
trackedTitleCount = mangaTrackMap.count { it.value.isNotEmpty() },
|
trackedTitleCount = mangaTrackMap.count { it.value.isNotEmpty() },
|
||||||
meanScore = meanScore,
|
meanScore = meanScore,
|
||||||
trackerCount = loggedServices.size,
|
trackerCount = loggedInTrackers.size,
|
||||||
)
|
)
|
||||||
|
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
|
@ -115,10 +115,10 @@ class StatsScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getMangaTrackMap(libraryManga: List<LibraryManga>): Map<Long, List<Track>> {
|
private suspend fun getMangaTrackMap(libraryManga: List<LibraryManga>): Map<Long, List<Track>> {
|
||||||
val loggedServicesIds = loggedServices.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 loggedServicesIds }
|
.fastFilter { it.syncId 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 = trackManager.getService(track.syncId)!!
|
val service = trackerManager.get(track.syncId)!!
|
||||||
return service.get10PointScore(track)
|
return service.get10PointScore(track)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,13 +459,13 @@
|
||||||
<!-- Tracking section -->
|
<!-- Tracking section -->
|
||||||
<string name="tracking_guide">Tracking guide</string>
|
<string name="tracking_guide">Tracking guide</string>
|
||||||
<string name="pref_auto_update_manga_sync">Update progress after reading</string>
|
<string name="pref_auto_update_manga_sync">Update progress after reading</string>
|
||||||
<string name="services">Services</string>
|
<string name="services">Trackers</string>
|
||||||
<string name="tracking_info">One-way sync to update the chapter progress in tracking services. Set up tracking for individual entries from their tracking button.</string>
|
<string name="tracking_info">One-way sync to update the chapter progress in external tracker services. Set up tracking for individual entries from their tracking button.</string>
|
||||||
<string name="enhanced_services">Enhanced services</string>
|
<string name="enhanced_services">Enhanced trackers</string>
|
||||||
<string name="enhanced_services_not_installed">Available but source not installed: %s</string>
|
<string name="enhanced_services_not_installed">Available but source not installed: %s</string>
|
||||||
<string name="enhanced_tracking_info">Services that provide enhanced features for specific sources. Entries are automatically tracked when added to your library.</string>
|
<string name="enhanced_tracking_info">Provides enhanced features for specific sources. Entries are automatically tracked when added to your library.</string>
|
||||||
<string name="action_track">Track</string>
|
<string name="action_track">Track</string>
|
||||||
<string name="track_activity_name">Tracking login</string>
|
<string name="track_activity_name">Tracker login</string>
|
||||||
|
|
||||||
<!-- Browse section -->
|
<!-- Browse section -->
|
||||||
<string name="pref_hide_in_library_items">Hide entries already in library</string>
|
<string name="pref_hide_in_library_items">Hide entries already in library</string>
|
||||||
|
|
Reference in a new issue