From 45be2f2e0213b2bea15b553a193ce6510f1b94fa Mon Sep 17 00:00:00 2001 From: Renan Lukas <14964993+RenanLukas@users.noreply.github.com> Date: Thu, 25 Apr 2024 21:33:30 -0300 Subject: [PATCH] WIP Start using UI state from ReaderTagsFeed in ReaderTagsFeedViewModel --- .../ui/reader/utils/ReaderUtilsWrapper.kt | 6 + .../viewmodels/ReaderTagsFeedViewModel.kt | 127 +++++++++++++++--- .../views/compose/tagsfeed/ReaderTagsFeed.kt | 8 +- 3 files changed, 119 insertions(+), 22 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderUtilsWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderUtilsWrapper.kt index 68d27dacaeb9..aacaf2d52eae 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderUtilsWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/utils/ReaderUtilsWrapper.kt @@ -63,4 +63,10 @@ class ReaderUtilsWrapper @Inject constructor( fun isSelfHosted(authorBlogId: Long) = ReaderUtils.isSelfHosted(authorBlogId) fun getTagFromTagUrl(url: String): String = ReaderUtils.getTagFromTagUrl(url) + + fun getShortLikeLabelText(numLikes: Int): String = + ReaderUtils.getShortLikeLabelText(contextProvider.getContext(), numLikes) + + fun getShortCommentLabelText(numComments: Int): String = + ReaderUtils.getShortCommentLabelText(contextProvider.getContext(), numComments) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModel.kt index 21a02e10dc2b..c4c8abd9c11f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModel.kt @@ -5,11 +5,11 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update -import org.wordpress.android.models.ReaderPostList import org.wordpress.android.models.ReaderTag import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.ui.reader.exceptions.ReaderPostFetchException import org.wordpress.android.ui.reader.repository.ReaderPostRepository +import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper import org.wordpress.android.ui.reader.views.compose.tagsfeed.TagsFeedPostItem import org.wordpress.android.viewmodel.ScopedViewModel import javax.inject.Inject @@ -19,8 +19,9 @@ import javax.inject.Named class ReaderTagsFeedViewModel @Inject constructor( @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, private val readerPostRepository: ReaderPostRepository, + private val readerUtilsWrapper: ReaderUtilsWrapper, ) : ScopedViewModel(bgDispatcher) { - private val _uiStateFlow = MutableStateFlow(UiState.Initial) + private val _uiStateFlow: MutableStateFlow = MutableStateFlow(UiState.Initial) val uiStateFlow: StateFlow = _uiStateFlow /** @@ -29,6 +30,10 @@ class ReaderTagsFeedViewModel @Inject constructor( * [FetchState]s: [FetchState.Loading], [FetchState.Success], [FetchState.Error]. */ fun fetchAll(tags: List) { + if (tags.isEmpty()) { + _uiStateFlow.value = UiState.Empty(::onOpenTagsListClick) + return + } tags.forEach { fetchTag(it) } @@ -42,23 +47,109 @@ class ReaderTagsFeedViewModel @Inject constructor( */ fun fetchTag(tag: ReaderTag) { launch { -// _uiStateFlow.update { -// it.copy(tagStates = it.tagStates + (tag to FetchState.Loading)) -// } -// -// try { -// val posts = readerPostRepository.fetchNewerPostsForTag(tag) -// _uiStateFlow.update { -// it.copy(tagStates = it.tagStates + (tag to FetchState.Success(posts))) -// } -// } catch (e: ReaderPostFetchException) { -// _uiStateFlow.update { -// it.copy(tagStates = it.tagStates + (tag to FetchState.Error(e))) -// } -// } + _uiStateFlow.update { UiState.Loading } + + val loadedData = mutableListOf() + val currentValue = _uiStateFlow.value + if (currentValue is UiState.Loaded) { + loadedData.addAll(currentValue.data) + } + try { + val posts = readerPostRepository.fetchNewerPostsForTag(tag) + if (posts.isNotEmpty()) { + loadedData.add( + TagFeedItem( + tagChip = TagChip( + tag = tag, + onTagClick = ::onTagClick, + ), + postList = PostList.Loaded( + posts.map { + TagsFeedPostItem( + siteName = it.blogName, + postDateLine = "1H", + postTitle = it.title, + postExcerpt = it.excerpt, + postImageUrl = it.blogImageUrl, + postNumberOfLikesText = readerUtilsWrapper.getShortLikeLabelText( + numLikes = it.numLikes + ), + postNumberOfCommentsText = readerUtilsWrapper.getShortCommentLabelText( + numComments = it.numReplies + ), + isPostLiked = it.isLikedByCurrentUser, + onSiteClick = ::onSiteClick, + onPostImageClick = ::onPostImageClick, + onPostLikeClick = ::onPostLikeClick, + onPostMoreMenuClick = ::onPostMoreMenuClick, + ) + } + ), + ) + ) + } else { + loadedData.add( + errorTagFeedItem( + tag = tag, + errorType = ErrorType.NoContent, + ) + ) + } + } catch (e: ReaderPostFetchException) { + loadedData.add( + errorTagFeedItem( + tag = tag, + errorType = ErrorType.Default, + ) + ) + } + _uiStateFlow.update { UiState.Loaded(loadedData) } } } + private fun errorTagFeedItem( + tag: ReaderTag, + errorType: ErrorType, + ): TagFeedItem = + TagFeedItem( + tagChip = TagChip( + tag = tag, + onTagClick = ::onTagClick + ), + postList = PostList.Error( + type = errorType, + onRetryClick = ::onRetryClick + ), + ) + + private fun onOpenTagsListClick() { + // TODO + } + + private fun onTagClick() { + // TODO + } + + private fun onRetryClick() { + // TODO + } + + private fun onSiteClick() { + // TODO + } + + private fun onPostImageClick() { + // TODO + } + + private fun onPostLikeClick() { + // TODO + } + + private fun onPostMoreMenuClick() { + // TODO + } + sealed class UiState { object Initial : UiState() data class Loaded(val data: List) : UiState() @@ -75,7 +166,7 @@ class ReaderTagsFeedViewModel @Inject constructor( data class TagChip( val tag: ReaderTag, - val onTagClicked: () -> Unit, + val onTagClick: () -> Unit, ) sealed class PostList { @@ -90,7 +181,7 @@ class ReaderTagsFeedViewModel @Inject constructor( } sealed interface ErrorType { - data object Loading : ErrorType + data object Default : ErrorType data object NoContent : ErrorType } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt index c9a0396f2f2a..41fc36ab1790 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt @@ -96,7 +96,7 @@ private fun Loaded(uiState: UiState.Loaded) { start = Margin.Large.value, ), text = UiString.UiStringText(tagChip.tag.tagTitle), - onClick = tagChip.onTagClicked, + onClick = tagChip.onTagClick, height = 36.dp, ) Spacer(modifier = Modifier.height(Margin.Large.value)) @@ -300,7 +300,7 @@ private fun PostListLoaded( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(bounded = false), onClick = { - tagChip.onTagClicked() + tagChip.onTagClick() AppLog.e(AppLog.T.READER, "RL-> Tag clicked") } ), @@ -374,7 +374,7 @@ private fun PostListError( ) Spacer(modifier = Modifier.height(Margin.Medium.value)) val errorMessage = when (postList.type) { - is ErrorType.Loading -> stringResource(R.string.reader_tags_feed_loading_error_description) + is ErrorType.Default -> stringResource(R.string.reader_tags_feed_loading_error_description) is ErrorType.NoContent -> stringResource(R.string.reader_tags_feed_no_content_error_description, tagName) } Text( @@ -529,7 +529,7 @@ fun ReaderTagsFeedLoaded() { ), TagFeedItem( tagChip = TagChip(readerTag, {}), - postList = PostList.Error(ErrorType.Loading, {}), + postList = PostList.Error(ErrorType.Default, {}), ), TagFeedItem( tagChip = TagChip(readerTag, {}),