Skip to content

Commit

Permalink
Merge pull request #20467 from wordpress-mobile/experimental/hack-wee…
Browse files Browse the repository at this point in the history
…k-2024-03-11/refactor-notifications--viewpager2

Refactor notification detail activity to use ViewPager2
  • Loading branch information
jarvislin authored Apr 5, 2024
2 parents f833f0b + 10c9cef commit d8aceba
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
Expand All @@ -14,9 +13,10 @@
import androidx.appcompat.app.ActionBar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ViewModelProvider;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
Expand Down Expand Up @@ -66,7 +66,8 @@
import org.wordpress.android.util.extensions.AppBarLayoutExtensionsKt;
import org.wordpress.android.util.extensions.CompatExtensionsKt;
import org.wordpress.android.widgets.WPSwipeSnackbar;
import org.wordpress.android.widgets.WPViewPagerTransformer;
import org.wordpress.android.widgets.WPViewPager2Transformer;
import org.wordpress.android.widgets.WPViewPager2Transformer.TransformType.SlideOver;

import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -103,7 +104,7 @@ public class NotificationsDetailActivity extends LocaleAwareActivity implements
@Nullable private String mNoteId;
private boolean mIsTappedOnNotification;

@Nullable private ViewPager.OnPageChangeListener mOnPageChangeListener;
@Nullable private ViewPager2.OnPageChangeCallback mOnPageChangeListener;
@Nullable private NotificationDetailFragmentAdapter mAdapter;

