Skip to content

Commit f2e73ee

Browse files
committed
Fix namespace tags position/style, page preview, and description state
- Description opens collapsed by default (reverted from expanded) - EHentai namespace tags now render in mangaGenresTags ComposeView (same position) with same accent-colored chip style as regular genres, grouped by namespace with label chips - Page preview: remove empty chapters guard that caused silent failure when chapters weren't fetched yet — manga.url fallback handles it - Remove namespace tags from EHentaiDescription (moved to genre section)
1 parent 6282989 commit f2e73ee

4 files changed

Lines changed: 109 additions & 28 deletions

File tree

app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class MangaDetailsPresenter(
161161
var allHistory: List<History> = emptyList()
162162
private set
163163

164-
val headerItem: MangaHeaderItem by lazy { MangaHeaderItem(mangaId, true)}
164+
val headerItem: MangaHeaderItem by lazy { MangaHeaderItem(mangaId, false)}
165165
var tabletChapterHeaderItem: MangaHeaderItem? = null
166166
get() {
167167
when (view?.isTablet) {

app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt

Lines changed: 108 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
5757
import androidx.compose.foundation.layout.padding
5858
import androidx.compose.foundation.lazy.LazyRow
5959
import androidx.compose.foundation.lazy.items
60+
import androidx.compose.runtime.remember
6061
import androidx.compose.foundation.shape.CircleShape
6162
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
6263
import androidx.compose.material3.MaterialTheme
@@ -535,11 +536,6 @@ class MangaHeaderHolder(
535536
}
536537

537538
private fun setGenreTags(binding: MangaHeaderItemBinding, manga: Manga) {
538-
// EH/EXH sources show namespace-grouped tags in metadata section instead
539-
if (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) {
540-
binding.mangaGenresTags.isVisible = false
541-
return
542-
}
543539
val genres = if (manga.genre.isNullOrBlank()) emptyList() else (manga.getGenres() ?: emptyList())
544540
val delegate = adapter.delegate
545541
val context = binding.root.context
@@ -574,17 +570,29 @@ class MangaHeaderHolder(
574570
if (dark) 0.945f else 0.175f,
575571
),
576572
)
573+
val isEH = manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID
577574
binding.mangaGenresTags.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
578575
binding.mangaGenresTags.setContent {
579576
yokai.presentation.theme.YokaiTheme {
580-
GenreTagsSection(
581-
genres = genres,
582-
containerColor = ComposeColor(containerColorInt),
583-
labelColor = ComposeColor(labelColorInt),
584-
isExpanded = descriptionExpandedState.value,
585-
onTagClick = { genre -> delegate.searchFromMetadata(genre) },
586-
onTagLongClick = { genre -> delegate.copyContentToClipboard(genre, genre) },
587-
)
577+
if (isEH) {
578+
NamespaceGenreTagsSection(
579+
genres = genres,
580+
containerColor = ComposeColor(containerColorInt),
581+
labelColor = ComposeColor(labelColorInt),
582+
isExpanded = descriptionExpandedState.value,
583+
onTagClick = { genre -> delegate.searchFromMetadata(genre) },
584+
onTagLongClick = { genre -> delegate.copyContentToClipboard(genre, genre) },
585+
)
586+
} else {
587+
GenreTagsSection(
588+
genres = genres,
589+
containerColor = ComposeColor(containerColorInt),
590+
labelColor = ComposeColor(labelColorInt),
591+
isExpanded = descriptionExpandedState.value,
592+
onTagClick = { genre -> delegate.searchFromMetadata(genre) },
593+
onTagLongClick = { genre -> delegate.copyContentToClipboard(genre, genre) },
594+
)
595+
}
588596
}
589597
}
590598
}
@@ -817,3 +825,90 @@ private fun GenreTagsSection(
817825
}
818826
}
819827
}
828+
829+
@OptIn(ExperimentalFoundationApi::class)
830+
@Composable
831+
private fun NamespaceGenreTagsSection(
832+
genres: List<String>,
833+
containerColor: ComposeColor,
834+
labelColor: ComposeColor,
835+
isExpanded: Boolean,
836+
onTagClick: (String) -> Unit,
837+
onTagLongClick: (String) -> Unit,
838+
) {
839+
// Parse "namespace: name" format into grouped map
840+
val grouped = remember(genres) {
841+
val map = linkedMapOf<String, MutableList<String>>()
842+
genres.forEach { genre ->
843+
val colonIdx = genre.indexOf(": ")
844+
if (colonIdx > 0) {
845+
val ns = genre.substring(0, colonIdx)
846+
val name = genre.substring(colonIdx + 2)
847+
map.getOrPut(ns) { mutableListOf() }.add(name)
848+
} else {
849+
map.getOrPut("") { mutableListOf() }.add(genre)
850+
}
851+
}
852+
map.toMap()
853+
}
854+
855+
@Composable
856+
fun Chip(text: String, searchQuery: String, isLabel: Boolean = false) {
857+
CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) {
858+
Surface(
859+
modifier = Modifier
860+
.padding(vertical = 4.dp)
861+
.combinedClickable(
862+
onClick = { if (!isLabel) onTagClick(searchQuery) },
863+
onLongClick = { if (!isLabel) onTagLongClick(text) },
864+
),
865+
shape = CircleShape,
866+
color = if (isLabel) ComposeColor.Transparent else containerColor,
867+
border = if (isLabel) {
868+
BorderStroke(1.dp, labelColor.copy(alpha = 0.5f))
869+
} else {
870+
BorderStroke(1.dp, MaterialTheme.colorScheme.outline)
871+
},
872+
) {
873+
Text(
874+
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
875+
text = text,
876+
style = MaterialTheme.typography.bodySmall,
877+
color = labelColor,
878+
maxLines = 1,
879+
overflow = TextOverflow.Ellipsis,
880+
)
881+
}
882+
}
883+
}
884+
885+
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
886+
if (isExpanded) {
887+
grouped.forEach { (namespace, tags) ->
888+
FlowRow(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
889+
if (namespace.isNotEmpty()) {
890+
Chip(text = namespace, searchQuery = "", isLabel = true)
891+
}
892+
tags.forEach { tag ->
893+
val searchQuery = if (namespace.isNotEmpty()) "$namespace:\"$tag\"" else tag
894+
Chip(text = tag, searchQuery = searchQuery)
895+
}
896+
}
897+
}
898+
} else {
899+
LazyRow(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
900+
grouped.forEach { (namespace, tags) ->
901+
if (namespace.isNotEmpty()) {
902+
item(key = "ns_$namespace") {
903+
Chip(text = namespace, searchQuery = "", isLabel = true)
904+
}
905+
}
906+
items(tags, key = { "${namespace}_$it" }) { tag ->
907+
val searchQuery = if (namespace.isNotEmpty()) "$namespace:\"$tag\"" else tag
908+
Chip(text = tag, searchQuery = searchQuery)
909+
}
910+
}
911+
}
912+
}
913+
}
914+
}

app/src/main/java/exh/ui/metadata/adapters/EHentaiDescription.kt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ import exh.metadata.MetadataUtil
2828
import exh.metadata.metadata.EHentaiSearchMetadata
2929
import exh.ui.metadata.GenreChip
3030
import exh.ui.metadata.MetadataUIUtil
31-
import exh.ui.metadata.NamespaceTags
32-
import exh.ui.metadata.SearchMetadataChips
3331
import exh.ui.metadata.getRatingColor
3432
import java.text.DateFormat
3533
import java.text.NumberFormat
@@ -146,15 +144,6 @@ fun EHentaiDescription(
146144
}
147145
}
148146

149-
// Namespace-grouped tags
150-
val chips = SearchMetadataChips(meta, sourceId, null)
151-
if (chips != null) {
152-
NamespaceTags(
153-
tags = chips,
154-
isExpanded = isExpanded,
155-
onClick = onSearch,
156-
)
157-
}
158147
}
159148
}
160149

app/src/main/java/exh/ui/pagepreview/components/PagePreviewInlineSection.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ fun PagePreviewInlineSection(
7070
state = PreviewState.Unavailable; return@withContext
7171
}
7272
val chapters = getChapter.awaitAll(mangaId, filterScanlators = false)
73-
if (chapters.isEmpty()) {
74-
state = PreviewState.Unavailable; return@withContext
75-
}
7673
val source = sourceManager.getOrStub(manga.source)
7774
val previewSource = source.getMainSource<PagePreviewSource>() ?: run {
7875
state = PreviewState.Unavailable; return@withContext

0 commit comments

Comments
 (0)