Support mass migration for selected library items (mihonapp/mihon#2336)
(cherry picked from commit 982ebcf777215c90584ad28fae79e9ca8a22a951) Co-authored-by: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>
This commit is contained in:
parent
9a3934eadf
commit
9cbd46947b
8 changed files with 158 additions and 185 deletions
|
|
@ -5,7 +5,6 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import eu.kanade.presentation.manga.DownloadAction
|
import eu.kanade.presentation.manga.DownloadAction
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
|
@ -18,9 +17,26 @@ fun DownloadDropdownMenu(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
onDownloadClicked: (DownloadAction) -> Unit,
|
onDownloadClicked: (DownloadAction) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
// KMK -->
|
offset: DpOffset = /* KMK --> */ DefaultDropdownMenuOffset, /* KMK <-- */
|
||||||
offset: DpOffset = DpOffset(0.dp, 0.dp),
|
) {
|
||||||
// KMK <--
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
modifier = modifier,
|
||||||
|
offset = offset,
|
||||||
|
content = {
|
||||||
|
DownloadDropdownMenuItems(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
onDownloadClicked = onDownloadClicked,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DownloadDropdownMenuItems(
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onDownloadClicked: (DownloadAction) -> Unit,
|
||||||
) {
|
) {
|
||||||
val options = persistentListOf(
|
val options = persistentListOf(
|
||||||
DownloadAction.NEXT_1_CHAPTER to pluralStringResource(MR.plurals.download_amount, 1, 1),
|
DownloadAction.NEXT_1_CHAPTER to pluralStringResource(MR.plurals.download_amount, 1, 1),
|
||||||
|
|
@ -30,22 +46,13 @@ fun DownloadDropdownMenu(
|
||||||
DownloadAction.UNREAD_CHAPTERS to stringResource(MR.strings.download_unread),
|
DownloadAction.UNREAD_CHAPTERS to stringResource(MR.strings.download_unread),
|
||||||
)
|
)
|
||||||
|
|
||||||
DropdownMenu(
|
options.forEach { (downloadAction, string) ->
|
||||||
expanded = expanded,
|
DropdownMenuItem(
|
||||||
onDismissRequest = onDismissRequest,
|
text = { Text(text = string) },
|
||||||
modifier = modifier,
|
onClick = {
|
||||||
// KMK -->
|
onDownloadClicked(downloadAction)
|
||||||
offset = offset,
|
onDismissRequest()
|
||||||
// KMK <--
|
},
|
||||||
) {
|
)
|
||||||
options.map { (downloadAction, string) ->
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text = string) },
|
|
||||||
onClick = {
|
|
||||||
onDownloadClicked(downloadAction)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import androidx.compose.material3.DropdownMenu as ComposeDropdownMenu
|
import androidx.compose.material3.DropdownMenu as ComposeDropdownMenu
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
val DefaultDropdownMenuOffset = DpOffset(8.dp, (-56).dp)
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DropdownMenu but overlaps anchor and has width constraints to better
|
* DropdownMenu but overlaps anchor and has width constraints to better
|
||||||
* match non-Compose implementation.
|
* match non-Compose implementation.
|
||||||
|
|
@ -34,7 +38,7 @@ fun DropdownMenu(
|
||||||
expanded: Boolean,
|
expanded: Boolean,
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
offset: DpOffset = DpOffset(8.dp, (-56).dp),
|
offset: DpOffset = /* KMK --> */ DefaultDropdownMenuOffset, /* KMK <-- */
|
||||||
scrollState: ScrollState = rememberScrollState(),
|
scrollState: ScrollState = rememberScrollState(),
|
||||||
properties: PopupProperties = PopupProperties(focusable = true),
|
properties: PopupProperties = PopupProperties(focusable = true),
|
||||||
content: @Composable ColumnScope.() -> Unit,
|
content: @Composable ColumnScope.() -> Unit,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
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
|
||||||
|
|
@ -29,8 +30,8 @@ import androidx.compose.material.icons.outlined.BookmarkRemove
|
||||||
import androidx.compose.material.icons.outlined.Delete
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material.icons.outlined.DoneAll
|
import androidx.compose.material.icons.outlined.DoneAll
|
||||||
import androidx.compose.material.icons.outlined.Download
|
import androidx.compose.material.icons.outlined.Download
|
||||||
import androidx.compose.material.icons.outlined.Merge
|
|
||||||
import androidx.compose.material.icons.outlined.MoreVert
|
import androidx.compose.material.icons.outlined.MoreVert
|
||||||
|
import androidx.compose.material.icons.outlined.Refresh
|
||||||
import androidx.compose.material.icons.outlined.RemoveDone
|
import androidx.compose.material.icons.outlined.RemoveDone
|
||||||
import androidx.compose.material.icons.outlined.SwapCalls
|
import androidx.compose.material.icons.outlined.SwapCalls
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
|
@ -211,7 +212,7 @@ internal fun RowScope.Button(
|
||||||
label = "color",
|
label = "color",
|
||||||
)
|
)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
Column(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(48.dp)
|
.size(48.dp)
|
||||||
.weight(animatedWeight)
|
.weight(animatedWeight)
|
||||||
|
|
@ -221,30 +222,34 @@ internal fun RowScope.Button(
|
||||||
onLongClick = onLongClick,
|
onLongClick = onLongClick,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.Center,
|
contentAlignment = Alignment.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Column(
|
||||||
imageVector = icon,
|
verticalArrangement = Arrangement.Center,
|
||||||
contentDescription = title,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
// KMK -->
|
|
||||||
tint = animatedColor,
|
|
||||||
// KMK <--
|
|
||||||
)
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = toConfirm,
|
|
||||||
enter = expandVertically(expandFrom = Alignment.Top) + fadeIn(),
|
|
||||||
exit = shrinkVertically(shrinkTowards = Alignment.Top) + fadeOut(),
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Icon(
|
||||||
text = title,
|
imageVector = icon,
|
||||||
overflow = TextOverflow.Visible,
|
contentDescription = title,
|
||||||
maxLines = 1,
|
|
||||||
style = MaterialTheme.typography.labelSmall,
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
color = animatedColor,
|
tint = animatedColor,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = toConfirm,
|
||||||
|
enter = expandVertically(expandFrom = Alignment.Top) + fadeIn(),
|
||||||
|
exit = shrinkVertically(shrinkTowards = Alignment.Top) + fadeOut(),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
overflow = TextOverflow.Visible,
|
||||||
|
maxLines = 1,
|
||||||
|
style = MaterialTheme.typography.labelSmall,
|
||||||
|
// KMK -->
|
||||||
|
color = animatedColor,
|
||||||
|
// KMK <--
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
content?.invoke()
|
content?.invoke()
|
||||||
}
|
}
|
||||||
|
|
@ -258,17 +263,17 @@ fun LibraryBottomActionMenu(
|
||||||
onMarkAsUnreadClicked: () -> Unit,
|
onMarkAsUnreadClicked: () -> Unit,
|
||||||
onDownloadClicked: ((DownloadAction) -> Unit)?,
|
onDownloadClicked: ((DownloadAction) -> Unit)?,
|
||||||
onDeleteClicked: () -> Unit,
|
onDeleteClicked: () -> Unit,
|
||||||
|
onMigrateClicked: () -> Unit,
|
||||||
|
// KMK -->
|
||||||
|
onMergeClicked: () -> Unit,
|
||||||
|
onSelectionUpdateClicked: () -> Unit,
|
||||||
|
// KMK <--
|
||||||
// SY -->
|
// SY -->
|
||||||
onClickCleanTitles: (() -> Unit)?,
|
onClickCleanTitles: (() -> Unit)?,
|
||||||
onClickMigrate: (() -> Unit)?,
|
|
||||||
onClickCollectRecommendations: (() -> Unit)?,
|
onClickCollectRecommendations: (() -> Unit)?,
|
||||||
onClickAddToMangaDex: (() -> Unit)?,
|
onClickAddToMangaDex: (() -> Unit)?,
|
||||||
onClickResetInfo: (() -> Unit)?,
|
onClickResetInfo: (() -> Unit)?,
|
||||||
// SY <--
|
// SY <--
|
||||||
// KMK -->
|
|
||||||
onClickMerge: (() -> Unit)?,
|
|
||||||
onClickRefreshSelected: (() -> Unit)?,
|
|
||||||
// KMK <--
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
|
|
@ -283,34 +288,17 @@ fun LibraryBottomActionMenu(
|
||||||
color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
) {
|
) {
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
val confirm =
|
val confirm = remember { mutableStateListOf(false, false, false, false, false, false /* SY --> */, false /* SY <-- */) }
|
||||||
remember {
|
|
||||||
mutableStateListOf(false, false, false, false, false /* SY --> */, false, false, false /* SY <-- */)
|
|
||||||
}
|
|
||||||
var resetJob: Job? = remember { null }
|
var resetJob: Job? = remember { null }
|
||||||
val onLongClickItem: (Int) -> Unit = { toConfirmIndex ->
|
val onLongClickItem: (Int) -> Unit = { toConfirmIndex ->
|
||||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
(0..<8).forEach { i -> confirm[i] = i == toConfirmIndex }
|
(0..<confirm.size).forEach { i -> confirm[i] = i == toConfirmIndex }
|
||||||
resetJob?.cancel()
|
resetJob?.cancel()
|
||||||
resetJob = scope.launch {
|
resetJob = scope.launch {
|
||||||
delay(1.seconds)
|
delay(1.seconds)
|
||||||
if (isActive) confirm[toConfirmIndex] = false
|
if (isActive) confirm[toConfirmIndex] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SY -->
|
|
||||||
val showOverflow = onClickCleanTitles != null ||
|
|
||||||
onClickAddToMangaDex != null ||
|
|
||||||
onClickResetInfo != null ||
|
|
||||||
// KMK -->
|
|
||||||
onClickMigrate != null ||
|
|
||||||
onClickMerge != null ||
|
|
||||||
onClickRefreshSelected != null ||
|
|
||||||
// KMK <--
|
|
||||||
onClickCollectRecommendations != null
|
|
||||||
val configuration = LocalConfiguration.current
|
|
||||||
val isTabletUi = remember { configuration.isTabletUi() }
|
|
||||||
var overFlowOpen by remember { mutableStateOf(false) }
|
|
||||||
// SY <--
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.windowInsetsPadding(
|
.windowInsetsPadding(
|
||||||
|
|
@ -326,30 +314,6 @@ fun LibraryBottomActionMenu(
|
||||||
onLongClick = { onLongClickItem(0) },
|
onLongClick = { onLongClickItem(0) },
|
||||||
onClick = onChangeCategoryClicked,
|
onClick = onChangeCategoryClicked,
|
||||||
)
|
)
|
||||||
if (onDownloadClicked != null) {
|
|
||||||
var downloadExpanded by remember { mutableStateOf(false) }
|
|
||||||
Button(
|
|
||||||
title = stringResource(MR.strings.action_download),
|
|
||||||
icon = Icons.Outlined.Download,
|
|
||||||
toConfirm = confirm[3],
|
|
||||||
onLongClick = { onLongClickItem(3) },
|
|
||||||
onClick = { downloadExpanded = !downloadExpanded },
|
|
||||||
) {
|
|
||||||
val onDismissRequest = { downloadExpanded = false }
|
|
||||||
DownloadDropdownMenu(
|
|
||||||
expanded = downloadExpanded,
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
onDownloadClicked = onDownloadClicked,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Button(
|
|
||||||
title = stringResource(MR.strings.action_delete),
|
|
||||||
icon = Icons.Outlined.Delete,
|
|
||||||
toConfirm = confirm[4],
|
|
||||||
onLongClick = { onLongClickItem(4) },
|
|
||||||
onClick = onDeleteClicked,
|
|
||||||
)
|
|
||||||
Button(
|
Button(
|
||||||
title = stringResource(MR.strings.action_mark_as_read),
|
title = stringResource(MR.strings.action_mark_as_read),
|
||||||
icon = Icons.Outlined.DoneAll,
|
icon = Icons.Outlined.DoneAll,
|
||||||
|
|
@ -364,71 +328,83 @@ fun LibraryBottomActionMenu(
|
||||||
onLongClick = { onLongClickItem(2) },
|
onLongClick = { onLongClickItem(2) },
|
||||||
onClick = onMarkAsUnreadClicked,
|
onClick = onMarkAsUnreadClicked,
|
||||||
)
|
)
|
||||||
// SY -->
|
if (onDownloadClicked != null) {
|
||||||
if (showOverflow) {
|
var downloadExpanded by remember { mutableStateOf(false) }
|
||||||
if (isTabletUi) {
|
|
||||||
if (onClickMigrate != null) {
|
|
||||||
Button(
|
|
||||||
title = stringResource(MR.strings.migrate),
|
|
||||||
icon = Icons.Outlined.SwapCalls,
|
|
||||||
toConfirm = confirm[6],
|
|
||||||
onLongClick = { onLongClickItem(6) },
|
|
||||||
onClick = onClickMigrate,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK -->
|
|
||||||
if (onClickMerge != null) {
|
|
||||||
Button(
|
|
||||||
title = stringResource(SYMR.strings.merge),
|
|
||||||
icon = Icons.Outlined.Merge,
|
|
||||||
toConfirm = confirm[7],
|
|
||||||
onLongClick = { onLongClickItem(7) },
|
|
||||||
onClick = onClickMerge,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK <--
|
|
||||||
}
|
|
||||||
Button(
|
Button(
|
||||||
title = stringResource(MR.strings.label_more),
|
title = stringResource(MR.strings.action_download),
|
||||||
icon = Icons.Outlined.MoreVert,
|
icon = Icons.Outlined.Download,
|
||||||
|
toConfirm = confirm[3],
|
||||||
|
onLongClick = { onLongClickItem(3) },
|
||||||
|
onClick = { downloadExpanded = !downloadExpanded },
|
||||||
|
) {
|
||||||
|
DownloadDropdownMenu(
|
||||||
|
expanded = downloadExpanded,
|
||||||
|
onDismissRequest = { downloadExpanded = false },
|
||||||
|
onDownloadClicked = onDownloadClicked,
|
||||||
|
offset = BottomBarMenuDpOffset,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SY -->
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
val isTabletUi = remember { configuration.isTabletUi() }
|
||||||
|
// SY <--
|
||||||
|
// KMK -->
|
||||||
|
if (onDownloadClicked == null || isTabletUi) {
|
||||||
|
Button(
|
||||||
|
title = stringResource(KMR.strings.action_update),
|
||||||
|
icon = Icons.Outlined.Refresh,
|
||||||
|
toConfirm = confirm[4],
|
||||||
|
onLongClick = { onLongClickItem(4) },
|
||||||
|
onClick = onSelectionUpdateClicked,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (isTabletUi) {
|
||||||
|
// KMK <--
|
||||||
|
Button(
|
||||||
|
title = stringResource(MR.strings.migrate),
|
||||||
|
icon = Icons.Outlined.SwapCalls,
|
||||||
toConfirm = confirm[5],
|
toConfirm = confirm[5],
|
||||||
onLongClick = { onLongClickItem(5) },
|
onLongClick = { onLongClickItem(5) },
|
||||||
onClick = { overFlowOpen = true },
|
onClick = onMigrateClicked,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
var overflowMenuOpen by remember { mutableStateOf(false) }
|
||||||
|
Button(
|
||||||
|
title = stringResource(MR.strings.label_more),
|
||||||
|
icon = Icons.Outlined.MoreVert,
|
||||||
|
toConfirm = confirm[6],
|
||||||
|
onLongClick = { onLongClickItem(6) },
|
||||||
|
onClick = { overflowMenuOpen = true },
|
||||||
|
) {
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = overFlowOpen,
|
expanded = overflowMenuOpen,
|
||||||
onDismissRequest = { overFlowOpen = false },
|
onDismissRequest = { overflowMenuOpen = false },
|
||||||
// KMK -->
|
offset = BottomBarMenuDpOffset,
|
||||||
offset = DpOffset((-10).dp, 0.dp),
|
|
||||||
// KMK <--
|
|
||||||
) {
|
) {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
if (onClickRefreshSelected != null) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(stringResource(KMR.strings.action_update)) },
|
|
||||||
onClick = {
|
|
||||||
overFlowOpen = false
|
|
||||||
onClickRefreshSelected()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK <--
|
|
||||||
if (!isTabletUi) {
|
if (!isTabletUi) {
|
||||||
if (onClickMigrate != null) {
|
if (onDownloadClicked != null) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(MR.strings.migrate)) },
|
text = { Text(stringResource(KMR.strings.action_update)) },
|
||||||
onClick = onClickMigrate,
|
onClick = onSelectionUpdateClicked,
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK -->
|
|
||||||
if (onClickMerge != null) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(stringResource(SYMR.strings.merge)) },
|
|
||||||
onClick = onClickMerge,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringResource(MR.strings.migrate)) },
|
||||||
|
onClick = onMigrateClicked,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringResource(MR.strings.action_delete)) },
|
||||||
|
onClick = onDeleteClicked,
|
||||||
|
)
|
||||||
|
// KMK -->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringResource(SYMR.strings.merge)) },
|
||||||
|
onClick = onMergeClicked,
|
||||||
|
)
|
||||||
if (onClickCleanTitles != null) {
|
if (onClickCleanTitles != null) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(SYMR.strings.action_clean_titles)) },
|
text = { Text(stringResource(SYMR.strings.action_clean_titles)) },
|
||||||
|
|
@ -453,31 +429,12 @@ fun LibraryBottomActionMenu(
|
||||||
onClick = onClickResetInfo,
|
onClick = onClickResetInfo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
// KMK <--
|
||||||
}
|
}
|
||||||
/* KMK -->
|
|
||||||
} else {
|
|
||||||
if (onClickMigrate != null) {
|
|
||||||
Button(
|
|
||||||
title = stringResource(MR.strings.migrate),
|
|
||||||
icon = Icons.Outlined.SwapCalls,
|
|
||||||
toConfirm = confirm[6],
|
|
||||||
onLongClick = { onLongClickItem(6) },
|
|
||||||
onClick = onClickMigrate,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (onClickMerge != null) {
|
|
||||||
Button(
|
|
||||||
title = stringResource(SYMR.strings.merge),
|
|
||||||
icon = Icons.Outlined.Merge,
|
|
||||||
toConfirm = confirm[7],
|
|
||||||
onLongClick = { onLongClickItem(7) },
|
|
||||||
onClick = onClickMerge,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK <-- */
|
|
||||||
}
|
}
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val BottomBarMenuDpOffset = DpOffset(0.dp, 0.dp)
|
||||||
|
|
|
||||||
|
|
@ -1012,9 +1012,9 @@ class LibraryScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetInfo() {
|
fun resetInfo() {
|
||||||
state.value.selectedManga.fastForEach { manga ->
|
state.value.selection.forEach { id ->
|
||||||
val mangaInfo = CustomMangaInfo(
|
val mangaInfo = CustomMangaInfo(
|
||||||
id = manga.id,
|
id = id,
|
||||||
title = null,
|
title = null,
|
||||||
author = null,
|
author = null,
|
||||||
artist = null,
|
artist = null,
|
||||||
|
|
@ -1034,7 +1034,7 @@ class LibraryScreenModel(
|
||||||
/**
|
/**
|
||||||
* Update Selected Mangas
|
* Update Selected Mangas
|
||||||
*/
|
*/
|
||||||
fun refreshSelectedManga(): Boolean {
|
fun updateSelectedManga(): Boolean {
|
||||||
val mangaIds = state.value.selection.toList()
|
val mangaIds = state.value.selection.toList()
|
||||||
return LibraryUpdateJob.startNow(
|
return LibraryUpdateJob.startNow(
|
||||||
context = preferences.context,
|
context = preferences.context,
|
||||||
|
|
|
||||||
|
|
@ -202,25 +202,24 @@ data object LibraryTab : Tab {
|
||||||
onDownloadClicked = screenModel::performDownloadAction
|
onDownloadClicked = screenModel::performDownloadAction
|
||||||
.takeIf { state.selectedManga.fastAll { !it.isLocal() } },
|
.takeIf { state.selectedManga.fastAll { !it.isLocal() } },
|
||||||
onDeleteClicked = screenModel::openDeleteMangaDialog,
|
onDeleteClicked = screenModel::openDeleteMangaDialog,
|
||||||
// SY -->
|
onMigrateClicked = {
|
||||||
onClickCleanTitles = screenModel::cleanTitles.takeIf { state.showCleanTitles },
|
val selection = state
|
||||||
onClickMigrate = {
|
// KMK -->
|
||||||
val selectedMangaIds = state.selectedManga
|
.selectedManga
|
||||||
.filterNot { it.source == MERGED_SOURCE_ID }
|
.filterNot { it.source == MERGED_SOURCE_ID }
|
||||||
.map { it.id }
|
.map { it.id }
|
||||||
|
// KMK <--
|
||||||
screenModel.clearSelection()
|
screenModel.clearSelection()
|
||||||
if (selectedMangaIds.isNotEmpty()) {
|
// KMK -->
|
||||||
navigator.push(MigrationConfigScreen(selectedMangaIds))
|
if (selection.isEmpty()) {
|
||||||
} else {
|
|
||||||
context.toast(SYMR.strings.no_valid_entry)
|
context.toast(SYMR.strings.no_valid_entry)
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
navigator.push(MigrationConfigScreen(selection))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClickCollectRecommendations = screenModel::showRecommendationSearchDialog.takeIf { state.selection.size > 1 },
|
|
||||||
onClickAddToMangaDex = screenModel::syncMangaToDex.takeIf { state.showAddToMangadex },
|
|
||||||
onClickResetInfo = screenModel::resetInfo.takeIf { state.showResetInfo },
|
|
||||||
// SY <--
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
onClickMerge = {
|
onMergeClicked = {
|
||||||
if (state.selection.size == 1) {
|
if (state.selection.size == 1) {
|
||||||
val manga = state.selectedManga.first()
|
val manga = state.selectedManga.first()
|
||||||
// Invoke merging for this manga
|
// Invoke merging for this manga
|
||||||
|
|
@ -258,8 +257,8 @@ data object LibraryTab : Tab {
|
||||||
context.toast(SYMR.strings.no_valid_entry)
|
context.toast(SYMR.strings.no_valid_entry)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClickRefreshSelected = {
|
onSelectionUpdateClicked = {
|
||||||
val started = screenModel.refreshSelectedManga()
|
val started = screenModel.updateSelectedManga()
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val msgRes = if (started) {
|
val msgRes = if (started) {
|
||||||
KMR.strings.updating
|
KMR.strings.updating
|
||||||
|
|
@ -273,6 +272,12 @@ data object LibraryTab : Tab {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
// SY -->
|
||||||
|
onClickCleanTitles = screenModel::cleanTitles.takeIf { state.showCleanTitles },
|
||||||
|
onClickCollectRecommendations = screenModel::showRecommendationSearchDialog.takeIf { state.selection.size > 1 },
|
||||||
|
onClickAddToMangaDex = screenModel::syncMangaToDex.takeIf { state.showAddToMangadex },
|
||||||
|
onClickResetInfo = screenModel::resetInfo.takeIf { state.showResetInfo },
|
||||||
|
// SY <--
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ import uy.kohesive.injekt.api.get
|
||||||
*
|
*
|
||||||
* @param mangaIds IDs of the manga that will be migrated using the sources configured on this screen.
|
* @param mangaIds IDs of the manga that will be migrated using the sources configured on this screen.
|
||||||
*/
|
*/
|
||||||
class MigrationConfigScreen(private val mangaIds: List<Long>) : Screen() {
|
class MigrationConfigScreen(private val mangaIds: Collection<Long>) : Screen() {
|
||||||
|
|
||||||
constructor(mangaId: Long) : this(listOf(mangaId))
|
constructor(mangaId: Long) : this(listOf(mangaId))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import tachiyomi.i18n.MR
|
||||||
/**
|
/**
|
||||||
* Screen showing a list of pair of current-target manga entries being migrated.
|
* Screen showing a list of pair of current-target manga entries being migrated.
|
||||||
*/
|
*/
|
||||||
class MigrationListScreen(private val mangaIds: List<Long>, private val extraSearchQuery: String?) : Screen() {
|
class MigrationListScreen(private val mangaIds: Collection<Long>, private val extraSearchQuery: String?) : Screen() {
|
||||||
|
|
||||||
private var matchOverride: Pair<Long, Long>? = null
|
private var matchOverride: Pair<Long, Long>? = null
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class MigrationListScreenModel(
|
class MigrationListScreenModel(
|
||||||
mangaIds: List<Long>,
|
mangaIds: Collection<Long>,
|
||||||
extraSearchQuery: String?,
|
extraSearchQuery: String?,
|
||||||
val preferences: SourcePreferences = Injekt.get(),
|
val preferences: SourcePreferences = Injekt.get(),
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue