diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/common/NoItemsMessage.kt b/app/src/main/java/org/schabi/newpipe/ui/components/common/NoItemsMessage.kt deleted file mode 100644 index afb53fdf4..000000000 --- a/app/src/main/java/org/schabi/newpipe/ui/components/common/NoItemsMessage.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.schabi.newpipe.ui.components.common - -import android.content.res.Configuration -import androidx.annotation.StringRes -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.sp -import org.schabi.newpipe.R -import org.schabi.newpipe.ui.theme.AppTheme - -@Composable -fun NoItemsMessage(@StringRes message: Int) { - Column( - modifier = Modifier - .fillMaxWidth() - .wrapContentSize(Alignment.Center), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text(text = "(╯°-°)╯", fontSize = 35.sp) - Text(text = stringResource(id = message), fontSize = 24.sp) - } -} - -@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO) -@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES) -@Composable -private fun NoItemsMessagePreview() { - AppTheme { - Surface(color = MaterialTheme.colorScheme.background) { - NoItemsMessage(message = R.string.no_videos) - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/video/RelatedItems.kt b/app/src/main/java/org/schabi/newpipe/ui/components/video/RelatedItems.kt index 6eee01bc0..3c6c49d35 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/video/RelatedItems.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/video/RelatedItems.kt @@ -26,9 +26,10 @@ import org.schabi.newpipe.R import org.schabi.newpipe.extractor.stream.StreamInfo import org.schabi.newpipe.extractor.stream.StreamType import org.schabi.newpipe.info_list.ItemViewMode -import org.schabi.newpipe.ui.components.common.NoItemsMessage import org.schabi.newpipe.ui.components.items.ItemList import org.schabi.newpipe.ui.components.items.stream.StreamInfoItem +import org.schabi.newpipe.ui.emptystate.EmptyStateComposable +import org.schabi.newpipe.ui.emptystate.EmptyStateSpec import org.schabi.newpipe.ui.theme.AppTheme import org.schabi.newpipe.util.NO_SERVICE_ID @@ -41,43 +42,44 @@ fun RelatedItems(info: StreamInfo) { mutableStateOf(sharedPreferences.getBoolean(key, false)) } - if (info.relatedItems.isEmpty()) { - NoItemsMessage(message = R.string.no_videos) - } else { - ItemList( - items = info.relatedItems, - mode = ItemViewMode.LIST, - listHeader = { - item { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 12.dp, end = 12.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Text(text = stringResource(R.string.auto_queue_description)) + ItemList( + items = info.relatedItems, + mode = ItemViewMode.LIST, + listHeader = { + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 12.dp, end = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text(text = stringResource(R.string.auto_queue_description)) - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = stringResource(R.string.auto_queue_toggle)) - Switch( - checked = isAutoQueueEnabled, - onCheckedChange = { - isAutoQueueEnabled = it - sharedPreferences.edit { - putBoolean(key, it) - } + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = stringResource(R.string.auto_queue_toggle)) + Switch( + checked = isAutoQueueEnabled, + onCheckedChange = { + isAutoQueueEnabled = it + sharedPreferences.edit { + putBoolean(key, it) } - ) - } + } + ) } } } - ) - } + if (info.relatedItems.isEmpty()) { + item { + EmptyStateComposable(EmptyStateSpec.NoVideos) + } + } + } + ) } @Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO) diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentRepliesDialog.kt b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentRepliesDialog.kt index 17ea900a5..d6d00b28c 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentRepliesDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentRepliesDialog.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.compose.ui.unit.dp @@ -38,7 +39,8 @@ import org.schabi.newpipe.extractor.stream.Description import org.schabi.newpipe.paging.CommentRepliesSource import org.schabi.newpipe.ui.components.common.LazyColumnThemedScrollbar import org.schabi.newpipe.ui.components.common.LoadingIndicator -import org.schabi.newpipe.ui.components.common.NoItemsMessage +import org.schabi.newpipe.ui.emptystate.EmptyStateComposable +import org.schabi.newpipe.ui.emptystate.EmptyStateSpec import org.schabi.newpipe.ui.theme.AppTheme @Composable @@ -130,13 +132,17 @@ private fun CommentRepliesDialog( val refresh = comments.loadState.refresh if (refresh is LoadState.Loading) { LoadingIndicator(modifier = Modifier.padding(top = 8.dp)) + } else if (refresh is LoadState.Error) { + // TODO use error panel instead + EmptyStateComposable( + EmptyStateSpec.DisabledComments.copy( + descriptionText = { + stringResource(R.string.error_unable_to_load_comments) + } + ) + ) } else { - val message = if (refresh is LoadState.Error) { - R.string.error_unable_to_load_comments - } else { - R.string.no_comments - } - NoItemsMessage(message) + EmptyStateComposable(EmptyStateSpec.NoComments) } } } else { diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt index 33c4e2139..d603c4a6f 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -28,7 +29,8 @@ import org.schabi.newpipe.extractor.comments.CommentsInfoItem import org.schabi.newpipe.extractor.stream.Description import org.schabi.newpipe.ui.components.common.LazyColumnThemedScrollbar import org.schabi.newpipe.ui.components.common.LoadingIndicator -import org.schabi.newpipe.ui.components.common.NoItemsMessage +import org.schabi.newpipe.ui.emptystate.EmptyStateComposable +import org.schabi.newpipe.ui.emptystate.EmptyStateSpec import org.schabi.newpipe.ui.theme.AppTheme import org.schabi.newpipe.viewmodels.CommentsViewModel import org.schabi.newpipe.viewmodels.util.Resource @@ -66,11 +68,11 @@ private fun CommentSection( if (commentInfo.isCommentsDisabled) { item { - NoItemsMessage(R.string.comments_are_disabled) + EmptyStateComposable(EmptyStateSpec.DisabledComments) } } else if (count == 0) { item { - NoItemsMessage(R.string.no_comments) + EmptyStateComposable(EmptyStateSpec.NoComments) } } else { // do not show anything if the comment count is unknown @@ -95,7 +97,14 @@ private fun CommentSection( is LoadState.Error -> { item { - NoItemsMessage(R.string.error_unable_to_load_comments) + // TODO use error panel instead + EmptyStateComposable( + EmptyStateSpec.DisabledComments.copy( + descriptionText = { + stringResource(R.string.error_unable_to_load_comments) + } + ) + ) } } @@ -110,7 +119,14 @@ private fun CommentSection( is Resource.Error -> { item { - NoItemsMessage(R.string.error_unable_to_load_comments) + // TODO use error panel instead + EmptyStateComposable( + EmptyStateSpec.DisabledComments.copy( + descriptionText = { + stringResource(R.string.error_unable_to_load_comments) + } + ) + ) } } } diff --git a/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt b/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt index 3e101d760..ab9bf6336 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt @@ -69,7 +69,7 @@ fun EmptyStateComposableGenericErrorPreview() { @Composable fun EmptyStateComposableNoCommentPreview() { AppTheme { - EmptyStateComposable(EmptyStateSpec.NoComment) + EmptyStateComposable(EmptyStateSpec.NoComments) } } @@ -91,15 +91,35 @@ data class EmptyStateSpec( descriptionText = { stringResource(id = R.string.empty_list_subtitle) }, ) - val NoComment = + val NoVideos = EmptyStateSpec( - modifier = { it.padding(top = 85.dp) }, + modifier = { + it + .fillMaxWidth() + .heightIn(min = 128.dp) + }, emojiText = { "(╯°-°)╯" }, + descriptionText = { stringResource(id = R.string.no_videos) }, + ) + + val NoComments = + EmptyStateSpec( + modifier = { + it + .fillMaxWidth() + .heightIn(min = 128.dp) + }, + emojiText = { "¯\\_(╹x╹)_/¯" }, descriptionText = { stringResource(id = R.string.no_comments) }, ) + val DisabledComments = + NoComments.copy( + descriptionText = { stringResource(id = R.string.comments_are_disabled) }, + ) + val NoSearchResult = - NoComment.copy( + NoComments.copy( modifier = { it }, emojiText = { "╰(°●°╰)" }, descriptionText = { stringResource(id = R.string.search_no_results) } @@ -111,7 +131,7 @@ data class EmptyStateSpec( ) val ContentNotSupported = - NoComment.copy( + NoComments.copy( modifier = { it.padding(top = 90.dp) }, emojiText = { "(︶︹︺)" }, descriptionText = { stringResource(id = R.string.content_not_supported) },