Address more spotless lint errors from KMK & SY
This commit is contained in:
parent
e7ca892f65
commit
48d874342e
119 changed files with 637 additions and 380 deletions
|
|
@ -13,7 +13,7 @@ class TrustExtension(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean {
|
suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
if (fingerprints.contains(CreateExtensionRepo.OFFICIAL_REPO_SIGNATURE)) return true
|
if (fingerprints.contains(CreateExtensionRepo.OFFICIAL_REPO_SIGNATURE)) return true
|
||||||
// KMK <--
|
// KMK <--
|
||||||
val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet()
|
val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet()
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,11 @@ class GetEnabledSources(
|
||||||
) { a, b, c -> Triple(a, b, c) },
|
) { a, b, c -> Triple(a, b, c) },
|
||||||
// SY <--
|
// SY <--
|
||||||
repository.getSources(),
|
repository.getSources(),
|
||||||
) { pinnedSourceIds,
|
) {
|
||||||
(enabledLanguages, disabledSources, lastUsedSource),
|
pinnedSourceIds,
|
||||||
(excludedFromDataSaver, sourcesInCategories, sourceCategoriesFilter),
|
(enabledLanguages, disabledSources, lastUsedSource),
|
||||||
sources,
|
(excludedFromDataSaver, sourcesInCategories, sourceCategoriesFilter),
|
||||||
|
sources,
|
||||||
->
|
->
|
||||||
|
|
||||||
val sourcesAndCategories = sourcesInCategories.map {
|
val sourcesAndCategories = sourcesInCategories.map {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ class SyncPreferences(
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo = preferenceStore.getBoolean("customInfo", true).get(),
|
customInfo = preferenceStore.getBoolean("customInfo", true).get(),
|
||||||
readEntries = preferenceStore.getBoolean("readEntries", true).get()
|
readEntries = preferenceStore.getBoolean("readEntries", true).get(),
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@ data class SyncSettings(
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val customInfo: Boolean = true,
|
val customInfo: Boolean = true,
|
||||||
val readEntries: Boolean = true
|
val readEntries: Boolean = true,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ private fun ExtensionFilterContent(
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = MaterialTheme.padding.small)
|
.padding(start = MaterialTheme.padding.small),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
items(state.languages) { language ->
|
items(state.languages) { language ->
|
||||||
|
|
@ -87,7 +87,7 @@ private fun ExtensionFilterContent(
|
||||||
contentDescription = language,
|
contentDescription = language,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(48.dp)
|
.width(48.dp)
|
||||||
.height(32.dp)
|
.height(32.dp),
|
||||||
)
|
)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
SwitchPreferenceWidget(
|
SwitchPreferenceWidget(
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ private fun ExtensionItemContent(
|
||||||
contentDescription = extension.lang ?: "",
|
contentDescription = extension.lang ?: "",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(18.dp)
|
.width(18.dp)
|
||||||
.height(12.dp)
|
.height(12.dp),
|
||||||
)
|
)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ internal fun GlobalSearchContent(
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
supportsLatest = false,
|
supportsLatest = false,
|
||||||
isStub = false
|
isStub = false,
|
||||||
)
|
)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,7 @@ private fun MigrateSourceItem(
|
||||||
contentDescription = lang,
|
contentDescription = lang,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(18.dp)
|
.width(18.dp)
|
||||||
.height(12.dp)
|
.height(12.dp),
|
||||||
)
|
)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -304,12 +304,12 @@ fun SourceFeedToolbar(
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
actions = persistentListOf(
|
actions = persistentListOf(
|
||||||
bulkSelectionButton(toggleSelectionMode),
|
bulkSelectionButton(toggleSelectionMode),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
persistentListOf(
|
persistentListOf(
|
||||||
if (sourceId != LocalSource.ID) {
|
if (sourceId != LocalSource.ID) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onWebViewClick
|
onClick = onWebViewClick,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.Public,
|
imageVector = Icons.Outlined.Public,
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ fun SourcesSearch(
|
||||||
),
|
),
|
||||||
contentPadding = PaddingValues(12.dp),
|
contentPadding = PaddingValues(12.dp),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -474,7 +474,8 @@ fun SourceOptionsDialog(
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
// KMK -->
|
// KMK -->
|
||||||
if (onClickSettings != null && source.installedExtension !== null &&
|
if (onClickSettings != null &&
|
||||||
|
source.installedExtension !== null &&
|
||||||
source.id !in listOf(LocalSource.ID, EH_SOURCE_ID, EXH_SOURCE_ID)
|
source.id !in listOf(LocalSource.ID, EH_SOURCE_ID, EXH_SOURCE_ID)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ private val defaultContent: @Composable RowScope.(
|
||||||
contentDescription = lang,
|
contentDescription = lang,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(18.dp)
|
.width(18.dp)
|
||||||
.height(12.dp)
|
.height(12.dp),
|
||||||
)
|
)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ fun GlobalSearchToolbar(
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
actions = persistentListOf(
|
actions = persistentListOf(
|
||||||
bulkSelectionButton(toggleSelectionMode),
|
bulkSelectionButton(toggleSelectionMode),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import tachiyomi.source.local.LocalSource
|
||||||
@Composable
|
@Composable
|
||||||
fun SourceSettingsButton(
|
fun SourceSettingsButton(
|
||||||
id: Long,
|
id: Long,
|
||||||
@Suppress("UNUSED_PARAMETER") modifier: Modifier = Modifier
|
@Suppress("UNUSED_PARAMETER") modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
// Create a fake source
|
// Create a fake source
|
||||||
val source = Source(id, "", "", supportsLatest = false, isStub = false)
|
val source = Source(id, "", "", supportsLatest = false, isStub = false)
|
||||||
|
|
@ -30,7 +30,7 @@ fun SourceSettingsButton(
|
||||||
@Composable
|
@Composable
|
||||||
fun SourceSettingsButton(
|
fun SourceSettingsButton(
|
||||||
source: Source,
|
source: Source,
|
||||||
@Suppress("UNUSED_PARAMETER") modifier: Modifier = Modifier
|
@Suppress("UNUSED_PARAMETER") modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
// Avoid E-Hentai & ExHentai which is built-in & not actually installed extensions
|
// Avoid E-Hentai & ExHentai which is built-in & not actually installed extensions
|
||||||
if (source.id == LocalSource.ID || source.id == EH_SOURCE_ID || source.id == EXH_SOURCE_ID) return
|
if (source.id == LocalSource.ID || source.id == EH_SOURCE_ID || source.id == EXH_SOURCE_ID) return
|
||||||
|
|
|
||||||
|
|
@ -520,7 +520,7 @@ private fun MangaScreenSmallImpl(
|
||||||
style = HazeStyle(
|
style = HazeStyle(
|
||||||
tint = HazeDefaults.tint(fullCoverBackground),
|
tint = HazeDefaults.tint(fullCoverBackground),
|
||||||
blurRadius = 10.dp,
|
blurRadius = 10.dp,
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
|
|
@ -928,7 +928,7 @@ private fun MangaScreenLargeImpl(
|
||||||
style = HazeStyle(
|
style = HazeStyle(
|
||||||
tint = HazeDefaults.tint(fullCoverBackground),
|
tint = HazeDefaults.tint(fullCoverBackground),
|
||||||
blurRadius = 10.dp,
|
blurRadius = 10.dp,
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
|
|
@ -1214,7 +1214,9 @@ private fun LazyListScope.sharedChapterItems(
|
||||||
// SY <--
|
// SY <--
|
||||||
},
|
},
|
||||||
readProgress = item.chapter.lastPageRead
|
readProgress = item.chapter.lastPageRead
|
||||||
.takeIf { /* SY --> */(!item.chapter.read || alwaysShowReadingProgress)/* SY <-- */ && it > 0L }
|
.takeIf {
|
||||||
|
/* SY --> */(!item.chapter.read || alwaysShowReadingProgress)/* SY <-- */ && it > 0L
|
||||||
|
}
|
||||||
?.let {
|
?.let {
|
||||||
stringResource(
|
stringResource(
|
||||||
MR.strings.chapter_progress,
|
MR.strings.chapter_progress,
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,12 @@ fun MangaChapterListItem(
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
if (readProgress != null || scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
if (readProgress != null ||
|
||||||
|
scanlator != null/* SY --> */ ||
|
||||||
|
sourceName != null/* SY <-- */
|
||||||
|
) {
|
||||||
|
DotSeparatorText()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (readProgress != null) {
|
if (readProgress != null) {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ enum class MangaCover(val ratio: Float) {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
loading = {
|
loading = {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifierColored
|
modifier = modifierColored,
|
||||||
) {
|
) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
color = tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor,
|
color = tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor,
|
||||||
|
|
@ -96,7 +96,7 @@ enum class MangaCover(val ratio: Float) {
|
||||||
Size.Big -> 16.dp
|
Size.Big -> 16.dp
|
||||||
Size.Medium -> 24.dp
|
Size.Medium -> 24.dp
|
||||||
else -> 32.dp
|
else -> 32.dp
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.align(Alignment.Center),
|
.align(Alignment.Center),
|
||||||
strokeWidth = when (size) {
|
strokeWidth = when (size) {
|
||||||
|
|
@ -108,7 +108,7 @@ enum class MangaCover(val ratio: Float) {
|
||||||
},
|
},
|
||||||
error = {
|
error = {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifierColored
|
modifier = modifierColored,
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.cover_error_vector),
|
imageVector = ImageVector.vectorResource(R.drawable.cover_error_vector),
|
||||||
|
|
@ -119,11 +119,11 @@ enum class MangaCover(val ratio: Float) {
|
||||||
Size.Big -> 16.dp
|
Size.Big -> 16.dp
|
||||||
Size.Medium -> 24.dp
|
Size.Medium -> 24.dp
|
||||||
else -> 32.dp
|
else -> 32.dp
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.align(Alignment.Center),
|
.align(Alignment.Center),
|
||||||
colorFilter = ColorFilter.tint(
|
colorFilter = ColorFilter.tint(
|
||||||
tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor
|
tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +178,7 @@ enum class MangaCoverHide(private val ratio: Float) {
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifierColored
|
modifier = modifierColored,
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.ic_baseline_menu_book_24),
|
imageVector = ImageVector.vectorResource(R.drawable.ic_baseline_menu_book_24),
|
||||||
|
|
@ -187,7 +187,7 @@ enum class MangaCoverHide(private val ratio: Float) {
|
||||||
.size(32.dp)
|
.size(32.dp)
|
||||||
.align(Alignment.Center),
|
.align(Alignment.Center),
|
||||||
colorFilter = ColorFilter.tint(
|
colorFilter = ColorFilter.tint(
|
||||||
tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor
|
tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,8 @@ fun MangaToolbar(
|
||||||
}
|
}
|
||||||
// KMK -->
|
// KMK -->
|
||||||
if (isHomeEnabled && navigator != null) {
|
if (isHomeEnabled && navigator != null) {
|
||||||
if (navigator.size >= 2 && navigator.items[navigator.size - 2] is MangaScreen ||
|
if (navigator.size >= 2 &&
|
||||||
|
navigator.items[navigator.size - 2] is MangaScreen ||
|
||||||
navigator.size >= 5
|
navigator.size >= 5
|
||||||
) {
|
) {
|
||||||
IconButton(onClick = { onHomeClicked() }) {
|
IconButton(onClick = { onHomeClicked() }) {
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ fun OutlinedButtonWithArrow(
|
||||||
vertical = MaterialTheme.padding.small,
|
vertical = MaterialTheme.padding.small,
|
||||||
),
|
),
|
||||||
colors = ButtonDefaults.outlinedButtonColors(),
|
colors = ButtonDefaults.outlinedButtonColors(),
|
||||||
shape = RoundedCornerShape(8.dp)
|
shape = RoundedCornerShape(8.dp),
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
|
|
@ -51,7 +51,7 @@ fun OutlinedButtonWithArrow(
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = icon,
|
imageVector = icon,
|
||||||
contentDescription = "Arrow"
|
contentDescription = "Arrow",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,6 +62,6 @@ fun OutlinedButtonWithArrow(
|
||||||
fun OutlinedButtonWithArrowPreview() {
|
fun OutlinedButtonWithArrowPreview() {
|
||||||
OutlinedButtonWithArrow(
|
OutlinedButtonWithArrow(
|
||||||
text = "Click Me",
|
text = "Click Me",
|
||||||
onClick = { /* Do nothing */ }
|
onClick = { /* Do nothing */ },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PagePreviewLoading(
|
private fun PagePreviewLoading(
|
||||||
setMaxWidth: (Dp) -> Unit
|
setMaxWidth: (Dp) -> Unit,
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
Box(
|
Box(
|
||||||
|
|
@ -63,7 +63,7 @@ private fun PagePreviewLoading(
|
||||||
@Composable
|
@Composable
|
||||||
private fun PagePreviewRow(
|
private fun PagePreviewRow(
|
||||||
onOpenPage: (Int) -> Unit,
|
onOpenPage: (Int) -> Unit,
|
||||||
items: ImmutableList<PagePreview>
|
items: ImmutableList<PagePreview>,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -88,7 +88,7 @@ private fun PagePreviewMore(
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
TextButton(onClick = onMorePreviewsClicked) {
|
TextButton(onClick = onMorePreviewsClicked) {
|
||||||
Text(stringResource(SYMR.strings.more_previews))
|
Text(stringResource(SYMR.strings.more_previews))
|
||||||
|
|
@ -116,7 +116,7 @@ fun PagePreviews(
|
||||||
pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount).forEach {
|
pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount).forEach {
|
||||||
PagePreviewRow(
|
PagePreviewRow(
|
||||||
onOpenPage = onOpenPage,
|
onOpenPage = onOpenPage,
|
||||||
items = remember(it) { it.toImmutableList() }
|
items = remember(it) { it.toImmutableList() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ fun LazyListScope.PagePreviewItems(
|
||||||
) {
|
) {
|
||||||
PagePreviewRow(
|
PagePreviewRow(
|
||||||
onOpenPage = onOpenPage,
|
onOpenPage = onOpenPage,
|
||||||
items = remember(it) { it.toImmutableList() }
|
items = remember(it) { it.toImmutableList() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item(
|
item(
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,9 @@ fun RelatedMangasRow(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> { EmptyResultItem() }
|
else -> {
|
||||||
|
EmptyResultItem()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ private fun ComingUpdatesScreenPreview() {
|
||||||
changelogInfo = """
|
changelogInfo = """
|
||||||
## Yay
|
## Yay
|
||||||
Foobar
|
Foobar
|
||||||
|
|
||||||
### More info
|
### More info
|
||||||
[komikku-app/komikku@23d862d17...48fb4a2e6](https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6)
|
[komikku-app/komikku@23d862d17...48fb4a2e6](https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6)
|
||||||
- Hello ([@cuong-tran](@https://github.com/cuong-tran))
|
- Hello ([@cuong-tran](@https://github.com/cuong-tran))
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ private fun WhatsNewScreenPreview() {
|
||||||
changelogInfo = """
|
changelogInfo = """
|
||||||
## Yay
|
## Yay
|
||||||
Foobar
|
Foobar
|
||||||
|
|
||||||
### More info
|
### More info
|
||||||
[komikku-app/komikku@23d862d17...48fb4a2e6](https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6)
|
[komikku-app/komikku@23d862d17...48fb4a2e6](https://github.com/komikku-app/komikku/compare/23d862d17...48fb4a2e6)
|
||||||
- Hello ([@cuong-tran](@https://github.com/cuong-tran))
|
- Hello ([@cuong-tran](@https://github.com/cuong-tran))
|
||||||
|
|
|
||||||
|
|
@ -263,11 +263,15 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||||
Preference.PreferenceItem.SliderPreference(
|
Preference.PreferenceItem.SliderPreference(
|
||||||
value = previewsRowCount,
|
value = previewsRowCount,
|
||||||
title = stringResource(SYMR.strings.pref_previews_row_count),
|
title = stringResource(SYMR.strings.pref_previews_row_count),
|
||||||
subtitle = if (previewsRowCount > 0) pluralStringResource(
|
subtitle = if (previewsRowCount > 0) {
|
||||||
SYMR.plurals.row_count,
|
pluralStringResource(
|
||||||
previewsRowCount,
|
SYMR.plurals.row_count,
|
||||||
previewsRowCount,
|
previewsRowCount,
|
||||||
) else stringResource(MR.strings.disabled),
|
previewsRowCount,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(MR.strings.disabled)
|
||||||
|
},
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 10,
|
max = 10,
|
||||||
onValueChanged = {
|
onValueChanged = {
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ object SettingsBrowseScreen : SearchableSettings {
|
||||||
pref = uiPreferences.feedTabInFront(),
|
pref = uiPreferences.feedTabInFront(),
|
||||||
title = stringResource(SYMR.strings.pref_feed_position),
|
title = stringResource(SYMR.strings.pref_feed_position),
|
||||||
subtitle = stringResource(SYMR.strings.pref_feed_position_summery),
|
subtitle = stringResource(SYMR.strings.pref_feed_position_summery),
|
||||||
enabled = hideFeedTab.not()
|
enabled = hideFeedTab.not(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ object AboutScreen : Screen() {
|
||||||
onPreferenceClick = {
|
onPreferenceClick = {
|
||||||
uriHandler.openUri(
|
uriHandler.openUri(
|
||||||
"https://crowdin.com/project/komikku/" +
|
"https://crowdin.com/project/komikku/" +
|
||||||
"invite?h=f922abd4193e77309b084a08c74b89872112170"
|
"invite?h=f922abd4193e77309b084a08c74b89872112170",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
|
||||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||||
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
||||||
import tachiyomi.presentation.core.components.SectionCard
|
import tachiyomi.presentation.core.components.SectionCard
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ fun ExhUtils(
|
||||||
modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor),
|
.background(backgroundColor),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(visible = isVisible) {
|
AnimatedVisibility(visible = isVisible) {
|
||||||
Column {
|
Column {
|
||||||
|
|
@ -84,7 +84,7 @@ fun ExhUtils(
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(3f),
|
Modifier.weight(3f),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(SYMR.strings.eh_autoscroll),
|
text = stringResource(SYMR.strings.eh_autoscroll),
|
||||||
|
|
@ -93,17 +93,17 @@ fun ExhUtils(
|
||||||
fontFamily = FontFamily.SansSerif,
|
fontFamily = FontFamily.SansSerif,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
modifier = Modifier.fillMaxWidth(0.75f),
|
modifier = Modifier.fillMaxWidth(0.75f),
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(1f),
|
Modifier.weight(1f),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Switch(
|
Switch(
|
||||||
checked = isAutoScroll,
|
checked = isAutoScroll,
|
||||||
onCheckedChange = null,
|
onCheckedChange = null,
|
||||||
enabled = isAutoScrollEnabled
|
enabled = isAutoScrollEnabled,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +114,7 @@ fun ExhUtils(
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(3f),
|
Modifier.weight(3f),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
var autoScrollFrequencyState by remember {
|
var autoScrollFrequencyState by remember {
|
||||||
mutableStateOf(autoScrollFrequency)
|
mutableStateOf(autoScrollFrequency)
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,10 @@ internal fun LazyListScope.updatesUiItems(
|
||||||
readProgress = updatesItem.update.lastPageRead
|
readProgress = updatesItem.update.lastPageRead
|
||||||
.takeIf {
|
.takeIf {
|
||||||
/* SY --> */(
|
/* SY --> */(
|
||||||
!updatesItem.update.read || (preserveReadingPosition && updatesItem.isEhBasedUpdate())
|
!updatesItem.update.read ||
|
||||||
)/* SY <-- */ && it > 0L
|
(preserveReadingPosition && updatesItem.isEhBasedUpdate())
|
||||||
|
)/* SY <-- */ &&
|
||||||
|
it > 0L
|
||||||
}
|
}
|
||||||
?.let {
|
?.let {
|
||||||
stringResource(
|
stringResource(
|
||||||
|
|
|
||||||
|
|
@ -185,8 +185,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||||
|
|
||||||
val syncPreferences: SyncPreferences = Injekt.get()
|
val syncPreferences: SyncPreferences = Injekt.get()
|
||||||
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
||||||
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppStart
|
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppStart) {
|
||||||
) {
|
|
||||||
SyncDataJob.startNow(this@App)
|
SyncDataJob.startNow(this@App)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,8 +246,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||||
|
|
||||||
val syncPreferences: SyncPreferences = Injekt.get()
|
val syncPreferences: SyncPreferences = Injekt.get()
|
||||||
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
||||||
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppResume
|
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppResume) {
|
||||||
) {
|
|
||||||
SyncDataJob.startNow(this@App)
|
SyncDataJob.startNow(this@App)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +342,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||||
"""
|
"""
|
||||||
App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.FLAVOR}, ${BuildConfig.COMMIT_SHA}, ${BuildConfig.VERSION_CODE})
|
App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.FLAVOR}, ${BuildConfig.COMMIT_SHA}, ${BuildConfig.VERSION_CODE})
|
||||||
Build version: ${BuildConfig.COMMIT_COUNT}
|
Build version: ${BuildConfig.COMMIT_COUNT}
|
||||||
Android version: ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT})
|
Android version: ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT})
|
||||||
Android build ID: ${Build.DISPLAY}
|
Android build ID: ${Build.DISPLAY}
|
||||||
Device brand: ${Build.BRAND}
|
Device brand: ${Build.BRAND}
|
||||||
Device manufacturer: ${Build.MANUFACTURER}
|
Device manufacturer: ${Build.MANUFACTURER}
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,11 @@ class BackupCreator(
|
||||||
}
|
}
|
||||||
|
|
||||||
val databaseManga = getFavorites.await() /* SY --> */ +
|
val databaseManga = getFavorites.await() /* SY --> */ +
|
||||||
if (options.readEntries) {
|
if (options.readEntries) {
|
||||||
handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
|
handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
} + getMergedManga.await() // SY <--
|
} + getMergedManga.await() // SY <--
|
||||||
val backupManga = backupMangas(databaseManga, options)
|
val backupManga = backupMangas(databaseManga, options)
|
||||||
val backup = Backup(
|
val backup = Backup(
|
||||||
backupManga = backupManga,
|
backupManga = backupManga,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class FeedBackupCreator(
|
class FeedBackupCreator(
|
||||||
private val handler: DatabaseHandler = Injekt.get()
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class SavedSearchBackupCreator(
|
class SavedSearchBackupCreator(
|
||||||
private val handler: DatabaseHandler = Injekt.get()
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun backupSavedSearches(): List<BackupSavedSearch> {
|
suspend fun backupSavedSearches(): List<BackupSavedSearch> {
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ data class BackupMergedMangaReference(
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupMergedMangaReferenceMapper =
|
val backupMergedMangaReferenceMapper =
|
||||||
{ _: Long,
|
{
|
||||||
|
_: Long,
|
||||||
isInfoManga: Boolean,
|
isInfoManga: Boolean,
|
||||||
getChapterUpdates: Boolean,
|
getChapterUpdates: Boolean,
|
||||||
chapterSortMode: Long,
|
chapterSortMode: Long,
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,20 @@ data class BackupTracking(
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupTrackMapper = {
|
val backupTrackMapper = {
|
||||||
_: Long, _: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastChapterRead: Double, totalChapters: Long, status: Long, score: Double, remoteUrl: String, startDate: Long, finishDate: Long ->
|
_: Long,
|
||||||
|
_: Long,
|
||||||
|
syncId: Long,
|
||||||
|
mediaId: Long,
|
||||||
|
libraryId: Long?,
|
||||||
|
title: String,
|
||||||
|
lastChapterRead: Double,
|
||||||
|
totalChapters: Long,
|
||||||
|
status: Long,
|
||||||
|
score: Double,
|
||||||
|
remoteUrl: String,
|
||||||
|
startDate: Long,
|
||||||
|
finishDate: Long,
|
||||||
|
->
|
||||||
BackupTracking(
|
BackupTracking(
|
||||||
syncId = syncId.toInt(),
|
syncId = syncId.toInt(),
|
||||||
mediaId = mediaId,
|
mediaId = mediaId,
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,17 @@ data class RestoreOptions(
|
||||||
extensionRepoSettings,
|
extensionRepoSettings,
|
||||||
sourceSettings,
|
sourceSettings,
|
||||||
// SY -->
|
// SY -->
|
||||||
savedSearches
|
savedSearches,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
||||||
fun canRestore() = libraryEntries || categories || appSettings || extensionRepoSettings || sourceSettings ||
|
fun canRestore() =
|
||||||
// SY -->
|
libraryEntries ||
|
||||||
savedSearches
|
categories ||
|
||||||
// SY <--
|
appSettings ||
|
||||||
|
extensionRepoSettings ||
|
||||||
|
sourceSettings /* SY --> */ ||
|
||||||
|
savedSearches /* SY <-- */
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val options = persistentListOf(
|
val options = persistentListOf(
|
||||||
|
|
@ -75,7 +78,7 @@ data class RestoreOptions(
|
||||||
extensionRepoSettings = array[3],
|
extensionRepoSettings = array[3],
|
||||||
sourceSettings = array[4],
|
sourceSettings = array[4],
|
||||||
// SY -->
|
// SY -->
|
||||||
savedSearches = array[5]
|
savedSearches = array[5],
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ class ChapterCache(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val json: Json,
|
private val json: Json,
|
||||||
// SY -->
|
// SY -->
|
||||||
readerPreferences: ReaderPreferences
|
readerPreferences: ReaderPreferences,
|
||||||
//S Y <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// --> EH
|
// --> EH
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,11 @@ object MangaCoverMetadata {
|
||||||
|
|
||||||
val options = BitmapFactory.Options()
|
val options = BitmapFactory.Options()
|
||||||
|
|
||||||
val updateColors = mangaCover.isMangaFavorite && mangaCover.dominantCoverColors == null ||
|
val updateColors = mangaCover.isMangaFavorite &&
|
||||||
!onlyDominantColor && mangaCover.vibrantCoverColor == null || force
|
mangaCover.dominantCoverColors == null ||
|
||||||
|
!onlyDominantColor &&
|
||||||
|
mangaCover.vibrantCoverColor == null ||
|
||||||
|
force
|
||||||
|
|
||||||
if (updateColors) {
|
if (updateColors) {
|
||||||
/**
|
/**
|
||||||
|
|
@ -123,7 +126,9 @@ object MangaCoverMetadata {
|
||||||
bufferedSource != null -> BitmapFactory.decodeStream(bufferedSource.inputStream(), null, options)
|
bufferedSource != null -> BitmapFactory.decodeStream(bufferedSource.inputStream(), null, options)
|
||||||
// if the file exists and the there was still an error then the file is corrupted
|
// if the file exists and the there was still an error then the file is corrupted
|
||||||
file?.exists() == true -> BitmapFactory.decodeFile(file.path, options)
|
file?.exists() == true -> BitmapFactory.decodeFile(file.path, options)
|
||||||
else -> { return }
|
else -> {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class PagePreviewFetcher(
|
||||||
source = ImageSource(
|
source = ImageSource(
|
||||||
file = file.toOkioPath(),
|
file = file.toOkioPath(),
|
||||||
fileSystem = FileSystem.SYSTEM,
|
fileSystem = FileSystem.SYSTEM,
|
||||||
diskCacheKey = diskCacheKey
|
diskCacheKey = diskCacheKey,
|
||||||
),
|
),
|
||||||
mimeType = "image/*",
|
mimeType = "image/*",
|
||||||
dataSource = DataSource.DISK,
|
dataSource = DataSource.DISK,
|
||||||
|
|
@ -229,7 +229,7 @@ class PagePreviewFetcher(
|
||||||
file = data,
|
file = data,
|
||||||
fileSystem = FileSystem.SYSTEM,
|
fileSystem = FileSystem.SYSTEM,
|
||||||
diskCacheKey = diskCacheKey,
|
diskCacheKey = diskCacheKey,
|
||||||
closeable = this
|
closeable = this,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,8 @@ class DownloadProvider(
|
||||||
getValidChapterDirNames(chp.name, chp.scanlator).any { dir ->
|
getValidChapterDirNames(chp.name, chp.scanlator).any { dir ->
|
||||||
mangaDir.findFile(dir) != null
|
mangaDir.findFile(dir) != null
|
||||||
}
|
}
|
||||||
} == null || it.name?.endsWith(Downloader.TMP_DIR_SUFFIX) == true
|
} == null ||
|
||||||
|
it.name?.endsWith(Downloader.TMP_DIR_SUFFIX) == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
|
||||||
|
|
@ -375,14 +375,17 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
async {
|
async {
|
||||||
semaphore.withPermit {
|
semaphore.withPermit {
|
||||||
if (
|
if (
|
||||||
mdlistLogged && mangaInSource.firstOrNull()
|
mdlistLogged &&
|
||||||
|
mangaInSource.firstOrNull()
|
||||||
?.let { it.manga.source in mangaDexSourceIds } == true
|
?.let { it.manga.source in mangaDexSourceIds } == true
|
||||||
) {
|
) {
|
||||||
launch {
|
launch {
|
||||||
mangaInSource.forEach { (manga) ->
|
mangaInSource.forEach { (manga) ->
|
||||||
try {
|
try {
|
||||||
val tracks = getTracks.await(manga.id)
|
val tracks = getTracks.await(manga.id)
|
||||||
if (tracks.isEmpty() || tracks.none { it.trackerId == TrackerManager.MDLIST }) {
|
if (tracks.isEmpty() ||
|
||||||
|
tracks.none { it.trackerId == TrackerManager.MDLIST }
|
||||||
|
) {
|
||||||
val track = mdList.createInitialTracker(manga)
|
val track = mdList.createInitialTracker(manga)
|
||||||
insertTrack.await(mdList.refresh(track).toDomainTrack(false)!!)
|
insertTrack.await(mdList.refresh(track).toDomainTrack(false)!!)
|
||||||
}
|
}
|
||||||
|
|
@ -412,10 +415,14 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
// SY -->
|
// SY -->
|
||||||
.sortedByDescending { it.sourceOrder }.run {
|
.sortedByDescending { it.sourceOrder }.run {
|
||||||
if (libraryPreferences.libraryReadDuplicateChapters().get()) {
|
if (libraryPreferences.libraryReadDuplicateChapters().get()) {
|
||||||
val readChapters = getChaptersByMangaId.await(manga.id).filter { it.read }
|
val readChapters = getChaptersByMangaId.await(manga.id).filter {
|
||||||
|
it.read
|
||||||
|
}
|
||||||
val newReadChapters = this.filter { chapter ->
|
val newReadChapters = this.filter { chapter ->
|
||||||
chapter.chapterNumber > 0 &&
|
chapter.chapterNumber > 0 &&
|
||||||
readChapters.any { it.chapterNumber == chapter.chapterNumber }
|
readChapters.any {
|
||||||
|
it.chapterNumber == chapter.chapterNumber
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newReadChapters.isNotEmpty()) {
|
if (newReadChapters.isNotEmpty()) {
|
||||||
|
|
@ -427,7 +434,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SY <--
|
// SY <--
|
||||||
|
|
||||||
if (newChapters.isNotEmpty()) {
|
if (newChapters.isNotEmpty()) {
|
||||||
val categoryIds = getCategories.await(manga.id).map { it.id }
|
val categoryIds = getCategories.await(manga.id).map { it.id }
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,9 @@ class GoogleDriveSyncService(context: Context, json: Json, syncPreferences: Sync
|
||||||
appProperties = mapOf("deviceId" to syncData.deviceId)
|
appProperties = mapOf("deviceId" to syncData.deviceId)
|
||||||
}
|
}
|
||||||
drive.files().update(fileId, fileMetadata, mediaContent).execute()
|
drive.files().update(fileId, fileMetadata, mediaContent).execute()
|
||||||
logcat(LogPriority.DEBUG) { "Updated existing sync data file in Google Drive with file ID: $fileId" }
|
logcat(LogPriority.DEBUG) {
|
||||||
|
"Updated existing sync data file in Google Drive with file ID: $fileId"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val fileMetadata = File().apply {
|
val fileMetadata = File().apply {
|
||||||
name = remoteFileName
|
name = remoteFileName
|
||||||
|
|
@ -175,7 +177,9 @@ class GoogleDriveSyncService(context: Context, json: Json, syncPreferences: Sync
|
||||||
val uploadedFile = drive.files().create(fileMetadata, mediaContent)
|
val uploadedFile = drive.files().create(fileMetadata, mediaContent)
|
||||||
.setFields("id")
|
.setFields("id")
|
||||||
.execute()
|
.execute()
|
||||||
logcat(LogPriority.DEBUG) { "Created new sync data file in Google Drive with file ID: ${uploadedFile.id}" }
|
logcat(LogPriority.DEBUG) {
|
||||||
|
"Created new sync data file in Google Drive with file ID: ${uploadedFile.id}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ abstract class SyncService(
|
||||||
val json: Json,
|
val json: Json,
|
||||||
val syncPreferences: SyncPreferences,
|
val syncPreferences: SyncPreferences,
|
||||||
) {
|
) {
|
||||||
abstract suspend fun doSync(syncData: SyncData): Backup?;
|
abstract suspend fun doSync(syncData: SyncData): Backup?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the local and remote sync data into a single JSON string.
|
* Merges the local and remote sync data into a single JSON string.
|
||||||
|
|
@ -44,7 +44,8 @@ abstract class SyncService(
|
||||||
remoteSyncData.backup?.backupManga,
|
remoteSyncData.backup?.backupManga,
|
||||||
localSyncData.backup?.backupCategories ?: emptyList(),
|
localSyncData.backup?.backupCategories ?: emptyList(),
|
||||||
remoteSyncData.backup?.backupCategories ?: emptyList(),
|
remoteSyncData.backup?.backupCategories ?: emptyList(),
|
||||||
mergedCategoriesList)
|
mergedCategoriesList,
|
||||||
|
)
|
||||||
|
|
||||||
val mergedSourcesList =
|
val mergedSourcesList =
|
||||||
mergeSourcesLists(localSyncData.backup?.backupSources, remoteSyncData.backup?.backupSources)
|
mergeSourcesLists(localSyncData.backup?.backupSources, remoteSyncData.backup?.backupSources)
|
||||||
|
|
@ -120,11 +121,13 @@ abstract class SyncService(
|
||||||
val mergedCategoriesMapByName = mergedCategories.associateBy { it.name }
|
val mergedCategoriesMapByName = mergedCategories.associateBy { it.name }
|
||||||
|
|
||||||
fun updateCategories(theManga: BackupManga, theMap: Map<Long, BackupCategory>): BackupManga {
|
fun updateCategories(theManga: BackupManga, theMap: Map<Long, BackupCategory>): BackupManga {
|
||||||
return theManga.copy(categories = theManga.categories.mapNotNull {
|
return theManga.copy(
|
||||||
theMap[it]?.let { category ->
|
categories = theManga.categories.mapNotNull {
|
||||||
mergedCategoriesMapByName[category.name]?.order
|
theMap[it]?.let { category ->
|
||||||
}
|
mergedCategoriesMapByName[category.name]?.order
|
||||||
})
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
|
@ -147,7 +150,7 @@ abstract class SyncService(
|
||||||
}
|
}
|
||||||
updateCategories(
|
updateCategories(
|
||||||
local.copy(chapters = mergeChapters(local.chapters, remote.chapters)),
|
local.copy(chapters = mergeChapters(local.chapters, remote.chapters)),
|
||||||
localCategoriesMapByOrder
|
localCategoriesMapByOrder,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
|
@ -155,7 +158,7 @@ abstract class SyncService(
|
||||||
}
|
}
|
||||||
updateCategories(
|
updateCategories(
|
||||||
remote.copy(chapters = mergeChapters(local.chapters, remote.chapters)),
|
remote.copy(chapters = mergeChapters(local.chapters, remote.chapters)),
|
||||||
remoteCategoriesMapByOrder
|
remoteCategoriesMapByOrder,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +304,7 @@ abstract class SyncService(
|
||||||
|
|
||||||
private fun mergeSourcesLists(
|
private fun mergeSourcesLists(
|
||||||
localSources: List<BackupSource>?,
|
localSources: List<BackupSource>?,
|
||||||
remoteSources: List<BackupSource>?
|
remoteSources: List<BackupSource>?,
|
||||||
): List<BackupSource> {
|
): List<BackupSource> {
|
||||||
val logTag = "MergeSources"
|
val logTag = "MergeSources"
|
||||||
|
|
||||||
|
|
@ -346,7 +349,7 @@ abstract class SyncService(
|
||||||
|
|
||||||
private fun mergePreferencesLists(
|
private fun mergePreferencesLists(
|
||||||
localPreferences: List<BackupPreference>?,
|
localPreferences: List<BackupPreference>?,
|
||||||
remotePreferences: List<BackupPreference>?
|
remotePreferences: List<BackupPreference>?,
|
||||||
): List<BackupPreference> {
|
): List<BackupPreference> {
|
||||||
val logTag = "MergePreferences"
|
val logTag = "MergePreferences"
|
||||||
|
|
||||||
|
|
@ -394,7 +397,7 @@ abstract class SyncService(
|
||||||
|
|
||||||
private fun mergeSourcePreferencesLists(
|
private fun mergeSourcePreferencesLists(
|
||||||
localPreferences: List<BackupSourcePreferences>?,
|
localPreferences: List<BackupSourcePreferences>?,
|
||||||
remotePreferences: List<BackupSourcePreferences>?
|
remotePreferences: List<BackupSourcePreferences>?,
|
||||||
): List<BackupSourcePreferences> {
|
): List<BackupSourcePreferences> {
|
||||||
val logTag = "MergeSourcePreferences"
|
val logTag = "MergeSourcePreferences"
|
||||||
|
|
||||||
|
|
@ -408,38 +411,39 @@ abstract class SyncService(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge both source preferences maps
|
// Merge both source preferences maps
|
||||||
val mergedSourcePreferences = (localPreferencesMap.keys + remotePreferencesMap.keys).distinct().mapNotNull { sourceKey ->
|
val mergedSourcePreferences = (localPreferencesMap.keys + remotePreferencesMap.keys).distinct()
|
||||||
val localSourcePreference = localPreferencesMap[sourceKey]
|
.mapNotNull { sourceKey ->
|
||||||
val remoteSourcePreference = remotePreferencesMap[sourceKey]
|
val localSourcePreference = localPreferencesMap[sourceKey]
|
||||||
|
val remoteSourcePreference = remotePreferencesMap[sourceKey]
|
||||||
|
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
"Processing source preference key: $sourceKey. " +
|
"Processing source preference key: $sourceKey. " +
|
||||||
"Local source preference: ${localSourcePreference != null}, " +
|
"Local source preference: ${localSourcePreference != null}, " +
|
||||||
"Remote source preference: ${remoteSourcePreference != null}"
|
"Remote source preference: ${remoteSourcePreference != null}"
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
localSourcePreference != null && remoteSourcePreference == null -> {
|
localSourcePreference != null && remoteSourcePreference == null -> {
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
"Using local source preference: ${localSourcePreference.sourceKey}."
|
"Using local source preference: ${localSourcePreference.sourceKey}."
|
||||||
|
}
|
||||||
|
localSourcePreference
|
||||||
}
|
}
|
||||||
localSourcePreference
|
remoteSourcePreference != null && localSourcePreference == null -> {
|
||||||
}
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
remoteSourcePreference != null && localSourcePreference == null -> {
|
"Using remote source preference: ${remoteSourcePreference.sourceKey}."
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
}
|
||||||
"Using remote source preference: ${remoteSourcePreference.sourceKey}."
|
remoteSourcePreference
|
||||||
}
|
}
|
||||||
remoteSourcePreference
|
localSourcePreference != null && remoteSourcePreference != null -> {
|
||||||
|
// Merge the individual preferences within the source preferences
|
||||||
|
val mergedPrefs =
|
||||||
|
mergeIndividualPreferences(localSourcePreference.prefs, remoteSourcePreference.prefs)
|
||||||
|
BackupSourcePreferences(sourceKey, mergedPrefs)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
localSourcePreference != null && remoteSourcePreference != null -> {
|
|
||||||
// Merge the individual preferences within the source preferences
|
|
||||||
val mergedPrefs =
|
|
||||||
mergeIndividualPreferences(localSourcePreference.prefs, remoteSourcePreference.prefs)
|
|
||||||
BackupSourcePreferences(sourceKey, mergedPrefs)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
"Source preferences merge completed. Total merged source preferences: ${mergedSourcePreferences.size}"
|
"Source preferences merge completed. Total merged source preferences: ${mergedSourcePreferences.size}"
|
||||||
|
|
@ -450,7 +454,7 @@ abstract class SyncService(
|
||||||
|
|
||||||
private fun mergeIndividualPreferences(
|
private fun mergeIndividualPreferences(
|
||||||
localPrefs: List<BackupPreference>,
|
localPrefs: List<BackupPreference>,
|
||||||
remotePrefs: List<BackupPreference>
|
remotePrefs: List<BackupPreference>,
|
||||||
): List<BackupPreference> {
|
): List<BackupPreference> {
|
||||||
val mergedPrefsMap = (localPrefs + remotePrefs).associateBy { it.key }
|
val mergedPrefsMap = (localPrefs + remotePrefs).associateBy { it.key }
|
||||||
return mergedPrefsMap.values.toList()
|
return mergedPrefsMap.values.toList()
|
||||||
|
|
@ -459,7 +463,7 @@ abstract class SyncService(
|
||||||
// SY -->
|
// SY -->
|
||||||
private fun mergeSavedSearchesLists(
|
private fun mergeSavedSearchesLists(
|
||||||
localSearches: List<BackupSavedSearch>?,
|
localSearches: List<BackupSavedSearch>?,
|
||||||
remoteSearches: List<BackupSavedSearch>?
|
remoteSearches: List<BackupSavedSearch>?,
|
||||||
): List<BackupSavedSearch> {
|
): List<BackupSavedSearch> {
|
||||||
val logTag = "MergeSavedSearches"
|
val logTag = "MergeSavedSearches"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class SyncYomiSyncService(
|
||||||
try {
|
try {
|
||||||
val (remoteData, etag) = pullSyncData()
|
val (remoteData, etag) = pullSyncData()
|
||||||
|
|
||||||
val finalSyncData = if (remoteData != null){
|
val finalSyncData = if (remoteData != null) {
|
||||||
assert(etag.isNotEmpty()) { "ETag should never be empty if remote data is not null" }
|
assert(etag.isNotEmpty()) { "ETag should never be empty if remote data is not null" }
|
||||||
logcat(LogPriority.DEBUG, "SyncService") {
|
logcat(LogPriority.DEBUG, "SyncService") {
|
||||||
"Try update remote data with ETag($etag)"
|
"Try update remote data with ETag($etag)"
|
||||||
|
|
@ -54,7 +54,6 @@ class SyncYomiSyncService(
|
||||||
|
|
||||||
pushSyncData(finalSyncData, etag)
|
pushSyncData(finalSyncData, etag)
|
||||||
return finalSyncData.backup
|
return finalSyncData.backup
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logcat(LogPriority.ERROR) { "Error syncing: ${e.message}" }
|
logcat(LogPriority.ERROR) { "Error syncing: ${e.message}" }
|
||||||
notifier.showSyncError(e.message)
|
notifier.showSyncError(e.message)
|
||||||
|
|
@ -113,7 +112,6 @@ class SyncYomiSyncService(
|
||||||
// return default value so we can overwrite it
|
// return default value so we can overwrite it
|
||||||
Pair(null, "")
|
Pair(null, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val responseBody = response.body.string()
|
val responseBody = response.body.string()
|
||||||
notifier.showSyncError("Failed to download sync data: $responseBody")
|
notifier.showSyncError("Failed to download sync data: $responseBody")
|
||||||
|
|
@ -165,11 +163,9 @@ class SyncYomiSyncService(
|
||||||
.takeIf { it?.isNotEmpty() == true } ?: throw SyncYomiException("Missing ETag")
|
.takeIf { it?.isNotEmpty() == true } ?: throw SyncYomiException("Missing ETag")
|
||||||
syncPreferences.lastSyncEtag().set(newETag)
|
syncPreferences.lastSyncEtag().set(newETag)
|
||||||
logcat(LogPriority.DEBUG) { "SyncYomi sync completed" }
|
logcat(LogPriority.DEBUG) { "SyncYomi sync completed" }
|
||||||
|
|
||||||
} else if (response.code == HttpStatus.SC_PRECONDITION_FAILED) {
|
} else if (response.code == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||||
// other clients updated remote data, will try next time
|
// other clients updated remote data, will try next time
|
||||||
logcat(LogPriority.DEBUG) { "SyncYomi sync failed with 412" }
|
logcat(LogPriority.DEBUG) { "SyncYomi sync failed with 412" }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val responseBody = response.body.string()
|
val responseBody = response.body.string()
|
||||||
notifier.showSyncError("Failed to upload sync data: $responseBody")
|
notifier.showSyncError("Failed to upload sync data: $responseBody")
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ class ExtensionManager(
|
||||||
val installedExtensionsFlow = installedExtensionMapFlow.mapExtensions(scope)
|
val installedExtensionsFlow = installedExtensionMapFlow.mapExtensions(scope)
|
||||||
|
|
||||||
private val availableExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Available>())
|
private val availableExtensionMapFlow = MutableStateFlow(emptyMap<String, Extension.Available>())
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val availableExtensionsFlow = availableExtensionMapFlow.map { it.filterNotBlacklisted().values.toList() }
|
val availableExtensionsFlow = availableExtensionMapFlow.map { it.filterNotBlacklisted().values.toList() }
|
||||||
.stateIn(scope, SharingStarted.Lazily, availableExtensionMapFlow.value.values.toList())
|
.stateIn(scope, SharingStarted.Lazily, availableExtensionMapFlow.value.values.toList())
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,10 @@ internal class ExtensionApi {
|
||||||
private val getExtensionRepo: GetExtensionRepo by injectLazy()
|
private val getExtensionRepo: GetExtensionRepo by injectLazy()
|
||||||
private val updateExtensionRepo: UpdateExtensionRepo by injectLazy()
|
private val updateExtensionRepo: UpdateExtensionRepo by injectLazy()
|
||||||
private val extensionManager: ExtensionManager by injectLazy()
|
private val extensionManager: ExtensionManager by injectLazy()
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
private val sourcePreferences: SourcePreferences by injectLazy()
|
private val sourcePreferences: SourcePreferences by injectLazy()
|
||||||
|
|
||||||
// SY <--
|
// SY <--
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ class EHentai(
|
||||||
doc.select("#gdd .gdt1").find { el ->
|
doc.select("#gdd .gdt1").find { el ->
|
||||||
el.text().lowercase() == "posted:"
|
el.text().lowercase() == "posted:"
|
||||||
}!!.nextElementSibling()!!.text(),
|
}!!.nextElementSibling()!!.text(),
|
||||||
MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC)
|
MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC),
|
||||||
)!!.toInstant().toEpochMilli(),
|
)!!.toInstant().toEpochMilli(),
|
||||||
scanlator = EHentaiSearchMetadata.galleryId(location),
|
scanlator = EHentaiSearchMetadata.galleryId(location),
|
||||||
)
|
)
|
||||||
|
|
@ -401,7 +401,7 @@ class EHentai(
|
||||||
chapter_number = index + 2f,
|
chapter_number = index + 2f,
|
||||||
date_upload = ZonedDateTime.parse(
|
date_upload = ZonedDateTime.parse(
|
||||||
posted,
|
posted,
|
||||||
MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC)
|
MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC),
|
||||||
).toInstant().toEpochMilli(),
|
).toInstant().toEpochMilli(),
|
||||||
scanlator = EHentaiSearchMetadata.galleryId(link),
|
scanlator = EHentaiSearchMetadata.galleryId(link),
|
||||||
)
|
)
|
||||||
|
|
@ -542,9 +542,10 @@ class EHentai(
|
||||||
if (
|
if (
|
||||||
MATCH_SEEK_REGEX.matches(jumpSeekValue) ||
|
MATCH_SEEK_REGEX.matches(jumpSeekValue) ||
|
||||||
(
|
(
|
||||||
MATCH_YEAR_REGEX.matches(jumpSeekValue) && jumpSeekValue.toIntOrNull()?.let {
|
MATCH_YEAR_REGEX.matches(jumpSeekValue) &&
|
||||||
it in 2007..2099
|
jumpSeekValue.toIntOrNull()?.let {
|
||||||
} == true
|
it in 2007..2099
|
||||||
|
} == true
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
uri.appendQueryParameter("seek", jumpSeekValue)
|
uri.appendQueryParameter("seek", jumpSeekValue)
|
||||||
|
|
@ -715,7 +716,7 @@ class EHentai(
|
||||||
when (left.removeSuffix(":").lowercase()) {
|
when (left.removeSuffix(":").lowercase()) {
|
||||||
"posted" -> datePosted = ZonedDateTime.parse(
|
"posted" -> datePosted = ZonedDateTime.parse(
|
||||||
right,
|
right,
|
||||||
MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC)
|
MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC),
|
||||||
).toInstant().toEpochMilli()
|
).toInstant().toEpochMilli()
|
||||||
// Example gallery with parent: https://e-hentai.org/g/1390451/7f181c2426/
|
// Example gallery with parent: https://e-hentai.org/g/1390451/7f181c2426/
|
||||||
// Example JP gallery: https://exhentai.org/g/1375385/03519d541b/
|
// Example JP gallery: https://exhentai.org/g/1375385/03519d541b/
|
||||||
|
|
|
||||||
|
|
@ -119,12 +119,13 @@ class MergedSource : HttpSource() {
|
||||||
"Manga references are empty, chapters unavailable, merge is likely corrupted"
|
"Manga references are empty, chapters unavailable, merge is likely corrupted"
|
||||||
}
|
}
|
||||||
|
|
||||||
val ifDownloadNewChapters = downloadChapters && manga.shouldDownloadNewChapters(
|
val ifDownloadNewChapters = downloadChapters &&
|
||||||
getCategories.await(manga.id).map {
|
manga.shouldDownloadNewChapters(
|
||||||
it.id
|
getCategories.await(manga.id).map {
|
||||||
},
|
it.id
|
||||||
downloadPreferences,
|
},
|
||||||
)
|
downloadPreferences,
|
||||||
|
)
|
||||||
val semaphore = Semaphore(5)
|
val semaphore = Semaphore(5)
|
||||||
var exception: Exception? = null
|
var exception: Exception? = null
|
||||||
return supervisorScope {
|
return supervisorScope {
|
||||||
|
|
|
||||||
|
|
@ -73,16 +73,17 @@ interface SecureActivityDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
val lockedDays = preferences.authenticatorDays().get()
|
val lockedDays = preferences.authenticatorDays().get()
|
||||||
val canLockToday = lockedDays == LOCK_ALL_DAYS || when (today.get(Calendar.DAY_OF_WEEK)) {
|
val canLockToday = lockedDays == LOCK_ALL_DAYS ||
|
||||||
Calendar.SUNDAY -> (lockedDays and LOCK_SUNDAY) == LOCK_SUNDAY
|
when (today.get(Calendar.DAY_OF_WEEK)) {
|
||||||
Calendar.MONDAY -> (lockedDays and LOCK_MONDAY) == LOCK_MONDAY
|
Calendar.SUNDAY -> (lockedDays and LOCK_SUNDAY) == LOCK_SUNDAY
|
||||||
Calendar.TUESDAY -> (lockedDays and LOCK_TUESDAY) == LOCK_TUESDAY
|
Calendar.MONDAY -> (lockedDays and LOCK_MONDAY) == LOCK_MONDAY
|
||||||
Calendar.WEDNESDAY -> (lockedDays and LOCK_WEDNESDAY) == LOCK_WEDNESDAY
|
Calendar.TUESDAY -> (lockedDays and LOCK_TUESDAY) == LOCK_TUESDAY
|
||||||
Calendar.THURSDAY -> (lockedDays and LOCK_THURSDAY) == LOCK_THURSDAY
|
Calendar.WEDNESDAY -> (lockedDays and LOCK_WEDNESDAY) == LOCK_WEDNESDAY
|
||||||
Calendar.FRIDAY -> (lockedDays and LOCK_FRIDAY) == LOCK_FRIDAY
|
Calendar.THURSDAY -> (lockedDays and LOCK_THURSDAY) == LOCK_THURSDAY
|
||||||
Calendar.SATURDAY -> (lockedDays and LOCK_SATURDAY) == LOCK_SATURDAY
|
Calendar.FRIDAY -> (lockedDays and LOCK_FRIDAY) == LOCK_FRIDAY
|
||||||
else -> false
|
Calendar.SATURDAY -> (lockedDays and LOCK_SATURDAY) == LOCK_SATURDAY
|
||||||
}
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
return canLockNow && canLockToday
|
return canLockNow && canLockToday
|
||||||
}
|
}
|
||||||
|
|
@ -99,11 +100,13 @@ interface SecureActivityDelegate {
|
||||||
|
|
||||||
// `requireUnlock` can be true on process start or if app was closed in locked state
|
// `requireUnlock` can be true on process start or if app was closed in locked state
|
||||||
if (!AuthenticatorUtil.isAuthenticating && !requireUnlock) {
|
if (!AuthenticatorUtil.isAuthenticating && !requireUnlock) {
|
||||||
requireUnlock = /* SY --> */ canLockNow(preferences) && /* SY <-- */ when (val lockDelay = preferences.lockAppAfter().get()) {
|
requireUnlock =
|
||||||
-1 -> false // Never
|
/* SY --> */ canLockNow(preferences) &&
|
||||||
0 -> true // Always
|
/* SY <-- */ when (val lockDelay = preferences.lockAppAfter().get()) {
|
||||||
else -> lastClosedPref.get() + lockDelay * 60_000 <= System.currentTimeMillis()
|
-1 -> false // Never
|
||||||
}
|
0 -> true // Always
|
||||||
|
else -> lastClosedPref.get() + lockDelay * 60_000 <= System.currentTimeMillis()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastClosedPref.delete()
|
lastClosedPref.delete()
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ fun feedTab(
|
||||||
onMoveBottom = {
|
onMoveBottom = {
|
||||||
dialog.nextFeed?.let { screenModel.moveToBottom(dialog.feedItem.feed) }
|
dialog.nextFeed?.let { screenModel.moveToBottom(dialog.feedItem.feed) }
|
||||||
screenModel.dismissDialog()
|
screenModel.dismissDialog()
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,11 @@ class MigrationListScreen(private val config: MigrationProcedureConfig) : Screen
|
||||||
)
|
)
|
||||||
|
|
||||||
val onDismissRequest = { screenModel.dialog.value = null }
|
val onDismissRequest = { screenModel.dialog.value = null }
|
||||||
when (@Suppress("NAME_SHADOWING") val dialog = dialog) {
|
when
|
||||||
|
(
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val dialog = dialog
|
||||||
|
) {
|
||||||
is MigrationListScreenModel.Dialog.MigrateMangaDialog -> {
|
is MigrationListScreenModel.Dialog.MigrateMangaDialog -> {
|
||||||
MigrationMangaDialog(
|
MigrationMangaDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,9 @@ class MigrationListScreenModel(
|
||||||
smartSearchEngine.normalSearch(source, mangaObj.ogTitle)
|
smartSearchEngine.normalSearch(source, mangaObj.ogTitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchResult != null && !(searchResult.url == mangaObj.url && source.id == mangaObj.source)) {
|
if (searchResult != null &&
|
||||||
|
!(searchResult.url == mangaObj.url && source.id == mangaObj.source)
|
||||||
|
) {
|
||||||
val localManga = networkToLocalManga.await(searchResult)
|
val localManga = networkToLocalManga.await(searchResult)
|
||||||
|
|
||||||
val chapters = if (source is EHentai) {
|
val chapters = if (source is EHentai) {
|
||||||
|
|
@ -239,7 +241,8 @@ class MigrationListScreenModel(
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return@async2 null
|
return@async2 null
|
||||||
}
|
}
|
||||||
manga.progress.value = validSources.size to processedSources.incrementAndGet()
|
manga.progress.value =
|
||||||
|
validSources.size to processedSources.incrementAndGet()
|
||||||
localManga to chapters.size
|
localManga to chapters.size
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|
@ -319,7 +322,8 @@ class MigrationListScreenModel(
|
||||||
if (result == null && hideNotFound) {
|
if (result == null && hideNotFound) {
|
||||||
removeManga(manga)
|
removeManga(manga)
|
||||||
}
|
}
|
||||||
if (result != null && showOnlyUpdates &&
|
if (result != null &&
|
||||||
|
showOnlyUpdates &&
|
||||||
(getChapterInfo(result.id).latestChapter ?: 0.0) <= (manga.chapterInfo.latestChapter ?: 0.0)
|
(getChapterInfo(result.id).latestChapter ?: 0.0) <= (manga.chapterInfo.latestChapter ?: 0.0)
|
||||||
) {
|
) {
|
||||||
removeManga(manga)
|
removeManga(manga)
|
||||||
|
|
@ -368,7 +372,10 @@ class MigrationListScreenModel(
|
||||||
|
|
||||||
dbChapters.forEach { chapter ->
|
dbChapters.forEach { chapter ->
|
||||||
if (chapter.isRecognizedNumber) {
|
if (chapter.isRecognizedNumber) {
|
||||||
val prevChapter = prevMangaChapters.find { it.isRecognizedNumber && it.chapterNumber == chapter.chapterNumber }
|
val prevChapter = prevMangaChapters.find {
|
||||||
|
it.isRecognizedNumber &&
|
||||||
|
it.chapterNumber == chapter.chapterNumber
|
||||||
|
}
|
||||||
if (prevChapter != null) {
|
if (prevChapter != null) {
|
||||||
chapterUpdates += ChapterUpdate(
|
chapterUpdates += ChapterUpdate(
|
||||||
id = chapter.id,
|
id = chapter.id,
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ data class SourceSearchScreen(
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
actions = persistentListOf(
|
actions = persistentListOf(
|
||||||
bulkSelectionButton(bulkFavoriteScreenModel::toggleSelectionMode),
|
bulkSelectionButton(bulkFavoriteScreenModel::toggleSelectionMode),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class SourcesScreenModel(
|
||||||
// KMK <--
|
// KMK <--
|
||||||
categories: List<String>,
|
categories: List<String>,
|
||||||
showLatest: Boolean,
|
showLatest: Boolean,
|
||||||
showPin: Boolean
|
showPin: Boolean,
|
||||||
) {
|
) {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
val searchQuery = filters.first
|
val searchQuery = filters.first
|
||||||
|
|
@ -156,7 +156,10 @@ class SourcesScreenModel(
|
||||||
items = byLang
|
items = byLang
|
||||||
.flatMap {
|
.flatMap {
|
||||||
listOf(
|
listOf(
|
||||||
SourceUiModel.Header(it.key.removePrefix(CATEGORY_KEY_PREFIX), it.value.firstOrNull()?.category != null),
|
SourceUiModel.Header(
|
||||||
|
it.key.removePrefix(CATEGORY_KEY_PREFIX),
|
||||||
|
it.value.firstOrNull()?.category != null,
|
||||||
|
),
|
||||||
*it.value.map { source ->
|
*it.value.map { source ->
|
||||||
SourceUiModel.Item(source)
|
SourceUiModel.Item(source)
|
||||||
}.toTypedArray(),
|
}.toTypedArray(),
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ data class BrowseSourceScreen(
|
||||||
val duplicateManga = screenModel.getDuplicateLibraryManga(manga)
|
val duplicateManga = screenModel.getDuplicateLibraryManga(manga)
|
||||||
when {
|
when {
|
||||||
manga.favorite -> screenModel.setDialog(
|
manga.favorite -> screenModel.setDialog(
|
||||||
BrowseSourceScreenModel.Dialog.RemoveManga(manga)
|
BrowseSourceScreenModel.Dialog.RemoveManga(manga),
|
||||||
)
|
)
|
||||||
duplicateManga != null -> screenModel.setDialog(
|
duplicateManga != null -> screenModel.setDialog(
|
||||||
BrowseSourceScreenModel.Dialog.AddDuplicateManga(
|
BrowseSourceScreenModel.Dialog.AddDuplicateManga(
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,7 @@ open class BrowseSourceScreenModel(
|
||||||
val filterable: Boolean = true,
|
val filterable: Boolean = true,
|
||||||
// SY <--
|
// SY <--
|
||||||
// KMK -->
|
// KMK -->
|
||||||
val mangaDisplayingList: MutableSet<Manga> = mutableSetOf()
|
val mangaDisplayingList: MutableSet<Manga> = mutableSetOf(),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
val isUserQuery get() = listing is Listing.Search && !listing.query.isNullOrEmpty()
|
val isUserQuery get() = listing is Listing.Search && !listing.query.isNullOrEmpty()
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,15 @@ class BiometricTimesScreen : Screen() {
|
||||||
fun showTimePicker(startTime: Duration? = null) {
|
fun showTimePicker(startTime: Duration? = null) {
|
||||||
val activity = context as? MainActivity ?: return
|
val activity = context as? MainActivity ?: return
|
||||||
val picker = MaterialTimePicker.Builder()
|
val picker = MaterialTimePicker.Builder()
|
||||||
.setTitleText(if (startTime == null) SYMR.strings.biometric_lock_start_time.getString(context) else SYMR.strings.biometric_lock_end_time.getString(context))
|
.setTitleText(
|
||||||
|
if (startTime ==
|
||||||
|
null
|
||||||
|
) {
|
||||||
|
SYMR.strings.biometric_lock_start_time.getString(context)
|
||||||
|
} else {
|
||||||
|
SYMR.strings.biometric_lock_end_time.getString(context)
|
||||||
|
},
|
||||||
|
)
|
||||||
.setInputMode(MaterialTimePicker.INPUT_MODE_CLOCK)
|
.setInputMode(MaterialTimePicker.INPUT_MODE_CLOCK)
|
||||||
.build()
|
.build()
|
||||||
picker.addOnPositiveButtonClickListener {
|
picker.addOnPositiveButtonClickListener {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ object DownloadQueueScreen : Screen() {
|
||||||
val screenModel = rememberScreenModel {
|
val screenModel = rememberScreenModel {
|
||||||
DownloadQueueScreenModel(
|
DownloadQueueScreenModel(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
navigator = navigator
|
navigator = navigator,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ object HomeScreen : Screen() {
|
||||||
materialFadeThroughOut(durationMillis = TAB_FADE_DURATION)
|
materialFadeThroughOut(durationMillis = TAB_FADE_DURATION)
|
||||||
},
|
},
|
||||||
label = "tabContent",
|
label = "tabContent",
|
||||||
contentKey = { it.key }
|
contentKey = { it.key },
|
||||||
) {
|
) {
|
||||||
tabNavigator.saveableState(key = "currentTab", it) {
|
tabNavigator.saveableState(key = "currentTab", it) {
|
||||||
it.Content()
|
it.Content()
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,8 @@ class LibraryScreenModel(
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
val list = it.split("|")
|
val list = it.split("|")
|
||||||
(list.getOrNull(0)?.toIntOrNull() ?: return@mapNotNull null) to (list.getOrNull(1) ?: return@mapNotNull null)
|
(list.getOrNull(0)?.toIntOrNull() ?: return@mapNotNull null) to
|
||||||
|
(list.getOrNull(1) ?: return@mapNotNull null)
|
||||||
}
|
}
|
||||||
.sortedBy { it.first }
|
.sortedBy { it.first }
|
||||||
.map { it.second }
|
.map { it.second }
|
||||||
|
|
@ -460,8 +461,12 @@ class LibraryScreenModel(
|
||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
LibrarySort.Type.TagList -> {
|
LibrarySort.Type.TagList -> {
|
||||||
val manga1IndexOfTag = listOfTags.indexOfFirst { i1.libraryManga.manga.genre?.contains(it) ?: false }
|
val manga1IndexOfTag = listOfTags.indexOfFirst {
|
||||||
val manga2IndexOfTag = listOfTags.indexOfFirst { i2.libraryManga.manga.genre?.contains(it) ?: false }
|
i1.libraryManga.manga.genre?.contains(it) ?: false
|
||||||
|
}
|
||||||
|
val manga2IndexOfTag = listOfTags.indexOfFirst {
|
||||||
|
i2.libraryManga.manga.genre?.contains(it) ?: false
|
||||||
|
}
|
||||||
manga1IndexOfTag.compareTo(manga2IndexOfTag)
|
manga1IndexOfTag.compareTo(manga2IndexOfTag)
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
@ -572,7 +577,7 @@ class LibraryScreenModel(
|
||||||
source.lang,
|
source.lang,
|
||||||
source.name,
|
source.name,
|
||||||
supportsLatest = false,
|
supportsLatest = false,
|
||||||
isStub = source is StubSource
|
isStub = source is StubSource,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|
@ -854,9 +859,12 @@ class LibraryScreenModel(
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
if (source is MergedSource) {
|
if (source is MergedSource) {
|
||||||
val mergedMangas = getMergedMangaById.await(manga.id)
|
val mergedMangas = getMergedMangaById.await(manga.id)
|
||||||
val sources = mergedMangas.distinctBy { it.source }.map { sourceManager.getOrStub(it.source) }
|
val sources = mergedMangas.distinctBy {
|
||||||
|
it.source
|
||||||
|
}.map { sourceManager.getOrStub(it.source) }
|
||||||
mergedMangas.forEach merge@{ mergedManga ->
|
mergedMangas.forEach merge@{ mergedManga ->
|
||||||
val mergedSource = sources.firstOrNull { mergedManga.source == it.id } as? HttpSource ?: return@merge
|
val mergedSource =
|
||||||
|
sources.firstOrNull { mergedManga.source == it.id } as? HttpSource ?: return@merge
|
||||||
downloadManager.deleteManga(mergedManga, mergedSource)
|
downloadManager.deleteManga(mergedManga, mergedSource)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -934,10 +942,11 @@ class LibraryScreenModel(
|
||||||
} else {
|
} else {
|
||||||
categoryName
|
categoryName
|
||||||
}
|
}
|
||||||
LibraryGroup.BY_TRACK_STATUS -> TrackStatus.entries
|
LibraryGroup.BY_TRACK_STATUS ->
|
||||||
.find { it.int.toLong() == category?.id }
|
TrackStatus.entries
|
||||||
.let { it ?: TrackStatus.OTHER }
|
.find { it.int.toLong() == category?.id }
|
||||||
.let { context.stringResource(it.res) }
|
.let { it ?: TrackStatus.OTHER }
|
||||||
|
.let { context.stringResource(it.res) }
|
||||||
LibraryGroup.UNGROUPED -> context.stringResource(SYMR.strings.ungrouped)
|
LibraryGroup.UNGROUPED -> context.stringResource(SYMR.strings.ungrouped)
|
||||||
else -> categoryName
|
else -> categoryName
|
||||||
}
|
}
|
||||||
|
|
@ -1024,49 +1033,66 @@ class LibraryScreenModel(
|
||||||
(manga.description?.contains(query, true) == true) ||
|
(manga.description?.contains(query, true) == true) ||
|
||||||
(source?.name?.contains(query, true) == true) ||
|
(source?.name?.contains(query, true) == true) ||
|
||||||
(sourceIdString != null && sourceIdString == query) ||
|
(sourceIdString != null && sourceIdString == query) ||
|
||||||
(loggedInTrackServices.isNotEmpty() && tracks != null && filterTracks(query, tracks, context)) ||
|
(
|
||||||
|
loggedInTrackServices.isNotEmpty() &&
|
||||||
|
tracks != null &&
|
||||||
|
filterTracks(query, tracks, context)
|
||||||
|
) ||
|
||||||
(genre.fastAny { it.contains(query, true) }) ||
|
(genre.fastAny { it.contains(query, true) }) ||
|
||||||
(searchTags?.fastAny { it.name.contains(query, true) } == true) ||
|
(searchTags?.fastAny { it.name.contains(query, true) } == true) ||
|
||||||
(searchTitles?.fastAny { it.title.contains(query, true) } == true)
|
(searchTitles?.fastAny { it.title.contains(query, true) } == true)
|
||||||
}
|
}
|
||||||
is Namespace -> {
|
is Namespace -> {
|
||||||
searchTags != null && searchTags.fastAny {
|
searchTags != null &&
|
||||||
val tag = queryComponent.tag
|
searchTags.fastAny {
|
||||||
(it.namespace.equals(queryComponent.namespace, true) && tag?.run { it.name.contains(tag.asQuery(), true) } == true) ||
|
val tag = queryComponent.tag
|
||||||
(tag == null && it.namespace.equals(queryComponent.namespace, true))
|
(
|
||||||
}
|
it.namespace.equals(queryComponent.namespace, true) &&
|
||||||
|
tag?.run { it.name.contains(tag.asQuery(), true) } == true
|
||||||
|
) ||
|
||||||
|
(tag == null && it.namespace.equals(queryComponent.namespace, true))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
true -> when (queryComponent) {
|
true -> when (queryComponent) {
|
||||||
is Text -> {
|
is Text -> {
|
||||||
val query = queryComponent.asQuery()
|
val query = queryComponent.asQuery()
|
||||||
query.isBlank() || (
|
query.isBlank() ||
|
||||||
(!manga.title.contains(query, true)) &&
|
(
|
||||||
(manga.author?.contains(query, true) != true) &&
|
(!manga.title.contains(query, true)) &&
|
||||||
(manga.artist?.contains(query, true) != true) &&
|
(manga.author?.contains(query, true) != true) &&
|
||||||
(manga.description?.contains(query, true) != true) &&
|
(manga.artist?.contains(query, true) != true) &&
|
||||||
(source?.name?.contains(query, true) != true) &&
|
(manga.description?.contains(query, true) != true) &&
|
||||||
(sourceIdString != null && sourceIdString != query) &&
|
(source?.name?.contains(query, true) != true) &&
|
||||||
(loggedInTrackServices.isEmpty() || tracks == null || !filterTracks(query, tracks, context)) &&
|
(sourceIdString != null && sourceIdString != query) &&
|
||||||
(!genre.fastAny { it.contains(query, true) }) &&
|
(
|
||||||
(searchTags?.fastAny { it.name.contains(query, true) } != true) &&
|
loggedInTrackServices.isEmpty() ||
|
||||||
(searchTitles?.fastAny { it.title.contains(query, true) } != true)
|
tracks == null ||
|
||||||
)
|
!filterTracks(query, tracks, context)
|
||||||
|
) &&
|
||||||
|
(!genre.fastAny { it.contains(query, true) }) &&
|
||||||
|
(searchTags?.fastAny { it.name.contains(query, true) } != true) &&
|
||||||
|
(searchTitles?.fastAny { it.title.contains(query, true) } != true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is Namespace -> {
|
is Namespace -> {
|
||||||
val searchedTag = queryComponent.tag?.asQuery()
|
val searchedTag = queryComponent.tag?.asQuery()
|
||||||
searchTags == null || (queryComponent.namespace.isBlank() && searchedTag.isNullOrBlank()) || searchTags.fastAll { mangaTag ->
|
searchTags == null ||
|
||||||
if (queryComponent.namespace.isBlank() && !searchedTag.isNullOrBlank()) {
|
(queryComponent.namespace.isBlank() && searchedTag.isNullOrBlank()) ||
|
||||||
!mangaTag.name.contains(searchedTag, true)
|
searchTags.fastAll { mangaTag ->
|
||||||
} else if (searchedTag.isNullOrBlank()) {
|
if (queryComponent.namespace.isBlank() && !searchedTag.isNullOrBlank()) {
|
||||||
mangaTag.namespace == null || !mangaTag.namespace.equals(queryComponent.namespace, true)
|
!mangaTag.name.contains(searchedTag, true)
|
||||||
} else if (mangaTag.namespace.isNullOrBlank()) {
|
} else if (searchedTag.isNullOrBlank()) {
|
||||||
true
|
mangaTag.namespace == null ||
|
||||||
} else {
|
!mangaTag.namespace.equals(queryComponent.namespace, true)
|
||||||
!mangaTag.name.contains(searchedTag, true) || !mangaTag.namespace.equals(queryComponent.namespace, true)
|
} else if (mangaTag.namespace.isNullOrBlank()) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
!mangaTag.name.contains(searchedTag, true) ||
|
||||||
|
!mangaTag.namespace.equals(queryComponent.namespace, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -364,8 +364,10 @@ class MainActivity : BaseActivity() {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
// BuildConfig.DEBUG ||
|
// BuildConfig.DEBUG ||
|
||||||
isReleaseBuildType && didMigration ||
|
isReleaseBuildType &&
|
||||||
isPreviewBuildType && previewCurrentVersion > previewLastVersion.get()
|
didMigration ||
|
||||||
|
isPreviewBuildType &&
|
||||||
|
previewCurrentVersion > previewLastVersion.get(),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ class MangaScreen(
|
||||||
|
|
||||||
val seedColor = successState.seedColor
|
val seedColor = successState.seedColor
|
||||||
TachiyomiTheme(
|
TachiyomiTheme(
|
||||||
seedColor = seedColor.takeIf { screenModel.themeCoverBased }
|
seedColor = seedColor.takeIf { screenModel.themeCoverBased },
|
||||||
) {
|
) {
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
|
|
@ -329,10 +329,14 @@ class MangaScreen(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onEditInfoClicked = screenModel::showEditMangaInfoDialog,
|
onEditInfoClicked = screenModel::showEditMangaInfoDialog,
|
||||||
onRecommendClicked = { openRecommends(context, navigator, screenModel.source?.getMainSource(), successState.manga) },
|
onRecommendClicked = {
|
||||||
|
openRecommends(context, navigator, screenModel.source?.getMainSource(), successState.manga)
|
||||||
|
},
|
||||||
onMergedSettingsClicked = screenModel::showEditMergedSettingsDialog,
|
onMergedSettingsClicked = screenModel::showEditMergedSettingsDialog,
|
||||||
onMergeClicked = { openSmartSearch(navigator, successState.manga) },
|
onMergeClicked = { openSmartSearch(navigator, successState.manga) },
|
||||||
onMergeWithAnotherClicked = { mergeWithAnother(navigator, context, successState.manga, screenModel::smartSearchMerge) },
|
onMergeWithAnotherClicked = {
|
||||||
|
mergeWithAnother(navigator, context, successState.manga, screenModel::smartSearchMerge)
|
||||||
|
},
|
||||||
onOpenPagePreview = { page ->
|
onOpenPagePreview = { page ->
|
||||||
openPagePreview(context, successState.chapters.minByOrNull { it.chapter.sourceOrder }?.chapter, page)
|
openPagePreview(context, successState.chapters.minByOrNull { it.chapter.sourceOrder }?.chapter, page)
|
||||||
},
|
},
|
||||||
|
|
@ -620,7 +624,8 @@ class MangaScreen(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
navigator.popUntil { screen ->
|
navigator.popUntil { screen ->
|
||||||
screen is HomeScreen ||
|
screen is HomeScreen ||
|
||||||
!library && (screen is BrowseSourceScreen || screen is SourceFeedScreen)
|
!library &&
|
||||||
|
(screen is BrowseSourceScreen || screen is SourceFeedScreen)
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,10 @@ class MangaScreenModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onEach { (manga, chapters) ->
|
.onEach { (manga, chapters) ->
|
||||||
if (chapters.isNotEmpty() && manga.isEhBasedManga() && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) {
|
if (chapters.isNotEmpty() &&
|
||||||
|
manga.isEhBasedManga() &&
|
||||||
|
DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled
|
||||||
|
) {
|
||||||
// Check for gallery in library and accept manga with lowest id
|
// Check for gallery in library and accept manga with lowest id
|
||||||
// Find chapters sharing same root
|
// Find chapters sharing same root
|
||||||
launchIO {
|
launchIO {
|
||||||
|
|
@ -388,7 +391,7 @@ class MangaScreenModel(
|
||||||
} else {
|
} else {
|
||||||
flowOf(emptySet())
|
flowOf(emptySet())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
) { mangaScanlators, mergeScanlators ->
|
) { mangaScanlators, mergeScanlators ->
|
||||||
mangaScanlators + mergeScanlators
|
mangaScanlators + mergeScanlators
|
||||||
} // SY <--
|
} // SY <--
|
||||||
|
|
@ -405,7 +408,15 @@ class MangaScreenModel(
|
||||||
val manga = getMangaAndChapters.awaitManga(mangaId)
|
val manga = getMangaAndChapters.awaitManga(mangaId)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val chapters = (if (manga.source == MERGED_SOURCE_ID) getMergedChaptersByMangaId.await(mangaId, applyScanlatorFilter = true) else getMangaAndChapters.awaitChapters(mangaId, applyScanlatorFilter = true))
|
val chapters = (
|
||||||
|
if (manga.source ==
|
||||||
|
MERGED_SOURCE_ID
|
||||||
|
) {
|
||||||
|
getMergedChaptersByMangaId.await(mangaId, applyScanlatorFilter = true)
|
||||||
|
} else {
|
||||||
|
getMangaAndChapters.awaitChapters(mangaId, applyScanlatorFilter = true)
|
||||||
|
}
|
||||||
|
)
|
||||||
.toChapterListItems(manga, null)
|
.toChapterListItems(manga, null)
|
||||||
val mergedData = getMergedReferencesById.await(mangaId).takeIf { it.isNotEmpty() }?.let { references ->
|
val mergedData = getMergedReferencesById.await(mangaId).takeIf { it.isNotEmpty() }?.let { references ->
|
||||||
MergedMangaData(
|
MergedMangaData(
|
||||||
|
|
@ -460,7 +471,8 @@ class MangaScreenModel(
|
||||||
} else {
|
} else {
|
||||||
PagePreviewState.Unused
|
PagePreviewState.Unused
|
||||||
},
|
},
|
||||||
alwaysShowReadingProgress = readerPreferences.preserveReadingPosition().get() && manga.isEhBasedManga(),
|
alwaysShowReadingProgress =
|
||||||
|
readerPreferences.preserveReadingPosition().get() && manga.isEhBasedManga(),
|
||||||
previewsRowCount = uiPreferences.previewsRowCount().get(),
|
previewsRowCount = uiPreferences.previewsRowCount().get(),
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
@ -542,7 +554,7 @@ class MangaScreenModel(
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.build()
|
.build(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1066,7 +1078,12 @@ class MangaScreenModel(
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
downloadManager.statusFlow()
|
downloadManager.statusFlow()
|
||||||
.filter {
|
.filter {
|
||||||
/* SY --> */ if (isMergedSource) it.manga.id in mergedIds else /* SY <-- */ it.manga.id == successState?.manga?.id
|
/* SY --> */ if (isMergedSource) {
|
||||||
|
it.manga.id in mergedIds
|
||||||
|
} else {
|
||||||
|
/* SY <-- */ it.manga.id ==
|
||||||
|
successState?.manga?.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.catch { error -> logcat(LogPriority.ERROR, error) }
|
.catch { error -> logcat(LogPriority.ERROR, error) }
|
||||||
.collect {
|
.collect {
|
||||||
|
|
@ -1079,7 +1096,12 @@ class MangaScreenModel(
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
downloadManager.progressFlow()
|
downloadManager.progressFlow()
|
||||||
.filter {
|
.filter {
|
||||||
/* SY --> */ if (isMergedSource) it.manga.id in mergedIds else /* SY <-- */ it.manga.id == successState?.manga?.id
|
/* SY --> */ if (isMergedSource) {
|
||||||
|
it.manga.id in mergedIds
|
||||||
|
} else {
|
||||||
|
/* SY <-- */ it.manga.id ==
|
||||||
|
successState?.manga?.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.catch { error -> logcat(LogPriority.ERROR, error) }
|
.catch { error -> logcat(LogPriority.ERROR, error) }
|
||||||
.collect {
|
.collect {
|
||||||
|
|
@ -1755,7 +1777,8 @@ class MangaScreenModel(
|
||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
.map { (tracks, supportedTrackers) ->
|
.map { (tracks, supportedTrackers) ->
|
||||||
val supportedTrackerTracks = if (manga.source in mangaDexSourceIds || state.mergedData?.manga?.values.orEmpty().any {
|
val supportedTrackerTracks = if (manga.source in mangaDexSourceIds ||
|
||||||
|
state.mergedData?.manga?.values.orEmpty().any {
|
||||||
it.source in mangaDexSourceIds
|
it.source in mangaDexSourceIds
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
@ -1937,7 +1960,7 @@ class MangaScreenModel(
|
||||||
* a list of <keyword, related mangas>
|
* a list of <keyword, related mangas>
|
||||||
*/
|
*/
|
||||||
val relatedMangaCollection: List<RelatedManga>? = null,
|
val relatedMangaCollection: List<RelatedManga>? = null,
|
||||||
val seedColor: Color? = manga.asMangaCover().vibrantCoverColor?.let { Color(it) }
|
val seedColor: Color? = manga.asMangaCover().vibrantCoverColor?.let { Color(it) },
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) : State {
|
) : State {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ class PaletteScreen(
|
||||||
val seedColor = seedColor?.let { Color(it) } ?: MaterialTheme.colorScheme.primary
|
val seedColor = seedColor?.let { Color(it) } ?: MaterialTheme.colorScheme.primary
|
||||||
|
|
||||||
TachiyomiTheme(
|
TachiyomiTheme(
|
||||||
seedColor = seedColor.takeIf { themeCoverBased }
|
seedColor = seedColor.takeIf { themeCoverBased },
|
||||||
) {
|
) {
|
||||||
MaterialThemeContent(seedColor)
|
MaterialThemeContent(seedColor)
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ class PaletteScreen(
|
||||||
"primary",
|
"primary",
|
||||||
MaterialTheme.colorScheme.primary,
|
MaterialTheme.colorScheme.primary,
|
||||||
"primaryContainer",
|
"primaryContainer",
|
||||||
MaterialTheme.colorScheme.primaryContainer
|
MaterialTheme.colorScheme.primaryContainer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -84,7 +84,7 @@ class PaletteScreen(
|
||||||
"secondary",
|
"secondary",
|
||||||
MaterialTheme.colorScheme.secondary,
|
MaterialTheme.colorScheme.secondary,
|
||||||
"secondaryContainer",
|
"secondaryContainer",
|
||||||
MaterialTheme.colorScheme.secondaryContainer
|
MaterialTheme.colorScheme.secondaryContainer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -92,7 +92,7 @@ class PaletteScreen(
|
||||||
"tertiary",
|
"tertiary",
|
||||||
MaterialTheme.colorScheme.tertiary,
|
MaterialTheme.colorScheme.tertiary,
|
||||||
"tertiaryContainer",
|
"tertiaryContainer",
|
||||||
MaterialTheme.colorScheme.tertiaryContainer
|
MaterialTheme.colorScheme.tertiaryContainer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -100,7 +100,7 @@ class PaletteScreen(
|
||||||
"surface",
|
"surface",
|
||||||
MaterialTheme.colorScheme.surface,
|
MaterialTheme.colorScheme.surface,
|
||||||
"surfaceVariant",
|
"surfaceVariant",
|
||||||
MaterialTheme.colorScheme.surfaceVariant
|
MaterialTheme.colorScheme.surfaceVariant,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -108,7 +108,7 @@ class PaletteScreen(
|
||||||
"inverseSurface",
|
"inverseSurface",
|
||||||
MaterialTheme.colorScheme.inverseSurface,
|
MaterialTheme.colorScheme.inverseSurface,
|
||||||
"surfaceTint",
|
"surfaceTint",
|
||||||
MaterialTheme.colorScheme.surfaceTint
|
MaterialTheme.colorScheme.surfaceTint,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -116,7 +116,7 @@ class PaletteScreen(
|
||||||
"inversePrimary",
|
"inversePrimary",
|
||||||
MaterialTheme.colorScheme.inversePrimary,
|
MaterialTheme.colorScheme.inversePrimary,
|
||||||
"background",
|
"background",
|
||||||
MaterialTheme.colorScheme.background
|
MaterialTheme.colorScheme.background,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -124,7 +124,7 @@ class PaletteScreen(
|
||||||
"error",
|
"error",
|
||||||
MaterialTheme.colorScheme.error,
|
MaterialTheme.colorScheme.error,
|
||||||
"errorContainer",
|
"errorContainer",
|
||||||
MaterialTheme.colorScheme.errorContainer
|
MaterialTheme.colorScheme.errorContainer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -132,7 +132,7 @@ class PaletteScreen(
|
||||||
"outline",
|
"outline",
|
||||||
MaterialTheme.colorScheme.outline,
|
MaterialTheme.colorScheme.outline,
|
||||||
"outlineVariant",
|
"outlineVariant",
|
||||||
MaterialTheme.colorScheme.outlineVariant
|
MaterialTheme.colorScheme.outlineVariant,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -140,7 +140,7 @@ class PaletteScreen(
|
||||||
"scrim",
|
"scrim",
|
||||||
MaterialTheme.colorScheme.scrim,
|
MaterialTheme.colorScheme.scrim,
|
||||||
"surfaceBright",
|
"surfaceBright",
|
||||||
MaterialTheme.colorScheme.surfaceBright
|
MaterialTheme.colorScheme.surfaceBright,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -148,7 +148,7 @@ class PaletteScreen(
|
||||||
"surfaceDim",
|
"surfaceDim",
|
||||||
MaterialTheme.colorScheme.surfaceDim,
|
MaterialTheme.colorScheme.surfaceDim,
|
||||||
"surfaceContainer",
|
"surfaceContainer",
|
||||||
MaterialTheme.colorScheme.surfaceContainer
|
MaterialTheme.colorScheme.surfaceContainer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -156,7 +156,7 @@ class PaletteScreen(
|
||||||
"surfaceContainerHigh",
|
"surfaceContainerHigh",
|
||||||
MaterialTheme.colorScheme.surfaceContainerHigh,
|
MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
"surfaceContainerHighest",
|
"surfaceContainerHighest",
|
||||||
MaterialTheme.colorScheme.surfaceContainerHighest
|
MaterialTheme.colorScheme.surfaceContainerHighest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
|
@ -164,7 +164,7 @@ class PaletteScreen(
|
||||||
"surfaceContainerLow",
|
"surfaceContainerLow",
|
||||||
MaterialTheme.colorScheme.surfaceContainerLow,
|
MaterialTheme.colorScheme.surfaceContainerLow,
|
||||||
"surfaceContainerLowest",
|
"surfaceContainerLowest",
|
||||||
MaterialTheme.colorScheme.surfaceContainerLowest
|
MaterialTheme.colorScheme.surfaceContainerLowest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +184,7 @@ fun ButtonsColor(
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
onClick = { },
|
onClick = { },
|
||||||
|
|
@ -194,7 +194,7 @@ fun ButtonsColor(
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = color1,
|
containerColor = color1,
|
||||||
contentColor = contentColor1,
|
contentColor = contentColor1,
|
||||||
)
|
),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = name1,
|
text = name1,
|
||||||
|
|
@ -211,7 +211,7 @@ fun ButtonsColor(
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = name2
|
text = name2,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ class EditMergedSettingsState(
|
||||||
}.map { reference -> mergedManga.firstOrNull { it.id == reference.mangaId } to reference }
|
}.map { reference -> mergedManga.firstOrNull { it.id == reference.mangaId } to reference }
|
||||||
mergeReference = mergedReferences.firstOrNull { it.mangaSourceId == MERGED_SOURCE_ID }
|
mergeReference = mergedReferences.firstOrNull { it.mangaSourceId == MERGED_SOURCE_ID }
|
||||||
|
|
||||||
val isPriorityOrder = mergeReference?.let { it.chapterSortMode == MergedMangaReference.CHAPTER_SORT_PRIORITY } ?: false
|
val isPriorityOrder =
|
||||||
|
mergeReference?.let { it.chapterSortMode == MergedMangaReference.CHAPTER_SORT_PRIORITY } ?: false
|
||||||
|
|
||||||
mergedMangaAdapter = EditMergedMangaAdapter(this, isPriorityOrder)
|
mergedMangaAdapter = EditMergedMangaAdapter(this, isPriorityOrder)
|
||||||
mergedMangaHeaderAdapter = EditMergedSettingsHeaderAdapter(this, mergedMangaAdapter!!)
|
mergedMangaHeaderAdapter = EditMergedSettingsHeaderAdapter(this, mergedMangaAdapter!!)
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,8 @@ class EditMergedSettingsHeaderAdapter(private val state: EditMergedSettingsState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun canMove() = state.mergeReference?.let { it.chapterSortMode == MergedMangaReference.CHAPTER_SORT_PRIORITY } ?: false
|
fun canMove() =
|
||||||
|
state.mergeReference?.let { it.chapterSortMode == MergedMangaReference.CHAPTER_SORT_PRIORITY } ?: false
|
||||||
|
|
||||||
interface SortingListener {
|
interface SortingListener {
|
||||||
fun onSetPrioritySort(isPriorityOrder: Boolean)
|
fun onSetPrioritySort(isPriorityOrder: Boolean)
|
||||||
|
|
|
||||||
|
|
@ -476,10 +476,12 @@ class ReaderActivity : BaseActivity() {
|
||||||
val landscapeVerticalSeekbar by readerPreferences.landscapeVerticalSeekbar().collectAsState()
|
val landscapeVerticalSeekbar by readerPreferences.landscapeVerticalSeekbar().collectAsState()
|
||||||
val leftHandedVerticalSeekbar by readerPreferences.leftVerticalSeekbar().collectAsState()
|
val leftHandedVerticalSeekbar by readerPreferences.leftVerticalSeekbar().collectAsState()
|
||||||
val configuration = LocalConfiguration.current
|
val configuration = LocalConfiguration.current
|
||||||
val verticalSeekbarLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && landscapeVerticalSeekbar
|
val verticalSeekbarLandscape =
|
||||||
|
configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && landscapeVerticalSeekbar
|
||||||
val verticalSeekbarHorizontal = configuration.orientation == Configuration.ORIENTATION_PORTRAIT
|
val verticalSeekbarHorizontal = configuration.orientation == Configuration.ORIENTATION_PORTRAIT
|
||||||
val viewerIsVertical = (state.viewer is WebtoonViewer || state.viewer is VerticalPagerViewer)
|
val viewerIsVertical = (state.viewer is WebtoonViewer || state.viewer is VerticalPagerViewer)
|
||||||
val showVerticalSeekbar = !forceHorizontalSeekbar && (verticalSeekbarLandscape || verticalSeekbarHorizontal) && viewerIsVertical
|
val showVerticalSeekbar =
|
||||||
|
!forceHorizontalSeekbar && (verticalSeekbarLandscape || verticalSeekbarHorizontal) && viewerIsVertical
|
||||||
val navBarType = when {
|
val navBarType = when {
|
||||||
!showVerticalSeekbar -> NavBarType.Bottom
|
!showVerticalSeekbar -> NavBarType.Bottom
|
||||||
leftHandedVerticalSeekbar -> NavBarType.VerticalLeft
|
leftHandedVerticalSeekbar -> NavBarType.VerticalLeft
|
||||||
|
|
@ -940,7 +942,8 @@ class ReaderActivity : BaseActivity() {
|
||||||
} else {
|
} else {
|
||||||
if (readerPreferences.fullscreen().get()) {
|
if (readerPreferences.fullscreen().get()) {
|
||||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
windowInsetsController.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1160,7 +1163,13 @@ class ReaderActivity : BaseActivity() {
|
||||||
// SY -->
|
// SY -->
|
||||||
val currentPageText = if (hasExtraPage) {
|
val currentPageText = if (hasExtraPage) {
|
||||||
val invertDoublePage = (viewModel.state.value.viewer as? PagerViewer)?.config?.invertDoublePages ?: false
|
val invertDoublePage = (viewModel.state.value.viewer as? PagerViewer)?.config?.invertDoublePages ?: false
|
||||||
if ((resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR) xor invertDoublePage) "${page.number}-${page.number + 1}" else "${page.number + 1}-${page.number}"
|
if ((resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR) xor
|
||||||
|
invertDoublePage
|
||||||
|
) {
|
||||||
|
"${page.number}-${page.number + 1}"
|
||||||
|
} else {
|
||||||
|
"${page.number + 1}-${page.number}"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
"${page.number}"
|
"${page.number}"
|
||||||
}
|
}
|
||||||
|
|
@ -1222,7 +1231,16 @@ class ReaderActivity : BaseActivity() {
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val text = if (secondPage != null) {
|
val text = if (secondPage != null) {
|
||||||
stringResource(SYMR.strings.share_pages_info, manga.title, chapter.name, if (resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR) "${page.number}-${page.number + 1}" else "${page.number + 1}-${page.number}")
|
stringResource(
|
||||||
|
SYMR.strings.share_pages_info, manga.title, chapter.name,
|
||||||
|
if (resources.configuration.layoutDirection ==
|
||||||
|
View.LAYOUT_DIRECTION_LTR
|
||||||
|
) {
|
||||||
|
"${page.number}-${page.number + 1}"
|
||||||
|
} else {
|
||||||
|
"${page.number + 1}-${page.number}"
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
stringResource(MR.strings.share_page_info, manga.title, chapter.name, page.number)
|
stringResource(MR.strings.share_page_info, manga.title, chapter.name, page.number)
|
||||||
}
|
}
|
||||||
|
|
@ -1386,11 +1404,14 @@ class ReaderActivity : BaseActivity() {
|
||||||
.onEach {
|
.onEach {
|
||||||
if (viewModel.state.value.viewer !is PagerViewer) return@onEach
|
if (viewModel.state.value.viewer !is PagerViewer) return@onEach
|
||||||
reloadChapters(
|
reloadChapters(
|
||||||
!it && when (readerPreferences.pageLayout().get()) {
|
!it &&
|
||||||
PagerConfig.PageLayout.DOUBLE_PAGES -> true
|
when (readerPreferences.pageLayout().get()) {
|
||||||
PagerConfig.PageLayout.AUTOMATIC -> resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
PagerConfig.PageLayout.DOUBLE_PAGES -> true
|
||||||
else -> false
|
PagerConfig.PageLayout.AUTOMATIC ->
|
||||||
},
|
resources.configuration.orientation ==
|
||||||
|
Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
else -> false
|
||||||
|
},
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||||
private val getMergedMangaById: GetMergedMangaById = Injekt.get(),
|
private val getMergedMangaById: GetMergedMangaById = Injekt.get(),
|
||||||
private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(),
|
private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(),
|
||||||
private val getMergedChaptersByMangaId: GetMergedChaptersByMangaId = Injekt.get(),
|
private val getMergedChaptersByMangaId: GetMergedChaptersByMangaId = Injekt.get(),
|
||||||
private val setReadStatus: SetReadStatus = Injekt.get()
|
private val setReadStatus: SetReadStatus = Injekt.get(),
|
||||||
// SY <--
|
// SY <--
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
|
|
@ -189,8 +189,9 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||||
// SY -->
|
// SY -->
|
||||||
val (chapters, mangaMap) = runBlocking {
|
val (chapters, mangaMap) = runBlocking {
|
||||||
if (manga.source == MERGED_SOURCE_ID) {
|
if (manga.source == MERGED_SOURCE_ID) {
|
||||||
getMergedChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) to getMergedMangaById.await(manga.id)
|
getMergedChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) to
|
||||||
.associateBy { it.id }
|
getMergedMangaById.await(manga.id)
|
||||||
|
.associateBy { it.id }
|
||||||
} else {
|
} else {
|
||||||
getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) to null
|
getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) to null
|
||||||
}
|
}
|
||||||
|
|
@ -709,7 +710,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||||
.ifEmpty { null }
|
.ifEmpty { null }
|
||||||
?.also {
|
?.also {
|
||||||
setReadStatus.await(true, *it.toTypedArray())
|
setReadStatus.await(true, *it.toTypedArray())
|
||||||
it.forEach { chapter ->
|
it.forEach { chapter ->
|
||||||
deleteChapterIfNeeded(ReaderChapter(chapter))
|
deleteChapterIfNeeded(ReaderChapter(chapter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,11 @@ class ChapterLoader(
|
||||||
|
|
||||||
// If the chapter is partially read, set the starting page to the last the user read
|
// If the chapter is partially read, set the starting page to the last the user read
|
||||||
// otherwise use the requested page.
|
// otherwise use the requested page.
|
||||||
if (!chapter.chapter.read /* --> EH */ || readerPrefs
|
if (!chapter.chapter.read /* --> EH */ ||
|
||||||
|
readerPrefs
|
||||||
.preserveReadingPosition()
|
.preserveReadingPosition()
|
||||||
.get() || page != null // <-- EH
|
.get() ||
|
||||||
|
page != null // <-- EH
|
||||||
) {
|
) {
|
||||||
chapter.requestedPage = /* SY --> */ page ?: /* SY <-- */ chapter.chapter.last_page_read
|
chapter.requestedPage = /* SY --> */ page ?: /* SY <-- */ chapter.chapter.last_page_read
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ class ReaderPreferences(
|
||||||
val archiveModeTypes = listOf(
|
val archiveModeTypes = listOf(
|
||||||
SYMR.strings.archive_mode_load_from_file,
|
SYMR.strings.archive_mode_load_from_file,
|
||||||
SYMR.strings.archive_mode_load_into_memory,
|
SYMR.strings.archive_mode_load_into_memory,
|
||||||
SYMR.strings.archive_mode_cache_to_disk
|
SYMR.strings.archive_mode_cache_to_disk,
|
||||||
)
|
)
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ enum class ReadingMode(
|
||||||
preference: Int?,
|
preference: Int?,
|
||||||
activity: ReaderActivity,
|
activity: ReaderActivity,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
@ColorInt seedColor: Int?
|
@ColorInt seedColor: Int?,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
): Viewer {
|
): Viewer {
|
||||||
return when (fromPreference(preference)) {
|
return when (fromPreference(preference)) {
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,12 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SubsamplingScaleImageView.landscapeZoom(forward: Boolean) {
|
private fun SubsamplingScaleImageView.landscapeZoom(forward: Boolean) {
|
||||||
if (config != null && config!!.landscapeZoom && config!!.minimumScaleType == SCALE_TYPE_CENTER_INSIDE && sWidth > sHeight && scale == minScale) {
|
if (config != null &&
|
||||||
|
config!!.landscapeZoom &&
|
||||||
|
config!!.minimumScaleType == SCALE_TYPE_CENTER_INSIDE &&
|
||||||
|
sWidth > sHeight &&
|
||||||
|
scale == minScale
|
||||||
|
) {
|
||||||
handler?.postDelayed(500) {
|
handler?.postDelayed(500) {
|
||||||
val point = when (config!!.zoomStartPosition) {
|
val point = when (config!!.zoomStartPosition) {
|
||||||
ZoomStartPosition.LEFT -> if (forward) PointF(0F, 0F) else PointF(sWidth.toFloat(), 0F)
|
ZoomStartPosition.LEFT -> if (forward) PointF(0F, 0F) else PointF(sWidth.toFloat(), 0F)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class ReaderProgressIndicator @JvmOverloads constructor(
|
||||||
// KMK <--
|
// KMK <--
|
||||||
TachiyomiTheme(
|
TachiyomiTheme(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
seedColor = seedColor?.let { Color(seedColor) }.takeIf { themeCoverBased }
|
seedColor = seedColor?.let { Color(seedColor) }.takeIf { themeCoverBased },
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
CombinedCircularProgressIndicator(progress = { progress })
|
CombinedCircularProgressIndicator(progress = { progress })
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class ReaderTransitionView @JvmOverloads constructor(
|
||||||
// KMK <--
|
// KMK <--
|
||||||
TachiyomiTheme(
|
TachiyomiTheme(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
seedColor = seedColor?.let { Color(seedColor) }.takeIf { themeCoverBased }
|
seedColor = seedColor?.let { Color(seedColor) }.takeIf { themeCoverBased },
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@ class PagerConfig(
|
||||||
|
|
||||||
var shiftDoublePage = false
|
var shiftDoublePage = false
|
||||||
|
|
||||||
var doublePages = readerPreferences.pageLayout().get() == PageLayout.DOUBLE_PAGES && !readerPreferences.dualPageSplitPaged().get()
|
var doublePages =
|
||||||
|
readerPreferences.pageLayout().get() == PageLayout.DOUBLE_PAGES && !readerPreferences.dualPageSplitPaged().get()
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
|
|
||||||
|
|
@ -318,9 +318,9 @@ class PagerPageHolder(
|
||||||
private fun handleWideImage(imageSource: BufferedSource): BufferedSource {
|
private fun handleWideImage(imageSource: BufferedSource): BufferedSource {
|
||||||
return if (
|
return if (
|
||||||
!ImageUtil.isAnimatedAndSupported(imageSource) &&
|
!ImageUtil.isAnimatedAndSupported(imageSource) &&
|
||||||
ImageUtil.isWideImage(imageSource) &&
|
ImageUtil.isWideImage(imageSource) &&
|
||||||
viewer.config.centerMarginType and PagerConfig.CenterMarginType.WIDE_PAGE_CENTER_MARGIN > 0 &&
|
viewer.config.centerMarginType and PagerConfig.CenterMarginType.WIDE_PAGE_CENTER_MARGIN > 0 &&
|
||||||
!viewer.config.imageCropBorders
|
!viewer.config.imageCropBorders
|
||||||
) {
|
) {
|
||||||
ImageUtil.addHorizontalCenterMargin(imageSource, height, context)
|
ImageUtil.addHorizontalCenterMargin(imageSource, height, context)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -338,7 +338,9 @@ class PagerPageHolder(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateCenterMargin(height: Int, height2: Int): Int {
|
private fun calculateCenterMargin(height: Int, height2: Int): Int {
|
||||||
return if (viewer.config.centerMarginType and PagerConfig.CenterMarginType.DOUBLE_PAGE_CENTER_MARGIN > 0 && !viewer.config.imageCropBorders) {
|
return if (viewer.config.centerMarginType and PagerConfig.CenterMarginType.DOUBLE_PAGE_CENTER_MARGIN > 0 &&
|
||||||
|
!viewer.config.imageCropBorders
|
||||||
|
) {
|
||||||
96 / (this.height.coerceAtLeast(1) / max(height, height2).coerceAtLeast(1)).coerceAtLeast(1)
|
96 / (this.height.coerceAtLeast(1) / max(height, height2).coerceAtLeast(1)).coerceAtLeast(1)
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
|
@ -381,8 +383,10 @@ class PagerPageHolder(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val sideMargin = if ((viewer.config.centerMarginType and PagerConfig.CenterMarginType.DOUBLE_PAGE_CENTER_MARGIN) > 0 &&
|
val sideMargin = if ((viewer.config.centerMarginType and PagerConfig.CenterMarginType.DOUBLE_PAGE_CENTER_MARGIN) >
|
||||||
viewer.config.doublePages && !viewer.config.imageCropBorders
|
0 &&
|
||||||
|
viewer.config.doublePages &&
|
||||||
|
!viewer.config.imageCropBorders
|
||||||
) {
|
) {
|
||||||
48
|
48
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,9 @@ abstract class PagerViewer(
|
||||||
* Sets the active [chapters] on this pager.
|
* Sets the active [chapters] on this pager.
|
||||||
*/
|
*/
|
||||||
private fun setChaptersInternal(chapters: ViewerChapters) {
|
private fun setChaptersInternal(chapters: ViewerChapters) {
|
||||||
val forceTransition = config.alwaysShowChapterTransition || adapter.joinedItems.getOrNull(pager.currentItem)?.first is ChapterTransition
|
val forceTransition =
|
||||||
|
config.alwaysShowChapterTransition ||
|
||||||
|
adapter.joinedItems.getOrNull(pager.currentItem)?.first is ChapterTransition
|
||||||
adapter.setChapters(chapters, forceTransition)
|
adapter.setChapters(chapters, forceTransition)
|
||||||
|
|
||||||
// Layout the pager once a chapter is being set
|
// Layout the pager once a chapter is being set
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,9 @@ class PagerViewerAdapter(
|
||||||
subItems.forEach { readerItem ->
|
subItems.forEach { readerItem ->
|
||||||
when (readerItem) {
|
when (readerItem) {
|
||||||
is ReaderPage -> {
|
is ReaderPage -> {
|
||||||
if (pagedItems.last().isNotEmpty() && pagedItems.last().last()?.chapter?.chapter?.id != readerItem.chapter.chapter.id) {
|
if (pagedItems.last().isNotEmpty() &&
|
||||||
|
pagedItems.last().last()?.chapter?.chapter?.id != readerItem.chapter.chapter.id
|
||||||
|
) {
|
||||||
pagedItems.add(mutableListOf())
|
pagedItems.add(mutableListOf())
|
||||||
}
|
}
|
||||||
pagedItems.last().add(readerItem)
|
pagedItems.last().add(readerItem)
|
||||||
|
|
@ -321,9 +323,10 @@ class PagerViewerAdapter(
|
||||||
// Add a 'blank' page after each full page. It will be used when chunked to solo a page
|
// Add a 'blank' page after each full page. It will be used when chunked to solo a page
|
||||||
items.add(itemIndex + 1, null)
|
items.add(itemIndex + 1, null)
|
||||||
if (
|
if (
|
||||||
currentItem.fullPage && itemIndex > 0 &&
|
currentItem.fullPage &&
|
||||||
items[itemIndex - 1] != null &&
|
itemIndex > 0 &&
|
||||||
(itemIndex - 1) % 2 == 0
|
items[itemIndex - 1] != null &&
|
||||||
|
(itemIndex - 1) % 2 == 0
|
||||||
) {
|
) {
|
||||||
// If a page is a full page, check if the previous page needs to be isolated
|
// If a page is a full page, check if the previous page needs to be isolated
|
||||||
// we should check if it's an even or odd page, since even pages need shifting
|
// we should check if it's an even or odd page, since even pages need shifting
|
||||||
|
|
@ -363,7 +366,8 @@ class PagerViewerAdapter(
|
||||||
// We will however shift to the first page of the new chapter if the last page we were are
|
// We will however shift to the first page of the new chapter if the last page we were are
|
||||||
// on is not in the new chapter that has loaded
|
// on is not in the new chapter that has loaded
|
||||||
val newPage = when {
|
val newPage = when {
|
||||||
oldCurrent?.first is ReaderPage && (oldCurrent.first as ReaderPage).chapter != currentChapter &&
|
oldCurrent?.first is ReaderPage &&
|
||||||
|
(oldCurrent.first as ReaderPage).chapter != currentChapter &&
|
||||||
(oldCurrent.second as? ChapterTransition)?.from != currentChapter ->
|
(oldCurrent.second as? ChapterTransition)?.from != currentChapter ->
|
||||||
subItems.find { it is ReaderPage && it.chapter == currentChapter }
|
subItems.find { it is ReaderPage && it.chapter == currentChapter }
|
||||||
useSecondPage -> oldCurrent?.second ?: oldCurrent?.first
|
useSecondPage -> oldCurrent?.second ?: oldCurrent?.first
|
||||||
|
|
@ -372,7 +376,10 @@ class PagerViewerAdapter(
|
||||||
|
|
||||||
val index = when (newPage) {
|
val index = when (newPage) {
|
||||||
is ChapterTransition -> {
|
is ChapterTransition -> {
|
||||||
val filteredPages = joinedItems.filter { it.first is ReaderPage && (it.first as ReaderPage).chapter == newPage.to }
|
val filteredPages = joinedItems.filter {
|
||||||
|
it.first is ReaderPage &&
|
||||||
|
(it.first as ReaderPage).chapter == newPage.to
|
||||||
|
}
|
||||||
val page = if (newPage is ChapterTransition.Next) {
|
val page = if (newPage is ChapterTransition.Next) {
|
||||||
filteredPages.minByOrNull { (it.first as ReaderPage).index }?.first
|
filteredPages.minByOrNull { (it.first as ReaderPage).index }?.first
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,9 @@ class WebtoonPageHolder(
|
||||||
ReaderPageImageView.Config(
|
ReaderPageImageView.Config(
|
||||||
zoomDuration = viewer.config.doubleTapAnimDuration,
|
zoomDuration = viewer.config.doubleTapAnimDuration,
|
||||||
minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH,
|
minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH,
|
||||||
cropBorders = (viewer.config.imageCropBorders && viewer.isContinuous) || (viewer.config.continuousCropBorders && !viewer.isContinuous),
|
cropBorders =
|
||||||
|
(viewer.config.imageCropBorders && viewer.isContinuous) ||
|
||||||
|
(viewer.config.continuousCropBorders && !viewer.isContinuous),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
removeErrorLayout()
|
removeErrorLayout()
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,10 @@ fun Context.notify(id: Int, channelId: String, block: (NotificationCompat.Builde
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.notify(id: Int, notification: Notification) {
|
fun Context.notify(id: Int, notification: Notification) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && PermissionChecker.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PermissionChecker.PERMISSION_GRANTED) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
|
||||||
|
PermissionChecker.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) !=
|
||||||
|
PermissionChecker.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,7 +34,10 @@ fun Context.notify(id: Int, notification: Notification) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.notify(notificationWithIdAndTags: List<NotificationWithIdAndTag>) {
|
fun Context.notify(notificationWithIdAndTags: List<NotificationWithIdAndTag>) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && PermissionChecker.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PermissionChecker.PERMISSION_GRANTED) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
|
||||||
|
PermissionChecker.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) !=
|
||||||
|
PermissionChecker.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,13 @@ class GalleryAdder(
|
||||||
return sourceManager.getVisibleCatalogueSources()
|
return sourceManager.getVisibleCatalogueSources()
|
||||||
.mapNotNull { it.getMainSource<UrlImportableSource>() }
|
.mapNotNull { it.getMainSource<UrlImportableSource>() }
|
||||||
.filter {
|
.filter {
|
||||||
it.lang in filters.enabledLangs && it.id !in filters.disabledSources && try {
|
it.lang in filters.enabledLangs &&
|
||||||
it.matchesUri(uri)
|
it.id !in filters.disabledSources &&
|
||||||
} catch (e: Exception) {
|
try {
|
||||||
false
|
it.matchesUri(uri)
|
||||||
}
|
} catch (e: Exception) {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,11 +84,13 @@ class GalleryAdder(
|
||||||
sourceManager.getVisibleCatalogueSources()
|
sourceManager.getVisibleCatalogueSources()
|
||||||
.mapNotNull { it.getMainSource<UrlImportableSource>() }
|
.mapNotNull { it.getMainSource<UrlImportableSource>() }
|
||||||
.find {
|
.find {
|
||||||
it.lang in filters.enabledLangs && it.id !in filters.disabledSources && try {
|
it.lang in filters.enabledLangs &&
|
||||||
it.matchesUri(uri)
|
it.id !in filters.disabledSources &&
|
||||||
} catch (e: Exception) {
|
try {
|
||||||
false
|
it.matchesUri(uri)
|
||||||
}
|
} catch (e: Exception) {
|
||||||
|
false
|
||||||
|
}
|
||||||
} ?: return GalleryAddEvent.Fail.UnknownSource(url, context)
|
} ?: return GalleryAddEvent.Fail.UnknownSource(url, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import kotlin.collections.List as ____KtList
|
||||||
|
|
||||||
public object EhAssets
|
public object EhAssets
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName", "ktlint:standard:backing-property-naming")
|
||||||
private var __AllAssets: ____KtList<ImageVector>? = null
|
private var __AllAssets: ____KtList<ImageVector>? = null
|
||||||
|
|
||||||
public val EhAssets.AllAssets: ____KtList<ImageVector>
|
public val EhAssets.AllAssets: ____KtList<ImageVector>
|
||||||
|
|
|
||||||
|
|
@ -165,4 +165,5 @@ public val EhAssets.EhLogo: ImageVector
|
||||||
return _ehLogo!!
|
return _ehLogo!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName", "ktlint:standard:backing-property-naming")
|
||||||
private var _ehLogo: ImageVector? = null
|
private var _ehLogo: ImageVector? = null
|
||||||
|
|
|
||||||
|
|
@ -427,4 +427,5 @@ public val EhAssets.MangadexLogo: ImageVector
|
||||||
return _mangadexLogo!!
|
return _mangadexLogo!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName", "ktlint:standard:backing-property-naming")
|
||||||
private var _mangadexLogo: ImageVector? = null
|
private var _mangadexLogo: ImageVector? = null
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ public object ExhGroup
|
||||||
public val EhAssets.Exh: ExhGroup
|
public val EhAssets.Exh: ExhGroup
|
||||||
get() = ExhGroup
|
get() = ExhGroup
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName", "ktlint:standard:backing-property-naming")
|
||||||
private var __AllAssets: ____KtList<ImageVector>? = null
|
private var __AllAssets: ____KtList<ImageVector>? = null
|
||||||
|
|
||||||
public val ExhGroup.AllAssets: ____KtList<ImageVector>
|
public val ExhGroup.AllAssets: ____KtList<ImageVector>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ public object AssetsGroup
|
||||||
public val ExhGroup.Assets: AssetsGroup
|
public val ExhGroup.Assets: AssetsGroup
|
||||||
get() = AssetsGroup
|
get() = AssetsGroup
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName", "ktlint:standard:backing-property-naming")
|
||||||
private var __AllAssets: ____KtList<ImageVector>? = null
|
private var __AllAssets: ____KtList<ImageVector>? = null
|
||||||
|
|
||||||
public val AssetsGroup.AllAssets: ____KtList<ImageVector>
|
public val AssetsGroup.AllAssets: ____KtList<ImageVector>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ public object EhassetsGroup
|
||||||
public val AssetsGroup.Ehassets: EhassetsGroup
|
public val AssetsGroup.Ehassets: EhassetsGroup
|
||||||
get() = EhassetsGroup
|
get() = EhassetsGroup
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName", "ktlint:standard:backing-property-naming")
|
||||||
private var __AllAssets: ____KtList<ImageVector>? = null
|
private var __AllAssets: ____KtList<ImageVector>? = null
|
||||||
|
|
||||||
public val EhassetsGroup.AllAssets: ____KtList<ImageVector>
|
public val EhassetsGroup.AllAssets: ____KtList<ImageVector>
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,12 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara
|
||||||
val raisedMeta = meta.raise<EHentaiSearchMetadata>()
|
val raisedMeta = meta.raise<EHentaiSearchMetadata>()
|
||||||
|
|
||||||
// Don't update galleries too frequently
|
// Don't update galleries too frequently
|
||||||
if (raisedMeta.aged || (curTime - raisedMeta.lastUpdateCheck < MIN_BACKGROUND_UPDATE_FREQ && DebugToggles.RESTRICT_EXH_GALLERY_UPDATE_CHECK_FREQUENCY.enabled)) {
|
if (raisedMeta.aged ||
|
||||||
|
(
|
||||||
|
curTime - raisedMeta.lastUpdateCheck < MIN_BACKGROUND_UPDATE_FREQ &&
|
||||||
|
DebugToggles.RESTRICT_EXH_GALLERY_UPDATE_CHECK_FREQUENCY.enabled
|
||||||
|
)
|
||||||
|
) {
|
||||||
return@mapNotNull null
|
return@mapNotNull null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,8 @@ class FavoritesSyncHelper(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate library state
|
// Validate library state
|
||||||
status.value = FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_verifying_library))
|
status.value =
|
||||||
|
FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_verifying_library))
|
||||||
val libraryManga = getLibraryManga.await()
|
val libraryManga = getLibraryManga.await()
|
||||||
val seenManga = HashSet<Long>(libraryManga.size)
|
val seenManga = HashSet<Long>(libraryManga.size)
|
||||||
libraryManga.forEach { (manga) ->
|
libraryManga.forEach { (manga) ->
|
||||||
|
|
@ -116,10 +117,12 @@ class FavoritesSyncHelper(val context: Context) {
|
||||||
|
|
||||||
// Download remote favorites
|
// Download remote favorites
|
||||||
val favorites = try {
|
val favorites = try {
|
||||||
status.value = FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_downloading))
|
status.value =
|
||||||
|
FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_downloading))
|
||||||
exh.fetchFavorites()
|
exh.fetchFavorites()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
status.value = FavoritesSyncStatus.Error(context.stringResource(SYMR.strings.favorites_sync_failed_to_featch))
|
status.value =
|
||||||
|
FavoritesSyncStatus.Error(context.stringResource(SYMR.strings.favorites_sync_failed_to_featch))
|
||||||
logger.e(context.stringResource(SYMR.strings.favorites_sync_could_not_fetch), e)
|
logger.e(context.stringResource(SYMR.strings.favorites_sync_could_not_fetch), e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +182,8 @@ class FavoritesSyncHelper(val context: Context) {
|
||||||
applyChangeSetToRemote(errorList, localChanges)
|
applyChangeSetToRemote(errorList, localChanges)
|
||||||
}
|
}
|
||||||
|
|
||||||
status.value = FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_cleaning_up))
|
status.value =
|
||||||
|
FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_cleaning_up))
|
||||||
storage.snapshotEntries()
|
storage.snapshotEntries()
|
||||||
|
|
||||||
withUIContext {
|
withUIContext {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,14 @@ class LocalFavoritesStorage(
|
||||||
private fun FavoriteEntry.urlEquals(other: FavoriteEntry) = (gid == other.gid && token == other.token) ||
|
private fun FavoriteEntry.urlEquals(other: FavoriteEntry) = (gid == other.gid && token == other.token) ||
|
||||||
(otherGid != null && otherToken != null && (otherGid == other.gid && otherToken == other.token)) ||
|
(otherGid != null && otherToken != null && (otherGid == other.gid && otherToken == other.token)) ||
|
||||||
(other.otherGid != null && other.otherToken != null && (gid == other.otherGid && token == other.otherToken)) ||
|
(other.otherGid != null && other.otherToken != null && (gid == other.otherGid && token == other.otherToken)) ||
|
||||||
(otherGid != null && otherToken != null && other.otherGid != null && other.otherToken != null && otherGid == other.otherGid && otherToken == other.otherToken)
|
(
|
||||||
|
otherGid != null &&
|
||||||
|
otherToken != null &&
|
||||||
|
other.otherGid != null &&
|
||||||
|
other.otherToken != null &&
|
||||||
|
otherGid == other.otherGid &&
|
||||||
|
otherToken == other.otherToken
|
||||||
|
)
|
||||||
|
|
||||||
private fun queryListForEntry(list: List<FavoriteEntry>, entry: FavoriteEntry) =
|
private fun queryListForEntry(list: List<FavoriteEntry>, entry: FavoriteEntry) =
|
||||||
list.find { it.urlEquals(entry) && it.category == entry.category }
|
list.find { it.urlEquals(entry) && it.category == entry.category }
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,14 @@ class EnhancedFilePrinter internal constructor(
|
||||||
val lastFileName = writer.lastFileName
|
val lastFileName = writer.lastFileName
|
||||||
if (fileNameGenerator.isFileNameChangeable) {
|
if (fileNameGenerator.isFileNameChangeable) {
|
||||||
val newFileName = fileNameGenerator.generateFileName(logLevel, System.currentTimeMillis())
|
val newFileName = fileNameGenerator.generateFileName(logLevel, System.currentTimeMillis())
|
||||||
require(!(newFileName == null || newFileName.trim { it <= ' ' }.isEmpty())) { "File name should not be empty." }
|
require(
|
||||||
|
!(
|
||||||
|
newFileName == null ||
|
||||||
|
newFileName.trim {
|
||||||
|
it <= ' '
|
||||||
|
}.isEmpty()
|
||||||
|
),
|
||||||
|
) { "File name should not be empty." }
|
||||||
if (newFileName != lastFileName) {
|
if (newFileName != lastFileName) {
|
||||||
if (writer.isOpened) {
|
if (writer.isOpened) {
|
||||||
writer.close()
|
writer.close()
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
||||||
val duplicateManga = screenModel.getDuplicateLibraryManga(manga)
|
val duplicateManga = screenModel.getDuplicateLibraryManga(manga)
|
||||||
when {
|
when {
|
||||||
manga.favorite -> screenModel.setDialog(
|
manga.favorite -> screenModel.setDialog(
|
||||||
BrowseSourceScreenModel.Dialog.RemoveManga(manga)
|
BrowseSourceScreenModel.Dialog.RemoveManga(manga),
|
||||||
)
|
)
|
||||||
duplicateManga != null -> screenModel.setDialog(
|
duplicateManga != null -> screenModel.setDialog(
|
||||||
BrowseSourceScreenModel.Dialog.AddDuplicateManga(
|
BrowseSourceScreenModel.Dialog.AddDuplicateManga(
|
||||||
|
|
@ -169,7 +169,7 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() {
|
||||||
dialog.duplicate.id,
|
dialog.duplicate.id,
|
||||||
dialog.manga.id,
|
dialog.manga.id,
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
is BrowseSourceScreenModel.Dialog.RemoveManga -> {
|
||||||
|
|
|
||||||
|
|
@ -131,10 +131,14 @@ class ApiMangaParser(
|
||||||
// things that will go with the genre tags but aren't actually genre
|
// things that will go with the genre tags but aren't actually genre
|
||||||
val nonGenres = listOfNotNull(
|
val nonGenres = listOfNotNull(
|
||||||
mangaAttributesDto.publicationDemographic
|
mangaAttributesDto.publicationDemographic
|
||||||
?.let { RaisedTag("Demographic", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT) },
|
?.let {
|
||||||
|
RaisedTag("Demographic", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT)
|
||||||
|
},
|
||||||
mangaAttributesDto.contentRating
|
mangaAttributesDto.contentRating
|
||||||
?.takeUnless { it == "safe" }
|
?.takeUnless { it == "safe" }
|
||||||
?.let { RaisedTag("Content Rating", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT) },
|
?.let {
|
||||||
|
RaisedTag("Content Rating", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
val genres = nonGenres + mangaAttributesDto.tags
|
val genres = nonGenres + mangaAttributesDto.tags
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class NamicomiHandler(currentClient: OkHttpClient, userAgent: String) {
|
||||||
val hash = data.jsonObject["hash"]!!.jsonPrimitive.content
|
val hash = data.jsonObject["hash"]!!.jsonPrimitive.content
|
||||||
|
|
||||||
/* Available quality levels: source, high, medium, low */
|
/* Available quality levels: source, high, medium, low */
|
||||||
val quality = if(dataSaver) "low" else "high"
|
val quality = if (dataSaver) "low" else "high"
|
||||||
|
|
||||||
return data
|
return data
|
||||||
.jsonObject[quality]!!
|
.jsonObject[quality]!!
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import exh.source.getMainSource
|
||||||
import exh.util.dropBlank
|
import exh.util.dropBlank
|
||||||
import exh.util.floor
|
import exh.util.floor
|
||||||
import exh.util.nullIfZero
|
import exh.util.nullIfZero
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,11 @@ class MetadataViewScreen(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
when (@Suppress("NAME_SHADOWING") val state = state) {
|
when
|
||||||
|
(
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val state = state
|
||||||
|
) {
|
||||||
MetadataViewState.Loading -> LoadingScreen()
|
MetadataViewState.Loading -> LoadingScreen()
|
||||||
MetadataViewState.MetadataNotFound -> EmptyScreen(MR.strings.no_results_found)
|
MetadataViewState.MetadataNotFound -> EmptyScreen(MR.strings.no_results_found)
|
||||||
MetadataViewState.SourceNotFound -> EmptyScreen(MR.strings.source_empty_screen)
|
MetadataViewState.SourceNotFound -> EmptyScreen(MR.strings.source_empty_screen)
|
||||||
|
|
@ -68,7 +72,8 @@ class MetadataViewScreen(
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val items = remember(state.meta) { state.meta.getExtraInfoPairs(context) }
|
val items = remember(state.meta) { state.meta.getExtraInfoPairs(context) }
|
||||||
ScrollbarLazyColumn(
|
ScrollbarLazyColumn(
|
||||||
contentPadding = paddingValues + WindowInsets.navigationBars.asPaddingValues() + topSmallPaddingValues,
|
contentPadding =
|
||||||
|
paddingValues + WindowInsets.navigationBars.asPaddingValues() + topSmallPaddingValues,
|
||||||
) {
|
) {
|
||||||
items(items) { (title, text) ->
|
items(items) { (title, text) ->
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -109,7 +114,7 @@ class MetadataViewScreen(
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
TachiyomiTheme(
|
TachiyomiTheme(
|
||||||
seedColor = seedColor?.let { Color(seedColor) }.takeIf { screenModel.themeCoverBased }
|
seedColor = seedColor?.let { Color(seedColor) }.takeIf { screenModel.themeCoverBased },
|
||||||
) {
|
) {
|
||||||
// KMK <--
|
// KMK <--
|
||||||
content()
|
content()
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,11 @@ fun EHentaiDescription(
|
||||||
?: meta.genre
|
?: meta.genre
|
||||||
?: context.stringResource(MR.strings.unknown)
|
?: context.stringResource(MR.strings.unknown)
|
||||||
|
|
||||||
binding.visible.text = context.stringResource(SYMR.strings.is_visible, meta.visible ?: context.stringResource(MR.strings.unknown))
|
binding.visible.text =
|
||||||
|
context.stringResource(
|
||||||
|
SYMR.strings.is_visible,
|
||||||
|
meta.visible ?: context.stringResource(MR.strings.unknown),
|
||||||
|
)
|
||||||
// KMK -->
|
// KMK -->
|
||||||
binding.visible.setTextColor(textColor)
|
binding.visible.setTextColor(textColor)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
@ -100,7 +104,8 @@ fun EHentaiDescription(
|
||||||
val ratingFloat = meta.averageRating?.toFloat()
|
val ratingFloat = meta.averageRating?.toFloat()
|
||||||
binding.ratingBar.rating = ratingFloat ?: 0F
|
binding.ratingBar.rating = ratingFloat ?: 0F
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
binding.rating.text = (ratingFloat ?: 0F).toString() + " - " + MetadataUIUtil.getRatingString(context, ratingFloat?.times(2))
|
binding.rating.text =
|
||||||
|
(ratingFloat ?: 0F).toString() + " - " + MetadataUIUtil.getRatingString(context, ratingFloat?.times(2))
|
||||||
// KMK -->
|
// KMK -->
|
||||||
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
|
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
|
||||||
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
|
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ fun HBrowseDescription(state: State.Success, openMetadataViewer: () -> Unit) {
|
||||||
if (meta == null || meta !is HBrowseSearchMetadata) return@AndroidView
|
if (meta == null || meta !is HBrowseSearchMetadata) return@AndroidView
|
||||||
val binding = DescriptionAdapterHbBinding.bind(it)
|
val binding = DescriptionAdapterHbBinding.bind(it)
|
||||||
|
|
||||||
binding.pages.text = context.pluralStringResource(SYMR.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
|
binding.pages.text =
|
||||||
|
context.pluralStringResource(SYMR.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
|
||||||
// KMK -->
|
// KMK -->
|
||||||
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
|
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
|
||||||
binding.pages.setTextColor(textColor)
|
binding.pages.setTextColor(textColor)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ fun MangaDexDescription(state: State.Success, openMetadataViewer: () -> Unit) {
|
||||||
val ratingFloat = meta.rating
|
val ratingFloat = meta.rating
|
||||||
binding.ratingBar.rating = ratingFloat?.div(2F) ?: 0F
|
binding.ratingBar.rating = ratingFloat?.div(2F) ?: 0F
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + getRatingString(context, ratingFloat)
|
binding.rating.text =
|
||||||
|
(round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + getRatingString(context, ratingFloat)
|
||||||
binding.rating.isVisible = ratingFloat != null
|
binding.rating.isVisible = ratingFloat != null
|
||||||
binding.ratingBar.isVisible = ratingFloat != null
|
binding.ratingBar.isVisible = ratingFloat != null
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ fun NHentaiDescription(state: State.Success, openMetadataViewer: () -> Unit) {
|
||||||
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT
|
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT
|
||||||
.format(
|
.format(
|
||||||
ZonedDateTime
|
ZonedDateTime
|
||||||
.ofInstant(Instant.ofEpochSecond(meta.uploadDate ?: 0), ZoneId.systemDefault())
|
.ofInstant(Instant.ofEpochSecond(meta.uploadDate ?: 0), ZoneId.systemDefault()),
|
||||||
)
|
)
|
||||||
// KMK -->
|
// KMK -->
|
||||||
binding.whenPosted.setTextColor(textColor)
|
binding.whenPosted.setTextColor(textColor)
|
||||||
|
|
|
||||||
|
|
@ -42,16 +42,17 @@ fun PururinDescription(state: State.Success, openMetadataViewer: () -> Unit) {
|
||||||
if (meta == null || meta !is PururinSearchMetadata) return@AndroidView
|
if (meta == null || meta !is PururinSearchMetadata) return@AndroidView
|
||||||
val binding = DescriptionAdapterPuBinding.bind(it)
|
val binding = DescriptionAdapterPuBinding.bind(it)
|
||||||
|
|
||||||
binding.genre.text = meta.tags.find { it.namespace == PururinSearchMetadata.TAG_NAMESPACE_CATEGORY }.let { genre ->
|
binding.genre.text =
|
||||||
genre?.let { tag -> MetadataUIUtil.getGenreAndColour(context, tag.name) }
|
meta.tags.find { it.namespace == PururinSearchMetadata.TAG_NAMESPACE_CATEGORY }.let { genre ->
|
||||||
?.let { (genre, name) ->
|
genre?.let { tag -> MetadataUIUtil.getGenreAndColour(context, tag.name) }
|
||||||
binding.genre.setBackgroundColor(genre.color)
|
?.let { (genre, name) ->
|
||||||
// KMK -->
|
binding.genre.setBackgroundColor(genre.color)
|
||||||
binding.genre.setTextColor(genreTextColor(genre))
|
// KMK -->
|
||||||
// KMK <--
|
binding.genre.setTextColor(genreTextColor(genre))
|
||||||
name
|
// KMK <--
|
||||||
} ?: genre?.name ?: context.stringResource(MR.strings.unknown)
|
name
|
||||||
}
|
} ?: genre?.name ?: context.stringResource(MR.strings.unknown)
|
||||||
|
}
|
||||||
|
|
||||||
binding.uploader.text = meta.uploaderDisp ?: meta.uploader.orEmpty()
|
binding.uploader.text = meta.uploaderDisp ?: meta.uploader.orEmpty()
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
@ -73,7 +74,9 @@ fun PururinDescription(state: State.Success, openMetadataViewer: () -> Unit) {
|
||||||
val ratingFloat = meta.averageRating?.toFloat()
|
val ratingFloat = meta.averageRating?.toFloat()
|
||||||
binding.ratingBar.rating = ratingFloat ?: 0F
|
binding.ratingBar.rating = ratingFloat ?: 0F
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUIUtil.getRatingString(context, ratingFloat?.times(2))
|
binding.rating.text =
|
||||||
|
(round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " +
|
||||||
|
MetadataUIUtil.getRatingString(context, ratingFloat?.times(2))
|
||||||
// KMK -->
|
// KMK -->
|
||||||
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
|
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
|
||||||
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
|
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue