Make migration changes

This commit is contained in:
Roshan Varughese 2024-10-26 22:19:24 +13:00
parent 298a1134e6
commit 17d9e47b11
9 changed files with 154 additions and 87 deletions

View file

@ -358,14 +358,14 @@ fun FailedUpdatesBottomActionMenu(
.padding(horizontal = 8.dp, vertical = 12.dp), .padding(horizontal = 8.dp, vertical = 12.dp),
) { ) {
Button( Button(
title = stringResource(R.string.action_delete), title = stringResource(MR.strings.action_delete),
icon = Icons.Outlined.Delete, icon = Icons.Outlined.Delete,
toConfirm = confirm[0], toConfirm = confirm[0],
onLongClick = { onLongClickItem(0) }, onLongClick = { onLongClickItem(0) },
onClick = onDeleteClicked, onClick = onDeleteClicked,
) )
Button( Button(
title = stringResource(R.string.action_dismiss), title = stringResource(MR.strings.action_dismiss),
icon = Icons.Outlined.VisibilityOff, icon = Icons.Outlined.VisibilityOff,
toConfirm = confirm[1], toConfirm = confirm[1],
onLongClick = { onLongClickItem(1) }, onLongClick = { onLongClickItem(1) },
@ -373,7 +373,7 @@ fun FailedUpdatesBottomActionMenu(
) )
if (groupingMode == GroupByMode.NONE && selected.size <= 1) { if (groupingMode == GroupByMode.NONE && selected.size <= 1) {
Button( Button(
title = stringResource(R.string.action_info), title = stringResource(MR.strings.action_info),
icon = Icons.Outlined.Info, icon = Icons.Outlined.Info,
toConfirm = confirm[2], toConfirm = confirm[2],
onLongClick = { onLongClickItem(2) }, onLongClick = { onLongClickItem(2) },

View file

@ -30,6 +30,7 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.updates.UpdatesItem import eu.kanade.tachiyomi.ui.updates.UpdatesItem
import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -152,26 +153,33 @@ private fun UpdatesAppBar(
modifier = modifier, modifier = modifier,
title = stringResource(MR.strings.label_recent_updates), title = stringResource(MR.strings.label_recent_updates),
actions = { actions = {
val actions = mutableListOf<AppBar.Action>() val actions = mutableListOf<AppBar.Action>().apply {
if (hasFailedUpdates) { // only add the warning icon if it is enabled if (hasFailedUpdates) {
actions += AppBar.Action( add(
title = stringResource(R.string.action_update_warning), AppBar.Action(
title = stringResource(MR.strings.action_update_warning),
icon = Icons.Rounded.Warning, icon = Icons.Rounded.Warning,
onClick = onUpdateWarning, onClick = onUpdateWarning,
iconTint = warningIconTint, iconTint = warningIconTint,
),
) )
} }
actions += AppBar.Action( add(
AppBar.Action(
title = stringResource(MR.strings.action_view_upcoming), title = stringResource(MR.strings.action_view_upcoming),
icon = Icons.Outlined.CalendarMonth, icon = Icons.Outlined.CalendarMonth,
onClick = onCalendarClicked, onClick = onCalendarClicked,
),
) )
actions += AppBar.Action( add(
title = stringResource(R.string.action_update_library), AppBar.Action(
title = stringResource(MR.strings.action_update_library),
icon = Icons.Outlined.Refresh, icon = Icons.Outlined.Refresh,
onClick = onUpdateLibrary, onClick = onUpdateLibrary,
),
) )
AppBarActions(actions) }
AppBarActions(actions.toImmutableList())
}, },
actionModeCounter = actionModeCounter, actionModeCounter = actionModeCounter,
onCancelActionMode = onCancelActionMode, onCancelActionMode = onCancelActionMode,

View file

@ -27,9 +27,9 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Dangerous
import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material.icons.rounded.Warning import androidx.compose.material.icons.rounded.Warning
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@ -38,6 +38,7 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -49,6 +50,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.hapticfeedback.HapticFeedbackType
@ -244,6 +246,15 @@ fun LazyListScope.failedUpdatesGroupUiItem(
.height(50.dp) .height(50.dp)
.aspectRatio(1f), .aspectRatio(1f),
) )
} else {
Image(
imageVector = Icons.Filled.Dangerous,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.error),
modifier = Modifier
.height(50.dp)
.aspectRatio(1f),
)
} }
Column( Column(
modifier = Modifier modifier = Modifier
@ -313,11 +324,13 @@ fun LazyListScope.failedUpdatesGroupUiItem(
if (expanded[errorMessageHeaderId] == null) { if (expanded[errorMessageHeaderId] == null) {
onExpandedMapChange(errorMessageHeaderId, true) onExpandedMapChange(errorMessageHeaderId, true)
} else { } else {
onExpandedMapChange(errorMessageHeaderId, !expanded[errorMessageHeaderId]!!) onExpandedMapChange(
errorMessageHeaderId,
!expanded[errorMessageHeaderId]!!,
)
} }
}, },
onLongClick = onLongClick = { onGroupSelected(items) },
{ onGroupSelected(items) },
) )
.padding( .padding(
horizontal = 12.dp, horizontal = 12.dp,
@ -390,7 +403,9 @@ fun LazyListScope.failedUpdatesGroupUiItem(
val isLastItem = index == items.lastIndex val isLastItem = index == items.lastIndex
AnimatedVisibility( AnimatedVisibility(
modifier = Modifier, modifier = Modifier,
visible = expanded[errorMessageHeaderId] == true && expanded[GroupKey(id, Pair("", ""))] == true, visible =
expanded[errorMessageHeaderId] == true &&
expanded[GroupKey(id, Pair("", ""))] == true,
) { ) {
FailedUpdatesUiItem( FailedUpdatesUiItem(
modifier = Modifier modifier = Modifier
@ -443,10 +458,12 @@ fun CustomIconButton(
enabled = enabled, enabled = enabled,
role = Role.Button, role = Role.Button,
interactionSource = interactionSource, interactionSource = interactionSource,
indication = rememberRipple( indication = remember {
ripple(
bounded = false, bounded = false,
radius = 20.dp, radius = 20.dp,
), )
},
), ),
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {

View file

@ -32,7 +32,7 @@ fun ErrorMessageDialog(
TextButton(onClick = { TextButton(onClick = {
onCopyClick() onCopyClick()
onDismissRequest() onDismissRequest()
},) { }) {
Text(text = stringResource(R.string.copy)) Text(text = stringResource(R.string.copy))
} }
}, },

View file

@ -51,7 +51,9 @@ import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.FastScrollLazyColumn
import tachiyomi.presentation.core.components.Pill import tachiyomi.presentation.core.components.Pill
import tachiyomi.presentation.core.components.SortItem import tachiyomi.presentation.core.components.SortItem
@ -59,8 +61,6 @@ import tachiyomi.presentation.core.components.material.ExtendedFloatingActionBut
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrollingUp
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
class FailedUpdatesScreen : Screen() { class FailedUpdatesScreen : Screen() {
@ -120,7 +120,8 @@ class FailedUpdatesScreen : Screen() {
text = { Text(text = stringResource(R.string.label_help)) }, text = { Text(text = stringResource(R.string.label_help)) },
icon = { Icon(imageVector = Icons.Outlined.HelpOutline, contentDescription = null) }, icon = { Icon(imageVector = Icons.Outlined.HelpOutline, contentDescription = null) },
onClick = { uriHandler.openUri("https://tachiyomi.org/help/guides/troubleshooting") }, onClick = { uriHandler.openUri("https://tachiyomi.org/help/guides/troubleshooting") },
expanded = failedUpdatesListState.isScrollingUp() || failedUpdatesListState.isScrolledToEnd(), // Revisit
// expanded = failedUpdatesListState.isScrollingUp() || failedUpdatesListState.isScrolledToEnd(),
) )
} }
}, },
@ -129,7 +130,7 @@ class FailedUpdatesScreen : Screen() {
state.isLoading -> LoadingScreen(modifier = Modifier.padding(contentPadding)) state.isLoading -> LoadingScreen(modifier = Modifier.padding(contentPadding))
state.items.isEmpty() -> EmptyScreen( state.items.isEmpty() -> EmptyScreen(
textResource = R.string.information_no_update_errors, stringRes = MR.strings.information_no_update_errors,
modifier = Modifier.padding(contentPadding), modifier = Modifier.padding(contentPadding),
happyFace = true, happyFace = true,
) )
@ -363,7 +364,7 @@ private fun FailedUpdatesAppBar(
onClick = { onClickGroup(GroupByMode.NONE) }, onClick = { onClickGroup(GroupByMode.NONE) },
) )
} }
AppBarActions(actions) AppBarActions(actions.toImmutableList())
} }
}, },
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
@ -399,7 +400,7 @@ private fun FailedUpdatesActionAppBar(
icon = Icons.Outlined.FlipToBack, icon = Icons.Outlined.FlipToBack,
onClick = onInvertSelection, onClick = onInvertSelection,
), ),
), ).toImmutableList(),
) )
}, },
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,

