From 01e3f8c60557d89b6cd9d28c11f41d676d0ab5d9 Mon Sep 17 00:00:00 2001 From: MajorTanya <39014446+MajorTanya@users.noreply.github.com> Date: Sat, 19 Sep 2026 20:35:25 +0200 Subject: [PATCH] Add refresh button to tracker for new profile info (#3828) * Add refresh button to tracker for new profile info As-is, allows a user to manually refresh their current user data from the tracker in order to update Mihon's knowledge of remote settings (e.g. nickname changes, AL/MB/Kitsu score types, etc.). * Catch errors to prevent app crashing Surfaces errors as toasts in the same way library title refreshes do. * spotless * [skip ci] Remove leftover debugging logs * Fix Kitsu user attribute access * Spotless * Lowercase Kitsu score type on refresh Maybe prevent needing another #3887 for this. * Center tracker vertically name if not logged in Looks much better than the name being stuck at the top with empty space below it. * Don't show Refresh button for Enhanced trackers * [skip ci] Add changelog entry --- CHANGELOG.md | 1 + .../more/settings/PreferenceItem.kt | 22 ++++++ .../widget/TrackingPreferenceWidget.kt | 75 ++++++++++++++----- .../tachiyomi/data/track/BaseTracker.kt | 33 ++++++++ .../eu/kanade/tachiyomi/data/track/Tracker.kt | 8 ++ .../tachiyomi/data/track/anilist/Anilist.kt | 6 ++ .../tachiyomi/data/track/bangumi/Bangumi.kt | 5 ++ .../tachiyomi/data/track/hikka/Hikka.kt | 5 ++ .../tachiyomi/data/track/kavita/Kavita.kt | 2 + .../tachiyomi/data/track/kitsu/Kitsu.kt | 13 ++++ .../tachiyomi/data/track/komga/Komga.kt | 2 + .../data/track/mangabaka/MangaBaka.kt | 14 ++++ .../data/track/mangaupdates/MangaUpdates.kt | 5 ++ .../data/track/myanimelist/MyAnimeList.kt | 5 ++ .../data/track/shikimori/Shikimori.kt | 5 ++ .../tachiyomi/data/track/suwayomi/Suwayomi.kt | 2 + .../main/java/eu/kanade/test/DummyTracker.kt | 10 +++ .../moko-resources/base/strings.xml | 3 + 18 files changed, 199 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d8cb0027..7b42ea786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co - Allow `id:` to search for slugs on Kitsu ([@MajorTanya](https://github.com/MajorTanya)) ([#3792](https://github.com/mihonapp/mihon/pull/3792)) - Add support for using the user's chosen rating system for Kitsu ([@MajorTanya](https://github.com/MajorTanya)) ([#3818](https://github.com/mihonapp/mihon/pull/3818)) - Add support for the Year, Month, and Day fields in ComicInfo.xml files for chapter dating ([@MajorTanya](https://github.com/MajorTanya)) ([#3967](https://github.com/mihonapp/mihon/pull/3967)) +- Add refresh buttons to trackers in Settings to update displayed usernames (all trackers) & rating systems (where supported) ([@MajorTanya](https://github.com/MajorTanya)) ([#3828](https://github.com/mihonapp/mihon/pull/3828)) ### Improved - Show updates and upcoming filter icon as active for categories ([@Secozzi](https://github.com/Secozzi)) ([#3772](https://github.com/mihonapp/mihon/pull/3772)) 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 179e8553c..5cc014eeb 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 @@ -9,12 +9,14 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.structuralEqualityPolicy import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import eu.kanade.presentation.more.settings.widget.EditTextPreferenceWidget import eu.kanade.presentation.more.settings.widget.InfoWidget @@ -26,7 +28,11 @@ import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.more.settings.widget.TitleFontSize import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget +import eu.kanade.tachiyomi.data.track.RefreshResult +import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.launch +import tachiyomi.core.common.i18n.stringResource +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.BaseSliderItem import tachiyomi.presentation.core.util.collectAsState @@ -169,12 +175,28 @@ internal fun PreferenceItem( ) } is Preference.PreferenceItem.TrackerPreference -> { + val context = LocalContext.current + LaunchedEffect(item.tracker) { + item.tracker.refreshResultFlow.collect { + when (it) { + RefreshResult.Success -> context.toast( + context.stringResource(MR.strings.refresh_tracker_success, item.tracker.name), + ) + + is RefreshResult.Error -> context.toast( + context.stringResource(MR.strings.refresh_tracker_error, item.tracker.name, it.msg), + ) + } + } + } val isLoggedIn by item.tracker.let { tracker -> tracker.isLoggedInFlow.collectAsState(tracker.isLoggedIn) } + val isRefreshing by item.tracker.isRefreshingFlow.collectAsState() TrackingPreferenceWidget( tracker = item.tracker, isLoggedIn = isLoggedIn, + isRefreshing = isRefreshing, onClick = { if (isLoggedIn) item.logout() else item.login() }, ) } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt index 076b93f0d..45e44fdc3 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt @@ -7,10 +7,13 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -19,9 +22,13 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted import eu.kanade.presentation.track.components.TrackLogoIcon +import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.Tracker +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import mihon.icons.materialsymbols.MaterialSymbols import mihon.icons.materialsymbols.rounded.Done +import mihon.icons.materialsymbols.rounded.Refresh import tachiyomi.i18n.MR import tachiyomi.presentation.core.i18n.stringResource @@ -30,41 +37,75 @@ fun TrackingPreferenceWidget( modifier: Modifier = Modifier, tracker: Tracker, isLoggedIn: Boolean, + isRefreshing: Boolean, onClick: (() -> Unit)? = null, ) { val highlighted = LocalPreferenceHighlighted.current + val scope = rememberCoroutineScope { Dispatchers.IO } Box(modifier = Modifier.highlightBackground(highlighted)) { Row( modifier = modifier - .clickable(enabled = onClick != null, onClick = { onClick?.invoke() }) .fillMaxWidth() .padding(horizontal = PrefsHorizontalPadding, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { - TrackLogoIcon(tracker) - Column( - modifier = Modifier.weight(1f), + Row( + modifier = Modifier + .clickable( + enabled = onClick != null, + onClick = { onClick?.invoke() }, + ) + .weight(1f), + verticalAlignment = Alignment.CenterVertically, ) { - Text( - text = tracker.name, - modifier = Modifier.padding(horizontal = 16.dp), - maxLines = 1, - style = MaterialTheme.typography.titleLarge, - fontSize = TitleFontSize, - fontWeight = FontWeight.Medium, - ) - val displayName = tracker.getDisplayUsername() - if (isLoggedIn && displayName.isNotBlank()) { + TrackLogoIcon(tracker) + Column( + modifier = Modifier.weight(1f), + ) { Text( - text = displayName, + text = tracker.name, modifier = Modifier.padding(horizontal = 16.dp), maxLines = 1, - style = MaterialTheme.typography.bodyMedium, - overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.titleLarge, + fontSize = TitleFontSize, + fontWeight = FontWeight.Medium, ) + val displayName = tracker.getDisplayUsername() + if (isLoggedIn && displayName.isNotBlank()) { + Text( + text = displayName, + modifier = Modifier.padding(horizontal = 16.dp), + maxLines = 1, + style = MaterialTheme.typography.bodyMedium, + overflow = TextOverflow.Ellipsis, + ) + } } } if (isLoggedIn) { + if (tracker !is EnhancedTracker) { + IconButton( + enabled = !isRefreshing, + onClick = { + scope.launch { tracker.refreshUser() } + }, + ) { + if (!isRefreshing) { + Icon( + imageVector = MaterialSymbols.Rounded.Refresh, + modifier = Modifier + .padding(4.dp) + .size(32.dp), + contentDescription = stringResource(MR.strings.refresh_tracker_profile), + ) + } else { + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + strokeWidth = 2.dp, + ) + } + } + } Icon( imageVector = MaterialSymbols.Rounded.Done, modifier = Modifier diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/BaseTracker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/BaseTracker.kt index 76def2146..0560e5a9a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/BaseTracker.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/BaseTracker.kt @@ -8,7 +8,12 @@ import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.util.system.toast +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import logcat.LogPriority import mihon.app.di.appGraph @@ -70,6 +75,29 @@ abstract class BaseTracker( } } + final override val isRefreshingFlow: StateFlow + field: MutableStateFlow = MutableStateFlow(false) + + final override val refreshResultFlow: SharedFlow + field: MutableSharedFlow = MutableSharedFlow(extraBufferCapacity = 1) + + final override suspend fun refreshUser() { + isRefreshingFlow.value = true + try { + updateUserConfig() + refreshResultFlow.emit(RefreshResult.Success) + } catch (e: Exception) { + if (e is CancellationException) throw e + logcat(LogPriority.ERROR, e) { "Failed to update user config id=$id" } + refreshResultFlow.emit(RefreshResult.Error(e.message ?: "Failed with unknown error")) + } finally { + isRefreshingFlow.value = false + } + } + + // does the actual remote calls shielded from outside access to guarantee proper refresh flow setting + protected abstract suspend fun updateUserConfig() + override fun getUsername() = trackPreferences.trackUsername(this).get() override fun getDisplayUsername(): String = trackPreferences.trackDisplayUsername(this).get() @@ -151,3 +179,8 @@ abstract class BaseTracker( } } } + +sealed interface RefreshResult { + data object Success : RefreshResult + data class Error(val msg: String) : RefreshResult +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt index 9f345b2a9..83d5b3f87 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt @@ -6,6 +6,8 @@ import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow import okhttp3.OkHttpClient import tachiyomi.domain.track.model.Track as DomainTrack @@ -57,10 +59,16 @@ interface Tracker { @CallSuper fun logout() + suspend fun refreshUser() + val isLoggedIn: Boolean val isLoggedInFlow: Flow + val isRefreshingFlow: StateFlow + + val refreshResultFlow: SharedFlow + fun getUsername(): String fun getPassword(): String diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt index d62410e3e..eba6717da 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt @@ -214,6 +214,12 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker { return track } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + scorePreference.set(currentUser.mediaListOptions.scoreFormat) + saveDisplayUsername(currentUser.name) + } + override suspend fun login(username: String, password: String) = login(password) suspend fun login(token: String) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt index a8d57f993..27a1e04ae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt @@ -120,6 +120,11 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") { } } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + saveDisplayUsername(currentUser.nickname?.takeIf { it.isNotBlank() } ?: currentUser.username) + } + fun saveToken(oauth: BGMOAuth?) { trackPreferences.trackToken(this).set(json.encodeToString(oauth)) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt index 39d7a0d15..9845e21ad 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/hikka/Hikka.kt @@ -146,6 +146,11 @@ class Hikka(id: Long) : BaseTracker(id, "Hikka"), DeletableTracker { return track } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + saveDisplayUsername(currentUser.username) + } + override suspend fun login(username: String, password: String) = login(password) suspend fun login(reference: String) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt index 29deb9e8e..7313610c8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt @@ -140,4 +140,6 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker { } authentications = oauth } + + override suspend fun updateUserConfig() = Unit } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt index 3c6e3534d..71813398c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt @@ -196,6 +196,19 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker { saveCredentials(username, currentUser.id) } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + + val ratingSystem = currentUser.ratingSystem + if (ratingSystem.lowercase() in listOf(RATING_SIMPLE, RATING_REGULAR, RATING_ADVANCED)) { + scorePreference.set(ratingSystem.lowercase()) + } else { + logcat(LogPriority.ERROR) { "Unsupported Kitsu score type: $ratingSystem" } + scorePreference.set(RATING_ADVANCED) + } + saveDisplayUsername(currentUser.profile.name) + } + override fun logout() { super.logout() interceptor.newAuth(null) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt index 8df1efd56..6919d08e6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt @@ -107,4 +107,6 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker { } else { null } + + override suspend fun updateUserConfig() = Unit } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBaka.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBaka.kt index 0d6a13f04..bf7829eb6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBaka.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBaka.kt @@ -143,6 +143,20 @@ class MangaBaka(id: Long) : BaseTracker(id, "MangaBaka"), DeletableTracker { } } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + val scoreType = when (currentUser.ratingSteps) { + 1 -> STEP_1 + 5 -> STEP_5 + 10 -> STEP_10 + 20 -> STEP_20 + 25 -> STEP_25 + else -> throw Exception("Unknown score step size ${currentUser.ratingSteps}") + } + scorePreference.set(scoreType) + saveDisplayUsername(currentUser.nickname ?: currentUser.preferredUsername ?: currentUser.id) + } + fun saveToken(oauth: MangaBakaOAuth?) { trackPreferences.trackToken(this).set(json.encodeToString(oauth)) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt index 3e4f23814..6ff264381 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt @@ -124,6 +124,11 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker saveCredentials(authenticated.uid.toString(), authenticated.sessionToken) } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + saveDisplayUsername(currentUser.username) + } + fun restoreSession(): String? { return trackPreferences.trackPassword(this).get().ifBlank { null } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt index a0c015e3f..311a0d89e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt @@ -144,6 +144,11 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker { } } + override suspend fun updateUserConfig() { + val username = api.getCurrentUser() + saveDisplayUsername(username) + } + override fun logout() { super.logout() trackPreferences.trackToken(this).delete() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt index 20f27bd97..cff1d2bdb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt @@ -136,6 +136,11 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker { } } + override suspend fun updateUserConfig() { + val currentUser = api.getCurrentUser() + saveDisplayUsername(currentUser.nickname) + } + fun saveToken(oauth: SMOAuth?) { trackPreferences.trackToken(this).set(json.encodeToString(oauth)) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt index a30b120e4..e7c62e7f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt @@ -108,4 +108,6 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker { val preferences = api.sourcePreferences() return preferences.getBoolean(TRACKER_DELETE_KEY, TRACKER_DELETE_DEFAULT) } + + override suspend fun updateUserConfig() = Unit } diff --git a/app/src/main/java/eu/kanade/test/DummyTracker.kt b/app/src/main/java/eu/kanade/test/DummyTracker.kt index c4840b2bf..cbde52398 100644 --- a/app/src/main/java/eu/kanade/test/DummyTracker.kt +++ b/app/src/main/java/eu/kanade/test/DummyTracker.kt @@ -2,9 +2,15 @@ package eu.kanade.test import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.track.RefreshResult import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.flowOf import okhttp3.OkHttpClient import tachiyomi.domain.track.model.Track @@ -17,6 +23,8 @@ data class DummyTracker( override val supportsPrivateTracking: Boolean = false, override val isLoggedIn: Boolean = false, override val isLoggedInFlow: Flow = flowOf(false), + override val isRefreshingFlow: StateFlow = MutableStateFlow(false), + override val refreshResultFlow: SharedFlow = MutableSharedFlow().asSharedFlow(), val valLogo: Int = R.drawable.brand_anilist, val valStatuses: List = (1L..6L).toList(), val valReadingStatus: Long = 1L, @@ -75,6 +83,8 @@ data class DummyTracker( track: eu.kanade.tachiyomi.data.database.models.Track, ): eu.kanade.tachiyomi.data.database.models.Track = track + override suspend fun refreshUser() = Unit + override suspend fun login(username: String, password: String) = Unit override fun logout() = Unit diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index 9cfe0ffc1..db4be5b3e 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -580,6 +580,9 @@ Available but source not installed: %s Provides enhanced features for specific sources. Entries are automatically tracked when added to your library. Tracker login + Refresh tracker profile + %s profile refreshed + %1$s refresh error: %2$s Hide entries already in library