Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Reader] Move announcement card inside the feeds #20872

Merged
merged 12 commits into from
May 24, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import org.wordpress.android.ui.reader.subfilter.SubfilterCategory
import org.wordpress.android.ui.reader.subfilter.SubfilterListItem
import org.wordpress.android.ui.reader.viewmodels.ReaderViewModel
import org.wordpress.android.ui.reader.viewmodels.ReaderViewModel.ReaderUiState.ContentUiState
import org.wordpress.android.ui.reader.views.compose.ReaderAnnouncementCard
import org.wordpress.android.ui.reader.views.compose.ReaderTopAppBar
import org.wordpress.android.ui.reader.views.compose.filter.ReaderFilterType
import org.wordpress.android.ui.utils.UiHelpers
Expand Down Expand Up @@ -181,7 +180,6 @@ class ReaderFragment : Fragment(R.layout.reader_fragment_layout), ScrollableView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding = ReaderFragmentLayoutBinding.bind(view).apply {
initTopAppBar()
initAnnouncementCard()
initViewModel(savedInstanceState)
}
}
Expand Down Expand Up @@ -264,23 +262,6 @@ class ReaderFragment : Fragment(R.layout.reader_fragment_layout), ScrollableView
}
}

private fun ReaderFragmentLayoutBinding.initAnnouncementCard() {
readerAnnouncementCardComposeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
val announcementCardUiState by viewModel.announcementCardState.observeAsState()
val state = announcementCardUiState ?: return@setContent
AppTheme {
ReaderAnnouncementCard(
shouldShow = state.shouldShow,
items = state.items,
onAnnouncementCardDoneClick = { viewModel.onAnnouncementCardDoneClick() }
)
}
}
}
}