View file

@ -4,11 +4,10 @@ import android.content.Context
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.util.addOrRemove import eu.kanade.core.util.addOrRemove
import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
@ -20,11 +19,11 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.preference.getEnum import tachiyomi.core.common.preference.getEnum
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
import tachiyomi.domain.failed.repository.FailedUpdatesRepository import tachiyomi.domain.failed.repository.FailedUpdatesRepository
@ -56,7 +55,7 @@ class FailedUpdatesScreenModel(
val channel = _channel.receiveAsFlow() val channel = _channel.receiveAsFlow()
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
val sortMode = preferenceStore.getEnum("sort_mode", SortingMode.BY_ALPHABET).get() val sortMode = preferenceStore.getEnum("sort_mode", SortingMode.BY_ALPHABET).get()
combine( combine(
getSourcesWithFavoriteCount.subscribe(), getSourcesWithFavoriteCount.subscribe(),
@ -79,10 +78,12 @@ class FailedUpdatesScreenModel(
items = libraryManga.filter { libraryManga -> items = libraryManga.filter { libraryManga ->
failedUpdates.any { it.mangaId == libraryManga.manga.id } failedUpdates.any { it.mangaId == libraryManga.manga.id }
}.map { libraryManga -> }.map { libraryManga ->
val source = sourceManager.get(libraryManga.manga.source)!! // Untrusted Extensions cause null crash
val source = sourceManager.getOrStub(libraryManga.manga.source)
val failedUpdate = failedUpdates.find { it.mangaId == libraryManga.manga.id }!! val failedUpdate = failedUpdates.find { it.mangaId == libraryManga.manga.id }!!
val errorMessage = failedUpdate.errorMessage val errorMessage = failedUpdate.errorMessage
val simplifiedErrorMessage = simplifyErrorMessage(errorMessage.substringBefore(":"), failedUpdate.isOnline) val simplifiedErrorMessage =
simplifyErrorMessage(errorMessage.substringBefore(":"), failedUpdate.isOnline)
FailedUpdatesManga( FailedUpdatesManga(
libraryManga = libraryManga, libraryManga = libraryManga,
errorMessage = errorMessage, errorMessage = errorMessage,
@ -106,42 +107,56 @@ class FailedUpdatesScreenModel(
private fun simplifyErrorMessage(exception: String, isOnline: Long): String { private fun simplifyErrorMessage(exception: String, isOnline: Long): String {
return when (exception) { return when (exception) {
// General networking exceptions // General networking exceptions
"SocketException" -> context.getString(R.string.exception_socket_error) // Hold your arses this is temporary and for testing purposes only
"BindException" -> context.getString(R.string.exception_bind_port) "SocketException" -> "Socket Exception"
"InterruptedIOException" -> context.getString(R.string.exception_io_interrupted) "BindException" -> "Bind Exception"
"HttpRetryException" -> context.getString(R.string.exception_http_retry) "InterruptedIOException" -> "Interrupted IO Exception"
"PortUnreachableException" -> context.getString(R.string.exception_port_unreachable) "HttpRetryException" -> "HTTP Retry Exception"
"PortUnreachableException" -> "Port Unreachable Exception"
// General IO-related exceptions // General IO-related exceptions
"IOException" -> if (isOnline == 1L) context.getString(R.string.exception_io_error) else context.getString(R.string.exception_internet_connection) "IOException" -> if (isOnline ==
"TimeoutException" -> context.getString(R.string.exception_timed_out) 1L
) {
"IO Exception"
} else {
"IOException: No Internet"
}
"TimeoutException" -> "Timeout Exception"
// SSL & Security-related // SSL & Security-related
"SSLException" -> context.getString(R.string.exception_ssl_connection) "SSLException" -> "SSL Exception"
"CertificateExpiredException" -> context.getString(R.string.exception_ssl_certificate) "CertificateExpiredException" -> "Certificate Expired Exception"
"CertificateNotYetValidException" -> context.getString(R.string.exception_ssl_not_valid) "CertificateNotYetValidException" -> "Certificate Not Yet Valid Exception"
"CertificateParsingException" -> context.getString(R.string.exception_ssl_parsing) "CertificateParsingException" -> "Certificate Parsing Exception"
"CertificateEncodingException" -> context.getString(R.string.exception_ssl_encoding) "CertificateEncodingException" -> "Certificate Encoding Exception"
"UnrecoverableKeyException" -> context.getString(R.string.exception_unrecoverable_key) "UnrecoverableKeyException" -> "Unrecoverable Key Exception"
"KeyManagementException" -> context.getString(R.string.exception_key_management) "KeyManagementException" -> "Key Management Exception"
"NoSuchAlgorithmException" -> context.getString(R.string.exception_algorithm) "NoSuchAlgorithmException" -> "No Such Algorithm Exception"
"KeyStoreException" -> context.getString(R.string.exception_keystore) "KeyStoreException" -> "Key Store Exception"
"NoSuchProviderException" -> context.getString(R.string.exception_security_provider) "NoSuchProviderException" -> "No Such Provider Exception"
"SignatureException" -> context.getString(R.string.exception_signature_validation) "SignatureException" -> "Signature Exception"
"InvalidKeySpecException" -> context.getString(R.string.exception_key_specification) "InvalidKeySpecException" -> "Invalid Key Spec Exception"
// Host & DNS-related // Host & DNS-related
"UnknownHostException" -> if (isOnline == 1L) context.getString(R.string.exception_domain) else context.getString(R.string.exception_internet_connection) "UnknownHostException" -> if (isOnline ==
"NoRouteToHostException" -> context.getString(R.string.exception_route_to_host) 1L
) {
"Unknown Host Exception"
} else {
"Unknown Host Exception: No Internet"
}
"ConnectException" -> "Connect Exception"
"NoRouteToHostException" -> "No Route To Host Exception"
// URL & URI related // URL & URI related
"URISyntaxException" -> context.getString(R.string.exception_uri_syntax) "URISyntaxException" -> "URI Syntax Exception"
"MalformedURLException" -> context.getString(R.string.exception_malformed_url) "MalformedURLException" -> "Malformed URL Exception"
// Authentication & Proxy // Authentication & Proxy
"ProtocolException" -> context.getString(R.string.exception_protocol_proxy_type) "ProtocolException" -> "Protocol Exception"
// Concurrency & Operation-related // Concurrency & Operation-related
"CancellationException" -> context.getString(R.string.exception_cancelled) "CancellationException" -> "Cancellation Exception"
"InterruptedException" -> context.getString(R.string.exception_interrupted) "InterruptedException" -> "Interrupted Exception"
"IllegalStateException" -> context.getString(R.string.exception_unexpected_state) "IllegalStateException" -> "Illegal State Exception"
"UnsupportedOperationException" -> context.getString(R.string.exception_not_supported) "UnsupportedOperationException" -> "Unsupported Operation Exception"
"IllegalArgumentException" -> context.getString(R.string.exception_invalid_argument) "IllegalArgumentException" -> "Illegal Argument Exception"
else -> "" else -> "Unknown: $exception"
} }
} }
@ -163,7 +178,13 @@ class FailedUpdatesScreenModel(
val descendingOrder = if (state.sortMode == SortingMode.BY_ALPHABET) !state.descendingOrder else false val descendingOrder = if (state.sortMode == SortingMode.BY_ALPHABET) !state.descendingOrder else false
preferenceStore.getBoolean("descending_order", false).set(descendingOrder) preferenceStore.getBoolean("descending_order", false).set(descendingOrder)
state.copy( state.copy(
items = if (descendingOrder) state.items.sortedByDescending { it.libraryManga.manga.title } else state.items.sortedBy { it.libraryManga.manga.title }, items = if (descendingOrder) {
state.items.sortedByDescending {
it.libraryManga.manga.title
}
} else {
state.items.sortedBy { it.libraryManga.manga.title }
},
descendingOrder = descendingOrder, descendingOrder = descendingOrder,
sortMode = SortingMode.BY_ALPHABET, sortMode = SortingMode.BY_ALPHABET,
) )
@ -172,7 +193,12 @@ class FailedUpdatesScreenModel(
} }
@Composable @Composable
fun categoryMap(items: List<FailedUpdatesManga>, groupMode: GroupByMode, sortMode: SortingMode, descendingOrder: Boolean): Map<String, Map<Pair<String, String>, List<FailedUpdatesManga>>> { fun categoryMap(
items: List<FailedUpdatesManga>,
groupMode: GroupByMode,
sortMode: SortingMode,
descendingOrder: Boolean,
): Map<String, Map<Pair<String, String>, List<FailedUpdatesManga>>> {
val unsortedMap = when (groupMode) { val unsortedMap = when (groupMode) {
GroupByMode.BY_SOURCE -> items.groupBy { it.source.name } GroupByMode.BY_SOURCE -> items.groupBy { it.source.name }
.mapValues { entry -> entry.value.groupBy { Pair(it.errorMessage, it.simplifiedErrorMessage) } } .mapValues { entry -> entry.value.groupBy { Pair(it.errorMessage, it.simplifiedErrorMessage) } }
@ -180,7 +206,14 @@ class FailedUpdatesScreenModel(
} }
return when (sortMode) { return when (sortMode) {
SortingMode.BY_ALPHABET -> { SortingMode.BY_ALPHABET -> {
val sortedMap = TreeMap<String, Map<Pair<String, String>, List<FailedUpdatesManga>>>(if (descendingOrder) { compareByDescending { it } } else { compareBy { it } }) val sortedMap =
TreeMap<String, Map<Pair<String, String>, List<FailedUpdatesManga>>>(
if (descendingOrder) {
compareByDescending { it }
} else {
compareBy { it }
},
)
sortedMap.putAll(unsortedMap) sortedMap.putAll(unsortedMap)
sortedMap sortedMap
} }
@ -276,7 +309,11 @@ class FailedUpdatesScreenModel(
range.forEach { range.forEach {
val inBetweenItem = getOrNull(it) val inBetweenItem = getOrNull(it)
if (inBetweenItem != null && !inBetweenItem.selected && inBetweenItem.errorMessage == firstErrorMessage && inBetweenItem.errorMessage == lastErrorMessage) { if (inBetweenItem != null &&
!inBetweenItem.selected &&
inBetweenItem.errorMessage == firstErrorMessage &&
inBetweenItem.errorMessage == lastErrorMessage
) {
selectedMangaIds.add(inBetweenItem.libraryManga.manga.id) selectedMangaIds.add(inBetweenItem.libraryManga.manga.id)
set(it, inBetweenItem.copy(selected = true)) set(it, inBetweenItem.copy(selected = true))
} }
@ -325,7 +362,7 @@ class FailedUpdatesScreenModel(
} }
fun removeMangas(mangaList: List<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) { fun removeMangas(mangaList: List<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
val mangaToDelete = mangaList.distinctBy { it.id } val mangaToDelete = mangaList.distinctBy { it.id }
if (deleteFromLibrary) { if (deleteFromLibrary) {
@ -368,7 +405,7 @@ class FailedUpdatesScreenModel(
) )
} }
coroutineScope.launchNonCancellable { failedUpdatesManager.removeFailedUpdatesByMangaIds(listOfMangaIds) } screenModelScope.launchNonCancellable { failedUpdatesManager.removeFailedUpdatesByMangaIds(listOfMangaIds) }
} }
fun openDeleteMangaDialog(selected: List<FailedUpdatesManga>) { fun openDeleteMangaDialog(selected: List<FailedUpdatesManga>) {

View file

@ -289,7 +289,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
is SourceNotInstalledException -> context.stringResource( is SourceNotInstalledException -> context.stringResource(
MR.strings.loader_not_implemented_error, MR.strings.loader_not_implemented_error,
) )
else -> e.message ?: context.getString(MR.strings.exception_unknown) else -> e.message ?: "context.getString(MR.strings.exception_unknown)"
} }
try { try {
failedUpdatesCount.getAndIncrement() failedUpdatesCount.getAndIncrement()
@ -322,7 +322,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
failedUpdatesCount.get(), failedUpdatesCount.get(),
) )
} }
} }
private fun downloadChapters(manga: Manga, chapters: List<Chapter>) { private fun downloadChapters(manga: Manga, chapters: List<Chapter>) {

View file

@ -41,7 +41,12 @@ object NotificationHandler {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
action = Constants.SHORTCUT_FAILED action = Constants.SHORTCUT_FAILED
} }
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) return PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
} }
/** /**

View file

@ -4,7 +4,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.failed.model.FailedUpdate import tachiyomi.domain.failed.model.FailedUpdate
import tachiyomi.domain.failed.repository.FailedUpdatesRepository import tachiyomi.domain.failed.repository.FailedUpdatesRepository