mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-27 16:26:29 +03:00
Add different download options within the Library (#8267)
* feat: add download options to library * feat: use max instead of min * feat: remove download all option * feat: applied requested changes + rename some functions * feat: merge downloadAllUnreadChapters and downloadUnreadChapters into one function * Apply suggestions from code review Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> * feat: apply lint suggestions + fix code feat: apply lint suggestions + fix code * feat: revert onClickDownload back to onDownloadClicked Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
parent
7818885406
commit
50b17d5d34
6 changed files with 151 additions and 63 deletions
|
@ -0,0 +1,66 @@
|
||||||
|
package eu.kanade.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DownloadDropdownMenu(
|
||||||
|
expanded: Boolean,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onDownloadClicked: (DownloadAction) -> Unit,
|
||||||
|
includeDownloadAllOption: Boolean = true,
|
||||||
|
) {
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.download_1)) },
|
||||||
|
onClick = {
|
||||||
|
onDownloadClicked(DownloadAction.NEXT_1_CHAPTER)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.download_5)) },
|
||||||
|
onClick = {
|
||||||
|
onDownloadClicked(DownloadAction.NEXT_5_CHAPTERS)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.download_10)) },
|
||||||
|
onClick = {
|
||||||
|
onDownloadClicked(DownloadAction.NEXT_10_CHAPTERS)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.download_custom)) },
|
||||||
|
onClick = {
|
||||||
|
onDownloadClicked(DownloadAction.CUSTOM)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.download_unread)) },
|
||||||
|
onClick = {
|
||||||
|
onDownloadClicked(DownloadAction.UNREAD_CHAPTERS)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (includeDownloadAllOption) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.download_all)) },
|
||||||
|
onClick = {
|
||||||
|
onDownloadClicked(DownloadAction.ALL_CHAPTERS)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
@ -37,8 +38,10 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
@ -48,6 +51,7 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -211,7 +215,7 @@ fun LibraryBottomActionMenu(
|
||||||
onChangeCategoryClicked: (() -> Unit)?,
|
onChangeCategoryClicked: (() -> Unit)?,
|
||||||
onMarkAsReadClicked: (() -> Unit)?,
|
onMarkAsReadClicked: (() -> Unit)?,
|
||||||
onMarkAsUnreadClicked: (() -> Unit)?,
|
onMarkAsUnreadClicked: (() -> Unit)?,
|
||||||
onDownloadClicked: (() -> Unit)?,
|
onDownloadClicked: ((DownloadAction) -> Unit)?,
|
||||||
onDeleteClicked: (() -> Unit)?,
|
onDeleteClicked: (() -> Unit)?,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
|
@ -270,13 +274,23 @@ fun LibraryBottomActionMenu(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (onDownloadClicked != null) {
|
if (onDownloadClicked != null) {
|
||||||
Button(
|
Box {
|
||||||
|
var downloadExpanded by remember { mutableStateOf(false) }
|
||||||
|
this@Row.Button(
|
||||||
title = stringResource(R.string.action_download),
|
title = stringResource(R.string.action_download),
|
||||||
icon = Icons.Outlined.Download,
|
icon = Icons.Outlined.Download,
|
||||||
toConfirm = confirm[3],
|
toConfirm = confirm[3],
|
||||||
onLongClick = { onLongClickItem(3) },
|
onLongClick = { onLongClickItem(3) },
|
||||||
onClick = onDownloadClicked,
|
onClick = { downloadExpanded = !downloadExpanded },
|
||||||
)
|
)
|
||||||
|
val onDismissRequest = { downloadExpanded = false }
|
||||||
|
DownloadDropdownMenu(
|
||||||
|
expanded = downloadExpanded,
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
onDownloadClicked = onDownloadClicked,
|
||||||
|
includeDownloadAllOption = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (onDeleteClicked != null) {
|
if (onDeleteClicked != null) {
|
||||||
Button(
|
Button(
|
||||||
|
|
|
@ -18,6 +18,7 @@ import eu.kanade.presentation.components.LoadingScreen
|
||||||
import eu.kanade.presentation.components.Scaffold
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.library.components.LibraryContent
|
import eu.kanade.presentation.library.components.LibraryContent
|
||||||
import eu.kanade.presentation.library.components.LibraryToolbar
|
import eu.kanade.presentation.library.components.LibraryToolbar
|
||||||
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
||||||
import eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
|
import eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
|
||||||
|
@ -30,7 +31,7 @@ fun LibraryScreen(
|
||||||
onChangeCategoryClicked: () -> Unit,
|
onChangeCategoryClicked: () -> Unit,
|
||||||
onMarkAsReadClicked: () -> Unit,
|
onMarkAsReadClicked: () -> Unit,
|
||||||
onMarkAsUnreadClicked: () -> Unit,
|
onMarkAsUnreadClicked: () -> Unit,
|
||||||
onDownloadClicked: () -> Unit,
|
onDownloadClicked: (DownloadAction) -> Unit,
|
||||||
onDeleteClicked: () -> Unit,
|
onDeleteClicked: () -> Unit,
|
||||||
onClickUnselectAll: () -> Unit,
|
onClickUnselectAll: () -> Unit,
|
||||||
onClickSelectAll: () -> Unit,
|
onClickSelectAll: () -> Unit,
|
||||||
|
|
|
@ -27,6 +27,7 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.presentation.components.AppStateBanners
|
import eu.kanade.presentation.components.AppStateBanners
|
||||||
|
import eu.kanade.presentation.components.DownloadDropdownMenu
|
||||||
import eu.kanade.presentation.components.DropdownMenu
|
import eu.kanade.presentation.components.DropdownMenu
|
||||||
import eu.kanade.presentation.components.OverflowMenu
|
import eu.kanade.presentation.components.OverflowMenu
|
||||||
import eu.kanade.presentation.manga.DownloadAction
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
|
@ -99,53 +100,11 @@ fun MangaToolbar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val onDismissRequest = { onDownloadExpanded(false) }
|
val onDismissRequest = { onDownloadExpanded(false) }
|
||||||
DropdownMenu(
|
DownloadDropdownMenu(
|
||||||
expanded = downloadExpanded,
|
expanded = downloadExpanded,
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
) {
|
onDownloadClicked = onClickDownload,
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = stringResource(R.string.download_1)) },
|
|
||||||
onClick = {
|
|
||||||
onClickDownload(DownloadAction.NEXT_1_CHAPTER)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = stringResource(R.string.download_5)) },
|
|
||||||
onClick = {
|
|
||||||
onClickDownload(DownloadAction.NEXT_5_CHAPTERS)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = stringResource(R.string.download_10)) },
|
|
||||||
onClick = {
|
|
||||||
onClickDownload(DownloadAction.NEXT_10_CHAPTERS)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = stringResource(R.string.download_custom)) },
|
|
||||||
onClick = {
|
|
||||||
onClickDownload(DownloadAction.CUSTOM)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = stringResource(R.string.download_unread)) },
|
|
||||||
onClick = {
|
|
||||||
onClickDownload(DownloadAction.UNREAD_CHAPTERS)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = stringResource(R.string.download_all)) },
|
|
||||||
onClick = {
|
|
||||||
onClickDownload(DownloadAction.ALL_CHAPTERS)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.presentation.components.ChangeCategoryDialog
|
import eu.kanade.presentation.components.ChangeCategoryDialog
|
||||||
import eu.kanade.presentation.components.DeleteLibraryMangaDialog
|
import eu.kanade.presentation.components.DeleteLibraryMangaDialog
|
||||||
import eu.kanade.presentation.library.LibraryScreen
|
import eu.kanade.presentation.library.LibraryScreen
|
||||||
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
|
import eu.kanade.presentation.manga.components.DownloadCustomAmountDialog
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
||||||
|
@ -54,7 +56,7 @@ class LibraryController(
|
||||||
onChangeCategoryClicked = ::showMangaCategoriesDialog,
|
onChangeCategoryClicked = ::showMangaCategoriesDialog,
|
||||||
onMarkAsReadClicked = { markReadStatus(true) },
|
onMarkAsReadClicked = { markReadStatus(true) },
|
||||||
onMarkAsUnreadClicked = { markReadStatus(false) },
|
onMarkAsUnreadClicked = { markReadStatus(false) },
|
||||||
onDownloadClicked = ::downloadUnreadChapters,
|
onDownloadClicked = ::runDownloadChapterAction,
|
||||||
onDeleteClicked = ::showDeleteMangaDialog,
|
onDeleteClicked = ::showDeleteMangaDialog,
|
||||||
onClickFilter = ::showSettingsSheet,
|
onClickFilter = ::showSettingsSheet,
|
||||||
onClickRefresh = {
|
onClickRefresh = {
|
||||||
|
@ -101,6 +103,16 @@ class LibraryController(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is LibraryPresenter.Dialog.DownloadCustomAmount -> {
|
||||||
|
DownloadCustomAmountDialog(
|
||||||
|
maxAmount = dialog.max,
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
onConfirm = { amount ->
|
||||||
|
presenter.downloadUnreadChapters(dialog.manga, amount)
|
||||||
|
presenter.clearSelection()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
null -> {}
|
null -> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,9 +230,22 @@ class LibraryController(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun downloadUnreadChapters() {
|
private fun runDownloadChapterAction(action: DownloadAction) {
|
||||||
val mangaList = presenter.selection.toList()
|
val mangas = presenter.selection.map { it.manga }.toList()
|
||||||
presenter.downloadUnreadChapters(mangaList.map { it.manga })
|
when (action) {
|
||||||
|
DownloadAction.NEXT_1_CHAPTER -> presenter.downloadUnreadChapters(mangas, 1)
|
||||||
|
DownloadAction.NEXT_5_CHAPTERS -> presenter.downloadUnreadChapters(mangas, 5)
|
||||||
|
DownloadAction.NEXT_10_CHAPTERS -> presenter.downloadUnreadChapters(mangas, 10)
|
||||||
|
DownloadAction.UNREAD_CHAPTERS -> presenter.downloadUnreadChapters(mangas, null)
|
||||||
|
DownloadAction.CUSTOM -> {
|
||||||
|
presenter.dialog = LibraryPresenter.Dialog.DownloadCustomAmount(
|
||||||
|
mangas,
|
||||||
|
presenter.selection.maxOf { it.unreadCount }.toInt(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
presenter.clearSelection()
|
presenter.clearSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
||||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||||
|
import eu.kanade.domain.chapter.model.Chapter
|
||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.library.model.LibraryManga
|
import eu.kanade.domain.library.model.LibraryManga
|
||||||
import eu.kanade.domain.library.model.LibrarySort
|
import eu.kanade.domain.library.model.LibrarySort
|
||||||
|
@ -39,11 +40,13 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
|
import eu.kanade.tachiyomi.data.database.models.toDomainManga
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
import eu.kanade.tachiyomi.util.chapter.getChapterSort
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
|
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
|
||||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
|
@ -401,18 +404,37 @@ class LibraryPresenter(
|
||||||
return mangaCategories.flatten().distinct().subtract(common)
|
return mangaCategories.flatten().distinct().subtract(common)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun shouldDownloadChapter(manga: Manga, chapter: Chapter): Boolean {
|
||||||
|
val activeDownload = downloadManager.queue.find { chapter.id == it.chapter.id }
|
||||||
|
val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
|
||||||
|
val state = when {
|
||||||
|
activeDownload != null -> activeDownload.status
|
||||||
|
downloaded -> Download.State.DOWNLOADED
|
||||||
|
else -> Download.State.NOT_DOWNLOADED
|
||||||
|
}
|
||||||
|
return state == Download.State.NOT_DOWNLOADED
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getNotDownloadedUnreadChapters(manga: Manga): List<Chapter> {
|
||||||
|
return getChapterByMangaId.await(manga.id)
|
||||||
|
.filter { chapter ->
|
||||||
|
!chapter.read && shouldDownloadChapter(manga, chapter)
|
||||||
|
}
|
||||||
|
.sortedWith(getChapterSort(manga, sortDescending = false))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queues all unread chapters from the given list of manga.
|
* Queues the amount specified of unread chapters from the list of mangas given.
|
||||||
*
|
*
|
||||||
* @param mangas the list of manga.
|
* @param mangas the list of manga.
|
||||||
|
* @param amount the amount to queue or null to queue all
|
||||||
*/
|
*/
|
||||||
fun downloadUnreadChapters(mangas: List<Manga>) {
|
fun downloadUnreadChapters(mangas: List<Manga>, amount: Int?) {
|
||||||
presenterScope.launchNonCancellable {
|
presenterScope.launchNonCancellable {
|
||||||
mangas.forEach { manga ->
|
mangas.forEach { manga ->
|
||||||
val chapters = getChapterByMangaId.await(manga.id)
|
val chapters = getNotDownloadedUnreadChapters(manga)
|
||||||
.filter { !it.read }
|
.let { if (amount != null) it.take(amount) else it }
|
||||||
.map { it.toDbChapter() }
|
.map { it.toDbChapter() }
|
||||||
|
|
||||||
downloadManager.downloadChapters(manga, chapters)
|
downloadManager.downloadChapters(manga, chapters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,5 +626,6 @@ class LibraryPresenter(
|
||||||
sealed class Dialog {
|
sealed class Dialog {
|
||||||
data class ChangeCategory(val manga: List<Manga>, val initialSelection: List<CheckboxState<Category>>) : Dialog()
|
data class ChangeCategory(val manga: List<Manga>, val initialSelection: List<CheckboxState<Category>>) : Dialog()
|
||||||
data class DeleteManga(val manga: List<Manga>) : Dialog()
|
data class DeleteManga(val manga: List<Manga>) : Dialog()
|
||||||
|
data class DownloadCustomAmount(val manga: List<Manga>, val max: Int) : Dialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue