Refactor some tracking-related logic

This commit is contained in:
arkon 2023-08-27 10:41:58 -04:00
parent 7644d7c31e
commit 98d6ce2eaf
28 changed files with 104 additions and 151 deletions

View File

@ -1,8 +1,8 @@
package eu.kanade.domain
import eu.kanade.domain.chapter.interactor.SetReadStatus
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
import eu.kanade.domain.download.interactor.DeleteDownload
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
import eu.kanade.domain.extension.interactor.GetExtensionSources
@ -127,7 +127,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(), get()) }
addFactory { SyncChapterProgressWithTrack(get(), get(), get()) }
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
addFactory { GetHistory(get()) }

View File

@ -11,7 +11,7 @@ import tachiyomi.domain.chapter.model.toChapterUpdate
import tachiyomi.domain.track.interactor.InsertTrack
import tachiyomi.domain.track.model.Track
class SyncChaptersWithTrackServiceTwoWay(
class SyncChapterProgressWithTrack(
private val updateChapter: UpdateChapter,
private val insertTrack: InsertTrack,
private val getChapterByMangaId: GetChapterByMangaId,

View File

@ -1,14 +1,13 @@
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.toDomainTrack
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
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
@ -16,28 +15,34 @@ class RefreshTracks(
private val getTracks: GetTracks,
private val trackManager: TrackManager,
private val insertTrack: InsertTrack,
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay,
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
) {
suspend fun await(mangaId: Long) {
supervisorScope {
getTracks.await(mangaId)
/**
* Fetches updated tracking data from all logged in trackers.
*
* @return Failed updates.
*/
suspend fun await(mangaId: Long): List<Pair<TrackService?, Throwable>> {
return supervisorScope {
return@supervisorScope getTracks.await(mangaId)
.map { track ->
async {
val service = trackManager.getService(track.syncId)
if (service != null && service.isLoggedIn) {
try {
return@async try {
if (service?.isLoggedIn == true) {
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)
syncChapterProgressWithTrack.await(mangaId, track, service)
}
null
} catch (e: Throwable) {
service to e
}
}
}
.awaitAll()
.filterNotNull()
}
}
}

View File

@ -127,7 +127,7 @@ private fun ColumnScope.FilterPage(
trackServices.map { service ->
val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
TriStateItem(
label = stringResource(service.nameRes()),
label = service.name,
state = filterTracker,
onClick = { screenModel.toggleTracker(service.id.toInt()) },
)

View File

@ -114,9 +114,7 @@ object SettingsTrackingScreen : SearchableSettings {
if (enhancedTrackers.second.isNotEmpty()) {
val missingSourcesInfo = stringResource(
R.string.enhanced_services_not_installed,
enhancedTrackers.second
.map { stringResource(it.nameRes()) }
.joinToString(),
enhancedTrackers.second.joinToString { it.name },
)
enhancedTrackerInfo += "\n\n$missingSourcesInfo"
}
@ -130,37 +128,37 @@ object SettingsTrackingScreen : SearchableSettings {
title = stringResource(R.string.services),
preferenceItems = listOf(
Preference.PreferenceItem.TrackingPreference(
title = stringResource(trackManager.myAnimeList.nameRes()),
title = trackManager.myAnimeList.name,
service = trackManager.myAnimeList,
login = { context.openInBrowser(MyAnimeListApi.authUrl(), forceDefaultBrowser = true) },
logout = { dialog = LogoutDialog(trackManager.myAnimeList) },
),
Preference.PreferenceItem.TrackingPreference(
title = stringResource(trackManager.aniList.nameRes()),
title = trackManager.aniList.name,
service = trackManager.aniList,
login = { context.openInBrowser(AnilistApi.authUrl(), forceDefaultBrowser = true) },
logout = { dialog = LogoutDialog(trackManager.aniList) },
),
Preference.PreferenceItem.TrackingPreference(
title = stringResource(trackManager.kitsu.nameRes()),
title = trackManager.kitsu.name,
service = trackManager.kitsu,
login = { dialog = LoginDialog(trackManager.kitsu, R.string.email) },
logout = { dialog = LogoutDialog(trackManager.kitsu) },
),
Preference.PreferenceItem.TrackingPreference(
title = stringResource(trackManager.mangaUpdates.nameRes()),
title = trackManager.mangaUpdates.name,
service = trackManager.mangaUpdates,
login = { dialog = LoginDialog(trackManager.mangaUpdates, R.string.username) },
logout = { dialog = LogoutDialog(trackManager.mangaUpdates) },
),
Preference.PreferenceItem.TrackingPreference(
title = stringResource(trackManager.shikimori.nameRes()),
title = trackManager.shikimori.name,
service = trackManager.shikimori,
login = { context.openInBrowser(ShikimoriApi.authUrl(), forceDefaultBrowser = true) },
logout = { dialog = LogoutDialog(trackManager.shikimori) },
),
Preference.PreferenceItem.TrackingPreference(
title = stringResource(trackManager.bangumi.nameRes()),
title = trackManager.bangumi.name,
service = trackManager.bangumi,
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
logout = { dialog = LogoutDialog(trackManager.bangumi) },
@ -173,7 +171,7 @@ object SettingsTrackingScreen : SearchableSettings {
preferenceItems = enhancedTrackers.first
.map { service ->
Preference.PreferenceItem.TrackingPreference(
title = stringResource(service.nameRes()),
title = service.name,
service = service,
login = { (service as EnhancedTrackService).loginNoop() },
logout = service::logout,
@ -202,7 +200,7 @@ object SettingsTrackingScreen : SearchableSettings {
title = {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = stringResource(R.string.login_title, stringResource(service.nameRes())),
text = stringResource(R.string.login_title, service.name),
modifier = Modifier.weight(1f),
)
IconButton(onClick = onDismissRequest) {
@ -310,7 +308,7 @@ object SettingsTrackingScreen : SearchableSettings {
onDismissRequest = onDismissRequest,
title = {
Text(
text = stringResource(R.string.logout_title, stringResource(service.nameRes())),
text = stringResource(R.string.logout_title, service.name),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
)

View File

@ -40,7 +40,7 @@ fun TrackingPreferenceWidget(
) {
TrackLogoIcon(service)
Text(
text = stringResource(service.nameRes()),
text = service.name,
modifier = Modifier
.weight(1f)
.padding(horizontal = 16.dp),

View File

@ -11,7 +11,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import eu.kanade.tachiyomi.data.track.TrackService
import tachiyomi.presentation.core.util.clickableNoIndication
@ -36,7 +35,7 @@ fun TrackLogoIcon(
) {
Image(
painter = painterResource(service.getLogo()),
contentDescription = stringResource(service.nameRes()),
contentDescription = service.name,
)
}
}

View File

@ -52,7 +52,7 @@ class BackupFileValidator(
val missingTrackers = trackers
.mapNotNull { trackManager.getService(it.toLong()) }
.filter { !it.isLoggedIn }
.map { context.getString(it.nameRes()) }
.map { it.name }
.sorted()
return Results(missingSources, missingTrackers)

View File

@ -283,7 +283,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
}
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
notifier.showProgressNotification(listOf(manga), progressCount++, mangaToUpdate.size)
refreshTracks.await(manga.id)
refreshTracks(manga.id)
}
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(
updatingManga: CopyOnWriteArrayList<Manga>,
completed: AtomicInteger,

View File

@ -30,7 +30,7 @@ class TrackManager(context: Context) {
val kitsu = Kitsu(KITSU)
val shikimori = Shikimori(SHIKIMORI)
val bangumi = Bangumi(BANGUMI)
val komga = Komga(context, KOMGA)
val komga = Komga(KOMGA)
val mangaUpdates = MangaUpdates(MANGA_UPDATES)
val kavita = Kavita(context, KAVITA)
val suwayomi = Suwayomi(SUWAYOMI)

View File

@ -5,7 +5,7 @@ import androidx.annotation.CallSuper
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.domain.track.service.TrackPreferences
@ -28,20 +28,16 @@ import uy.kohesive.injekt.injectLazy
import java.time.ZoneOffset
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 networkService: NetworkHelper by injectLazy()
private val insertTrack: InsertTrack by injectLazy()
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay by injectLazy()
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack by injectLazy()
open val client: OkHttpClient
get() = networkService.client
// Name of the manga sync service to display
@StringRes
abstract fun nameRes(): Int
// Application and remote support for reading dates
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
suspend fun registerTracking(item: Track, mangaId: Long) {
suspend fun register(item: Track, mangaId: Long) {
item.manga_id = mangaId
try {
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) {
withUIContext { Injekt.get<Application>().toast(e.message) }

View File

@ -12,7 +12,7 @@ import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
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 {
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 getLogoColor() = Color.rgb(18, 25, 35)

View File

@ -10,7 +10,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
class Bangumi(id: Long) : TrackService(id) {
class Bangumi(id: Long) : TrackService(id, "Bangumi") {
private val json: Json by injectLazy()
@ -18,9 +18,6 @@ class Bangumi(id: Long) : TrackService(id) {
private val api by lazy { BangumiApi(client, interceptor) }
@StringRes
override fun nameRes() = R.string.tracker_bangumi
override fun getScoreList(): List<String> {
return IntRange(0, 10).map(Int::toString)
}

View File

@ -14,7 +14,7 @@ import tachiyomi.domain.manga.model.Manga
import java.security.MessageDigest
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 {
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) }
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 getLogoColor() = Color.rgb(74, 198, 148)

View File

@ -115,8 +115,8 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
}
private fun getLatestChapterRead(url: String): Float {
val serieId = getIdFromUrl(url)
val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$serieId"
val seriesId = getIdFromUrl(url)
val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$seriesId"
try {
with(json) {
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 {
try {
val serieDto: SeriesDto = with(json) {
val seriesDto: SeriesDto = with(json) {
authClient.newCall(GET(url))
.awaitSuccess()
.parseAs()
}
val track = serieDto.toTrack()
val track = seriesDto.toTrack()
track.apply {
cover_url = serieDto.thumbnail_url.toString()
cover_url = seriesDto.thumbnail_url.toString()
tracking_url = url
total_chapters = getTotalChapters(url)
title = serieDto.name
status = when (serieDto.pagesRead) {
serieDto.pages -> Kavita.COMPLETED
title = seriesDto.name
status = when (seriesDto.pagesRead) {
seriesDto.pages -> Kavita.COMPLETED
0 -> Kavita.UNREAD
else -> Kavita.READING
}

View File

@ -12,7 +12,7 @@ import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat
class Kitsu(id: Long) : TrackService(id), DeletableTrackService {
class Kitsu(id: Long) : TrackService(id, "Kitsu"), DeletableTrackService {
companion object {
const val READING = 1
@ -22,9 +22,6 @@ class Kitsu(id: Long) : TrackService(id), DeletableTrackService {
const val PLAN_TO_READ = 5
}
@StringRes
override fun nameRes() = R.string.tracker_kitsu
override val supportsReadingDates: Boolean = true
private val json: Json by injectLazy()

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.track.komga
import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
@ -14,7 +13,7 @@ import okhttp3.OkHttpClient
import tachiyomi.domain.manga.model.Manga
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 {
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) }
@StringRes
override fun nameRes() = R.string.tracker_komga
override fun getLogo() = R.drawable.ic_tracker_komga
override fun getLogoColor() = Color.rgb(51, 37, 50)

View File

@ -17,7 +17,7 @@ import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
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) {

View File

@ -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.model.TrackSearch
class MangaUpdates(id: Long) : TrackService(id), DeletableTrackService {
class MangaUpdates(id: Long) : TrackService(id, "MangaUpdates"), DeletableTrackService {
companion object {
const val READING_LIST = 0
@ -24,9 +24,6 @@ class MangaUpdates(id: Long) : TrackService(id), DeletableTrackService {
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 getLogoColor(): Int = Color.rgb(146, 160, 173)

View File

@ -11,7 +11,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
class MyAnimeList(id: Long) : TrackService(id), DeletableTrackService {
class MyAnimeList(id: Long) : TrackService(id, "MyAnimeList"), DeletableTrackService {
companion object {
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 api by lazy { MyAnimeListApi(client, interceptor) }
@StringRes
override fun nameRes() = R.string.tracker_myanimelist
override val supportsReadingDates: Boolean = true
override fun getLogo() = R.drawable.ic_tracker_mal

View File

@ -11,7 +11,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
class Shikimori(id: Long) : TrackService(id), DeletableTrackService {
class Shikimori(id: Long) : TrackService(id, "Shikimori"), DeletableTrackService {
companion object {
const val READING = 1
@ -28,9 +28,6 @@ class Shikimori(id: Long) : TrackService(id), DeletableTrackService {
private val api by lazy { ShikimoriApi(client, interceptor) }
@StringRes
override fun nameRes() = R.string.tracker_shikimori
override fun getScoreList(): List<String> {
return IntRange(0, 10).map(Int::toString)
}

View File

@ -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 {
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
.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()
.appendQueryParameter("user_id", user_id)
.appendQueryParameter("user_id", userId)
.appendQueryParameter("target_id", track.media_id.toString())
.appendQueryParameter("target_type", "Manga")
.build()

View File

@ -11,13 +11,10 @@ import eu.kanade.tachiyomi.source.Source
import tachiyomi.domain.manga.model.Manga as DomainManga
import tachiyomi.domain.track.model.Track as DomainTrack
class Suwayomi(id: Long) : TrackService(id), EnhancedTrackService {
class Suwayomi(id: Long) : TrackService(id, "Suwayomi"), EnhancedTrackService {
val api by lazy { TachideskApi() }
@StringRes
override fun nameRes() = R.string.tracker_suwayomi
override fun getLogo() = R.drawable.ic_tracker_suwayomi
override fun getLogoColor() = Color.rgb(255, 35, 35) // TODO

View File

@ -28,19 +28,19 @@ class TachideskApi {
private val network: NetworkHelper by injectLazy()
private val json: Json by injectLazy()
val client: OkHttpClient =
private val client: OkHttpClient =
network.client.newBuilder()
.dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing
.build()
fun headersBuilder(): Headers.Builder = Headers.Builder().apply {
private fun headersBuilder(): Headers.Builder = Headers.Builder().apply {
if (basePassword.isNotEmpty() && baseLogin.isNotEmpty()) {
val credentials = Credentials.basic(baseLogin, basePassword)
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 baseLogin by lazy { getPrefBaseLogin() }
@ -100,7 +100,7 @@ class TachideskApi {
return getTrackSearch(track.tracking_url)
}
val tachideskExtensionId by lazy {
private val tachideskExtensionId 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
@ -110,6 +110,10 @@ class TachideskApi {
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 {
private const val ADDRESS_TITLE = "Server URL Address"
private const val ADDRESS_DEFAULT = ""
@ -118,8 +122,4 @@ class TachideskApi {
private const val PASSWORD_TITLE = "Password (Basic Auth)"
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)!!
}

View File

@ -14,7 +14,7 @@ import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope
import eu.kanade.core.preference.asState
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
import eu.kanade.domain.chapter.interactor.SyncChapterProgressWithTrack
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toDomainManga
import eu.kanade.domain.source.service.SourcePreferences
@ -77,7 +77,7 @@ class BrowseSourceScreenModel(
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
private val updateManga: UpdateManga = 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))) {
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLoggedIn } }
@ -297,7 +297,7 @@ class BrowseSourceScreenModel(
(service as TrackService).bind(track)
insertTrack.await(track.toDomainTrack()!!)
syncChaptersWithTrackServiceTwoWay.await(manga.id, track.toDomainTrack()!!, service)
syncChapterProgressWithTrack.await(manga.id, track.toDomainTrack()!!, service)
}
} catch (e: Exception) {
logcat(LogPriority.WARN, e) { "Could not match manga: ${manga.title} with service $service" }

View File

@ -323,7 +323,7 @@ class MangaScreenModel(
launchIO {
try {
service.match(manga)?.let { track ->
(service as TrackService).registerTracking(track, mangaId)
(service as TrackService).register(track, mangaId)
}
} catch (e: Exception) {
logcat(LogPriority.WARN, e) {

View File

@ -39,9 +39,8 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator
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.toDomainTrack
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.track.TrackChapterSelector
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.track.interactor.DeleteTrack
import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack
import tachiyomi.domain.track.model.Track
import tachiyomi.presentation.core.components.material.AlertDialogContent
import tachiyomi.presentation.core.components.material.padding
@ -208,7 +206,7 @@ data class TrackInfoDialogHomeScreen(
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
try {
val matchResult = item.service.match(manga) ?: throw Exception()
item.service.registerTracking(matchResult, mangaId)
item.service.register(matchResult, mangaId)
} catch (e: Exception) {
withUIContext { Injekt.get<Application>().toast(R.string.error_no_match) }
}
@ -216,38 +214,25 @@ data class TrackInfoDialogHomeScreen(
}
private suspend fun refreshTrackers() {
val insertTrack = Injekt.get<InsertTrack>()
val syncChaptersWithTrackServiceTwoWay = Injekt.get<SyncChaptersWithTrackServiceTwoWay>()
val refreshTracks = Injekt.get<RefreshTracks>()
val context = Injekt.get<Application>()
try {
val trackItems = getTracks.await(mangaId).mapToTrackItem()
for (trackItem in trackItems) {
try {
val track = trackItem.track ?: continue
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 {
context.toast(
context.getString(
R.string.track_error,
context.getString(trackItem.service.nameRes()),
e.message,
),
)
}
refreshTracks.await(mangaId)
.filter { it.first != null }
.forEach { (track, e) ->
logcat(LogPriority.ERROR, e) {
"Failed to refresh track data mangaId=$mangaId for service ${track!!.id}"
}
withUIContext {
context.toast(
context.getString(
R.string.track_error,
track!!.name,
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> {
@ -581,7 +566,7 @@ private data class TrackDateRemoverScreen(
)
},
text = {
val serviceName = stringResource(sm.getServiceNameRes())
val serviceName = sm.getServiceName()
Text(
text = if (start) {
stringResource(R.string.track_remove_start_date_conf_text, serviceName)
@ -618,7 +603,7 @@ private data class TrackDateRemoverScreen(
private val start: Boolean,
) : ScreenModel {
fun getServiceNameRes() = service.nameRes()
fun getServiceName() = service.name
fun removeDate() {
coroutineScope.launchNonCancellable {
@ -703,7 +688,7 @@ data class TrackServiceSearchScreen(
}
fun registerTracking(item: TrackSearch) {
coroutineScope.launchNonCancellable { service.registerTracking(item, mangaId) }
coroutineScope.launchNonCancellable { service.register(item, mangaId) }
}
fun updateSelection(selected: TrackSearch) {
@ -734,7 +719,7 @@ private data class TrackServiceRemoveScreen(
service = Injekt.get<TrackManager>().getService(serviceId)!!,
)
}
val serviceName = stringResource(sm.getServiceNameRes())
val serviceName = sm.getServiceName()
var removeRemoteTrack by remember { mutableStateOf(false) }
AlertDialogContent(
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
@ -799,7 +784,7 @@ private data class TrackServiceRemoveScreen(
private val deleteTrack: DeleteTrack = Injekt.get(),
) : ScreenModel {
fun getServiceNameRes() = service.nameRes()
fun getServiceName() = service.name
fun isServiceDeletable() = service is DeletableTrackService

View File

@ -697,15 +697,6 @@
<string name="are_you_sure">Are you sure?</string>
<!-- 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>
<plurals name="num_trackers">
<item quantity="one">%d tracker</item>