Minor refactoring

(cherry picked from commit ef7b285151f83b8ef679786417b82ca3227dab35)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt
This commit is contained in:
arkon 2023-07-16 18:43:37 -04:00 committed by Jobobby04
parent 996d47e094
commit 2a5c869b1a
22 changed files with 72 additions and 101 deletions

View File

@ -30,7 +30,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.browse.components.BaseSourceItem
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.browse.source.SourcesState
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreenModel
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing
import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.domain.source.model.Pin
@ -47,7 +47,7 @@ import tachiyomi.source.local.isLocal
@Composable
fun SourcesScreen(
state: SourcesState,
state: SourcesScreenModel.State,
contentPadding: PaddingValues,
onClickItem: (Source, Listing) -> Unit,
onClickPin: (Source) -> Unit,

View File

@ -1,27 +1,21 @@
package eu.kanade.tachiyomi.data.backup
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
object BackupConst {
private const val NAME = "BackupRestoreServices"
const val EXTRA_URI = "$ID.$NAME.EXTRA_URI"
// Filter options
internal const val BACKUP_CATEGORY = 0x1
internal const val BACKUP_CATEGORY_MASK = 0x1
internal const val BACKUP_CHAPTER = 0x2
internal const val BACKUP_CHAPTER_MASK = 0x2
internal const val BACKUP_HISTORY = 0x4
internal const val BACKUP_HISTORY_MASK = 0x4
internal const val BACKUP_TRACK = 0x8
internal const val BACKUP_TRACK_MASK = 0x8
// Filter options
internal object BackupConst {
const val BACKUP_CATEGORY = 0x1
const val BACKUP_CATEGORY_MASK = 0x1
const val BACKUP_CHAPTER = 0x2
const val BACKUP_CHAPTER_MASK = 0x2
const val BACKUP_HISTORY = 0x4
const val BACKUP_HISTORY_MASK = 0x4
const val BACKUP_TRACK = 0x8
const val BACKUP_TRACK_MASK = 0x8
// SY -->
internal const val BACKUP_CUSTOM_INFO = 0x10
internal const val BACKUP_CUSTOM_INFO_MASK = 0x10
internal const val BACKUP_READ_MANGA = 0x20
internal const val BACKUP_READ_MANGA_MASK = 0x20
internal const val BACKUP_ALL = 0x3F
const val BACKUP_CUSTOM_INFO = 0x10
const val BACKUP_CUSTOM_INFO_MASK = 0x10
const val BACKUP_READ_MANGA = 0x20
const val BACKUP_READ_MANGA_MASK = 0x20
const val BACKUP_ALL = 0x3F
// SY <--
}

View File

@ -13,7 +13,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.Response

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context
import androidx.core.content.edit
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import tachiyomi.domain.chapter.model.Chapter

View File

@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import tachiyomi.domain.chapter.interactor.GetChapter

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.DeletableTrackService
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy

View File

@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy

View File

@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.network.parseAs
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.track.bangumi
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.FormBody
import okhttp3.Interceptor

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.DeletableTrackService
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.track.kitsu
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Interceptor
import okhttp3.Response

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.DeletableTrackService
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.DeletableTrackService
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.track.shikimori
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Interceptor
import okhttp3.Response

View File

@ -29,9 +29,6 @@ class MigrateSearchScreen(private val mangaId: Long, private val validSources: L
onChangeSearchFilter = screenModel::setSourceFilter,
onToggleResults = screenModel::toggleFilterResults,
onClickSource = {
if (!screenModel.incognitoMode.get()) {
screenModel.lastUsedSourceId.set(it.id)
}
// SY -->
navigator.push(SourceSearchScreen(state.manga!!, it.id, state.searchQuery))
// SY <--

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.coroutineScope
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
@ -21,16 +20,11 @@ class MigrateSearchScreenModel(
// SY -->
val validSources: List<Long>,
// SY <--
initialExtensionFilter: String = "",
preferences: BasePreferences = Injekt.get(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val getManga: GetManga = Injekt.get(),
) : SearchScreenModel<MigrateSearchScreenModel.State>(State()) {
val incognitoMode = preferences.incognitoMode()
val lastUsedSourceId = sourcePreferences.lastUsedSource()
init {
coroutineScope.launch {
val manga = getManga.await(mangaId)!!
@ -68,11 +62,11 @@ class MigrateSearchScreenModel(
return mutableState.value.items
}
fun setSourceFilter(filter: SourceFilter) {
override fun setSourceFilter(filter: SourceFilter) {
mutableState.update { it.copy(sourceFilter = filter) }
}
fun toggleFilterResults() {
override fun toggleFilterResults() {
mutableState.update {
it.copy(onlyShowHasResults = !it.onlyShowHasResults)
}

View File

@ -5,7 +5,6 @@ import androidx.compose.runtime.getValue
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.source.interactor.GetEnabledSources
import eu.kanade.domain.source.interactor.GetShowLatest
import eu.kanade.domain.source.interactor.GetSourceCategories
@ -36,8 +35,6 @@ import uy.kohesive.injekt.api.get
import java.util.TreeMap
class SourcesScreenModel(
private val preferences: BasePreferences = Injekt.get(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val getEnabledSources: GetEnabledSources = Injekt.get(),
private val toggleSource: ToggleSource = Injekt.get(),
private val toggleSourcePin: ToggleSourcePin = Injekt.get(),
@ -47,9 +44,10 @@ class SourcesScreenModel(
private val getShowLatest: GetShowLatest = Injekt.get(),
private val toggleExcludeFromDataSaver: ToggleExcludeFromDataSaver = Injekt.get(),
private val setSourceCategories: SetSourceCategories = Injekt.get(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
val smartSearchConfig: SourcesScreen.SmartSearchConfig?,
// SY <--
) : StateScreenModel<SourcesState>(SourcesState()) {
) : StateScreenModel<SourcesScreenModel.State>(State()) {
private val _events = Channel<Event>(Int.MAX_VALUE)
val events = _events.receiveAsFlow()
@ -132,12 +130,6 @@ class SourcesScreenModel(
}
}
fun onOpenSource(source: Source) {
if (!preferences.incognitoMode().get()) {
sourcePreferences.lastUsedSource().set(source.id)
}
}
fun toggleSource(source: Source) {
toggleSource.await(source)
}
@ -177,6 +169,21 @@ class SourcesScreenModel(
data class SourceCategories(val source: Source) : Dialog()
}
@Immutable
data class State(
val dialog: Dialog? = null,
val isLoading: Boolean = true,
val items: List<SourceUiModel> = emptyList(),
// SY -->
val categories: List<String> = emptyList(),
val showPin: Boolean = true,
val showLatest: Boolean = false,
val dataSaverEnabled: Boolean = false,
// SY <--
) {
val isEmpty = items.isEmpty()
}
companion object {
const val PINNED_KEY = "pinned"
const val LAST_USED_KEY = "last_used"
@ -186,18 +193,3 @@ class SourcesScreenModel(
// SY <--
}
}
@Immutable
data class SourcesState(
val dialog: SourcesScreenModel.Dialog? = null,
val isLoading: Boolean = true,
val items: List<SourceUiModel> = emptyList(),
// SY -->
val categories: List<String> = emptyList(),
val showPin: Boolean = true,
val showLatest: Boolean = false,
val dataSaverEnabled: Boolean = false,
// SY <--
) {
val isEmpty = items.isEmpty()
}

View File

@ -69,7 +69,6 @@ fun Screen.sourcesTab(
listing == Listing.Popular && screenModel.useNewSourceNavigation -> SourceFeedScreen(source.id)
else -> BrowseSourceScreen(source.id, listing.query)
}
screenModel.onOpenSource(source)
navigator.push(screen)
// SY <--
},

View File

@ -13,6 +13,7 @@ import androidx.paging.map
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.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toDomainManga
@ -97,6 +98,7 @@ open class BrowseSourceScreenModel(
// SY <--
private val sourceManager: SourceManager = Injekt.get(),
sourcePreferences: SourcePreferences = Injekt.get(),
basePreferences: BasePreferences = Injekt.get(),
private val libraryPreferences: LibraryPreferences = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(),
private val getRemoteManga: GetRemoteManga = Injekt.get(),
@ -156,6 +158,10 @@ open class BrowseSourceScreenModel(
}
}
if (!basePreferences.incognitoMode().get()) {
sourcePreferences.lastUsedSource().set(source.id)
}
// SY -->
val savedSearchFilters = savedSearch
val jsonFilters = filtersJson

View File

@ -64,9 +64,6 @@ class GlobalSearchScreen(
onChangeSearchFilter = screenModel::setSourceFilter,
onToggleResults = screenModel::toggleFilterResults,
onClickSource = {
if (!screenModel.incognitoMode.get()) {
screenModel.lastUsedSourceId.set(it.id)
}
navigator.push(BrowseSourceScreen(it.id, state.searchQuery))
},
onClickItem = { navigator.push(MangaScreen(it.id, true)) },

View File

@ -1,25 +1,14 @@
package eu.kanade.tachiyomi.ui.browse.source.globalsearch
import androidx.compose.runtime.Immutable
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.source.CatalogueSource
import kotlinx.coroutines.flow.update
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class GlobalSearchScreenModel(
initialQuery: String = "",
initialExtensionFilter: String? = null,
preferences: BasePreferences = Injekt.get(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
) : SearchScreenModel<GlobalSearchScreenModel.State>(State(searchQuery = initialQuery)) {
val incognitoMode = preferences.incognitoMode()
val lastUsedSourceId = sourcePreferences.lastUsedSource()
init {
extensionFilter = initialExtensionFilter
if (initialQuery.isNotBlank() || !initialExtensionFilter.isNullOrBlank()) {
@ -28,15 +17,8 @@ class GlobalSearchScreenModel(
}
override fun getEnabledSources(): List<CatalogueSource> {
val enabledLanguages = sourcePreferences.enabledLanguages().get()
val disabledSources = sourcePreferences.disabledSources().get()
val pinnedSources = sourcePreferences.pinnedSources().get()
return sourceManager.getVisibleCatalogueSources()
return super.getEnabledSources()
.filter { mutableState.value.sourceFilter != SourceFilter.PinnedOnly || "${it.id}" in pinnedSources }
.filter { it.lang in enabledLanguages }
.filterNot { "${it.id}" in disabledSources }
.sortedWith(compareBy({ "${it.id}" !in pinnedSources }, { "${it.name.lowercase()} (${it.lang})" }))
}
override fun updateSearchQuery(query: String?) {
@ -55,11 +37,11 @@ class GlobalSearchScreenModel(
return mutableState.value.items
}
fun setSourceFilter(filter: SourceFilter) {
override fun setSourceFilter(filter: SourceFilter) {
mutableState.update { it.copy(sourceFilter = filter) }
}
fun toggleFilterResults() {
override fun toggleFilterResults() {
mutableState.update {
it.copy(onlyShowHasResults = !it.onlyShowHasResults)
}

View File

@ -10,16 +10,19 @@ import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.presentation.util.ioCoroutineScope
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.CatalogueSource
import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import tachiyomi.core.util.lang.awaitSingle
import tachiyomi.domain.manga.interactor.GetManga
import tachiyomi.domain.manga.interactor.NetworkToLocalManga
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.Executors
@ -27,6 +30,7 @@ import java.util.concurrent.Executors
abstract class SearchScreenModel<T>(
initialState: T,
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val extensionManager: ExtensionManager = Injekt.get(),
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
private val getManga: GetManga = Injekt.get(),
@ -34,12 +38,13 @@ abstract class SearchScreenModel<T>(
) : StateScreenModel<T>(initialState) {
private val coroutineDispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
private var searchJob: Job? = null
protected var query: String? = null
protected var extensionFilter: String? = null
private val sources by lazy { getSelectedSources() }
private val pinnedSources by lazy { sourcePreferences.pinnedSources().get() }
protected val pinnedSources = sourcePreferences.pinnedSources().get()
private val sortComparator = { map: Map<CatalogueSource, SearchItemResult> ->
compareBy<CatalogueSource>(
@ -53,14 +58,27 @@ abstract class SearchScreenModel<T>(
fun getManga(initialManga: Manga): State<Manga> {
return produceState(initialValue = initialManga) {
getManga.subscribe(initialManga.url, initialManga.source)
.filterNotNull()
.collectLatest { manga ->
if (manga == null) return@collectLatest
value = manga
}
}
}
abstract fun getEnabledSources(): List<CatalogueSource>
open fun getEnabledSources(): List<CatalogueSource> {
val enabledLanguages = sourcePreferences.enabledLanguages().get()
val disabledSources = sourcePreferences.disabledSources().get()
val pinnedSources = sourcePreferences.pinnedSources().get()
return sourceManager.getVisibleCatalogueSources()
.filter { it.lang in enabledLanguages && "${it.id}" !in disabledSources }
.sortedWith(
compareBy(
{ "${it.id}" !in pinnedSources },
{ "${it.name.lowercase()} (${it.lang})" },
),
)
}
private fun getSelectedSources(): List<CatalogueSource> {
val enabledSources = getEnabledSources()
@ -90,15 +108,19 @@ abstract class SearchScreenModel<T>(
updateItems(function(getItems()))
}
abstract fun setSourceFilter(filter: SourceFilter)
abstract fun toggleFilterResults()
fun search(query: String) {
if (this.query == query) return
this.query = query
searchJob?.cancel()
val initialItems = getSelectedSources().associateWith { SearchItemResult.Loading }
updateItems(initialItems)
ioCoroutineScope.launch {
searchJob = ioCoroutineScope.launch {
sources
.map { source ->
async {