Fix scrolling to correct comment after closing replies

This commit is contained in:
Stypox 2023-12-22 12:50:32 +01:00
parent b4016c91c1
commit d76e9b0bd8
No known key found for this signature in database
GPG key ID: 4BDF1B40A49FDD23
3 changed files with 80 additions and 44 deletions

View file

@ -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<FragmentContainerView> 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() {

View file

@ -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);
}
}

View file

@ -111,7 +111,13 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfoItem, Com
return ItemViewMode.LIST;
}
public void scrollToComment(final CommentsInfoItem comment) {
itemsList.scrollToPosition(infoListAdapter.getItemsList().indexOf(comment));
public boolean scrollToComment(final CommentsInfoItem comment) {
final int position = infoListAdapter.getItemsList().indexOf(comment);
if (position < 0) {
return false;
}
itemsList.scrollToPosition(position);
return true;
}
}