diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index f5e428e8a..4da261de6 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -1,7 +1,6 @@ package eu.kanade.domain 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.download.interactor.DeleteDownload 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.ToggleSource 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.SyncChapterProgressWithTrack import eu.kanade.domain.track.interactor.TrackChapter import tachiyomi.data.category.CategoryRepositoryImpl import tachiyomi.data.chapter.ChapterRepositoryImpl @@ -114,11 +115,13 @@ class DomainModule : InjektModule { addSingletonFactory { TrackRepositoryImpl(get()) } addFactory { TrackChapter(get(), get(), get(), get()) } + addFactory { AddTracks(get(), get(), get()) } addFactory { RefreshTracks(get(), get(), get(), get()) } addFactory { DeleteTrack(get()) } addFactory { GetTracksPerManga(get()) } addFactory { GetTracks(get()) } addFactory { InsertTrack(get()) } + addFactory { SyncChapterProgressWithTrack(get(), get(), get()) } addSingletonFactory { ChapterRepositoryImpl(get()) } addFactory { GetChapter(get()) } @@ -127,7 +130,6 @@ class DomainModule : InjektModule { addFactory { SetReadStatus(get(), get(), get(), get()) } addFactory { ShouldUpdateDbChapter() } addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) } - addFactory { SyncChapterProgressWithTrack(get(), get(), get()) } addSingletonFactory { HistoryRepositoryImpl(get()) } addFactory { GetHistory(get()) } diff --git a/app/src/main/java/eu/kanade/domain/track/interactor/AddTracks.kt b/app/src/main/java/eu/kanade/domain/track/interactor/AddTracks.kt new file mode 100644 index 000000000..5a56889fb --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/track/interactor/AddTracks.kt @@ -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() + .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" } + } + } + } + } +} diff --git a/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt b/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt index 87b7c8d99..8c8952304 100644 --- a/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt +++ b/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt @@ -1,10 +1,9 @@ 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.toDomainTrack -import eu.kanade.tachiyomi.data.track.TrackManager -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.Tracker +import eu.kanade.tachiyomi.data.track.TrackerManager import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.supervisorScope @@ -13,7 +12,7 @@ import tachiyomi.domain.track.interactor.InsertTrack class RefreshTracks( private val getTracks: GetTracks, - private val trackManager: TrackManager, + private val trackerManager: TrackerManager, private val insertTrack: InsertTrack, private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack, ) { @@ -23,18 +22,17 @@ class RefreshTracks( * * @return Failed updates. */ - suspend fun await(mangaId: Long): List> { + suspend fun await(mangaId: Long): List> { return supervisorScope { return@supervisorScope getTracks.await(mangaId) - .map { track -> + .map { it to trackerManager.get(it.syncId) } + .filter { (_, service) -> service?.isLoggedIn == true } + .map { (track, service) -> async { - val service = trackManager.getService(track.syncId) return@async try { - if (service?.isLoggedIn == true) { - val updatedTrack = service.refresh(track.toDbTrack()) - insertTrack.await(updatedTrack.toDomainTrack()!!) - syncChapterProgressWithTrack.await(mangaId, track, service) - } + val updatedTrack = service!!.refresh(track.toDbTrack()) + insertTrack.await(updatedTrack.toDomainTrack()!!) + syncChapterProgressWithTrack.await(mangaId, track, service) null } catch (e: Throwable) { service to e diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChapterProgressWithTrack.kt b/app/src/main/java/eu/kanade/domain/track/interactor/SyncChapterProgressWithTrack.kt similarity index 83% rename from app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChapterProgressWithTrack.kt rename to app/src/main/java/eu/kanade/domain/track/interactor/SyncChapterProgressWithTrack.kt index 86862504c..dcb95ff26 100644 --- a/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChapterProgressWithTrack.kt +++ b/app/src/main/java/eu/kanade/domain/track/interactor/SyncChapterProgressWithTrack.kt @@ -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.tachiyomi.data.track.EnhancedTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker import logcat.LogPriority import tachiyomi.core.util.system.logcat import tachiyomi.domain.chapter.interactor.GetChapterByMangaId @@ -20,9 +20,9 @@ class SyncChapterProgressWithTrack( suspend fun await( mangaId: Long, remoteTrack: Track, - service: TrackService, + tracker: Tracker, ) { - if (service !is EnhancedTrackService) { + if (tracker !is EnhancedTracker) { return } @@ -39,7 +39,7 @@ class SyncChapterProgressWithTrack( val updatedTrack = remoteTrack.copy(lastChapterRead = localLastRead.toDouble()) try { - service.update(updatedTrack.toDbTrack()) + tracker.update(updatedTrack.toDbTrack()) updateChapter.awaitAll(chapterUpdates) insertTrack.await(updatedTrack) } catch (e: Throwable) { diff --git a/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt b/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt index 96f2f6ca4..fa6245f22 100644 --- a/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt +++ b/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt @@ -4,30 +4,29 @@ import android.content.Context import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.track.service.DelayedTrackingUpdateJob 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.awaitAll -import kotlinx.coroutines.coroutineScope import logcat.LogPriority -import tachiyomi.core.util.lang.launchNonCancellable +import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.InsertTrack class TrackChapter( private val getTracks: GetTracks, - private val trackManager: TrackManager, + private val trackerManager: TrackerManager, private val insertTrack: InsertTrack, private val delayedTrackingStore: DelayedTrackingStore, ) { - suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) = coroutineScope { - launchNonCancellable { + suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) { + withNonCancellableContext { val tracks = getTracks.await(mangaId) - if (tracks.isEmpty()) return@launchNonCancellable + if (tracks.isEmpty()) return@withNonCancellableContext tracks.mapNotNull { track -> - val service = trackManager.getService(track.syncId) + val service = trackerManager.get(track.syncId) if (service == null || !service.isLoggedIn || chapterNumber <= track.lastChapterRead) { return@mapNotNull null } diff --git a/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt b/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt index 0273e0fdc..f578bd600 100644 --- a/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt +++ b/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt @@ -10,7 +10,7 @@ import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkerParameters import eu.kanade.domain.track.model.toDbTrack 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 logcat.LogPriority import tachiyomi.core.util.lang.withIOContext @@ -33,7 +33,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) val getTracks = Injekt.get() val insertTrack = Injekt.get() - val trackManager = Injekt.get() + val trackerManager = Injekt.get() val delayedTrackingStore = Injekt.get() withIOContext { @@ -47,7 +47,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) } .forEach { track -> try { - val service = trackManager.getService(track.syncId) + val service = trackerManager.get(track.syncId) if (service != null && service.isLoggedIn) { logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.id}, last chapter read: ${track.lastChapterRead}" } service.update(track.toDbTrack(), true) diff --git a/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt b/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt index 2ddba51e0..418d794b9 100644 --- a/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt +++ b/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt @@ -1,6 +1,6 @@ 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 tachiyomi.core.preference.PreferenceStore @@ -8,16 +8,16 @@ class TrackPreferences( 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) 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) diff --git a/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt index 0c8a80217..6d7882f43 100644 --- a/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt @@ -108,13 +108,13 @@ private fun ColumnScope.FilterPage( onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompleted) }, ) - val trackServices = remember { screenModel.trackServices } - when (trackServices.size) { + val trackers = remember { screenModel.trackers } + when (trackers.size) { 0 -> { // No trackers } 1 -> { - val service = trackServices[0] + val service = trackers[0] val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState() TriStateItem( label = stringResource(R.string.action_filter_tracked), @@ -124,7 +124,7 @@ private fun ColumnScope.FilterPage( } else -> { HeadingItem(R.string.action_filter_tracked) - trackServices.map { service -> + trackers.map { service -> val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState() TriStateItem( label = service.name, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt b/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt index fa25ff184..c852e03a3 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource 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 sealed class Preference { @@ -132,10 +132,10 @@ sealed class Preference { ) : PreferenceItem() /** - * A [PreferenceItem] for individual tracking service. + * A [PreferenceItem] for individual tracker. */ - data class TrackingPreference( - val service: TrackService, + data class TrackerPreference( + val tracker: Tracker, override val title: String, val login: () -> Unit, val logout: () -> Unit, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt index 940a48225..b68f17fcd 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt @@ -156,13 +156,13 @@ internal fun PreferenceItem( }, ) } - is Preference.PreferenceItem.TrackingPreference -> { + is Preference.PreferenceItem.TrackerPreference -> { val uName by Injekt.get() - .getString(TrackPreferences.trackUsername(item.service.id)) + .getString(TrackPreferences.trackUsername(item.tracker.id)) .collectAsState() - item.service.run { + item.tracker.run { TrackingPreferenceWidget( - service = this, + tracker = this, checked = uName.isNotEmpty(), onClick = { if (isLoggedIn) item.logout() else item.login() }, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt index cd600969c..cad067a98 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt @@ -34,7 +34,7 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.download.DownloadCache 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.NetworkPreferences import eu.kanade.tachiyomi.network.PREF_DOH_360 @@ -328,7 +328,7 @@ object SettingsAdvancedScreen : SearchableSettings { private fun getLibraryGroup(): Preference.PreferenceGroup { val scope = rememberCoroutineScope() val context = LocalContext.current - val trackManager = remember { Injekt.get() } + val trackerManager = remember { Injekt.get() } return Preference.PreferenceGroup( title = stringResource(R.string.label_library), @@ -340,7 +340,7 @@ object SettingsAdvancedScreen : SearchableSettings { Preference.PreferenceItem.TextPreference( title = stringResource(R.string.pref_refresh_library_tracking), subtitle = stringResource(R.string.pref_refresh_library_tracking_summary), - enabled = trackManager.hasLoggedServices(), + enabled = trackerManager.hasLoggedIn(), onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.TRACKING) }, ), Preference.PreferenceItem.TextPreference( diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt index 35552e225..0e71d4cdb 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt @@ -23,7 +23,7 @@ import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.widget.TriStateListDialog import eu.kanade.tachiyomi.R 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 kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -199,7 +199,7 @@ object SettingsLibraryScreen : SearchableSettings { ), Preference.PreferenceItem.SwitchPreference( pref = libraryPreferences.autoUpdateTrackers(), - enabled = Injekt.get().hasLoggedServices(), + enabled = Injekt.get().hasLoggedIn(), title = stringResource(R.string.pref_library_update_refresh_trackers), subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary), ), diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt index d57034536..655d79cc2 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt @@ -44,9 +44,9 @@ import androidx.compose.ui.unit.dp import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.presentation.more.settings.Preference import eu.kanade.tachiyomi.R -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.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker +import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.anilist.AnilistApi import eu.kanade.tachiyomi.data.track.bangumi.BangumiApi import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeListApi @@ -82,7 +82,7 @@ object SettingsTrackingScreen : SearchableSettings { override fun getPreferences(): List { val context = LocalContext.current val trackPreferences = remember { Injekt.get() } - val trackManager = remember { Injekt.get() } + val trackerManager = remember { Injekt.get() } val sourceManager = remember { Injekt.get() } var dialog by remember { mutableStateOf(null) } @@ -90,24 +90,24 @@ object SettingsTrackingScreen : SearchableSettings { when (this) { is LoginDialog -> { TrackingLoginDialog( - service = service, + tracker = tracker, uNameStringRes = uNameStringRes, onDismissRequest = { dialog = null }, ) } is LogoutDialog -> { TrackingLogoutDialog( - service = service, + tracker = tracker, onDismissRequest = { dialog = null }, ) } } } - val enhancedTrackers = trackManager.services - .filter { it is EnhancedTrackService } + val enhancedTrackers = trackerManager.trackers + .filter { it is EnhancedTracker } .partition { service -> - val acceptedSources = (service as EnhancedTrackService).getAcceptedSources() + val acceptedSources = (service as EnhancedTracker).getAcceptedSources() sourceManager.getCatalogueSources().any { it::class.qualifiedName in acceptedSources } } var enhancedTrackerInfo = stringResource(R.string.enhanced_tracking_info) @@ -127,41 +127,41 @@ object SettingsTrackingScreen : SearchableSettings { Preference.PreferenceGroup( title = stringResource(R.string.services), preferenceItems = listOf( - Preference.PreferenceItem.TrackingPreference( - title = trackManager.myAnimeList.name, - service = trackManager.myAnimeList, + Preference.PreferenceItem.TrackerPreference( + title = trackerManager.myAnimeList.name, + tracker = trackerManager.myAnimeList, login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) }, - logout = { dialog = LogoutDialog(trackManager.myAnimeList) }, + logout = { dialog = LogoutDialog(trackerManager.myAnimeList) }, ), - Preference.PreferenceItem.TrackingPreference( - title = trackManager.aniList.name, - service = trackManager.aniList, + Preference.PreferenceItem.TrackerPreference( + title = trackerManager.aniList.name, + tracker = trackerManager.aniList, login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) }, - logout = { dialog = LogoutDialog(trackManager.aniList) }, + logout = { dialog = LogoutDialog(trackerManager.aniList) }, ), - Preference.PreferenceItem.TrackingPreference( - title = trackManager.kitsu.name, - service = trackManager.kitsu, - login = { dialog = LoginDialog(trackManager.kitsu, R.string.email) }, - logout = { dialog = LogoutDialog(trackManager.kitsu) }, + Preference.PreferenceItem.TrackerPreference( + title = trackerManager.kitsu.name, + tracker = trackerManager.kitsu, + login = { dialog = LoginDialog(trackerManager.kitsu, R.string.email) }, + logout = { dialog = LogoutDialog(trackerManager.kitsu) }, ), - Preference.PreferenceItem.TrackingPreference( - title = trackManager.mangaUpdates.name, - service = trackManager.mangaUpdates, - login = { dialog = LoginDialog(trackManager.mangaUpdates, R.string.username) }, - logout = { dialog = LogoutDialog(trackManager.mangaUpdates) }, + Preference.PreferenceItem.TrackerPreference( + title = trackerManager.mangaUpdates.name, + tracker = trackerManager.mangaUpdates, + login = { dialog = LoginDialog(trackerManager.mangaUpdates, R.string.username) }, + logout = { dialog = LogoutDialog(trackerManager.mangaUpdates) }, ), - Preference.PreferenceItem.TrackingPreference( - title = trackManager.shikimori.name, - service = trackManager.shikimori, + Preference.PreferenceItem.TrackerPreference( + title = trackerManager.shikimori.name, + tracker = trackerManager.shikimori, login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) }, - logout = { dialog = LogoutDialog(trackManager.shikimori) }, + logout = { dialog = LogoutDialog(trackerManager.shikimori) }, ), - Preference.PreferenceItem.TrackingPreference( - title = trackManager.bangumi.name, - service = trackManager.bangumi, + Preference.PreferenceItem.TrackerPreference( + title = trackerManager.bangumi.name, + tracker = trackerManager.bangumi, 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)), ), @@ -170,10 +170,10 @@ object SettingsTrackingScreen : SearchableSettings { title = stringResource(R.string.enhanced_services), preferenceItems = enhancedTrackers.first .map { service -> - Preference.PreferenceItem.TrackingPreference( + Preference.PreferenceItem.TrackerPreference( title = service.name, - service = service, - login = { (service as EnhancedTrackService).loginNoop() }, + tracker = service, + login = { (service as EnhancedTracker).loginNoop() }, logout = service::logout, ) } + listOf(Preference.PreferenceItem.InfoPreference(enhancedTrackerInfo)), @@ -183,15 +183,15 @@ object SettingsTrackingScreen : SearchableSettings { @Composable private fun TrackingLoginDialog( - service: TrackService, + tracker: Tracker, @StringRes uNameStringRes: Int, onDismissRequest: () -> Unit, ) { val context = LocalContext.current val scope = rememberCoroutineScope() - var username by remember { mutableStateOf(TextFieldValue(service.getUsername())) } - var password by remember { mutableStateOf(TextFieldValue(service.getPassword())) } + var username by remember { mutableStateOf(TextFieldValue(tracker.getUsername())) } + var password by remember { mutableStateOf(TextFieldValue(tracker.getPassword())) } var processing by remember { mutableStateOf(false) } var inputError by remember { mutableStateOf(false) } @@ -200,7 +200,7 @@ object SettingsTrackingScreen : SearchableSettings { title = { Row(verticalAlignment = Alignment.CenterVertically) { Text( - text = stringResource(R.string.login_title, service.name), + text = stringResource(R.string.login_title, tracker.name), modifier = Modifier.weight(1f), ) IconButton(onClick = onDismissRequest) { @@ -264,7 +264,7 @@ object SettingsTrackingScreen : SearchableSettings { processing = true val result = checkLogin( context = context, - service = service, + tracker = tracker, username = username.text, password = password.text, ) @@ -283,16 +283,16 @@ object SettingsTrackingScreen : SearchableSettings { private suspend fun checkLogin( context: Context, - service: TrackService, + tracker: Tracker, username: String, password: String, ): Boolean { return try { - service.login(username, password) + tracker.login(username, password) withUIContext { context.toast(R.string.login_success) } true } catch (e: Throwable) { - service.logout() + tracker.logout() withUIContext { context.toast(e.message.toString()) } false } @@ -300,7 +300,7 @@ object SettingsTrackingScreen : SearchableSettings { @Composable private fun TrackingLogoutDialog( - service: TrackService, + tracker: Tracker, onDismissRequest: () -> Unit, ) { val context = LocalContext.current @@ -308,7 +308,7 @@ object SettingsTrackingScreen : SearchableSettings { onDismissRequest = onDismissRequest, title = { Text( - text = stringResource(R.string.logout_title, service.name), + text = stringResource(R.string.logout_title, tracker.name), textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth(), ) @@ -324,7 +324,7 @@ object SettingsTrackingScreen : SearchableSettings { Button( modifier = Modifier.weight(1f), onClick = { - service.logout() + tracker.logout() onDismissRequest() context.toast(R.string.logout_success) }, @@ -342,10 +342,10 @@ object SettingsTrackingScreen : SearchableSettings { } private data class LoginDialog( - val service: TrackService, + val tracker: Tracker, @StringRes val uNameStringRes: Int, ) private data class LogoutDialog( - val service: TrackService, + val tracker: Tracker, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt index e0c34fbc4..d8544d156 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt @@ -20,12 +20,12 @@ import androidx.compose.ui.unit.dp import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted import eu.kanade.presentation.track.components.TrackLogoIcon import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.Tracker @Composable fun TrackingPreferenceWidget( modifier: Modifier = Modifier, - service: TrackService, + tracker: Tracker, checked: Boolean, onClick: (() -> Unit)? = null, ) { @@ -38,9 +38,9 @@ fun TrackingPreferenceWidget( .padding(horizontal = PrefsHorizontalPadding, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { - TrackLogoIcon(service) + TrackLogoIcon(tracker) Text( - text = service.name, + text = tracker.name, modifier = Modifier .weight(1f) .padding(horizontal = 16.dp), diff --git a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt index d9a899d5d..bf7860147 100644 --- a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt +++ b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt @@ -49,7 +49,7 @@ import eu.kanade.domain.track.model.toDbTrack import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.track.components.TrackLogoIcon 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.util.system.copyToClipboard import java.text.DateFormat @@ -80,12 +80,12 @@ fun TrackInfoDialogHome( ) { trackItems.forEach { item -> if (item.track != null) { - val supportsScoring = item.service.getScoreList().isNotEmpty() - val supportsReadingDates = item.service.supportsReadingDates + val supportsScoring = item.tracker.getScoreList().isNotEmpty() + val supportsReadingDates = item.tracker.supportsReadingDates TrackInfoItem( title = item.track.title, - service = item.service, - status = item.service.getStatus(item.track.status.toInt()), + tracker = item.tracker, + status = item.tracker.getStatus(item.track.status.toInt()), onStatusClick = { onStatusClick(item) }, chapters = "${item.track.lastChapterRead.toInt()}".let { val totalChapters = item.track.totalChapters @@ -97,7 +97,7 @@ fun TrackInfoDialogHome( } }, onChaptersClick = { onChapterClick(item) }, - score = item.service.displayScore(item.track.toDbTrack()) + score = item.tracker.displayScore(item.track.toDbTrack()) .takeIf { supportsScoring && item.track.score != 0.0 }, onScoreClick = { onScoreClick(item) } .takeIf { supportsScoring }, @@ -115,7 +115,7 @@ fun TrackInfoDialogHome( ) } else { TrackInfoItemEmpty( - service = item.service, + tracker = item.tracker, onNewSearch = { onNewSearch(item) }, ) } @@ -126,7 +126,7 @@ fun TrackInfoDialogHome( @Composable private fun TrackInfoItem( title: String, - service: TrackService, + tracker: Tracker, @StringRes status: Int?, onStatusClick: () -> Unit, chapters: String, @@ -147,7 +147,7 @@ private fun TrackInfoItem( verticalAlignment = Alignment.CenterVertically, ) { TrackLogoIcon( - service = service, + tracker = tracker, onClick = onOpenInBrowser, ) Box( @@ -260,13 +260,13 @@ private fun TrackDetailsItem( @Composable private fun TrackInfoItemEmpty( - service: TrackService, + tracker: Tracker, onNewSearch: () -> Unit, ) { Row( verticalAlignment = Alignment.CenterVertically, ) { - TrackLogoIcon(service) + TrackLogoIcon(tracker) TextButton( onClick = onNewSearch, modifier = Modifier diff --git a/app/src/main/java/eu/kanade/presentation/track/TrackServiceSearch.kt b/app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt similarity index 99% rename from app/src/main/java/eu/kanade/presentation/track/TrackServiceSearch.kt rename to app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt index 1ac38ecf0..c2b951453 100644 --- a/app/src/main/java/eu/kanade/presentation/track/TrackServiceSearch.kt +++ b/app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt @@ -70,7 +70,7 @@ import tachiyomi.presentation.core.util.runOnEnterKeyPressed import tachiyomi.presentation.core.util.secondaryItemAlpha @Composable -fun TrackServiceSearch( +fun TrackerSearch( query: TextFieldValue, onQueryChange: (TextFieldValue) -> Unit, onDispatchQuery: () -> Unit, diff --git a/app/src/main/java/eu/kanade/presentation/track/components/TrackLogoIcon.kt b/app/src/main/java/eu/kanade/presentation/track/components/TrackLogoIcon.kt index 44d98cbd2..52bf66575 100644 --- a/app/src/main/java/eu/kanade/presentation/track/components/TrackLogoIcon.kt +++ b/app/src/main/java/eu/kanade/presentation/track/components/TrackLogoIcon.kt @@ -12,12 +12,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource 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 @Composable fun TrackLogoIcon( - service: TrackService, + tracker: Tracker, onClick: (() -> Unit)? = null, ) { val modifier = if (onClick != null) { @@ -29,13 +29,13 @@ fun TrackLogoIcon( Box( modifier = modifier .size(48.dp) - .background(color = Color(service.getLogoColor()), shape = MaterialTheme.shapes.medium) + .background(color = Color(tracker.getLogoColor()), shape = MaterialTheme.shapes.medium) .padding(4.dp), contentAlignment = Alignment.Center, ) { Image( - painter = painterResource(service.getLogo()), - contentDescription = service.name, + painter = painterResource(tracker.getLogo()), + contentDescription = tracker.name, ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index 481ff079a..51bd28098 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadProvider 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.network.JavaScriptEngine import eu.kanade.tachiyomi.network.NetworkHelper @@ -132,7 +132,7 @@ class AppModule(val app: Application) : InjektModule { addSingletonFactory { DownloadManager(app) } addSingletonFactory { DownloadCache(app) } - addSingletonFactory { TrackManager(app) } + addSingletonFactory { TrackerManager() } addSingletonFactory { DelayedTrackingStore(app) } addSingletonFactory { ImageSaver(app) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index 3c15c913d..c3b4db069 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -9,7 +9,7 @@ import eu.kanade.domain.ui.UiPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.data.backup.BackupCreateJob 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.PREF_DOH_CLOUDFLARE import eu.kanade.tachiyomi.ui.reader.setting.OrientationType @@ -47,7 +47,7 @@ object Migrations { libraryPreferences: LibraryPreferences, readerPreferences: ReaderPreferences, backupPreferences: BackupPreferences, - trackManager: TrackManager, + trackerManager: TrackerManager, ): Boolean { val lastVersionCode = preferenceStore.getInt("last_version_code", 0) val oldVersion = lastVersionCode.get() @@ -135,8 +135,8 @@ object Migrations { // Force MAL log out due to login flow change // v52: switched from scraping to WebView // v53: switched from WebView to OAuth - if (trackManager.myAnimeList.isLoggedIn) { - trackManager.myAnimeList.logout() + if (trackerManager.myAnimeList.isLoggedIn) { + trackerManager.myAnimeList.logout() context.toast(R.string.myanimelist_relogin) } } @@ -342,7 +342,7 @@ object Migrations { "pref_filter_library_started", "pref_filter_library_bookmarked", "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 -> val pref = preferenceStore.getInt(key, 0) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt index 0fe9ddff9..ea8f3c9ea 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.backup import android.content.Context import android.net.Uri 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 tachiyomi.domain.source.service.SourceManager import uy.kohesive.injekt.Injekt @@ -11,7 +11,7 @@ import uy.kohesive.injekt.api.get class BackupFileValidator( 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 } .distinct() val missingTrackers = trackers - .mapNotNull { trackManager.getService(it.toLong()) } + .mapNotNull { trackerManager.get(it.toLong()) } .filter { !it.isLoggedIn } .map { it.name } .sorted() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/DeletableTrackService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/DeletableTracker.kt similarity index 56% rename from app/src/main/java/eu/kanade/tachiyomi/data/track/DeletableTrackService.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/track/DeletableTracker.kt index 7f1494707..c61c55e78 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/DeletableTrackService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/DeletableTracker.kt @@ -3,9 +3,9 @@ package eu.kanade.tachiyomi.data.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 } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/EnhancedTrackService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/EnhancedTracker.kt similarity index 62% rename from app/src/main/java/eu/kanade/tachiyomi/data/track/EnhancedTrackService.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/track/EnhancedTracker.kt index 75245cf80..a501cded8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/EnhancedTrackService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/EnhancedTracker.kt @@ -6,31 +6,32 @@ import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.track.model.Track /** - * An Enhanced Track Service will never prompt the user to match a manga with the remote. - * It is expected that such Track Service can only work with specific sources and unique IDs. + * A tracker that will never prompt the user to manually bind an entry. + * 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 { 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 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? /** - * 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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt similarity index 95% rename from app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt index e30100e29..490ea0e96 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt @@ -5,7 +5,7 @@ import androidx.annotation.CallSuper import androidx.annotation.ColorInt import androidx.annotation.DrawableRes 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.toDomainTrack import eu.kanade.domain.track.service.TrackPreferences @@ -28,7 +28,7 @@ import uy.kohesive.injekt.injectLazy import java.time.ZoneOffset 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 networkService: NetworkHelper by injectLazy() @@ -83,7 +83,7 @@ abstract class TrackService(val id: Long, val name: String) { @CallSuper open fun logout() { - trackPreferences.setTrackCredentials(this, "", "") + trackPreferences.setCredentials(this, "", "") } open val isLoggedIn: Boolean @@ -95,7 +95,7 @@ abstract class TrackService(val id: Long, val name: String) { fun getPassword() = trackPreferences.trackPassword(this).get() 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 @@ -111,7 +111,7 @@ abstract class TrackService(val id: Long, val name: String) { insertTrack.await(track) - // TODO: merge into SyncChaptersWithTrackServiceTwoWay? + // TODO: merge into [SyncChapterProgressWithTrack]? // Update chapter progress if newer chapters marked read locally if (hasReadChapters) { 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) { withUIContext { Injekt.get().toast(e.message) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackerManager.kt similarity index 51% rename from app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/track/TrackerManager.kt index c6d62c382..3943537e2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackerManager.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.data.track -import android.content.Context import eu.kanade.tachiyomi.data.track.anilist.Anilist import eu.kanade.tachiyomi.data.track.bangumi.Bangumi 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.suwayomi.Suwayomi -class TrackManager(context: Context) { +class TrackerManager { companion object { - const val MYANIMELIST = 1L const val ANILIST = 2L 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 SUWAYOMI = 9L } - val myAnimeList = MyAnimeList(MYANIMELIST) + val myAnimeList = MyAnimeList(1L) val aniList = Anilist(ANILIST) val kitsu = Kitsu(KITSU) - val shikimori = Shikimori(SHIKIMORI) - val bangumi = Bangumi(BANGUMI) - val komga = Komga(KOMGA) - val mangaUpdates = MangaUpdates(MANGA_UPDATES) - val kavita = Kavita(context, KAVITA) - val suwayomi = Suwayomi(SUWAYOMI) + val shikimori = Shikimori(4L) + val bangumi = Bangumi(5L) + val komga = Komga(6L) + val mangaUpdates = MangaUpdates(7L) + val kavita = Kavita(KAVITA) + 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 } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt index c6365106e..3ecf9119d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt @@ -4,15 +4,15 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.DeletableTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.DeletableTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import uy.kohesive.injekt.injectLazy 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 { const val READING = 1 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt index 0e39d680f..46de5e735 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.track.anilist import eu.kanade.domain.track.service.TrackPreferences 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 kotlinx.serialization.Serializable import uy.kohesive.injekt.injectLazy @@ -20,7 +20,7 @@ data class ALManga( val total_chapters: Int, ) { - fun toTrack() = TrackSearch.create(TrackManager.ANILIST).apply { + fun toTrack() = TrackSearch.create(TrackerManager.ANILIST).apply { media_id = this@ALManga.media_id title = title_user_pref total_chapters = this@ALManga.total_chapters @@ -50,7 +50,7 @@ data class ALUserManga( val manga: ALManga, ) { - fun toTrack() = Track.create(TrackManager.ANILIST).apply { + fun toTrack() = Track.create(TrackerManager.ANILIST).apply { media_id = manga.media_id title = manga.title_user_pref status = toTrackStatus() @@ -62,7 +62,7 @@ data class ALUserManga( total_chapters = manga.total_chapters } - fun toTrackStatus() = when (list_status) { + private fun toTrackStatus() = when (list_status) { "CURRENT" -> Anilist.READING "COMPLETED" -> Anilist.COMPLETED "PAUSED" -> Anilist.ON_HOLD diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt index f5d8ecc0d..71aff2f2a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt @@ -4,19 +4,19 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R 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 kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json 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 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 { return IntRange(0, 10).map(Int::toString) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt index 444487df1..6762fdcaf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.bangumi import android.net.Uri import androidx.core.net.toUri 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.network.GET import eu.kanade.tachiyomi.network.POST @@ -26,7 +25,11 @@ import uy.kohesive.injekt.injectLazy import java.net.URLEncoder 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() @@ -105,7 +108,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept } else { 0 } - return TrackSearch.create(TrackManager.BANGUMI).apply { + return TrackSearch.create(trackId).apply { media_id = obj["id"]!!.jsonPrimitive.long title = obj["name_cn"]!!.jsonPrimitive.content cover_url = coverUrl diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt index c11730754..f90038161 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt @@ -1,20 +1,21 @@ package eu.kanade.tachiyomi.data.track.kavita -import android.content.Context -import android.content.SharedPreferences import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.EnhancedTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch +import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.Source import tachiyomi.domain.manga.model.Manga +import tachiyomi.domain.source.service.SourceManager +import uy.kohesive.injekt.injectLazy import java.security.MessageDigest 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 { 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) } val api by lazy { KavitaApi(client, interceptor) } + private val sourceManager: SourceManager by injectLazy() + override fun getLogo(): Int = R.drawable.ic_tracker_kavita 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") } - // 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 override fun loginNoop() { saveCredentials("user", "pass") @@ -110,28 +113,29 @@ class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita" fun loadOAuth() { val oauth = OAuth() - for (sourceId in 1..3) { - val authentication = oauth.authentications[sourceId - 1] - val sourceSuffixID by lazy { - val key = "kavita_$sourceId/all/1" // Hardcoded versionID to 1 + for (id in 1..3) { + val authentication = oauth.authentications[id - 1] + val sourceId by lazy { + val key = "kavita_$id/all/1" // Hardcoded versionID to 1 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 } - val preferences: SharedPreferences by lazy { - context.getSharedPreferences("source_$sourceSuffixID", Context.MODE_PRIVATE) - } - val prefApiUrl = preferences.getString("APIURL", "")!! - if (prefApiUrl.isEmpty()) { + val preferences = (sourceManager.get(sourceId) as ConfigurableSource).getPreferences() + + val prefApiUrl = preferences.getString("APIURL", "") + val prefApiKey = preferences.getString("APIKEY", "") + if (prefApiUrl.isNullOrEmpty() || prefApiKey.isNullOrEmpty()) { // Source not configured. Skip continue } - val prefApiKey = preferences.getString("APIKEY", "")!! + val token = api.getNewToken(apiUrl = prefApiUrl, apiKey = prefApiKey) if (token.isNullOrEmpty()) { // Source is not accessible. Skip continue } + authentication.apiUrl = prefApiUrl authentication.jwtToken = token.toString() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/KavitaModels.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/KavitaModels.kt index 3900c3f39..6f42f6836 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/KavitaModels.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/KavitaModels.kt @@ -1,6 +1,6 @@ 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 kotlinx.serialization.Serializable @@ -22,7 +22,7 @@ data class SeriesDto( val libraryId: Int, val libraryName: String? = "", ) { - fun toTrack(): TrackSearch = TrackSearch.create(TrackManager.KAVITA).also { + fun toTrack(): TrackSearch = TrackSearch.create(TrackerManager.KAVITA).also { it.title = name it.summary = "" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt index ade2456bb..a2764c685 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt @@ -4,15 +4,15 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.DeletableTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.DeletableTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import uy.kohesive.injekt.injectLazy import java.text.DecimalFormat -class Kitsu(id: Long) : TrackService(id, "Kitsu"), DeletableTrackService { +class Kitsu(id: Long) : Tracker(id, "Kitsu"), DeletableTracker { companion object { const val READING = 1 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuModels.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuModels.kt index 915c7ae8b..1cbf16c71 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuModels.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuModels.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.track.kitsu import androidx.annotation.CallSuper 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 kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonObject @@ -35,7 +35,7 @@ class KitsuSearchManga(obj: JsonObject) { private val endDate = obj["endDate"]?.jsonPrimitive?.contentOrNull @CallSuper - fun toTrack() = TrackSearch.create(TrackManager.KITSU).apply { + fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply { media_id = this@KitsuSearchManga.id title = canonicalTitle total_chapters = chapterCount ?: 0 @@ -67,7 +67,7 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) { private val ratingTwenty = obj["attributes"]!!.jsonObject["ratingTwenty"]?.jsonPrimitive?.contentOrNull 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 title = canonicalTitle total_chapters = chapterCount ?: 0 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt index 8937bd21a..450e502be 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt @@ -4,8 +4,8 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.EnhancedTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.source.Source import okhttp3.Dns @@ -13,7 +13,7 @@ import okhttp3.OkHttpClient import tachiyomi.domain.manga.model.Manga 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 { 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 .build() - val api by lazy { KomgaApi(client) } + val api by lazy { KomgaApi(id, client) } override fun getLogo() = R.drawable.ic_tracker_komga @@ -85,7 +85,7 @@ class Komga(id: Long) : TrackService(id, "Komga"), EnhancedTrackService { 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 override fun loginNoop() { saveCredentials("user", "pass") diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/KomgaApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/KomgaApi.kt index 89e7fafbd..5992727ae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/KomgaApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/KomgaApi.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.data.track.komga 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.network.GET import eu.kanade.tachiyomi.network.awaitSuccess @@ -19,7 +18,10 @@ import uy.kohesive.injekt.injectLazy 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() @@ -85,13 +87,13 @@ class KomgaApi(private val client: OkHttpClient) { 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.summary = metadata.summary 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 } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt index 33df93222..417f6acb8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt @@ -4,13 +4,13 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.DeletableTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.DeletableTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.mangaupdates.dto.copyTo import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch 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 { const val READING_LIST = 0 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt index 3acbb035d..cd0d1eb1b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt @@ -4,14 +4,14 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.DeletableTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.DeletableTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import uy.kohesive.injekt.injectLazy -class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), DeletableTrackService { +class MyAnimeList(id: Long) : Tracker(id, "MyAnimeList"), DeletableTracker { companion object { const val READING = 1 @@ -28,7 +28,7 @@ class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), DeletableTrackSer private val json: Json by injectLazy() 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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt index 1bfb4e581..d66a4c561 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.myanimelist import android.net.Uri import androidx.core.net.toUri 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.network.GET import eu.kanade.tachiyomi.network.POST @@ -32,7 +31,11 @@ import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat 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() @@ -106,7 +109,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI .parseAs() .let { val obj = it.jsonObject - TrackSearch.create(TrackManager.MYANIMELIST).apply { + TrackSearch.create(trackId).apply { media_id = obj["id"]!!.jsonPrimitive.long title = obj["title"]!!.jsonPrimitive.content summary = obj["synopsis"]?.jsonPrimitive?.content ?: "" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt index 463059055..312c9acbd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt @@ -4,14 +4,14 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.DeletableTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.DeletableTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import uy.kohesive.injekt.injectLazy -class Shikimori(id: Long) : TrackService(id, "Shikimori"), DeletableTrackService { +class Shikimori(id: Long) : Tracker(id, "Shikimori"), DeletableTracker { companion object { 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 api by lazy { ShikimoriApi(client, interceptor) } + private val api by lazy { ShikimoriApi(id, client, interceptor) } override fun getScoreList(): List { return IntRange(0, 10).map(Int::toString) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt index 0137ed6df..fd62f18fc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/ShikimoriApi.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.track.shikimori import androidx.core.net.toUri 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.network.DELETE import eu.kanade.tachiyomi.network.GET @@ -28,7 +27,11 @@ import okhttp3.RequestBody.Companion.toRequestBody import tachiyomi.core.util.lang.withIOContext 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() @@ -96,7 +99,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter } private fun jsonToSearch(obj: JsonObject): TrackSearch { - return TrackSearch.create(TrackManager.SHIKIMORI).apply { + return TrackSearch.create(trackId).apply { media_id = obj["id"]!!.jsonPrimitive.long title = obj["name"]!!.jsonPrimitive.content 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 { - return Track.create(TrackManager.SHIKIMORI).apply { + return Track.create(trackId).apply { title = mangas["name"]!!.jsonPrimitive.content media_id = obj["id"]!!.jsonPrimitive.long total_chapters = mangas["chapters"]!!.jsonPrimitive.int diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt index 3958bfa2e..2c7fd67c4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt @@ -4,16 +4,16 @@ import android.graphics.Color import androidx.annotation.StringRes import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.track.EnhancedTrackService -import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.source.Source import tachiyomi.domain.manga.model.Manga as DomainManga 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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/TachideskApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/SuwayomiApi.kt similarity index 87% rename from app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/TachideskApi.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/SuwayomiApi.kt index 86227095d..5c5367bec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/TachideskApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/SuwayomiApi.kt @@ -4,7 +4,6 @@ import android.app.Application import android.content.Context import android.content.SharedPreferences 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.network.GET import eu.kanade.tachiyomi.network.NetworkHelper @@ -24,7 +23,7 @@ import uy.kohesive.injekt.injectLazy import java.nio.charset.Charset import java.security.MessageDigest -class TachideskApi { +class SuwayomiApi(private val trackId: Long) { private val network: NetworkHelper by injectLazy() private val json: Json by injectLazy() @@ -62,7 +61,7 @@ class TachideskApi { .parseAs() } - TrackSearch.create(TrackManager.SUWAYOMI).apply { + TrackSearch.create(trackId).apply { title = manga.title cover_url = "$url/thumbnail" summary = manga.description.orEmpty() @@ -101,26 +100,24 @@ class TachideskApi { return getTrackSearch(track.tracking_url) } - private val tachideskExtensionId by lazy { + private val sourceId by lazy { val key = "tachidesk/en/1" 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 } private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$tachideskExtensionId", Context.MODE_PRIVATE) + Injekt.get().getSharedPreferences("source_$sourceId", Context.MODE_PRIVATE) } private fun getPrefBaseUrl(): String = preferences.getString(ADDRESS_TITLE, ADDRESS_DEFAULT)!! private fun getPrefBaseLogin(): String = preferences.getString(LOGIN_TITLE, LOGIN_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_DEFAULT = "" - private const val LOGIN_TITLE = "Login (Basic Auth)" - private const val LOGIN_DEFAULT = "" - private const val PASSWORD_TITLE = "Password (Basic Auth)" - private const val PASSWORD_DEFAULT = "" - } } + +private const val ADDRESS_TITLE = "Server URL Address" +private const val ADDRESS_DEFAULT = "" +private const val LOGIN_TITLE = "Login (Basic Auth)" +private const val LOGIN_DEFAULT = "" +private const val PASSWORD_TITLE = "Password (Basic Auth)" +private const val PASSWORD_DEFAULT = "" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/TachideskDto.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/SuwayomiModels.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/TachideskDto.kt rename to app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/SuwayomiModels.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt index ab1431fe8..ac8964412 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt @@ -35,8 +35,8 @@ import eu.kanade.domain.manga.model.toSManga import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadManager -import eu.kanade.tachiyomi.data.track.EnhancedTrackService -import eu.kanade.tachiyomi.data.track.TrackManager +import eu.kanade.tachiyomi.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags @@ -177,7 +177,7 @@ internal class MigrateDialogScreenModel( } private val enhancedServices by lazy { - Injekt.get().services.filterIsInstance() + Injekt.get().trackers.filterIsInstance() } suspend fun migrateManga( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index 188b148eb..b99a67608 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -15,16 +15,12 @@ import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.core.preference.asState 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.model.toDomainManga 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.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.model.FilterList import eu.kanade.tachiyomi.util.removeCovers @@ -37,11 +33,9 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import logcat.LogPriority import tachiyomi.core.preference.CheckboxState import tachiyomi.core.preference.mapAsCheckboxState import tachiyomi.core.util.lang.launchIO -import tachiyomi.core.util.system.logcat import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.SetMangaCategories 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.source.interactor.GetRemoteManga import tachiyomi.domain.source.service.SourceManager -import tachiyomi.domain.track.interactor.InsertTrack import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.util.Date @@ -76,12 +69,9 @@ class BrowseSourceScreenModel( private val getManga: GetManga = Injekt.get(), private val networkToLocalManga: NetworkToLocalManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), - private val insertTrack: InsertTrack = Injekt.get(), - private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack = Injekt.get(), + private val addTracks: AddTracks = Injekt.get(), ) : StateScreenModel(State(Listing.valueOf(listingQuery))) { - private val loggedServices by lazy { Injekt.get().services.filter { it.isLoggedIn } } - var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope) val source = sourceManager.getOrStub(sourceId) @@ -243,8 +233,7 @@ class BrowseSourceScreenModel( new = new.removeCovers(coverCache) } else { setMangaDefaultChapterFlags.await(manga) - - autoAddTrack(manga) + addTracks.bindEnhancedTracks(manga, source) } updateManga.await(new.toMangaUpdate()) @@ -281,25 +270,6 @@ class BrowseSourceScreenModel( } } - private suspend fun autoAddTrack(manga: Manga) { - loggedServices - .filterIsInstance() - .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. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 99b964cae..3f0408094 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -23,7 +23,7 @@ import eu.kanade.presentation.manga.DownloadAction import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadCache 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.online.HttpSource import eu.kanade.tachiyomi.util.chapter.getNextUnread @@ -88,7 +88,7 @@ class LibraryScreenModel( private val sourceManager: SourceManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(), private val downloadCache: DownloadCache = Injekt.get(), - private val trackManager: TrackManager = Injekt.get(), + private val trackerManager: TrackerManager = Injekt.get(), ) : StateScreenModel(State()) { var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(coroutineScope) @@ -101,9 +101,9 @@ class LibraryScreenModel( getTracksPerManga.subscribe(), getTrackingFilterFlow(), downloadCache.changes, - ) { searchQuery, library, tracks, loggedInTrackServices, _ -> + ) { searchQuery, library, tracks, loggedInTrackers, _ -> library - .applyFilters(tracks, loggedInTrackServices) + .applyFilters(tracks, loggedInTrackers) .applySort() .mapValues { (_, value) -> if (searchQuery != null) { @@ -169,7 +169,7 @@ class LibraryScreenModel( */ private suspend fun LibraryMap.applyFilters( trackMap: Map>, - loggedInTrackServices: Map, + loggedInTrackers: Map, ): LibraryMap { val prefs = getLibraryItemPreferencesFlow().first() val downloadedOnly = prefs.globalFilterDownloaded @@ -180,10 +180,10 @@ class LibraryScreenModel( val filterBookmarked = prefs.filterBookmarked 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 includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null } + val excludedTracks = loggedInTrackers.mapNotNull { if (it.value == TriState.ENABLED_NOT) 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 filterFnDownloaded: (LibraryItem) -> Boolean = { @@ -366,14 +366,14 @@ class LibraryScreenModel( * @return map of track id with the filter value */ private fun getTrackingFilterFlow(): Flow> { - val loggedServices = trackManager.services.filter { it.isLoggedIn } - return if (loggedServices.isNotEmpty()) { - val prefFlows = loggedServices + val loggedInTrackers = trackerManager.trackers.filter { it.isLoggedIn } + return if (loggedInTrackers.isNotEmpty()) { + val prefFlows = loggedInTrackers .map { libraryPreferences.filterTracking(it.id.toInt()).changes() } .toTypedArray() combine(*prefFlows) { - loggedServices - .mapIndexed { index, trackService -> trackService.id to it[index] } + loggedInTrackers + .mapIndexed { index, tracker -> tracker.id to it[index] } .toMap() } } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt index 1a9ce4208..2a59af85c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.library import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.coroutineScope 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.TriState import tachiyomi.core.preference.getAndSet @@ -22,11 +22,11 @@ class LibrarySettingsScreenModel( val libraryPreferences: LibraryPreferences = Injekt.get(), private val setDisplayMode: SetDisplayMode = Injekt.get(), private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(), - private val trackManager: TrackManager = Injekt.get(), + private val trackerManager: TrackerManager = Injekt.get(), ) : ScreenModel { - val trackServices - get() = trackManager.services.filter { it.isLoggedIn } + val trackers + get() = trackerManager.trackers.filter { it.isLoggedIn } fun toggleFilter(preference: (LibraryPreferences) -> Preference) { preference(libraryPreferences).getAndSet { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 868a8cee7..1d67ab668 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -138,7 +138,7 @@ class MainActivity : BaseActivity() { libraryPreferences = libraryPreferences, readerPreferences = Injekt.get(), backupPreferences = Injekt.get(), - trackManager = Injekt.get(), + trackerManager = Injekt.get(), ) } else { false diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index 0827caded..9e94a2605 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -23,9 +23,9 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.model.Download -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.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker +import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.network.HttpException import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.ui.manga.track.TrackItem @@ -84,7 +84,7 @@ class MangaScreenModel( private val libraryPreferences: LibraryPreferences = Injekt.get(), readerPreferences: ReaderPreferences = 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 downloadCache: DownloadCache = Injekt.get(), private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(), @@ -105,7 +105,7 @@ class MangaScreenModel( private val successState: 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? get() = successState?.manga @@ -317,14 +317,14 @@ class MangaScreenModel( // Finally match with enhanced tracking when available val source = state.source state.trackItems - .map { it.service } - .filterIsInstance() + .map { it.tracker } + .filterIsInstance() .filter { it.accept(source) } .forEach { service -> launchIO { try { service.match(manga)?.let { track -> - (service as TrackService).register(track, mangaId) + (service as Tracker).register(track, mangaId) } } catch (e: Exception) { logcat(LogPriority.WARN, e) { @@ -949,11 +949,11 @@ class MangaScreenModel( getTracks.subscribe(manga.id) .catch { logcat(LogPriority.ERROR, it) } .map { tracks -> - loggedServices + loggedInTrackers // Map to TrackItem .map { service -> TrackItem(tracks.find { it.syncId == service.id }, service) } // 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() .collectLatest { trackItems -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt index f92374b2a..f25dab5c8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt @@ -46,14 +46,14 @@ import eu.kanade.presentation.track.TrackChapterSelector import eu.kanade.presentation.track.TrackDateSelector import eu.kanade.presentation.track.TrackInfoDialogHome import eu.kanade.presentation.track.TrackScoreSelector -import eu.kanade.presentation.track.TrackServiceSearch import eu.kanade.presentation.track.TrackStatusSelector +import eu.kanade.presentation.track.TrackerSearch import eu.kanade.presentation.util.Screen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.track.DeletableTrackService -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.data.track.DeletableTracker +import eu.kanade.tachiyomi.data.track.EnhancedTracker +import eu.kanade.tachiyomi.data.track.Tracker +import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone import eu.kanade.tachiyomi.util.system.openInBrowser @@ -105,7 +105,7 @@ data class TrackInfoDialogHomeScreen( navigator.push( TrackStatusSelectorScreen( track = it.track!!, - serviceId = it.service.id, + serviceId = it.tracker.id, ), ) }, @@ -113,7 +113,7 @@ data class TrackInfoDialogHomeScreen( navigator.push( TrackChapterSelectorScreen( track = it.track!!, - serviceId = it.service.id, + serviceId = it.tracker.id, ), ) }, @@ -121,7 +121,7 @@ data class TrackInfoDialogHomeScreen( navigator.push( TrackScoreSelectorScreen( track = it.track!!, - serviceId = it.service.id, + serviceId = it.tracker.id, ), ) }, @@ -129,7 +129,7 @@ data class TrackInfoDialogHomeScreen( navigator.push( TrackDateSelectorScreen( track = it.track!!, - serviceId = it.service.id, + serviceId = it.tracker.id, start = true, ), ) @@ -138,21 +138,21 @@ data class TrackInfoDialogHomeScreen( navigator.push( TrackDateSelectorScreen( track = it.track!!, - serviceId = it.service.id, + serviceId = it.tracker.id, start = false, ), ) }, onNewSearch = { - if (it.service is EnhancedTrackService) { + if (it.tracker is EnhancedTracker) { sm.registerEnhancedTracking(it) } else { navigator.push( - TrackServiceSearchScreen( + TrackerSearchScreen( mangaId = mangaId, initialQuery = it.track?.title ?: mangaTitle, currentUrl = it.track?.remoteUrl, - serviceId = it.service.id, + serviceId = it.tracker.id, ), ) } @@ -160,10 +160,10 @@ data class TrackInfoDialogHomeScreen( onOpenInBrowser = { openTrackerInBrowser(context, it) }, onRemoved = { navigator.push( - TrackServiceRemoveScreen( + TrackerRemoveScreen( mangaId = mangaId, track = it.track!!, - serviceId = it.service.id, + serviceId = it.tracker.id, ), ) }, @@ -201,12 +201,12 @@ data class TrackInfoDialogHomeScreen( } fun registerEnhancedTracking(item: TrackItem) { - item.service as EnhancedTrackService + item.tracker as EnhancedTracker coroutineScope.launchNonCancellable { val manga = Injekt.get().await(mangaId) ?: return@launchNonCancellable try { - val matchResult = item.service.match(manga) ?: throw Exception() - item.service.register(matchResult, mangaId) + val matchResult = item.tracker.match(manga) ?: throw Exception() + item.tracker.register(matchResult, mangaId) } catch (e: Exception) { withUIContext { Injekt.get().toast(R.string.error_no_match) } } @@ -236,13 +236,13 @@ data class TrackInfoDialogHomeScreen( } private fun List.mapToTrackItem(): List { - val loggedServices = Injekt.get().services.filter { it.isLoggedIn } + val loggedInTrackers = Injekt.get().trackers.filter { it.isLoggedIn } val source = Injekt.get().getOrStub(sourceId) - return loggedServices + return loggedInTrackers // Map to TrackItem .map { service -> TrackItem(find { it.syncId == service.id }, service) } // 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 @@ -263,7 +263,7 @@ private data class TrackStatusSelectorScreen( val sm = rememberScreenModel { Model( track = track, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, ) } val state by sm.state.collectAsState() @@ -281,11 +281,11 @@ private data class TrackStatusSelectorScreen( private class Model( private val track: Track, - private val service: TrackService, + private val tracker: Tracker, ) : StateScreenModel(State(track.status.toInt())) { fun getSelections(): Map { - return service.getStatusList().associateWith { service.getStatus(it) } + return tracker.getStatusList().associateWith { tracker.getStatus(it) } } fun setSelection(selection: Int) { @@ -294,7 +294,7 @@ private data class TrackStatusSelectorScreen( fun setStatus() { 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 { Model( track = track, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, ) } val state by sm.state.collectAsState() @@ -335,7 +335,7 @@ private data class TrackChapterSelectorScreen( private class Model( private val track: Track, - private val service: TrackService, + private val tracker: Tracker, ) : StateScreenModel(State(track.lastChapterRead.toInt())) { fun getRange(): Iterable { @@ -353,7 +353,7 @@ private data class TrackChapterSelectorScreen( fun setChapter() { 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 { Model( track = track, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, ) } val state by sm.state.collectAsState() @@ -394,11 +394,11 @@ private data class TrackScoreSelectorScreen( private class Model( private val track: Track, - private val service: TrackService, - ) : StateScreenModel(State(service.displayScore(track.toDbTrack()))) { + private val tracker: Tracker, + ) : StateScreenModel(State(tracker.displayScore(track.toDbTrack()))) { fun getSelections(): List { - return service.getScoreList() + return tracker.getScoreList() } fun setSelection(selection: String) { @@ -407,7 +407,7 @@ private data class TrackScoreSelectorScreen( fun setScore() { 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 { Model( track = track, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, start = start, ) } @@ -515,7 +515,7 @@ private data class TrackDateSelectorScreen( private class Model( private val track: Track, - private val service: TrackService, + private val tracker: Tracker, private val start: Boolean, ) : ScreenModel { @@ -534,15 +534,15 @@ private data class TrackDateSelectorScreen( val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault()) coroutineScope.launchNonCancellable { if (start) { - service.setRemoteStartDate(track.toDbTrack(), localMillis) + tracker.setRemoteStartDate(track.toDbTrack(), localMillis) } else { - service.setRemoteFinishDate(track.toDbTrack(), localMillis) + tracker.setRemoteFinishDate(track.toDbTrack(), localMillis) } } } 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 { Model( track = track, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, start = start, ) } @@ -614,25 +614,25 @@ private data class TrackDateRemoverScreen( private class Model( private val track: Track, - private val service: TrackService, + private val tracker: Tracker, private val start: Boolean, ) : ScreenModel { - fun getServiceName() = service.name + fun getServiceName() = tracker.name fun removeDate() { coroutineScope.launchNonCancellable { if (start) { - service.setRemoteStartDate(track.toDbTrack(), 0) + tracker.setRemoteStartDate(track.toDbTrack(), 0) } else { - service.setRemoteFinishDate(track.toDbTrack(), 0) + tracker.setRemoteFinishDate(track.toDbTrack(), 0) } } } } } -data class TrackServiceSearchScreen( +data class TrackerSearchScreen( private val mangaId: Long, private val initialQuery: String, private val currentUrl: String?, @@ -647,14 +647,14 @@ data class TrackServiceSearchScreen( mangaId = mangaId, currentUrl = currentUrl, initialQuery = initialQuery, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, ) } val state by sm.state.collectAsState() var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) } - TrackServiceSearch( + TrackerSearch( query = textFieldValue, onQueryChange = { textFieldValue = it }, onDispatchQuery = { sm.trackingSearch(textFieldValue.text) }, @@ -673,7 +673,7 @@ data class TrackServiceSearchScreen( private val mangaId: Long, private val currentUrl: String? = null, initialQuery: String, - private val service: TrackService, + private val tracker: Tracker, ) : StateScreenModel(State()) { init { @@ -690,7 +690,7 @@ data class TrackServiceSearchScreen( val result = withIOContext { try { - val results = service.search(query) + val results = tracker.search(query) Result.success(results) } catch (e: Throwable) { Result.failure(e) @@ -706,7 +706,7 @@ data class TrackServiceSearchScreen( } fun registerTracking(item: TrackSearch) { - coroutineScope.launchNonCancellable { service.register(item, mangaId) } + coroutineScope.launchNonCancellable { tracker.register(item, mangaId) } } 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 track: Track, private val serviceId: Long, @@ -734,10 +734,10 @@ private data class TrackServiceRemoveScreen( Model( mangaId = mangaId, track = track, - service = Injekt.get().getService(serviceId)!!, + tracker = Injekt.get().get(serviceId)!!, ) } - val serviceName = sm.getServiceName() + val serviceName = sm.getName() var removeRemoteTrack by remember { mutableStateOf(false) } AlertDialogContent( modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars), @@ -758,7 +758,7 @@ private data class TrackServiceRemoveScreen( Text( text = stringResource(R.string.track_delete_text, serviceName), ) - if (sm.isServiceDeletable()) { + if (sm.isDeletable()) { Row(verticalAlignment = Alignment.CenterVertically) { Checkbox(checked = removeRemoteTrack, onCheckedChange = { removeRemoteTrack = it }) Text(text = stringResource(R.string.track_delete_remote_text, serviceName)) @@ -798,17 +798,17 @@ private data class TrackServiceRemoveScreen( private class Model( private val mangaId: Long, private val track: Track, - private val service: TrackService, + private val tracker: Tracker, private val deleteTrack: DeleteTrack = Injekt.get(), ) : ScreenModel { - fun getServiceName() = service.name + fun getName() = tracker.name - fun isServiceDeletable() = service is DeletableTrackService + fun isDeletable() = tracker is DeletableTracker fun deleteMangaFromService() { coroutineScope.launchNonCancellable { - (service as DeletableTrackService).delete(track.toDbTrack()) + (tracker as DeletableTracker).delete(track.toDbTrack()) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackItem.kt index d0883e593..fd46e0eec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackItem.kt @@ -1,6 +1,6 @@ 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 -data class TrackItem(val track: Track?, val service: TrackService) +data class TrackItem(val track: Track?, val tracker: Tracker) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt index a1a91a003..92302d718 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/BaseOAuthLoginActivity.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.setting.track import android.content.Intent import android.net.Uri 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.main.MainActivity import eu.kanade.tachiyomi.util.view.setComposeContent @@ -12,7 +12,7 @@ import uy.kohesive.injekt.injectLazy abstract class BaseOAuthLoginActivity : BaseActivity() { - internal val trackManager: TrackManager by injectLazy() + internal val trackerManager: TrackerManager by injectLazy() abstract fun handleResult(data: Uri?) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLoginActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLoginActivity.kt index af13de51b..47cd88416 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLoginActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/track/TrackLoginActivity.kt @@ -20,11 +20,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() { val matchResult = regex.find(data.fragment.toString()) if (matchResult?.groups?.get(1) != null) { lifecycleScope.launchIO { - trackManager.aniList.login(matchResult.groups[1]!!.value) + trackerManager.aniList.login(matchResult.groups[1]!!.value) returnToSettings() } } else { - trackManager.aniList.logout() + trackerManager.aniList.logout() returnToSettings() } } @@ -33,11 +33,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() { val code = data.getQueryParameter("code") if (code != null) { lifecycleScope.launchIO { - trackManager.bangumi.login(code) + trackerManager.bangumi.login(code) returnToSettings() } } else { - trackManager.bangumi.logout() + trackerManager.bangumi.logout() returnToSettings() } } @@ -46,11 +46,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() { val code = data.getQueryParameter("code") if (code != null) { lifecycleScope.launchIO { - trackManager.myAnimeList.login(code) + trackerManager.myAnimeList.login(code) returnToSettings() } } else { - trackManager.myAnimeList.logout() + trackerManager.myAnimeList.logout() returnToSettings() } } @@ -59,11 +59,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() { val code = data.getQueryParameter("code") if (code != null) { lifecycleScope.launchIO { - trackManager.shikimori.login(code) + trackerManager.shikimori.login(code) returnToSettings() } } else { - trackManager.shikimori.logout() + trackerManager.shikimori.logout() returnToSettings() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt index 873bd2723..6131308d0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt @@ -10,7 +10,7 @@ import eu.kanade.core.util.fastMapNotNull import eu.kanade.presentation.more.stats.StatsScreenState import eu.kanade.presentation.more.stats.data.StatsData 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 kotlinx.coroutines.flow.update import tachiyomi.core.util.lang.launchIO @@ -33,10 +33,10 @@ class StatsScreenModel( private val getTotalReadDuration: GetTotalReadDuration = Injekt.get(), private val getTracks: GetTracks = Injekt.get(), private val preferences: LibraryPreferences = Injekt.get(), - private val trackManager: TrackManager = Injekt.get(), + private val trackerManager: TrackerManager = Injekt.get(), ) : StateScreenModel(StatsScreenState.Loading) { - private val loggedServices by lazy { trackManager.services.fastFilter { it.isLoggedIn } } + private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn } } init { coroutineScope.launchIO { @@ -72,7 +72,7 @@ class StatsScreenModel( val trackersStatData = StatsData.Trackers( trackedTitleCount = mangaTrackMap.count { it.value.isNotEmpty() }, meanScore = meanScore, - trackerCount = loggedServices.size, + trackerCount = loggedInTrackers.size, ) mutableState.update { @@ -115,10 +115,10 @@ class StatsScreenModel( } private suspend fun getMangaTrackMap(libraryManga: List): Map> { - val loggedServicesIds = loggedServices.map { it.id }.toHashSet() + val loggedInTrackerIds = loggedInTrackers.map { it.id }.toHashSet() return libraryManga.associate { manga -> val tracks = getTracks.await(manga.id) - .fastFilter { it.syncId in loggedServicesIds } + .fastFilter { it.syncId in loggedInTrackerIds } manga.id to tracks } @@ -144,7 +144,7 @@ class StatsScreenModel( } private fun get10PointScore(track: Track): Double { - val service = trackManager.getService(track.syncId)!! + val service = trackerManager.get(track.syncId)!! return service.get10PointScore(track) } } diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index bed8f0836..8821087b2 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -459,13 +459,13 @@ Tracking guide Update progress after reading - Services - One-way sync to update the chapter progress in tracking services. Set up tracking for individual entries from their tracking button. - Enhanced services + Trackers + One-way sync to update the chapter progress in external tracker services. Set up tracking for individual entries from their tracking button. + Enhanced trackers Available but source not installed: %s - Services that provide enhanced features for specific sources. Entries are automatically tracked when added to your library. + Provides enhanced features for specific sources. Entries are automatically tracked when added to your library. Track - Tracking login + Tracker login Hide entries already in library