feat (ui): showing source icon in library (#261)
* showing source icon in library * Change language icon for local source from Folder to Globe * adjust size & padding for icon & badge * Setting enable/disable source icon
This commit is contained in:
parent
49e1759a05
commit
29eeccad1b
10 changed files with 142 additions and 4 deletions
|
|
@ -34,6 +34,7 @@ import tachiyomi.domain.library.model.LibrarySort
|
|||
import tachiyomi.domain.library.model.sort
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.kmk.KMR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.components.CheckboxItem
|
||||
import tachiyomi.presentation.core.components.HeadingItem
|
||||
|
|
@ -311,6 +312,12 @@ private fun ColumnScope.DisplayPage(
|
|||
label = stringResource(MR.strings.action_display_language_badge),
|
||||
pref = screenModel.libraryPreferences.languageBadge(),
|
||||
)
|
||||
// KMK -->
|
||||
CheckboxItem(
|
||||
label = stringResource(KMR.strings.action_display_source_badge),
|
||||
pref = screenModel.libraryPreferences.sourceBadge(),
|
||||
)
|
||||
// KMK <--
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_show_continue_reading_button),
|
||||
pref = screenModel.libraryPreferences.showContinueReadingButton(),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,23 @@
|
|||
package eu.kanade.presentation.library.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material.icons.outlined.Folder
|
||||
import androidx.compose.material.icons.outlined.Language
|
||||
import androidx.compose.material.icons.outlined.LocalLibrary
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.source.model.icon
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.presentation.core.components.Badge
|
||||
import tachiyomi.source.local.isLocal
|
||||
|
||||
@Composable
|
||||
internal fun DownloadsBadge(count: Long) {
|
||||
|
|
@ -34,7 +44,7 @@ internal fun LanguageBadge(
|
|||
) {
|
||||
if (isLocal) {
|
||||
Badge(
|
||||
imageVector = Icons.Outlined.Folder,
|
||||
imageVector = Icons.Outlined.Language,
|
||||
color = MaterialTheme.colorScheme.tertiary,
|
||||
iconColor = MaterialTheme.colorScheme.onTertiary,
|
||||
)
|
||||
|
|
@ -47,6 +57,46 @@ internal fun LanguageBadge(
|
|||
}
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
@Composable
|
||||
fun SourceIconBadge(
|
||||
source: Source?,
|
||||
) {
|
||||
if (source == null) return
|
||||
val icon = source.icon
|
||||
|
||||
when {
|
||||
source.isStub && icon == null -> {
|
||||
Badge(
|
||||
imageVector = Icons.Filled.Warning,
|
||||
iconColor = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
icon != null -> {
|
||||
Badge(
|
||||
imageBitmap = icon,
|
||||
modifier = Modifier.scale(1.3f).height(18.dp),
|
||||
)
|
||||
}
|
||||
source.isLocal() -> {
|
||||
Badge(
|
||||
imageVector = Icons.Outlined.Folder,
|
||||
color = MaterialTheme.colorScheme.tertiary,
|
||||
iconColor = MaterialTheme.colorScheme.onTertiary,
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
// Default source icon (if source doesn't have an icon)
|
||||
Badge(
|
||||
imageVector = Icons.Outlined.LocalLibrary,
|
||||
color = MaterialTheme.colorScheme.tertiary,
|
||||
iconColor = MaterialTheme.colorScheme.onTertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun BadgePreview() {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ internal fun LibraryComfortableGrid(
|
|||
isLocal = libraryItem.isLocal,
|
||||
sourceLanguage = libraryItem.sourceLanguage,
|
||||
)
|
||||
// KMK -->
|
||||
SourceIconBadge(source = libraryItem.source)
|
||||
// KMK <--
|
||||
},
|
||||
onLongClick = { onLongClick(libraryItem.libraryManga) },
|
||||
onClick = { onClick(libraryItem.libraryManga) },
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ internal fun LibraryCompactGrid(
|
|||
isLocal = libraryItem.isLocal,
|
||||
sourceLanguage = libraryItem.sourceLanguage,
|
||||
)
|
||||
// KMK -->
|
||||
SourceIconBadge(source = libraryItem.source)
|
||||
// KMK <--
|
||||
},
|
||||
onLongClick = { onLongClick(libraryItem.libraryManga) },
|
||||
onClick = { onClick(libraryItem.libraryManga) },
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ internal fun LibraryList(
|
|||
isLocal = libraryItem.isLocal,
|
||||
sourceLanguage = libraryItem.sourceLanguage,
|
||||
)
|
||||
// KMK -->
|
||||
SourceIconBadge(source = libraryItem.source)
|
||||
// KMK <--
|
||||
},
|
||||
onLongClick = { onLongClick(libraryItem.libraryManga) },
|
||||
onClick = { onClick(libraryItem.libraryManga) },
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.library
|
|||
|
||||
import eu.kanade.tachiyomi.source.getNameForMangaInfo
|
||||
import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
|
@ -12,6 +13,9 @@ data class LibraryItem(
|
|||
val unreadCount: Long = -1,
|
||||
val isLocal: Boolean = false,
|
||||
val sourceLanguage: String = "",
|
||||
// KMK -->
|
||||
val source: Source? = null,
|
||||
// KMK <--
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
) {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ import tachiyomi.domain.manga.model.CustomMangaInfo
|
|||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaUpdate
|
||||
import tachiyomi.domain.manga.model.applyFilter
|
||||
import tachiyomi.domain.source.model.StubSource
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.domain.track.interactor.GetTracksPerManga
|
||||
|
|
@ -118,6 +119,7 @@ import tachiyomi.source.local.isLocal
|
|||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Collections
|
||||
import tachiyomi.domain.source.model.Source as DomainSource
|
||||
|
||||
/**
|
||||
* Typealias for the library manga, using the category as keys, and list of manga as values.
|
||||
|
|
@ -498,6 +500,9 @@ class LibraryScreenModel(
|
|||
// SY -->
|
||||
libraryPreferences.filterLewd().changes(),
|
||||
// SY <--
|
||||
// KMK -->
|
||||
libraryPreferences.sourceBadge().changes(),
|
||||
// KMK <--
|
||||
) {
|
||||
ItemPreferences(
|
||||
downloadBadge = it[0] as Boolean,
|
||||
|
|
@ -514,6 +519,9 @@ class LibraryScreenModel(
|
|||
// SY -->
|
||||
filterLewd = it[11] as TriState,
|
||||
// SY <--
|
||||
// KMK -->
|
||||
sourceBadge = it[12] as Boolean,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -530,6 +538,9 @@ class LibraryScreenModel(
|
|||
libraryMangaList
|
||||
.map { libraryManga ->
|
||||
// Display mode based on user preference: take it from global library setting or category
|
||||
// KMK -->
|
||||
val source = sourceManager.getOrStub(libraryManga.manga.source)
|
||||
// KMK <--
|
||||
LibraryItem(
|
||||
libraryManga,
|
||||
downloadCount = if (prefs.downloadBadge) {
|
||||
|
|
@ -548,10 +559,23 @@ class LibraryScreenModel(
|
|||
unreadCount = libraryManga.unreadCount,
|
||||
isLocal = if (prefs.localBadge) libraryManga.manga.isLocal() else false,
|
||||
sourceLanguage = if (prefs.languageBadge) {
|
||||
sourceManager.getOrStub(libraryManga.manga.source).lang
|
||||
source.lang
|
||||
} else {
|
||||
""
|
||||
},
|
||||
// KMK -->
|
||||
source = if (prefs.sourceBadge) {
|
||||
DomainSource(
|
||||
source.id,
|
||||
source.lang,
|
||||
source.name,
|
||||
supportsLatest = false,
|
||||
isStub = source is StubSource
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
.groupBy { it.libraryManga.category }
|
||||
|
|
@ -1312,6 +1336,9 @@ class LibraryScreenModel(
|
|||
val downloadBadge: Boolean,
|
||||
val localBadge: Boolean,
|
||||
val languageBadge: Boolean,
|
||||
// KMK -->
|
||||
val sourceBadge: Boolean,
|
||||
// KMK <--
|
||||
val skipOutsideReleasePeriod: Boolean,
|
||||
|
||||
val globalFilterDownloaded: Boolean,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,11 @@ class LibraryPreferences(
|
|||
|
||||
fun localBadge() = preferenceStore.getBoolean("display_local_badge", true)
|
||||
|
||||
fun languageBadge() = preferenceStore.getBoolean("display_language_badge", false)
|
||||
fun languageBadge() = preferenceStore.getBoolean("display_language_badge", true)
|
||||
|
||||
// KMK -->
|
||||
fun sourceBadge() = preferenceStore.getBoolean("display_source_badge", true)
|
||||
// KMK <--
|
||||
|
||||
fun newShowUpdatesCount() = preferenceStore.getBoolean("library_show_updates_count", true)
|
||||
fun newUpdatesCount() = preferenceStore.getInt(Preference.appStateKey("library_unseen_updates_count"), 0)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
<!-- Library section -->
|
||||
<string name="pref_show_updating_progress_banner">Show updating progress banner</string>
|
||||
<string name="action_display_source_badge">Source icon</string>
|
||||
|
||||
<!-- Extension section -->
|
||||
<string name="ext_unofficial">Unofficial</string>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package tachiyomi.presentation.core.components
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.InlineTextContent
|
||||
import androidx.compose.foundation.text.appendInlineContent
|
||||
|
|
@ -10,9 +13,12 @@ import androidx.compose.material3.Icon
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
|
@ -29,7 +35,12 @@ fun BadgeGroup(
|
|||
shape: Shape = MaterialTheme.shapes.extraSmall,
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
Row(modifier = modifier.clip(shape)) {
|
||||
Row(
|
||||
modifier = modifier.clip(shape)
|
||||
// KMK -->
|
||||
.height(18.dp),
|
||||
// KMK <--
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
|
@ -99,3 +110,28 @@ fun Badge(
|
|||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
@Composable
|
||||
fun Badge(
|
||||
imageBitmap: ImageBitmap,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = MaterialTheme.colorScheme.secondary,
|
||||
tint: Color? = null,
|
||||
shape: Shape = RectangleShape,
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.clip(shape)
|
||||
.background(color),
|
||||
) {
|
||||
Image(
|
||||
bitmap = imageBitmap,
|
||||
colorFilter = tint?.let { ColorFilter.tint(it) },
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
|
|
|||
Loading…
Reference in a new issue