mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-21 12:17:12 +03:00
parent
a654a54b74
commit
c07cc8dc21
95 changed files with 770 additions and 710 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,7 +3,8 @@
|
|||
/acra.properties
|
||||
/.idea/workspace.xml
|
||||
.DS_Store
|
||||
.idea/
|
||||
.idea/*
|
||||
!.idea/icon.png
|
||||
*iml
|
||||
*.iml
|
||||
|
||||
|
|
BIN
.idea/icon.png
Normal file
BIN
.idea/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
3
app/.idea/.gitignore
vendored
Normal file
3
app/.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
1
app/.idea/.name
Normal file
1
app/.idea/.name
Normal file
|
@ -0,0 +1 @@
|
|||
MangaDownloader.kt
|
7
app/.idea/discord.xml
Normal file
7
app/.idea/discord.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
18
app/.idea/gradle.xml
Normal file
18
app/.idea/gradle.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveExternalAnnotations" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
3
app/.idea/misc.xml
Normal file
3
app/.idea/misc.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
</project>
|
6
app/.idea/vcs.xml
Normal file
6
app/.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -19976,8 +19976,8 @@ HSPLeu/kanade/domain/track/service/TrackPreferences;-><init>(Ltachiyomi/core/pre
|
|||
PLeu/kanade/domain/track/service/TrackPreferences;-><init>(Ltachiyomi/core/preference/PreferenceStore;)V
|
||||
HSPLeu/kanade/domain/track/service/TrackPreferences;->anilistScoreType()Ltachiyomi/core/preference/Preference;
|
||||
PLeu/kanade/domain/track/service/TrackPreferences;->anilistScoreType()Ltachiyomi/core/preference/Preference;
|
||||
HSPLeu/kanade/domain/track/service/TrackPreferences;->trackUsername(Leu/kanade/tachiyomi/data/track/TrackService;)Ltachiyomi/core/preference/Preference;
|
||||
PLeu/kanade/domain/track/service/TrackPreferences;->trackUsername(Leu/kanade/tachiyomi/data/track/TrackService;)Ltachiyomi/core/preference/Preference;
|
||||
HSPLeu/kanade/domain/track/service/TrackPreferences;->trackUsername(Leu/kanade/tachiyomi/data/track/Tracker;)Ltachiyomi/core/preference/Preference;
|
||||
PLeu/kanade/domain/track/service/TrackPreferences;->trackUsername(Leu/kanade/tachiyomi/data/track/Tracker;)Ltachiyomi/core/preference/Preference;
|
||||
Leu/kanade/domain/track/service/TrackPreferences$Companion;
|
||||
HSPLeu/kanade/domain/track/service/TrackPreferences$Companion;-><init>()V
|
||||
PLeu/kanade/domain/track/service/TrackPreferences$Companion;-><init>()V
|
||||
|
@ -21563,31 +21563,31 @@ PLeu/kanade/tachiyomi/data/notification/Notifications$createChannels$9;->invoke(
|
|||
Leu/kanade/tachiyomi/data/saver/ImageSaver;
|
||||
Leu/kanade/tachiyomi/data/track/DeletableTrackService;
|
||||
Leu/kanade/tachiyomi/data/track/EnhancedTrackService;
|
||||
Leu/kanade/tachiyomi/data/track/TrackManager;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackManager;-><clinit>()V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackManager;-><clinit>()V
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackManager;-><init>(Landroid/app/Application;)V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackManager;-><init>(Landroid/app/Application;)V
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackManager;->getServices()Ljava/util/List;
|
||||
PLeu/kanade/tachiyomi/data/track/TrackManager;->getServices()Ljava/util/List;
|
||||
Leu/kanade/tachiyomi/data/track/TrackerManager;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackerManager;-><clinit>()V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackerManager;-><clinit>()V
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackerManager;-><init>(Landroid/app/Application;)V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackerManager;-><init>(Landroid/app/Application;)V
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackerManager;->getServices()Ljava/util/List;
|
||||
PLeu/kanade/tachiyomi/data/track/TrackerManager;->getServices()Ljava/util/List;
|
||||
Leu/kanade/tachiyomi/data/track/TrackManager$Companion;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackManager$Companion;-><init>()V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackManager$Companion;-><init>()V
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackManager$Companion;-><init>(I)V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackManager$Companion;-><init>(I)V
|
||||
Leu/kanade/tachiyomi/data/track/TrackService;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService;-><init>(J)V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService;-><init>(J)V
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService;->getId()J
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService;->getId()J
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService;->getNetworkService()Leu/kanade/tachiyomi/network/NetworkHelper;
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService;->getNetworkService()Leu/kanade/tachiyomi/network/NetworkHelper;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService;->getTrackPreferences()Leu/kanade/domain/track/service/TrackPreferences;
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService;->getTrackPreferences()Leu/kanade/domain/track/service/TrackPreferences;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService;->getUsername()Ljava/lang/String;
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService;->getUsername()Ljava/lang/String;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService;->isLogged()Z
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService;->isLogged()Z
|
||||
Leu/kanade/tachiyomi/data/track/Tracker;
|
||||
HSPLeu/kanade/tachiyomi/data/track/Tracker;-><init>(J)V
|
||||
PLeu/kanade/tachiyomi/data/track/Tracker;-><init>(J)V
|
||||
HSPLeu/kanade/tachiyomi/data/track/Tracker;->getId()J
|
||||
PLeu/kanade/tachiyomi/data/track/Tracker;->getId()J
|
||||
HSPLeu/kanade/tachiyomi/data/track/Tracker;->getNetworkService()Leu/kanade/tachiyomi/network/NetworkHelper;
|
||||
PLeu/kanade/tachiyomi/data/track/Tracker;->getNetworkService()Leu/kanade/tachiyomi/network/NetworkHelper;
|
||||
HSPLeu/kanade/tachiyomi/data/track/Tracker;->getTrackPreferences()Leu/kanade/domain/track/service/TrackPreferences;
|
||||
PLeu/kanade/tachiyomi/data/track/Tracker;->getTrackPreferences()Leu/kanade/domain/track/service/TrackPreferences;
|
||||
HSPLeu/kanade/tachiyomi/data/track/Tracker;->getUsername()Ljava/lang/String;
|
||||
PLeu/kanade/tachiyomi/data/track/Tracker;->getUsername()Ljava/lang/String;
|
||||
HSPLeu/kanade/tachiyomi/data/track/Tracker;->isLogged()Z
|
||||
PLeu/kanade/tachiyomi/data/track/Tracker;->isLogged()Z
|
||||
Leu/kanade/tachiyomi/data/track/TrackService$special$$inlined$injectLazy$1;
|
||||
HSPLeu/kanade/tachiyomi/data/track/TrackService$special$$inlined$injectLazy$1;-><clinit>()V
|
||||
PLeu/kanade/tachiyomi/data/track/TrackService$special$$inlined$injectLazy$1;-><clinit>()V
|
||||
|
|
|
@ -13,10 +13,8 @@ import eu.kanade.domain.extension.manga.interactor.GetExtensionSources
|
|||
import eu.kanade.domain.extension.manga.interactor.GetMangaExtensionLanguages
|
||||
import eu.kanade.domain.extension.manga.interactor.GetMangaExtensionsByType
|
||||
import eu.kanade.domain.items.chapter.interactor.SetReadStatus
|
||||
import eu.kanade.domain.items.chapter.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.items.chapter.interactor.SyncChaptersWithSource
|
||||
import eu.kanade.domain.items.episode.interactor.SetSeenStatus
|
||||
import eu.kanade.domain.items.episode.interactor.SyncEpisodeProgressWithTrack
|
||||
import eu.kanade.domain.items.episode.interactor.SyncEpisodesWithSource
|
||||
import eu.kanade.domain.source.anime.interactor.GetAnimeSourcesWithFavoriteCount
|
||||
import eu.kanade.domain.source.anime.interactor.GetEnabledAnimeSources
|
||||
|
@ -30,9 +28,13 @@ import eu.kanade.domain.source.manga.interactor.ToggleMangaSource
|
|||
import eu.kanade.domain.source.manga.interactor.ToggleMangaSourcePin
|
||||
import eu.kanade.domain.source.service.SetMigrateSorting
|
||||
import eu.kanade.domain.source.service.ToggleLanguage
|
||||
import eu.kanade.domain.track.anime.interactor.AddAnimeTracks
|
||||
import eu.kanade.domain.track.anime.interactor.RefreshAnimeTracks
|
||||
import eu.kanade.domain.track.anime.interactor.SyncEpisodeProgressWithTrack
|
||||
import eu.kanade.domain.track.anime.interactor.TrackEpisode
|
||||
import eu.kanade.domain.track.manga.interactor.AddMangaTracks
|
||||
import eu.kanade.domain.track.manga.interactor.RefreshMangaTracks
|
||||
import eu.kanade.domain.track.manga.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.track.manga.interactor.TrackChapter
|
||||
import tachiyomi.data.category.anime.AnimeCategoryRepositoryImpl
|
||||
import tachiyomi.data.category.manga.MangaCategoryRepositoryImpl
|
||||
|
@ -222,19 +224,23 @@ class DomainModule : InjektModule {
|
|||
|
||||
addSingletonFactory<AnimeTrackRepository> { AnimeTrackRepositoryImpl(get()) }
|
||||
addFactory { TrackEpisode(get(), get(), get(), get()) }
|
||||
addFactory { AddAnimeTracks(get(), get(), get()) }
|
||||
addFactory { RefreshAnimeTracks(get(), get(), get(), get()) }
|
||||
addFactory { DeleteAnimeTrack(get()) }
|
||||
addFactory { GetTracksPerAnime(get()) }
|
||||
addFactory { GetAnimeTracks(get()) }
|
||||
addFactory { InsertAnimeTrack(get()) }
|
||||
addFactory { SyncEpisodeProgressWithTrack(get(), get(), get()) }
|
||||
|
||||
addSingletonFactory<MangaTrackRepository> { MangaTrackRepositoryImpl(get()) }
|
||||
addFactory { TrackChapter(get(), get(), get(), get()) }
|
||||
addFactory { AddMangaTracks(get(), get(), get()) }
|
||||
addFactory { RefreshMangaTracks(get(), get(), get(), get()) }
|
||||
addFactory { DeleteMangaTrack(get()) }
|
||||
addFactory { GetTracksPerManga(get()) }
|
||||
addFactory { GetMangaTracks(get()) }
|
||||
addFactory { InsertMangaTrack(get()) }
|
||||
addFactory { SyncChapterProgressWithTrack(get(), get(), get()) }
|
||||
|
||||
addSingletonFactory<EpisodeRepository> { EpisodeRepositoryImpl(get()) }
|
||||
addFactory { GetEpisode(get()) }
|
||||
|
@ -243,7 +249,6 @@ class DomainModule : InjektModule {
|
|||
addFactory { SetSeenStatus(get(), get(), get(), get()) }
|
||||
addFactory { ShouldUpdateDbEpisode() }
|
||||
addFactory { SyncEpisodesWithSource(get(), get(), get(), get(), get(), get(), get()) }
|
||||
addFactory { SyncEpisodeProgressWithTrack(get(), get(), get()) }
|
||||
|
||||
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
|
||||
addFactory { GetChapter(get()) }
|
||||
|
@ -252,7 +257,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<AnimeHistoryRepository> { AnimeHistoryRepositoryImpl(get()) }
|
||||
addFactory { GetAnimeHistory(get()) }
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package eu.kanade.domain.track.anime.interactor
|
||||
|
||||
import eu.kanade.domain.track.anime.model.toDomainTrack
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.entries.anime.model.Anime
|
||||
import tachiyomi.domain.track.anime.interactor.GetAnimeTracks
|
||||
import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
|
||||
|
||||
class AddAnimeTracks(
|
||||
private val getTracks: GetAnimeTracks,
|
||||
private val insertTrack: InsertAnimeTrack,
|
||||
private val syncChapterProgressWithTrack: SyncEpisodeProgressWithTrack,
|
||||
) {
|
||||
|
||||
suspend fun bindEnhancedTracks(anime: Anime, source: AnimeSource) {
|
||||
withNonCancellableContext {
|
||||
getTracks.await(anime.id)
|
||||
.filterIsInstance<EnhancedAnimeTracker>()
|
||||
.filter { it.accept(source) }
|
||||
.forEach { service ->
|
||||
try {
|
||||
service.match(anime)?.let { track ->
|
||||
track.anime_id = anime.id
|
||||
(service as Tracker).animeService.bind(track)
|
||||
insertTrack.await(track.toDomainTrack()!!)
|
||||
|
||||
syncChapterProgressWithTrack.await(
|
||||
anime.id,
|
||||
track.toDomainTrack()!!,
|
||||
service.animeService,
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(
|
||||
LogPriority.WARN,
|
||||
e,
|
||||
) { "Could not match manga: ${anime.title} with service $service" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package eu.kanade.domain.track.anime.interactor
|
||||
|
||||
import eu.kanade.domain.items.episode.interactor.SyncEpisodeProgressWithTrack
|
||||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.domain.track.anime.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.anime.interactor.InsertAnimeTrack
|
|||
|
||||
class RefreshAnimeTracks(
|
||||
private val getTracks: GetAnimeTracks,
|
||||
private val trackManager: TrackManager,
|
||||
private val trackerManager: TrackerManager,
|
||||
private val insertTrack: InsertAnimeTrack,
|
||||
private val syncEpisodeProgressWithTrack: SyncEpisodeProgressWithTrack,
|
||||
) {
|
||||
|
@ -23,22 +22,17 @@ class RefreshAnimeTracks(
|
|||
*
|
||||
* @return Failed updates.
|
||||
*/
|
||||
suspend fun await(animeId: Long): List<Pair<TrackService?, Throwable>> {
|
||||
suspend fun await(animeId: Long): List<Pair<Tracker?, Throwable>> {
|
||||
return supervisorScope {
|
||||
return@supervisorScope getTracks.await(animeId)
|
||||
.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.animeService.refresh(track.toDbTrack())
|
||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||
syncEpisodeProgressWithTrack.await(
|
||||
animeId,
|
||||
track,
|
||||
service.animeService,
|
||||
)
|
||||
}
|
||||
val updatedTrack = service!!.animeService.refresh(track.toDbTrack())
|
||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||
syncEpisodeProgressWithTrack.await(animeId, track, service.animeService)
|
||||
null
|
||||
} catch (e: Throwable) {
|
||||
service to e
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package eu.kanade.domain.items.episode.interactor
|
||||
package eu.kanade.domain.track.anime.interactor
|
||||
|
||||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTracker
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.items.episode.interactor.GetEpisodeByAnimeId
|
||||
|
@ -10,7 +10,6 @@ import tachiyomi.domain.items.episode.interactor.UpdateEpisode
|
|||
import tachiyomi.domain.items.episode.model.toEpisodeUpdate
|
||||
import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
|
||||
import tachiyomi.domain.track.anime.model.AnimeTrack
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class SyncEpisodeProgressWithTrack(
|
||||
private val updateEpisode: UpdateEpisode,
|
||||
|
@ -21,9 +20,9 @@ class SyncEpisodeProgressWithTrack(
|
|||
suspend fun await(
|
||||
animeId: Long,
|
||||
remoteTrack: AnimeTrack,
|
||||
service: AnimeTrackService,
|
||||
service: AnimeTracker,
|
||||
) {
|
||||
if (service !is EnhancedAnimeTrackService) {
|
||||
if (service !is EnhancedAnimeTracker) {
|
||||
return
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.domain.track.anime.service.DelayedAnimeTrackingUpdateJob
|
||||
import eu.kanade.domain.track.anime.store.DelayedAnimeTrackingStore
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.util.system.isOnline
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
|
@ -17,7 +17,7 @@ import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
|
|||
|
||||
class TrackEpisode(
|
||||
private val getTracks: GetAnimeTracks,
|
||||
private val trackManager: TrackManager,
|
||||
private val trackerManager: TrackerManager,
|
||||
private val insertTrack: InsertAnimeTrack,
|
||||
private val delayedTrackingStore: DelayedAnimeTrackingStore,
|
||||
) {
|
||||
|
@ -29,14 +29,14 @@ class TrackEpisode(
|
|||
if (tracks.isEmpty()) return@launchNonCancellable
|
||||
|
||||
tracks.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn && episodeNumber > track.lastEpisodeSeen) {
|
||||
val tracker = trackerManager.get(track.syncId)
|
||||
if (tracker != null && tracker.isLoggedIn && episodeNumber > track.lastEpisodeSeen) {
|
||||
val updatedTrack = track.copy(lastEpisodeSeen = episodeNumber)
|
||||
|
||||
async {
|
||||
runCatching {
|
||||
if (context.isOnline()) {
|
||||
service.animeService.update(updatedTrack.toDbTrack(), true)
|
||||
tracker.animeService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} else {
|
||||
delayedTrackingStore.addAnimeItem(updatedTrack)
|
||||
|
|
|
@ -10,7 +10,7 @@ import androidx.work.OneTimeWorkRequestBuilder
|
|||
import androidx.work.WorkerParameters
|
||||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.domain.track.anime.store.DelayedAnimeTrackingStore
|
||||
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 DelayedAnimeTrackingUpdateJob(context: Context, workerParams: WorkerParame
|
|||
val getTracks = Injekt.get<GetAnimeTracks>()
|
||||
val insertTrack = Injekt.get<InsertAnimeTrack>()
|
||||
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val trackerManager = Injekt.get<TrackerManager>()
|
||||
val delayedTrackingStore = Injekt.get<DelayedAnimeTrackingStore>()
|
||||
|
||||
withIOContext {
|
||||
|
@ -47,10 +47,10 @@ class DelayedAnimeTrackingUpdateJob(context: Context, workerParams: WorkerParame
|
|||
}
|
||||
.forEach { animeTrack ->
|
||||
try {
|
||||
val service = trackManager.getService(animeTrack.syncId)
|
||||
if (service != null && service.isLoggedIn) {
|
||||
val tracker = trackerManager.get(animeTrack.syncId)
|
||||
if (tracker != null && tracker.isLoggedIn) {
|
||||
logcat(LogPriority.DEBUG) { "Updating delayed track item: ${animeTrack.id}, last episode seen: ${animeTrack.lastEpisodeSeen}" }
|
||||
service.animeService.update(animeTrack.toDbTrack(), true)
|
||||
tracker.animeService.update(animeTrack.toDbTrack(), true)
|
||||
insertTrack.await(animeTrack)
|
||||
}
|
||||
delayedTrackingStore.removeAnimeItem(animeTrack.id)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package eu.kanade.domain.track.manga.interactor
|
||||
|
||||
import eu.kanade.domain.track.manga.model.toDomainTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.entries.manga.model.Manga
|
||||
import tachiyomi.domain.track.manga.interactor.GetMangaTracks
|
||||
import tachiyomi.domain.track.manga.interactor.InsertMangaTrack
|
||||
|
||||
class AddMangaTracks(
|
||||
private val getTracks: GetMangaTracks,
|
||||
private val insertTrack: InsertMangaTrack,
|
||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
||||
) {
|
||||
|
||||
suspend fun bindEnhancedTracks(manga: Manga, source: MangaSource) {
|
||||
withNonCancellableContext {
|
||||
getTracks.await(manga.id)
|
||||
.filterIsInstance<EnhancedMangaTracker>()
|
||||
.filter { it.accept(source) }
|
||||
.forEach { service ->
|
||||
try {
|
||||
service.match(manga)?.let { track ->
|
||||
track.manga_id = manga.id
|
||||
(service as Tracker).mangaService.bind(track)
|
||||
insertTrack.await(track.toDomainTrack()!!)
|
||||
|
||||
syncChapterProgressWithTrack.await(
|
||||
manga.id,
|
||||
track.toDomainTrack()!!,
|
||||
service.mangaService,
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(
|
||||
LogPriority.WARN,
|
||||
e,
|
||||
) { "Could not match manga: ${manga.title} with service $service" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package eu.kanade.domain.track.manga.interactor
|
||||
|
||||
import eu.kanade.domain.items.chapter.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.domain.track.manga.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.manga.interactor.InsertMangaTrack
|
|||
|
||||
class RefreshMangaTracks(
|
||||
private val getTracks: GetMangaTracks,
|
||||
private val trackManager: TrackManager,
|
||||
private val trackerManager: TrackerManager,
|
||||
private val insertTrack: InsertMangaTrack,
|
||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
||||
) {
|
||||
|
@ -23,22 +22,17 @@ class RefreshMangaTracks(
|
|||
*
|
||||
* @return Failed updates.
|
||||
*/
|
||||
suspend fun await(mangaId: Long): List<Pair<TrackService?, Throwable>> {
|
||||
suspend fun await(mangaId: Long): List<Pair<Tracker?, Throwable>> {
|
||||
return supervisorScope {
|
||||
return@supervisorScope 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.mangaService.refresh(track.toDbTrack())
|
||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||
syncChapterProgressWithTrack.await(
|
||||
mangaId,
|
||||
track,
|
||||
service.mangaService,
|
||||
)
|
||||
}
|
||||
val updatedTrack = service!!.mangaService.refresh(track.toDbTrack())
|
||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||
syncChapterProgressWithTrack.await(mangaId, track, service.mangaService)
|
||||
null
|
||||
} catch (e: Throwable) {
|
||||
service to e
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package eu.kanade.domain.items.chapter.interactor
|
||||
package eu.kanade.domain.track.manga.interactor
|
||||
|
||||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.items.chapter.interactor.GetChapterByMangaId
|
||||
|
@ -20,9 +20,9 @@ class SyncChapterProgressWithTrack(
|
|||
suspend fun await(
|
||||
mangaId: Long,
|
||||
remoteTrack: MangaTrack,
|
||||
service: MangaTrackService,
|
||||
tracker: MangaTracker,
|
||||
) {
|
||||
if (service !is EnhancedMangaTrackService) {
|
||||
if (tracker !is EnhancedMangaTracker) {
|
||||
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) {
|
|
@ -4,38 +4,37 @@ import android.content.Context
|
|||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.domain.track.manga.service.DelayedMangaTrackingUpdateJob
|
||||
import eu.kanade.domain.track.manga.store.DelayedMangaTrackingStore
|
||||
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.manga.interactor.GetMangaTracks
|
||||
import tachiyomi.domain.track.manga.interactor.InsertMangaTrack
|
||||
|
||||
class TrackChapter(
|
||||
private val getTracks: GetMangaTracks,
|
||||
private val trackManager: TrackManager,
|
||||
private val trackerManager: TrackerManager,
|
||||
private val insertTrack: InsertMangaTrack,
|
||||
private val delayedTrackingStore: DelayedMangaTrackingStore,
|
||||
) {
|
||||
|
||||
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)
|
||||
if (service != null && service.isLoggedIn && chapterNumber > track.lastChapterRead) {
|
||||
val tracker = trackerManager.get(track.syncId)
|
||||
if (tracker != null && tracker.isLoggedIn && chapterNumber > track.lastChapterRead) {
|
||||
val updatedTrack = track.copy(lastChapterRead = chapterNumber)
|
||||
|
||||
async {
|
||||
runCatching {
|
||||
try {
|
||||
service.mangaService.update(updatedTrack.toDbTrack(), true)
|
||||
tracker.mangaService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} catch (e: Exception) {
|
||||
delayedTrackingStore.addMangaItem(updatedTrack)
|
||||
|
|
|
@ -10,7 +10,7 @@ import androidx.work.OneTimeWorkRequestBuilder
|
|||
import androidx.work.WorkerParameters
|
||||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.domain.track.manga.store.DelayedMangaTrackingStore
|
||||
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 DelayedMangaTrackingUpdateJob(context: Context, workerParams: WorkerParame
|
|||
val getTracks = Injekt.get<GetMangaTracks>()
|
||||
val insertTrack = Injekt.get<InsertMangaTrack>()
|
||||
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val trackerManager = Injekt.get<TrackerManager>()
|
||||
val delayedTrackingStore = Injekt.get<DelayedMangaTrackingStore>()
|
||||
|
||||
withIOContext {
|
||||
|
@ -47,10 +47,10 @@ class DelayedMangaTrackingUpdateJob(context: Context, workerParams: WorkerParame
|
|||
}
|
||||
.forEach { track ->
|
||||
try {
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn) {
|
||||
val tracker = trackerManager.get(track.syncId)
|
||||
if (tracker != null && tracker.isLoggedIn) {
|
||||
logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.id}, last chapter read: ${track.lastChapterRead}" }
|
||||
service.mangaService.update(track.toDbTrack(), true)
|
||||
tracker.mangaService.update(track.toDbTrack(), true)
|
||||
insertTrack.await(track)
|
||||
}
|
||||
delayedTrackingStore.removeMangaItem(track.id)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -108,13 +108,13 @@ private fun ColumnScope.FilterPage(
|
|||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompletedAnime) },
|
||||
)
|
||||
|
||||
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.filterTrackedAnime(
|
||||
service.id.toInt(),
|
||||
).collectAsState()
|
||||
|
@ -126,7 +126,7 @@ private fun ColumnScope.FilterPage(
|
|||
}
|
||||
else -> {
|
||||
HeadingItem(R.string.action_filter_tracked)
|
||||
trackServices.map { service ->
|
||||
trackers.map { service ->
|
||||
val filterTracker by screenModel.libraryPreferences.filterTrackedAnime(
|
||||
service.id.toInt(),
|
||||
).collectAsState()
|
||||
|
|
|
@ -108,13 +108,13 @@ private fun ColumnScope.FilterPage(
|
|||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompletedManga) },
|
||||
)
|
||||
|
||||
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.filterTrackedManga(
|
||||
service.id.toInt(),
|
||||
).collectAsState()
|
||||
|
@ -126,7 +126,7 @@ private fun ColumnScope.FilterPage(
|
|||
}
|
||||
else -> {
|
||||
HeadingItem(R.string.action_filter_tracked)
|
||||
trackServices.map { service ->
|
||||
trackers.map { service ->
|
||||
val filterTracker by screenModel.libraryPreferences.filterTrackedManga(
|
||||
service.id.toInt(),
|
||||
).collectAsState()
|
||||
|
|
|
@ -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 {
|
||||
|
@ -146,10 +146,10 @@ sealed class Preference {
|
|||
) : PreferenceItem<String>()
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
|
|
@ -171,13 +171,13 @@ internal fun PreferenceItem(
|
|||
singleLine = false,
|
||||
)
|
||||
}
|
||||
is Preference.PreferenceItem.TrackingPreference -> {
|
||||
is Preference.PreferenceItem.TrackerPreference -> {
|
||||
val uName by Injekt.get<PreferenceStore>()
|
||||
.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() },
|
||||
)
|
||||
|
|
|
@ -40,7 +40,7 @@ import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadCache
|
|||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadCache
|
||||
import eu.kanade.tachiyomi.data.library.anime.AnimeLibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.library.manga.MangaLibraryUpdateJob
|
||||
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
|
||||
|
@ -353,7 +353,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||
private fun getLibraryGroup(): Preference.PreferenceGroup {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val trackManager = remember { Injekt.get<TrackManager>() }
|
||||
val trackerManager = remember { Injekt.get<TrackerManager>() }
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.label_library),
|
||||
|
@ -374,7 +374,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 = {
|
||||
MangaLibraryUpdateJob.startNow(
|
||||
context,
|
||||
|
|
|
@ -24,7 +24,7 @@ import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.library.anime.AnimeLibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.library.manga.MangaLibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.ui.category.CategoriesTab
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -287,7 +287,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
|||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = libraryPreferences.autoUpdateTrackers(),
|
||||
enabled = Injekt.get<TrackManager>().hasLoggedServices(),
|
||||
enabled = Injekt.get<TrackerManager>().hasLoggedIn(),
|
||||
title = stringResource(R.string.pref_library_update_refresh_trackers),
|
||||
subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
|
||||
),
|
||||
|
|
|
@ -272,7 +272,7 @@ private fun getIndex() = settingScreens
|
|||
SettingsData(
|
||||
title = stringResource(screen.getTitleRes()),
|
||||
route = screen,
|
||||
contents = screen.getPreferences(),
|
||||
contents = screen.sourcePreferences(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
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
|
||||
|
@ -83,7 +83,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
|||
override fun getPreferences(): List<Preference> {
|
||||
val context = LocalContext.current
|
||||
val trackPreferences = remember { Injekt.get<TrackPreferences>() }
|
||||
val trackManager = remember { Injekt.get<TrackManager>() }
|
||||
val trackerManager = remember { Injekt.get<TrackerManager>() }
|
||||
val sourceManager = remember { Injekt.get<MangaSourceManager>() }
|
||||
|
||||
var dialog by remember { mutableStateOf<Any?>(null) }
|
||||
|
@ -91,24 +91,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 enhancedMangaTrackers = trackManager.services
|
||||
.filter { it is EnhancedMangaTrackService }
|
||||
val enhancedMangaTrackers = trackerManager.trackers
|
||||
.filter { it is EnhancedMangaTracker }
|
||||
.partition { service ->
|
||||
val acceptedMangaSources = (service as EnhancedMangaTrackService).getAcceptedSources()
|
||||
val acceptedMangaSources = (service as EnhancedMangaTracker).getAcceptedSources()
|
||||
sourceManager.getCatalogueSources().any { it::class.qualifiedName in acceptedMangaSources }
|
||||
}
|
||||
var enhancedMangaTrackerInfo = stringResource(R.string.enhanced_tracking_info)
|
||||
|
@ -136,72 +136,72 @@ 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.simkl.name,
|
||||
service = trackManager.simkl,
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
title = trackerManager.simkl.name,
|
||||
tracker = trackerManager.simkl,
|
||||
login = {
|
||||
context.openInBrowser(
|
||||
SimklApi.authUrl(),
|
||||
forceDefaultBrowser = true,
|
||||
)
|
||||
},
|
||||
logout = { dialog = LogoutDialog(trackManager.simkl) },
|
||||
logout = { dialog = LogoutDialog(trackerManager.simkl) },
|
||||
),
|
||||
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)),
|
||||
),
|
||||
|
@ -210,10 +210,10 @@ object SettingsTrackingScreen : SearchableSettings {
|
|||
title = stringResource(R.string.enhanced_services),
|
||||
preferenceItems = enhancedMangaTrackers.first
|
||||
.map { service ->
|
||||
Preference.PreferenceItem.TrackingPreference(
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
title = service.name,
|
||||
service = service,
|
||||
login = { (service as EnhancedMangaTrackService).loginNoop() },
|
||||
tracker = service,
|
||||
login = { (service as EnhancedMangaTracker).loginNoop() },
|
||||
logout = service::logout,
|
||||
)
|
||||
} + listOf(Preference.PreferenceItem.InfoPreference(enhancedMangaTrackerInfo)),
|
||||
|
@ -224,15 +224,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) }
|
||||
|
||||
|
@ -241,7 +241,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) {
|
||||
|
@ -305,7 +305,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
|||
processing = true
|
||||
val result = checkLogin(
|
||||
context = context,
|
||||
service = service,
|
||||
tracker = tracker,
|
||||
username = username.text,
|
||||
password = password.text,
|
||||
)
|
||||
|
@ -324,16 +324,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
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
|||
|
||||
@Composable
|
||||
private fun TrackingLogoutDialog(
|
||||
service: TrackService,
|
||||
tracker: Tracker,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
@ -349,7 +349,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(),
|
||||
)
|
||||
|
@ -365,7 +365,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
|||
Button(
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
service.logout()
|
||||
tracker.logout()
|
||||
onDismissRequest()
|
||||
context.toast(R.string.logout_success)
|
||||
},
|
||||
|
@ -383,10 +383,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,
|
||||
)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -38,7 +38,7 @@ import eu.kanade.presentation.track.components.TrackLogoIcon
|
|||
import eu.kanade.presentation.track.manga.TrackDetailsItem
|
||||
import eu.kanade.presentation.track.manga.TrackInfoItemMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.ui.entries.anime.track.AnimeTrackItem
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import java.text.DateFormat
|
||||
|
@ -69,12 +69,12 @@ fun AnimeTrackInfoDialogHome(
|
|||
) {
|
||||
trackItems.forEach { item ->
|
||||
if (item.track != null) {
|
||||
val supportsScoring = item.service.animeService.getScoreList().isNotEmpty()
|
||||
val supportsReadingDates = item.service.supportsReadingDates
|
||||
val supportsScoring = item.tracker.animeService.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) },
|
||||
episodes = "${item.track.lastEpisodeSeen.toInt()}".let {
|
||||
val totalEpisodes = item.track.totalEpisodes
|
||||
|
@ -86,7 +86,7 @@ fun AnimeTrackInfoDialogHome(
|
|||
}
|
||||
},
|
||||
onEpisodesClick = { onEpisodeClick(item) },
|
||||
score = item.service.animeService.displayScore(item.track.toDbTrack())
|
||||
score = item.tracker.animeService.displayScore(item.track.toDbTrack())
|
||||
.takeIf { supportsScoring && item.track.score != 0.0 },
|
||||
onScoreClick = { onScoreClick(item) }
|
||||
.takeIf { supportsScoring },
|
||||
|
@ -108,7 +108,7 @@ fun AnimeTrackInfoDialogHome(
|
|||
)
|
||||
} else {
|
||||
TrackInfoItemEmpty(
|
||||
service = item.service,
|
||||
tracker = item.tracker,
|
||||
onNewSearch = { onNewSearch(item) },
|
||||
)
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ fun AnimeTrackInfoDialogHome(
|
|||
@Composable
|
||||
private fun TrackInfoItem(
|
||||
title: String,
|
||||
service: TrackService,
|
||||
tracker: Tracker,
|
||||
@StringRes status: Int?,
|
||||
onStatusClick: () -> Unit,
|
||||
episodes: String,
|
||||
|
@ -140,7 +140,7 @@ private fun TrackInfoItem(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
TrackLogoIcon(
|
||||
service = service,
|
||||
tracker = tracker,
|
||||
onClick = onOpenInBrowser,
|
||||
)
|
||||
Box(
|
||||
|
@ -228,13 +228,13 @@ private fun TrackInfoItem(
|
|||
|
||||
@Composable
|
||||
private fun TrackInfoItemEmpty(
|
||||
service: TrackService,
|
||||
tracker: Tracker,
|
||||
onNewSearch: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
TrackLogoIcon(service)
|
||||
TrackLogoIcon(tracker)
|
||||
TextButton(
|
||||
onClick = onNewSearch,
|
||||
modifier = Modifier
|
||||
|
|
|
@ -53,7 +53,7 @@ import tachiyomi.presentation.core.util.plus
|
|||
import tachiyomi.presentation.core.util.runOnEnterKeyPressed
|
||||
|
||||
@Composable
|
||||
fun AnimeTrackServiceSearch(
|
||||
fun AnimeTrackerSearch(
|
||||
query: TextFieldValue,
|
||||
onQueryChange: (TextFieldValue) -> Unit,
|
||||
onDispatchQuery: () -> Unit,
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ import eu.kanade.domain.track.manga.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.entries.manga.track.MangaTrackItem
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import java.text.DateFormat
|
||||
|
@ -80,12 +80,12 @@ fun MangaTrackInfoDialogHome(
|
|||
) {
|
||||
trackItems.forEach { item ->
|
||||
if (item.track != null) {
|
||||
val supportsScoring = item.service.mangaService.getScoreList().isNotEmpty()
|
||||
val supportsReadingDates = item.service.supportsReadingDates
|
||||
val supportsScoring = item.tracker.mangaService.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 MangaTrackInfoDialogHome(
|
|||
}
|
||||
},
|
||||
onChaptersClick = { onChapterClick(item) },
|
||||
score = item.service.mangaService.displayScore(item.track.toDbTrack())
|
||||
score = item.tracker.mangaService.displayScore(item.track.toDbTrack())
|
||||
.takeIf { supportsScoring && item.track.score != 0.0 },
|
||||
onScoreClick = { onScoreClick(item) }
|
||||
.takeIf { supportsScoring },
|
||||
|
@ -119,7 +119,7 @@ fun MangaTrackInfoDialogHome(
|
|||
)
|
||||
} else {
|
||||
TrackInfoItemEmpty(
|
||||
service = item.service,
|
||||
tracker = item.tracker,
|
||||
onNewSearch = { onNewSearch(item) },
|
||||
)
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ fun MangaTrackInfoDialogHome(
|
|||
@Composable
|
||||
private fun TrackInfoItem(
|
||||
title: String,
|
||||
service: TrackService,
|
||||
tracker: Tracker,
|
||||
@StringRes status: Int?,
|
||||
onStatusClick: () -> Unit,
|
||||
chapters: String,
|
||||
|
@ -151,7 +151,7 @@ private fun TrackInfoItem(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
TrackLogoIcon(
|
||||
service = service,
|
||||
tracker = tracker,
|
||||
onClick = onOpenInBrowser,
|
||||
)
|
||||
Box(
|
||||
|
@ -264,13 +264,13 @@ 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
|
||||
|
|
|
@ -70,7 +70,7 @@ import tachiyomi.presentation.core.util.runOnEnterKeyPressed
|
|||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
|
||||
@Composable
|
||||
fun MangaTrackServiceSearch(
|
||||
fun MangaTrackerSearch(
|
||||
query: TextFieldValue,
|
||||
onQueryChange: (TextFieldValue) -> Unit,
|
||||
onDispatchQuery: () -> Unit,
|
|
@ -29,7 +29,7 @@ import eu.kanade.tachiyomi.data.download.manga.MangaDownloadCache
|
|||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadProvider
|
||||
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.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
||||
|
@ -209,7 +209,7 @@ class AppModule(val app: Application) : InjektModule {
|
|||
addSingletonFactory { AnimeDownloadManager(app) }
|
||||
addSingletonFactory { AnimeDownloadCache(app) }
|
||||
|
||||
addSingletonFactory { TrackManager(app) }
|
||||
addSingletonFactory { TrackerManager(app) }
|
||||
addSingletonFactory { DelayedAnimeTrackingStore(app) }
|
||||
addSingletonFactory { DelayedMangaTrackingStore(app) }
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
|||
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.library.anime.AnimeLibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.library.manga.MangaLibraryUpdateJob
|
||||
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.player.settings.PlayerPreferences
|
||||
|
@ -50,7 +50,7 @@ object Migrations {
|
|||
readerPreferences: ReaderPreferences,
|
||||
playerPreferences: PlayerPreferences,
|
||||
backupPreferences: BackupPreferences,
|
||||
trackManager: TrackManager,
|
||||
trackerManager: TrackerManager,
|
||||
): Boolean {
|
||||
val lastVersionCode = preferenceStore.getInt("last_version_code", 0)
|
||||
val oldVersion = lastVersionCode.get()
|
||||
|
@ -164,8 +164,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)
|
||||
}
|
||||
}
|
||||
|
@ -470,7 +470,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)
|
||||
|
|
|
@ -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.anime.service.AnimeSourceManager
|
||||
import tachiyomi.domain.source.manga.service.MangaSourceManager
|
||||
|
@ -13,7 +13,7 @@ import uy.kohesive.injekt.api.get
|
|||
class BackupFileValidator(
|
||||
private val mangaSourceManager: MangaSourceManager = Injekt.get(),
|
||||
private val animeSourceManager: AnimeSourceManager = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
) {
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,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()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package eu.kanade.tachiyomi.data.track
|
||||
|
||||
import android.app.Application
|
||||
import eu.kanade.domain.items.episode.interactor.SyncEpisodeProgressWithTrack
|
||||
import eu.kanade.domain.track.anime.interactor.SyncEpisodeProgressWithTrack
|
||||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.domain.track.anime.model.toDomainTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
|
@ -24,7 +24,7 @@ import tachiyomi.domain.track.anime.model.AnimeTrack as DomainAnimeTrack
|
|||
private val insertTrack: InsertAnimeTrack by injectLazy()
|
||||
private val syncEpisodeProgressWithTrack: SyncEpisodeProgressWithTrack by injectLazy()
|
||||
|
||||
interface AnimeTrackService {
|
||||
interface AnimeTracker {
|
||||
|
||||
// Common functions
|
||||
fun getCompletionStatus(): Int
|
||||
|
@ -108,7 +108,7 @@ interface AnimeTrackService {
|
|||
}
|
||||
}
|
||||
|
||||
syncEpisodeProgressWithTrack.await(animeId, track, this@AnimeTrackService)
|
||||
syncEpisodeProgressWithTrack.await(animeId, track, this@AnimeTracker)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
withUIContext { Injekt.get<Application>().toast(e.message) }
|
|
@ -3,9 +3,9 @@ package eu.kanade.tachiyomi.data.track
|
|||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
|
||||
/**
|
||||
* 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 DeletableAnimeTrackService {
|
||||
interface DeletableAnimeTracker {
|
||||
|
||||
suspend fun delete(track: AnimeTrack): AnimeTrack
|
||||
}
|
|
@ -3,9 +3,9 @@ package eu.kanade.tachiyomi.data.track
|
|||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
|
||||
/**
|
||||
* 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 DeletableMangaTrackService {
|
||||
interface DeletableMangaTracker {
|
||||
|
||||
suspend fun delete(track: MangaTrack): MangaTrack
|
||||
}
|
|
@ -9,9 +9,9 @@ import tachiyomi.domain.track.anime.model.AnimeTrack
|
|||
* 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.
|
||||
*/
|
||||
interface EnhancedAnimeTrackService {
|
||||
interface EnhancedAnimeTracker {
|
||||
/**
|
||||
* 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: AnimeSource): Boolean {
|
||||
return source::class.qualifiedName in getAcceptedSources()
|
||||
|
@ -25,12 +25,12 @@ interface EnhancedAnimeTrackService {
|
|||
fun loginNoop()
|
||||
|
||||
/**
|
||||
* match is similar to TrackService.search, but only return zero or one match.
|
||||
* match is similar to Tracker.search, but only return zero or one match.
|
||||
*/
|
||||
suspend fun match(anime: Anime): AnimeTrackSearch?
|
||||
|
||||
/**
|
||||
* Checks whether the provided source/track/anime triplet is from this AnimeTrackService
|
||||
* Checks whether the provided source/track/anime triplet is from this AnimeTracker
|
||||
*/
|
||||
fun isTrackFrom(track: AnimeTrack, anime: Anime, source: AnimeSource?): Boolean
|
||||
|
|
@ -6,12 +6,12 @@ import tachiyomi.domain.entries.manga.model.Manga
|
|||
import tachiyomi.domain.track.manga.model.MangaTrack
|
||||
|
||||
/**
|
||||
* 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 EnhancedMangaTrackService {
|
||||
interface EnhancedMangaTracker {
|
||||
/**
|
||||
* 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: MangaSource): Boolean {
|
||||
return source::class.qualifiedName in getAcceptedSources()
|
||||
|
@ -25,12 +25,12 @@ interface EnhancedMangaTrackService {
|
|||
fun loginNoop()
|
||||
|
||||
/**
|
||||
* match is similar to TrackService.search, but only return zero or one match.
|
||||
* match is similar to Tracker.search, but only return zero or one match.
|
||||
*/
|
||||
suspend fun match(manga: Manga): MangaTrackSearch?
|
||||
|
||||
/**
|
||||
* Checks whether the provided source/track/manga triplet is from this TrackService
|
||||
* Checks whether the provided source/track/manga triplet is from this [MangaTrack]
|
||||
*/
|
||||
fun isTrackFrom(track: MangaTrack, manga: Manga, source: MangaSource?): Boolean
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package eu.kanade.tachiyomi.data.track
|
||||
|
||||
import android.app.Application
|
||||
import eu.kanade.domain.items.chapter.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.track.manga.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.domain.track.manga.model.toDomainTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
|
@ -24,7 +24,7 @@ import tachiyomi.domain.track.manga.model.MangaTrack as DomainTrack
|
|||
private val insertTrack: InsertMangaTrack by injectLazy()
|
||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack by injectLazy()
|
||||
|
||||
interface MangaTrackService {
|
||||
interface MangaTracker {
|
||||
|
||||
// Common functions
|
||||
fun getCompletionStatus(): Int
|
||||
|
@ -108,7 +108,7 @@ interface MangaTrackService {
|
|||
}
|
||||
}
|
||||
|
||||
syncChapterProgressWithTrack.await(mangaId, track, this@MangaTrackService)
|
||||
syncChapterProgressWithTrack.await(mangaId, track, this@MangaTracker)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
withUIContext { Injekt.get<Application>().toast(e.message) }
|
|
@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.network.NetworkHelper
|
|||
import okhttp3.OkHttpClient
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
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()
|
||||
|
@ -33,7 +33,7 @@ abstract class TrackService(val id: Long, val name: String) {
|
|||
|
||||
@CallSuper
|
||||
open fun logout() {
|
||||
trackPreferences.setTrackCredentials(this, "", "")
|
||||
trackPreferences.setCredentials(this, "", "")
|
||||
}
|
||||
|
||||
open val isLoggedIn: Boolean
|
||||
|
@ -45,12 +45,12 @@ 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)
|
||||
}
|
||||
|
||||
open val animeService: AnimeTrackService
|
||||
get() = this as AnimeTrackService
|
||||
open val animeService: AnimeTracker
|
||||
get() = this as AnimeTracker
|
||||
|
||||
open val mangaService: MangaTrackService
|
||||
get() = this as MangaTrackService
|
||||
open val mangaService: MangaTracker
|
||||
get() = this as MangaTracker
|
||||
}
|
|
@ -12,35 +12,29 @@ import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
|
|||
import eu.kanade.tachiyomi.data.track.simkl.Simkl
|
||||
import eu.kanade.tachiyomi.data.track.suwayomi.Suwayomi
|
||||
|
||||
class TrackManager(context: Context) {
|
||||
class TrackerManager(context: Context) {
|
||||
|
||||
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
|
||||
const val SIMKL = 101L
|
||||
}
|
||||
|
||||
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 shikimori = Shikimori(4L)
|
||||
val bangumi = Bangumi(5L)
|
||||
val komga = Komga(6L)
|
||||
val mangaUpdates = MangaUpdates(7L)
|
||||
val kavita = Kavita(context, KAVITA)
|
||||
val suwayomi = Suwayomi(SUWAYOMI)
|
||||
val suwayomi = Suwayomi(9L)
|
||||
val simkl = Simkl(SIMKL)
|
||||
|
||||
val services = listOf(myAnimeList, aniList, kitsu, shikimori, bangumi, komga, mangaUpdates, kavita, suwayomi, simkl)
|
||||
val trackers = listOf(myAnimeList, aniList, kitsu, shikimori, bangumi, komga, mangaUpdates, kavita, suwayomi, simkl)
|
||||
|
||||
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 }
|
||||
}
|
|
@ -5,11 +5,11 @@ import androidx.annotation.StringRes
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -19,7 +19,7 @@ import uy.kohesive.injekt.injectLazy
|
|||
import tachiyomi.domain.track.anime.model.AnimeTrack as DomainAnimeTrack
|
||||
import tachiyomi.domain.track.manga.model.MangaTrack as DomainTrack
|
||||
|
||||
class Anilist(id: Long) : TrackService(id, "AniList"), MangaTrackService, AnimeTrackService, DeletableMangaTrackService, DeletableAnimeTrackService {
|
||||
class Anilist(id: Long) : Tracker(id, "AniList"), MangaTracker, AnimeTracker, DeletableMangaTracker, DeletableAnimeTracker {
|
||||
|
||||
companion object {
|
||||
const val READING = 1
|
||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.track.anilist
|
|||
import eu.kanade.domain.track.service.TrackPreferences
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -22,7 +22,7 @@ data class ALManga(
|
|||
val total_chapters: Int,
|
||||
) {
|
||||
|
||||
fun toTrack() = MangaTrackSearch.create(TrackManager.ANILIST).apply {
|
||||
fun toTrack() = MangaTrackSearch.create(TrackerManager.ANILIST).apply {
|
||||
media_id = this@ALManga.media_id
|
||||
title = title_user_pref
|
||||
total_chapters = this@ALManga.total_chapters
|
||||
|
@ -53,7 +53,7 @@ data class ALAnime(
|
|||
val total_episodes: Int,
|
||||
) {
|
||||
|
||||
fun toTrack() = AnimeTrackSearch.create(TrackManager.ANILIST).apply {
|
||||
fun toTrack() = AnimeTrackSearch.create(TrackerManager.ANILIST).apply {
|
||||
media_id = this@ALAnime.media_id
|
||||
title = title_user_pref
|
||||
total_episodes = this@ALAnime.total_episodes
|
||||
|
@ -83,7 +83,7 @@ data class ALUserManga(
|
|||
val manga: ALManga,
|
||||
) {
|
||||
|
||||
fun toTrack() = MangaTrack.create(TrackManager.ANILIST).apply {
|
||||
fun toTrack() = MangaTrack.create(TrackerManager.ANILIST).apply {
|
||||
media_id = manga.media_id
|
||||
title = manga.title_user_pref
|
||||
status = toTrackStatus()
|
||||
|
@ -95,7 +95,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.PAUSED
|
||||
|
@ -116,7 +116,7 @@ data class ALUserAnime(
|
|||
val anime: ALAnime,
|
||||
) {
|
||||
|
||||
fun toTrack() = AnimeTrack.create(TrackManager.ANILIST).apply {
|
||||
fun toTrack() = AnimeTrack.create(TrackerManager.ANILIST).apply {
|
||||
media_id = anime.media_id
|
||||
title = anime.title_user_pref
|
||||
status = toTrackStatus()
|
||||
|
@ -128,7 +128,7 @@ data class ALUserAnime(
|
|||
total_episodes = anime.total_episodes
|
||||
}
|
||||
|
||||
fun toTrackStatus() = when (list_status) {
|
||||
private fun toTrackStatus() = when (list_status) {
|
||||
"CURRENT" -> Anilist.WATCHING
|
||||
"COMPLETED" -> Anilist.COMPLETED
|
||||
"PAUSED" -> Anilist.PAUSED
|
||||
|
|
|
@ -5,9 +5,9 @@ import androidx.annotation.StringRes
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -15,13 +15,13 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class Bangumi(id: Long) : TrackService(id, "Bangumi"), MangaTrackService, AnimeTrackService {
|
||||
class Bangumi(id: Long) : Tracker(id, "Bangumi"), MangaTracker, AnimeTracker {
|
||||
|
||||
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<String> {
|
||||
return IntRange(0, 10).map(Int::toString)
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.net.Uri
|
|||
import androidx.core.net.toUri
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
|
@ -29,7 +28,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()
|
||||
|
||||
|
@ -175,7 +178,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||
} else {
|
||||
0
|
||||
}
|
||||
return MangaTrackSearch.create(TrackManager.BANGUMI).apply {
|
||||
return MangaTrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["name_cn"]!!.jsonPrimitive.content
|
||||
cover_url = coverUrl
|
||||
|
@ -197,7 +200,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||
} else {
|
||||
0
|
||||
}
|
||||
return AnimeTrackSearch.create(TrackManager.BANGUMI).apply {
|
||||
return AnimeTrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["name_cn"]!!.jsonPrimitive.content
|
||||
cover_url = coverUrl
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
package eu.kanade.tachiyomi.data.track.kavita
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.StringRes
|
||||
import com.google.common.base.Strings.isNullOrEmpty
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import eu.kanade.tachiyomi.source.sourcePreferences
|
||||
import tachiyomi.domain.entries.manga.model.Manga
|
||||
import tachiyomi.domain.source.manga.service.MangaSourceManager
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.security.MessageDigest
|
||||
import tachiyomi.domain.track.manga.model.MangaTrack as DomainTrack
|
||||
|
||||
class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita"), EnhancedMangaTrackService, MangaTrackService {
|
||||
class Kavita(private val context: Context, id: Long) : Tracker(id, "Kavita"), EnhancedMangaTracker, MangaTracker {
|
||||
|
||||
companion object {
|
||||
const val UNREAD = 1
|
||||
|
@ -28,6 +32,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: MangaSourceManager by injectLazy()
|
||||
|
||||
override fun getLogo(): Int = R.drawable.ic_tracker_kavita
|
||||
|
||||
override fun getLogoColor() = Color.rgb(74, 198, 148)
|
||||
|
@ -84,7 +90,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")
|
||||
|
@ -111,28 +117,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", 0x0000)
|
||||
}
|
||||
val prefApiUrl = preferences.getString("APIURL", "")!!
|
||||
if (prefApiUrl.isEmpty()) {
|
||||
val preferences = (sourceManager.get(sourceId) as ConfigurableSource).sourcePreferences()
|
||||
|
||||
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()
|
||||
}
|
||||
|
|
|
@ -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.MangaTrackSearch
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
@ -22,7 +22,7 @@ data class SeriesDto(
|
|||
val libraryId: Int,
|
||||
val libraryName: String? = "",
|
||||
) {
|
||||
fun toTrack(): MangaTrackSearch = MangaTrackSearch.create(TrackManager.KAVITA).also {
|
||||
fun toTrack(): MangaTrackSearch = MangaTrackSearch.create(TrackerManager.KAVITA).also {
|
||||
it.title = name
|
||||
it.summary = ""
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import androidx.annotation.StringRes
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -18,7 +18,7 @@ import kotlinx.serialization.json.Json
|
|||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class Kitsu(id: Long) : TrackService(id, "Kitsu"), AnimeTrackService, MangaTrackService, DeletableMangaTrackService, DeletableAnimeTrackService {
|
||||
class Kitsu(id: Long) : Tracker(id, "Kitsu"), AnimeTracker, MangaTracker, DeletableMangaTracker, DeletableAnimeTracker {
|
||||
|
||||
companion object {
|
||||
const val READING = 1
|
||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.track.kitsu
|
|||
import androidx.annotation.CallSuper
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -37,7 +37,7 @@ class KitsuSearchManga(obj: JsonObject) {
|
|||
private val endDate = obj["endDate"]?.jsonPrimitive?.contentOrNull
|
||||
|
||||
@CallSuper
|
||||
fun toTrack() = MangaTrackSearch.create(TrackManager.KITSU).apply {
|
||||
fun toTrack() = MangaTrackSearch.create(TrackerManager.KITSU).apply {
|
||||
media_id = this@KitsuSearchManga.id
|
||||
title = canonicalTitle
|
||||
total_chapters = chapterCount ?: 0
|
||||
|
@ -73,7 +73,7 @@ class KitsuSearchAnime(obj: JsonObject) {
|
|||
private val endDate = obj["endDate"]?.jsonPrimitive?.contentOrNull
|
||||
|
||||
@CallSuper
|
||||
fun toTrack() = AnimeTrackSearch.create(TrackManager.KITSU).apply {
|
||||
fun toTrack() = AnimeTrackSearch.create(TrackerManager.KITSU).apply {
|
||||
media_id = this@KitsuSearchAnime.id
|
||||
title = canonicalTitle
|
||||
total_episodes = episodeCount ?: 0
|
||||
|
@ -105,7 +105,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() = MangaTrackSearch.create(TrackManager.KITSU).apply {
|
||||
fun toTrack() = MangaTrackSearch.create(TrackerManager.KITSU).apply {
|
||||
media_id = libraryId
|
||||
title = canonicalTitle
|
||||
total_chapters = chapterCount ?: 0
|
||||
|
@ -147,7 +147,7 @@ class KitsuLibAnime(obj: JsonObject, anime: JsonObject) {
|
|||
private val ratingTwenty = obj["attributes"]!!.jsonObject["ratingTwenty"]?.jsonPrimitive?.contentOrNull
|
||||
val progress = obj["attributes"]!!.jsonObject["progress"]!!.jsonPrimitive.int
|
||||
|
||||
fun toTrack() = AnimeTrackSearch.create(TrackManager.KITSU).apply {
|
||||
fun toTrack() = AnimeTrackSearch.create(TrackerManager.KITSU).apply {
|
||||
media_id = libraryId
|
||||
title = canonicalTitle
|
||||
total_episodes = episodeCount ?: 0
|
||||
|
|
|
@ -4,9 +4,9 @@ import android.graphics.Color
|
|||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import okhttp3.Dns
|
||||
|
@ -14,7 +14,7 @@ import okhttp3.OkHttpClient
|
|||
import tachiyomi.domain.entries.manga.model.Manga
|
||||
import tachiyomi.domain.track.manga.model.MangaTrack as DomainTrack
|
||||
|
||||
class Komga(id: Long) : TrackService(id, "Komga"), EnhancedMangaTrackService, MangaTrackService {
|
||||
class Komga(id: Long) : Tracker(id, "Komga"), EnhancedMangaTracker, MangaTracker {
|
||||
|
||||
companion object {
|
||||
const val UNREAD = 1
|
||||
|
@ -27,7 +27,7 @@ class Komga(id: Long) : TrackService(id, "Komga"), EnhancedMangaTrackService, Ma
|
|||
.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
|
||||
|
||||
|
@ -86,7 +86,7 @@ class Komga(id: Long) : TrackService(id, "Komga"), EnhancedMangaTrackService, Ma
|
|||
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")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package eu.kanade.tachiyomi.data.track.komga
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
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()
|
||||
|
||||
|
@ -91,14 +93,14 @@ class KomgaApi(private val client: OkHttpClient) {
|
|||
return getTrackSearch(track.tracking_url)
|
||||
}
|
||||
|
||||
private fun SeriesDto.toTrack(): MangaTrackSearch = MangaTrackSearch.create(TrackManager.KOMGA).also {
|
||||
private fun SeriesDto.toTrack(): MangaTrackSearch = MangaTrackSearch.create(trackId).also {
|
||||
it.title = metadata.title
|
||||
it.summary = metadata.summary
|
||||
it.publishing_status = metadata.status
|
||||
}
|
||||
|
||||
private fun ReadListDto.toTrack(): MangaTrackSearch = MangaTrackSearch.create(
|
||||
TrackManager.KOMGA,
|
||||
trackId,
|
||||
).also {
|
||||
it.title = name
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ import android.graphics.Color
|
|||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
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.MangaTrackSearch
|
||||
|
||||
class MangaUpdates(id: Long) : TrackService(id, "MangaUpdates"), MangaTrackService, DeletableMangaTrackService {
|
||||
class MangaUpdates(id: Long) : Tracker(id, "MangaUpdates"), MangaTracker, DeletableMangaTracker {
|
||||
|
||||
companion object {
|
||||
const val READING_LIST = 0
|
||||
|
|
|
@ -5,11 +5,11 @@ import androidx.annotation.StringRes
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -17,7 +17,7 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), MangaTrackService, AnimeTrackService, DeletableMangaTrackService, DeletableAnimeTrackService {
|
||||
class MyAnimeList(id: Long) : Tracker(id, "MyAnimeList"), MangaTracker, AnimeTracker, DeletableMangaTracker, DeletableAnimeTracker {
|
||||
|
||||
companion object {
|
||||
const val READING = 1
|
||||
|
@ -37,7 +37,7 @@ class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), MangaTrackService
|
|||
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
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.net.Uri
|
|||
import androidx.core.net.toUri
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
|
@ -34,7 +33,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()
|
||||
|
||||
|
@ -136,7 +139,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
|||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val obj = it.jsonObject
|
||||
MangaTrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||
MangaTrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
|
@ -176,7 +179,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
|||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val obj = it.jsonObject
|
||||
AnimeTrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||
AnimeTrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
|
|
|
@ -5,11 +5,11 @@ import androidx.annotation.StringRes
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -17,7 +17,7 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class Shikimori(id: Long) : TrackService(id, "Shikimori"), MangaTrackService, AnimeTrackService, DeletableMangaTrackService, DeletableAnimeTrackService {
|
||||
class Shikimori(id: Long) : Tracker(id, "Shikimori"), MangaTracker, AnimeTracker, DeletableMangaTracker, DeletableAnimeTracker {
|
||||
|
||||
companion object {
|
||||
const val READING = 1
|
||||
|
@ -32,7 +32,7 @@ class Shikimori(id: Long) : TrackService(id, "Shikimori"), MangaTrackService, An
|
|||
|
||||
private val interceptor by lazy { ShikimoriInterceptor(this) }
|
||||
|
||||
private val api by lazy { ShikimoriApi(client, interceptor) }
|
||||
private val api by lazy { ShikimoriApi(id, client, interceptor) }
|
||||
|
||||
override fun getScoreList(): List<String> {
|
||||
return IntRange(0, 10).map(Int::toString)
|
||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.shikimori
|
|||
import androidx.core.net.toUri
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.network.DELETE
|
||||
|
@ -30,7 +29,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()
|
||||
|
||||
|
@ -165,7 +168,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
|||
}
|
||||
|
||||
private fun jsonToSearch(obj: JsonObject): MangaTrackSearch {
|
||||
return MangaTrackSearch.create(TrackManager.SHIKIMORI).apply {
|
||||
return MangaTrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["name"]!!.jsonPrimitive.content
|
||||
total_chapters = obj["chapters"]!!.jsonPrimitive.int
|
||||
|
@ -179,7 +182,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
|||
}
|
||||
|
||||
private fun jsonToAnimeSearch(obj: JsonObject): AnimeTrackSearch {
|
||||
return AnimeTrackSearch.create(TrackManager.SHIKIMORI).apply {
|
||||
return AnimeTrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["name"]!!.jsonPrimitive.content
|
||||
total_episodes = obj["episodes"]!!.jsonPrimitive.int
|
||||
|
@ -193,7 +196,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
|||
}
|
||||
|
||||
private fun jsonToTrack(obj: JsonObject, mangas: JsonObject): MangaTrack {
|
||||
return MangaTrack.create(TrackManager.SHIKIMORI).apply {
|
||||
return MangaTrack.create(trackId).apply {
|
||||
title = mangas["name"]!!.jsonPrimitive.content
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
|
||||
|
@ -206,7 +209,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
|||
}
|
||||
|
||||
private fun jsonToAnimeTrack(obj: JsonObject, animes: JsonObject): AnimeTrack {
|
||||
return AnimeTrack.create(TrackManager.SHIKIMORI).apply {
|
||||
return AnimeTrack.create(trackId).apply {
|
||||
title = animes["name"]!!.jsonPrimitive.content
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
total_episodes = animes["episodes"]!!.jsonPrimitive.int
|
||||
|
|
|
@ -4,15 +4,15 @@ import android.graphics.Color
|
|||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class Simkl(id: Long) : TrackService(id, "Simkl"), AnimeTrackService {
|
||||
class Simkl(id: Long) : Tracker(id, "Simkl"), AnimeTracker {
|
||||
|
||||
companion object {
|
||||
const val WATCHING = 1
|
||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.track.simkl
|
|||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
|
@ -167,7 +167,7 @@ class SimklApi(private val client: OkHttpClient, interceptor: SimklInterceptor)
|
|||
}
|
||||
|
||||
private fun jsonToAnimeSearch(obj: JsonObject, type: String): AnimeTrackSearch {
|
||||
return AnimeTrackSearch.create(TrackManager.SIMKL).apply {
|
||||
return AnimeTrackSearch.create(TrackerManager.SIMKL).apply {
|
||||
media_id = obj["ids"]!!.jsonObject["simkl_id"]!!.jsonPrimitive.long
|
||||
title = obj["title_romaji"]?.jsonPrimitive?.content ?: obj["title"]!!.jsonPrimitive.content
|
||||
total_episodes = obj["ep_count"]?.jsonPrimitive?.intOrNull ?: 1
|
||||
|
@ -186,7 +186,7 @@ class SimklApi(private val client: OkHttpClient, interceptor: SimklInterceptor)
|
|||
type: String,
|
||||
statusString: String,
|
||||
): AnimeTrack {
|
||||
return AnimeTrack.create(TrackManager.SIMKL).apply {
|
||||
return AnimeTrack.create(TrackerManager.SIMKL).apply {
|
||||
title = obj[typeName]!!.jsonObject["title"]!!.jsonPrimitive.content
|
||||
val id = obj[typeName]!!.jsonObject["ids"]!!.jsonObject["simkl"]!!.jsonPrimitive.long
|
||||
media_id = id
|
||||
|
|
|
@ -4,16 +4,17 @@ import android.graphics.Color
|
|||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import tachiyomi.domain.entries.manga.model.Manga as DomainManga
|
||||
import tachiyomi.domain.track.manga.model.MangaTrack as DomainTrack
|
||||
|
||||
class Suwayomi(id: Long) : TrackService(id, "Suwayomi"), EnhancedMangaTrackService, MangaTrackService {
|
||||
val api by lazy { TachideskApi() }
|
||||
class Suwayomi(id: Long) : Tracker(id, "Suwayomi"), EnhancedMangaTracker, MangaTracker {
|
||||
|
||||
val api by lazy { SuwayomiApi(id) }
|
||||
|
||||
override fun getLogo() = R.drawable.ic_tracker_suwayomi
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.suwayomi
|
|||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
|
@ -23,7 +22,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 by injectLazy<NetworkHelper>()
|
||||
private val json: Json by injectLazy()
|
||||
|
@ -62,7 +61,7 @@ class TachideskApi {
|
|||
.parseAs<MangaDataClass>()
|
||||
}
|
||||
|
||||
MangaTrackSearch.create(TrackManager.SUWAYOMI).apply {
|
||||
MangaTrackSearch.create(trackId).apply {
|
||||
title = manga.title
|
||||
cover_url = "$url/thumbnail"
|
||||
summary = manga.description.orEmpty()
|
||||
|
@ -101,14 +100,14 @@ 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<Application>().getSharedPreferences("source_$tachideskExtensionId", 0x0000)
|
||||
Injekt.get<Application>().getSharedPreferences("source_$sourceId", 0x0000)
|
||||
}
|
||||
|
||||
private fun getPrefBaseUrl(): String = preferences.getString(ADDRESS_TITLE, ADDRESS_DEFAULT)!!
|
||||
|
@ -117,13 +116,11 @@ class TachideskApi {
|
|||
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 = ""
|
|
@ -11,8 +11,6 @@ import uy.kohesive.injekt.api.get
|
|||
|
||||
fun AnimeSource.icon(): Drawable? = Injekt.get<AnimeExtensionManager>().getAppIconForSource(this.id)
|
||||
|
||||
fun AnimeSource.getPreferenceKey(): String = "source_$id"
|
||||
|
||||
fun AnimeSource.toStubSource(): StubAnimeSource = StubAnimeSource(id = id, lang = lang, name = name)
|
||||
|
||||
fun AnimeSource.getNameForAnimeInfo(): String {
|
||||
|
|
|
@ -11,8 +11,6 @@ import uy.kohesive.injekt.api.get
|
|||
|
||||
fun MangaSource.icon(): Drawable? = Injekt.get<MangaExtensionManager>().getAppIconForSource(this.id)
|
||||
|
||||
fun MangaSource.getPreferenceKey(): String = "source_$id"
|
||||
|
||||
fun MangaSource.toStubSource(): StubMangaSource = StubMangaSource(id = id, lang = lang, name = name)
|
||||
|
||||
fun MangaSource.getNameForMangaInfo(): String {
|
||||
|
|
|
@ -38,8 +38,8 @@ import eu.kanade.presentation.components.UpIcon
|
|||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.sourcePreferences
|
||||
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
||||
import eu.kanade.tachiyomi.source.anime.getPreferenceKey
|
||||
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
|
||||
import tachiyomi.domain.source.anime.service.AnimeSourceManager
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
|
@ -138,15 +138,9 @@ class SourcePreferencesFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun populateScreen(): PreferenceScreen {
|
||||
val sourceId = requireArguments().getLong(SOURCE_ID)
|
||||
val source = Injekt.get<AnimeSourceManager>().get(sourceId)!!
|
||||
val source = Injekt.get<AnimeSourceManager>().get(sourceId)!! as ConfigurableAnimeSource
|
||||
|
||||
check(source is ConfigurableAnimeSource)
|
||||
|
||||
val sharedPreferences = requireContext().getSharedPreferences(
|
||||
source.getPreferenceKey(),
|
||||
Context.MODE_PRIVATE,
|
||||
)
|
||||
val dataStore = SharedPreferencesDataStore(sharedPreferences)
|
||||
val dataStore = SharedPreferencesDataStore(source.sourcePreferences())
|
||||
preferenceManager.preferenceDataStore = dataStore
|
||||
|
||||
val sourceScreen = preferenceManager.createPreferenceScreen(requireContext())
|
||||
|
|
|
@ -37,8 +37,8 @@ import eu.kanade.tachiyomi.animesource.AnimeSource
|
|||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
||||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.ui.browse.anime.migration.AnimeMigrationFlags
|
||||
import kotlinx.coroutines.flow.update
|
||||
import tachiyomi.core.preference.Preference
|
||||
|
@ -180,7 +180,7 @@ internal class MigrateAnimeDialogScreenModel(
|
|||
}
|
||||
|
||||
private val enhancedServices by lazy {
|
||||
Injekt.get<TrackManager>().services.filterIsInstance<EnhancedAnimeTrackService>()
|
||||
Injekt.get<TrackerManager>().trackers.filterIsInstance<EnhancedAnimeTracker>()
|
||||
}
|
||||
|
||||
suspend fun migrateAnime(
|
||||
|
|
|
@ -17,16 +17,12 @@ import eu.kanade.core.preference.asState
|
|||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.entries.anime.interactor.UpdateAnime
|
||||
import eu.kanade.domain.entries.anime.model.toDomainAnime
|
||||
import eu.kanade.domain.items.episode.interactor.SyncEpisodeProgressWithTrack
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.domain.track.anime.model.toDomainTrack
|
||||
import eu.kanade.domain.track.anime.interactor.AddAnimeTracks
|
||||
import eu.kanade.presentation.util.ioCoroutineScope
|
||||
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
@ -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.anime.interactor.GetAnimeCategories
|
||||
import tachiyomi.domain.category.anime.interactor.SetAnimeCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
|
@ -54,7 +48,6 @@ import tachiyomi.domain.items.episode.interactor.SetAnimeDefaultEpisodeFlags
|
|||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.source.anime.interactor.GetRemoteAnime
|
||||
import tachiyomi.domain.source.anime.service.AnimeSourceManager
|
||||
import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
|
@ -76,12 +69,9 @@ class BrowseAnimeSourceScreenModel(
|
|||
private val getAnime: GetAnime = Injekt.get(),
|
||||
private val networkToLocalAnime: NetworkToLocalAnime = Injekt.get(),
|
||||
private val updateAnime: UpdateAnime = Injekt.get(),
|
||||
private val insertTrack: InsertAnimeTrack = Injekt.get(),
|
||||
private val syncEpisodeProgressWithTrack: SyncEpisodeProgressWithTrack = Injekt.get(),
|
||||
private val addTracks: AddAnimeTracks = Injekt.get(),
|
||||
) : StateScreenModel<BrowseAnimeSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
||||
|
||||
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLoggedIn } }
|
||||
|
||||
var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope)
|
||||
|
||||
val source = sourceManager.getOrStub(sourceId)
|
||||
|
@ -242,8 +232,7 @@ class BrowseAnimeSourceScreenModel(
|
|||
new = new.removeCovers(coverCache)
|
||||
} else {
|
||||
setAnimeDefaultEpisodeFlags.await(anime)
|
||||
|
||||
autoAddTrack(anime)
|
||||
addTracks.bindEnhancedTracks(anime, source)
|
||||
}
|
||||
|
||||
updateAnime.await(new.toAnimeUpdate())
|
||||
|
@ -284,31 +273,6 @@ class BrowseAnimeSourceScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun autoAddTrack(anime: Anime) {
|
||||
loggedServices
|
||||
.filterIsInstance<EnhancedAnimeTrackService>()
|
||||
.filter { it.accept(source) }
|
||||
.forEach { service ->
|
||||
try {
|
||||
service.match(anime)?.let { track ->
|
||||
track.anime_id = anime.id
|
||||
(service as TrackService).animeService.bind(track)
|
||||
insertTrack.await(track.toDomainTrack()!!)
|
||||
syncEpisodeProgressWithTrack.await(
|
||||
anime.id,
|
||||
track.toDomainTrack()!!,
|
||||
service.animeService,
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(
|
||||
LogPriority.WARN,
|
||||
e,
|
||||
) { "Could not match anime: ${anime.title} with service $service" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user categories.
|
||||
*
|
||||
|
|
|
@ -39,7 +39,7 @@ import eu.kanade.presentation.util.Screen
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.manga.getPreferenceKey
|
||||
import eu.kanade.tachiyomi.source.sourcePreferences
|
||||
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
|
||||
import tachiyomi.domain.source.manga.service.MangaSourceManager
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
|
@ -138,15 +138,9 @@ class MangaSourcePreferencesFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun populateScreen(): PreferenceScreen {
|
||||
val sourceId = requireArguments().getLong(SOURCE_ID)
|
||||
val source = Injekt.get<MangaSourceManager>().get(sourceId)!!
|
||||
val source = Injekt.get<MangaSourceManager>().get(sourceId)!! as ConfigurableSource
|
||||
|
||||
check(source is ConfigurableSource)
|
||||
|
||||
val sharedPreferences = requireContext().getSharedPreferences(
|
||||
source.getPreferenceKey(),
|
||||
Context.MODE_PRIVATE,
|
||||
)
|
||||
val dataStore = SharedPreferencesDataStore(sharedPreferences)
|
||||
val dataStore = SharedPreferencesDataStore(source.sourcePreferences())
|
||||
preferenceManager.preferenceDataStore = dataStore
|
||||
|
||||
val sourceScreen = preferenceManager.createPreferenceScreen(requireContext())
|
||||
|
|
|
@ -35,8 +35,8 @@ import eu.kanade.domain.items.chapter.interactor.SyncChaptersWithSource
|
|||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.cache.MangaCoverCache
|
||||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.ui.browse.manga.migration.MangaMigrationFlags
|
||||
|
@ -180,7 +180,7 @@ internal class MigrateMangaDialogScreenModel(
|
|||
}
|
||||
|
||||
private val enhancedServices by lazy {
|
||||
Injekt.get<TrackManager>().services.filterIsInstance<EnhancedMangaTrackService>()
|
||||
Injekt.get<TrackerManager>().trackers.filterIsInstance<EnhancedMangaTracker>()
|
||||
}
|
||||
|
||||
suspend fun migrateManga(
|
||||
|
|
|
@ -17,14 +17,10 @@ import eu.kanade.core.preference.asState
|
|||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.entries.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.entries.manga.model.toDomainManga
|
||||
import eu.kanade.domain.items.chapter.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.domain.track.manga.model.toDomainTrack
|
||||
import eu.kanade.domain.track.manga.interactor.AddMangaTracks
|
||||
import eu.kanade.presentation.util.ioCoroutineScope
|
||||
import eu.kanade.tachiyomi.data.cache.MangaCoverCache
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
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.manga.interactor.GetMangaCategories
|
||||
import tachiyomi.domain.category.manga.interactor.SetMangaCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
|
@ -54,7 +48,6 @@ import tachiyomi.domain.items.chapter.interactor.SetMangaDefaultChapterFlags
|
|||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.source.manga.interactor.GetRemoteManga
|
||||
import tachiyomi.domain.source.manga.service.MangaSourceManager
|
||||
import tachiyomi.domain.track.manga.interactor.InsertMangaTrack
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
|
@ -76,12 +69,9 @@ class BrowseMangaSourceScreenModel(
|
|||
private val getManga: GetManga = Injekt.get(),
|
||||
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
||||
private val updateManga: UpdateManga = Injekt.get(),
|
||||
private val insertTrack: InsertMangaTrack = Injekt.get(),
|
||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack = Injekt.get(),
|
||||
private val addTracks: AddMangaTracks = Injekt.get(),
|
||||
) : StateScreenModel<BrowseMangaSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
||||
|
||||
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLoggedIn } }
|
||||
|
||||
var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope)
|
||||
|
||||
val source = sourceManager.getOrStub(sourceId)
|
||||
|
@ -243,8 +233,7 @@ class BrowseMangaSourceScreenModel(
|
|||
new = new.removeCovers(coverCache)
|
||||
} else {
|
||||
setMangaDefaultChapterFlags.await(manga)
|
||||
|
||||
autoAddTrack(manga)
|
||||
addTracks.bindEnhancedTracks(manga, source)
|
||||
}
|
||||
|
||||
updateManga.await(new.toMangaUpdate())
|
||||
|
@ -286,28 +275,6 @@ class BrowseMangaSourceScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun autoAddTrack(manga: Manga) {
|
||||
loggedServices
|
||||
.filterIsInstance<EnhancedMangaTrackService>()
|
||||
.filter { it.accept(source) }
|
||||
.forEach { service ->
|
||||
try {
|
||||
service.match(manga)?.let { track ->
|
||||
track.manga_id = manga.id
|
||||
(service as TrackService).mangaService.bind(track)
|
||||
insertTrack.await(track.toDomainTrack()!!)
|
||||
syncChapterProgressWithTrack.await(
|
||||
manga.id,
|
||||
track.toDomainTrack()!!,
|
||||
service.mangaService,
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user categories.
|
||||
*
|
||||
|
|
|
@ -27,9 +27,9 @@ import eu.kanade.tachiyomi.animesource.model.Video
|
|||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadCache
|
||||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.anime.model.AnimeDownload
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.network.HttpException
|
||||
import eu.kanade.tachiyomi.ui.entries.anime.track.AnimeTrackItem
|
||||
import eu.kanade.tachiyomi.ui.player.settings.PlayerPreferences
|
||||
|
@ -90,7 +90,7 @@ class AnimeScreenModel(
|
|||
uiPreferences: UiPreferences = Injekt.get(),
|
||||
private val trackPreferences: TrackPreferences = Injekt.get(),
|
||||
internal val playerPreferences: PlayerPreferences = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
private val downloadManager: AnimeDownloadManager = Injekt.get(),
|
||||
private val downloadCache: AnimeDownloadCache = Injekt.get(),
|
||||
private val getAnimeAndEpisodes: GetAnimeWithEpisodes = Injekt.get(),
|
||||
|
@ -112,7 +112,7 @@ class AnimeScreenModel(
|
|||
private val successState: State.Success?
|
||||
get() = state.value as? State.Success
|
||||
|
||||
private val loggedServices by lazy { trackManager.services.filter { it.isLoggedIn && it is AnimeTrackService } }
|
||||
private val loggedInTrackers by lazy { trackerManager.trackers.filter { it.isLoggedIn && it is AnimeTracker } }
|
||||
|
||||
val anime: Anime?
|
||||
get() = successState?.anime
|
||||
|
@ -335,14 +335,14 @@ class AnimeScreenModel(
|
|||
// Finally match with enhanced tracking when available
|
||||
val source = state.source
|
||||
state.trackItems
|
||||
.map { it.service }
|
||||
.filterIsInstance<EnhancedAnimeTrackService>()
|
||||
.map { it.tracker }
|
||||
.filterIsInstance<EnhancedAnimeTracker>()
|
||||
.filter { it.accept(source) }
|
||||
.forEach { service ->
|
||||
launchIO {
|
||||
try {
|
||||
service.match(anime)?.let { track ->
|
||||
(service as AnimeTrackService).register(track, animeId)
|
||||
(service as AnimeTracker).register(track, animeId)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.WARN, e) {
|
||||
|
@ -992,7 +992,7 @@ class AnimeScreenModel(
|
|||
getTracks.subscribe(anime.id)
|
||||
.catch { logcat(LogPriority.ERROR, it) }
|
||||
.map { tracks ->
|
||||
loggedServices
|
||||
loggedInTrackers
|
||||
// Map to TrackItem
|
||||
.map { service ->
|
||||
AnimeTrackItem(
|
||||
|
@ -1001,7 +1001,7 @@ class AnimeScreenModel(
|
|||
)
|
||||
}
|
||||
// Show only if the service supports this anime's source
|
||||
.filter { (it.service as? EnhancedAnimeTrackService)?.accept(source!!) ?: true }
|
||||
.filter { (it.tracker as? EnhancedAnimeTracker)?.accept(source!!) ?: true }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { trackItems ->
|
||||
|
|
|
@ -47,14 +47,14 @@ import eu.kanade.presentation.track.TrackItemSelector
|
|||
import eu.kanade.presentation.track.TrackScoreSelector
|
||||
import eu.kanade.presentation.track.TrackStatusSelector
|
||||
import eu.kanade.presentation.track.anime.AnimeTrackInfoDialogHome
|
||||
import eu.kanade.presentation.track.anime.AnimeTrackServiceSearch
|
||||
import eu.kanade.presentation.track.anime.AnimeTrackerSearch
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.DeletableAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
|
@ -110,7 +110,7 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackStatusSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -118,7 +118,7 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackEpisodeSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -126,7 +126,7 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackScoreSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -134,7 +134,7 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackDateSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
start = true,
|
||||
),
|
||||
)
|
||||
|
@ -143,13 +143,13 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackDateSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
start = false,
|
||||
),
|
||||
)
|
||||
},
|
||||
onNewSearch = {
|
||||
if (it.service is EnhancedAnimeTrackService) {
|
||||
if (it.tracker is EnhancedAnimeTracker) {
|
||||
sm.registerEnhancedTracking(it)
|
||||
} else {
|
||||
navigator.push(
|
||||
|
@ -157,7 +157,7 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
animeId = animeId,
|
||||
initialQuery = it.track?.title ?: animeTitle,
|
||||
currentUrl = it.track?.remoteUrl,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -165,10 +165,10 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
onOpenInBrowser = { openTrackerInBrowser(context, it) },
|
||||
onRemoved = {
|
||||
navigator.push(
|
||||
TrackAnimeServiceRemoveScreen(
|
||||
TrackerAnimeRemoveScreen(
|
||||
animeId = animeId,
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -212,12 +212,12 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
}
|
||||
|
||||
fun registerEnhancedTracking(item: AnimeTrackItem) {
|
||||
item.service as EnhancedAnimeTrackService
|
||||
item.tracker as EnhancedAnimeTracker
|
||||
coroutineScope.launchNonCancellable {
|
||||
val anime = Injekt.get<GetAnime>().await(animeId) ?: return@launchNonCancellable
|
||||
try {
|
||||
val matchResult = item.service.match(anime) ?: throw Exception()
|
||||
item.service.animeService.register(matchResult, animeId)
|
||||
val matchResult = item.tracker.match(anime) ?: throw Exception()
|
||||
item.tracker.animeService.register(matchResult, animeId)
|
||||
} catch (e: Exception) {
|
||||
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
|
||||
}
|
||||
|
@ -247,15 +247,15 @@ data class AnimeTrackInfoDialogHomeScreen(
|
|||
}
|
||||
|
||||
private fun List<AnimeTrack>.mapToTrackItem(): List<AnimeTrackItem> {
|
||||
val loggedServices = Injekt.get<TrackManager>().services.filter {
|
||||
it.isLoggedIn && it is AnimeTrackService
|
||||
val loggedInTrackers = Injekt.get<TrackerManager>().trackers.filter {
|
||||
it.isLoggedIn && it is AnimeTracker
|
||||
}
|
||||
val source = Injekt.get<AnimeSourceManager>().getOrStub(sourceId)
|
||||
return loggedServices
|
||||
return loggedInTrackers
|
||||
// Map to TrackItem
|
||||
.map { service -> AnimeTrackItem(find { it.syncId.toLong() == service.id }, service) }
|
||||
// Show only if the service supports this anime's source
|
||||
.filter { (it.service as? EnhancedAnimeTrackService)?.accept(source) ?: true }
|
||||
.filter { (it.tracker as? EnhancedAnimeTracker)?.accept(source) ?: true }
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
@ -276,7 +276,7 @@ private data class TrackStatusSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val state by sm.state.collectAsState()
|
||||
|
@ -294,11 +294,11 @@ private data class TrackStatusSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbAnimeTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State(track.status.toInt())) {
|
||||
|
||||
fun getSelections(): Map<Int, Int?> {
|
||||
return service.animeService.getStatusListAnime().associateWith { service.getStatus(it) }
|
||||
return tracker.animeService.getStatusListAnime().associateWith { tracker.getStatus(it) }
|
||||
}
|
||||
|
||||
fun setSelection(selection: Int) {
|
||||
|
@ -307,7 +307,7 @@ private data class TrackStatusSelectorScreen(
|
|||
|
||||
fun setStatus() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
service.animeService.setRemoteAnimeStatus(track.toDbTrack(), state.value.selection)
|
||||
tracker.animeService.setRemoteAnimeStatus(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ private data class TrackEpisodeSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val state by sm.state.collectAsState()
|
||||
|
@ -349,7 +349,7 @@ private data class TrackEpisodeSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbAnimeTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State(track.lastEpisodeSeen.toInt())) {
|
||||
|
||||
fun getRange(): Iterable<Int> {
|
||||
|
@ -367,7 +367,7 @@ private data class TrackEpisodeSelectorScreen(
|
|||
|
||||
fun setEpisode() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
service.animeService.setRemoteLastEpisodeSeen(
|
||||
tracker.animeService.setRemoteLastEpisodeSeen(
|
||||
track.toDbTrack(),
|
||||
state.value.selection,
|
||||
)
|
||||
|
@ -392,7 +392,7 @@ private data class TrackScoreSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val state by sm.state.collectAsState()
|
||||
|
@ -411,11 +411,11 @@ private data class TrackScoreSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbAnimeTrack,
|
||||
private val service: TrackService,
|
||||
) : StateScreenModel<Model.State>(State(service.animeService.displayScore(track.toDbTrack()))) {
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State(tracker.animeService.displayScore(track.toDbTrack()))) {
|
||||
|
||||
fun getSelections(): List<String> {
|
||||
return service.animeService.getScoreList()
|
||||
return tracker.animeService.getScoreList()
|
||||
}
|
||||
|
||||
fun setSelection(selection: String) {
|
||||
|
@ -424,7 +424,7 @@ private data class TrackScoreSelectorScreen(
|
|||
|
||||
fun setScore() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
service.animeService.setRemoteScore(track.toDbTrack(), state.value.selection)
|
||||
tracker.animeService.setRemoteScore(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ private data class TrackDateSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
start = start,
|
||||
)
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ private data class TrackDateSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbAnimeTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
private val start: Boolean,
|
||||
) : ScreenModel {
|
||||
|
||||
|
@ -553,15 +553,15 @@ private data class TrackDateSelectorScreen(
|
|||
millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault())
|
||||
coroutineScope.launchNonCancellable {
|
||||
if (start) {
|
||||
service.animeService.setRemoteStartDate(track.toDbTrack(), localMillis)
|
||||
tracker.animeService.setRemoteStartDate(track.toDbTrack(), localMillis)
|
||||
} else {
|
||||
service.animeService.setRemoteFinishDate(track.toDbTrack(), localMillis)
|
||||
tracker.animeService.setRemoteFinishDate(track.toDbTrack(), localMillis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun confirmRemoveDate(navigator: Navigator) {
|
||||
navigator.push(TrackDateRemoverScreen(track, service.id, start))
|
||||
navigator.push(TrackDateRemoverScreen(track, tracker.id, start))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ private data class TrackDateRemoverScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
start = start,
|
||||
)
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ private data class TrackDateRemoverScreen(
|
|||
)
|
||||
},
|
||||
text = {
|
||||
val serviceName = sm.getServiceName()
|
||||
val serviceName = sm.getName()
|
||||
Text(
|
||||
text = if (start) {
|
||||
stringResource(R.string.track_remove_start_date_conf_text, serviceName)
|
||||
|
@ -636,18 +636,18 @@ private data class TrackDateRemoverScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbAnimeTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
private val start: Boolean,
|
||||
) : ScreenModel {
|
||||
|
||||
fun getServiceName() = service.name
|
||||
fun getName() = tracker.name
|
||||
|
||||
fun removeDate() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
if (start) {
|
||||
service.animeService.setRemoteStartDate(track.toDbTrack(), 0)
|
||||
tracker.animeService.setRemoteStartDate(track.toDbTrack(), 0)
|
||||
} else {
|
||||
service.animeService.setRemoteFinishDate(track.toDbTrack(), 0)
|
||||
tracker.animeService.setRemoteFinishDate(track.toDbTrack(), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -669,14 +669,14 @@ data class TrackServiceSearchScreen(
|
|||
animeId = animeId,
|
||||
currentUrl = currentUrl,
|
||||
initialQuery = initialQuery,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
|
||||
val state by sm.state.collectAsState()
|
||||
|
||||
var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) }
|
||||
AnimeTrackServiceSearch(
|
||||
AnimeTrackerSearch(
|
||||
query = textFieldValue,
|
||||
onQueryChange = { textFieldValue = it },
|
||||
onDispatchQuery = { sm.trackingSearch(textFieldValue.text) },
|
||||
|
@ -695,7 +695,7 @@ data class TrackServiceSearchScreen(
|
|||
private val animeId: Long,
|
||||
private val currentUrl: String? = null,
|
||||
initialQuery: String,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State()) {
|
||||
|
||||
init {
|
||||
|
@ -712,7 +712,7 @@ data class TrackServiceSearchScreen(
|
|||
|
||||
val result = withIOContext {
|
||||
try {
|
||||
val results = service.animeService.searchAnime(query)
|
||||
val results = tracker.animeService.searchAnime(query)
|
||||
Result.success(results)
|
||||
} catch (e: Throwable) {
|
||||
Result.failure(e)
|
||||
|
@ -728,7 +728,7 @@ data class TrackServiceSearchScreen(
|
|||
}
|
||||
|
||||
fun registerTracking(item: AnimeTrackSearch) {
|
||||
coroutineScope.launchNonCancellable { service.animeService.register(item, animeId) }
|
||||
coroutineScope.launchNonCancellable { tracker.animeService.register(item, animeId) }
|
||||
}
|
||||
|
||||
fun updateSelection(selected: AnimeTrackSearch) {
|
||||
|
@ -743,7 +743,7 @@ data class TrackServiceSearchScreen(
|
|||
}
|
||||
}
|
||||
|
||||
private data class TrackAnimeServiceRemoveScreen(
|
||||
private data class TrackerAnimeRemoveScreen(
|
||||
private val animeId: Long,
|
||||
private val track: AnimeTrack,
|
||||
private val serviceId: Long,
|
||||
|
@ -756,10 +756,10 @@ private data class TrackAnimeServiceRemoveScreen(
|
|||
Model(
|
||||
animeId = animeId,
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val serviceName = sm.getServiceName()
|
||||
val serviceName = sm.getName()
|
||||
var removeRemoteTrack by remember { mutableStateOf(false) }
|
||||
AlertDialogContent(
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
||||
|
@ -780,7 +780,7 @@ private data class TrackAnimeServiceRemoveScreen(
|
|||
Text(
|
||||
text = stringResource(R.string.track_delete_text, serviceName),
|
||||
)
|
||||
if (sm.isServiceDeletable()) {
|
||||
if (sm.isDeletable()) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Checkbox(
|
||||
checked = removeRemoteTrack,
|
||||
|
@ -828,17 +828,17 @@ private data class TrackAnimeServiceRemoveScreen(
|
|||
private class Model(
|
||||
private val animeId: Long,
|
||||
private val track: AnimeTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
private val deleteTrack: DeleteAnimeTrack = Injekt.get(),
|
||||
) : ScreenModel {
|
||||
|
||||
fun getServiceName() = service.name
|
||||
fun getName() = tracker.name
|
||||
|
||||
fun isServiceDeletable() = service is DeletableAnimeTrackService
|
||||
fun isDeletable() = tracker is DeletableAnimeTracker
|
||||
|
||||
fun deleteAnimeFromService() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
(service as DeletableAnimeTrackService).delete(track.toDbTrack())
|
||||
(tracker as DeletableAnimeTracker).delete(track.toDbTrack())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package eu.kanade.tachiyomi.ui.entries.anime.track
|
||||
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import tachiyomi.domain.track.anime.model.AnimeTrack
|
||||
|
||||
data class AnimeTrackItem(val track: AnimeTrack?, val service: TrackService)
|
||||
data class AnimeTrackItem(val track: AnimeTrack?, val tracker: Tracker)
|
||||
|
|
|
@ -24,9 +24,9 @@ import eu.kanade.tachiyomi.R
|
|||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadCache
|
||||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.manga.model.MangaDownload
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.network.HttpException
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import eu.kanade.tachiyomi.ui.entries.manga.track.MangaTrackItem
|
||||
|
@ -86,7 +86,7 @@ class MangaScreenModel(
|
|||
readerPreferences: ReaderPreferences = Injekt.get(),
|
||||
uiPreferences: UiPreferences = Injekt.get(),
|
||||
private val trackPreferences: TrackPreferences = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
private val downloadManager: MangaDownloadManager = Injekt.get(),
|
||||
private val downloadCache: MangaDownloadCache = Injekt.get(),
|
||||
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
||||
|
@ -107,7 +107,7 @@ class MangaScreenModel(
|
|||
private val successState: State.Success?
|
||||
get() = state.value as? State.Success
|
||||
|
||||
private val loggedServices by lazy { trackManager.services.filter { it.isLoggedIn && it is MangaTrackService } }
|
||||
private val loggedInTrackers by lazy { trackerManager.trackers.filter { it.isLoggedIn && it is MangaTracker } }
|
||||
|
||||
val manga: Manga?
|
||||
get() = successState?.manga
|
||||
|
@ -331,14 +331,14 @@ class MangaScreenModel(
|
|||
// Finally match with enhanced tracking when available
|
||||
val source = state.source
|
||||
state.trackItems
|
||||
.map { it.service }
|
||||
.filterIsInstance<EnhancedMangaTrackService>()
|
||||
.map { it.tracker }
|
||||
.filterIsInstance<EnhancedMangaTracker>()
|
||||
.filter { it.accept(source) }
|
||||
.forEach { service ->
|
||||
launchIO {
|
||||
try {
|
||||
service.match(manga)?.let { track ->
|
||||
(service as MangaTrackService).register(track, mangaId)
|
||||
(service as MangaTracker).register(track, mangaId)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.WARN, e) {
|
||||
|
@ -979,7 +979,7 @@ class MangaScreenModel(
|
|||
getTracks.subscribe(manga.id)
|
||||
.catch { logcat(LogPriority.ERROR, it) }
|
||||
.map { tracks ->
|
||||
loggedServices
|
||||
loggedInTrackers
|
||||
// Map to TrackItem
|
||||
.map { service ->
|
||||
MangaTrackItem(
|
||||
|
@ -988,7 +988,7 @@ class MangaScreenModel(
|
|||
)
|
||||
}
|
||||
// Show only if the service supports this manga's source
|
||||
.filter { (it.service as? EnhancedMangaTrackService)?.accept(source!!) ?: true }
|
||||
.filter { (it.tracker as? EnhancedMangaTracker)?.accept(source!!) ?: true }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { trackItems ->
|
||||
|
|
|
@ -47,14 +47,14 @@ import eu.kanade.presentation.track.TrackItemSelector
|
|||
import eu.kanade.presentation.track.TrackScoreSelector
|
||||
import eu.kanade.presentation.track.TrackStatusSelector
|
||||
import eu.kanade.presentation.track.manga.MangaTrackInfoDialogHome
|
||||
import eu.kanade.presentation.track.manga.MangaTrackServiceSearch
|
||||
import eu.kanade.presentation.track.manga.MangaTrackerSearch
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.DeletableMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.model.MangaTrackSearch
|
||||
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
|
@ -110,7 +110,7 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackStatusSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -118,7 +118,7 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackChapterSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -126,7 +126,7 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackScoreSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -134,7 +134,7 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackDateSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
start = true,
|
||||
),
|
||||
)
|
||||
|
@ -143,13 +143,13 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
navigator.push(
|
||||
TrackDateSelectorScreen(
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
start = false,
|
||||
),
|
||||
)
|
||||
},
|
||||
onNewSearch = {
|
||||
if (it.service is EnhancedMangaTrackService) {
|
||||
if (it.tracker is EnhancedMangaTracker) {
|
||||
sm.registerEnhancedTracking(it)
|
||||
} else {
|
||||
navigator.push(
|
||||
|
@ -157,7 +157,7 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
mangaId = mangaId,
|
||||
initialQuery = it.track?.title ?: mangaTitle,
|
||||
currentUrl = it.track?.remoteUrl,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -165,10 +165,10 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
onOpenInBrowser = { openTrackerInBrowser(context, it) },
|
||||
onRemoved = {
|
||||
navigator.push(
|
||||
TrackMangaServiceRemoveScreen(
|
||||
TrackerMangaRemoveScreen(
|
||||
mangaId = mangaId,
|
||||
track = it.track!!,
|
||||
serviceId = it.service.id,
|
||||
serviceId = it.tracker.id,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -212,12 +212,12 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
}
|
||||
|
||||
fun registerEnhancedTracking(item: MangaTrackItem) {
|
||||
item.service as EnhancedMangaTrackService
|
||||
item.tracker as EnhancedMangaTracker
|
||||
coroutineScope.launchNonCancellable {
|
||||
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
|
||||
try {
|
||||
val matchResult = item.service.match(manga) ?: throw Exception()
|
||||
item.service.mangaService.register(matchResult, mangaId)
|
||||
val matchResult = item.tracker.match(manga) ?: throw Exception()
|
||||
item.tracker.mangaService.register(matchResult, mangaId)
|
||||
} catch (e: Exception) {
|
||||
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
|
||||
}
|
||||
|
@ -247,15 +247,15 @@ data class MangaTrackInfoDialogHomeScreen(
|
|||
}
|
||||
|
||||
private fun List<MangaTrack>.mapToTrackItem(): List<MangaTrackItem> {
|
||||
val loggedServices = Injekt.get<TrackManager>().services.filter {
|
||||
it.isLoggedIn && it is MangaTrackService
|
||||
val loggedInTrackers = Injekt.get<TrackerManager>().trackers.filter {
|
||||
it.isLoggedIn && it is MangaTracker
|
||||
}
|
||||
val source = Injekt.get<MangaSourceManager>().getOrStub(sourceId)
|
||||
return loggedServices
|
||||
return loggedInTrackers
|
||||
// Map to TrackItem
|
||||
.map { service -> MangaTrackItem(find { it.syncId == service.id }, service) }
|
||||
// Show only if the service supports this manga's source
|
||||
.filter { (it.service as? EnhancedMangaTrackService)?.accept(source) ?: true }
|
||||
.filter { (it.tracker as? EnhancedMangaTracker)?.accept(source) ?: true }
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
@ -276,7 +276,7 @@ private data class TrackStatusSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val state by sm.state.collectAsState()
|
||||
|
@ -294,11 +294,11 @@ private data class TrackStatusSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbMangaTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State(track.status.toInt())) {
|
||||
|
||||
fun getSelections(): Map<Int, Int?> {
|
||||
return service.mangaService.getStatusListManga().associateWith { service.getStatus(it) }
|
||||
return tracker.mangaService.getStatusListManga().associateWith { tracker.getStatus(it) }
|
||||
}
|
||||
|
||||
fun setSelection(selection: Int) {
|
||||
|
@ -307,7 +307,7 @@ private data class TrackStatusSelectorScreen(
|
|||
|
||||
fun setStatus() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
service.mangaService.setRemoteMangaStatus(track.toDbTrack(), state.value.selection)
|
||||
tracker.mangaService.setRemoteMangaStatus(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ private data class TrackChapterSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val state by sm.state.collectAsState()
|
||||
|
@ -349,7 +349,7 @@ private data class TrackChapterSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbMangaTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State(track.lastChapterRead.toInt())) {
|
||||
|
||||
fun getRange(): Iterable<Int> {
|
||||
|
@ -367,7 +367,7 @@ private data class TrackChapterSelectorScreen(
|
|||
|
||||
fun setChapter() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
service.mangaService.setRemoteLastChapterRead(
|
||||
tracker.mangaService.setRemoteLastChapterRead(
|
||||
track.toDbTrack(),
|
||||
state.value.selection,
|
||||
)
|
||||
|
@ -392,7 +392,7 @@ private data class TrackScoreSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val state by sm.state.collectAsState()
|
||||
|
@ -411,11 +411,11 @@ private data class TrackScoreSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbMangaTrack,
|
||||
private val service: TrackService,
|
||||
) : StateScreenModel<Model.State>(State(service.mangaService.displayScore(track.toDbTrack()))) {
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State(tracker.mangaService.displayScore(track.toDbTrack()))) {
|
||||
|
||||
fun getSelections(): List<String> {
|
||||
return service.mangaService.getScoreList()
|
||||
return tracker.mangaService.getScoreList()
|
||||
}
|
||||
|
||||
fun setSelection(selection: String) {
|
||||
|
@ -424,7 +424,7 @@ private data class TrackScoreSelectorScreen(
|
|||
|
||||
fun setScore() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
service.mangaService.setRemoteScore(track.toDbTrack(), state.value.selection)
|
||||
tracker.mangaService.setRemoteScore(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ private data class TrackDateSelectorScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
start = start,
|
||||
)
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ private data class TrackDateSelectorScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbMangaTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
private val start: Boolean,
|
||||
) : ScreenModel {
|
||||
|
||||
|
@ -553,15 +553,15 @@ private data class TrackDateSelectorScreen(
|
|||
millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault())
|
||||
coroutineScope.launchNonCancellable {
|
||||
if (start) {
|
||||
service.mangaService.setRemoteStartDate(track.toDbTrack(), localMillis)
|
||||
tracker.mangaService.setRemoteStartDate(track.toDbTrack(), localMillis)
|
||||
} else {
|
||||
service.mangaService.setRemoteFinishDate(track.toDbTrack(), localMillis)
|
||||
tracker.mangaService.setRemoteFinishDate(track.toDbTrack(), localMillis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun confirmRemoveDate(navigator: Navigator) {
|
||||
navigator.push(TrackDateRemoverScreen(track, service.id, start))
|
||||
navigator.push(TrackDateRemoverScreen(track, tracker.id, start))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ private data class TrackDateRemoverScreen(
|
|||
val sm = rememberScreenModel {
|
||||
Model(
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
start = start,
|
||||
)
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ private data class TrackDateRemoverScreen(
|
|||
)
|
||||
},
|
||||
text = {
|
||||
val serviceName = sm.getServiceName()
|
||||
val serviceName = sm.getName()
|
||||
Text(
|
||||
text = if (start) {
|
||||
stringResource(R.string.track_remove_start_date_conf_text, serviceName)
|
||||
|
@ -636,18 +636,18 @@ private data class TrackDateRemoverScreen(
|
|||
|
||||
private class Model(
|
||||
private val track: DbMangaTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
private val start: Boolean,
|
||||
) : ScreenModel {
|
||||
|
||||
fun getServiceName() = service.name
|
||||
fun getName() = tracker.name
|
||||
|
||||
fun removeDate() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
if (start) {
|
||||
service.mangaService.setRemoteStartDate(track.toDbTrack(), 0)
|
||||
tracker.mangaService.setRemoteStartDate(track.toDbTrack(), 0)
|
||||
} else {
|
||||
service.mangaService.setRemoteFinishDate(track.toDbTrack(), 0)
|
||||
tracker.mangaService.setRemoteFinishDate(track.toDbTrack(), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -669,14 +669,14 @@ data class TrackServiceSearchScreen(
|
|||
mangaId = mangaId,
|
||||
currentUrl = currentUrl,
|
||||
initialQuery = initialQuery,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
|
||||
val state by sm.state.collectAsState()
|
||||
|
||||
var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) }
|
||||
MangaTrackServiceSearch(
|
||||
MangaTrackerSearch(
|
||||
query = textFieldValue,
|
||||
onQueryChange = { textFieldValue = it },
|
||||
onDispatchQuery = { sm.trackingSearch(textFieldValue.text) },
|
||||
|
@ -695,7 +695,7 @@ data class TrackServiceSearchScreen(
|
|||
private val mangaId: Long,
|
||||
private val currentUrl: String? = null,
|
||||
initialQuery: String,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
) : StateScreenModel<Model.State>(State()) {
|
||||
|
||||
init {
|
||||
|
@ -712,7 +712,7 @@ data class TrackServiceSearchScreen(
|
|||
|
||||
val result = withIOContext {
|
||||
try {
|
||||
val results = service.mangaService.searchManga(query)
|
||||
val results = tracker.mangaService.searchManga(query)
|
||||
Result.success(results)
|
||||
} catch (e: Throwable) {
|
||||
Result.failure(e)
|
||||
|
@ -728,7 +728,7 @@ data class TrackServiceSearchScreen(
|
|||
}
|
||||
|
||||
fun registerTracking(item: MangaTrackSearch) {
|
||||
coroutineScope.launchNonCancellable { service.mangaService.register(item, mangaId) }
|
||||
coroutineScope.launchNonCancellable { tracker.mangaService.register(item, mangaId) }
|
||||
}
|
||||
|
||||
fun updateSelection(selected: MangaTrackSearch) {
|
||||
|
@ -743,7 +743,7 @@ data class TrackServiceSearchScreen(
|
|||
}
|
||||
}
|
||||
|
||||
private data class TrackMangaServiceRemoveScreen(
|
||||
private data class TrackerMangaRemoveScreen(
|
||||
private val mangaId: Long,
|
||||
private val track: MangaTrack,
|
||||
private val serviceId: Long,
|
||||
|
@ -756,10 +756,10 @@ private data class TrackMangaServiceRemoveScreen(
|
|||
Model(
|
||||
mangaId = mangaId,
|
||||
track = track,
|
||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||
tracker = Injekt.get<TrackerManager>().get(serviceId)!!,
|
||||
)
|
||||
}
|
||||
val serviceName = sm.getServiceName()
|
||||
val serviceName = sm.getName()
|
||||
var removeRemoteTrack by remember { mutableStateOf(false) }
|
||||
AlertDialogContent(
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
||||
|
@ -780,7 +780,7 @@ private data class TrackMangaServiceRemoveScreen(
|
|||
Text(
|
||||
text = stringResource(R.string.track_delete_text, serviceName),
|
||||
)
|
||||
if (sm.isServiceDeletable()) {
|
||||
if (sm.isDeletable()) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Checkbox(
|
||||
checked = removeRemoteTrack,
|
||||
|
@ -828,17 +828,17 @@ private data class TrackMangaServiceRemoveScreen(
|
|||
private class Model(
|
||||
private val mangaId: Long,
|
||||
private val track: MangaTrack,
|
||||
private val service: TrackService,
|
||||
private val tracker: Tracker,
|
||||
private val deleteTrack: DeleteMangaTrack = Injekt.get(),
|
||||
) : ScreenModel {
|
||||
|
||||
fun getServiceName() = service.name
|
||||
fun getName() = tracker.name
|
||||
|
||||
fun isServiceDeletable() = service is DeletableMangaTrackService
|
||||
fun isDeletable() = tracker is DeletableMangaTracker
|
||||
|
||||
fun deleteMangaFromService() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
(service as DeletableMangaTrackService).delete(track.toDbTrack())
|
||||
(tracker as DeletableMangaTracker).delete(track.toDbTrack())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package eu.kanade.tachiyomi.ui.entries.manga.track
|
||||
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import tachiyomi.domain.track.manga.model.MangaTrack
|
||||
|
||||
data class MangaTrackItem(val track: MangaTrack?, val service: TrackService)
|
||||
data class MangaTrackItem(val track: MangaTrack?, val tracker: Tracker)
|
||||
|
|
|
@ -25,8 +25,8 @@ import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
|||
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
||||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadCache
|
||||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.util.episode.getNextUnseen
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -89,7 +89,7 @@ class AnimeLibraryScreenModel(
|
|||
private val sourceManager: AnimeSourceManager = Injekt.get(),
|
||||
private val downloadManager: AnimeDownloadManager = Injekt.get(),
|
||||
private val downloadCache: AnimeDownloadCache = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
) : StateScreenModel<AnimeLibraryScreenModel.State>(State()) {
|
||||
|
||||
var activeCategoryIndex: Int by libraryPreferences.lastUsedAnimeCategory().asState(
|
||||
|
@ -104,9 +104,9 @@ class AnimeLibraryScreenModel(
|
|||
getTracksPerAnime.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) {
|
||||
|
@ -172,7 +172,7 @@ class AnimeLibraryScreenModel(
|
|||
*/
|
||||
private suspend fun AnimeLibraryMap.applyFilters(
|
||||
trackMap: Map<Long, List<Long>>,
|
||||
loggedInTrackServices: Map<Long, TriState>,
|
||||
loggedInTrackers: Map<Long, TriState>,
|
||||
): AnimeLibraryMap {
|
||||
val prefs = getAnimelibItemPreferencesFlow().first()
|
||||
val downloadedOnly = prefs.globalFilterDownloaded
|
||||
|
@ -183,10 +183,10 @@ class AnimeLibraryScreenModel(
|
|||
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: (AnimeLibraryItem) -> Boolean = {
|
||||
|
@ -380,14 +380,14 @@ class AnimeLibraryScreenModel(
|
|||
* @return map of track id with the filter value
|
||||
*/
|
||||
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
||||
val loggedServices = trackManager.services.filter { it.isLoggedIn && it is AnimeTrackService }
|
||||
return if (loggedServices.isNotEmpty()) {
|
||||
val prefFlows = loggedServices
|
||||
val loggedInTrackers = trackerManager.trackers.filter { it.isLoggedIn && it is AnimeTracker }
|
||||
return if (loggedInTrackers.isNotEmpty()) {
|
||||
val prefFlows = loggedInTrackers
|
||||
.map { libraryPreferences.filterTrackedAnime(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 {
|
||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.library.anime
|
|||
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 AnimeLibrarySettingsScreenModel(
|
|||
val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
private val setAnimeDisplayMode: SetAnimeDisplayMode = Injekt.get(),
|
||||
private val setSortModeForCategory: SetSortModeForAnimeCategory = 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<TriState>) {
|
||||
preference(libraryPreferences).getAndSet {
|
||||
|
|
|
@ -23,8 +23,8 @@ import eu.kanade.presentation.library.LibraryToolbarTitle
|
|||
import eu.kanade.tachiyomi.data.cache.MangaCoverCache
|
||||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadCache
|
||||
import eu.kanade.tachiyomi.data.download.manga.MangaDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
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
|
||||
|
@ -89,7 +89,7 @@ class MangaLibraryScreenModel(
|
|||
private val sourceManager: MangaSourceManager = Injekt.get(),
|
||||
private val downloadManager: MangaDownloadManager = Injekt.get(),
|
||||
private val downloadCache: MangaDownloadCache = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
) : StateScreenModel<MangaLibraryScreenModel.State>(State()) {
|
||||
|
||||
var activeCategoryIndex: Int by libraryPreferences.lastUsedMangaCategory().asState(
|
||||
|
@ -104,9 +104,9 @@ class MangaLibraryScreenModel(
|
|||
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) {
|
||||
|
@ -172,7 +172,7 @@ class MangaLibraryScreenModel(
|
|||
*/
|
||||
private suspend fun MangaLibraryMap.applyFilters(
|
||||
trackMap: Map<Long, List<Long>>,
|
||||
loggedInTrackServices: Map<Long, TriState>,
|
||||
loggedInTrackers: Map<Long, TriState>,
|
||||
): MangaLibraryMap {
|
||||
val prefs = getLibraryItemPreferencesFlow().first()
|
||||
val downloadedOnly = prefs.globalFilterDownloaded
|
||||
|
@ -183,10 +183,10 @@ class MangaLibraryScreenModel(
|
|||
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: (MangaLibraryItem) -> Boolean = {
|
||||
|
@ -372,14 +372,14 @@ class MangaLibraryScreenModel(
|
|||
* @return map of track id with the filter value
|
||||
*/
|
||||
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
||||
val loggedServices = trackManager.services.filter { it.isLoggedIn && it is MangaTrackService }
|
||||
return if (loggedServices.isNotEmpty()) {
|
||||
val prefFlows = loggedServices
|
||||
val loggedInTrackers = trackerManager.trackers.filter { it.isLoggedIn && it is MangaTracker }
|
||||
return if (loggedInTrackers.isNotEmpty()) {
|
||||
val prefFlows = loggedInTrackers
|
||||
.map { libraryPreferences.filterTrackedManga(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 {
|
||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.library.manga
|
|||
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 MangaLibrarySettingsScreenModel(
|
|||
val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
private val setMangaDisplayMode: SetMangaDisplayMode = Injekt.get(),
|
||||
private val setSortModeForCategory: SetSortModeForMangaCategory = 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<TriState>) {
|
||||
preference(libraryPreferences).getAndSet {
|
||||
|
|
|
@ -157,7 +157,7 @@ class MainActivity : BaseActivity() {
|
|||
readerPreferences = Injekt.get(),
|
||||
playerPreferences = Injekt.get(),
|
||||
backupPreferences = Injekt.get(),
|
||||
trackManager = Injekt.get(),
|
||||
trackerManager = Injekt.get(),
|
||||
)
|
||||
} else {
|
||||
false
|
||||
|
|
|
@ -20,8 +20,8 @@ import eu.kanade.tachiyomi.animesource.AnimeSource
|
|||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.ui.player.loader.EpisodeLoader
|
||||
import eu.kanade.tachiyomi.ui.player.settings.PlayerPreferences
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
|
@ -492,15 +492,15 @@ class ExternalIntents {
|
|||
private suspend fun updateTrackEpisodeSeen(episodeNumber: Double, anime: Anime) {
|
||||
if (!trackPreferences.autoUpdateTrack().get()) return
|
||||
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val trackerManager = Injekt.get<TrackerManager>()
|
||||
val context = Injekt.get<Application>()
|
||||
|
||||
withIOContext {
|
||||
getTracks.await(anime.id)
|
||||
.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn &&
|
||||
service is AnimeTrackService && episodeNumber > track.lastEpisodeSeen
|
||||
val tracker = trackerManager.get(track.syncId)
|
||||
if (tracker != null && tracker.isLoggedIn &&
|
||||
tracker is AnimeTracker && episodeNumber > track.lastEpisodeSeen
|
||||
) {
|
||||
val updatedTrack = track.copy(lastEpisodeSeen = episodeNumber)
|
||||
|
||||
|
@ -509,7 +509,7 @@ class ExternalIntents {
|
|||
async {
|
||||
runCatching {
|
||||
if (context.isOnline()) {
|
||||
service.animeService.update(updatedTrack.toDbTrack(), true)
|
||||
tracker.animeService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} else {
|
||||
delayedTrackingStore.addAnimeItem(updatedTrack)
|
||||
|
|
|
@ -24,7 +24,7 @@ import eu.kanade.tachiyomi.data.download.anime.model.AnimeDownload
|
|||
import eu.kanade.tachiyomi.data.saver.Image
|
||||
import eu.kanade.tachiyomi.data.saver.ImageSaver
|
||||
import eu.kanade.tachiyomi.data.saver.Location
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
||||
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
|
||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||
|
@ -658,7 +658,7 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
*/
|
||||
suspend fun aniSkipResponse(playerDuration: Int?): List<Stamp>? {
|
||||
val animeId = currentAnime?.id ?: return null
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val trackerManager = Injekt.get<TrackerManager>()
|
||||
var malId: Long?
|
||||
val episodeNumber = currentEpisode?.episode_number?.toInt() ?: return null
|
||||
if (getTracks.await(animeId).isEmpty()) {
|
||||
|
@ -667,8 +667,8 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
getTracks.await(animeId).map { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
malId = when (service) {
|
||||
val tracker = trackerManager.get(track.syncId)
|
||||
malId = when (tracker) {
|
||||
is MyAnimeList -> track.remoteId
|
||||
is Anilist -> AniSkipApi().getMalIdFromAL(track.remoteId)
|
||||
else -> null
|
||||
|
|
|
@ -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?)
|
||||
|
||||
|
|
|
@ -21,11 +21,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()
|
||||
}
|
||||
}
|
||||
|
@ -34,11 +34,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()
|
||||
}
|
||||
}
|
||||
|
@ -47,11 +47,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()
|
||||
}
|
||||
}
|
||||
|
@ -60,11 +60,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()
|
||||
}
|
||||
}
|
||||
|
@ -73,11 +73,11 @@ class TrackLoginActivity : BaseOAuthLoginActivity() {
|
|||
val code = data?.getQueryParameter("code")
|
||||
if (code != null) {
|
||||
lifecycleScope.launchIO {
|
||||
trackManager.simkl.login(code)
|
||||
trackerManager.simkl.login(code)
|
||||
returnToSettings()
|
||||
}
|
||||
} else {
|
||||
trackManager.simkl.logout()
|
||||
trackerManager.simkl.logout()
|
||||
returnToSettings()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ import eu.kanade.presentation.more.stats.StatsScreenState
|
|||
import eu.kanade.presentation.more.stats.data.StatsData
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.AnimeTracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import kotlinx.coroutines.flow.update
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
import tachiyomi.domain.entries.anime.interactor.GetLibraryAnime
|
||||
|
@ -34,10 +34,10 @@ class AnimeStatsScreenModel(
|
|||
private val getEpisodeByAnimeId: GetEpisodeByAnimeId = Injekt.get(),
|
||||
private val getTracks: GetAnimeTracks = Injekt.get(),
|
||||
private val preferences: LibraryPreferences = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||
|
||||
private val loggedServices by lazy { trackManager.services.fastFilter { it.isLoggedIn && it is AnimeTrackService } }
|
||||
private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn && it is AnimeTracker } }
|
||||
|
||||
init {
|
||||
coroutineScope.launchIO {
|
||||
|
@ -73,7 +73,7 @@ class AnimeStatsScreenModel(
|
|||
val trackersStatData = StatsData.Trackers(
|
||||
trackedTitleCount = animeTrackMap.count { it.value.isNotEmpty() },
|
||||
meanScore = meanScore,
|
||||
trackerCount = loggedServices.size,
|
||||
trackerCount = loggedInTrackers.size,
|
||||
)
|
||||
|
||||
mutableState.update {
|
||||
|
@ -116,10 +116,10 @@ class AnimeStatsScreenModel(
|
|||
}
|
||||
|
||||
private suspend fun getAnimeTrackMap(libraryAnime: List<LibraryAnime>): Map<Long, List<AnimeTrack>> {
|
||||
val loggedServicesIds = loggedServices.map { it.id }.toHashSet()
|
||||
val loggedInTrackerIds = loggedInTrackers.map { it.id }.toHashSet()
|
||||
return libraryAnime.associate { anime ->
|
||||
val tracks = getTracks.await(anime.id)
|
||||
.fastFilter { it.syncId in loggedServicesIds }
|
||||
.fastFilter { it.syncId in loggedInTrackerIds }
|
||||
|
||||
anime.id to tracks
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ class AnimeStatsScreenModel(
|
|||
}
|
||||
|
||||
private fun get10PointScore(track: AnimeTrack): Double {
|
||||
val service = trackManager.getService(track.syncId)!!
|
||||
return service.animeService.get10PointScore(track)
|
||||
val tracker = trackerManager.get(track.syncId)!!
|
||||
return tracker.animeService.get10PointScore(track)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ 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.manga.MangaDownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.MangaTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.MangaTracker
|
||||
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
|
||||
|
@ -34,10 +34,10 @@ class MangaStatsScreenModel(
|
|||
private val getTotalReadDuration: GetTotalReadDuration = Injekt.get(),
|
||||
private val getTracks: GetMangaTracks = Injekt.get(),
|
||||
private val preferences: LibraryPreferences = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||
|
||||
private val loggedServices by lazy { trackManager.services.fastFilter { it.isLoggedIn && it is MangaTrackService } }
|
||||
private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn && it is MangaTracker } }
|
||||
|
||||
init {
|
||||
coroutineScope.launchIO {
|
||||
|
@ -73,7 +73,7 @@ class MangaStatsScreenModel(
|
|||
val trackersStatData = StatsData.Trackers(
|
||||
trackedTitleCount = mangaTrackMap.count { it.value.isNotEmpty() },
|
||||
meanScore = meanScore,
|
||||
trackerCount = loggedServices.size,
|
||||
trackerCount = loggedInTrackers.size,
|
||||
)
|
||||
|
||||
mutableState.update {
|
||||
|
@ -116,10 +116,10 @@ class MangaStatsScreenModel(
|
|||
}
|
||||
|
||||
private suspend fun getMangaTrackMap(libraryManga: List<LibraryManga>): Map<Long, List<MangaTrack>> {
|
||||
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
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ class MangaStatsScreenModel(
|
|||
}
|
||||
|
||||
private fun get10PointScore(track: MangaTrack): Double {
|
||||
val service = trackManager.getService(track.syncId)!!
|
||||
return service.mangaService.get10PointScore(track)
|
||||
val tracker = trackerManager.get(track.syncId)!!
|
||||
return tracker.mangaService.get10PointScore(track)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@ class AniChartApi {
|
|||
|
||||
return withIOContext {
|
||||
val matchingTrackItem = trackItems.firstOrNull {
|
||||
(it.service is Anilist && it.track != null) ||
|
||||
(it.service is MyAnimeList && it.track != null) ||
|
||||
(it.service is Simkl && it.track != null)
|
||||
(it.tracker is Anilist && it.track != null) ||
|
||||
(it.tracker is MyAnimeList && it.track != null) ||
|
||||
(it.tracker is Simkl && it.track != null)
|
||||
} ?: return@withIOContext Pair(1, 0L)
|
||||
|
||||
matchingTrackItem.let { item ->
|
||||
item.track!!.let {
|
||||
airingEpisodeData = when (item.service) {
|
||||
airingEpisodeData = when (item.tracker) {
|
||||
is Anilist -> getAnilistAiringEpisodeData(it.remoteId)
|
||||
is MyAnimeList -> getAnilistAiringEpisodeData(getAlIdFromMal(it.remoteId))
|
||||
is Simkl -> getSimklAiringEpisodeData(it.remoteId)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[versions]
|
||||
aboutlib_version = "10.9.0"
|
||||
aboutlib_version = "10.9.1"
|
||||
okhttp_version = "5.0.0-alpha.11"
|
||||
shizuku_version = "12.2.0"
|
||||
sqlite = "2.3.1"
|
||||
|
@ -43,8 +43,8 @@ coil-core = { module = "io.coil-kt:coil" }
|
|||
coil-gif = { module = "io.coil-kt:coil-gif" }
|
||||
coil-compose = { module = "io.coil-kt:coil-compose" }
|
||||
|
||||
subsamplingscaleimageview = "com.github.tachiyomiorg:subsampling-scale-image-view:c8e2650"
|
||||
image-decoder = "com.github.tachiyomiorg:image-decoder:16eda64574"
|
||||
subsamplingscaleimageview = "com.github.tachiyomiorg:subsampling-scale-image-view:7e57335"
|
||||
image-decoder = "com.github.tachiyomiorg:image-decoder:fbd6601290"
|
||||
|
||||
natural-comparator = "com.github.gpanther:java-nat-sort:natural-comparator-1.1"
|
||||
|
||||
|
|
|
@ -14,8 +14,14 @@ interface ConfigurableAnimeSource : AnimeSource {
|
|||
*
|
||||
* @since extensions-lib 1.5
|
||||
*/
|
||||
fun getPreferences(): SharedPreferences =
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", Context.MODE_PRIVATE)
|
||||
fun getSourcePreferences(): SharedPreferences =
|
||||
Injekt.get<Application>().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE)
|
||||
|
||||
fun setupPreferenceScreen(screen: PreferenceScreen)
|
||||
}
|
||||
|
||||
private fun ConfigurableAnimeSource.preferenceKey(): String = "source_$id"
|
||||
|
||||
// TODO: use getSourcePreferences once all extensions are on ext-lib 1.5
|
||||
fun ConfigurableAnimeSource.sourcePreferences(): SharedPreferences =
|
||||
Injekt.get<Application>().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE)
|
||||
|
|
|
@ -14,8 +14,14 @@ interface ConfigurableSource : MangaSource {
|
|||
*
|
||||
* @since extensions-lib 1.5
|
||||
*/
|
||||
fun getPreferences(): SharedPreferences =
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", Context.MODE_PRIVATE)
|
||||
fun getSourcePreferences(): SharedPreferences =
|
||||
Injekt.get<Application>().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE)
|
||||
|
||||
fun setupPreferenceScreen(screen: PreferenceScreen)
|
||||
}
|
||||
|
||||
private fun ConfigurableSource.preferenceKey(): String = "source_$id"
|
||||
|
||||
// TODO: use getSourcePreferences once all extensions are on ext-lib 1.5
|
||||
fun ConfigurableSource.sourcePreferences(): SharedPreferences =
|
||||
Injekt.get<Application>().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE)
|
||||
|
|
Loading…
Reference in a new issue