Skip to content

Commit

Permalink
Merge branch 'feature/tags-ia' into issue/20621-tags-feed-onboarding
Browse files Browse the repository at this point in the history
  • Loading branch information
RenanLukas committed May 18, 2024
2 parents c80c983 + 8255e5b commit 5efab23
Show file tree
Hide file tree
Showing 14 changed files with 633 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,15 @@ class SubFilterViewModel @Inject constructor(
}

fun setDefaultSubfilter(isClearingFilter: Boolean) {
readerTracker.track(Stat.READER_FILTER_SHEET_CLEARED)
val filterItemType = FilterItemType.fromSubfilterListItem(getCurrentSubfilterValue())
if (filterItemType != null) {
readerTracker.track(
Stat.READER_FILTER_SHEET_CLEARED,
mutableMapOf(FilterItemType.trackingEntry(filterItemType))
)
} else {
readerTracker.track(Stat.READER_FILTER_SHEET_CLEARED)
}
updateSubfilter(
filter = SiteAll(
onClickAction = ::onSubfilterClicked,
Expand Down Expand Up @@ -317,7 +325,15 @@ class SubFilterViewModel @Inject constructor(
fun onSubfilterSelected(subfilterListItem: SubfilterListItem) {
// We should not track subfilter selected if we're clearing a filter that is currently applied.
if (!subfilterListItem.isClearingFilter) {
readerTracker.track(Stat.READER_FILTER_SHEET_ITEM_SELECTED)
val filterItemType = FilterItemType.fromSubfilterListItem(subfilterListItem)
if (filterItemType != null) {
readerTracker.track(
Stat.READER_FILTER_SHEET_ITEM_SELECTED,
mutableMapOf(FilterItemType.trackingEntry(filterItemType))
)
} else {
readerTracker.track(Stat.READER_FILTER_SHEET_ITEM_SELECTED,)
}
}
changeSubfilter(subfilterListItem, true, mTagFragmentStartedWith)
}
Expand Down Expand Up @@ -425,4 +441,22 @@ class SubFilterViewModel @Inject constructor(
return SUBFILTER_VM_BASE_KEY + tag.keyString
}
}

sealed class FilterItemType(val trackingValue: String) {
data object Tag : FilterItemType("topic")

data object Blog : FilterItemType("site")

companion object {
fun fromSubfilterListItem(subfilterListItem: SubfilterListItem): FilterItemType? =
when(subfilterListItem.type) {
SubfilterListItem.ItemType.SITE -> Blog
SubfilterListItem.ItemType.TAG -> Tag
else -> null
}

fun trackingEntry(filterItemType: FilterItemType): Pair<String, String> =
"type" to filterItemType.trackingValue
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class ReaderTracker @Inject constructor(
ReaderTab.A8C -> analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_A8C_SHOWN)
ReaderTab.P2 -> analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_P2_SHOWN)
ReaderTab.CUSTOM -> analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_CUSTOM_TAB_SHOWN)
ReaderTab.TAGS_FEED -> analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_TAGS_FEED_SHOWN)
}
appPrefsWrapper.setReaderActiveTab(readerTab)
}
Expand Down Expand Up @@ -404,6 +405,7 @@ class ReaderTracker @Inject constructor(
readerTag.isA8C -> "a8c"
readerTag.isListTopic -> "list"
readerTag.isP2 -> "p2"
readerTag.isTags -> "tags"
else -> null
}?.let { trackingId ->
analyticsTrackerWrapper.track(
Expand Down Expand Up @@ -515,7 +517,8 @@ enum class ReaderTab(
SAVED(4, ReaderTracker.SOURCE_SAVED),
CUSTOM(5, ReaderTracker.SOURCE_CUSTOM),
A8C(6, ReaderTracker.SOURCE_A8C),
P2(7, ReaderTracker.SOURCE_P2);
P2(7, ReaderTracker.SOURCE_P2),
TAGS_FEED(8, ReaderTracker.SOURCE_TAGS_FEED);

companion object {
fun fromId(id: Int): ReaderTab {
Expand All @@ -527,6 +530,7 @@ enum class ReaderTab(
A8C.id -> A8C
P2.id -> P2
CUSTOM.id -> CUSTOM
TAGS_FEED.id -> TAGS_FEED
else -> throw RuntimeException("Unexpected ReaderTab id")
}
}
Expand All @@ -540,6 +544,7 @@ enum class ReaderTab(
readerTag.isDiscover -> DISCOVER
readerTag.isA8C -> A8C
readerTag.isP2 -> P2
readerTag.isTags -> TAGS_FEED
else -> CUSTOM
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import org.wordpress.android.models.ReaderTag
import org.wordpress.android.ui.reader.utils.ReaderUtilsWrapper
import org.wordpress.android.ui.reader.views.compose.tagsfeed.TagsFeedPostItem
import org.wordpress.android.util.DateTimeUtilsWrapper
import org.wordpress.android.util.UrlUtilsWrapper
import javax.inject.Inject

class ReaderTagsFeedUiStateMapper @Inject constructor(
private val dateTimeUtilsWrapper: DateTimeUtilsWrapper,
private val readerUtilsWrapper: ReaderUtilsWrapper,
private val urlUtilsWrapper: UrlUtilsWrapper,
) {
@Suppress("LongParameterList")
fun mapLoadedTagFeedItem(
Expand All @@ -29,25 +31,26 @@ class ReaderTagsFeedUiStateMapper @Inject constructor(
onMoreFromTagClick = onMoreFromTagClick,
),
postList = ReaderTagsFeedViewModel.PostList.Loaded(
posts.map {
posts.map { post ->
TagsFeedPostItem(
siteName = it.blogName,
siteName = post.blogName.takeIf { it.isNotBlank() }
?: post.blogUrl.let { urlUtilsWrapper.removeScheme(it) },
postDateLine = dateTimeUtilsWrapper.javaDateToTimeSpan(
it.getDisplayDate(dateTimeUtilsWrapper)
post.getDisplayDate(dateTimeUtilsWrapper)
),
postTitle = it.title,
postExcerpt = it.excerpt,
postImageUrl = it.featuredImage,
postNumberOfLikesText = if (it.numLikes > 0) readerUtilsWrapper.getShortLikeLabelText(
numLikes = it.numLikes
postTitle = post.title,
postExcerpt = post.excerpt,
postImageUrl = post.featuredImage,
postNumberOfLikesText = if (post.numLikes > 0) readerUtilsWrapper.getShortLikeLabelText(
numLikes = post.numLikes
) else "",
postNumberOfCommentsText = if (it.numReplies > 0) readerUtilsWrapper.getShortCommentLabelText(
numComments = it.numReplies
postNumberOfCommentsText = if (post.numReplies > 0) readerUtilsWrapper.getShortCommentLabelText(
numComments = post.numReplies
) else "",
isPostLiked = it.isLikedByCurrentUser,
isPostLiked = post.isLikedByCurrentUser,
isLikeButtonEnabled = true,
postId = it.postId,
blogId = it.blogId,
postId = post.postId,
blogId = post.blogId,
onSiteClick = onSiteClick,
onPostCardClick = onPostCardClick,
onPostLikeClick = onPostLikeClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import org.wordpress.android.R
import org.wordpress.android.analytics.AnalyticsTracker
import org.wordpress.android.datasets.wrappers.ReaderPostTableWrapper
import org.wordpress.android.models.ReaderPost
import org.wordpress.android.models.ReaderTag
Expand Down Expand Up @@ -48,6 +49,7 @@ class ReaderTagsFeedViewModel @Inject constructor(
private val readerPostMoreButtonUiStateBuilder: ReaderPostMoreButtonUiStateBuilder,
private val readerPostUiStateBuilder: ReaderPostUiStateBuilder,
private val displayUtilsWrapper: DisplayUtilsWrapper,
private val readerTracker: ReaderTracker,
) : ScopedViewModel(bgDispatcher) {
private val _uiStateFlow: MutableStateFlow<UiState> = MutableStateFlow(UiState.Initial)
val uiStateFlow: StateFlow<UiState> = _uiStateFlow
Expand Down Expand Up @@ -235,11 +237,13 @@ class ReaderTagsFeedViewModel @Inject constructor(

@VisibleForTesting
fun onTagChipClick(readerTag: ReaderTag) {
readerTracker.track(AnalyticsTracker.Stat.READER_TAGS_FEED_HEADER_TAPPED)
_actionEvents.value = ActionEvent.FilterTagPostsFeed(readerTag)
}

@VisibleForTesting
fun onMoreFromTagClick(readerTag: ReaderTag) {
readerTracker.track(AnalyticsTracker.Stat.READER_TAGS_FEED_MORE_FROM_TAG_TAPPED)
_actionEvents.value = ActionEvent.OpenTagPostList(readerTag)
}

Expand All @@ -258,9 +262,14 @@ class ReaderTagsFeedViewModel @Inject constructor(
}
}

private fun onPostCardClick(postItem: TagsFeedPostItem) {
@VisibleForTesting
fun onPostCardClick(postItem: TagsFeedPostItem) {
launch {
findPost(postItem.postId, postItem.blogId)?.let {
readerTracker.trackBlog(
AnalyticsTracker.Stat.READER_POST_CARD_TAPPED,
it.blogId, it.feedId, it.isFollowedByCurrentUser, ReaderTracker.SOURCE_TAGS_FEED,
)
readerPostCardActionsHandler.handleOnItemClicked(
it,
ReaderTracker.SOURCE_TAGS_FEED
Expand Down Expand Up @@ -430,7 +439,7 @@ class ReaderTagsFeedViewModel @Inject constructor(
it,
type,
isBookmarkList = false,
source = ReaderTracker.SOURCE_DISCOVER
source = ReaderTracker.SOURCE_TAGS_FEED,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
Expand All @@ -61,8 +64,6 @@ import org.wordpress.android.ui.reader.viewmodels.tagsfeed.ReaderTagsFeedViewMod
import org.wordpress.android.ui.reader.views.compose.filter.ReaderFilterChip
import org.wordpress.android.ui.utils.UiString

private const val LOADING_POSTS_COUNT = 5

@Composable
fun ReaderTagsFeed(uiState: UiState) {
Box(
Expand Down Expand Up @@ -147,8 +148,14 @@ private fun Loaded(uiState: UiState.Loaded) {

@Composable
private fun Loading() {
val fetchingPostsLabel = stringResource(id = R.string.posts_fetching)

LazyColumn(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.clearAndSetSemantics {
contentDescription = fetchingPostsLabel
},
userScrollEnabled = false,
) {
val numberOfLoadingRows = 3
Expand Down Expand Up @@ -177,7 +184,7 @@ private fun Loading() {
horizontalArrangement = Arrangement.spacedBy(Margin.Large.value),
contentPadding = PaddingValues(horizontal = Margin.Large.value),
) {
items(LOADING_POSTS_COUNT) {
items(ReaderTagsFeedComposeUtils.LOADING_POSTS_COUNT) {
ReaderTagsFeedPostListItemLoading()
}
}
Expand Down Expand Up @@ -259,17 +266,21 @@ private fun Empty(uiState: UiState.Empty) {

@Composable
private fun PostListLoading() {
val loadingLabel = stringResource(id = R.string.loading)
LazyRow(
modifier = Modifier
.fillMaxWidth(),
.fillMaxWidth()
.clearAndSetSemantics {
contentDescription = loadingLabel
},
userScrollEnabled = false,
horizontalArrangement = Arrangement.spacedBy(Margin.ExtraMediumLarge.value),
contentPadding = PaddingValues(
start = Margin.Large.value,
end = Margin.Large.value
),
) {
items(LOADING_POSTS_COUNT) {
items(ReaderTagsFeedComposeUtils.LOADING_POSTS_COUNT) {
ReaderTagsFeedPostListItemLoading()
}
}
Expand Down Expand Up @@ -304,7 +315,7 @@ private fun PostListLoaded(
)
Box(
modifier = Modifier
.height(340.dp)
.height(ReaderTagsFeedComposeUtils.PostItemHeight)
.padding(
start = Margin.ExtraLarge.value,
end = Margin.ExtraLarge.value,
Expand Down Expand Up @@ -364,6 +375,7 @@ private fun PostListError(
modifier = Modifier
.height(250.dp)
.fillMaxWidth()
.semantics(mergeDescendants = true) {}
.padding(start = 60.dp, end = 60.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.wordpress.android.ui.reader.views.compose.tagsfeed

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.min
import androidx.compose.ui.unit.sp

object ReaderTagsFeedComposeUtils {
const val LOADING_POSTS_COUNT = 5

const val POST_ITEM_TITLE_MAX_LINES = 2
val POST_ITEM_IMAGE_SIZE = 64.dp
private val POST_ITEM_HEIGHT = 150.sp // use SP to scale with text size, which is the main content of the item
private val POST_ITEM_MAX_WIDTH = 320.dp
private const val POST_ITEM_WIDTH_PERCENTAGE = 0.8f

val PostItemHeight: Dp
@Composable
get() {
with(LocalDensity.current) {
return POST_ITEM_HEIGHT.toDp()
}
}

val PostItemWidth: Dp
@Composable
get() {
val localConfiguration = LocalConfiguration.current
val screenWidth = remember(localConfiguration) {
localConfiguration.screenWidthDp.dp
}
return min((screenWidth * POST_ITEM_WIDTH_PERCENTAGE), POST_ITEM_MAX_WIDTH)
}
}
Loading

0 comments on commit 5efab23

Please sign in to comment.