@Nullable private NotificationsDetailActivityBinding mBinding = null;
Expand Down Expand Up @@ -155,8 +156,7 @@ public void handleOnBackPressed() {

// set up the viewpager and adapter for lateral navigation
if (mBinding != null) {
mBinding.viewpager.setPageTransformer(false,
new WPViewPagerTransformer(WPViewPagerTransformer.TransformType.SLIDE_OVER));
mBinding.viewpager.setPageTransformer(new WPViewPager2Transformer(SlideOver.INSTANCE));
}

Note note = NotificationsTable.getNoteById(mNoteId);
Expand Down Expand Up @@ -233,18 +233,18 @@ private void updateUIAndNote(boolean doRefresh) {
private void resetOnPageChangeListener() {
if (mOnPageChangeListener != null) {
if (mBinding != null) {
mBinding.viewpager.removeOnPageChangeListener(mOnPageChangeListener);
mBinding.viewpager.unregisterOnPageChangeCallback(mOnPageChangeListener);
}
} else {
mOnPageChangeListener = new ViewPager.OnPageChangeListener() {
mOnPageChangeListener = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}

@Override
public void onPageSelected(int position) {
if (mBinding != null && mAdapter != null) {
Fragment fragment = mAdapter.getItem(mBinding.viewpager.getCurrentItem());
Fragment fragment = mAdapter.createFragment(mBinding.viewpager.getCurrentItem());
boolean hideToolbar = (fragment instanceof ReaderPostDetailFragment);
showHideToolbar(hideToolbar);

Expand All @@ -268,7 +268,7 @@ public void onPageScrollStateChanged(int state) {
};
}
if (mBinding != null) {
mBinding.viewpager.addOnPageChangeListener(mOnPageChangeListener);
mBinding.viewpager.registerOnPageChangeCallback(mOnPageChangeListener);
}
}

Expand All @@ -281,14 +281,14 @@ private void trackCommentNote(@NonNull Note note) {
}

public void showHideToolbar(boolean hide) {
if (mBinding != null) {
setSupportActionBar(mBinding.toolbarMain);
}
if (getSupportActionBar() != null) {
if (hide) {
getSupportActionBar().hide();
} else {
if (mBinding != null) {
setSupportActionBar(mBinding.toolbarMain);
getSupportActionBar().show();
}
getSupportActionBar().show();
}
getSupportActionBar().setDisplayShowTitleEnabled(!hide);
}
Expand Down Expand Up @@ -320,7 +320,7 @@ protected void onStart() {
EventBus.getDefault().register(this);
// If the user hasn't used swipe yet and if the adapter is initialised and have at least 2 notifications,
// show a hint to promote swipe usage on the ViewPager
if (!AppPrefs.isNotificationsSwipeToNavigateShown() && mAdapter != null && mAdapter.getCount() > 1) {
if (!AppPrefs.isNotificationsSwipeToNavigateShown() && mAdapter != null && 1 < mAdapter.getItemCount()) {
if (mBinding != null) {
WPSwipeSnackbar.show(mBinding.viewpager);
AppPrefs.setNotificationsSwipeToNavigateShown(true);
Expand Down Expand Up @@ -380,11 +380,12 @@ private NotificationDetailFragmentAdapter buildNoteListAdapterAndSetPosition(Not
// apply filter to the list so we show the same items that the list show vertically, but horizontally
ArrayList<Note> filteredNotes = NotesAdapter.buildFilteredNotesList(notes, filter);

adapter = new NotificationDetailFragmentAdapter(getSupportFragmentManager(), filteredNotes);
adapter = new NotificationDetailFragmentAdapter(getSupportFragmentManager(), getLifecycle(), filteredNotes);

if (mBinding != null) {
mBinding.viewpager.setAdapter(adapter);
mBinding.viewpager.setCurrentItem(NotificationsUtils.findNoteInNoteArray(filteredNotes, note.getId()));
mBinding.viewpager.setCurrentItem(
NotificationsUtils.findNoteInNoteArray(filteredNotes, note.getId()), false);
}

return adapter;
Expand All @@ -395,8 +396,7 @@ private NotificationDetailFragmentAdapter buildNoteListAdapterAndSetPosition(Not
* Defaults to NotificationDetailListFragment
*/
@NonNull
@SuppressWarnings("deprecation")
private Fragment getDetailFragmentForNote(@NonNull Note note) {
private Fragment createDetailFragmentForNote(@NonNull Note note) {
Fragment fragment;
if (note.isCommentType()) {
// show comment detail for comment notifications
Expand Down Expand Up @@ -589,7 +589,7 @@ public void onEventMainThread(NotificationEvents.NotificationsRefreshError error
@Override
public void onPositiveClicked(@NonNull String instanceTag) {
if (mBinding != null && mAdapter != null) {
Fragment fragment = mAdapter.getItem(mBinding.viewpager.getCurrentItem());
Fragment fragment = mAdapter.createFragment(mBinding.viewpager.getCurrentItem());
if (fragment instanceof BasicFragmentDialog.BasicDialogPositiveClickInterface) {
((BasicDialogPositiveClickInterface) fragment).onPositiveClicked(instanceTag);
}
Expand All @@ -603,56 +603,30 @@ public void onScrollableViewInitialized(int containerId) {
}
}

@SuppressWarnings("deprecation")
private class NotificationDetailFragmentAdapter extends FragmentStatePagerAdapter {
private class NotificationDetailFragmentAdapter extends FragmentStateAdapter {
@NonNull
private final ArrayList<Note> mNoteList;

@SuppressWarnings("unchecked")
NotificationDetailFragmentAdapter(FragmentManager fm, ArrayList<Note> notes) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
NotificationDetailFragmentAdapter(@NonNull FragmentManager fm, @NonNull Lifecycle lifecycle,
@NonNull ArrayList<Note> notes) {
super(fm, lifecycle);
mNoteList = (ArrayList<Note>) notes.clone();
}

@NonNull
@Override
public Fragment getItem(int position) {
return getDetailFragmentForNote(mNoteList.get(position));
public Fragment createFragment(int position) {
return createDetailFragmentForNote(mNoteList.get(position));
}

@Override
public int getCount() {
public int getItemCount() {
return mNoteList.size();
}

@Override
public void restoreState(@Nullable Parcelable state, @Nullable ClassLoader loader) {
// work around "Fragment no longer exists for key" Android bug
// by catching the IllegalStateException
// https://code.google.com/p/android/issues/detail?id=42601
try {
AppLog.d(AppLog.T.NOTIFS, "notifications pager > adapter restoreState");
super.restoreState(state, loader);
} catch (IllegalStateException e) {
AppLog.e(AppLog.T.NOTIFS, e);
}
}

@Nullable
@Override
public Parcelable saveState() {
AppLog.d(AppLog.T.NOTIFS, "notifications pager > adapter saveState");
Bundle bundle = (Bundle) super.saveState();
if (bundle == null) {
bundle = new Bundle();
}
// This is a possible solution to https://github.com/wordpress-mobile/WordPress-Android/issues/5456
// See https://issuetracker.google.com/issues/37103380#comment77 for more details
bundle.putParcelableArray("states", null);
return bundle;
}

boolean isValidPosition(int position) {
return (position >= 0 && position < getCount());
return (position >= 0 && position < getItemCount());
}

private Note getNoteAtPosition(int position) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import android.view.ContextThemeWrapper
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
Expand All @@ -37,15 +36,13 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import androidx.core.view.MenuProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.commit
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.Factory
import androidx.recyclerview.widget.DefaultItemAnimator
Expand Down Expand Up @@ -172,7 +169,6 @@ import com.google.android.material.R as MaterialR
@Suppress("LargeClass")
class ReaderPostDetailFragment : ViewPagerFragment(),
WPMainActivity.OnActivityBackPressedListener,
MenuProvider,
ScrollDirectionListener,
ReaderCustomViewListener,
ReaderWebViewPageFinishedListener,
Expand Down Expand Up @@ -416,7 +412,6 @@ class ReaderPostDetailFragment : ViewPagerFragment(),
appBar = view.findViewById(R.id.appbar_with_collapsing_toolbar_layout)
toolBar = appBar.findViewById(R.id.toolbar_main)

toolBar.setVisible(true)
appBar.addOnOffsetChangedListener(appBarLayoutOffsetChangedListener)

// Fixes collapsing toolbar layout being obscured by the status bar when drawn behind it
Expand All @@ -429,7 +424,10 @@ class ReaderPostDetailFragment : ViewPagerFragment(),
}

// Fixes viewpager not displaying menu items for first fragment
val activity = activity as? AppCompatActivity
activity?.supportActionBar?.hide()
toolBar.inflateMenu(R.menu.reader_detail)
toolBar.setOnMenuItemClickListener { handleMenuItemSelected(it)}

// for related posts, show an X in the toolbar which closes the activity
if (isRelatedPost) {
Expand Down Expand Up @@ -534,24 +532,8 @@ class ReaderPostDetailFragment : ViewPagerFragment(),
activity?.window?.setWindowNavigationBarColor(themeValues.intBackgroundColor)
}

override fun onResume() {
super.onResume()
replaceActivityToolbarWithCollapsingToolbar()
}

private fun replaceActivityToolbarWithCollapsingToolbar() {
val activity = activity as? AppCompatActivity
activity?.supportActionBar?.hide()

toolBar.setVisible(true)
activity?.setSupportActionBar(toolBar)

activity?.supportActionBar?.setDisplayShowTitleEnabled(isRelatedPost)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)

initLikeFacesRecycler(savedInstanceState)
initCommentSnippetRecycler(savedInstanceState)
Expand Down Expand Up @@ -865,7 +847,7 @@ class ReaderPostDetailFragment : ViewPagerFragment(),
@Suppress("ForbiddenComment")
private fun onPostExecuteShowPost() {
// make sure options menu reflects whether we now have a post
activity?.invalidateOptionsMenu()
prepareMenu(toolBar.menu)

viewModel.post?.let {
if (handleDirectOperation()) return
Expand Down Expand Up @@ -1079,12 +1061,7 @@ class ReaderPostDetailFragment : ViewPagerFragment(),
moreMenuPopup?.dismiss()
}

override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menu.clear()
menuInflater.inflate(R.menu.reader_detail, menu)
}

override fun onPrepareMenu(menu: Menu) {
private fun prepareMenu(menu: Menu) {
val postHasUrl = viewModel.post?.hasUrl() == true
val menuBrowse = menu.findItem(R.id.menu_browse)
// browse require the post to have a URL (some feed-based posts don't have one) or an intercepted URI
Expand All @@ -1097,7 +1074,7 @@ class ReaderPostDetailFragment : ViewPagerFragment(),
menuReadingPreferences?.isVisible = readingPreferencesFeatureConfig.isEnabled()
}

override fun onMenuItemSelected(menuItem: MenuItem) = when (menuItem.itemId) {
private fun handleMenuItemSelected(menuItem: MenuItem) = when (menuItem.itemId) {
R.id.menu_browse -> {
val interceptedUri = viewModel.interceptedUri
if (viewModel.hasPost) {
Expand Down
Loading

0 comments on commit d8aceba

Please sign in to comment.