From d76e9b0bd8940f8afc038f0b1d59581d2f0324fd Mon Sep 17 00:00:00 2001 From: Stypox Date: Fri, 22 Dec 2023 12:50:32 +0100 Subject: [PATCH] Fix scrolling to correct comment after closing replies --- .../java/org/schabi/newpipe/MainActivity.java | 100 +++++++++++------- .../fragments/detail/VideoDetailFragment.java | 14 ++- .../list/comments/CommentsFragment.java | 10 +- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 5c56e867c..a096e7eaf 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -44,6 +44,7 @@ import android.widget.FrameLayout; import android.widget.Spinner; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AppCompatActivity; @@ -51,6 +52,7 @@ import androidx.core.app.ActivityCompat; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentContainerView; import androidx.fragment.app.FragmentManager; import androidx.preference.PreferenceManager; @@ -64,6 +66,7 @@ import org.schabi.newpipe.databinding.ToolbarLayoutBinding; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance; import org.schabi.newpipe.fragments.BackPressable; @@ -561,9 +564,7 @@ public class MainActivity extends AppCompatActivity { // Expand DetailsFragment if CommentRepliesFragment was opened // and no other CommentRepliesFragments are on top of the back stack // to show the top level comments again. - final FragmentManager.BackStackEntry bse = fm.getBackStackEntryAt( - fm.getBackStackEntryCount() - 2); // current fragment is at the top - openDetailFragmentFromCommentReplies(fm, bse); + openDetailFragmentFromCommentReplies(fm, false); } } else { @@ -646,10 +647,7 @@ public class MainActivity extends AppCompatActivity { // Expand DetailsFragment if CommentRepliesFragment was opened // and no other CommentRepliesFragments are on top of the back stack // to show the top level comments again. - fm.popBackStackImmediate(); - final FragmentManager.BackStackEntry bse = fm.getBackStackEntryAt( - fm.getBackStackEntryCount() - 1); - openDetailFragmentFromCommentReplies(fm, bse); + openDetailFragmentFromCommentReplies(fm, true); } else if (!NavigationHelper.tryGotoSearchFragment(fm)) { // If search fragment wasn't found in the backstack go to the main fragment NavigationHelper.gotoMainFragment(fm); @@ -850,38 +848,64 @@ public class MainActivity extends AppCompatActivity { private void openDetailFragmentFromCommentReplies( @NonNull final FragmentManager fm, - @NonNull final FragmentManager.BackStackEntry bse) { - if (!CommentRepliesFragment.TAG.equals(bse.getName())) { - final CommentRepliesFragment commentRepliesFragment = - (CommentRepliesFragment) fm.findFragmentByTag( - CommentRepliesFragment.TAG); - final BottomSheetBehavior bsb = BottomSheetBehavior - .from(mainBinding.fragmentPlayerHolder); - bsb.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { - @Override - public void onStateChanged(@NonNull final View bottomSheet, - final int newState) { - if (newState == BottomSheetBehavior.STATE_EXPANDED) { - final Fragment detailFragment = fm.findFragmentById( - R.id.fragment_player_holder); - if (detailFragment instanceof VideoDetailFragment - && commentRepliesFragment != null) { - // should always be the case - ((VideoDetailFragment) detailFragment).scrollToComment( - commentRepliesFragment.getCommentsInfoItem()); - } - bsb.removeBottomSheetCallback(this); - } - } - - @Override - public void onSlide(@NonNull final View bottomSheet, - final float slideOffset) { - // not needed, listener is removed once the sheet is expanded - } - }); - bsb.setState(BottomSheetBehavior.STATE_EXPANDED); + final boolean popBackStack + ) { + // obtain the name of the fragment under the replies fragment that's going to be popped + @Nullable final String fragmentUnderEntryName; + if (fm.getBackStackEntryCount() < 2) { + fragmentUnderEntryName = null; + } else { + fragmentUnderEntryName = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 2) + .getName(); } + + // the root comment is the comment for which the user opened the replies page + @Nullable final CommentRepliesFragment repliesFragment = + (CommentRepliesFragment) fm.findFragmentByTag(CommentRepliesFragment.TAG); + @Nullable final CommentsInfoItem rootComment = + repliesFragment == null ? null : repliesFragment.getCommentsInfoItem(); + + // sometimes this function pops the backstack, other times it's handled by the system + if (popBackStack) { + fm.popBackStackImmediate(); + } + + // only expand the bottom sheet back if there are no more nested comment replies fragments + // stacked under the one that is currently being popped + if (CommentRepliesFragment.TAG.equals(fragmentUnderEntryName)) { + return; + } + + final BottomSheetBehavior behavior = BottomSheetBehavior + .from(mainBinding.fragmentPlayerHolder); + // do not return to the comment if the details fragment was closed + if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) { + return; + } + + // scroll to the root comment once the bottom sheet expansion animation is finished + behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { + @Override + public void onStateChanged(@NonNull final View bottomSheet, + final int newState) { + if (newState == BottomSheetBehavior.STATE_EXPANDED) { + final Fragment detailFragment = fm.findFragmentById( + R.id.fragment_player_holder); + if (detailFragment instanceof VideoDetailFragment && rootComment != null) { + // should always be the case + ((VideoDetailFragment) detailFragment).scrollToComment(rootComment); + } + behavior.removeBottomSheetCallback(this); + } + } + + @Override + public void onSlide(@NonNull final View bottomSheet, final float slideOffset) { + // not needed, listener is removed once the sheet is expanded + } + }); + + behavior.setState(BottomSheetBehavior.STATE_EXPANDED); } private boolean bottomSheetHiddenOrCollapsed() { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index d607c5401..4da0a561e 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -1014,10 +1014,16 @@ public final class VideoDetailFragment } public void scrollToComment(final CommentsInfoItem comment) { - final Fragment fragment = pageAdapter.getItem( - pageAdapter.getItemPositionByTitle(COMMENTS_TAB_TAG)); - if (fragment instanceof CommentsFragment) { - ((CommentsFragment) fragment).scrollToComment(comment); + final int commentsTabPos = pageAdapter.getItemPositionByTitle(COMMENTS_TAB_TAG); + final Fragment fragment = pageAdapter.getItem(commentsTabPos); + if (!(fragment instanceof CommentsFragment)) { + return; + } + + // unexpand the app bar only if scrolling to the comment succeeded + if (((CommentsFragment) fragment).scrollToComment(comment)) { + binding.appBarLayout.setExpanded(false, false); + binding.viewPager.setCurrentItem(commentsTabPos, false); } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.java index 9481eba81..e25e02794 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentsFragment.java @@ -111,7 +111,13 @@ public class CommentsFragment extends BaseListInfoFragment