feat(ui): Panorama cover

* support panorama cover

* bigger panorama cover size in GlobalSearchCardRow

* setting to enable/disable

* panorama cover for History items

* Keep panorama cover position in Library View centered for better visual

* fix: update ratio in Detail page if cover doesn't reload anew

* adjust ratio to switch to panorma

* panorama cover for Migration items

* center panorama cover & add dominant background color

* panorama cover for EditMangaInfo

* Fix size on GlobalSearchCardRow

* display mode for manual panorama cover

* Fix LibraryFlagsTest
This commit is contained in:
Cuong-Tran 2024-09-27 09:50:22 +07:00
parent 8d592c2541
commit 147a36a709
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
26 changed files with 571 additions and 103 deletions

View file

@ -64,6 +64,8 @@ class UiPreferences(
fun showHomeOnRelatedMangas() = preferenceStore.getBoolean("show_home_on_related_mangas", true)
fun readButtonPosition() = preferenceStore.getString("reading_button_position", FabPosition.End.toString())
fun usePanoramaCover() = preferenceStore.getBoolean("use_panorama_cover", false)
// KMK <--
fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", false)

View file

@ -182,6 +182,21 @@ fun BrowseSourceContent(
// KMK <--
)
}
// KMK -->
LibraryDisplayMode.ComfortableGridPanorama -> {
BrowseSourceComfortableGrid(
mangaList = mangaList,
columns = columns,
contentPadding = contentPadding,
onMangaClick = onMangaClick,
onMangaLongClick = onMangaLongClick,
// KMK -->
selection = selection,
usePanoramaCover = true,
// KMK <--
)
}
// KMK <--
LibraryDisplayMode.List -> {
BrowseSourceList(
mangaList = mangaList,

View file

@ -80,6 +80,20 @@ fun RelatedMangasContent(
selection = selection,
)
}
LibraryDisplayMode.ComfortableGridPanorama -> {
RelatedMangasComfortableGrid(
relatedMangas = relatedMangas,
getManga = getMangaState,
columns = columns,
contentPadding = contentPadding,
onMangaClick = onMangaClick,
onMangaLongClick = onMangaLongClick,
onKeywordClick = onKeywordClick,
onKeywordLongClick = onKeywordLongClick,
selection = selection,
usePanoramaCover = true,
)
}
LibraryDisplayMode.CompactGrid, LibraryDisplayMode.CoverOnlyGrid -> {
RelatedMangasCompactGrid(
relatedMangas = relatedMangas,

View file

@ -36,6 +36,7 @@ fun BrowseSourceComfortableGrid(
onMangaLongClick: (Manga) -> Unit,
// KMK -->
selection: List<Manga>,
usePanoramaCover: Boolean? = null,
// KMK <--
) {
LazyVerticalGrid(
@ -66,6 +67,7 @@ fun BrowseSourceComfortableGrid(
onLongClick = { onMangaLongClick(manga) },
// KMK -->
isSelected = selection.fastAny { selected -> selected.id == manga.id },
usePanoramaCover = usePanoramaCover,
// KMK <--
)
}
@ -88,6 +90,7 @@ internal fun BrowseSourceComfortableGridItem(
onLongClick: () -> Unit = onClick,
// KMK -->
isSelected: Boolean = false,
usePanoramaCover: Boolean?,
// KMK <--
) {
MangaComfortableGridItem(
@ -101,6 +104,8 @@ internal fun BrowseSourceComfortableGridItem(
),
// KMK -->
isSelected = isSelected,
panoramaCover = usePanoramaCover,
fitToPanoramaCover = true,
// KMK <--
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
coverBadgeStart = {

View file

@ -101,6 +101,7 @@ internal fun BrowseSourceCompactGridItem(
),
// KMK -->
isSelected = isSelected,
fitToPanoramaCover = true,
// KMK <--
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
coverBadgeStart = {

View file

@ -10,6 +10,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.components.DropdownMenu
@ -18,7 +19,11 @@ import eu.kanade.tachiyomi.ui.browse.bulkSelectionButton
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.i18n.MR
import tachiyomi.i18n.kmk.KMR
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun BrowseSourceSimpleToolbar(
@ -67,6 +72,16 @@ fun BrowseSourceSimpleToolbar(
selectingDisplayMode = false
onDisplayModeChange(LibraryDisplayMode.ComfortableGrid)
}
val usePanoramaCover by lazy { Injekt.get<UiPreferences>().usePanoramaCover() }
if (!usePanoramaCover.collectAsState().value) {
RadioMenuItem(
text = { Text(text = stringResource(KMR.strings.action_display_comfortable_grid_panorama)) },
isChecked = displayMode == LibraryDisplayMode.ComfortableGridPanorama,
) {
selectingDisplayMode = false
onDisplayModeChange(LibraryDisplayMode.ComfortableGridPanorama)
}
}
RadioMenuItem(
text = { Text(text = stringResource(MR.strings.action_display_grid)) },
isChecked = displayMode == LibraryDisplayMode.CompactGrid,

View file

@ -12,6 +12,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.components.AppBarTitle
@ -25,8 +26,12 @@ import exh.source.anyIs
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.i18n.MR
import tachiyomi.i18n.kmk.KMR
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import tachiyomi.source.local.LocalSource
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun BrowseSourceToolbar(
@ -138,6 +143,18 @@ fun BrowseSourceToolbar(
selectingDisplayMode = false
onDisplayModeChange(LibraryDisplayMode.ComfortableGrid)
}
// KMK -->
val usePanoramaCover by lazy { Injekt.get<UiPreferences>().usePanoramaCover() }
if (!usePanoramaCover.collectAsState().value) {
RadioMenuItem(
text = { Text(text = stringResource(KMR.strings.action_display_comfortable_grid_panorama)) },
isChecked = displayMode == LibraryDisplayMode.ComfortableGridPanorama,
) {
selectingDisplayMode = false
onDisplayModeChange(LibraryDisplayMode.ComfortableGridPanorama)
}
}
// KMK <--
RadioMenuItem(
text = { Text(text = stringResource(MR.strings.action_display_grid)) },
isChecked = displayMode == LibraryDisplayMode.CompactGrid,

View file

@ -12,17 +12,24 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastAny
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.library.components.CommonMangaItemDefaults
import eu.kanade.presentation.library.components.MangaComfortableGridItem
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaCover
import tachiyomi.domain.manga.model.asMangaCover
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun GlobalSearchCardRow(
@ -68,9 +75,20 @@ internal fun MangaItem(
onLongClick: () -> Unit,
// KMK -->
isSelected: Boolean = false,
panoramaCover: Boolean? = null,
// KMK <--
) {
Box(modifier = Modifier.width(96.dp)) {
// KMK -->
val usePanoramaCover = panoramaCover ?: Injekt.get<UiPreferences>().usePanoramaCover().collectAsState().value
val coverRatio = remember { mutableFloatStateOf(1f) }
// KMK <--
Box(
modifier = Modifier.width(
// KMK -->
if (usePanoramaCover && coverRatio.floatValue <= RatioSwitchToPanorama) 205.dp else 96.dp,
// KMK <--
),
) {
MangaComfortableGridItem(
title = title,
titleMaxLines = 3,
@ -80,6 +98,9 @@ internal fun MangaItem(
},
// KMK -->
isSelected = isSelected,
coverRatio = coverRatio,
panoramaCover = usePanoramaCover,
fitToPanoramaCover = true,
// KMK <--
coverAlpha = if (isFavorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
onClick = onClick,

View file

@ -13,8 +13,11 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -25,14 +28,21 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.manga.components.CoverPlaceholderColor
import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.asMangaCover
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.Badge
import tachiyomi.presentation.core.components.BadgeGroup
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun MigrationItem(
@ -41,7 +51,15 @@ fun MigrationItem(
sourcesString: String,
chapterInfo: MigratingManga.ChapterInfo,
onClick: () -> Unit,
// KMK -->
coverRatio: MutableFloatState = remember { mutableFloatStateOf(1f) },
// KMK <--
) {
// KMK -->
val usePanoramaCover by Injekt.get<UiPreferences>().usePanoramaCover().collectAsState()
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
val bgColor = manga.asMangaCover().dominantCoverColors?.first?.let { Color(it) }
// KMK <--
Column(
modifier
.widthIn(max = 150.dp)
@ -53,13 +71,41 @@ fun MigrationItem(
val context = LocalContext.current
Box(
Modifier.fillMaxWidth()
// KMK -->
.background(bgColor ?: CoverPlaceholderColor)
// KMK <--
.aspectRatio(MangaCover.Book.ratio),
) {
MangaCover.Book(
modifier = Modifier
.fillMaxWidth(),
data = manga,
)
// KMK -->
if (usePanoramaCover && coverIsWide) {
MangaCover.Panorama(
modifier = Modifier
// KMK -->
.align(Alignment.Center)
// KMK <--
.fillMaxWidth(),
data = manga,
// KMK -->
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
)
} else {
// KMK <--
MangaCover.Book(
modifier = Modifier
.fillMaxWidth(),
data = manga,
// KMK -->
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
)
}
Box(
modifier = Modifier
.clip(RoundedCornerShape(bottomStart = 4.dp, bottomEnd = 4.dp))

View file

@ -35,6 +35,7 @@ fun RelatedMangasComfortableGrid(
onKeywordClick: (String) -> Unit,
onKeywordLongClick: (String) -> Unit,
selection: List<Manga>,
usePanoramaCover: Boolean? = null,
) {
FastScrollLazyVerticalGrid(
columns = columns,
@ -89,6 +90,7 @@ fun RelatedMangasComfortableGrid(
onLongClick = { onMangaLongClick(manga) },
isSelected = selection.fastAny { selected -> selected.id == manga.id },
metadata = null,
usePanoramaCover = usePanoramaCover,
)
}
}

View file

@ -14,6 +14,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -23,7 +26,9 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.presentation.util.formatChapterNumber
import eu.kanade.tachiyomi.util.lang.toTimestampString
@ -31,6 +36,9 @@ import tachiyomi.domain.history.model.HistoryWithRelations
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
private val HistoryItemHeight = 96.dp
@ -41,6 +49,9 @@ fun HistoryItem(
onClickResume: () -> Unit,
onClickDelete: () -> Unit,
modifier: Modifier = Modifier,
// KMK -->
coverRatio: MutableFloatState = remember { mutableFloatStateOf(1f) },
// KMK <--
) {
Row(
modifier = modifier
@ -51,19 +62,42 @@ fun HistoryItem(
) {
// KMK -->
val mangaCover = history.coverData
val usePanoramaCover by Injekt.get<UiPreferences>().usePanoramaCover().collectAsState()
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
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,
size = MangaCover.Size.Medium,
if (usePanoramaCover && coverIsWide) {
MangaCover.Panorama(
modifier = Modifier.fillMaxHeight(),
data = mangaCover,
onClick = onClickCover,
// KMK -->
bgColor = bgColor,
tint = onBgColor,
size = MangaCover.Size.Medium,
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
)
} else {
// KMK <--
)
MangaCover.Book(
modifier = Modifier.fillMaxHeight(),
data = mangaCover,
onClick = onClickCover,
// KMK -->
bgColor = bgColor,
tint = onBgColor,
size = MangaCover.Size.Medium,
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
)
}
Column(
modifier = Modifier
.weight(1f)

View file

@ -17,6 +17,7 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.util.fastForEach
import dev.icerock.moko.resources.StringResource
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.components.TabbedDialog
import eu.kanade.presentation.components.TabbedDialogPaddings
import eu.kanade.tachiyomi.R
@ -45,6 +46,8 @@ import tachiyomi.presentation.core.components.SortItem
import tachiyomi.presentation.core.components.TriStateItem
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun LibrarySettingsDialog(
@ -255,8 +258,11 @@ private fun ColumnScope.SortPage(
private val displayModes = listOf(
MR.strings.action_display_grid to LibraryDisplayMode.CompactGrid,
MR.strings.action_display_comfortable_grid to LibraryDisplayMode.ComfortableGrid,
MR.strings.action_display_cover_only_grid to LibraryDisplayMode.CoverOnlyGrid,
MR.strings.action_display_list to LibraryDisplayMode.List,
MR.strings.action_display_cover_only_grid to LibraryDisplayMode.CoverOnlyGrid,
// KMK -->
KMR.strings.action_display_comfortable_grid_panorama to LibraryDisplayMode.ComfortableGridPanorama,
// KMK <--
)
@Suppress("UnusedReceiverParameter")
@ -265,14 +271,22 @@ private fun ColumnScope.DisplayPage(
screenModel: LibrarySettingsScreenModel,
) {
val displayMode by screenModel.libraryPreferences.displayMode().collectAsState()
// KMK -->
val usePanoramaCover by lazy { Injekt.get<UiPreferences>().usePanoramaCover() }
// KMK <--
SettingsChipRow(MR.strings.action_display_mode) {
displayModes.map { (titleRes, mode) ->
FilterChip(
selected = displayMode == mode,
onClick = { screenModel.setDisplayMode(mode) },
label = { Text(stringResource(titleRes)) },
)
}
displayModes
.filterNot {
it.second == LibraryDisplayMode.ComfortableGridPanorama &&
usePanoramaCover.collectAsState().value
}
.map { (titleRes, mode) ->
FilterChip(
selected = displayMode == mode,
onClick = { screenModel.setDisplayMode(mode) },
label = { Text(stringResource(titleRes)) },
)
}
}
if (displayMode != LibraryDisplayMode.List) {

View file

@ -25,6 +25,10 @@ import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -32,18 +36,24 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.manga.components.MangaCoverHide
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
import exh.debug.DebugToggles
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.BadgeGroup
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import tachiyomi.presentation.core.util.selectedBackground
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import tachiyomi.domain.manga.model.MangaCover as MangaCoverModel
object CommonMangaItemDefaults {
@ -82,9 +92,13 @@ fun MangaCompactGridItem(
coverBadgeEnd: @Composable (RowScope.() -> Unit)? = null,
// KMK -->
libraryColored: Boolean = true,
coverRatio: MutableFloatState = remember { mutableFloatStateOf(1f) },
fitToPanoramaCover: Boolean = false,
// KMK <--
) {
// KMK -->
val usePanoramaCover by Injekt.get<UiPreferences>().usePanoramaCover().collectAsState()
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
val bgColor = coverData.dominantCoverColors?.first?.let { Color(it) }.takeIf { libraryColored }
val onBgColor = coverData.dominantCoverColors?.second.takeIf { libraryColored }
// KMK <--
@ -104,22 +118,58 @@ fun MangaCompactGridItem(
tint = onBgColor,
)
} else {
// KMK <--
MangaCover.Book(
modifier = Modifier
if (fitToPanoramaCover && usePanoramaCover && coverIsWide) {
MangaCover.Panorama(
modifier = Modifier
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
// KMK <--
.fillMaxWidth(),
data = coverData,
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
tint = onBgColor,
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
.fillMaxWidth(),
data = coverData,
// KMK -->
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
tint = onBgColor,
)
} else {
// KMK <--
)
MangaCover.Book(
modifier = Modifier
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
// KMK <--
.fillMaxWidth(),
data = coverData,
// KMK -->
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
tint = onBgColor,
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
scale = if (usePanoramaCover && coverIsWide) {
ContentScale.Fit
} else {
ContentScale.Crop
},
// KMK <--
)
}
}
},
// KMK -->
ratio = if (fitToPanoramaCover && usePanoramaCover && coverIsWide) {
MangaCover.Panorama.ratio
} else {
MangaCover.Book.ratio
},
// KMK <--
badgesStart = coverBadgeStart,
badgesEnd = coverBadgeEnd,
content = {
@ -208,14 +258,19 @@ fun MangaComfortableGridItem(
isSelected: Boolean = false,
titleMaxLines: Int = 2,
coverAlpha: Float = 1f,
coverBadgeStart: (@Composable RowScope.() -> Unit)? = null,
coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null,
coverBadgeStart: @Composable (RowScope.() -> Unit)? = null,
coverBadgeEnd: @Composable (RowScope.() -> Unit)? = null,
onClickContinueReading: (() -> Unit)? = null,
// KMK -->
libraryColored: Boolean = true,
coverRatio: MutableFloatState = remember { mutableFloatStateOf(1f) },
panoramaCover: Boolean?,
fitToPanoramaCover: Boolean = false,
// KMK <--
) {
// KMK -->
val usePanoramaCover = panoramaCover ?: Injekt.get<UiPreferences>().usePanoramaCover().collectAsState().value
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
val bgColor = coverData.dominantCoverColors?.first?.let { Color(it) }.takeIf { libraryColored }
val onBgColor = coverData.dominantCoverColors?.second.takeIf { libraryColored }
// KMK <--
@ -236,22 +291,58 @@ fun MangaComfortableGridItem(
tint = onBgColor,
)
} else {
// KMK <--
MangaCover.Book(
modifier = Modifier
if (fitToPanoramaCover && usePanoramaCover && coverIsWide) {
MangaCover.Panorama(
modifier = Modifier
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
// KMK <--
.fillMaxWidth(),
data = coverData,
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
tint = onBgColor,
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
.fillMaxWidth(),
data = coverData,
// KMK -->
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
tint = onBgColor,
)
} else {
// KMK <--
)
MangaCover.Book(
modifier = Modifier
// KMK -->
// .alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha)
// KMK <--
.fillMaxWidth(),
data = coverData,
// KMK -->
alpha = if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha,
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { isSelected }),
tint = onBgColor,
onCoverLoaded = { _, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
scale = if (usePanoramaCover && coverIsWide) {
ContentScale.Fit
} else {
ContentScale.Crop
},
// KMK <--
)
}
}
},
// KMK -->
ratio = if (fitToPanoramaCover && usePanoramaCover && coverIsWide) {
MangaCover.Panorama.ratio
} else {
MangaCover.Book.ratio
},
// KMK <--
badgesStart = coverBadgeStart,
badgesEnd = coverBadgeEnd,
content = {
@ -285,6 +376,9 @@ fun MangaComfortableGridItem(
private fun MangaGridCover(
modifier: Modifier = Modifier,
cover: @Composable BoxScope.() -> Unit = {},
// KMK -->
ratio: Float = MangaCover.Book.ratio,
// KMK <--
badgesStart: (@Composable RowScope.() -> Unit)? = null,
badgesEnd: (@Composable RowScope.() -> Unit)? = null,
content: @Composable (BoxScope.() -> Unit)? = null,
@ -292,7 +386,7 @@ private fun MangaGridCover(
Box(
modifier = modifier
.fillMaxWidth()
.aspectRatio(MangaCover.Book.ratio),
.aspectRatio(ratio),
) {
cover()
content?.invoke(this)

View file

@ -21,6 +21,9 @@ internal fun LibraryComfortableGrid(
onClickContinueReading: ((LibraryManga) -> Unit)?,
searchQuery: String?,
onGlobalSearchClicked: () -> Unit,
// KMK -->
usePanoramaCover: Boolean? = null,
// KMK <--
) {
LazyLibraryGrid(
modifier = Modifier.fillMaxSize(),
@ -67,6 +70,9 @@ internal fun LibraryComfortableGrid(
} else {
null
},
// KMK -->
panoramaCover = usePanoramaCover,
// KMK <--
)
}
}

View file

@ -112,6 +112,22 @@ fun LibraryPager(
onGlobalSearchClicked = onGlobalSearchClicked,
)
}
// KMK -->
LibraryDisplayMode.ComfortableGridPanorama -> {
LibraryComfortableGrid(
items = library,
columns = columns,
contentPadding = contentPadding,
selection = selectedManga,
onClick = onClickManga,
onLongClick = onLongClickManga,
onClickContinueReading = onClickContinueReading,
searchQuery = searchQuery,
onGlobalSearchClicked = onGlobalSearchClicked,
usePanoramaCover = true,
)
}
// KMK <--
}
}
}

View file

@ -36,6 +36,7 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
@ -207,6 +208,7 @@ fun MangaScreen(
librarySearch: (query: String) -> Unit,
onSourceClick: () -> Unit,
onCoverLoaded: (MangaCover) -> Unit,
coverRatio: MutableFloatState,
onPaletteScreenClick: () -> Unit,
hazeState: HazeState,
// KMK <--
@ -271,6 +273,7 @@ fun MangaScreen(
librarySearch = librarySearch,
onSourceClick = onSourceClick,
onCoverLoaded = onCoverLoaded,
coverRatio = coverRatio,
onPaletteScreenClick = onPaletteScreenClick,
hazeState = hazeState,
// KMK <--
@ -328,6 +331,7 @@ fun MangaScreen(
librarySearch = librarySearch,
onSourceClick = onSourceClick,
onCoverLoaded = onCoverLoaded,
coverRatio = coverRatio,
onPaletteScreenClick = onPaletteScreenClick,
hazeState = hazeState,
// KMK <--
@ -402,6 +406,7 @@ private fun MangaScreenSmallImpl(
librarySearch: (query: String) -> Unit,
onSourceClick: () -> Unit,
onCoverLoaded: (MangaCover) -> Unit,
coverRatio: MutableFloatState,
onPaletteScreenClick: () -> Unit,
hazeState: HazeState,
// KMK <--
@ -620,6 +625,7 @@ private fun MangaScreenSmallImpl(
librarySearch = librarySearch,
onSourceClick = onSourceClick,
onCoverLoaded = onCoverLoaded,
coverRatio = coverRatio,
// KMK <--
)
}
@ -860,6 +866,7 @@ private fun MangaScreenLargeImpl(
librarySearch: (query: String) -> Unit,
onSourceClick: () -> Unit,
onCoverLoaded: (MangaCover) -> Unit,
coverRatio: MutableFloatState,
onPaletteScreenClick: () -> Unit,
hazeState: HazeState,
// KMK <--
@ -1070,6 +1077,7 @@ private fun MangaScreenLargeImpl(
librarySearch = librarySearch,
onSourceClick = onSourceClick,
onCoverLoaded = onCoverLoaded,
coverRatio = coverRatio,
// KMK <--
)
MangaActionRow(

View file

@ -26,6 +26,7 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImagePainter
import coil3.compose.SubcomposeAsyncImage
import eu.kanade.tachiyomi.R
import tachiyomi.domain.manga.model.Manga
@ -35,6 +36,10 @@ import tachiyomi.domain.manga.model.MangaCover as DomainMangaCover
enum class MangaCover(val ratio: Float) {
Square(1f / 1f),
Book(2f / 3f),
// KMK -->
Panorama(3f / 2f),
// KMK <--
;
enum class Size {
@ -54,9 +59,10 @@ enum class MangaCover(val ratio: Float) {
alpha: Float = 1f,
bgColor: Color? = null,
@ColorInt tint: Int? = null,
/** Perform action when cover loaded, specifically generating color map */
onCoverLoaded: ((DomainMangaCover) -> Unit)? = null,
/** Perform action when cover loaded, specifically generating color map. If the cover doesn't update, it won't be called */
onCoverLoaded: ((DomainMangaCover, result: AsyncImagePainter.State.Success) -> Unit)? = null,
size: Size = Size.Normal,
scale: ContentScale = ContentScale.Crop,
// KMK <--
) {
// KMK -->
@ -128,19 +134,19 @@ enum class MangaCover(val ratio: Float) {
)
}
},
onSuccess = {
onSuccess = { result ->
succeed = true
if (onCoverLoaded != null) {
when (data) {
is Manga -> onCoverLoaded(data.asMangaCover())
is DomainMangaCover -> onCoverLoaded(data)
is Manga -> onCoverLoaded(data.asMangaCover(), result)
is DomainMangaCover -> onCoverLoaded(data, result)
}
}
},
// KMK <--
contentDescription = contentDescription,
modifier = modifierColored,
contentScale = ContentScale.Crop,
contentScale = scale,
)
}
}
@ -194,5 +200,7 @@ enum class MangaCoverHide(private val ratio: Float) {
}
}
internal val RatioSwitchToPanorama = 0.75f
internal val CoverPlaceholderColor = Color(0x1F888888)
internal val CoverPlaceholderOnBgColor = Color(0x8F888888)

View file

@ -51,6 +51,7 @@ import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
@ -96,6 +97,7 @@ import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.pluralStringResource
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.clickableNoIndication
import tachiyomi.presentation.core.util.collectAsState
import tachiyomi.presentation.core.util.secondaryItemAlpha
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -120,8 +122,12 @@ fun MangaInfoBox(
librarySearch: (query: String) -> Unit,
onSourceClick: () -> Unit,
onCoverLoaded: (DomainMangaCover) -> Unit,
coverRatio: MutableFloatState,
// KMK <--
) {
// KMK -->
val usePanoramaCover by Injekt.get<UiPreferences>().usePanoramaCover().collectAsState()
// KMK <--
Box(modifier = modifier) {
// Backdrop
val backdropGradientColors = listOf(
@ -135,6 +141,12 @@ fun MangaInfoBox(
.build(),
contentDescription = null,
contentScale = ContentScale.Crop,
// KMK -->
onSuccess = { result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
},
// KMK <--
modifier = Modifier
.matchParentSize()
.drawWithContent {
@ -170,6 +182,8 @@ fun MangaInfoBox(
librarySearch = librarySearch,
onSourceClick = onSourceClick,
onCoverLoaded = onCoverLoaded,
coverRatio = coverRatio,
usePanoramaCover = usePanoramaCover,
// KMK <--
)
} else {
@ -184,6 +198,8 @@ fun MangaInfoBox(
librarySearch = librarySearch,
onSourceClick = onSourceClick,
onCoverLoaded = onCoverLoaded,
coverRatio = coverRatio,
usePanoramaCover = usePanoramaCover,
// KMK <--
)
}
@ -458,6 +474,8 @@ private fun MangaAndSourceTitlesLarge(
librarySearch: (query: String) -> Unit,
onSourceClick: () -> Unit,
onCoverLoaded: (DomainMangaCover) -> Unit,
coverRatio: MutableFloatState,
usePanoramaCover: Boolean = false,
// KMK <--
) {
Column(
@ -466,18 +484,43 @@ private fun MangaAndSourceTitlesLarge(
.padding(start = 16.dp, top = appBarPadding + 16.dp, end = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
MangaCover.Book(
modifier = Modifier.fillMaxWidth(0.65f),
data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover -> onCoverLoaded(mangaCover) },
// KMK -->
if (usePanoramaCover && coverRatio.floatValue <= RatioSwitchToPanorama) {
MangaCover.Panorama(
modifier = Modifier.fillMaxWidth(0.65f),
data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
onCoverLoaded(mangaCover)
},
// KMK <--
)
} else {
// KMK <--
)
MangaCover.Book(
modifier = Modifier.fillMaxWidth(0.65f),
data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
onCoverLoaded(mangaCover)
},
// KMK <--
)
}
Spacer(modifier = Modifier.height(16.dp))
MangaContentInfo(
title = manga.title,
@ -508,6 +551,8 @@ private fun MangaAndSourceTitlesSmall(
librarySearch: (query: String) -> Unit,
onSourceClick: () -> Unit,
onCoverLoaded: (DomainMangaCover) -> Unit,
coverRatio: MutableFloatState,
usePanoramaCover: Boolean = false,
// KMK <--
) {
Row(
@ -517,20 +562,51 @@ private fun MangaAndSourceTitlesSmall(
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
MangaCover.Book(
modifier = Modifier
.sizeIn(maxWidth = 100.dp)
.align(Alignment.Top),
data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover -> onCoverLoaded(mangaCover) },
// KMK -->
if (usePanoramaCover && coverRatio.floatValue <= RatioSwitchToPanorama) {
MangaCover.Panorama(
modifier = Modifier
.sizeIn(maxHeight = 100.dp)
// KMK -->
.align(Alignment.CenterVertically),
// KMK <--
data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
onCoverLoaded(mangaCover)
},
// KMK <--
)
} else {
// KMK <--
)
MangaCover.Book(
modifier = Modifier
.sizeIn(maxWidth = 100.dp)
// KMK -->
.align(Alignment.CenterVertically),
// KMK <--
data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick,
// KMK -->
onCoverLoaded = { mangaCover, result ->
val image = result.result.image
coverRatio.floatValue = image.height.toFloat() / image.width
onCoverLoaded(mangaCover)
},
// KMK <--
)
}
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
) {

View file

@ -272,6 +272,13 @@ object SettingsAppearanceScreen : SearchableSettings {
return Preference.PreferenceGroup(
stringResource(SYMR.strings.pref_category_fork),
preferenceItems = persistentListOf(
// KMK -->
Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.usePanoramaCover(),
title = stringResource(KMR.strings.pref_use_panorama_cover),
subtitle = stringResource(KMR.strings.pref_use_panorama_cover_summary),
),
// KMK <--
Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.expandFilters(),
title = stringResource(SYMR.strings.toggle_expand_search_filters),

View file

@ -160,5 +160,5 @@ object MangaCoverMetadata {
preferences.coverColors().set(mapColorCopy.map { "${it.key}|${it.value.first}|${it.value.second}" }.toSet())
}
const val SUB_SAMPLE = 4
private const val SUB_SAMPLE = 4
}

View file

@ -21,6 +21,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -37,6 +38,7 @@ import coil3.transform.RoundedCornersTransformation
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.EditMangaDialogBinding
import eu.kanade.tachiyomi.source.model.SManga
@ -62,6 +64,9 @@ import tachiyomi.source.local.isLocal
@Composable
fun EditMangaDialog(
manga: Manga,
// KMK -->
coverRatio: MutableFloatState,
// KMK <--
onDismissRequest: () -> Unit,
onPositiveClick: (
title: String?,
@ -145,6 +150,7 @@ fun EditMangaDialog(
scope,
// KMK -->
colors,
coverRatio = coverRatio,
// KMK <--
)
}
@ -178,9 +184,16 @@ private fun onViewCreated(
scope: CoroutineScope,
// KMK -->
colors: EditMangaDialogColors,
coverRatio: MutableFloatState,
// KMK <--
) {
loadCover(manga, binding)
loadCover(
manga,
binding,
// KMK -->
coverRatio,
// KMK <--
)
// KMK -->
// val statusAdapter: ArrayAdapter<String> = ArrayAdapter(
@ -344,9 +357,25 @@ private fun resetTags(
}
}
private fun loadCover(manga: Manga, binding: EditMangaDialogBinding) {
binding.mangaCover.load(manga) {
transformations(RoundedCornersTransformation(4.dpToPx.toFloat()))
private fun loadCover(
manga: Manga,
binding: EditMangaDialogBinding,
// KMK -->
coverRatio: MutableFloatState,
// KMK <--
) {
// KMK -->
if (coverRatio.floatValue <= RatioSwitchToPanorama) {
binding.mangaCover.visibility = View.GONE
binding.mangaCoverPanorama.visibility = View.VISIBLE
binding.mangaCoverPanorama.load(manga) {
transformations(RoundedCornersTransformation(4.dpToPx.toFloat()))
}
} else {
// KMK <--
binding.mangaCover.load(manga) {
transformations(RoundedCornersTransformation(4.dpToPx.toFloat()))
}
}
}

View file

@ -14,6 +14,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@ -262,6 +263,7 @@ class MangaScreen(
// SY <--
// KMK -->
val coverRatio = remember { mutableFloatStateOf(1f) }
val hazeState = remember { HazeState() }
// KMK <--
@ -402,6 +404,7 @@ class MangaScreen(
onCoverLoaded = {
if (screenModel.themeCoverBased || successState.manga.favorite) screenModel.setPaletteColor(it)
},
coverRatio = coverRatio,
onPaletteScreenClick = { navigator.push(PaletteScreen(successState.seedColor?.toArgb())) },
hazeState = hazeState,
// KMK <--
@ -537,6 +540,9 @@ class MangaScreen(
is MangaScreenModel.Dialog.EditMangaInfo -> {
EditMangaDialog(
manga = dialog.manga,
// KMK -->
coverRatio = coverRatio,
// KMK <--
onDismissRequest = screenModel::dismissDialog,
onPositiveClick = screenModel::updateMangaInfo,
)

View file

@ -20,6 +20,17 @@
android:background="@drawable/rounded_rectangle"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
<!-- KMK -> -->
<ImageView
android:id="@+id/manga_cover_panorama"
android:layout_width="150dp"
android:layout_height="100dp"
android:visibility="gone"
android:adjustViewBounds="true"
android:background="@drawable/rounded_rectangle"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
<!-- KMK <- -->
</FrameLayout>
<LinearLayout
@ -134,25 +145,32 @@
android:layout_marginEnd="16dp"
android:layout_marginBottom="12dp" />
<Button
android:id="@+id/reset_tags"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="@string/reset_tags"
android:textAllCaps="false" />
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/reset_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="@string/reset_info"
android:textAllCaps="false" />
<Button
android:id="@+id/reset_tags"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/reset_tags"
android:textAllCaps="false" />
<Button
android:id="@+id/reset_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="@string/reset_info"
android:textAllCaps="false" />
</LinearLayout>
<View
android:layout_width="match_parent"

View file

@ -4,6 +4,11 @@ sealed interface LibraryDisplayMode {
data object CompactGrid : LibraryDisplayMode
data object ComfortableGrid : LibraryDisplayMode
// KMK -->
data object ComfortableGridPanorama : LibraryDisplayMode
// KMK <--
data object List : LibraryDisplayMode
data object CoverOnlyGrid : LibraryDisplayMode
@ -18,12 +23,15 @@ sealed interface LibraryDisplayMode {
}
companion object {
val values by lazy { setOf(CompactGrid, ComfortableGrid, List, CoverOnlyGrid) }
val values by lazy { setOf(CompactGrid, ComfortableGrid, ComfortableGridPanorama, List, CoverOnlyGrid) }
val default = CompactGrid
fun deserialize(serialized: String): LibraryDisplayMode {
return when (serialized) {
"COMFORTABLE_GRID" -> ComfortableGrid
// KMK -->
"COMFORTABLE_GRID_PANORAMA" -> ComfortableGridPanorama
// KMK <--
"COMPACT_GRID" -> CompactGrid
"COVER_ONLY_GRID" -> CoverOnlyGrid
"LIST" -> List
@ -35,6 +43,9 @@ sealed interface LibraryDisplayMode {
fun serialize(): String {
return when (this) {
ComfortableGrid -> "COMFORTABLE_GRID"
// KMK -->
ComfortableGridPanorama -> "COMFORTABLE_GRID_PANORAMA"
// KMK <--
CompactGrid -> "COMPACT_GRID"
CoverOnlyGrid -> "COVER_ONLY_GRID"
List -> "LIST"

View file

@ -11,7 +11,7 @@ class LibraryFlagsTest {
@Test
fun `Check the amount of flags`() {
LibraryDisplayMode.values.size shouldBe 4
LibraryDisplayMode.values.size shouldBe 5
LibrarySort.types.size shouldBe 10
LibrarySort.directions.size shouldBe 2
}

View file

@ -30,6 +30,9 @@
<string name="pref_theme_cover_based_style_monochrome">Monochrome</string>
<string name="pref_theme_cover_based_style_fidelity">Fidelity</string>
<string name="pref_theme_cover_based_style_content">Content</string>
<string name="pref_use_panorama_cover">Panorama Cover</string>
<string name="pref_use_panorama_cover_summary">Show cover in landscape mode if it\'s a wide image</string>
<string name="action_display_comfortable_grid_panorama">Panorama comfortable grid</string>
<string name="pref_expand_related_mangas">Expand Suggestions</string>
<string name="pref_expand_related_mangas_summary">If turned off, Suggestions won\'t automatically load &amp; show expanded</string>
<string name="put_related_mangas_in_overflow">Suggestions in overflow</string>