add KMK comment

This commit is contained in:
Tran M. Cuong 2024-06-16 19:09:17 +07:00
parent 854ea8c7f0
commit 7a99a9a9b5
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
79 changed files with 517 additions and 70 deletions

View file

@ -13,7 +13,9 @@ class TrustExtension(
) {
suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean {
// KMK -->
if (fingerprints.contains(CreateExtensionRepo.OFFICIAL_REPO_SIGNATURE)) return true
// KMK <--
val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet()
val key = "${pkgInfo.packageName}:${PackageInfoCompat.getLongVersionCode(pkgInfo)}:${fingerprints.last()}"
return trustedFingerprints.any { fingerprints.contains(it) } || key in preferences.trustedExtensions().get()

View file

@ -19,6 +19,7 @@ class SyncChapterProgressWithTrack(
private val getChaptersByMangaId: GetChaptersByMangaId,
) {
val trackPreferences: TrackPreferences = Injekt.get()
suspend fun await(
mangaId: Long,
remoteTrack: Track,
@ -32,12 +33,15 @@ class SyncChapterProgressWithTrack(
// Current chapters in database
val dbChapters = getChaptersByMangaId.await(mangaId)
// KMK -->
.reversed()
// KMK <--
.filter { it.isRecognizedNumber }
val sortedChapters = dbChapters
.sortedBy { it.chapterNumber }
// KMK -->
// Chapters to update to follow tracker: only continuous incremental chapters
// any abnormal chapter number will stop it from updating read status further
var lastCheckChapter: Double
@ -49,6 +53,7 @@ class SyncChapterProgressWithTrack(
chapter.chapterNumber >= lastCheckChapter && chapter.chapterNumber <= remoteTrack.lastChapterRead
}
.filter { chapter -> !chapter.read }
// KMK <--
.map { it.copy(read = true).toChapterUpdate() }
// only take into account continuous reading

View file

@ -35,6 +35,10 @@ class TrackPreferences(
fun anilistScoreType() = preferenceStore.getString("anilist_score_type", Anilist.POINT_10)
fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true)
// KMK -->
fun updateTrackMarkedRead() = preferenceStore.getBoolean("pref_update_tracking_marked_read_key", false)
fun autoSyncReadChapters() = preferenceStore.getBoolean("pref_auto_sync_read_chapters_key", false)
// KMK <--
}

View file

@ -25,9 +25,11 @@ class UiPreferences(
fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
// KMK -->
fun themeCoverBased() = preferenceStore.getBoolean("pref_theme_cover_based_key", true)
fun themeCoverBasedStyle() = preferenceStore.getEnum("pref_theme_cover_based_style_key", PaletteStyle.Vibrant)
// KMK <--
fun relativeTime() = preferenceStore.getBoolean("relative_time_v2", true)
@ -43,7 +45,9 @@ class UiPreferences(
fun feedTabInFront() = preferenceStore.getBoolean("latest_tab_position", false)
// KMK -->
fun expandRelatedTitles() = preferenceStore.getBoolean("expand_related_titles", true)
// KMK <--
fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", true)

View file

@ -70,8 +70,10 @@ fun ExtensionDetailsScreen(
navigateUp: () -> Unit,
state: ExtensionDetailsScreenModel.State,
onClickSourcePreferences: (sourceId: Long) -> Unit,
// KMK -->
onClickWhatsNew: () -> Unit,
onClickReadme: () -> Unit,
// KMK <--
onClickEnableAll: () -> Unit,
onClickDisableAll: () -> Unit,
onClickClearCookies: () -> Unit,

View file

@ -59,9 +59,9 @@ private fun ExtensionFilterContent(
items(state.languages) { language ->
SwitchPreferenceWidget(
modifier = Modifier.animateItemPlacement(),
title = LocaleHelper.getSourceDisplayName(language, context)
title = LocaleHelper.getSourceDisplayName(language, context) +
// KMK -->
+ " (${LocaleHelper.getDisplayName(language)})",
" (${LocaleHelper.getDisplayName(language)})",
// KMK <--
checked = language in state.enabledLanguages,
onCheckedChanged = { onClickLang(language) },

View file

@ -210,9 +210,12 @@ fun FeedAddSearchDialog(
val context = LocalContext.current
val savedSearchStrings = remember {
savedSearches.map {
it?.name
// KMK -->
it?.name ?: if (source.supportsLatest) {
?: if (source.supportsLatest) {
// KMK <--
context.stringResource(MR.strings.latest)
// KMK -->
} else {
context.stringResource(MR.strings.popular)
}
@ -244,8 +247,8 @@ fun FeedAddSearchDialog(
@Composable
fun <T> RadioSelector(
options: ImmutableList<T>,
selected: Int?,
optionStrings: ImmutableList<String> = remember { options.map { it.toString() }.toImmutableList() },
selected: Int?,
onSelectOption: (Int) -> Unit = {},
) {
Column(Modifier.verticalScroll(rememberScrollState())) {

View file

@ -98,7 +98,10 @@ fun SourcesScreen(
when {
state.isLoading -> LoadingScreen(Modifier.padding(contentPadding))
state.isEmpty && state.searchQuery.isNullOrBlank() -> EmptyScreen(
// KMK -->
state.searchQuery.isNullOrBlank() &&
// KMK <--
state.isEmpty -> EmptyScreen(
MR.strings.source_empty_screen,
modifier = Modifier.padding(contentPadding),
)

View file

@ -57,9 +57,11 @@ private val defaultContent: @Composable RowScope.(Source, String?) -> Unit = { s
Text(
text = source.name +
// KMK -->
(source.installedExtension?.let { extension ->
" (${extension.name})".takeIf {extension.name != source.name }
} ?: ""),
(
source.installedExtension?.let { extension ->
" (${extension.name})".takeIf { extension.name != source.name }
} ?: ""
),
// KMK <--
maxLines = 1,
overflow = TextOverflow.Ellipsis,

View file

@ -99,11 +99,10 @@ internal fun BrowseSourceComfortableGridItem(
ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified,
),
// KMK -->
isSelected = isSelected,
coverAlpha = when {
manga.favorite -> CommonMangaItemDefaults.BrowseFavoriteCoverAlpha
else -> 1f
},
// KMK <--
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
coverBadgeStart = {
InLibraryBadge(enabled = manga.favorite)
},

View file

@ -99,11 +99,10 @@ internal fun BrowseSourceCompactGridItem(
ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified,
),
// KMK -->
isSelected = isSelected,
coverAlpha = when {
manga.favorite -> CommonMangaItemDefaults.BrowseFavoriteCoverAlpha
else -> 1f
},
// KMK <--
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
coverBadgeStart = {
InLibraryBadge(enabled = manga.favorite)
},

View file

@ -92,11 +92,10 @@ internal fun BrowseSourceListItem(
ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified,
),
// KMK -->
isSelected = isSelected,
coverAlpha = when {
manga.favorite -> CommonMangaItemDefaults.BrowseFavoriteCoverAlpha
else -> 1f
},
// KMK <--
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
badge = {
InLibraryBadge(enabled = manga.favorite)
// SY -->

View file

@ -78,11 +78,10 @@ internal fun MangaItem(
coverBadgeStart = {
InLibraryBadge(enabled = isFavorite)
},
// KMK -->
isSelected = isSelected,
coverAlpha = when {
isFavorite -> CommonMangaItemDefaults.BrowseFavoriteCoverAlpha
else -> 1f
},
// KMK <--
coverAlpha = if (isFavorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
onClick = onClick,
onLongClick = onLongClick,
)

View file

@ -49,15 +49,19 @@ fun HistoryItem(
.padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small),
verticalAlignment = Alignment.CenterVertically,
) {
// KMK -->
val mangaCover = history.coverData
val bgColor = mangaCover.dominantCoverColors?.first?.let { Color(it) }
val onBgColor = mangaCover.dominantCoverColors?.second
// KMK <--
MangaCover.Book(
modifier = Modifier.fillMaxHeight(),
data = mangaCover,
onClick = onClickCover,
// KMK -->
bgColor = bgColor,
tint = onBgColor,
// KMK <--
)
Column(
modifier = Modifier

View file

@ -71,10 +71,14 @@ fun MangaCompactGridItem(
coverAlpha: Float = 1f,
coverBadgeStart: @Composable (RowScope.() -> Unit)? = null,
coverBadgeEnd: @Composable (RowScope.() -> Unit)? = null,
// KMK -->
libraryColored: Boolean? = null,
// KMK <--
) {
// KMK -->
val bgColor = libraryColored?.let { coverData.dominantCoverColors?.first?.let { Color(it) } }
val onBgColor = libraryColored?.let { coverData.dominantCoverColors?.second }
// KMK <--
GridItemSelectable(
isSelected = isSelected,
onClick = onClick,
@ -84,11 +88,16 @@ fun MangaCompactGridItem(
cover = {
MangaCover.Book(
modifier = Modifier
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
// KMK <--
.fillMaxWidth(),
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
data = coverData,
// KMK -->
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
bgColor = bgColor,
tint = onBgColor,
// KMK <--
)
},
badgesStart = coverBadgeStart,
@ -178,10 +187,14 @@ fun MangaComfortableGridItem(
coverBadgeStart: (@Composable RowScope.() -> Unit)? = null,
coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null,
onClickContinueReading: (() -> Unit)? = null,
// KMK -->
libraryColored: Boolean? = null,
// KMK <--
) {
// KMK -->
val bgColor = libraryColored?.let { coverData.dominantCoverColors?.first?.let { Color(it) } }
val onBgColor = libraryColored?.let { coverData.dominantCoverColors?.second }
// KMK <--
GridItemSelectable(
isSelected = isSelected,
onClick = onClick,
@ -192,11 +205,16 @@ fun MangaComfortableGridItem(
cover = {
MangaCover.Book(
modifier = Modifier
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
// KMK <--
.fillMaxWidth(),
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
data = coverData,
// KMK -->
alpha = if (isSelected) GridSelectedCoverAlpha else coverAlpha,
bgColor = bgColor,
tint = onBgColor,
// KMK <--
)
},
badgesStart = coverBadgeStart,
@ -334,10 +352,14 @@ fun MangaListItem(
isSelected: Boolean = false,
coverAlpha: Float = 1f,
onClickContinueReading: (() -> Unit)? = null,
// KMK -->
libraryColored: Boolean? = null,
// KMK <--
) {
// KMK -->
val bgColor = libraryColored?.let { coverData.dominantCoverColors?.first?.let { Color(it) } }
val onBgColor = libraryColored?.let { coverData.dominantCoverColors?.second }
// KMK <--
Row(
modifier = Modifier
.selectedBackground(isSelected)
@ -351,11 +373,16 @@ fun MangaListItem(
) {
MangaCover.Square(
modifier = Modifier
// KMK -->
// .alpha(coverAlpha)
// KMK <--
.fillMaxHeight(),
alpha = coverAlpha,
data = coverData,
// KMK -->
alpha = coverAlpha,
bgColor = bgColor,
tint = onBgColor,
// KMK <--
)
Text(
text = title,

View file

@ -61,7 +61,9 @@ internal fun LibraryComfortableGrid(
} else {
null
},
// KMK -->
libraryColored = true,
// KMK <--
)
}
}

View file

@ -62,7 +62,9 @@ internal fun LibraryCompactGrid(
} else {
null
},
// KMK -->
libraryColored = true,
// KMK <--
)
}
}

View file

@ -69,7 +69,9 @@ internal fun LibraryList(
} else {
null
},
// KMK -->
libraryColored = true,
// KMK <--
)
}
}

View file

@ -445,7 +445,9 @@ private fun MangaScreenSmallImpl(
actionModeCounter = selectedChapterCount,
onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() },
// KMK -->
onPaletteScreenClick = onPaletteScreenClick,
// KMK <--
)
},
bottomBar = {
@ -669,7 +671,9 @@ private fun MangaScreenSmallImpl(
chapterCount = chapters.size,
missingChapterCount = missingChapterCount,
onClick = onFilterClicked,
// KMK -->
hasFilters = state.filterActive,
// KMK <--
)
}
@ -820,7 +824,9 @@ private fun MangaScreenLargeImpl(
actionModeCounter = selectedChapterCount,
onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() },
// KMK -->
onPaletteScreenClick = onPaletteScreenClick,
// KMK <--
)
},
bottomBar = {
@ -1029,7 +1035,9 @@ private fun MangaScreenLargeImpl(
chapterCount = chapters.size,
missingChapterCount = missingChapterCount,
onClick = onFilterButtonClicked,
// KMK -->
hasFilters = state.filterActive,
// KMK <--
)
}

View file

@ -102,7 +102,7 @@ private fun NotDownloadedIndicator(
painter = painterResource(R.drawable.ic_download_chapter_24dp),
contentDescription = stringResource(MR.strings.manga_download),
modifier = Modifier.size(IndicatorSize),
tint = MaterialTheme.colorScheme.primary,
tint = MaterialTheme.colorScheme.primary, // KMK: onSurfaceVariant
)
}
}
@ -128,7 +128,7 @@ private fun DownloadingIndicator(
contentAlignment = Alignment.Center,
) {
val arrowColor: Color
val strokeColor = MaterialTheme.colorScheme.primary
val strokeColor = MaterialTheme.colorScheme.primary // KMK: onSurfaceVariant
val downloadProgress = downloadProgressProvider()
val indeterminate = downloadState == Download.State.QUEUE ||
(downloadState == Download.State.DOWNLOADING && downloadProgress == 0)
@ -208,7 +208,7 @@ private fun DownloadedIndicator(
imageVector = Icons.Filled.CheckCircle,
contentDescription = null,
modifier = Modifier.size(IndicatorSize),
tint = MaterialTheme.colorScheme.primary,
tint = MaterialTheme.colorScheme.primary, // KMK: onSurfaceVariant
)
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
DropdownMenuItem(

View file

@ -29,11 +29,15 @@ fun ChapterHeader(
chapterCount: Int?,
missingChapterCount: Int,
onClick: () -> Unit,
// KMK -->
hasFilters: Boolean,
// KMK <--
modifier: Modifier = Modifier,
) {
// KMK -->
val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else MaterialTheme.colorScheme.primary
Row(
// KMK <--
modifier = modifier
.fillMaxWidth()
.clickable(
@ -41,9 +45,11 @@ fun ChapterHeader(
onClick = onClick,
)
.padding(horizontal = 16.dp, vertical = 4.dp),
// KMK -->
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
// KMK <--
Column(
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
) {
@ -60,11 +66,13 @@ fun ChapterHeader(
MissingChaptersWarning(missingChapterCount)
}
// KMK -->
Icon(
imageVector = Icons.Outlined.FilterList,
contentDescription = null,
tint = filterTint,
)
// KMK <--
}
}

View file

@ -41,11 +41,14 @@ enum class MangaCover(val ratio: Float) {
contentDescription: String = "",
shape: Shape = MaterialTheme.shapes.extraSmall,
onClick: (() -> Unit)? = null,
// KMK -->
alpha: Float = 1f,
bgColor: Color? = null,
@ColorInt tint: Int? = null,
onCoverLoaded: ((DomainMangaCover) -> Unit)? = null,
// KMK <--
) {
// KMK -->
val animatedImageVector = AnimatedImageVector.animatedVectorResource(R.drawable.anim_waiting)
var atEnd by remember { mutableStateOf(false) }
@ -61,9 +64,12 @@ enum class MangaCover(val ratio: Float) {
}
var succeed by remember { mutableStateOf(false) }
// KMK <--
AsyncImage(
model = data,
// KMK -->
// placeholder = ColorPainter(CoverPlaceholderColor),
placeholder = rememberAnimatedVectorPainter(animatedImageVector = animatedImageVector, atEnd = atEnd),
error = rememberResourceBitmapPainter(id = R.drawable.cover_error, tint),
fallback = rememberResourceBitmapPainter(id = R.drawable.cover_error, tint),
@ -76,12 +82,15 @@ enum class MangaCover(val ratio: Float) {
}
}
},
// KMK <--
contentDescription = contentDescription,
modifier = modifier
.aspectRatio(ratio)
.clip(shape)
// KMK -->
.alpha(if (succeed) alpha else 1f)
.background(bgColor ?: Color.Transparent)
// KMK <--
.then(
if (onClick != null) {
Modifier.clickable(

View file

@ -132,12 +132,17 @@ fun MangaInfoBox(
drawRect(
brush = Brush.verticalGradient(
colors = backdropGradientColors,
// KMK -->
startY = size.height / 2,
// KMKM <--
),
)
}
// KMK -->
.background(MaterialTheme.colorScheme.surfaceTint.copy(alpha = 0.4f))
.blur(7.dp)
// .blur(4.dp)
// KMK <--
.alpha(0.2f),
)
@ -234,7 +239,11 @@ fun MangaActionRow(
)
},
icon = Icons.Default.HourglassEmpty,
color = if (isUserIntervalMode || nextUpdateDays?.let { it <= 1 } == true) {
color = if (isUserIntervalMode ||
// KMK -->
nextUpdateDays?.let { it <= 1 } == true
// KMK <--
) {
MaterialTheme.colorScheme.primary
} else {
defaultActionButtonColor
@ -255,7 +264,7 @@ fun MangaActionRow(
MangaActionButton(
title = stringResource(MR.strings.action_web_view),
icon = Icons.Outlined.Public,
color = MaterialTheme.colorScheme.primary,
color = MaterialTheme.colorScheme.primary, // KMK: defaultActionButtonColor
onClick = onWebViewClicked,
onLongClick = onWebViewLongClicked,
)
@ -265,7 +274,7 @@ fun MangaActionRow(
MangaActionButton(
title = stringResource(SYMR.strings.merge),
icon = Icons.AutoMirrored.Outlined.CallMerge,
color = MaterialTheme.colorScheme.primary,
color = MaterialTheme.colorScheme.primary, // KMK: defaultActionButtonColor
onClick = onMergeClicked,
)
}
@ -286,8 +295,10 @@ fun ExpandableMangaDescription(
// SY <--
modifier: Modifier = Modifier,
) {
// KMK -->
val uiPreferences = Injekt.get<UiPreferences>()
val pureDarkMode = uiPreferences.themeDarkAmoled().get()
// KMK <--
Column(modifier = modifier) {
val (expanded, onExpanded) = rememberSaveable {
mutableStateOf(defaultExpandState)
@ -355,7 +366,9 @@ fun ExpandableMangaDescription(
tagSelected = it
showMenu = true
},
// KMK -->
pureDarkMode = pureDarkMode,
// KMK <--
)
} else {
// SY <--
@ -371,7 +384,9 @@ fun ExpandableMangaDescription(
tagSelected = it
showMenu = true
},
// KMK -->
pureDarkMode = pureDarkMode,
// KMK <--
)
}
}
@ -389,7 +404,9 @@ fun ExpandableMangaDescription(
tagSelected = it
showMenu = true
},
// KMK -->
pureDarkMode = pureDarkMode,
// KMK <--
)
}
}
@ -427,7 +444,9 @@ private fun MangaAndSourceTitlesLarge(
data = coverDataProvider(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover -> onCoverLoaded(mangaCover) },
// KMK <--
)
Spacer(modifier = Modifier.height(16.dp))
MangaContentInfo(
@ -477,7 +496,9 @@ private fun MangaAndSourceTitlesSmall(
data = coverDataProvider(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover -> onCoverLoaded(mangaCover) },
// KMK <--
)
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
@ -636,6 +657,7 @@ private fun ColumnScope.MangaContentInfo(
text = sourceName,
modifier = Modifier.clickableNoIndication {
// KMK -->
// doSearch(sourceName, false)
onSourceClick()
// KMK <--
},
@ -695,7 +717,9 @@ private fun MangaSummary(
contentDescription = stringResource(
if (expanded) MR.strings.manga_info_collapse else MR.strings.manga_info_expand,
),
tint = MaterialTheme.colorScheme.primary,
// KMK -->
tint = MaterialTheme.colorScheme.primary, // KMK: onBackground
// KMK <--
modifier = Modifier.background(Brush.radialGradient(colors = colors.asReversed())),
)
}

View file

@ -56,7 +56,9 @@ fun MangaToolbar(
modifier: Modifier = Modifier,
backgroundAlphaProvider: () -> Float = titleAlphaProvider,
// KMK -->
onPaletteScreenClick: () -> Unit,
// KMK <--
) {
Column(
modifier = modifier,

View file

@ -99,7 +99,9 @@ value class SearchMetadataChips(
fun NamespaceTags(
tags: SearchMetadataChips,
onClick: (item: String) -> Unit,
// KMK -->
pureDarkMode: Boolean = false,
// KMK <--
) {
Column(Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(4.dp)) {
tags.tags.forEach { (namespace, tags) ->
@ -109,7 +111,9 @@ fun NamespaceTags(
modifier = Modifier.padding(top = 4.dp),
text = namespace,
onClick = null,
// KMK -->
pureDarkMode = pureDarkMode,
// KMK <--
)
}
FlowRow(
@ -125,20 +129,28 @@ fun NamespaceTags(
border = borderDp?.let {
SuggestionChipDefaults.suggestionChipBorder(
borderWidth = it,
// KMK -->
borderColor = MaterialTheme.colorScheme.primary,
// KMK <--
)
} ?: SuggestionChipDefaults.suggestionChipBorder(
// KMK -->
borderColor = MaterialTheme.colorScheme.primary,
// KMK <--
),
borderM3 = borderDp?.let {
SuggestionChipDefaultsM3.suggestionChipBorder(
enabled = true,
borderWidth = it,
// KMK -->
borderColor = MaterialTheme.colorScheme.primary,
// KMK <--
)
} ?: SuggestionChipDefaultsM3.suggestionChipBorder(
enabled = true,
// KMK -->
borderColor = MaterialTheme.colorScheme.primary,
// KMK <--
),
)
}
@ -154,12 +166,17 @@ fun TagsChip(
onClick: (() -> Unit)?,
modifier: Modifier = Modifier,
border: ChipBorder? = SuggestionChipDefaults.suggestionChipBorder(),
// KMK -->
// borderM3: BorderStroke? = SuggestionChipDefaultsM3.suggestionChipBorder(enabled = true),
borderM3: BorderStroke? = null,
pureDarkMode: Boolean = false,
// KMK <--
) {
CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) {
if (onClick != null) {
// KMK -->
if (borderM3 != null || pureDarkMode) {
// KMK <--
SuggestionChip(
modifier = modifier,
onClick = onClick,
@ -171,7 +188,9 @@ fun TagsChip(
overflow = TextOverflow.Ellipsis,
)
},
border = borderM3 ?: SuggestionChipDefaultsM3.suggestionChipBorder(
border = borderM3
// KMK -->
?: SuggestionChipDefaultsM3.suggestionChipBorder(
enabled = true,
borderColor = MaterialTheme.colorScheme.primary,
),
@ -193,6 +212,7 @@ fun TagsChip(
),
)
}
// KMK <--
} else {
SuggestionChip(
modifier = modifier,

View file

@ -451,7 +451,9 @@ object SettingsAdvancedScreen : SearchableSettings {
}
},
),
// KMK -->
Preference.PreferenceItem.InfoPreference(stringResource(KMR.strings.pref_private_installer_warning)),
// KMK <--
Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.ext_revoke_trust),
onClick = {

View file

@ -47,7 +47,9 @@ object SettingsAppearanceScreen : SearchableSettings {
return listOf(
getThemeGroup(uiPreferences = uiPreferences),
// KMK -->
getDetailsPageThemeGroup(uiPreferences = uiPreferences),
// KMK <--
getDisplayGroup(uiPreferences = uiPreferences),
// SY -->
getNavbarGroup(uiPreferences = uiPreferences),
@ -106,6 +108,7 @@ object SettingsAppearanceScreen : SearchableSettings {
)
}
// KMK -->
@Composable
private fun getDetailsPageThemeGroup(
uiPreferences: UiPreferences,
@ -132,6 +135,7 @@ object SettingsAppearanceScreen : SearchableSettings {
),
)
}
// KMK <--
@Composable
private fun getDisplayGroup(
@ -192,7 +196,9 @@ object SettingsAppearanceScreen : SearchableSettings {
@Composable
fun getForkGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup {
val previewsRowCount by uiPreferences.previewsRowCount().collectAsState()
// KMK -->
val sourcePreferences = remember { Injekt.get<SourcePreferences>() }
// KMK <--
return Preference.PreferenceGroup(
stringResource(SYMR.strings.pref_category_fork),
@ -201,12 +207,14 @@ object SettingsAppearanceScreen : SearchableSettings {
pref = uiPreferences.expandFilters(),
title = stringResource(SYMR.strings.toggle_expand_search_filters),
),
// KMK -->
Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.expandRelatedTitles(),
title = stringResource(KMR.strings.pref_expand_related_titles),
subtitle = stringResource(KMR.strings.pref_expand_related_titles_summary),
enabled = sourcePreferences.relatedMangas().get(),
),
// KMK <--
Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.recommendsInOverflow(),
title = stringResource(SYMR.strings.put_recommends_in_overflow),

View file

@ -126,6 +126,7 @@ object SettingsTrackingScreen : SearchableSettings {
pref = trackPreferences.autoUpdateTrack(),
title = stringResource(MR.strings.pref_auto_update_manga_sync),
),
// KMK -->
Preference.PreferenceItem.SwitchPreference(
pref = trackPreferences.updateTrackMarkedRead(),
title = stringResource(KMR.strings.pref_update_tracking_marked_read),
@ -134,6 +135,7 @@ object SettingsTrackingScreen : SearchableSettings {
pref = trackPreferences.autoSyncReadChapters(),
title = stringResource(KMR.strings.pref_auto_sync_read_chapters),
),
// KMK <--
Preference.PreferenceGroup(
title = stringResource(MR.strings.services),
preferenceItems = persistentListOf(

View file

@ -329,6 +329,7 @@ object AboutScreen : Screen() {
}
}
// KMK -->
private suspend fun getReleaseNotes(
context: Context,
onAvailableUpdate: (GetApplicationRelease.Result.NewUpdate) -> Unit,
@ -351,6 +352,7 @@ object AboutScreen : Screen() {
}
}
}
// KMK <--
fun getVersionName(withBuildDate: Boolean): String {
return when {

View file

@ -50,11 +50,13 @@ fun WhatsNewDialog(onDismissRequest: () -> Unit) {
}
},
title = { Text(text = stringResource(MR.strings.updated_version, BuildConfig.VERSION_NAME)) },
// KMK -->
dismissButton = {
TextButton(onClick = { context.openInBrowser(RELEASE_URL) }) {
Text(text = stringResource(KMR.strings.changelogs))
}
},
// KMK <--
text = {
Column {
val changelog by produceState<List<DisplayChangelog>?>(initialValue = null) {

View file

@ -169,17 +169,21 @@ private fun UpdatesUiItem(
.padding(horizontal = MaterialTheme.padding.medium),
verticalAlignment = Alignment.CenterVertically,
) {
// KMK -->
val mangaCover = update.coverData
val bgColor = mangaCover.dominantCoverColors?.first?.let { Color(it) }
val onBgColor = mangaCover.dominantCoverColors?.second
// KMK <--
MangaCover.Square(
modifier = Modifier
.padding(vertical = 6.dp)
.fillMaxHeight(),
data = mangaCover,
onClick = onClickCover,
// KMK -->
bgColor = bgColor,
tint = onBgColor,
// KMK <--
)
Column(

View file

@ -20,12 +20,19 @@ import androidx.core.graphics.drawable.toBitmap
* @return the bitmap associated with the resource
*/
@Composable
fun rememberResourceBitmapPainter(@DrawableRes id: Int, @ColorInt tint: Int? = null): BitmapPainter {
fun rememberResourceBitmapPainter(
@DrawableRes id: Int,
// KMK -->
@ColorInt tint: Int? = null,
// KMK <--
): BitmapPainter {
val context = LocalContext.current
return remember(id) {
val drawable = ContextCompat.getDrawable(context, id)
?: throw Resources.NotFoundException()
// KMK -->
tint?.let { drawable.setTint(it) }
// KMK <--
BitmapPainter(drawable.toBitmap().asImageBitmap())
}
}

View file

@ -101,8 +101,10 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
@SuppressLint("LaunchActivityFromNotification")
override fun onCreate() {
super<Application>.onCreate()
// KMK -->
Firebase.initialize(this)
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
// KMK <--
// SY -->
if (!isDevFlavor) {
@ -168,7 +170,9 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get())
// KMK -->
MangaCoverMetadata.load()
// KMK <--
// Updates widget update
with(WidgetManager(Injekt.get(), Injekt.get())) {

View file

@ -56,8 +56,11 @@ import java.io.IOException
*/
@Suppress("LongParameterList")
class MangaCoverFetcher(
// KMK -->
private val mangaCover: MangaCover,
private val url: String? = mangaCover.url,
// private val url: String?,
// KMK <--
private val isLibraryManga: Boolean,
private val options: Options,
private val coverFileLazy: Lazy<File?>,
@ -68,8 +71,10 @@ class MangaCoverFetcher(
private val imageLoader: ImageLoader,
) : Fetcher {
// KMK -->
private val fileScope by lazy { CoroutineScope(Job() + Dispatchers.IO) }
private val uiPreferences = Injekt.get<UiPreferences>()
// KMK <--
private val diskCacheKey: String
get() = diskCacheKeyLazy.value
@ -98,7 +103,9 @@ class MangaCoverFetcher(
}
private fun fileLoader(file: File): FetchResult {
// KMK -->
setRatioAndColorsInScope(mangaCover, ogFile = file)
// KMK <--
return SourceFetchResult(
source = ImageSource(
file = file.toOkioPath(),
@ -111,7 +118,9 @@ class MangaCoverFetcher(
}
private fun fileUriLoader(uri: String): FetchResult {
// KMK -->
setRatioAndColorsInScope(mangaCover)
// KMK <--
val source = UniFile.fromUri(options.context, uri.toUri())!!
.openInputStream()
.source()
@ -145,7 +154,9 @@ class MangaCoverFetcher(
}
// Read from snapshot
// KMK -->
setRatioAndColorsInScope(mangaCover, bufferedSource = snapshot.toImageSource().source())
// KMK <--
return SourceFetchResult(
source = snapshot.toImageSource(),
mimeType = "image/*",
@ -166,7 +177,9 @@ class MangaCoverFetcher(
// Read from disk cache
snapshot = writeToDiskCache(response)
if (snapshot != null) {
// KMK -->
setRatioAndColorsInScope(mangaCover, bufferedSource = snapshot.toImageSource().source())
// KMK <--
return SourceFetchResult(
source = snapshot.toImageSource(),
mimeType = "image/*",
@ -174,6 +187,7 @@ class MangaCoverFetcher(
)
}
// KMK -->
setRatioAndColorsInScope(
mangaCover,
bufferedSource = ImageSource(
@ -181,6 +195,7 @@ class MangaCoverFetcher(
fileSystem = FileSystem.SYSTEM,
).source(),
)
// KMK <--
// Read from response if cache is unused or unusable
return SourceFetchResult(
source = ImageSource(source = responseBody.source(), fileSystem = FileSystem.SYSTEM),
@ -319,6 +334,7 @@ class MangaCoverFetcher(
}
}
// KMK -->
/**
* [setRatioAndColorsInScope] is called whenever a cover is loaded with [MangaCoverFetcher.fetch]
*
@ -338,6 +354,7 @@ class MangaCoverFetcher(
MangaCoverMetadata.setRatioAndColors(mangaCover, bufferedSource, ogFile, onlyFavorite, force)
}
}
// KMK <--
private enum class Type {
File,
@ -354,7 +371,10 @@ class MangaCoverFetcher(
override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
// KMK -->
// url = data.thumbnailUrl,
mangaCover = data.asMangaCover(),
// KMK <--
isLibraryManga = data.favorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) },
@ -376,7 +396,10 @@ class MangaCoverFetcher(
override fun create(data: MangaCover, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
// KMK -->
// url = data.url,
mangaCover = data,
// KMK <--
isLibraryManga = data.isMangaFavorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.url) },

View file

@ -70,6 +70,8 @@ object MangaCoverMetadata {
*
* This is only for loading color first time it appears on Library/Browse. Any new colors caused by loading new
* cover when open a manga detail or change cover will be updated separately on [MangaScreenModel.setPaletteColor].
*
* @author Jays2Kings, cuong-tran
*/
fun setRatioAndColors(
mangaCover: MangaCover,

View file

@ -44,6 +44,7 @@ val Options.customDecoder: Boolean
private val customDecoderKey = Extras.Key(default = false)
// KMK -->
/**
* Calculate the best [Palette.Swatch] from [Palette]
* @author Jays2Kings
@ -82,3 +83,4 @@ fun Palette.getBestColor(): Int? {
}
}?.rgb
}
// KMK <--

View file

@ -85,7 +85,7 @@ class DownloadCache(
* The interval after which this cache should be invalidated. 1 hour shouldn't cause major
* issues, as the cache is only used for UI feedback.
*/
private val renewInterval //= 1.hours.inWholeMilliseconds
private val renewInterval // = 1.hours.inWholeMilliseconds
// KMK -->
get() = downloadPreferences.downloadCacheRenewInterval().get()
.hours.inWholeMilliseconds
@ -330,7 +330,11 @@ class DownloadCache(
lastRenew = 0L
renewalJob?.cancel()
diskCacheFile.delete()
renewCache(/* KMK --> */ 0L /* KMK <-- */)
renewCache(
// KMK -->
renewInterval = 0L,
// KMK <--
)
}
// KMK -->
@ -345,9 +349,18 @@ class DownloadCache(
/**
* Renews the downloads cache.
*/
private fun renewCache(/* KMK --> */ renewInterval: Long = this.renewInterval /* KMK <-- */) {
private fun renewCache(
// KMK -->
renewInterval: Long = this.renewInterval,
// KMK <--
) {
// Avoid renewing cache if in the process nor too often
if (/* KMK --> */ renewInterval < 0L || /* KMK <-- */ lastRenew + renewInterval >= System.currentTimeMillis() || renewalJob?.isActive == true) {
if (lastRenew + renewInterval >= System.currentTimeMillis() ||
// KMK -->
renewInterval < 0L ||
// KMK <--
renewalJob?.isActive == true
) {
return
}

View file

@ -80,5 +80,7 @@ interface Tracker {
suspend fun setRemoteFinishDate(track: Track, epochMillis: Long)
// KMK -->
fun hasNotStartedReading(status: Long): Boolean
// KMK <--
}

View file

@ -241,5 +241,7 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
}
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == PLAN_TO_READ
// KMK <--
}

View file

@ -148,5 +148,7 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
.toImmutableList()
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == PLAN_TO_READ
// KMK <--
}

View file

@ -145,5 +145,7 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
authentications = oauth
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == UNREAD
// KMK <--
}

View file

@ -154,5 +154,7 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
}
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == PLAN_TO_READ
// KMK <--
}

View file

@ -112,5 +112,7 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
null
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == UNREAD
// KMK <--
}

View file

@ -121,5 +121,7 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
return trackPreferences.trackPassword(this).get().ifBlank { null }
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == WISH_LIST
// KMK <--
}

View file

@ -173,5 +173,7 @@ class MdList(id: Long) : BaseTracker(id, "MDList") {
class MangaDexNotFoundException : Exception("Mangadex not enabled")
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == FollowStatus.PLAN_TO_READ.long
// KMK <--
}

View file

@ -175,5 +175,7 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
}
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == PLAN_TO_READ
// KMK <--
}

View file

@ -152,5 +152,7 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
interceptor.newAuth(null)
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == PLAN_TO_READ
// KMK <--
}

View file

@ -104,5 +104,7 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
null
}
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == UNREAD
// KMK <--
}

View file

@ -82,7 +82,12 @@ data class BrowseTab(
)
} else if (feedTabInFront) {
persistentListOf(
feedTab(/* KMK --> */feedScreenModel, bulkFavoriteScreenModel/* KMK <-- */),
feedTab(
// KMK -->
feedScreenModel,
bulkFavoriteScreenModel,
// KMK <--
),
sourcesTab(),
extensionsTab(extensionsScreenModel),
migrateSourceTab(),
@ -90,7 +95,12 @@ data class BrowseTab(
} else {
persistentListOf(
sourcesTab(),
feedTab(/* KMK --> */feedScreenModel, bulkFavoriteScreenModel/* KMK <-- */),
feedTab(
// KMK -->
feedScreenModel,
bulkFavoriteScreenModel,
// KMK <--
),
extensionsTab(extensionsScreenModel),
migrateSourceTab(),
)

View file

@ -30,14 +30,18 @@ data class ExtensionDetailsScreen(
}
val navigator = LocalNavigator.currentOrThrow
// KMK -->
val uriHandler = LocalUriHandler.current
// KMK <--
ExtensionDetailsScreen(
navigateUp = navigator::pop,
state = state,
onClickSourcePreferences = { navigator.push(SourcePreferencesScreen(it)) },
// KMK -->
onClickWhatsNew = { uriHandler.openUri(screenModel.getChangelogUrl()) },
onClickReadme = { uriHandler.openUri(screenModel.getReadmeUrl()) },
// KMK <--
onClickEnableAll = { screenModel.toggleSources(true) },
onClickDisableAll = { screenModel.toggleSources(false) },
onClickClearCookies = screenModel::clearCookies,

View file

@ -131,6 +131,7 @@ open class FeedScreenModel(
source,
(
// KMK -->
// (if (source.supportsLatest) persistentListOf(null) else persistentListOf()) +
persistentListOf(null) +
// KMK <-->
getSourceSavedSearches(source.id)
@ -152,7 +153,7 @@ open class FeedScreenModel(
}
private suspend fun hasTooManyFeeds(): Boolean {
return countFeedSavedSearchGlobal.await() > MAX_FEED_ITEMS
return countFeedSavedSearchGlobal.await() > MaxFeedItems
}
fun getEnabledSources(): ImmutableList<CatalogueSource> {
@ -234,10 +235,13 @@ open class FeedScreenModel(
withContext(coroutineDispatcher) {
if (itemUI.savedSearch == null) {
// KMK -->
if (itemUI.source.supportsLatest)
if (itemUI.source.supportsLatest) {
// KMK <--
itemUI.source.getLatestUpdates(1)
else
// KMK -->
} else {
itemUI.source.getPopularManga(1)
}
// KMK <--
} else {
itemUI.source.getSearchManga(
@ -331,4 +335,4 @@ data class FeedScreenState(
get() = items?.fastAny { it.results == null } != false
}
const val MAX_FEED_ITEMS = 20
const val MaxFeedItems = 20

View file

@ -112,9 +112,9 @@ fun feedTab(
listingQuery = if (!source.supportsLatest) {
GetRemoteManga.QUERY_POPULAR
} else {
// KMK <--
GetRemoteManga.QUERY_LATEST
},
// KMK <--
),
)
},

View file

@ -98,6 +98,7 @@ class SourcesScreenModel(
// KMK -->
filters: Pair<String?, Boolean>,
unfilteredSources: List<Source>,
// sources: List<Source>,
// KMK <--
categories: List<String>,
showLatest: Boolean,

View file

@ -166,7 +166,10 @@ class SourceFeedScreen(val sourceId: Long) : Screen() {
openMangaDexRandom = if (screenModel.sourceIsMangaDex) {
{
screenModel.onMangaDexRandom {
// KMK -->
// navigator.replace(
navigator.push(
// KMK <--
BrowseSourceScreen(
sourceId,
"id:$it",
@ -179,7 +182,10 @@ class SourceFeedScreen(val sourceId: Long) : Screen() {
},
openMangaDexFollows = if (screenModel.sourceIsMangaDex) {
{
// KMK -->
// navigator.replace(MangaDexFollowsScreen(sourceId))
navigator.push(MangaDexFollowsScreen(sourceId))
// KMK <--
}
} else {
null
@ -221,19 +227,31 @@ class SourceFeedScreen(val sourceId: Long) : Screen() {
}
fun onBrowseClick(navigator: Navigator, sourceId: Long, search: String? = null, savedSearch: Long? = null, filters: String? = null) {
// KMK -->
// navigator.replace(BrowseSourceScreen(sourceId, search, savedSearch = savedSearch, filtersJson = filters))
navigator.push(BrowseSourceScreen(sourceId, search, savedSearch = savedSearch, filtersJson = filters))
// KMK <--
}
private fun onLatestClick(navigator: Navigator, source: Source) {
// KMK -->
// navigator.replace(BrowseSourceScreen(source.id, GetRemoteManga.QUERY_LATEST))
navigator.push(BrowseSourceScreen(source.id, GetRemoteManga.QUERY_LATEST))
// KMK <--
}
fun onBrowseClick(navigator: Navigator, source: Source) {
// KMK -->
// navigator.replace(BrowseSourceScreen(source.id, GetRemoteManga.QUERY_POPULAR))
navigator.push(BrowseSourceScreen(source.id, GetRemoteManga.QUERY_POPULAR))
// KMK <--
}
private fun onSavedSearchClick(navigator: Navigator, source: Source, savedSearch: SavedSearch) {
// KMK -->
// navigator.replace(BrowseSourceScreen(source.id, listingQuery = null, savedSearch = savedSearch.id))
navigator.push(BrowseSourceScreen(source.id, listingQuery = null, savedSearch = savedSearch.id))
// KMK <--
}
private fun onSearchClick(navigator: Navigator, source: Source, query: String) {

View file

@ -17,7 +17,7 @@ import eu.kanade.presentation.browse.SourceFeedUI
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.online.all.MangaDex
import eu.kanade.tachiyomi.ui.browse.feed.MAX_FEED_ITEMS
import eu.kanade.tachiyomi.ui.browse.feed.MaxFeedItems
import exh.source.getMainSource
import exh.source.mangaDexSourceIds
import exh.util.nullIfBlank
@ -109,7 +109,7 @@ open class SourceFeedScreenModel(
}
private suspend fun hasTooManyFeeds(): Boolean {
return countFeedSavedSearchBySourceId.await(source.id) > MAX_FEED_ITEMS
return countFeedSavedSearchBySourceId.await(source.id) > MaxFeedItems
}
fun createFeed(savedSearchId: Long) {

View file

@ -290,6 +290,9 @@ object LibraryTab : Tab {
initialSelection = dialog.initialSelection,
onDismissRequest = onDismissRequest,
onEditCategories = {
// KMK -->
// screenModel.clearSelection()
// KMK <--
navigator.push(CategoryScreen())
},
onConfirm = { include, exclude ->

View file

@ -337,10 +337,12 @@ class MainActivity : BaseActivity() {
// SY -->
}
// KMK -->
override fun onPause() {
super.onPause()
MangaCoverMetadata.savePrefs()
}
// KMK <--
override fun onProvideAssistContent(outContent: AssistContent) {
super.onProvideAssistContent(outContent)

View file

@ -58,7 +58,6 @@ import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.source.local.isLocal
import timber.log.Timber
@Composable
fun EditMangaDialog(
@ -78,6 +77,7 @@ fun EditMangaDialog(
var binding by remember {
mutableStateOf<EditMangaDialogBinding?>(null)
}
// KMK -->
val colors = EditMangaDialogColors(
textColor = MaterialTheme.colorScheme.onSurfaceVariant.toArgb(),
textHighlightColor = MaterialTheme.colorScheme.outline.toArgb(),
@ -89,6 +89,7 @@ fun EditMangaDialog(
dropdownBgColor = MaterialTheme.colorScheme.surfaceVariant.toArgb(),
dialogBgColor = MaterialTheme.colorScheme.surfaceContainerHigh.toArgb(),
)
// KMK <--
AlertDialog(
onDismissRequest = onDismissRequest,
confirmButton = {
@ -142,7 +143,9 @@ fun EditMangaDialog(
factoryContext,
this,
scope,
// KMK -->
colors,
// KMK <--
)
}
.root
@ -154,6 +157,7 @@ fun EditMangaDialog(
)
}
// KMK -->
class EditMangaDialogColors(
@ColorInt val textColor: Int,
@ColorInt val textHighlightColor: Int,
@ -165,17 +169,23 @@ class EditMangaDialogColors(
@ColorInt val dropdownBgColor: Int,
@ColorInt val dialogBgColor: Int,
)
// KMK <--
private fun onViewCreated(
manga: Manga,
context: Context,
binding: EditMangaDialogBinding,
scope: CoroutineScope,
// KMK -->
colors: EditMangaDialogColors,
// KMK <--
) {
loadCover(manga, binding)
// KMK -->
// val statusAdapter: ArrayAdapter<String> = ArrayAdapter(
val statusAdapter = SpinnerAdapter(
// KMK <--
context,
android.R.layout.simple_spinner_dropdown_item,
listOf(
@ -187,7 +197,9 @@ private fun onViewCreated(
MR.strings.cancelled,
MR.strings.on_hiatus,
).map { context.stringResource(it) },
// KMK -->
colors,
// KMK <--
)
binding.status.adapter = statusAdapter
@ -206,6 +218,7 @@ private fun onViewCreated(
)
}
// KMK -->
// Set Spinner's selected item's background color to transparent
binding.status.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
@ -216,6 +229,7 @@ private fun onViewCreated(
// Set Spinner's dropdown caret color
binding.status.backgroundTintList = ColorStateList.valueOf(colors.iconColor)
// KMK
if (manga.isLocal()) {
if (manga.title != manga.url) {
@ -265,6 +279,7 @@ private fun onViewCreated(
}
binding.mangaGenresTags.clearFocus()
// KMK -->
listOf(
binding.title,
binding.mangaAuthor,
@ -308,6 +323,7 @@ private fun onViewCreated(
binding.resetTags.setBackgroundColor(colors.btnBgColor)
binding.resetInfo.setTextColor(colors.btnTextColor)
binding.resetInfo.setBackgroundColor(colors.btnBgColor)
// KMK <--
binding.resetTags.setOnClickListener { resetTags(manga, binding, scope, colors) }
binding.resetInfo.setOnClickListener { resetInfo(manga, binding, scope, colors) }
@ -317,7 +333,9 @@ private fun resetTags(
manga: Manga,
binding: EditMangaDialogBinding,
scope: CoroutineScope,
// KMK -->
colors: EditMangaDialogColors,
// KMK <--
) {
if (manga.genre.isNullOrEmpty() || manga.isLocal()) {
binding.mangaGenresTags.setChips(emptyList(), scope, colors)
@ -336,7 +354,9 @@ private fun resetInfo(
manga: Manga,
binding: EditMangaDialogBinding,
scope: CoroutineScope,
// KMK -->
colors: EditMangaDialogColors,
// KMK <--
) {
binding.title.setText("")
binding.mangaAuthor.setText("")
@ -349,24 +369,35 @@ private fun resetInfo(
private fun ChipGroup.setChips(
items: List<String>,
scope: CoroutineScope,
// KMK -->
colors: EditMangaDialogColors,
// KMK <--
) {
removeAllViews()
// KMK -->
val colorStateList = ColorStateList.valueOf(colors.tagColor)
// KMK <--
items.asSequence().map { item ->
Chip(context).apply {
text = item
// KMK -->
setTextColor(colors.tagTextColor)
// KMK <--
isCloseIconVisible = true
// KMK -->
// closeIcon?.setTint(context.getResourceColor(R.attr.colorAccent))
closeIcon?.setTint(colors.iconColor)
// KMK <--
setOnCloseIconClickListener {
removeView(this)
}
// KMK -->
chipBackgroundColor = colorStateList
// KMK <--
}
}.forEach {
addView(it)
@ -374,16 +405,24 @@ private fun ChipGroup.setChips(
val addTagChip = Chip(context).apply {
text = SYMR.strings.add_tag.getString(context)
// KMK -->
setTextColor(colors.tagTextColor)
// KMK <--
chipIcon = ContextCompat.getDrawable(context, R.drawable.ic_add_24dp)?.apply {
isChipIconVisible = true
// KMK -->
// setTint(context.getResourceColor(R.attr.colorAccent))
setTint(colors.iconColor)
// KMK <--
}
// KMK -->
chipBackgroundColor = colorStateList
// KMK <--
setOnClickListener {
// KMK -->
var dialog: AlertDialog? = null
val builder = MaterialAlertDialogBuilder(context)
@ -391,8 +430,10 @@ private fun ChipGroup.setChips(
.setTitle(SYMR.strings.add_tag.getString(context))
.setPositiveButton(MR.strings.action_ok.getString(context)) {
dialog?.dismissDialog()
// KMK <--
val newTag = it.trimOrNull()
if (newTag != null) setChips(items + listOfNotNull(newTag), scope, colors)
// KMK -->
}
.setNegativeButton(MR.strings.action_cancel.getString(context)) {
dialog?.dismissDialog()
@ -403,6 +444,7 @@ private fun ChipGroup.setChips(
dialog = builder.create()
dialog.setView(binding.root)
dialog.show()
// KMK <--
}
}
addView(addTagChip)
@ -416,6 +458,7 @@ private fun ChipGroup.getTextStrings(): List<String> = children.mapNotNull {
}
}.toList()
// KMK -->
private class SpinnerAdapter(
context: Context,
@LayoutRes val resource: Int,
@ -447,7 +490,6 @@ private class SpinnerAdapter(
// If no custom field is assigned, assume the whole resource is a TextView
text = view as TextView
} catch (e: ClassCastException) {
Timber.e("You must supply a resource ID for a TextView")
throw IllegalStateException("ArrayAdapter requires the resource ID to be a TextView", e)
}
@ -460,3 +502,4 @@ private class SpinnerAdapter(
return view
}
}
// KMK <--

View file

@ -136,6 +136,7 @@ class MangaScreen(
}
val successState = state as MangaScreenModel.State.Success
// KMK -->
val seedColorState = rememberUpdatedState(newValue = successState.seedColor)
val uiPreferences = remember { Injekt.get<UiPreferences>() }
@ -159,6 +160,7 @@ class MangaScreen(
screenModel: MangaScreenModel,
successState: MangaScreenModel.State.Success,
) {
// KMK <--
val navigator = LocalNavigator.currentOrThrow
val haptic = LocalHapticFeedback.current
val scope = rememberCoroutineScope()
@ -254,7 +256,15 @@ class MangaScreen(
previewsRowCount = successState.previewsRowCount,
// SY -->
onMigrateClicked = { migrateManga(navigator, screenModel.manga!!) }.takeIf { successState.manga.favorite },
onMetadataViewerClicked = { openMetadataViewer(navigator, successState.manga, successState.seedColor) },
onMetadataViewerClicked = {
openMetadataViewer(
navigator,
successState.manga,
// KMK -->
successState.seedColor,
// KMK <--
)
},
onEditInfoClicked = screenModel::showEditMangaInfoDialog,
onRecommendClicked = { openRecommends(context, navigator, screenModel.source?.getMainSource(), successState.manga) },
onMergedSettingsClicked = screenModel::showEditMergedSettingsDialog,
@ -524,21 +534,33 @@ class MangaScreen(
return
}
// KMK -->
navigator.popUntil { screen ->
navigator.size < 2 || screen is BrowseSourceScreen ||
screen is HomeScreen || screen is SourceFeedScreen
}
// KMK <--
when (val previousController = navigator.lastItem) {
is HomeScreen -> {
// KMK -->
// navigator.pop()
// KMK <--
previousController.search(query)
}
is BrowseSourceScreen -> {
// KMK -->
// navigator.pop()
// KMK <--
previousController.search(query)
}
// SY -->
is SourceFeedScreen -> {
// KMK -->
// navigator.pop()
// navigator.replace(BrowseSourceScreen(previousController.sourceId, query))
navigator.push(BrowseSourceScreen(previousController.sourceId, query))
// KMK <--
}
// SY <--
}
@ -559,10 +581,14 @@ class MangaScreen(
while (idx >= 0) {
previousController = navigator.items[idx--]
if (previousController is BrowseSourceScreen && source is HttpSource) {
// KMK -->
// navigator.pop()
navigator.popUntil { navigator.size == idx + 2 }
// KMK <--
previousController.searchGenre(genreName)
return
}
// KMK -->
if (previousController is SourceFeedScreen && source is HttpSource) {
navigator.popUntil { navigator.size == idx + 2 }
navigator.push(BrowseSourceScreen(previousController.sourceId, ""))
@ -570,6 +596,7 @@ class MangaScreen(
previousController.searchGenre(genreName)
return
}
// KMK <--
}
performSearch(navigator, genreName, global = false)
}
@ -599,7 +626,13 @@ class MangaScreen(
// SY <--
}
private fun openMetadataViewer(navigator: Navigator, manga: Manga, seedColor: Color? = null) {
private fun openMetadataViewer(
navigator: Navigator,
manga: Manga,
// KMK -->
seedColor: Color? = null,
// KMK <--
) {
navigator.push(MetadataViewScreen(manga.id, manga.source, seedColor))
}

View file

@ -221,7 +221,9 @@ class MangaScreenModel(
val loggedInTrackers by lazy { trackerManager.trackers.filter { it.isLoggedIn } }
// KMK -->
val useNewSourceNavigation by uiPreferences.useNewSourceNavigation().asState(screenModelScope)
// KMK <--
val manga: Manga?
get() = successState?.manga
@ -462,7 +464,9 @@ class MangaScreenModel(
// Fetch info-chapters when needed
if (screenModelScope.isActive) {
val fetchFromSourceTasks = listOf(
// KMK -->
async { syncTrackers() },
// KMK <--
async { if (needRefreshInfo) fetchMangaFromSource() },
async { if (needRefreshChapter) fetchChaptersFromSource() },
)
@ -477,6 +481,7 @@ class MangaScreenModel(
}
}
// KMK -->
/**
* Get the color of the manga cover by loading cover with ImageRequest directly from network.
*/
@ -530,7 +535,6 @@ class MangaScreenModel(
)
}
// KMK -->
private suspend fun syncTrackers() {
if (!trackPreferences.autoSyncReadChapters().get()) return
@ -558,7 +562,9 @@ class MangaScreenModel(
screenModelScope.launch {
updateSuccessState { it.copy(isRefreshingData = true) }
val fetchFromSourceTasks = listOf(
// KMK -->
async { syncTrackers() },
// KMK <--
async { fetchMangaFromSource(manualFetch) },
async { fetchChaptersFromSource(manualFetch) },
)
@ -1103,6 +1109,7 @@ class MangaScreenModel(
} else {
downloadManager.getQueuedDownloadOrNull(chapter.id)
}
// SY -->
@Suppress("NAME_SHADOWING")
val manga = mergedData?.manga?.get(chapter.mangaId) ?: manga
@ -1769,6 +1776,7 @@ class MangaScreenModel(
) : Dialog
data class DeleteChapters(val chapters: List<Chapter>) : Dialog
data class DuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog
/* SY -->
data class Migrate(val newManga: Manga, val oldManga: Manga) : Dialog
SY <-- */

View file

@ -18,6 +18,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
import eu.kanade.tachiyomi.ui.manga.EditMangaDialogColors
// KMK -->
@Suppress("UnusedReceiverParameter")
fun MaterialAlertDialogBuilder.binding(context: Context): DialogStubTextinputBinding {
return DialogStubTextinputBinding.inflate(LayoutInflater.from(context))
@ -53,12 +54,14 @@ fun DialogStubTextinputBinding.setNegativeButton(text: String, onClick: () -> Un
return this
}
@Suppress("unused")
fun DialogStubTextinputBinding.setHint(hint: String? = null): DialogStubTextinputBinding {
textField.hint = hint
return this
}
fun DialogStubTextinputBinding.setTextEdit(prefill: String? = null): DialogStubTextinputBinding {
// KMK <--
textField.editText?.apply {
setText(prefill, TextView.BufferType.EDITABLE)
post {
@ -66,6 +69,7 @@ fun DialogStubTextinputBinding.setTextEdit(prefill: String? = null): DialogStubT
context.getSystemService<InputMethodManager>()?.showSoftInput(this, 0)
}
}
// KMK -->
return this
}
@ -133,3 +137,4 @@ class RoundedCornerDrawable(val color: Int, private val cornerRadius: Float = 72
paint.colorFilter = colorFilter
}
}
// KMK <--

View file

@ -117,5 +117,7 @@ data class DummyTracker(
epochMillis: Long,
) = Unit
// KMK -->
override fun hasNotStartedReading(status: Long): Boolean = status == 2L
// KMK <--
}

View file

@ -42,7 +42,9 @@ import uy.kohesive.injekt.api.get
class MetadataViewScreen(
private val mangaId: Long,
private val sourceId: Long,
// KMK -->
private val seedColor: Color? = null,
// KMK <--
) : Screen() {
@Composable
@ -109,6 +111,7 @@ class MetadataViewScreen(
}
}
// KMK -->
val uiPreferences = remember { Injekt.get<UiPreferences>() }
if (uiPreferences.themeCoverBased().get()) {
@ -123,5 +126,6 @@ class MetadataViewScreen(
} else {
content()
}
// KMK <--
}
}

View file

@ -29,9 +29,11 @@ fun EHentaiDescription(
search: (String) -> Unit,
) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
val ratingBarSecondaryColor = MaterialTheme.colorScheme.outlineVariant.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -50,26 +52,38 @@ fun EHentaiDescription(
}
?: meta.genre
?: context.stringResource(MR.strings.unknown)
// KMK -->
binding.genre.setTextColor(textColor)
// KMK <--
binding.visible.text = context.stringResource(SYMR.strings.is_visible, meta.visible ?: context.stringResource(MR.strings.unknown))
// KMK -->
binding.visible.setTextColor(textColor)
// KMK <--
binding.favorites.text = (meta.favorites ?: 0).toString()
// KMK -->
binding.favorites.bindDrawable(context, R.drawable.ic_book_24dp, iconColor)
binding.favorites.setTextColor(textColor)
// KMK <--
binding.uploader.text = meta.uploader ?: context.stringResource(MR.strings.unknown)
// KMK -->
binding.uploader.setTextColor(textColor)
// KMK <--
binding.size.text = MetadataUtil.humanReadableByteCount(meta.size ?: 0, true)
// KMK -->
binding.size.bindDrawable(context, R.drawable.ic_outline_sd_card_24, iconColor)
binding.size.setTextColor(textColor)
// KMK <--
val length = meta.length ?: 0
binding.pages.text = context.pluralStringResource(SYMR.plurals.num_pages, length, length)
// KMK -->
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
binding.pages.setTextColor(textColor)
// KMK <--
val language = meta.language ?: context.stringResource(MR.strings.unknown)
binding.language.text = if (meta.translated == true) {
@ -77,18 +91,22 @@ fun EHentaiDescription(
} else {
language
}
// KMK -->
binding.language.setTextColor(textColor)
// KMK <--
val ratingFloat = meta.averageRating?.toFloat()
binding.ratingBar.rating = ratingFloat ?: 0F
@SuppressLint("SetTextI18n")
binding.rating.text = (ratingFloat ?: 0F).toString() + " - " + MetadataUIUtil.getRatingString(context, ratingFloat?.times(2))
// KMK -->
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
binding.rating.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
listOf(
binding.favorites,

View file

@ -20,8 +20,10 @@ import tachiyomi.i18n.MR
@Composable
fun EightMusesDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -33,10 +35,12 @@ fun EightMusesDescription(state: State.Success, openMetadataViewer: () -> Unit)
val binding = DescriptionAdapter8mBinding.bind(it)
binding.title.text = meta.title ?: context.stringResource(MR.strings.unknown)
// KMK -->
binding.title.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
binding.title.setOnLongClickListener {
context.copyToClipboard(
@ -45,7 +49,9 @@ fun EightMusesDescription(state: State.Success, openMetadataViewer: () -> Unit)
)
true
}
// KMK -->
binding.title.setTextColor(textColor)
// KMK <--
binding.moreInfo.setOnClickListener {
openMetadataViewer()

View file

@ -20,8 +20,10 @@ import tachiyomi.i18n.sy.SYMR
@Composable
fun HBrowseDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -33,11 +35,13 @@ fun HBrowseDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val binding = DescriptionAdapterHbBinding.bind(it)
binding.pages.text = context.pluralStringResource(SYMR.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
// KMK -->
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
binding.pages.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
binding.pages.setOnLongClickListener {
context.copyToClipboard(

View file

@ -23,9 +23,11 @@ import kotlin.math.round
@Composable
fun MangaDexDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
val ratingBarSecondaryColor = MaterialTheme.colorScheme.outlineVariant.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -43,12 +45,14 @@ fun MangaDexDescription(state: State.Success, openMetadataViewer: () -> Unit) {
binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + getRatingString(context, ratingFloat)
binding.rating.isVisible = ratingFloat != null
binding.ratingBar.isVisible = ratingFloat != null
// KMK -->
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
binding.rating.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
binding.rating.setOnLongClickListener {
context.copyToClipboard(

View file

@ -64,10 +64,14 @@ object MetadataUIUtil {
fun TextView.bindDrawable(
context: Context,
@DrawableRes drawable: Int,
// KMK -->
@ColorInt color: Int = context.getResourceColor(R.attr.colorAccent),
// KMK <--
) {
ContextCompat.getDrawable(context, drawable)?.apply {
// KMK -->
setTint(color)
// KMK <--
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
setCompoundDrawables(this, null, null, null)
}

View file

@ -27,8 +27,10 @@ import java.time.ZonedDateTime
@Composable
fun NHentaiDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -49,13 +51,17 @@ fun NHentaiDescription(state: State.Success, openMetadataViewer: () -> Unit) {
it.second
} ?: categoriesString ?: context.stringResource(MR.strings.unknown)
}
// KMK -->
binding.genre.setTextColor(textColor)
// KMK <--
meta.favoritesCount?.let {
if (it == 0L) return@let
binding.favorites.text = it.toString()
// KMK -->
binding.favorites.bindDrawable(context, R.drawable.ic_book_24dp, iconColor)
binding.favorites.setTextColor(textColor)
// KMK <--
}
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT
@ -63,22 +69,28 @@ fun NHentaiDescription(state: State.Success, openMetadataViewer: () -> Unit) {
ZonedDateTime
.ofInstant(Instant.ofEpochSecond(meta.uploadDate ?: 0), ZoneId.systemDefault())
)
// KMK -->
binding.whenPosted.setTextColor(textColor)
// KMK <--
binding.pages.text = context.pluralStringResource(
SYMR.plurals.num_pages,
meta.pageImageTypes.size,
meta.pageImageTypes.size,
)
// KMK -->
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
binding.pages.setTextColor(textColor)
// KMK <--
@SuppressLint("SetTextI18n")
binding.id.text = "#" + (meta.nhId ?: 0)
// KMK -->
binding.id.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
listOf(
binding.favorites,

View file

@ -25,9 +25,11 @@ import kotlin.math.round
@Composable
fun PururinDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
val ratingBarSecondaryColor = MaterialTheme.colorScheme.outlineVariant.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -44,29 +46,39 @@ fun PururinDescription(state: State.Success, openMetadataViewer: () -> Unit) {
it.second
} ?: genre?.name ?: context.stringResource(MR.strings.unknown)
}
// KMK -->
binding.genre.setTextColor(textColor)
// KMK <--
binding.uploader.text = meta.uploaderDisp ?: meta.uploader.orEmpty()
// KMK -->
binding.uploader.setTextColor(textColor)
// KMK <--
binding.size.text = meta.fileSize ?: context.stringResource(MR.strings.unknown)
// KMK -->
binding.size.bindDrawable(context, R.drawable.ic_outline_sd_card_24, iconColor)
binding.size.setTextColor(textColor)
// KMK <--
binding.pages.text = context.pluralStringResource(SYMR.plurals.num_pages, meta.pages ?: 0, meta.pages ?: 0)
// KMK -->
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
binding.pages.setTextColor(textColor)
// KMK <--
val ratingFloat = meta.averageRating?.toFloat()
binding.ratingBar.rating = ratingFloat ?: 0F
@SuppressLint("SetTextI18n")
binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUIUtil.getRatingString(context, ratingFloat?.times(2))
// KMK -->
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
binding.rating.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
listOf(
binding.genre,

View file

@ -26,9 +26,11 @@ import kotlin.math.round
@Composable
fun TsuminoDescription(state: State.Success, openMetadataViewer: () -> Unit) {
val context = LocalContext.current
// KMK -->
val textColor = MaterialTheme.colorScheme.secondary.toArgb()
val iconColor = MaterialTheme.colorScheme.primary.toArgb()
val ratingBarSecondaryColor = MaterialTheme.colorScheme.outlineVariant.toArgb()
// KMK <--
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { factoryContext ->
@ -43,31 +45,43 @@ fun TsuminoDescription(state: State.Success, openMetadataViewer: () -> Unit) {
binding.genre.setBackgroundColor(it.first)
it.second
} ?: meta.category ?: context.stringResource(MR.strings.unknown)
// KMK -->
binding.genre.setTextColor(textColor)
// KMK <--
binding.favorites.text = (meta.favorites ?: 0).toString()
// KMK -->
binding.favorites.bindDrawable(context, R.drawable.ic_book_24dp, iconColor)
binding.favorites.setTextColor(textColor)
// KMK <--
binding.whenPosted.text = TsuminoSearchMetadata.TSUMINO_DATE_FORMAT.format(Date(meta.uploadDate ?: 0))
// KMK -->
binding.whenPosted.setTextColor(textColor)
// KMK <--
binding.uploader.text = meta.uploader ?: context.stringResource(MR.strings.unknown)
// KMK -->
binding.uploader.setTextColor(textColor)
// KMK <--
binding.pages.text = context.pluralStringResource(SYMR.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
// KMK -->
binding.pages.bindDrawable(context, R.drawable.ic_baseline_menu_book_24, iconColor)
binding.pages.setTextColor(textColor)
// KMK <--
binding.ratingBar.rating = meta.averageRating ?: 0F
@SuppressLint("SetTextI18n")
binding.rating.text = (round((meta.averageRating ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUIUtil.getRatingString(context, meta.averageRating?.times(2))
// KMK -->
binding.ratingBar.supportProgressTintList = ColorStateList.valueOf(iconColor)
binding.ratingBar.supportSecondaryProgressTintList = ColorStateList.valueOf(ratingBarSecondaryColor)
binding.rating.setTextColor(textColor)
binding.moreInfo.bindDrawable(context, R.drawable.ic_info_24dp, iconColor)
binding.moreInfo.setTextColor(textColor)
// KMK <--
listOf(
binding.favorites,

View file

@ -39,9 +39,11 @@ fun UpcomingItem(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.large),
) {
// KMK -->
val mangaCover = upcoming.asMangaCover()
val bgColor = mangaCover.dominantCoverColors?.first?.let { Color(it) }
val onBgColor = mangaCover.dominantCoverColors?.second
// KMK <--
MangaCover.Book(
modifier = Modifier.fillMaxHeight(),
data = mangaCover,

View file

@ -35,6 +35,7 @@ class LibraryPreferences(
fun lastUpdatedTimestamp() = preferenceStore.getLong(Preference.appStateKey("library_update_last_timestamp"), 0L)
fun autoUpdateInterval() = preferenceStore.getInt("pref_library_update_interval_key", 0)
// KMK -->
fun coverRatios() = preferenceStore.getStringSet(
Preference.appStateKey("pref_library_cover_ratios_key"),
emptySet(),
@ -44,6 +45,7 @@ class LibraryPreferences(
Preference.appStateKey("pref_library_cover_colors_key"),
emptySet(),
)
// KMK <--
fun autoUpdateDeviceRestrictions() = preferenceStore.getStringSet(
"library_update_restriction",

View file

@ -25,6 +25,7 @@ data class MangaCover(
val url: String? = customThumbnailUrl ?: ogUrl
// SY <--
// KMK -->
/**
* [vibrantCoverColor] is used to set the color theme in manga detail page.
* It contains color for all mangas, both in library or browsing.
@ -66,8 +67,6 @@ data class MangaCover(
coverRatioMap[mangaId] = value
}
companion object {
private val getCustomMangaInfo: GetCustomMangaInfo by injectLazy()
/**
* [vibrantCoverColorMap] store color generated while browsing library.
* It always empty at beginning each time app starts, then add more color while browsing.
@ -84,6 +83,11 @@ data class MangaCover(
var coverColorMap = ConcurrentHashMap<Long, Pair<Int, Int>>()
var coverRatioMap = ConcurrentHashMap<Long, Float>()
// KMK <--
// SY -->
private val getCustomMangaInfo: GetCustomMangaInfo by injectLazy()
// SY <--
}
}

View file

@ -29,9 +29,7 @@ data class Release(
else -> ""
}
// SY -->
return assets.find { it.contains("Komikku$apkVariant-") } ?: assets[0]
// SY <--
}
/**

View file

@ -79,6 +79,7 @@ class GetApplicationReleaseTest {
),
)
// KMK: Don't cast, will throw exception if the result is different from expected
result shouldBe GetApplicationRelease.Result.NewUpdate(release)
}
@ -106,6 +107,7 @@ class GetApplicationReleaseTest {
),
)
// KMK: Don't cast, will throw exception if the result is different from expected
result shouldBe GetApplicationRelease.Result.NewUpdate(release)
}

View file

@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp
import tachiyomi.presentation.core.util.drawVerticalScrollbar
/**
* LazyColumn with scrollbar.
* LazyColumn with scrollbar (non-controllable).
*/
@Composable
fun ScrollbarLazyColumn(

View file

@ -22,12 +22,16 @@ val CoverHeight = 87.dp
fun UpdatesMangaCover(
cover: Bitmap?,
modifier: GlanceModifier = GlanceModifier,
// KMK -->
color: Color? = null,
// KMK <--
) {
Box(
modifier = modifier
.size(width = CoverWidth, height = CoverHeight)
// KMK -->
.background(color ?: Color.Unspecified)
// KMK <--
.appWidgetInnerRadius(),
) {
if (cover != null) {

View file

@ -88,7 +88,9 @@ fun UpdatesWidget(
UpdatesMangaCover(
cover = cover,
modifier = GlanceModifier.clickable(actionStartActivity(intent)),
// KMK -->
color = MangaCover.coverColorMap[mangaId]?.first?.let { Color(it) },
// KMK <--
)
}
}