feat(local): Allow delete whole manga's downloaded folder & clear chapters list (#1016)
* feat(local): Allow delete local files * Refresh chapters list after deleting * Allow delete whole entry's downloaded folder & clear episodes/chapters list Also hide `Open folder` for merged entries * Don't delete local folder & refresh local's chapters list state after clear * use forEachIndexed instead of forEach * adding comment * add empty line
This commit is contained in:
parent
32d448d6ab
commit
3ec6aeaba2
9 changed files with 192 additions and 12 deletions
|
|
@ -57,17 +57,14 @@ fun DeleteLibraryMangaDialog(
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
list.forEach { state ->
|
list.forEachIndexed { index, state ->
|
||||||
LabeledCheckbox(
|
LabeledCheckbox(
|
||||||
label = stringResource(state.value),
|
label = stringResource(state.value),
|
||||||
checked = state.isChecked,
|
checked = state.isChecked,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
val index = list.indexOf(state)
|
val mutableList = list.toMutableList()
|
||||||
if (index != -1) {
|
mutableList[index] = state.next() as CheckboxState.State<StringResource>
|
||||||
val mutableList = list.toMutableList()
|
list = mutableList.toList()
|
||||||
mutableList[index] = state.next() as CheckboxState.State<StringResource>
|
|
||||||
list = mutableList.toList()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,7 @@ fun MangaScreen(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
getMangaState: @Composable (Manga) -> State<Manga>,
|
getMangaState: @Composable (Manga) -> State<Manga>,
|
||||||
onClickSourceSettingsClicked: (() -> Unit)?,
|
onClickSourceSettingsClicked: (() -> Unit)?,
|
||||||
|
onClearManga: () -> Unit,
|
||||||
onOpenMangaFolder: (() -> Unit)?,
|
onOpenMangaFolder: (() -> Unit)?,
|
||||||
onRelatedMangasScreenClick: () -> Unit,
|
onRelatedMangasScreenClick: () -> Unit,
|
||||||
onRelatedMangaClick: (Manga) -> Unit,
|
onRelatedMangaClick: (Manga) -> Unit,
|
||||||
|
|
@ -269,6 +270,7 @@ fun MangaScreen(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
getMangaState = getMangaState,
|
getMangaState = getMangaState,
|
||||||
onClickSourceSettingsClicked = onClickSourceSettingsClicked,
|
onClickSourceSettingsClicked = onClickSourceSettingsClicked,
|
||||||
|
onClearManga = onClearManga,
|
||||||
onOpenMangaFolder = onOpenMangaFolder,
|
onOpenMangaFolder = onOpenMangaFolder,
|
||||||
onRelatedMangasScreenClick = onRelatedMangasScreenClick,
|
onRelatedMangasScreenClick = onRelatedMangasScreenClick,
|
||||||
onRelatedMangaClick = onRelatedMangaClick,
|
onRelatedMangaClick = onRelatedMangaClick,
|
||||||
|
|
@ -330,6 +332,7 @@ fun MangaScreen(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
getMangaState = getMangaState,
|
getMangaState = getMangaState,
|
||||||
onClickSourceSettingsClicked = onClickSourceSettingsClicked,
|
onClickSourceSettingsClicked = onClickSourceSettingsClicked,
|
||||||
|
onClearManga = onClearManga,
|
||||||
onOpenMangaFolder = onOpenMangaFolder,
|
onOpenMangaFolder = onOpenMangaFolder,
|
||||||
onRelatedMangasScreenClick = onRelatedMangasScreenClick,
|
onRelatedMangasScreenClick = onRelatedMangasScreenClick,
|
||||||
onRelatedMangaClick = onRelatedMangaClick,
|
onRelatedMangaClick = onRelatedMangaClick,
|
||||||
|
|
@ -408,6 +411,7 @@ private fun MangaScreenSmallImpl(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
getMangaState: @Composable ((Manga) -> State<Manga>),
|
getMangaState: @Composable ((Manga) -> State<Manga>),
|
||||||
onClickSourceSettingsClicked: (() -> Unit)?,
|
onClickSourceSettingsClicked: (() -> Unit)?,
|
||||||
|
onClearManga: () -> Unit,
|
||||||
onOpenMangaFolder: (() -> Unit)?,
|
onOpenMangaFolder: (() -> Unit)?,
|
||||||
onRelatedMangasScreenClick: () -> Unit,
|
onRelatedMangasScreenClick: () -> Unit,
|
||||||
onRelatedMangaClick: (Manga) -> Unit,
|
onRelatedMangaClick: (Manga) -> Unit,
|
||||||
|
|
@ -491,6 +495,7 @@ private fun MangaScreenSmallImpl(
|
||||||
onClickEditInfo = onEditInfoClicked.takeIf { state.manga.favorite },
|
onClickEditInfo = onEditInfoClicked.takeIf { state.manga.favorite },
|
||||||
// KMK -->
|
// KMK -->
|
||||||
onClickSourceSettings = onClickSourceSettingsClicked,
|
onClickSourceSettings = onClickSourceSettingsClicked,
|
||||||
|
onClearManga = onClearManga,
|
||||||
onOpenMangaFolder = onOpenMangaFolder,
|
onOpenMangaFolder = onOpenMangaFolder,
|
||||||
onClickRelatedMangas = onRelatedMangasScreenClick.takeIf {
|
onClickRelatedMangas = onRelatedMangasScreenClick.takeIf {
|
||||||
!expandRelatedMangas &&
|
!expandRelatedMangas &&
|
||||||
|
|
@ -875,6 +880,7 @@ private fun MangaScreenLargeImpl(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
getMangaState: @Composable ((Manga) -> State<Manga>),
|
getMangaState: @Composable ((Manga) -> State<Manga>),
|
||||||
onClickSourceSettingsClicked: (() -> Unit)?,
|
onClickSourceSettingsClicked: (() -> Unit)?,
|
||||||
|
onClearManga: () -> Unit,
|
||||||
onOpenMangaFolder: (() -> Unit)?,
|
onOpenMangaFolder: (() -> Unit)?,
|
||||||
onRelatedMangasScreenClick: () -> Unit,
|
onRelatedMangasScreenClick: () -> Unit,
|
||||||
onRelatedMangaClick: (Manga) -> Unit,
|
onRelatedMangaClick: (Manga) -> Unit,
|
||||||
|
|
@ -950,6 +956,7 @@ private fun MangaScreenLargeImpl(
|
||||||
onClickEditInfo = onEditInfoClicked.takeIf { state.manga.favorite },
|
onClickEditInfo = onEditInfoClicked.takeIf { state.manga.favorite },
|
||||||
// KMK -->
|
// KMK -->
|
||||||
onClickSourceSettings = onClickSourceSettingsClicked,
|
onClickSourceSettings = onClickSourceSettingsClicked,
|
||||||
|
onClearManga = onClearManga,
|
||||||
onOpenMangaFolder = onOpenMangaFolder,
|
onOpenMangaFolder = onOpenMangaFolder,
|
||||||
onClickRelatedMangas = onRelatedMangasScreenClick.takeIf {
|
onClickRelatedMangas = onRelatedMangasScreenClick.takeIf {
|
||||||
!expandRelatedMangas &&
|
!expandRelatedMangas &&
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
|
@ -19,10 +20,14 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
import tachiyomi.core.common.preference.CheckboxState
|
||||||
import tachiyomi.domain.manga.interactor.FetchInterval
|
import tachiyomi.domain.manga.interactor.FetchInterval
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.i18n.kmk.KMR
|
||||||
|
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||||
import tachiyomi.presentation.core.components.WheelTextPicker
|
import tachiyomi.presentation.core.components.WheelTextPicker
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
|
|
@ -62,6 +67,65 @@ fun DeleteChaptersDialog(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
@Composable
|
||||||
|
fun ClearMangaDialog(
|
||||||
|
isMergedSource: Boolean,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onConfirm: (Boolean, Boolean) -> Unit,
|
||||||
|
) {
|
||||||
|
var list by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
buildList<CheckboxState.State<StringResource>> {
|
||||||
|
add(CheckboxState.State.None(KMR.strings.downloaded_data))
|
||||||
|
add(CheckboxState.State.None(KMR.strings.chapters_from_database))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
enabled = list.any { it.isChecked },
|
||||||
|
onClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
onConfirm(
|
||||||
|
list[0].isChecked,
|
||||||
|
list[1].isChecked,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(MR.strings.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Text(text = stringResource(MR.strings.action_remove))
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
list.forEachIndexed { index, state ->
|
||||||
|
LabeledCheckbox(
|
||||||
|
label = stringResource(state.value),
|
||||||
|
checked = state.isChecked,
|
||||||
|
enabled = index != 0 || !isMergedSource,
|
||||||
|
onCheckedChange = {
|
||||||
|
val mutableList = list.toMutableList()
|
||||||
|
mutableList[index] = state.next() as CheckboxState.State<StringResource>
|
||||||
|
list = mutableList.toList()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SetIntervalDialog(
|
fun SetIntervalDialog(
|
||||||
interval: Int,
|
interval: Int,
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ fun MangaToolbar(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
onClickRelatedMangas: (() -> Unit)?,
|
onClickRelatedMangas: (() -> Unit)?,
|
||||||
onClickSourceSettings: (() -> Unit)?,
|
onClickSourceSettings: (() -> Unit)?,
|
||||||
|
onClearManga: () -> Unit,
|
||||||
onOpenMangaFolder: (() -> Unit)?,
|
onOpenMangaFolder: (() -> Unit)?,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
onClickRecommend: (() -> Unit)?,
|
onClickRecommend: (() -> Unit)?,
|
||||||
|
|
@ -243,6 +244,12 @@ fun MangaToolbar(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(KMR.strings.action_clear_manga),
|
||||||
|
onClick = onClearManga,
|
||||||
|
),
|
||||||
|
)
|
||||||
if (onClickSourceSettings != null) {
|
if (onClickSourceSettings != null) {
|
||||||
add(
|
add(
|
||||||
AppBar.OverflowAction(
|
AppBar.OverflowAction(
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import tachiyomi.domain.download.service.DownloadPreferences
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.source.local.isLocal
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
|
@ -277,6 +278,10 @@ class DownloadManager(
|
||||||
provider.findMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source)?.delete()
|
provider.findMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source)?.delete()
|
||||||
cache.removeManga(manga)
|
cache.removeManga(manga)
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
if (source.isLocal()) return@launchIO
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
// Delete source directory if empty
|
// Delete source directory if empty
|
||||||
val sourceDir = provider.findSourceDir(source)
|
val sourceDir = provider.findSourceDir(source)
|
||||||
if (sourceDir?.listFiles()?.isEmpty() == true) {
|
if (sourceDir?.listFiles()?.isEmpty() == true) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import tachiyomi.domain.chapter.model.Chapter
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.storage.service.StorageManager
|
import tachiyomi.domain.storage.service.StorageManager
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.source.local.isLocal
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
@ -74,7 +75,13 @@ class DownloadProvider(
|
||||||
* @param source the source to query.
|
* @param source the source to query.
|
||||||
*/
|
*/
|
||||||
fun findSourceDir(source: Source): UniFile? {
|
fun findSourceDir(source: Source): UniFile? {
|
||||||
return downloadsDir?.findFile(getSourceDirName(source))
|
// KMK -->
|
||||||
|
return if (source.isLocal()) {
|
||||||
|
storageManager.getLocalSourceDirectory()
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
downloadsDir?.findFile(getSourceDirName(source))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -113,9 +120,22 @@ class DownloadProvider(
|
||||||
fun findChapterDirs(chapters: List<Chapter>, manga: Manga, source: Source): Pair<UniFile?, List<UniFile>> {
|
fun findChapterDirs(chapters: List<Chapter>, manga: Manga, source: Source): Pair<UniFile?, List<UniFile>> {
|
||||||
val mangaDir = findMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source) ?: return null to emptyList()
|
val mangaDir = findMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source) ?: return null to emptyList()
|
||||||
return mangaDir to chapters.mapNotNull { chapter ->
|
return mangaDir to chapters.mapNotNull { chapter ->
|
||||||
getValidChapterDirNames(chapter.name, chapter.scanlator).asSequence()
|
// KMK -->
|
||||||
.mapNotNull { mangaDir.findFile(it) }
|
if (source.isLocal()) {
|
||||||
.firstOrNull()
|
val splitUrl = chapter.url.split('/', limit = 2)
|
||||||
|
if (splitUrl.size < 2) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
val (mangaDirName, chapterDirName) = splitUrl
|
||||||
|
mangaDir.findFile(chapterDirName)
|
||||||
|
?: storageManager.getLocalSourceDirectory()?.findFile(mangaDirName)?.findFile(chapterDirName)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
getValidChapterDirNames(chapter.name, chapter.scanlator).asSequence()
|
||||||
|
.mapNotNull { mangaDir.findFile(it) }
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ import eu.kanade.presentation.manga.ChapterSettingsDialog
|
||||||
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
import eu.kanade.presentation.manga.DuplicateMangaDialog
|
||||||
import eu.kanade.presentation.manga.EditCoverAction
|
import eu.kanade.presentation.manga.EditCoverAction
|
||||||
import eu.kanade.presentation.manga.MangaScreen
|
import eu.kanade.presentation.manga.MangaScreen
|
||||||
|
import eu.kanade.presentation.manga.components.ClearMangaDialog
|
||||||
import eu.kanade.presentation.manga.components.DeleteChaptersDialog
|
import eu.kanade.presentation.manga.components.DeleteChaptersDialog
|
||||||
import eu.kanade.presentation.manga.components.MangaCoverDialog
|
import eu.kanade.presentation.manga.components.MangaCoverDialog
|
||||||
import eu.kanade.presentation.manga.components.ScanlatorFilterDialog
|
import eu.kanade.presentation.manga.components.ScanlatorFilterDialog
|
||||||
|
|
@ -65,6 +66,7 @@ import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.isLocalOrStub
|
import eu.kanade.tachiyomi.source.isLocalOrStub
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||||
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
import eu.kanade.tachiyomi.ui.browse.BulkFavoriteScreenModel
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreen
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
||||||
|
|
@ -418,8 +420,9 @@ class MangaScreen(
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}.takeIf { isConfigurableSource },
|
}.takeIf { isConfigurableSource },
|
||||||
|
onClearManga = { screenModel.showClearMangaDialog(successState.source is MergedSource) },
|
||||||
onOpenMangaFolder = { screenModel.openMangaFolder() }
|
onOpenMangaFolder = { screenModel.openMangaFolder() }
|
||||||
.takeIf { successState.source !is StubSource },
|
.takeIf { successState.source !is StubSource && successState.source !is MergedSource },
|
||||||
onRelatedMangasScreenClick = {
|
onRelatedMangasScreenClick = {
|
||||||
if (successState.isRelatedMangasFetched == null) {
|
if (successState.isRelatedMangasFetched == null) {
|
||||||
scope.launchIO { screenModel.fetchRelatedMangasFromSource(onDemand = true) }
|
scope.launchIO { screenModel.fetchRelatedMangasFromSource(onDemand = true) }
|
||||||
|
|
@ -634,6 +637,15 @@ class MangaScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
// KMK -->
|
||||||
|
is MangaScreenModel.Dialog.ClearManga -> {
|
||||||
|
ClearMangaDialog(
|
||||||
|
isMergedSource = dialog.isMergedSource,
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
onConfirm = screenModel::clearManga,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showScanlatorsDialog) {
|
if (showScanlatorsDialog) {
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ import tachiyomi.core.common.util.system.logcat
|
||||||
import tachiyomi.domain.category.interactor.GetCategories
|
import tachiyomi.domain.category.interactor.GetCategories
|
||||||
import tachiyomi.domain.category.interactor.SetMangaCategories
|
import tachiyomi.domain.category.interactor.SetMangaCategories
|
||||||
import tachiyomi.domain.category.model.Category
|
import tachiyomi.domain.category.model.Category
|
||||||
|
import tachiyomi.domain.chapter.interactor.DeleteChapters
|
||||||
import tachiyomi.domain.chapter.interactor.GetMergedChaptersByMangaId
|
import tachiyomi.domain.chapter.interactor.GetMergedChaptersByMangaId
|
||||||
import tachiyomi.domain.chapter.interactor.SetMangaDefaultChapterFlags
|
import tachiyomi.domain.chapter.interactor.SetMangaDefaultChapterFlags
|
||||||
import tachiyomi.domain.chapter.interactor.UpdateChapter
|
import tachiyomi.domain.chapter.interactor.UpdateChapter
|
||||||
|
|
@ -231,6 +232,7 @@ class MangaScreenModel(
|
||||||
private val deleteLibraryUpdateErrors: DeleteLibraryUpdateErrors = Injekt.get(),
|
private val deleteLibraryUpdateErrors: DeleteLibraryUpdateErrors = Injekt.get(),
|
||||||
private val insertLibraryUpdateErrors: InsertLibraryUpdateErrors = Injekt.get(),
|
private val insertLibraryUpdateErrors: InsertLibraryUpdateErrors = Injekt.get(),
|
||||||
private val insertLibraryUpdateErrorMessages: InsertLibraryUpdateErrorMessages = Injekt.get(),
|
private val insertLibraryUpdateErrorMessages: InsertLibraryUpdateErrorMessages = Injekt.get(),
|
||||||
|
private val deleteChaptersFromDb: DeleteChapters = Injekt.get(),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) : StateScreenModel<MangaScreenModel.State>(State.Loading) {
|
) : StateScreenModel<MangaScreenModel.State>(State.Loading) {
|
||||||
|
|
||||||
|
|
@ -1524,6 +1526,12 @@ class MangaScreenModel(
|
||||||
ignoreCategoryExclusion = true,
|
ignoreCategoryExclusion = true,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
|
// KMK -->
|
||||||
|
if (source?.isLocal() == true) {
|
||||||
|
// Refresh chapters state for Local source
|
||||||
|
fetchChaptersFromSource()
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
logcat(LogPriority.ERROR, e)
|
logcat(LogPriority.ERROR, e)
|
||||||
|
|
@ -1531,6 +1539,51 @@ class MangaScreenModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
fun clearManga(
|
||||||
|
deleteDownload: Boolean,
|
||||||
|
removeChapters: Boolean,
|
||||||
|
) {
|
||||||
|
if (deleteDownload) {
|
||||||
|
deleteDownloadedData()
|
||||||
|
}
|
||||||
|
if (removeChapters) {
|
||||||
|
removeChaptersDatabase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteDownloadedData() {
|
||||||
|
screenModelScope.launchNonCancellable {
|
||||||
|
try {
|
||||||
|
successState?.let { state ->
|
||||||
|
downloadManager.deleteManga(
|
||||||
|
manga = state.manga,
|
||||||
|
source = state.source,
|
||||||
|
removeQueued = true,
|
||||||
|
)
|
||||||
|
if (source?.isLocal() == true) {
|
||||||
|
// Refresh chapters state for Local source
|
||||||
|
fetchChaptersFromSource()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeChaptersDatabase() {
|
||||||
|
screenModelScope.launchNonCancellable {
|
||||||
|
try {
|
||||||
|
successState?.chapters?.map { it.id }
|
||||||
|
?.let { deleteChaptersFromDb.await(it) }
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
private fun downloadNewChapters(chapters: List<Chapter>) {
|
private fun downloadNewChapters(chapters: List<Chapter>) {
|
||||||
screenModelScope.launchNonCancellable {
|
screenModelScope.launchNonCancellable {
|
||||||
val manga = successState?.manga ?: return@launchNonCancellable
|
val manga = successState?.manga ?: return@launchNonCancellable
|
||||||
|
|
@ -1822,6 +1875,10 @@ class MangaScreenModel(
|
||||||
data class EditMergedSettings(val mergedData: MergedMangaData) : Dialog
|
data class EditMergedSettings(val mergedData: MergedMangaData) : Dialog
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
data class ClearManga(val isMergedSource: Boolean) : Dialog
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
data object SettingsSheet : Dialog
|
data object SettingsSheet : Dialog
|
||||||
data object TrackSheet : Dialog
|
data object TrackSheet : Dialog
|
||||||
data object FullCover : Dialog
|
data object FullCover : Dialog
|
||||||
|
|
@ -1883,6 +1940,12 @@ class MangaScreenModel(
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
fun showClearMangaDialog(isMergedSource: Boolean) {
|
||||||
|
updateSuccessState { it.copy(dialog = Dialog.ClearManga(isMergedSource)) }
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
sealed interface State {
|
sealed interface State {
|
||||||
@Immutable
|
@Immutable
|
||||||
data object Loading : State
|
data object Loading : State
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@
|
||||||
<string name="action_show_hidden_categories">Show hidden categories</string>
|
<string name="action_show_hidden_categories">Show hidden categories</string>
|
||||||
<string name="action_panorama_cover">Panorama cover</string>
|
<string name="action_panorama_cover">Panorama cover</string>
|
||||||
<string name="action_open_folder">Open folder</string>
|
<string name="action_open_folder">Open folder</string>
|
||||||
|
<string name="action_clear_manga">Clear manga</string>
|
||||||
<string name="action_update">Update</string>
|
<string name="action_update">Update</string>
|
||||||
|
|
||||||
<!-- Reader -->
|
<!-- Reader -->
|
||||||
<!-- Reader Actions -->
|
<!-- Reader Actions -->
|
||||||
<string name="action_copy_to_clipboard_first_page">Copy first page to clipboard</string>
|
<string name="action_copy_to_clipboard_first_page">Copy first page to clipboard</string>
|
||||||
|
|
@ -121,6 +123,9 @@
|
||||||
<string name="action_skip_duplicate_manga">Skip it</string>
|
<string name="action_skip_duplicate_manga">Skip it</string>
|
||||||
<string name="action_allow_all_duplicate_manga">Allow all</string>
|
<string name="action_allow_all_duplicate_manga">Allow all</string>
|
||||||
<string name="action_skip_all_duplicate_manga">Skip all</string>
|
<string name="action_skip_all_duplicate_manga">Skip all</string>
|
||||||
|
<string name="downloaded_data">Downloaded data</string>
|
||||||
|
<string name="chapters_from_database">Chapters & History from Database</string>
|
||||||
|
|
||||||
<!--UpdateCheck-->
|
<!--UpdateCheck-->
|
||||||
<string name="update_check_try_now">Try now</string>
|
<string name="update_check_try_now">Try now</string>
|
||||||
<string name="update_completed">Update completed</string>
|
<string name="update_completed">Update completed</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue