瀏覽代碼

Move library page EmptyScreens into list/grids

It does look awkward due to the lack of filled height within those list/grids though.

Fixes #8720
Fixes #8721
arkon 2 年之前
父節點
當前提交
376bbeb724

+ 35 - 63
app/src/main/java/eu/kanade/presentation/components/EmptyScreen.kt

@@ -22,12 +22,9 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastFirstOrNull
 import eu.kanade.presentation.theme.TachiyomiTheme
 import eu.kanade.presentation.util.ThemePreviews
 import eu.kanade.presentation.util.secondaryItemAlpha
@@ -54,68 +51,45 @@ fun EmptyScreen(
     actions: List<EmptyScreenAction>? = null,
 ) {
     val face = remember { getRandomErrorFace() }
-    Layout(
-        content = {
-            Column(
+    Column(
+        modifier = modifier
+            .fillMaxSize()
+            .padding(horizontal = 24.dp),
+        horizontalAlignment = Alignment.CenterHorizontally,
+        verticalArrangement = Arrangement.Center,
+    ) {
+        Text(
+            text = face,
+            modifier = Modifier.secondaryItemAlpha(),
+            style = MaterialTheme.typography.displayMedium,
+        )
+
+        Text(
+            text = message,
+            modifier = Modifier.paddingFromBaseline(top = 24.dp).secondaryItemAlpha(),
+            style = MaterialTheme.typography.bodyMedium,
+            textAlign = TextAlign.Center,
+        )
+
+        if (!actions.isNullOrEmpty()) {
+            Row(
                 modifier = Modifier
-                    .layoutId("face")
-                    .padding(horizontal = 24.dp),
-                horizontalAlignment = Alignment.CenterHorizontally,
+                    .padding(
+                        top = 24.dp,
+                        start = 24.dp,
+                        end = 24.dp,
+                    ),
+                horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
             ) {
-                Text(
-                    text = face,
-                    modifier = Modifier.secondaryItemAlpha(),
-                    style = MaterialTheme.typography.displayMedium,
-                )
-
-                Text(
-                    text = message,
-                    modifier = Modifier.paddingFromBaseline(top = 24.dp).secondaryItemAlpha(),
-                    style = MaterialTheme.typography.bodyMedium,
-                    textAlign = TextAlign.Center,
-                )
-            }
-            if (!actions.isNullOrEmpty()) {
-                Row(
-                    modifier = Modifier
-                        .layoutId("actions")
-                        .padding(
-                            top = 24.dp,
-                            start = horizontalPadding,
-                            end = horizontalPadding,
-                        ),
-                    horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
-                ) {
-                    actions.forEach {
-                        ActionButton(
-                            modifier = Modifier.weight(1f),
-                            title = stringResource(it.stringResId),
-                            icon = it.icon,
-                            onClick = it.onClick,
-                        )
-                    }
+                actions.forEach {
+                    ActionButton(
+                        modifier = Modifier.weight(1f),
+                        title = stringResource(it.stringResId),
+                        icon = it.icon,
+                        onClick = it.onClick,
+                    )
                 }
             }
-        },
-        modifier = modifier.fillMaxSize(),
-    ) { measurables, constraints ->
-        val looseConstraints = constraints.copy(minWidth = 0, minHeight = 0)
-        val facePlaceable = measurables.fastFirstOrNull { it.layoutId == "face" }!!
-            .measure(looseConstraints)
-        val actionsPlaceable = measurables.fastFirstOrNull { it.layoutId == "actions" }
-            ?.measure(looseConstraints)
-
-        layout(constraints.maxWidth, constraints.maxHeight) {
-            val faceY = (constraints.maxHeight - facePlaceable.height) / 2
-            facePlaceable.placeRelative(
-                x = (constraints.maxWidth - facePlaceable.width) / 2,
-                y = faceY,
-            )
-
-            actionsPlaceable?.placeRelative(
-                x = (constraints.maxWidth - actionsPlaceable.width) / 2,
-                y = faceY + facePlaceable.height,
-            )
         }
     }
 }
@@ -187,8 +161,6 @@ data class EmptyScreenAction(
     val onClick: () -> Unit,
 )
 
-private val horizontalPadding = 24.dp
-
 private val ERROR_FACES = listOf(
     "(・o・;)",
     "Σ(ಠ_ಠ)",

+ 44 - 33
app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt

@@ -2,6 +2,7 @@ package eu.kanade.presentation.library.components
 
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.lazy.grid.GridItemSpan
 import androidx.compose.foundation.lazy.grid.items
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -22,6 +23,7 @@ fun LibraryComfortableGrid(
     onClickContinueReading: ((LibraryManga) -> Unit)?,
     searchQuery: String?,
     onGlobalSearchClicked: () -> Unit,
+    hasActiveFilters: Boolean,
 ) {
     LazyLibraryGrid(
         modifier = Modifier.fillMaxSize(),
@@ -30,39 +32,48 @@ fun LibraryComfortableGrid(
     ) {
         globalSearchItem(searchQuery, onGlobalSearchClicked)
 
-        items(
-            items = items,
-            contentType = { "library_comfortable_grid_item" },
-        ) { libraryItem ->
-            val manga = libraryItem.libraryManga.manga
-            MangaComfortableGridItem(
-                isSelected = selection.fastAny { it.id == libraryItem.libraryManga.id },
-                title = manga.title,
-                coverData = MangaCover(
-                    mangaId = manga.id,
-                    sourceId = manga.source,
-                    isMangaFavorite = manga.favorite,
-                    url = manga.thumbnailUrl,
-                    lastModified = manga.coverLastModified,
-                ),
-                coverBadgeStart = {
-                    DownloadsBadge(count = libraryItem.downloadCount.toInt())
-                    UnreadBadge(count = libraryItem.unreadCount.toInt())
-                },
-                coverBadgeEnd = {
-                    LanguageBadge(
-                        isLocal = libraryItem.isLocal,
-                        sourceLanguage = libraryItem.sourceLanguage,
-                    )
-                },
-                onLongClick = { onLongClick(libraryItem.libraryManga) },
-                onClick = { onClick(libraryItem.libraryManga) },
-                onClickContinueReading = if (onClickContinueReading != null) {
-                    { onClickContinueReading(libraryItem.libraryManga) }
-                } else {
-                    null
-                },
-            )
+        if (items.isEmpty()) {
+            item(
+                span = { GridItemSpan(maxLineSpan) },
+                contentType = "library_comfortable_grid_empty",
+            ) {
+                LibraryPagerEmptyScreen(searchQuery, hasActiveFilters, contentPadding)
+            }
+        } else {
+            items(
+                items = items,
+                contentType = { "library_comfortable_grid_item" },
+            ) { libraryItem ->
+                val manga = libraryItem.libraryManga.manga
+                MangaComfortableGridItem(
+                    isSelected = selection.fastAny { it.id == libraryItem.libraryManga.id },
+                    title = manga.title,
+                    coverData = MangaCover(
+                        mangaId = manga.id,
+                        sourceId = manga.source,
+                        isMangaFavorite = manga.favorite,
+                        url = manga.thumbnailUrl,
+                        lastModified = manga.coverLastModified,
+                    ),
+                    coverBadgeStart = {
+                        DownloadsBadge(count = libraryItem.downloadCount.toInt())
+                        UnreadBadge(count = libraryItem.unreadCount.toInt())
+                    },
+                    coverBadgeEnd = {
+                        LanguageBadge(
+                            isLocal = libraryItem.isLocal,
+                            sourceLanguage = libraryItem.sourceLanguage,
+                        )
+                    },
+                    onLongClick = { onLongClick(libraryItem.libraryManga) },
+                    onClick = { onClick(libraryItem.libraryManga) },
+                    onClickContinueReading = if (onClickContinueReading != null) {
+                        { onClickContinueReading(libraryItem.libraryManga) }
+                    } else {
+                        null
+                    },
+                )
+            }
         }
     }
 }

+ 44 - 33
app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt

@@ -2,6 +2,7 @@ package eu.kanade.presentation.library.components
 
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.lazy.grid.GridItemSpan
 import androidx.compose.foundation.lazy.grid.items
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -23,6 +24,7 @@ fun LibraryCompactGrid(
     onClickContinueReading: ((LibraryManga) -> Unit)?,
     searchQuery: String?,
     onGlobalSearchClicked: () -> Unit,
+    hasActiveFilters: Boolean,
 ) {
     LazyLibraryGrid(
         modifier = Modifier.fillMaxSize(),
@@ -31,39 +33,48 @@ fun LibraryCompactGrid(
     ) {
         globalSearchItem(searchQuery, onGlobalSearchClicked)
 
-        items(
-            items = items,
-            contentType = { "library_compact_grid_item" },
-        ) { libraryItem ->
-            val manga = libraryItem.libraryManga.manga
-            MangaCompactGridItem(
-                isSelected = selection.fastAny { it.id == libraryItem.libraryManga.id },
-                title = manga.title.takeIf { showTitle },
-                coverData = MangaCover(
-                    mangaId = manga.id,
-                    sourceId = manga.source,
-                    isMangaFavorite = manga.favorite,
-                    url = manga.thumbnailUrl,
-                    lastModified = manga.coverLastModified,
-                ),
-                coverBadgeStart = {
-                    DownloadsBadge(count = libraryItem.downloadCount.toInt())
-                    UnreadBadge(count = libraryItem.unreadCount.toInt())
-                },
-                coverBadgeEnd = {
-                    LanguageBadge(
-                        isLocal = libraryItem.isLocal,
-                        sourceLanguage = libraryItem.sourceLanguage,
-                    )
-                },
-                onLongClick = { onLongClick(libraryItem.libraryManga) },
-                onClick = { onClick(libraryItem.libraryManga) },
-                onClickContinueReading = if (onClickContinueReading != null) {
-                    { onClickContinueReading(libraryItem.libraryManga) }
-                } else {
-                    null
-                },
-            )
+        if (items.isEmpty()) {
+            item(
+                span = { GridItemSpan(maxLineSpan) },
+                contentType = "library_compact_grid_empty",
+            ) {
+                LibraryPagerEmptyScreen(searchQuery, hasActiveFilters, contentPadding)
+            }
+        } else {
+            items(
+                items = items,
+                contentType = { "library_compact_grid_item" },
+            ) { libraryItem ->
+                val manga = libraryItem.libraryManga.manga
+                MangaCompactGridItem(
+                    isSelected = selection.fastAny { it.id == libraryItem.libraryManga.id },
+                    title = manga.title.takeIf { showTitle },
+                    coverData = MangaCover(
+                        mangaId = manga.id,
+                        sourceId = manga.source,
+                        isMangaFavorite = manga.favorite,
+                        url = manga.thumbnailUrl,
+                        lastModified = manga.coverLastModified,
+                    ),
+                    coverBadgeStart = {
+                        DownloadsBadge(count = libraryItem.downloadCount.toInt())
+                        UnreadBadge(count = libraryItem.unreadCount.toInt())
+                    },
+                    coverBadgeEnd = {
+                        LanguageBadge(
+                            isLocal = libraryItem.isLocal,
+                            sourceLanguage = libraryItem.sourceLanguage,
+                        )
+                    },
+                    onLongClick = { onLongClick(libraryItem.libraryManga) },
+                    onClick = { onClick(libraryItem.libraryManga) },
+                    onClickContinueReading = if (onClickContinueReading != null) {
+                        { onClickContinueReading(libraryItem.libraryManga) }
+                    } else {
+                        null
+                    },
+                )
+            }
         }
     }
 }

+ 40 - 31
app/src/main/java/eu/kanade/presentation/library/components/LibraryList.kt

@@ -30,6 +30,7 @@ fun LibraryList(
     onClickContinueReading: ((LibraryManga) -> Unit)?,
     searchQuery: String?,
     onGlobalSearchClicked: () -> Unit,
+    hasActiveFilters: Boolean,
 ) {
     FastScrollLazyColumn(
         modifier = Modifier.fillMaxSize(),
@@ -49,37 +50,45 @@ fun LibraryList(
             }
         }
 
-        items(
-            items = items,
-            contentType = { "library_list_item" },
-        ) { libraryItem ->
-            val manga = libraryItem.libraryManga.manga
-            MangaListItem(
-                isSelected = selection.fastAny { it.id == libraryItem.libraryManga.id },
-                title = manga.title,
-                coverData = MangaCover(
-                    mangaId = manga.id,
-                    sourceId = manga.source,
-                    isMangaFavorite = manga.favorite,
-                    url = manga.thumbnailUrl,
-                    lastModified = manga.coverLastModified,
-                ),
-                badge = {
-                    DownloadsBadge(count = libraryItem.downloadCount.toInt())
-                    UnreadBadge(count = libraryItem.unreadCount.toInt())
-                    LanguageBadge(
-                        isLocal = libraryItem.isLocal,
-                        sourceLanguage = libraryItem.sourceLanguage,
-                    )
-                },
-                onLongClick = { onLongClick(libraryItem.libraryManga) },
-                onClick = { onClick(libraryItem.libraryManga) },
-                onClickContinueReading = if (onClickContinueReading != null) {
-                    { onClickContinueReading(libraryItem.libraryManga) }
-                } else {
-                    null
-                },
-            )
+        if (items.isEmpty()) {
+            item(
+                contentType = "library_list_empty",
+            ) {
+                LibraryPagerEmptyScreen(searchQuery, hasActiveFilters, contentPadding)
+            }
+        } else {
+            items(
+                items = items,
+                contentType = { "library_list_item" },
+            ) { libraryItem ->
+                val manga = libraryItem.libraryManga.manga
+                MangaListItem(
+                    isSelected = selection.fastAny { it.id == libraryItem.libraryManga.id },
+                    title = manga.title,
+                    coverData = MangaCover(
+                        mangaId = manga.id,
+                        sourceId = manga.source,
+                        isMangaFavorite = manga.favorite,
+                        url = manga.thumbnailUrl,
+                        lastModified = manga.coverLastModified,
+                    ),
+                    badge = {
+                        DownloadsBadge(count = libraryItem.downloadCount.toInt())
+                        UnreadBadge(count = libraryItem.unreadCount.toInt())
+                        LanguageBadge(
+                            isLocal = libraryItem.isLocal,
+                            sourceLanguage = libraryItem.sourceLanguage,
+                        )
+                    },
+                    onLongClick = { onLongClick(libraryItem.libraryManga) },
+                    onClick = { onClick(libraryItem.libraryManga) },
+                    onClickContinueReading = if (onClickContinueReading != null) {
+                        { onClickContinueReading(libraryItem.libraryManga) }
+                    } else {
+                        null
+                    },
+                )
+            }
         }
     }
 }

+ 5 - 6
app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt

@@ -48,11 +48,6 @@ fun LibraryPager(
         }
         val library = getLibraryForPage(page)
 
-        if (library.isEmpty()) {
-            LibraryPagerEmptyScreen(searchQuery, hasActiveFilters, contentPadding)
-            return@HorizontalPager
-        }
-
         val displayMode = getDisplayModeForPage(page)
         val columns by if (displayMode != LibraryDisplayMode.List) {
             val configuration = LocalConfiguration.current
@@ -74,6 +69,7 @@ fun LibraryPager(
                     onClickContinueReading = onClickContinueReading,
                     searchQuery = searchQuery,
                     onGlobalSearchClicked = onGlobalSearchClicked,
+                    hasActiveFilters = hasActiveFilters,
                 )
             }
             LibraryDisplayMode.CompactGrid, LibraryDisplayMode.CoverOnlyGrid -> {
@@ -88,6 +84,7 @@ fun LibraryPager(
                     onClickContinueReading = onClickContinueReading,
                     searchQuery = searchQuery,
                     onGlobalSearchClicked = onGlobalSearchClicked,
+                    hasActiveFilters = hasActiveFilters,
                 )
             }
             LibraryDisplayMode.ComfortableGrid -> {
@@ -101,6 +98,7 @@ fun LibraryPager(
                     onClickContinueReading = onClickContinueReading,
                     searchQuery = searchQuery,
                     onGlobalSearchClicked = onGlobalSearchClicked,
+                    hasActiveFilters = hasActiveFilters,
                 )
             }
         }
@@ -108,7 +106,7 @@ fun LibraryPager(
 }
 
 @Composable
-private fun LibraryPagerEmptyScreen(
+internal fun LibraryPagerEmptyScreen(
     searchQuery: String?,
     hasActiveFilters: Boolean,
     contentPadding: PaddingValues,
@@ -119,6 +117,7 @@ private fun LibraryPagerEmptyScreen(
         else -> R.string.information_no_manga_category
     }
 
+    // TODO: vertically center this better
     EmptyScreen(
         textResource = msg,
         modifier = Modifier.padding(contentPadding),

+ 37 - 37
app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSearchScreen.kt

@@ -212,43 +212,43 @@ private fun SearchResult(
     }
 
     Crossfade(targetState = result) {
-        LazyColumn(
-            modifier = modifier.fillMaxSize(),
-            state = listState,
-            contentPadding = contentPadding,
-            horizontalAlignment = Alignment.CenterHorizontally,
-        ) {
-            when {
-                it == null -> {
-                    /* Don't show anything just yet */
-                }
-                // No result
-                it.isEmpty() -> item { EmptyScreen(stringResource(R.string.no_results_found)) }
-                // Show result list
-                else -> items(
-                    items = it,
-                    key = { i -> i.hashCode() },
-                ) { item ->
-                    Column(
-                        modifier = Modifier
-                            .fillMaxWidth()
-                            .clickable { onItemClick(item) }
-                            .padding(horizontal = 24.dp, vertical = 14.dp),
-                    ) {
-                        Text(
-                            text = item.title,
-                            overflow = TextOverflow.Ellipsis,
-                            maxLines = 1,
-                            fontWeight = FontWeight.Normal,
-                            style = MaterialTheme.typography.titleMedium,
-                        )
-                        Text(
-                            text = item.breadcrumbs,
-                            modifier = Modifier.paddingFromBaseline(top = 16.dp),
-                            maxLines = 1,
-                            color = MaterialTheme.colorScheme.onSurfaceVariant,
-                            style = MaterialTheme.typography.bodySmall,
-                        )
+        when {
+            it == null -> {}
+            it.isEmpty() -> {
+                EmptyScreen(stringResource(R.string.no_results_found))
+            }
+            else -> {
+                LazyColumn(
+                    modifier = modifier.fillMaxSize(),
+                    state = listState,
+                    contentPadding = contentPadding,
+                    horizontalAlignment = Alignment.CenterHorizontally,
+                ) {
+                    items(
+                        items = it,
+                        key = { i -> i.hashCode() },
+                    ) { item ->
+                        Column(
+                            modifier = Modifier
+                                .fillMaxWidth()
+                                .clickable { onItemClick(item) }
+                                .padding(horizontal = 24.dp, vertical = 14.dp),
+                        ) {
+                            Text(
+                                text = item.title,
+                                overflow = TextOverflow.Ellipsis,
+                                maxLines = 1,
+                                fontWeight = FontWeight.Normal,
+                                style = MaterialTheme.typography.titleMedium,
+                            )
+                            Text(
+                                text = item.breadcrumbs,
+                                modifier = Modifier.paddingFromBaseline(top = 16.dp),
+                                maxLines = 1,
+                                color = MaterialTheme.colorScheme.onSurfaceVariant,
+                                style = MaterialTheme.typography.bodySmall,
+                            )
+                        }
                     }
                 }
             }