private fun ReaderFragmentLayoutBinding.initViewModel(savedInstanceState: Bundle?) {
viewModel = ViewModelProvider(this@ReaderFragment, viewModelFactory)[ReaderViewModel::class.java]
startReaderViewModel(savedInstanceState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
import org.wordpress.android.ui.reader.discover.viewholders.ReaderPostNewViewHolder;
import org.wordpress.android.ui.reader.discover.viewholders.ReaderPostViewHolder;
import org.wordpress.android.ui.reader.models.ReaderBlogIdPostId;
import org.wordpress.android.ui.reader.repository.ReaderAnnouncementRepository;
import org.wordpress.android.ui.reader.tracker.ReaderTab;
import org.wordpress.android.ui.reader.tracker.ReaderTracker;
import org.wordpress.android.ui.reader.utils.ReaderXPostUtils;
import org.wordpress.android.ui.reader.views.ReaderAnnouncementCardView;
import org.wordpress.android.ui.reader.views.ReaderGapMarkerView;
import org.wordpress.android.ui.reader.views.ReaderSiteHeaderView;
import org.wordpress.android.ui.reader.views.ReaderTagHeaderView;
Expand Down Expand Up @@ -117,9 +119,11 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
private static final int VIEW_TYPE_TAG_HEADER = 3;
private static final int VIEW_TYPE_GAP_MARKER = 4;
private static final int VIEW_TYPE_REMOVED_POST = 5;
private static final int VIEW_TYPE_READER_ANNOUNCEMENT = 6;

private static final long ITEM_ID_HEADER = -1L;
private static final long ITEM_ID_GAP_MARKER = -2L;
private static final long ITEM_ID_READER_ANNOUNCEMENT = -3L;

private static final float READER_FEATURED_IMAGE_ASPECT_RATIO = 16 / 9f;

Expand All @@ -131,6 +135,7 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
@Inject ReaderPostMoreButtonUiStateBuilder mReaderPostMoreButtonUiStateBuilder;
@Inject ReaderTracker mReaderTracker;
@Inject ReaderImprovementsFeatureConfig mReaderImprovementsFeatureConfig;
@Inject ReaderAnnouncementRepository mReaderAnnouncementRepository;

public String getSource() {
return mSource;
Expand Down Expand Up @@ -179,6 +184,15 @@ private static class ReaderRemovedPostViewHolder extends RecyclerView.ViewHolder
}
}

private static class ReaderAnnouncementCardViewHolder extends RecyclerView.ViewHolder {
private final ReaderAnnouncementCardView mAnnouncementCardView;

ReaderAnnouncementCardViewHolder(View itemView) {
super(itemView);
mAnnouncementCardView = (ReaderAnnouncementCardView) itemView;
}
}

private static class SiteHeaderViewHolder extends RecyclerView.ViewHolder {
private final ReaderSiteHeaderView mSiteHeaderView;

Expand Down Expand Up @@ -212,23 +226,33 @@ private static class GapMarkerViewHolder extends RecyclerView.ViewHolder {

@Override
public int getItemViewType(int position) {
if (position == 0 && hasSiteHeader()) {
// first item is a ReaderSiteHeaderView
return VIEW_TYPE_SITE_HEADER;
} else if (position == 0 && hasTagHeader()) {
// first item is a ReaderTagHeaderView
return VIEW_TYPE_TAG_HEADER;
} else if (position == mGapMarkerPosition) {
// announcement logic
if (getAnnouncementPosition() == position) {
return VIEW_TYPE_READER_ANNOUNCEMENT;
}

// header logic
if (position == getHeaderPosition()) {
if (hasSiteHeader()) {
return VIEW_TYPE_SITE_HEADER;
} else if (hasTagHeader()) {
return VIEW_TYPE_TAG_HEADER;
}
}

// gap marker logic
if (position == mGapMarkerPosition) {
return VIEW_TYPE_GAP_MARKER;
}

// post logic
ReaderPost post = getItem(position);
if (post != null && post.isXpost()) {
return VIEW_TYPE_XPOST;
} else if (post != null && isBookmarksList() && !post.isBookmarked) {
return VIEW_TYPE_REMOVED_POST;
} else {
ReaderPost post = getItem(position);
if (post != null && post.isXpost()) {
return VIEW_TYPE_XPOST;
} else if (post != null && isBookmarksList() && !post.isBookmarked) {
return VIEW_TYPE_REMOVED_POST;
} else {
return VIEW_TYPE_POST;
}
return VIEW_TYPE_POST;
}
}

Expand All @@ -237,6 +261,10 @@ public int getItemViewType(int position) {
Context context = parent.getContext();
View postView;
switch (viewType) {
case VIEW_TYPE_READER_ANNOUNCEMENT:
ReaderAnnouncementCardView readerAnnouncementCardView = new ReaderAnnouncementCardView(context);
return new ReaderAnnouncementCardViewHolder(readerAnnouncementCardView);

case VIEW_TYPE_SITE_HEADER:
ReaderSiteHeaderView readerSiteHeaderView = new ReaderSiteHeaderView(context);
readerSiteHeaderView.setOnFollowListener(mFollowListener);
Expand Down Expand Up @@ -298,6 +326,14 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
} else if (holder instanceof GapMarkerViewHolder) {
GapMarkerViewHolder gapHolder = (GapMarkerViewHolder) holder;
gapHolder.mGapMarkerView.setCurrentTag(mCurrentTag);
} else if (holder instanceof ReaderAnnouncementCardViewHolder) {
ReaderAnnouncementCardViewHolder announcementViewHolder = (ReaderAnnouncementCardViewHolder) holder;
announcementViewHolder.mAnnouncementCardView
.setItems(mReaderAnnouncementRepository.getReaderAnnouncementItems());
announcementViewHolder.mAnnouncementCardView.setOnDoneClickListener(() -> {
mReaderAnnouncementRepository.dismissReaderAnnouncement();
notifyItemRemoved(getAnnouncementPosition());
});
}
}

Expand Down Expand Up @@ -680,6 +716,12 @@ private boolean hasTagHeader() {
return (getPostListType() == ReaderPostListType.TAG_PREVIEW) && !isEmpty();
}

private boolean hasAnnouncement() {
return mIsMainReader && mReaderAnnouncementRepository.hasReaderAnnouncement() && !isEmpty()
&& (getPostListType() != ReaderPostListType.BLOG_PREVIEW)
&& (mCurrentTag != null && !mCurrentTag.isTagTopic());
}

private boolean isDiscover() {
return mCurrentTag != null && mCurrentTag.isDiscover();
}
Expand Down Expand Up @@ -766,6 +808,9 @@ private void loadPosts() {
}

private ReaderPost getItem(int position) {
if (position == getAnnouncementPosition() && hasAnnouncement()) {
return null;
}
if (position == getHeaderPosition() && hasHeader()) {
return null;
}
Expand All @@ -788,22 +833,27 @@ private ReaderPost getItem(int position) {
}

private int getItemPositionOffset() {
return hasHeader() ? 1 : 0;
int offset = 0;
if (hasAnnouncement()) offset++;
if (hasHeader()) offset++;
return offset;
}

private int getHeaderPosition() {
return hasHeader() ? 0 : -1;
int headerPosition = hasAnnouncement() ? 1 : 0;
return hasHeader() ? headerPosition : -1;
}

private int getAnnouncementPosition() {
return hasAnnouncement() ? 0 : -1;
}

@Override
public int getItemCount() {
int size = mPosts.size();
if (mGapMarkerPosition != -1) {
size++;
}
if (hasHeader()) {
size++;
}
if (mGapMarkerPosition != -1) size++;
if (hasHeader()) size++;
if (hasAnnouncement()) size++;
return size;
}

Expand All @@ -824,6 +874,8 @@ public long getItemId(int position) {
return ITEM_ID_HEADER;
case VIEW_TYPE_GAP_MARKER:
return ITEM_ID_GAP_MARKER;
case VIEW_TYPE_READER_ANNOUNCEMENT:
return ITEM_ID_READER_ANNOUNCEMENT;
default:
ReaderPost post = getItem(position);
return post != null ? post.getStableId() : 0;
Expand Down Expand Up @@ -892,7 +944,7 @@ protected void onCancelled() {

@Override
protected Boolean doInBackground(Void... params) {
int numExisting;
int numExisting = 0;
switch (getPostListType()) {
case TAG_PREVIEW:
case TAG_FOLLOWED:
Expand All @@ -909,7 +961,7 @@ protected Boolean doInBackground(Void... params) {
numExisting = ReaderPostTable.getNumPostsInBlog(mCurrentBlogId);
}
break;
default:
case TAGS_FEED:
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.wordpress.android.ui.reader.discover.ReaderPostCardAction.PrimaryActi
import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.SPACER_NO_ACTION
import org.wordpress.android.ui.reader.discover.interests.TagUiState
import org.wordpress.android.ui.reader.models.ReaderImageList
import org.wordpress.android.ui.reader.views.compose.ReaderAnnouncementCardItemData
import org.wordpress.android.ui.reader.views.uistates.ReaderBlogSectionUiState
import org.wordpress.android.ui.utils.UiDimen
import org.wordpress.android.ui.utils.UiString
Expand Down Expand Up @@ -175,6 +176,11 @@ sealed class ReaderCardUiState {
}
}
}

data class ReaderAnnouncementCardUiState(
val items: List<ReaderAnnouncementCardItemData>,
val onDoneClick: () -> Unit,
) : ReaderCardUiState()
}

data class ReaderPostActions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package org.wordpress.android.ui.reader.discover
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView.Adapter
import org.wordpress.android.ui.reader.discover.ReaderCardUiState.ReaderAnnouncementCardUiState
import org.wordpress.android.ui.reader.discover.ReaderCardUiState.ReaderInterestsCardUiState
import org.wordpress.android.ui.reader.discover.ReaderCardUiState.ReaderPostNewUiState
import org.wordpress.android.ui.reader.discover.ReaderCardUiState.ReaderPostUiState
import org.wordpress.android.ui.reader.discover.ReaderCardUiState.ReaderRecommendedBlogsCardUiState
import org.wordpress.android.ui.reader.discover.viewholders.ReaderAnnouncementCardViewHolder
import org.wordpress.android.ui.reader.discover.viewholders.ReaderInterestsCardNewViewHolder
import org.wordpress.android.ui.reader.discover.viewholders.ReaderInterestsCardViewHolder
import org.wordpress.android.ui.reader.discover.viewholders.ReaderPostNewViewHolder
Expand All @@ -24,6 +26,7 @@ private const val POST_VIEW_TYPE: Int = 1
private const val INTEREST_VIEW_TYPE: Int = 2
private const val RECOMMENDED_BLOGS_VIEW_TYPE: Int = 3
private const val POST_NEW_VIEW_TYPE: Int = 4
private const val READER_ANNOUNCEMENT_TYPE: Int = 5

class ReaderDiscoverAdapter(
private val uiHelpers: UiHelpers,
Expand All @@ -43,13 +46,15 @@ class ReaderDiscoverAdapter(
networkUtilsWrapper,
parent
)

INTEREST_VIEW_TYPE -> {
if (isReaderImprovementsEnabled) {
ReaderInterestsCardNewViewHolder(uiHelpers, parent)
} else {
ReaderInterestsCardViewHolder(uiHelpers, parent)
}
}

RECOMMENDED_BLOGS_VIEW_TYPE ->
if (isReaderImprovementsEnabled) {
ReaderRecommendedBlogsCardNewViewHolder(
Expand All @@ -60,6 +65,9 @@ class ReaderDiscoverAdapter(
parent, imageManager, uiHelpers
)
}

READER_ANNOUNCEMENT_TYPE -> ReaderAnnouncementCardViewHolder(parent)

else -> throw NotImplementedError("Unknown ViewType")
}
}
Expand Down Expand Up @@ -93,6 +101,7 @@ class ReaderDiscoverAdapter(
is ReaderPostNewUiState -> POST_NEW_VIEW_TYPE
is ReaderInterestsCardUiState -> INTEREST_VIEW_TYPE
is ReaderRecommendedBlogsCardUiState -> RECOMMENDED_BLOGS_VIEW_TYPE
is ReaderAnnouncementCardUiState -> READER_ANNOUNCEMENT_TYPE
}
}

Expand All @@ -115,14 +124,17 @@ class ReaderDiscoverAdapter(
is ReaderPostUiState -> {
oldItem.postId == (newItem as ReaderPostUiState).postId && oldItem.blogId == newItem.blogId
}

is ReaderPostNewUiState -> {
oldItem.postId == (newItem as ReaderPostNewUiState).postId && oldItem.blogId == newItem.blogId
}

is ReaderRecommendedBlogsCardUiState -> {
val newItemState = newItem as? ReaderRecommendedBlogsCardUiState
oldItem.blogs.map { it.blogId to it.feedId } == newItemState?.blogs?.map { it.blogId to it.feedId }
}
is ReaderInterestsCardUiState -> {

is ReaderInterestsCardUiState, is ReaderAnnouncementCardUiState -> {
oldItem == newItem
}
}
Expand Down
Loading
Loading