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 android.widget.Spinner;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
@ -51,6 +52,7 @@ import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat; import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentContainerView;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -64,6 +66,7 @@ import org.schabi.newpipe.databinding.ToolbarLayoutBinding;
import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService; 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.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance; import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.BackPressable;
@ -561,9 +564,7 @@ public class MainActivity extends AppCompatActivity {
// Expand DetailsFragment if CommentRepliesFragment was opened // Expand DetailsFragment if CommentRepliesFragment was opened
// and no other CommentRepliesFragments are on top of the back stack // and no other CommentRepliesFragments are on top of the back stack
// to show the top level comments again. // to show the top level comments again.
final FragmentManager.BackStackEntry bse = fm.getBackStackEntryAt( openDetailFragmentFromCommentReplies(fm, false);
fm.getBackStackEntryCount() - 2); // current fragment is at the top
openDetailFragmentFromCommentReplies(fm, bse);
} }
} else { } else {
@ -646,10 +647,7 @@ public class MainActivity extends AppCompatActivity {
// Expand DetailsFragment if CommentRepliesFragment was opened // Expand DetailsFragment if CommentRepliesFragment was opened
// and no other CommentRepliesFragments are on top of the back stack // and no other CommentRepliesFragments are on top of the back stack
// to show the top level comments again. // to show the top level comments again.
fm.popBackStackImmediate(); openDetailFragmentFromCommentReplies(fm, true);
final FragmentManager.BackStackEntry bse = fm.getBackStackEntryAt(
fm.getBackStackEntryCount() - 1);
openDetailFragmentFromCommentReplies(fm, bse);
} else if (!NavigationHelper.tryGotoSearchFragment(fm)) { } else if (!NavigationHelper.tryGotoSearchFragment(fm)) {
// If search fragment wasn't found in the backstack go to the main fragment // If search fragment wasn't found in the backstack go to the main fragment
NavigationHelper.gotoMainFragment(fm); NavigationHelper.gotoMainFragment(fm);
@ -850,38 +848,64 @@ public class MainActivity extends AppCompatActivity {
private void openDetailFragmentFromCommentReplies( private void openDetailFragmentFromCommentReplies(
@NonNull final FragmentManager fm, @NonNull final FragmentManager fm,
@NonNull final FragmentManager.BackStackEntry bse) { final boolean popBackStack
if (!CommentRepliesFragment.TAG.equals(bse.getName())) { ) {
final CommentRepliesFragment commentRepliesFragment = // obtain the name of the fragment under the replies fragment that's going to be popped
(CommentRepliesFragment) fm.findFragmentByTag( @Nullable final String fragmentUnderEntryName;
CommentRepliesFragment.TAG); if (fm.getBackStackEntryCount() < 2) {
final BottomSheetBehavior bsb = BottomSheetBehavior fragmentUnderEntryName = null;
.from(mainBinding.fragmentPlayerHolder); } else {
bsb.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { fragmentUnderEntryName = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 2)
@Override .getName();
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);
} }
// 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() { private boolean bottomSheetHiddenOrCollapsed() {

View file

@ -1014,10 +1014,16 @@ public final class VideoDetailFragment
} }
public void scrollToComment(final CommentsInfoItem comment) { public void scrollToComment(final CommentsInfoItem comment) {
final Fragment fragment = pageAdapter.getItem( final int commentsTabPos = pageAdapter.getItemPositionByTitle(COMMENTS_TAB_TAG);
pageAdapter.getItemPositionByTitle(COMMENTS_TAB_TAG)); final Fragment fragment = pageAdapter.getItem(commentsTabPos);
if (fragment instanceof CommentsFragment) { if (!(fragment instanceof CommentsFragment)) {
((CommentsFragment) fragment).scrollToComment(comment); 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; return ItemViewMode.LIST;
} }
public void scrollToComment(final CommentsInfoItem comment) { public boolean scrollToComment(final CommentsInfoItem comment) {
itemsList.scrollToPosition(infoListAdapter.getItemsList().indexOf(comment)); final int position = infoListAdapter.getItemsList().indexOf(comment);
if (position < 0) {
return false;
}
itemsList.scrollToPosition(position);
return true;
} }
} }