diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 37d72d3e65..8ccc2db652 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -194,7 +194,7 @@ dependencies { implementation(androidx.bundles.workmanager) // RxJava - implementation(libs.bundles.reactivex) + implementation(libs.rxjava) implementation(libs.flowreactivenetwork) // Networking diff --git a/app/proguard-android-optimize.txt b/app/proguard-android-optimize.txt index 9f53403165..7072ff7036 100644 --- a/app/proguard-android-optimize.txt +++ b/app/proguard-android-optimize.txt @@ -14,7 +14,7 @@ } -keepclassmembers class * implements android.os.Parcelable { - public static final ** CREATOR; + public static final ** CREATOR; } -keep class androidx.annotation.Keep diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 4679656733..ddb8f83af8 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -11,8 +11,8 @@ -keep,allowoptimization class kotlin.time.** { public protected *; } -keep,allowoptimization class okhttp3.** { public protected *; } -keep,allowoptimization class okio.** { public protected *; } --keep,allowoptimization class rx.** { public protected *; } -keep,allowoptimization class org.jsoup.** { public protected *; } +-keep,allowoptimization class rx.** { public protected *; } -keep,allowoptimization class app.cash.quickjs.** { public protected *; } -keep,allowoptimization class uy.kohesive.injekt.** { public protected *; } diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index 65e458d19c..bcdb513644 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -16,6 +16,7 @@ import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSourcePin +import eu.kanade.domain.track.interactor.RefreshTracks import eu.kanade.domain.track.interactor.TrackChapter import tachiyomi.data.category.CategoryRepositoryImpl import tachiyomi.data.chapter.ChapterRepositoryImpl @@ -115,6 +116,7 @@ class DomainModule : InjektModule { addSingletonFactory { TrackRepositoryImpl(get()) } addFactory { TrackChapter(get(), get(), get(), get()) } + addFactory { RefreshTracks(get(), get(), get(), get()) } addFactory { DeleteTrack(get()) } addFactory { GetTracksPerManga(get()) } addFactory { GetTracks(get()) } @@ -127,7 +129,7 @@ class DomainModule : InjektModule { addFactory { SetReadStatus(get(), get(), get(), get()) } addFactory { ShouldUpdateDbChapter() } addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) } - addFactory { SyncChaptersWithTrackServiceTwoWay(get(), get()) } + addFactory { SyncChaptersWithTrackServiceTwoWay(get(), get(), get()) } addSingletonFactory { HistoryRepositoryImpl(get()) } addFactory { GetHistory(get()) } diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithTrackServiceTwoWay.kt b/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithTrackServiceTwoWay.kt index da9ee05ea6..ddd8ebaa3c 100644 --- a/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithTrackServiceTwoWay.kt +++ b/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithTrackServiceTwoWay.kt @@ -1,11 +1,12 @@ package eu.kanade.domain.chapter.interactor import eu.kanade.domain.track.model.toDbTrack +import eu.kanade.tachiyomi.data.track.EnhancedTrackService import eu.kanade.tachiyomi.data.track.TrackService import logcat.LogPriority import tachiyomi.core.util.system.logcat +import tachiyomi.domain.chapter.interactor.GetChapterByMangaId import tachiyomi.domain.chapter.interactor.UpdateChapter -import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.toChapterUpdate import tachiyomi.domain.track.interactor.InsertTrack import tachiyomi.domain.track.model.Track @@ -13,14 +14,22 @@ import tachiyomi.domain.track.model.Track class SyncChaptersWithTrackServiceTwoWay( private val updateChapter: UpdateChapter, private val insertTrack: InsertTrack, + private val getChapterByMangaId: GetChapterByMangaId, ) { suspend fun await( - chapters: List, + mangaId: Long, remoteTrack: Track, service: TrackService, ) { - val sortedChapters = chapters.sortedBy { it.chapterNumber } + if (service !is EnhancedTrackService) { + return + } + + val sortedChapters = getChapterByMangaId.await(mangaId) + .sortedBy { it.chapterNumber } + .filter { it.isRecognizedNumber } + val chapterUpdates = sortedChapters .filter { chapter -> chapter.chapterNumber <= remoteTrack.lastChapterRead && !chapter.read } .map { it.copy(read = true).toChapterUpdate() } diff --git a/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt b/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt new file mode 100644 index 0000000000..dbff0e934a --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/track/interactor/RefreshTracks.kt @@ -0,0 +1,43 @@ +package eu.kanade.domain.track.interactor + +import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay +import eu.kanade.domain.track.model.toDbTrack +import eu.kanade.domain.track.model.toDomainTrack +import eu.kanade.tachiyomi.data.track.TrackManager +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.supervisorScope +import logcat.LogPriority +import tachiyomi.core.util.system.logcat +import tachiyomi.domain.track.interactor.GetTracks +import tachiyomi.domain.track.interactor.InsertTrack + +class RefreshTracks( + private val getTracks: GetTracks, + private val trackManager: TrackManager, + private val insertTrack: InsertTrack, + private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay, +) { + + suspend fun await(mangaId: Long) { + supervisorScope { + getTracks.await(mangaId) + .map { track -> + async { + val service = trackManager.getService(track.syncId) + if (service != null && service.isLoggedIn) { + try { + val updatedTrack = service.refresh(track.toDbTrack()) + insertTrack.await(updatedTrack.toDomainTrack()!!) + syncChaptersWithTrackServiceTwoWay.await(mangaId, track, service) + } catch (e: Throwable) { + // Ignore errors and continue + logcat(LogPriority.ERROR, e) + } + } + } + } + .awaitAll() + } + } +} diff --git a/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt b/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt index 57a49006ad..96f2f6ca49 100644 --- a/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt +++ b/app/src/main/java/eu/kanade/domain/track/interactor/TrackChapter.kt @@ -24,33 +24,31 @@ class TrackChapter( suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) = coroutineScope { launchNonCancellable { val tracks = getTracks.await(mangaId) - if (tracks.isEmpty()) return@launchNonCancellable tracks.mapNotNull { track -> val service = trackManager.getService(track.syncId) - if (service != null && service.isLogged && chapterNumber > track.lastChapterRead) { - val updatedTrack = track.copy(lastChapterRead = chapterNumber) + if (service == null || !service.isLoggedIn || chapterNumber <= track.lastChapterRead) { + return@mapNotNull null + } - async { - runCatching { - try { - service.update(updatedTrack.toDbTrack(), true) - insertTrack.await(updatedTrack) - } catch (e: Exception) { - delayedTrackingStore.addItem(updatedTrack) - DelayedTrackingUpdateJob.setupTask(context) - throw e - } + val updatedTrack = track.copy(lastChapterRead = chapterNumber) + async { + runCatching { + try { + service.update(updatedTrack.toDbTrack(), true) + insertTrack.await(updatedTrack) + } catch (e: Exception) { + delayedTrackingStore.addItem(updatedTrack) + DelayedTrackingUpdateJob.setupTask(context) + throw e } } - } else { - null } } .awaitAll() .mapNotNull { it.exceptionOrNull() } - .forEach { logcat(LogPriority.INFO, it) } + .forEach { logcat(LogPriority.WARN, it) } } } } diff --git a/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt b/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt index 3959c67071..0273e0fdc0 100644 --- a/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt +++ b/app/src/main/java/eu/kanade/domain/track/service/DelayedTrackingUpdateJob.kt @@ -48,7 +48,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) .forEach { track -> try { val service = trackManager.getService(track.syncId) - if (service != null && service.isLogged) { + if (service != null && service.isLoggedIn) { logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.id}, last chapter read: ${track.lastChapterRead}" } service.update(track.toDbTrack(), true) insertTrack.await(track) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt index 33a277c94b..940a482258 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt @@ -164,7 +164,7 @@ internal fun PreferenceItem( TrackingPreferenceWidget( service = this, checked = uName.isNotEmpty(), - onClick = { if (isLogged) item.logout() else item.login() }, + onClick = { if (isLoggedIn) item.logout() else item.login() }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt b/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt index 7169c9e9bd..9b4d4286f3 100644 --- a/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt +++ b/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt @@ -4,16 +4,26 @@ import android.content.Context import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.network.HttpException import eu.kanade.tachiyomi.source.online.LicensedMangaChaptersException +import eu.kanade.tachiyomi.util.system.isOnline import tachiyomi.data.source.NoResultsException import tachiyomi.domain.source.model.SourceNotInstalledException +import java.net.UnknownHostException context(Context) val Throwable.formattedMessage: String get() { when (this) { + is HttpException -> return getString(R.string.exception_http, code) + is UnknownHostException -> { + return if (!isOnline()) { + getString(R.string.exception_offline) + } else { + getString(R.string.exception_unknown_host, message) + } + } + is NoResultsException -> return getString(R.string.no_results_found) is SourceNotInstalledException -> return getString(R.string.loader_not_implemented_error) - is HttpException -> return "$message: ${getString(R.string.http_error_hint)}" is LicensedMangaChaptersException -> return getString(R.string.licensed_manga_chapters_error) } return when (val className = this::class.simpleName) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index ec33eac9e4..75edfdd462 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -135,7 +135,7 @@ 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.isLogged) { + if (trackManager.myAnimeList.isLoggedIn) { trackManager.myAnimeList.logout() context.toast(R.string.myanimelist_relogin) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt index e2cd12e3bb..56ac0b8e0a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt @@ -51,7 +51,7 @@ class BackupFileValidator( .distinct() val missingTrackers = trackers .mapNotNull { trackManager.getService(it.toLong()) } - .filter { !it.isLogged } + .filter { !it.isLoggedIn } .map { context.getString(it.nameRes()) } .sorted() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index a89b611fa6..d8fb589400 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -15,19 +15,14 @@ import androidx.work.WorkQuery import androidx.work.WorkerParameters import androidx.work.workDataOf import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource -import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.copyFrom import eu.kanade.domain.manga.model.toSManga -import eu.kanade.domain.track.model.toDbTrack -import eu.kanade.domain.track.model.toDomainTrack +import eu.kanade.domain.track.interactor.RefreshTracks import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.notification.Notifications -import eu.kanade.tachiyomi.data.track.EnhancedTrackService -import eu.kanade.tachiyomi.data.track.TrackManager -import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.UpdateStrategy @@ -43,7 +38,6 @@ import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.ensureActive import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import logcat.LogPriority @@ -52,7 +46,6 @@ import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.model.Category -import tachiyomi.domain.chapter.interactor.GetChapterByMangaId import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.NoChaptersException import tachiyomi.domain.download.service.DownloadPreferences @@ -73,8 +66,6 @@ import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.toMangaUpdate import tachiyomi.domain.source.model.SourceNotInstalledException import tachiyomi.domain.source.service.SourceManager -import tachiyomi.domain.track.interactor.GetTracks -import tachiyomi.domain.track.interactor.InsertTrack import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.time.ZonedDateTime @@ -91,17 +82,13 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet private val downloadPreferences: DownloadPreferences = Injekt.get() private val libraryPreferences: LibraryPreferences = Injekt.get() private val downloadManager: DownloadManager = Injekt.get() - private val trackManager: TrackManager = Injekt.get() private val coverCache: CoverCache = Injekt.get() private val getLibraryManga: GetLibraryManga = Injekt.get() private val getManga: GetManga = Injekt.get() private val updateManga: UpdateManga = Injekt.get() - private val getChapterByMangaId: GetChapterByMangaId = Injekt.get() private val getCategories: GetCategories = Injekt.get() private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get() - private val getTracks: GetTracks = Injekt.get() - private val insertTrack: InsertTrack = Injekt.get() - private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get() + private val refreshTracks: RefreshTracks = Injekt.get() private val setFetchInterval: SetFetchInterval = Injekt.get() private val failedUpdatesManager: FailedUpdatesRepository = Injekt.get() @@ -303,8 +290,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet } if (libraryPreferences.autoUpdateTrackers().get()) { - val loggedServices = trackManager.services.filter { it.isLogged } - updateTrackings(manga, loggedServices) + refreshTracks.await(manga.id) } } } @@ -423,49 +409,19 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet private suspend fun updateTrackings() { coroutineScope { var progressCount = 0 - val loggedServices = trackManager.services.filter { it.isLogged } mangaToUpdate.forEach { libraryManga -> - val manga = libraryManga.manga - ensureActive() + val manga = libraryManga.manga notifier.showProgressNotification(listOf(manga), progressCount++, mangaToUpdate.size) - - // Update the tracking details. - updateTrackings(manga, loggedServices) + refreshTracks.await(manga.id) } notifier.cancelProgressNotification() } } - private suspend fun updateTrackings(manga: Manga, loggedServices: List) { - getTracks.await(manga.id) - .map { track -> - supervisorScope { - async { - val service = trackManager.getService(track.syncId) - if (service != null && service in loggedServices) { - try { - val updatedTrack = service.refresh(track.toDbTrack()) - insertTrack.await(updatedTrack.toDomainTrack()!!) - - if (service is EnhancedTrackService) { - val chapters = getChapterByMangaId.await(manga.id) - syncChaptersWithTrackServiceTwoWay.await(chapters, track, service) - } - } catch (e: Throwable) { - // Ignore errors and continue - logcat(LogPriority.ERROR, e) - } - } - } - } - } - .awaitAll() - } - private suspend fun withUpdateNotification( updatingManga: CopyOnWriteArrayList, completed: AtomicInteger, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt index e1abbec832..e668aea35e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackManager.kt @@ -39,5 +39,5 @@ class TrackManager(context: Context) { fun getService(id: Long) = services.find { it.id == id } - fun hasLoggedServices() = services.any { it.isLogged } + fun hasLoggedServices() = services.any { it.isLoggedIn } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt index d7dd11c945..1a09579643 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt @@ -33,6 +33,7 @@ abstract class TrackService(val id: Long) { val trackPreferences: TrackPreferences by injectLazy() val networkService: NetworkHelper by injectLazy() private val insertTrack: InsertTrack by injectLazy() + private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay by injectLazy() open val client: OkHttpClient get() = networkService.client @@ -89,7 +90,7 @@ abstract class TrackService(val id: Long) { trackPreferences.setTrackCredentials(this, "", "") } - open val isLogged: Boolean + open val isLoggedIn: Boolean get() = getUsername().isNotEmpty() && getPassword().isNotEmpty() @@ -101,6 +102,7 @@ abstract class TrackService(val id: Long) { trackPreferences.setTrackCredentials(this, username, password) } + // TODO: move this to an interactor, and update all trackers based on common data suspend fun registerTracking(item: Track, mangaId: Long) { item.manga_id = mangaId try { @@ -113,6 +115,7 @@ abstract class TrackService(val id: Long) { insertTrack.await(track) + // TODO: merge into SyncChaptersWithTrackServiceTwoWay? // Update chapter progress if newer chapters marked read locally if (hasReadChapters) { val latestLocalReadChapterNumber = allChapters @@ -144,9 +147,7 @@ abstract class TrackService(val id: Long) { } } - if (this is EnhancedTrackService) { - Injekt.get().await(allChapters, track, this@TrackService) - } + syncChaptersWithTrackServiceTwoWay.await(mangaId, track, this@TrackService) } } catch (e: Throwable) { withUIContext { Injekt.get().toast(e.message) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index a2a5e0fe3c..2c1044d884 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -45,7 +45,6 @@ import tachiyomi.core.util.system.logcat import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.SetMangaCategories import tachiyomi.domain.category.model.Category -import tachiyomi.domain.chapter.interactor.GetChapterByMangaId import tachiyomi.domain.chapter.interactor.SetMangaDefaultChapterFlags import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.GetDuplicateLibraryManga @@ -72,7 +71,6 @@ class BrowseSourceScreenModel( private val getRemoteManga: GetRemoteManga = Injekt.get(), private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(), private val getCategories: GetCategories = Injekt.get(), - private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(), private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags = Injekt.get(), private val getManga: GetManga = Injekt.get(), @@ -82,7 +80,7 @@ class BrowseSourceScreenModel( private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(), ) : StateScreenModel(State(Listing.valueOf(listingQuery))) { - private val loggedServices by lazy { Injekt.get().services.filter { it.isLogged } } + private val loggedServices by lazy { Injekt.get().services.filter { it.isLoggedIn } } var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope) @@ -299,8 +297,7 @@ class BrowseSourceScreenModel( (service as TrackService).bind(track) insertTrack.await(track.toDomainTrack()!!) - val chapters = getChapterByMangaId.await(manga.id) - syncChaptersWithTrackServiceTwoWay.await(chapters, track.toDomainTrack()!!, service) + syncChaptersWithTrackServiceTwoWay.await(manga.id, track.toDomainTrack()!!, service) } } catch (e: Exception) { logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 7ae1aa7299..99b964caef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -366,7 +366,7 @@ class LibraryScreenModel( * @return map of track id with the filter value */ private fun getTrackingFilterFlow(): Flow> { - val loggedServices = trackManager.services.filter { it.isLogged } + val loggedServices = trackManager.services.filter { it.isLoggedIn } return if (loggedServices.isNotEmpty()) { val prefFlows = loggedServices .map { libraryPreferences.filterTracking(it.id.toInt()).changes() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt index a5a21317e3..1a9ce4208f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsScreenModel.kt @@ -26,7 +26,7 @@ class LibrarySettingsScreenModel( ) : ScreenModel { val trackServices - get() = trackManager.services.filter { it.isLogged } + get() = trackManager.services.filter { it.isLoggedIn } fun toggleFilter(preference: (LibraryPreferences) -> Preference) { preference(libraryPreferences).getAndSet { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index 37fde20727..c288733a00 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -105,7 +105,7 @@ class MangaScreenModel( private val successState: State.Success? get() = state.value as? State.Success - private val loggedServices by lazy { trackManager.services.filter { it.isLogged } } + private val loggedServices by lazy { trackManager.services.filter { it.isLoggedIn } } val manga: Manga? get() = successState?.manga diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt index 815c8d4542..91fea703b3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt @@ -71,7 +71,6 @@ import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.interactor.GetManga -import tachiyomi.domain.manga.interactor.GetMangaWithChapters import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.track.interactor.DeleteTrack import tachiyomi.domain.track.interactor.GetTracks @@ -218,8 +217,7 @@ data class TrackInfoDialogHomeScreen( private suspend fun refreshTrackers() { val insertTrack = Injekt.get() - val getMangaWithChapters = Injekt.get() - val syncTwoWayService = Injekt.get() + val syncChaptersWithTrackServiceTwoWay = Injekt.get() val context = Injekt.get() try { @@ -229,11 +227,7 @@ data class TrackInfoDialogHomeScreen( val track = trackItem.track ?: continue val domainTrack = trackItem.service.refresh(track.toDbTrack()).toDomainTrack() ?: continue insertTrack.await(domainTrack) - - if (trackItem.service is EnhancedTrackService) { - val allChapters = getMangaWithChapters.awaitChapters(mangaId) - syncTwoWayService.await(allChapters, domainTrack, trackItem.service) - } + syncChaptersWithTrackServiceTwoWay.await(mangaId, domainTrack, trackItem.service) } catch (e: Exception) { logcat( LogPriority.ERROR, @@ -257,7 +251,7 @@ data class TrackInfoDialogHomeScreen( } private fun List.mapToTrackItem(): List { - val loggedServices = Injekt.get().services.filter { it.isLogged } + val loggedServices = Injekt.get().services.filter { it.isLoggedIn } val source = Injekt.get().getOrStub(sourceId) return loggedServices // Map to TrackItem diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt index a7c18c25ae..873bd27235 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt @@ -36,7 +36,7 @@ class StatsScreenModel( private val trackManager: TrackManager = Injekt.get(), ) : StateScreenModel(StatsScreenState.Loading) { - private val loggedServices by lazy { trackManager.services.fastFilter { it.isLogged } } + private val loggedServices by lazy { trackManager.services.fastFilter { it.isLoggedIn } } init { coroutineScope.launchIO { diff --git a/domain/src/main/java/tachiyomi/domain/source/model/StubSource.kt b/domain/src/main/java/tachiyomi/domain/source/model/StubSource.kt index 3fbd021016..38d38ef575 100644 --- a/domain/src/main/java/tachiyomi/domain/source/model/StubSource.kt +++ b/domain/src/main/java/tachiyomi/domain/source/model/StubSource.kt @@ -6,20 +6,19 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import rx.Observable -@Suppress("OverridingDeprecatedMember") class StubSource( override val id: Long, override val lang: String, override val name: String, ) : Source { - val isInvalid: Boolean = name.isBlank() || lang.isBlank() + private val isInvalid: Boolean = name.isBlank() || lang.isBlank() override suspend fun getMangaDetails(manga: SManga): SManga { throw SourceNotInstalledException() } - @Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getMangaDetails")) + @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getMangaDetails")) override fun fetchMangaDetails(manga: SManga): Observable { return Observable.error(SourceNotInstalledException()) } @@ -28,7 +27,7 @@ class StubSource( throw SourceNotInstalledException() } - @Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList")) + @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getChapterList")) override fun fetchChapterList(manga: SManga): Observable> { return Observable.error(SourceNotInstalledException()) } @@ -37,7 +36,7 @@ class StubSource( throw SourceNotInstalledException() } - @Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getPageList")) + @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPageList")) override fun fetchPageList(chapter: SChapter): Observable> { return Observable.error(SourceNotInstalledException()) } diff --git a/gradle.properties b/gradle.properties index 39f9c9b71c..8102dd1763 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,4 +25,4 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 android.useAndroidX=true android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false -android.nonFinalResIds=false \ No newline at end of file +#android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8992dd8c9e..1cef0edeb6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,6 @@ desugar = "com.android.tools:desugar_jdk_libs:2.0.3" android-shortcut-gradle = "com.github.zellius:android-shortcut-gradle-plugin:0.1.2" google-services-gradle = "com.google.gms:google-services:4.3.15" -rxandroid = "io.reactivex:rxandroid:1.2.1" rxjava = "io.reactivex:rxjava:1.3.8" flowreactivenetwork = "ru.beryukhov:flowreactivenetwork:1.0.4" @@ -94,7 +93,6 @@ voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", vers kotlinter = "org.jmailen.gradle:kotlinter-gradle:3.13.0" [bundles] -reactivex = ["rxandroid", "rxjava"] okhttp = ["okhttp-core", "okhttp-logging", "okhttp-dnsoverhttps"] js-engine = ["quickjs-android"] sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"] diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 2a5051825c..9fb371192c 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -620,8 +620,6 @@ No more results No results found - - Check website in WebView Licensed - No chapters to show Local source Other @@ -964,35 +962,8 @@ You are about to remove \"%s\" from your library - Unknown network error - Socket error - Failed to bind to the port - IO operation interrupted - HTTP operation needs to retry - Port unreachable - IO error occurred - No internet connection - Operation timed out - SSL connection error - SSL certificate expired - SSL certificate not yet valid - Error parsing SSL certificate - Error encoding SSL certificate - Unrecoverable key encountered - Issue with key management - Algorithm not available - Keystore error - Security provider not found - Issue with signature validation - Invalid key specification - Domain not resolved - No route to host - Invalid URI syntax - Malformed URL - Invalid protocol or proxy type - Operation was cancelled - Operation was interrupted - Unexpected state encountered - Operation not supported - Invalid argument provided + + HTTP %d, check website in WebView + No Internet connection + Couldn\'t reach %s diff --git a/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/Source.kt b/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/Source.kt index 5f5dd57ee8..15747af982 100644 --- a/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/Source.kt +++ b/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/Source.kt @@ -24,13 +24,44 @@ interface Source { val lang: String get() = "" + /** + * Get the updated details for a manga. + * + * @param manga the manga to update. + */ + @Suppress("DEPRECATION") + suspend fun getMangaDetails(manga: SManga): SManga { + return fetchMangaDetails(manga).awaitSingle() + } + + /** + * Get all the available chapters for a manga. + * + * @param manga the manga to update. + */ + @Suppress("DEPRECATION") + suspend fun getChapterList(manga: SManga): List { + return fetchChapterList(manga).awaitSingle() + } + + /** + * Get the list of pages a chapter has. Pages should be returned + * in the expected order; the index is ignored. + * + * @param chapter the chapter. + */ + @Suppress("DEPRECATION") + suspend fun getPageList(chapter: SChapter): List { + return fetchPageList(chapter).awaitSingle() + } + /** * Returns an observable with the updated details for a manga. * * @param manga the manga to update. */ @Deprecated( - "Use the 1.x API instead", + "Use the non-RxJava API instead", ReplaceWith("getMangaDetails"), ) fun fetchMangaDetails(manga: SManga): Observable = throw IllegalStateException("Not used") @@ -41,7 +72,7 @@ interface Source { * @param manga the manga to update. */ @Deprecated( - "Use the 1.x API instead", + "Use the non-RxJava API instead", ReplaceWith("getChapterList"), ) fun fetchChapterList(manga: SManga): Observable> = throw IllegalStateException("Not used") @@ -53,33 +84,8 @@ interface Source { * @param chapter the chapter. */ @Deprecated( - "Use the 1.x API instead", + "Use the non-RxJava API instead", ReplaceWith("getPageList"), ) fun fetchPageList(chapter: SChapter): Observable> = Observable.empty() - - /** - * [1.x API] Get the updated details for a manga. - */ - @Suppress("DEPRECATION") - suspend fun getMangaDetails(manga: SManga): SManga { - return fetchMangaDetails(manga).awaitSingle() - } - - /** - * [1.x API] Get all the available chapters for a manga. - */ - @Suppress("DEPRECATION") - suspend fun getChapterList(manga: SManga): List { - return fetchChapterList(manga).awaitSingle() - } - - /** - * [1.x API] Get the list of pages a chapter has. Pages should be returned - * in the expected order; the index is ignored. - */ - @Suppress("DEPRECATION") - suspend fun getPageList(chapter: SChapter): List { - return fetchPageList(chapter).awaitSingle() - } }