Support external repos

Largely taken from SY.

Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com>
(cherry picked from commit c17ada2c98041877ab901efb9b03497130ead34a)

# Conflicts:
#	app/src/main/java/eu/kanade/domain/source/interactor/CreateSourceRepo.kt
#	app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt
#	app/src/main/java/eu/kanade/presentation/category/SourceRepoScreen.kt
#	app/src/main/java/eu/kanade/presentation/category/components/CategoryDialogs.kt
#	app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoContent.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt
#	app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt
This commit is contained in:
arkon
2024-01-05 17:28:08 -05:00
committed by Jobobby04
parent b677f81fb1
commit 24a56a5529
35 changed files with 133 additions and 244 deletions
@@ -11,8 +11,11 @@ import eu.kanade.domain.manga.interactor.GetExcludedScanlators
import eu.kanade.domain.manga.interactor.SetExcludedScanlators
import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.source.interactor.CreateSourceRepo
import eu.kanade.domain.source.interactor.DeleteSourceRepos
import eu.kanade.domain.source.interactor.GetEnabledSources
import eu.kanade.domain.source.interactor.GetLanguagesWithSources
import eu.kanade.domain.source.interactor.GetSourceRepos
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
import eu.kanade.domain.source.interactor.SetMigrateSorting
import eu.kanade.domain.source.interactor.ToggleLanguage
@@ -167,5 +170,9 @@ class DomainModule : InjektModule {
addFactory { ToggleLanguage(get()) }
addFactory { ToggleSource(get()) }
addFactory { ToggleSourcePin(get()) }
addFactory { CreateSourceRepo(get()) }
addFactory { DeleteSourceRepos(get()) }
addFactory { GetSourceRepos(get()) }
}
}
@@ -7,7 +7,6 @@ import eu.kanade.domain.manga.interactor.GetPagePreviews
import eu.kanade.domain.manga.interactor.GetSortTag
import eu.kanade.domain.manga.interactor.ReorderSortTag
import eu.kanade.domain.source.interactor.CreateSourceCategory
import eu.kanade.domain.source.interactor.CreateSourceRepo
import eu.kanade.domain.source.interactor.DeleteSourceCategory
import eu.kanade.domain.source.interactor.GetExhSavedSearch
import eu.kanade.domain.source.interactor.GetShowLatest
@@ -61,14 +60,12 @@ import tachiyomi.domain.source.interactor.CountFeedSavedSearchBySourceId
import tachiyomi.domain.source.interactor.CountFeedSavedSearchGlobal
import tachiyomi.domain.source.interactor.DeleteFeedSavedSearchById
import tachiyomi.domain.source.interactor.DeleteSavedSearchById
import tachiyomi.domain.source.interactor.DeleteSourceRepos
import tachiyomi.domain.source.interactor.GetFeedSavedSearchBySourceId
import tachiyomi.domain.source.interactor.GetFeedSavedSearchGlobal
import tachiyomi.domain.source.interactor.GetSavedSearchById
import tachiyomi.domain.source.interactor.GetSavedSearchBySourceId
import tachiyomi.domain.source.interactor.GetSavedSearchBySourceIdFeed
import tachiyomi.domain.source.interactor.GetSavedSearchGlobalFeed
import tachiyomi.domain.source.interactor.GetSourceRepos
import tachiyomi.domain.source.interactor.InsertFeedSavedSearch
import tachiyomi.domain.source.interactor.InsertSavedSearch
import tachiyomi.domain.source.repository.FeedSavedSearchRepository
@@ -94,9 +91,6 @@ class SYDomainModule : InjektModule {
addFactory { FilterSerializer() }
addFactory { GetHistoryByMangaId(get()) }
addFactory { GetChapterByUrl(get()) }
addFactory { CreateSourceRepo(get()) }
addFactory { DeleteSourceRepos(get()) }
addFactory { GetSourceRepos(get()) }
addFactory { GetSourceCategories(get()) }
addFactory { CreateSourceCategory(get()) }
addFactory { RenameSourceCategory(get(), get()) }
@@ -1,9 +1,9 @@
package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.plusAssign
import tachiyomi.domain.UnsortedPreferences
class CreateSourceRepo(private val preferences: UnsortedPreferences) {
class CreateSourceRepo(private val preferences: SourcePreferences) {
fun await(name: String): Result {
// Do not allow invalid formats
@@ -0,0 +1,12 @@
package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
class DeleteSourceRepos(private val preferences: SourcePreferences) {
fun await(repos: List<String>) {
preferences.extensionRepos().set(
preferences.extensionRepos().get().filterNot { it in repos }.toSet(),
)
}
}
@@ -0,0 +1,12 @@
package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class GetSourceRepos(private val preferences: SourcePreferences) {
fun subscribe(): Flow<List<String>> {
return preferences.extensionRepos().changes().map { it.sortedWith(String.CASE_INSENSITIVE_ORDER) }
}
}
@@ -38,6 +38,8 @@ class SourcePreferences(
SetMigrateSorting.Direction.ASCENDING,
)
fun extensionRepos() = preferenceStore.getStringSet("extension_repos", emptySet())
fun extensionUpdatesCount() = preferenceStore.getInt("ext_updates_count", 0)
fun trustedSignatures() = preferenceStore.getStringSet(Preference.appStateKey("trusted_signatures"), emptySet())
@@ -156,11 +156,12 @@ private fun ExtensionDetails(
item {
WarningBanner(SYMR.strings.redundant_extension_message)
}
// SY <--
extension.isRepoSource ->
item {
val uriHandler = LocalUriHandler.current
WarningBanner(
SYMR.strings.repo_extension_message,
MR.strings.repo_extension_message,
modifier = Modifier.clickable {
extension.repoUrl ?: return@clickable
uriHandler.openUri(
@@ -171,7 +172,6 @@ private fun ExtensionDetails(
},
)
}
// SY <--
extension.isUnofficial ->
item {
WarningBanner(MR.strings.unofficial_extension_message)
@@ -340,13 +340,11 @@ private fun ExtensionItemContent(
val warning = when {
extension is Extension.Untrusted -> MR.strings.ext_untrusted
// SY -->
extension is Extension.Installed && extension.isRepoSource -> SYMR.strings.repo_source
extension is Extension.Available && extension.isRepoSource -> SYMR.strings.repo_source
// SY <--
extension is Extension.Installed && extension.isUnofficial -> MR.strings.ext_unofficial
extension is Extension.Installed && extension.isObsolete -> MR.strings.ext_obsolete
// SY -->
extension is Extension.Installed && extension.isRedundant -> SYMR.strings.ext_redundant
// SY <--
extension.isNsfw -> MR.strings.ext_nsfw_short
else -> null
}
@@ -8,9 +8,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import eu.kanade.presentation.category.components.CategoryFloatingActionButton
import eu.kanade.presentation.category.components.repo.SourceRepoContent
import eu.kanade.presentation.category.repos.RepoScreenState
import eu.kanade.presentation.components.AppBar
import eu.kanade.tachiyomi.ui.category.repos.RepoScreenState
import tachiyomi.i18n.sy.SYMR
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
@@ -30,7 +30,7 @@ fun SourceRepoScreen(
topBar = { scrollBehavior ->
AppBar(
navigateUp = navigateUp,
title = stringResource(SYMR.strings.action_edit_repos),
title = stringResource(MR.strings.label_extension_repos),
scrollBehavior = scrollBehavior,
)
},
@@ -43,7 +43,7 @@ fun SourceRepoScreen(
) { paddingValues ->
if (state.isEmpty) {
EmptyScreen(
SYMR.strings.information_empty_repos,
MR.strings.information_empty_repos,
modifier = Modifier.padding(paddingValues),
)
return@Scaffold
@@ -42,12 +42,10 @@ import kotlin.time.Duration.Companion.seconds
fun CategoryCreateDialog(
onDismissRequest: () -> Unit,
onCreate: (String) -> Unit,
// SY -->
categories: ImmutableList<String>,
title: String,
extraMessage: String? = null,
alreadyExistsError: StringResource = MR.strings.error_category_exists,
// SY <--
) {
var name by remember { mutableStateOf("") }
@@ -76,12 +74,9 @@ fun CategoryCreateDialog(
Text(text = title)
},
text = {
// SY -->
Column {
if (extraMessage != null) {
Text(extraMessage)
}
// SY <--
extraMessage?.let { Text(it) }
OutlinedTextField(
modifier = Modifier
.focusRequester(focusRequester),
@@ -101,9 +96,7 @@ fun CategoryCreateDialog(
isError = name.isNotEmpty() && nameAlreadyExists,
singleLine = true,
)
// SY -->
}
// SY <--
},
)
@@ -118,11 +111,9 @@ fun CategoryCreateDialog(
fun CategoryRenameDialog(
onDismissRequest: () -> Unit,
onRename: (String) -> Unit,
// SY -->
categories: ImmutableList<String>,
category: String,
alreadyExistsError: StringResource = MR.strings.error_category_exists,
// SY <--
) {
var name by remember { mutableStateOf(category) }
var valueHasChanged by remember { mutableStateOf(false) }
@@ -185,10 +176,8 @@ fun CategoryRenameDialog(
fun CategoryDeleteDialog(
onDismissRequest: () -> Unit,
onDelete: () -> Unit,
// SY -->
title: String,
text: String,
// SY <--
) {
AlertDialog(
onDismissRequest = onDismissRequest,
@@ -351,7 +340,3 @@ fun ChangeCategoryDialog(
},
)
}
private fun List<Category>.anyWithName(name: String): Boolean {
return any { name == it.name }
}
@@ -2,11 +2,23 @@ package eu.kanade.presentation.category.components.repo
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.ElevatedCard
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.ui.Alignment
import androidx.compose.ui.Modifier
import kotlinx.collections.immutable.ImmutableList
import tachiyomi.presentation.core.components.material.padding
@@ -17,11 +29,13 @@ fun SourceRepoContent(
lazyListState: LazyListState,
paddingValues: PaddingValues,
onClickDelete: (String) -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumn(
state = lazyListState,
contentPadding = paddingValues,
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
modifier = modifier,
) {
items(repos) { repo ->
SourceRepoListItem(
@@ -32,3 +46,34 @@ fun SourceRepoContent(
}
}
}
@Composable
private fun SourceRepoListItem(
repo: String,
onDelete: () -> Unit,
modifier: Modifier = Modifier,
) {
ElevatedCard(
modifier = modifier,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
start = MaterialTheme.padding.medium,
top = MaterialTheme.padding.medium,
end = MaterialTheme.padding.medium,
),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = Icons.AutoMirrored.Outlined.Label, contentDescription = "")
Text(text = repo, modifier = Modifier.padding(start = MaterialTheme.padding.medium))
}
Row {
Spacer(modifier = Modifier.weight(1f))
IconButton(onClick = onDelete) {
Icon(imageVector = Icons.Outlined.Delete, contentDescription = "")
}
}
}
}
@@ -1,50 +0,0 @@
package eu.kanade.presentation.category.components.repo
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Label
import androidx.compose.material3.ElevatedCard
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.ui.Alignment
import androidx.compose.ui.Modifier
import tachiyomi.presentation.core.components.material.padding
@Composable
fun SourceRepoListItem(
modifier: Modifier,
repo: String,
onDelete: () -> Unit,
) {
ElevatedCard(
modifier = modifier,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
start = MaterialTheme.padding.medium,
top = MaterialTheme.padding.medium,
end = MaterialTheme.padding.medium,
),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = Icons.AutoMirrored.Outlined.Label, contentDescription = "")
Text(text = repo, modifier = Modifier.padding(start = MaterialTheme.padding.medium))
}
Row {
Spacer(modifier = Modifier.weight(1f))
IconButton(onClick = onDelete) {
Icon(imageVector = Icons.Outlined.Delete, contentDescription = "")
}
}
}
}
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.category.repos
package eu.kanade.presentation.category.repos
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -14,11 +14,12 @@ import eu.kanade.presentation.category.components.CategoryDeleteDialog
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.collectLatest
import tachiyomi.i18n.sy.SYMR
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
class RepoScreen : Screen() {
@Composable
override fun Content() {
val context = LocalContext.current
@@ -48,17 +49,17 @@ class RepoScreen : Screen() {
onDismissRequest = screenModel::dismissDialog,
onCreate = { screenModel.createRepo(it) },
categories = successState.repos,
title = stringResource(SYMR.strings.action_add_repo),
extraMessage = stringResource(SYMR.strings.action_add_repo_message),
alreadyExistsError = SYMR.strings.error_repo_exists,
title = stringResource(MR.strings.action_add_repo),
extraMessage = stringResource(MR.strings.action_add_repo_message),
alreadyExistsError = MR.strings.error_repo_exists,
)
}
is RepoDialog.Delete -> {
CategoryDeleteDialog(
onDismissRequest = screenModel::dismissDialog,
onDelete = { screenModel.deleteRepos(listOf(dialog.repo)) },
title = stringResource(SYMR.strings.delete_repo),
text = stringResource(SYMR.strings.delete_repo_confirmation, dialog.repo),
title = stringResource(MR.strings.action_delete_repo),
text = stringResource(MR.strings.delete_repo_confirmation, dialog.repo),
)
}
}
@@ -1,10 +1,12 @@
package eu.kanade.tachiyomi.ui.category.repos
package eu.kanade.presentation.category.repos
import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import dev.icerock.moko.resources.StringResource
import eu.kanade.domain.source.interactor.CreateSourceRepo
import eu.kanade.domain.source.interactor.DeleteSourceRepos
import eu.kanade.domain.source.interactor.GetSourceRepos
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.channels.Channel
@@ -12,10 +14,7 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import tachiyomi.core.util.lang.launchIO
import tachiyomi.domain.source.interactor.DeleteSourceRepos
import tachiyomi.domain.source.interactor.GetSourceRepos
import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -87,7 +86,7 @@ class RepoScreenModel(
sealed class RepoEvent {
sealed class LocalizedMessage(val stringRes: StringResource) : RepoEvent()
data object InvalidName : LocalizedMessage(SYMR.strings.invalid_repo_name)
data object InvalidName : LocalizedMessage(MR.strings.invalid_repo_name)
data object InternalError : LocalizedMessage(MR.strings.internal_error)
}
@@ -10,8 +10,8 @@ import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.category.repos.RepoScreen
import eu.kanade.presentation.more.settings.Preference
import eu.kanade.tachiyomi.ui.category.repos.RepoScreen
import eu.kanade.tachiyomi.ui.category.sources.SourceCategoryScreen
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
import kotlinx.collections.immutable.persistentListOf
@@ -34,7 +34,11 @@ object SettingsBrowseScreen : SearchableSettings {
@Composable
override fun getPreferences(): List<Preference> {
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow
val sourcePreferences = remember { Injekt.get<SourcePreferences>() }
val reposCount by sourcePreferences.extensionRepos().collectAsState()
// SY -->
val uiPreferences = remember { Injekt.get<UiPreferences>() }
val unsortedPreferences = remember { Injekt.get<UnsortedPreferences>() }
@@ -45,7 +49,6 @@ object SettingsBrowseScreen : SearchableSettings {
title = stringResource(MR.strings.label_sources),
preferenceItems = persistentListOf(
kotlin.run {
val navigator = LocalNavigator.currentOrThrow
val count by sourcePreferences.sourcesTabCategories().collectAsState()
Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.action_edit_categories),
@@ -82,22 +85,6 @@ object SettingsBrowseScreen : SearchableSettings {
),
),
),
Preference.PreferenceGroup(
title = stringResource(MR.strings.label_extensions),
preferenceItems = persistentListOf(
kotlin.run {
val navigator = LocalNavigator.currentOrThrow
val count by unsortedPreferences.extensionRepos().collectAsState()
Preference.PreferenceItem.TextPreference(
title = stringResource(SYMR.strings.action_edit_repos),
subtitle = pluralStringResource(SYMR.plurals.num_repos, count.size, count.size),
onClick = {
navigator.push(RepoScreen())
},
)
},
),
),
// SY <--
Preference.PreferenceGroup(
title = stringResource(MR.strings.label_sources),
@@ -106,6 +93,13 @@ object SettingsBrowseScreen : SearchableSettings {
pref = sourcePreferences.hideInLibraryItems(),
title = stringResource(MR.strings.pref_hide_in_library_items),
),
Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.label_extension_repos),
subtitle = pluralStringResource(MR.plurals.num_repos, reposCount.size, reposCount.size),
onClick = {
navigator.push(RepoScreen())
},
),
),
),
Preference.PreferenceGroup(
@@ -18,7 +18,6 @@ import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.UnsortedPreferences
import uy.kohesive.injekt.injectLazy
import java.time.Instant
import kotlin.time.Duration.Companion.days
@@ -27,6 +26,7 @@ internal class ExtensionGithubApi {
private val networkService: NetworkHelper by injectLazy()
private val preferenceStore: PreferenceStore by injectLazy()
private val sourcePreferences: SourcePreferences by injectLazy()
private val extensionManager: ExtensionManager by injectLazy()
private val json: Json by injectLazy()
@@ -34,11 +34,6 @@ internal class ExtensionGithubApi {
preferenceStore.getLong(Preference.appStateKey("last_ext_check"), 0)
}
// SY -->
private val sourcePreferences: SourcePreferences by injectLazy()
private val unsortedPreferences: UnsortedPreferences by injectLazy()
// SY <--
private var requiresFallbackSource = false
suspend fun findExtensions(): List<Extension.Available> {
@@ -66,7 +61,7 @@ internal class ExtensionGithubApi {
val extensions = with(json) {
response
.parseAs<List<ExtensionJsonObject>>()
.toExtensions() /* SY --> */ + unsortedPreferences.extensionRepos()
.toExtensions() + sourcePreferences.extensionRepos()
.get()
.flatMap { repoPath ->
val url = if (requiresFallbackSource) {
@@ -80,7 +75,6 @@ internal class ExtensionGithubApi {
.parseAs<List<ExtensionJsonObject>>()
.toExtensions(url, repoSource = true)
}
// SY <--
}
// Sanity check - a small number of extensions probably means something broke
@@ -138,10 +132,8 @@ internal class ExtensionGithubApi {
}
private fun List<ExtensionJsonObject>.toExtensions(
// SY -->
repoUrl: String = getUrlPrefix(),
repoSource: Boolean = false,
// SY <--
): List<Extension.Available> {
return this
.filter {
@@ -159,17 +151,15 @@ internal class ExtensionGithubApi {
isNsfw = it.nsfw == 1,
sources = it.sources?.map(extensionSourceMapper).orEmpty(),
apkName = it.apk,
iconUrl = "${/* SY --> */ repoUrl /* SY <-- */}icon/${it.pkg}.png",
// SY -->
iconUrl = "${repoUrl}icon/${it.pkg}.png",
repoUrl = repoUrl,
isRepoSource = repoSource,
// SY <--
)
}
}
fun getApkUrl(extension: Extension.Available): String {
return /* SY --> */ "${extension.repoUrl}/apk/${extension.apkName}" // SY <--
return "${extension.repoUrl}/apk/${extension.apkName}"
}
private fun getUrlPrefix(): String {
@@ -29,10 +29,10 @@ sealed class Extension {
val isObsolete: Boolean = false,
val isUnofficial: Boolean = false,
val isShared: Boolean,
// SY -->
val isRedundant: Boolean = false,
val repoUrl: String? = null,
val isRepoSource: Boolean = false,
// SY -->
val isRedundant: Boolean = false,
// SY <--
) : Extension()
@@ -47,10 +47,8 @@ sealed class Extension {
val sources: List<Source>,
val apkName: String,
val iconUrl: String,
// SY -->
val repoUrl: String,
val isRepoSource: Boolean,
// SY <--
) : Extension() {
data class Source(
@@ -371,7 +371,10 @@ open class BrowseSourceScreenModel(
else -> {
val preselectedIds = getCategories.await(manga.id).map { it.id }
setDialog(
Dialog.ChangeMangaCategory(manga, categories.mapAsCheckboxState { it.id in preselectedIds }.toImmutableList()),
Dialog.ChangeMangaCategory(
manga,
categories.mapAsCheckboxState { it.id in preselectedIds }.toImmutableList(),
),
)
}
}
@@ -56,30 +56,24 @@ class CategoryScreen : Screen() {
CategoryCreateDialog(
onDismissRequest = screenModel::dismissDialog,
onCreate = screenModel::createCategory,
// SY -->
categories = successState.categories.fastMap { it.name }.toImmutableList(),
title = stringResource(MR.strings.action_add_category),
// SY <--
)
}
is CategoryDialog.Rename -> {
CategoryRenameDialog(
onDismissRequest = screenModel::dismissDialog,
onRename = { screenModel.renameCategory(dialog.category, it) },
// SY -->
categories = successState.categories.fastMap { it.name }.toImmutableList(),
category = dialog.category.name,
// SY <--
)
}
is CategoryDialog.Delete -> {
CategoryDeleteDialog(
onDismissRequest = screenModel::dismissDialog,
onDelete = { screenModel.deleteCategory(dialog.category.id) },
// SY -->
title = stringResource(MR.strings.delete_category),
text = stringResource(MR.strings.delete_category_confirmation, dialog.category.name),
// SY <--
)
}
is CategoryDialog.SortAlphabetically -> {
@@ -1117,13 +1117,15 @@ class LibraryScreenModel(
val common = getCommonCategories(mangaList)
// Get indexes of the mix categories to preselect.
val mix = getMixCategories(mangaList)
val preselected = categories.map {
when (it) {
in common -> CheckboxState.State.Checked(it)
in mix -> CheckboxState.TriState.Exclude(it)
else -> CheckboxState.State.None(it)
val preselected = categories
.map {
when (it) {
in common -> CheckboxState.State.Checked(it)
in mix -> CheckboxState.TriState.Exclude(it)
else -> CheckboxState.State.None(it)
}
}
}.toImmutableList()
.toImmutableList()
mutableState.update { it.copy(dialog = Dialog.ChangeCategory(mangaList, preselected)) }
}
}
@@ -121,6 +121,7 @@ class ChapterLoader(
source = source,
downloadManager = downloadManager,
downloadProvider = downloadProvider,
tempFileManager = tempFileManager,
)
source is HttpSource -> HttpPageLoader(chapter, source)
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
@@ -139,7 +140,7 @@ class ChapterLoader(
}
}
// SY <--
isDownloaded -> DownloadPageLoader(chapter, manga, source, downloadManager, downloadProvider)
isDownloaded -> DownloadPageLoader(chapter, manga, source, downloadManager, downloadProvider, tempFileManager)
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
when (format) {
is Format.Directory -> DirectoryPageLoader(format.file)