Refactor some tracking-related logic
This commit is contained in:
parent
7644d7c31e
commit
98d6ce2eaf
28 changed files with 104 additions and 151 deletions
|
@ -1,8 +1,8 @@
|
||||||
package eu.kanade.domain
|
package eu.kanade.domain
|
||||||
|
|
||||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||||
|
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
|
||||||
import eu.kanade.domain.download.interactor.DeleteDownload
|
import eu.kanade.domain.download.interactor.DeleteDownload
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
||||||
|
@ -127,7 +127,7 @@ class DomainModule : InjektModule {
|
||||||
addFactory { SetReadStatus(get(), get(), get(), get()) }
|
addFactory { SetReadStatus(get(), get(), get(), get()) }
|
||||||
addFactory { ShouldUpdateDbChapter() }
|
addFactory { ShouldUpdateDbChapter() }
|
||||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) }
|
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) }
|
||||||
addFactory { SyncChaptersWithTrackServiceTwoWay(get(), get(), get()) }
|
addFactory { SyncChapterProgressWithTrack(get(), get(), get()) }
|
||||||
|
|
||||||
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
||||||
addFactory { GetHistory(get()) }
|
addFactory { GetHistory(get()) }
|
||||||
|
|
|
@ -11,7 +11,7 @@ import tachiyomi.domain.chapter.model.toChapterUpdate
|
||||||
import tachiyomi.domain.track.interactor.InsertTrack
|
import tachiyomi.domain.track.interactor.InsertTrack
|
||||||
import tachiyomi.domain.track.model.Track
|
import tachiyomi.domain.track.model.Track
|
||||||
|
|
||||||
class SyncChaptersWithTrackServiceTwoWay(
|
class SyncChapterProgressWithTrack(
|
||||||
private val updateChapter: UpdateChapter,
|
private val updateChapter: UpdateChapter,
|
||||||
private val insertTrack: InsertTrack,
|
private val insertTrack: InsertTrack,
|
||||||
private val getChapterByMangaId: GetChapterByMangaId,
|
private val getChapterByMangaId: GetChapterByMangaId,
|
|
@ -1,14 +1,13 @@
|
||||||
package eu.kanade.domain.track.interactor
|
package eu.kanade.domain.track.interactor
|
||||||
|
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
import eu.kanade.domain.track.model.toDomainTrack
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
import logcat.LogPriority
|
|
||||||
import tachiyomi.core.util.system.logcat
|
|
||||||
import tachiyomi.domain.track.interactor.GetTracks
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
import tachiyomi.domain.track.interactor.InsertTrack
|
import tachiyomi.domain.track.interactor.InsertTrack
|
||||||
|
|
||||||
|
@ -16,28 +15,34 @@ class RefreshTracks(
|
||||||
private val getTracks: GetTracks,
|
private val getTracks: GetTracks,
|
||||||
private val trackManager: TrackManager,
|
private val trackManager: TrackManager,
|
||||||
private val insertTrack: InsertTrack,
|
private val insertTrack: InsertTrack,
|
||||||
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay,
|
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun await(mangaId: Long) {
|
/**
|
||||||
supervisorScope {
|
* Fetches updated tracking data from all logged in trackers.
|
||||||
getTracks.await(mangaId)
|
*
|
||||||
|
* @return Failed updates.
|
||||||
|
*/
|
||||||
|
suspend fun await(mangaId: Long): List<Pair<TrackService?, Throwable>> {
|
||||||
|
return supervisorScope {
|
||||||
|
return@supervisorScope getTracks.await(mangaId)
|
||||||
.map { track ->
|
.map { track ->
|
||||||
async {
|
async {
|
||||||
val service = trackManager.getService(track.syncId)
|
val service = trackManager.getService(track.syncId)
|
||||||
if (service != null && service.isLoggedIn) {
|
return@async try {
|
||||||
try {
|
if (service?.isLoggedIn == true) {
|
||||||
val updatedTrack = service.refresh(track.toDbTrack())
|
val updatedTrack = service.refresh(track.toDbTrack())
|
||||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||||
syncChaptersWithTrackServiceTwoWay.await(mangaId, track, service)
|
syncChapterProgressWithTrack.await(mangaId, track, service)
|
||||||
} catch (e: Throwable) {
|
|
||||||
// Ignore errors and continue
|
|
||||||
logcat(LogPriority.ERROR, e)
|
|
||||||
}
|
}
|
||||||
|
null
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
service to e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.awaitAll()
|
.awaitAll()
|
||||||
|
.filterNotNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ private fun ColumnScope.FilterPage(
|
||||||
trackServices.map { service ->
|
trackServices.map { service ->
|
||||||
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
|
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
|
||||||
TriStateItem(
|
TriStateItem(
|
||||||
label = stringResource(service.nameRes()),
|
label = service.name,
|
||||||
state = filterTracker,
|
state = filterTracker,
|
||||||
onClick = { screenModel.toggleTracker(service.id.toInt()) },
|
onClick = { screenModel.toggleTracker(service.id.toInt()) },
|
||||||
)
|
)
|
||||||
|
|
|
@ -114,9 +114,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
if (enhancedTrackers.second.isNotEmpty()) {
|
if (enhancedTrackers.second.isNotEmpty()) {
|
||||||
val missingSourcesInfo = stringResource(
|
val missingSourcesInfo = stringResource(
|
||||||
R.string.enhanced_services_not_installed,
|
R.string.enhanced_services_not_installed,
|
||||||
enhancedTrackers.second
|
enhancedTrackers.second.joinToString { it.name },
|
||||||
.map { stringResource(it.nameRes()) }
|
|
||||||
.joinToString(),
|
|
||||||
)
|
)
|
||||||
enhancedTrackerInfo += "\n\n$missingSourcesInfo"
|
enhancedTrackerInfo += "\n\n$missingSourcesInfo"
|
||||||
}
|
}
|
||||||
|
@ -130,37 +128,37 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
title = stringResource(R.string.services),
|
title = stringResource(R.string.services),
|
||||||
preferenceItems = listOf(
|
preferenceItems = listOf(
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(trackManager.myAnimeList.nameRes()),
|
title = trackManager.myAnimeList.name,
|
||||||
service = trackManager.myAnimeList,
|
service = trackManager.myAnimeList,
|
||||||
login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.myAnimeList) },
|
logout = { dialog = LogoutDialog(trackManager.myAnimeList) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(trackManager.aniList.nameRes()),
|
title = trackManager.aniList.name,
|
||||||
service = trackManager.aniList,
|
service = trackManager.aniList,
|
||||||
login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.aniList) },
|
logout = { dialog = LogoutDialog(trackManager.aniList) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(trackManager.kitsu.nameRes()),
|
title = trackManager.kitsu.name,
|
||||||
service = trackManager.kitsu,
|
service = trackManager.kitsu,
|
||||||
login = { dialog = LoginDialog(trackManager.kitsu, R.string.email) },
|
login = { dialog = LoginDialog(trackManager.kitsu, R.string.email) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.kitsu) },
|
logout = { dialog = LogoutDialog(trackManager.kitsu) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(trackManager.mangaUpdates.nameRes()),
|
title = trackManager.mangaUpdates.name,
|
||||||
service = trackManager.mangaUpdates,
|
service = trackManager.mangaUpdates,
|
||||||
login = { dialog = LoginDialog(trackManager.mangaUpdates, R.string.username) },
|
login = { dialog = LoginDialog(trackManager.mangaUpdates, R.string.username) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.mangaUpdates) },
|
logout = { dialog = LogoutDialog(trackManager.mangaUpdates) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(trackManager.shikimori.nameRes()),
|
title = trackManager.shikimori.name,
|
||||||
service = trackManager.shikimori,
|
service = trackManager.shikimori,
|
||||||
login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.shikimori) },
|
logout = { dialog = LogoutDialog(trackManager.shikimori) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(trackManager.bangumi.nameRes()),
|
title = trackManager.bangumi.name,
|
||||||
service = trackManager.bangumi,
|
service = trackManager.bangumi,
|
||||||
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
|
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
|
||||||
logout = { dialog = LogoutDialog(trackManager.bangumi) },
|
logout = { dialog = LogoutDialog(trackManager.bangumi) },
|
||||||
|
@ -173,7 +171,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
preferenceItems = enhancedTrackers.first
|
preferenceItems = enhancedTrackers.first
|
||||||
.map { service ->
|
.map { service ->
|
||||||
Preference.PreferenceItem.TrackingPreference(
|
Preference.PreferenceItem.TrackingPreference(
|
||||||
title = stringResource(service.nameRes()),
|
title = service.name,
|
||||||
service = service,
|
service = service,
|
||||||
login = { (service as EnhancedTrackService).loginNoop() },
|
login = { (service as EnhancedTrackService).loginNoop() },
|
||||||
logout = service::logout,
|
logout = service::logout,
|
||||||
|
@ -202,7 +200,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
title = {
|
title = {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.login_title, stringResource(service.nameRes())),
|
text = stringResource(R.string.login_title, service.name),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
IconButton(onClick = onDismissRequest) {
|
IconButton(onClick = onDismissRequest) {
|
||||||
|
@ -310,7 +308,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.logout_title, stringResource(service.nameRes())),
|
text = stringResource(R.string.logout_title, service.name),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -40,7 +40,7 @@ fun TrackingPreferenceWidget(
|
||||||
) {
|
) {
|
||||||
TrackLogoIcon(service)
|
TrackLogoIcon(service)
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(service.nameRes()),
|
text = service.name,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
|
|
|
@ -11,7 +11,6 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import tachiyomi.presentation.core.util.clickableNoIndication
|
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||||
|
@ -36,7 +35,7 @@ fun TrackLogoIcon(
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(service.getLogo()),
|
painter = painterResource(service.getLogo()),
|
||||||
contentDescription = stringResource(service.nameRes()),
|
contentDescription = service.name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class BackupFileValidator(
|
||||||
val missingTrackers = trackers
|
val missingTrackers = trackers
|
||||||
.mapNotNull { trackManager.getService(it.toLong()) }
|
.mapNotNull { trackManager.getService(it.toLong()) }
|
||||||
.filter { !it.isLoggedIn }
|
.filter { !it.isLoggedIn }
|
||||||
.map { context.getString(it.nameRes()) }
|
.map { it.name }
|
||||||
.sorted()
|
.sorted()
|
||||||
|
|
||||||
return Results(missingSources, missingTrackers)
|
return Results(missingSources, missingTrackers)
|
||||||
|
|
|
@ -283,7 +283,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libraryPreferences.autoUpdateTrackers().get()) {
|
if (libraryPreferences.autoUpdateTrackers().get()) {
|
||||||
refreshTracks.await(manga.id)
|
refreshTracks(manga.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,13 +409,20 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
|
|
||||||
val manga = libraryManga.manga
|
val manga = libraryManga.manga
|
||||||
notifier.showProgressNotification(listOf(manga), progressCount++, mangaToUpdate.size)
|
notifier.showProgressNotification(listOf(manga), progressCount++, mangaToUpdate.size)
|
||||||
refreshTracks.await(manga.id)
|
refreshTracks(manga.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier.cancelProgressNotification()
|
notifier.cancelProgressNotification()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun refreshTracks(mangaId: Long) {
|
||||||
|
refreshTracks.await(mangaId).forEach { (_, e) ->
|
||||||
|
// Ignore errors and continue
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun withUpdateNotification(
|
private suspend fun withUpdateNotification(
|
||||||
updatingManga: CopyOnWriteArrayList<Manga>,
|
updatingManga: CopyOnWriteArrayList<Manga>,
|
||||||
completed: AtomicInteger,
|
completed: AtomicInteger,
|
||||||
|
|
|
@ -30,7 +30,7 @@ class TrackManager(context: Context) {
|
||||||
val kitsu = Kitsu(KITSU)
|
val kitsu = Kitsu(KITSU)
|
||||||
val shikimori = Shikimori(SHIKIMORI)
|
val shikimori = Shikimori(SHIKIMORI)
|
||||||
val bangumi = Bangumi(BANGUMI)
|
val bangumi = Bangumi(BANGUMI)
|
||||||
val komga = Komga(context, KOMGA)
|
val komga = Komga(KOMGA)
|
||||||
val mangaUpdates = MangaUpdates(MANGA_UPDATES)
|
val mangaUpdates = MangaUpdates(MANGA_UPDATES)
|
||||||
val kavita = Kavita(context, KAVITA)
|
val kavita = Kavita(context, KAVITA)
|
||||||
val suwayomi = Suwayomi(SUWAYOMI)
|
val suwayomi = Suwayomi(SUWAYOMI)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import androidx.annotation.CallSuper
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
import eu.kanade.domain.track.model.toDomainTrack
|
||||||
import eu.kanade.domain.track.service.TrackPreferences
|
import eu.kanade.domain.track.service.TrackPreferences
|
||||||
|
@ -28,20 +28,16 @@ import uy.kohesive.injekt.injectLazy
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
abstract class TrackService(val id: Long) {
|
abstract class TrackService(val id: Long, val name: String) {
|
||||||
|
|
||||||
val trackPreferences: TrackPreferences by injectLazy()
|
val trackPreferences: TrackPreferences by injectLazy()
|
||||||
val networkService: NetworkHelper by injectLazy()
|
val networkService: NetworkHelper by injectLazy()
|
||||||
private val insertTrack: InsertTrack by injectLazy()
|
private val insertTrack: InsertTrack by injectLazy()
|
||||||
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay by injectLazy()
|
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack by injectLazy()
|
||||||
|
|
||||||
open val client: OkHttpClient
|
open val client: OkHttpClient
|
||||||
get() = networkService.client
|
get() = networkService.client
|
||||||
|
|
||||||
// Name of the manga sync service to display
|
|
||||||
@StringRes
|
|
||||||
abstract fun nameRes(): Int
|
|
||||||
|
|
||||||
// Application and remote support for reading dates
|
// Application and remote support for reading dates
|
||||||
open val supportsReadingDates: Boolean = false
|
open val supportsReadingDates: Boolean = false
|
||||||
|
|
||||||
|
@ -103,7 +99,7 @@ abstract class TrackService(val id: Long) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this to an interactor, and update all trackers based on common data
|
// TODO: move this to an interactor, and update all trackers based on common data
|
||||||
suspend fun registerTracking(item: Track, mangaId: Long) {
|
suspend fun register(item: Track, mangaId: Long) {
|
||||||
item.manga_id = mangaId
|
item.manga_id = mangaId
|
||||||
try {
|
try {
|
||||||
withIOContext {
|
withIOContext {
|
||||||
|
@ -147,7 +143,7 @@ abstract class TrackService(val id: Long) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
syncChaptersWithTrackServiceTwoWay.await(mangaId, track, this@TrackService)
|
syncChapterProgressWithTrack.await(mangaId, track, this@TrackService)
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
withUIContext { Injekt.get<Application>().toast(e.message) }
|
withUIContext { Injekt.get<Application>().toast(e.message) }
|
||||||
|
|
|
@ -12,7 +12,7 @@ import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Anilist(id: Long) : TrackService(id), DeletableTrackService {
|
class Anilist(id: Long) : TrackService(id, "AniList"), DeletableTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
@ -49,9 +49,6 @@ class Anilist(id: Long) : TrackService(id), DeletableTrackService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_anilist
|
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.ic_tracker_anilist
|
override fun getLogo() = R.drawable.ic_tracker_anilist
|
||||||
|
|
||||||
override fun getLogoColor() = Color.rgb(18, 25, 35)
|
override fun getLogoColor() = Color.rgb(18, 25, 35)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class Bangumi(id: Long) : TrackService(id) {
|
class Bangumi(id: Long) : TrackService(id, "Bangumi") {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
@ -18,9 +18,6 @@ class Bangumi(id: Long) : TrackService(id) {
|
||||||
|
|
||||||
private val api by lazy { BangumiApi(client, interceptor) }
|
private val api by lazy { BangumiApi(client, interceptor) }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_bangumi
|
|
||||||
|
|
||||||
override fun getScoreList(): List<String> {
|
override fun getScoreList(): List<String> {
|
||||||
return IntRange(0, 10).map(Int::toString)
|
return IntRange(0, 10).map(Int::toString)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import tachiyomi.domain.manga.model.Manga
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Kavita(private val context: Context, id: Long) : TrackService(id), EnhancedTrackService {
|
class Kavita(private val context: Context, id: Long) : TrackService(id, "Kavita"), EnhancedTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val UNREAD = 1
|
const val UNREAD = 1
|
||||||
|
@ -27,9 +27,6 @@ class Kavita(private val context: Context, id: Long) : TrackService(id), Enhance
|
||||||
private val interceptor by lazy { KavitaInterceptor(this) }
|
private val interceptor by lazy { KavitaInterceptor(this) }
|
||||||
val api by lazy { KavitaApi(client, interceptor) }
|
val api by lazy { KavitaApi(client, interceptor) }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_kavita
|
|
||||||
|
|
||||||
override fun getLogo(): Int = R.drawable.ic_tracker_kavita
|
override fun getLogo(): Int = R.drawable.ic_tracker_kavita
|
||||||
|
|
||||||
override fun getLogoColor() = Color.rgb(74, 198, 148)
|
override fun getLogoColor() = Color.rgb(74, 198, 148)
|
||||||
|
|
|
@ -115,8 +115,8 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLatestChapterRead(url: String): Float {
|
private fun getLatestChapterRead(url: String): Float {
|
||||||
val serieId = getIdFromUrl(url)
|
val seriesId = getIdFromUrl(url)
|
||||||
val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$serieId"
|
val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$seriesId"
|
||||||
try {
|
try {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(GET(requestUrl)).execute().use {
|
authClient.newCall(GET(requestUrl)).execute().use {
|
||||||
|
@ -137,21 +137,21 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||||
|
|
||||||
suspend fun getTrackSearch(url: String): TrackSearch = withIOContext {
|
suspend fun getTrackSearch(url: String): TrackSearch = withIOContext {
|
||||||
try {
|
try {
|
||||||
val serieDto: SeriesDto = with(json) {
|
val seriesDto: SeriesDto = with(json) {
|
||||||
authClient.newCall(GET(url))
|
authClient.newCall(GET(url))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs()
|
.parseAs()
|
||||||
}
|
}
|
||||||
|
|
||||||
val track = serieDto.toTrack()
|
val track = seriesDto.toTrack()
|
||||||
track.apply {
|
track.apply {
|
||||||
cover_url = serieDto.thumbnail_url.toString()
|
cover_url = seriesDto.thumbnail_url.toString()
|
||||||
tracking_url = url
|
tracking_url = url
|
||||||
total_chapters = getTotalChapters(url)
|
total_chapters = getTotalChapters(url)
|
||||||
|
|
||||||
title = serieDto.name
|
title = seriesDto.name
|
||||||
status = when (serieDto.pagesRead) {
|
status = when (seriesDto.pagesRead) {
|
||||||
serieDto.pages -> Kavita.COMPLETED
|
seriesDto.pages -> Kavita.COMPLETED
|
||||||
0 -> Kavita.UNREAD
|
0 -> Kavita.UNREAD
|
||||||
else -> Kavita.READING
|
else -> Kavita.READING
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
class Kitsu(id: Long) : TrackService(id), DeletableTrackService {
|
class Kitsu(id: Long) : TrackService(id, "Kitsu"), DeletableTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
@ -22,9 +22,6 @@ class Kitsu(id: Long) : TrackService(id), DeletableTrackService {
|
||||||
const val PLAN_TO_READ = 5
|
const val PLAN_TO_READ = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_kitsu
|
|
||||||
|
|
||||||
override val supportsReadingDates: Boolean = true
|
override val supportsReadingDates: Boolean = true
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package eu.kanade.tachiyomi.data.track.komga
|
package eu.kanade.tachiyomi.data.track.komga
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
@ -14,7 +13,7 @@ import okhttp3.OkHttpClient
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Komga(private val context: Context, id: Long) : TrackService(id), EnhancedTrackService {
|
class Komga(id: Long) : TrackService(id, "Komga"), EnhancedTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val UNREAD = 1
|
const val UNREAD = 1
|
||||||
|
@ -29,9 +28,6 @@ class Komga(private val context: Context, id: Long) : TrackService(id), Enhanced
|
||||||
|
|
||||||
val api by lazy { KomgaApi(client) }
|
val api by lazy { KomgaApi(client) }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_komga
|
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.ic_tracker_komga
|
override fun getLogo() = R.drawable.ic_tracker_komga
|
||||||
|
|
||||||
override fun getLogoColor() = Color.rgb(51, 37, 50)
|
override fun getLogoColor() = Color.rgb(51, 37, 50)
|
||||||
|
|
|
@ -17,7 +17,7 @@ import tachiyomi.core.util.lang.withIOContext
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
const val READLIST_API = "/api/v1/readlists"
|
private const val READLIST_API = "/api/v1/readlists"
|
||||||
|
|
||||||
class KomgaApi(private val client: OkHttpClient) {
|
class KomgaApi(private val client: OkHttpClient) {
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.data.track.mangaupdates.dto.copyTo
|
||||||
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch
|
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
|
|
||||||
class MangaUpdates(id: Long) : TrackService(id), DeletableTrackService {
|
class MangaUpdates(id: Long) : TrackService(id, "MangaUpdates"), DeletableTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING_LIST = 0
|
const val READING_LIST = 0
|
||||||
|
@ -24,9 +24,6 @@ class MangaUpdates(id: Long) : TrackService(id), DeletableTrackService {
|
||||||
|
|
||||||
private val api by lazy { MangaUpdatesApi(interceptor, client) }
|
private val api by lazy { MangaUpdatesApi(interceptor, client) }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes(): Int = R.string.tracker_manga_updates
|
|
||||||
|
|
||||||
override fun getLogo(): Int = R.drawable.ic_manga_updates
|
override fun getLogo(): Int = R.drawable.ic_manga_updates
|
||||||
|
|
||||||
override fun getLogoColor(): Int = Color.rgb(146, 160, 173)
|
override fun getLogoColor(): Int = Color.rgb(146, 160, 173)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class MyAnimeList(id: Long) : TrackService(id), DeletableTrackService {
|
class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), DeletableTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
@ -30,9 +30,6 @@ class MyAnimeList(id: Long) : TrackService(id), DeletableTrackService {
|
||||||
private val interceptor by lazy { MyAnimeListInterceptor(this, getPassword()) }
|
private val interceptor by lazy { MyAnimeListInterceptor(this, getPassword()) }
|
||||||
private val api by lazy { MyAnimeListApi(client, interceptor) }
|
private val api by lazy { MyAnimeListApi(client, interceptor) }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_myanimelist
|
|
||||||
|
|
||||||
override val supportsReadingDates: Boolean = true
|
override val supportsReadingDates: Boolean = true
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.ic_tracker_mal
|
override fun getLogo() = R.drawable.ic_tracker_mal
|
||||||
|
|
|
@ -11,7 +11,7 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class Shikimori(id: Long) : TrackService(id), DeletableTrackService {
|
class Shikimori(id: Long) : TrackService(id, "Shikimori"), DeletableTrackService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
|
@ -28,9 +28,6 @@ class Shikimori(id: Long) : TrackService(id), DeletableTrackService {
|
||||||
|
|
||||||
private val api by lazy { ShikimoriApi(client, interceptor) }
|
private val api by lazy { ShikimoriApi(client, interceptor) }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_shikimori
|
|
||||||
|
|
||||||
override fun getScoreList(): List<String> {
|
override fun getScoreList(): List<String> {
|
||||||
return IntRange(0, 10).map(Int::toString)
|
return IntRange(0, 10).map(Int::toString)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findLibManga(track: Track, user_id: String): Track? {
|
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
||||||
.appendPath(track.media_id.toString())
|
.appendPath(track.media_id.toString())
|
||||||
|
@ -134,7 +134,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||||
}
|
}
|
||||||
|
|
||||||
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
||||||
.appendQueryParameter("user_id", user_id)
|
.appendQueryParameter("user_id", userId)
|
||||||
.appendQueryParameter("target_id", track.media_id.toString())
|
.appendQueryParameter("target_id", track.media_id.toString())
|
||||||
.appendQueryParameter("target_type", "Manga")
|
.appendQueryParameter("target_type", "Manga")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -11,13 +11,10 @@ import eu.kanade.tachiyomi.source.Source
|
||||||
import tachiyomi.domain.manga.model.Manga as DomainManga
|
import tachiyomi.domain.manga.model.Manga as DomainManga
|
||||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Suwayomi(id: Long) : TrackService(id), EnhancedTrackService {
|
class Suwayomi(id: Long) : TrackService(id, "Suwayomi"), EnhancedTrackService {
|
||||||
|
|
||||||
val api by lazy { TachideskApi() }
|
val api by lazy { TachideskApi() }
|
||||||
|
|
||||||
@StringRes
|
|
||||||
override fun nameRes() = R.string.tracker_suwayomi
|
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.ic_tracker_suwayomi
|
override fun getLogo() = R.drawable.ic_tracker_suwayomi
|
||||||
|
|
||||||
override fun getLogoColor() = Color.rgb(255, 35, 35) // TODO
|
override fun getLogoColor() = Color.rgb(255, 35, 35) // TODO
|
||||||
|
|
|
@ -28,19 +28,19 @@ class TachideskApi {
|
||||||
private val network: NetworkHelper by injectLazy()
|
private val network: NetworkHelper by injectLazy()
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
val client: OkHttpClient =
|
private val client: OkHttpClient =
|
||||||
network.client.newBuilder()
|
network.client.newBuilder()
|
||||||
.dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing
|
.dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun headersBuilder(): Headers.Builder = Headers.Builder().apply {
|
private fun headersBuilder(): Headers.Builder = Headers.Builder().apply {
|
||||||
if (basePassword.isNotEmpty() && baseLogin.isNotEmpty()) {
|
if (basePassword.isNotEmpty() && baseLogin.isNotEmpty()) {
|
||||||
val credentials = Credentials.basic(baseLogin, basePassword)
|
val credentials = Credentials.basic(baseLogin, basePassword)
|
||||||
add("Authorization", credentials)
|
add("Authorization", credentials)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val headers: Headers by lazy { headersBuilder().build() }
|
private val headers: Headers by lazy { headersBuilder().build() }
|
||||||
|
|
||||||
private val baseUrl by lazy { getPrefBaseUrl() }
|
private val baseUrl by lazy { getPrefBaseUrl() }
|
||||||
private val baseLogin by lazy { getPrefBaseLogin() }
|
private val baseLogin by lazy { getPrefBaseLogin() }
|
||||||
|
@ -100,7 +100,7 @@ class TachideskApi {
|
||||||
return getTrackSearch(track.tracking_url)
|
return getTrackSearch(track.tracking_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
val tachideskExtensionId by lazy {
|
private val tachideskExtensionId by lazy {
|
||||||
val key = "tachidesk/en/1"
|
val key = "tachidesk/en/1"
|
||||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
||||||
|
@ -110,6 +110,10 @@ class TachideskApi {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$tachideskExtensionId", 0x0000)
|
Injekt.get<Application>().getSharedPreferences("source_$tachideskExtensionId", 0x0000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getPrefBaseUrl(): String = preferences.getString(ADDRESS_TITLE, ADDRESS_DEFAULT)!!
|
||||||
|
private fun getPrefBaseLogin(): String = preferences.getString(LOGIN_TITLE, LOGIN_DEFAULT)!!
|
||||||
|
private fun getPrefBasePassword(): String = preferences.getString(PASSWORD_TITLE, PASSWORD_DEFAULT)!!
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ADDRESS_TITLE = "Server URL Address"
|
private const val ADDRESS_TITLE = "Server URL Address"
|
||||||
private const val ADDRESS_DEFAULT = ""
|
private const val ADDRESS_DEFAULT = ""
|
||||||
|
@ -118,8 +122,4 @@ class TachideskApi {
|
||||||
private const val PASSWORD_TITLE = "Password (Basic Auth)"
|
private const val PASSWORD_TITLE = "Password (Basic Auth)"
|
||||||
private const val PASSWORD_DEFAULT = ""
|
private const val PASSWORD_DEFAULT = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPrefBaseUrl(): String = preferences.getString(ADDRESS_TITLE, ADDRESS_DEFAULT)!!
|
|
||||||
private fun getPrefBaseLogin(): String = preferences.getString(LOGIN_TITLE, LOGIN_DEFAULT)!!
|
|
||||||
private fun getPrefBasePassword(): String = preferences.getString(PASSWORD_TITLE, PASSWORD_DEFAULT)!!
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import cafe.adriel.voyager.core.model.coroutineScope
|
import cafe.adriel.voyager.core.model.coroutineScope
|
||||||
import eu.kanade.core.preference.asState
|
import eu.kanade.core.preference.asState
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toDomainManga
|
import eu.kanade.domain.manga.model.toDomainManga
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
|
@ -77,7 +77,7 @@ class BrowseSourceScreenModel(
|
||||||
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
private val insertTrack: InsertTrack = Injekt.get(),
|
private val insertTrack: InsertTrack = Injekt.get(),
|
||||||
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(),
|
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack = Injekt.get(),
|
||||||
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
||||||
|
|
||||||
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLoggedIn } }
|
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLoggedIn } }
|
||||||
|
@ -297,7 +297,7 @@ class BrowseSourceScreenModel(
|
||||||
(service as TrackService).bind(track)
|
(service as TrackService).bind(track)
|
||||||
insertTrack.await(track.toDomainTrack()!!)
|
insertTrack.await(track.toDomainTrack()!!)
|
||||||
|
|
||||||
syncChaptersWithTrackServiceTwoWay.await(manga.id, track.toDomainTrack()!!, service)
|
syncChapterProgressWithTrack.await(manga.id, track.toDomainTrack()!!, service)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" }
|
logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" }
|
||||||
|
|
|
@ -323,7 +323,7 @@ class MangaScreenModel(
|
||||||
launchIO {
|
launchIO {
|
||||||
try {
|
try {
|
||||||
service.match(manga)?.let { track ->
|
service.match(manga)?.let { track ->
|
||||||
(service as TrackService).registerTracking(track, mangaId)
|
(service as TrackService).register(track, mangaId)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logcat(LogPriority.WARN, e) {
|
logcat(LogPriority.WARN, e) {
|
||||||
|
|
|
@ -39,9 +39,8 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.track.interactor.RefreshTracks
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
import eu.kanade.presentation.track.TrackChapterSelector
|
import eu.kanade.presentation.track.TrackChapterSelector
|
||||||
import eu.kanade.presentation.track.TrackDateSelector
|
import eu.kanade.presentation.track.TrackDateSelector
|
||||||
|
@ -74,7 +73,6 @@ import tachiyomi.domain.manga.interactor.GetManga
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.domain.track.interactor.DeleteTrack
|
import tachiyomi.domain.track.interactor.DeleteTrack
|
||||||
import tachiyomi.domain.track.interactor.GetTracks
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
import tachiyomi.domain.track.interactor.InsertTrack
|
|
||||||
import tachiyomi.domain.track.model.Track
|
import tachiyomi.domain.track.model.Track
|
||||||
import tachiyomi.presentation.core.components.material.AlertDialogContent
|
import tachiyomi.presentation.core.components.material.AlertDialogContent
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
@ -208,7 +206,7 @@ data class TrackInfoDialogHomeScreen(
|
||||||
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
|
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
|
||||||
try {
|
try {
|
||||||
val matchResult = item.service.match(manga) ?: throw Exception()
|
val matchResult = item.service.match(manga) ?: throw Exception()
|
||||||
item.service.registerTracking(matchResult, mangaId)
|
item.service.register(matchResult, mangaId)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
|
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
|
||||||
}
|
}
|
||||||
|
@ -216,39 +214,26 @@ data class TrackInfoDialogHomeScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun refreshTrackers() {
|
private suspend fun refreshTrackers() {
|
||||||
val insertTrack = Injekt.get<InsertTrack>()
|
val refreshTracks = Injekt.get<RefreshTracks>()
|
||||||
val syncChaptersWithTrackServiceTwoWay = Injekt.get<SyncChaptersWithTrackServiceTwoWay>()
|
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
|
|
||||||
try {
|
refreshTracks.await(mangaId)
|
||||||
val trackItems = getTracks.await(mangaId).mapToTrackItem()
|
.filter { it.first != null }
|
||||||
for (trackItem in trackItems) {
|
.forEach { (track, e) ->
|
||||||
try {
|
logcat(LogPriority.ERROR, e) {
|
||||||
val track = trackItem.track ?: continue
|
"Failed to refresh track data mangaId=$mangaId for service ${track!!.id}"
|
||||||
val domainTrack = trackItem.service.refresh(track.toDbTrack()).toDomainTrack() ?: continue
|
}
|
||||||
insertTrack.await(domainTrack)
|
|
||||||
syncChaptersWithTrackServiceTwoWay.await(mangaId, domainTrack, trackItem.service)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(
|
|
||||||
LogPriority.ERROR,
|
|
||||||
e,
|
|
||||||
) { "Failed to refresh track data mangaId=$mangaId for service ${trackItem.service.id}" }
|
|
||||||
withUIContext {
|
withUIContext {
|
||||||
context.toast(
|
context.toast(
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.track_error,
|
R.string.track_error,
|
||||||
context.getString(trackItem.service.nameRes()),
|
track!!.name,
|
||||||
e.message,
|
e.message,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(LogPriority.ERROR, e) { "Failed to refresh track data mangaId=$mangaId" }
|
|
||||||
withUIContext { context.toast(e.message) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun List<Track>.mapToTrackItem(): List<TrackItem> {
|
private fun List<Track>.mapToTrackItem(): List<TrackItem> {
|
||||||
val loggedServices = Injekt.get<TrackManager>().services.filter { it.isLoggedIn }
|
val loggedServices = Injekt.get<TrackManager>().services.filter { it.isLoggedIn }
|
||||||
|
@ -581,7 +566,7 @@ private data class TrackDateRemoverScreen(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
val serviceName = stringResource(sm.getServiceNameRes())
|
val serviceName = sm.getServiceName()
|
||||||
Text(
|
Text(
|
||||||
text = if (start) {
|
text = if (start) {
|
||||||
stringResource(R.string.track_remove_start_date_conf_text, serviceName)
|
stringResource(R.string.track_remove_start_date_conf_text, serviceName)
|
||||||
|
@ -618,7 +603,7 @@ private data class TrackDateRemoverScreen(
|
||||||
private val start: Boolean,
|
private val start: Boolean,
|
||||||
) : ScreenModel {
|
) : ScreenModel {
|
||||||
|
|
||||||
fun getServiceNameRes() = service.nameRes()
|
fun getServiceName() = service.name
|
||||||
|
|
||||||
fun removeDate() {
|
fun removeDate() {
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
|
@ -703,7 +688,7 @@ data class TrackServiceSearchScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerTracking(item: TrackSearch) {
|
fun registerTracking(item: TrackSearch) {
|
||||||
coroutineScope.launchNonCancellable { service.registerTracking(item, mangaId) }
|
coroutineScope.launchNonCancellable { service.register(item, mangaId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelection(selected: TrackSearch) {
|
fun updateSelection(selected: TrackSearch) {
|
||||||
|
@ -734,7 +719,7 @@ private data class TrackServiceRemoveScreen(
|
||||||
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
service = Injekt.get<TrackManager>().getService(serviceId)!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val serviceName = stringResource(sm.getServiceNameRes())
|
val serviceName = sm.getServiceName()
|
||||||
var removeRemoteTrack by remember { mutableStateOf(false) }
|
var removeRemoteTrack by remember { mutableStateOf(false) }
|
||||||
AlertDialogContent(
|
AlertDialogContent(
|
||||||
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
||||||
|
@ -799,7 +784,7 @@ private data class TrackServiceRemoveScreen(
|
||||||
private val deleteTrack: DeleteTrack = Injekt.get(),
|
private val deleteTrack: DeleteTrack = Injekt.get(),
|
||||||
) : ScreenModel {
|
) : ScreenModel {
|
||||||
|
|
||||||
fun getServiceNameRes() = service.nameRes()
|
fun getServiceName() = service.name
|
||||||
|
|
||||||
fun isServiceDeletable() = service is DeletableTrackService
|
fun isServiceDeletable() = service is DeletableTrackService
|
||||||
|
|
||||||
|
|
|
@ -697,15 +697,6 @@
|
||||||
<string name="are_you_sure">Are you sure?</string>
|
<string name="are_you_sure">Are you sure?</string>
|
||||||
|
|
||||||
<!-- Tracking Screen -->
|
<!-- Tracking Screen -->
|
||||||
<string name="tracker_anilist" translatable="false">AniList</string>
|
|
||||||
<string name="tracker_myanimelist" translatable="false">MyAnimeList</string>
|
|
||||||
<string name="tracker_kitsu" translatable="false">Kitsu</string>
|
|
||||||
<string name="tracker_komga" translatable="false">Komga</string>
|
|
||||||
<string name="tracker_bangumi" translatable="false">Bangumi</string>
|
|
||||||
<string name="tracker_shikimori" translatable="false">Shikimori</string>
|
|
||||||
<string name="tracker_manga_updates" translatable="false">MangaUpdates</string>
|
|
||||||
<string name="tracker_kavita" translatable="false">Kavita</string>
|
|
||||||
<string name="tracker_suwayomi" translatable="false">Suwayomi</string>
|
|
||||||
<string name="manga_tracking_tab">Tracking</string>
|
<string name="manga_tracking_tab">Tracking</string>
|
||||||
<plurals name="num_trackers">
|
<plurals name="num_trackers">
|
||||||
<item quantity="one">%d tracker</item>
|
<item quantity="one">%d tracker</item>
|
||||||
|
|
Reference in a new issue