mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
#1812 Scroll the stories list to the last user read story once reading session ends
This commit is contained in:
parent
ae720e9947
commit
bea1140ea2
7 changed files with 107 additions and 14 deletions
|
@ -21,7 +21,7 @@ public class AllStoriesItemsList extends ItemsList {
|
|||
setIntent(intent);
|
||||
if (getIntent().getBooleanExtra(EXTRA_WIDGET_STORY, false)) {
|
||||
String hash = (String) getIntent().getSerializableExtra(EXTRA_STORY_HASH);
|
||||
UIUtils.startReadingActivity(fs, hash, this);
|
||||
UIUtils.startReadingActivity(this, fs, hash, readingActivityLaunch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,13 @@ import static com.newsblur.service.NBSyncReceiver.UPDATE_REBUILD;
|
|||
import static com.newsblur.service.NBSyncReceiver.UPDATE_STATUS;
|
||||
import static com.newsblur.service.NBSyncReceiver.UPDATE_STORY;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
@ -29,6 +34,7 @@ import com.newsblur.service.NBSyncService;
|
|||
import com.newsblur.util.AppConstants;
|
||||
import com.newsblur.util.FeedSet;
|
||||
import com.newsblur.util.FeedUtils;
|
||||
import com.newsblur.util.Log;
|
||||
import com.newsblur.util.ReadingActionListener;
|
||||
import com.newsblur.util.PrefsUtils;
|
||||
import com.newsblur.util.Session;
|
||||
|
@ -65,8 +71,13 @@ public abstract class ItemsList extends NbActivity implements ReadingActionListe
|
|||
private ItemListContextMenuDelegate contextMenuDelegate;
|
||||
@Nullable
|
||||
private SessionDataSource sessionDataSource;
|
||||
|
||||
@Override
|
||||
|
||||
@NonNull
|
||||
protected ActivityResultLauncher<Intent> readingActivityLaunch = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(), this::handleReadingActivityResult
|
||||
);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
Trace.beginSection("ItemsListOnCreate");
|
||||
super.onCreate(bundle);
|
||||
|
@ -84,11 +95,11 @@ public abstract class ItemsList extends NbActivity implements ReadingActionListe
|
|||
feedUtils.prepareReadingSession(this, fs, false);
|
||||
if (getIntent().getBooleanExtra(EXTRA_WIDGET_STORY, false)) {
|
||||
String hash = (String) getIntent().getSerializableExtra(EXTRA_STORY_HASH);
|
||||
UIUtils.startReadingActivity(fs, hash, this);
|
||||
UIUtils.startReadingActivity(this, fs, hash, readingActivityLaunch);
|
||||
} else if (PrefsUtils.isAutoOpenFirstUnread(this)) {
|
||||
StateFilter intelState = PrefsUtils.getStateFilter(this);
|
||||
if (dbHelper.getUnreadCount(fs, intelState) > 0) {
|
||||
UIUtils.startReadingActivity(fs, Reading.FIND_FIRST_UNREAD, this);
|
||||
UIUtils.startReadingActivity(this, fs, Reading.FIND_FIRST_UNREAD, readingActivityLaunch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,6 +296,20 @@ public abstract class ItemsList extends NbActivity implements ReadingActionListe
|
|||
itemSetFragment.scrollToTop();
|
||||
}
|
||||
|
||||
public void startReadingActivity(FeedSet feedSet, String storyHash) {
|
||||
UIUtils.startReadingActivity(this, feedSet, storyHash, readingActivityLaunch);
|
||||
}
|
||||
|
||||
private void handleReadingActivityResult(ActivityResult result) {
|
||||
if (result.getData() != null) {
|
||||
int lastReadingPosition = result.getData().getIntExtra(Reading.LAST_READING_POS, -1);
|
||||
if (lastReadingPosition > 1) {
|
||||
Log.d(this.getClass().getName(), "Scrolling to last reading position " + lastReadingPosition);
|
||||
itemSetFragment.scrollToPosition(lastReadingPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.newsblur.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
|
@ -10,6 +11,7 @@ import android.view.KeyEvent
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.commit
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
|
@ -32,8 +34,20 @@ import com.newsblur.service.NBSyncReceiver.Companion.UPDATE_REBUILD
|
|||
import com.newsblur.service.NBSyncReceiver.Companion.UPDATE_STATUS
|
||||
import com.newsblur.service.NBSyncReceiver.Companion.UPDATE_STORY
|
||||
import com.newsblur.service.NBSyncService
|
||||
import com.newsblur.util.*
|
||||
import com.newsblur.util.AppConstants
|
||||
import com.newsblur.util.CursorFilters
|
||||
import com.newsblur.util.DefaultFeedView
|
||||
import com.newsblur.util.FeedSet
|
||||
import com.newsblur.util.FeedUtils
|
||||
import com.newsblur.util.ImageLoader
|
||||
import com.newsblur.util.MarkStoryReadBehavior
|
||||
import com.newsblur.util.PrefConstants.ThemeValue
|
||||
import com.newsblur.util.PrefsUtils
|
||||
import com.newsblur.util.StateFilter
|
||||
import com.newsblur.util.UIUtils
|
||||
import com.newsblur.util.ViewUtils
|
||||
import com.newsblur.util.VolumeKeyNavigation
|
||||
import com.newsblur.util.executeAsyncTask
|
||||
import com.newsblur.view.ReadingScrollView.ScrollChangeListener
|
||||
import com.newsblur.viewModel.StoriesViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -42,7 +56,6 @@ import kotlinx.coroutines.Job
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.Runnable
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
|
@ -142,6 +155,7 @@ abstract class Reading : NbActivity(), OnPageChangeListener, ScrollChangeListene
|
|||
setupViews()
|
||||
setupListeners()
|
||||
setupObservers()
|
||||
setupOnBackPressed()
|
||||
getActiveStoriesCursor(this, true)
|
||||
}
|
||||
|
||||
|
@ -226,6 +240,17 @@ abstract class Reading : NbActivity(), OnPageChangeListener, ScrollChangeListene
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides on back pressed to use overridden [Reading.finish] method
|
||||
*/
|
||||
private fun setupOnBackPressed() {
|
||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(enabled = true) {
|
||||
override fun handleOnBackPressed() {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun getActiveStoriesCursor(context: Context, finishOnInvalidFs: Boolean = false) {
|
||||
fs?.let {
|
||||
val cursorFilters = CursorFilters(context, it)
|
||||
|
@ -843,6 +868,20 @@ abstract class Reading : NbActivity(), OnPageChangeListener, ScrollChangeListene
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the [Reading] finish method and
|
||||
* passes back the last read item position from the pager
|
||||
*/
|
||||
override fun finish() {
|
||||
setResult(Activity.RESULT_OK, Intent().apply {
|
||||
pager?.currentItem?.let { position ->
|
||||
com.newsblur.util.Log.d(this@Reading.javaClass.name, "Finish reading at position $position")
|
||||
putExtra(LAST_READING_POS, position)
|
||||
}
|
||||
})
|
||||
super.finish()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_FEEDSET = "feed_set"
|
||||
const val EXTRA_STORY_HASH = "story_hash"
|
||||
|
@ -857,5 +896,7 @@ abstract class Reading : NbActivity(), OnPageChangeListener, ScrollChangeListene
|
|||
|
||||
/** The minimum screen width (in DP) needed to show all the overlay controls. */
|
||||
private const val OVERLAY_MIN_WIDTH_DP = 355
|
||||
|
||||
const val LAST_READING_POS = "last_reading_pos"
|
||||
}
|
||||
}
|
|
@ -80,6 +80,7 @@ public class StoryViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
private final ExecutorService executorService;
|
||||
private final NbActivity context;
|
||||
private final ItemSetFragment fragment;
|
||||
private final OnStoryClickListener listener;
|
||||
private FeedSet fs;
|
||||
private StoryListStyle listStyle;
|
||||
private boolean ignoreReadStatus;
|
||||
|
@ -96,7 +97,8 @@ public class StoryViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
StoryListStyle listStyle,
|
||||
ImageLoader iconLoader,
|
||||
ImageLoader thumbnailLoader,
|
||||
FeedUtils feedUtils) {
|
||||
FeedUtils feedUtils,
|
||||
OnStoryClickListener listener) {
|
||||
this.context = context;
|
||||
this.fragment = fragment;
|
||||
this.fs = fs;
|
||||
|
@ -104,6 +106,7 @@ public class StoryViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
this.iconLoader = iconLoader;
|
||||
this.thumbnailLoader = thumbnailLoader;
|
||||
this.feedUtils = feedUtils;
|
||||
this.listener = listener;
|
||||
|
||||
if (fs.isGlobalShared()) {ignoreReadStatus = false; ignoreIntel = true; singleFeed = false;}
|
||||
if (fs.isAllSocial()) {ignoreReadStatus = false; ignoreIntel = false; singleFeed = false;}
|
||||
|
@ -392,7 +395,7 @@ public class StoryViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
return;
|
||||
}
|
||||
if (gestureL2R || gestureR2L) return;
|
||||
UIUtils.startReadingActivity(fs, story.storyHash, context);
|
||||
listener.onStoryClicked(fs, story.storyHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -817,4 +820,8 @@ public class StoryViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
notifyItemRangeChanged(0, getItemCount());
|
||||
}
|
||||
|
||||
public interface OnStoryClickListener {
|
||||
void onStoryClicked(FeedSet feedSet, String storyHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ public class ItemSetFragment extends NbFragment {
|
|||
}
|
||||
});
|
||||
|
||||
adapter = new StoryViewAdapter(((NbActivity) getActivity()), this, getFeedSet(), listStyle, iconLoader, thumbnailLoader, feedUtils);
|
||||
adapter = new StoryViewAdapter(((NbActivity) getActivity()), this, getFeedSet(), listStyle, iconLoader, thumbnailLoader, feedUtils, getOnStoryClickListener());
|
||||
adapter.addFooterView(footerView);
|
||||
adapter.addFooterView(fleuronBinding.getRoot());
|
||||
binding.itemgridfragmentGrid.setAdapter(adapter);
|
||||
|
@ -261,6 +261,13 @@ public class ItemSetFragment extends NbFragment {
|
|||
layoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
|
||||
public void scrollToPosition(int position) {
|
||||
int layoutTotalPositions = layoutManager.getItemCount() - 1;
|
||||
if (position > 0 && position <= layoutTotalPositions) {
|
||||
layoutManager.scrollToPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
protected FeedSet getFeedSet() {
|
||||
return ((ItemsList) getActivity()).getFeedSet();
|
||||
}
|
||||
|
@ -546,6 +553,13 @@ public class ItemSetFragment extends NbFragment {
|
|||
fleuronBinding.getRoot().setLayoutParams(newLayout);
|
||||
}
|
||||
|
||||
private StoryViewAdapter.OnStoryClickListener getOnStoryClickListener() {
|
||||
return (feedSet, storyHash) -> {
|
||||
ItemsList activity = ((ItemsList) getActivity());
|
||||
if (activity != null) activity.startReadingActivity(feedSet, storyHash);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState (Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
|
|
@ -135,7 +135,7 @@ abstract class ProfileActivityDetailsFragment : Fragment(), OnItemClickListener
|
|||
//context.startActivity(intent);
|
||||
}
|
||||
} else if (activity.category == ActivityDetails.Category.STAR) {
|
||||
UIUtils.startReadingActivity(FeedSet.allSaved(), activity.storyHash, context)
|
||||
UIUtils.startReadingActivity(context, FeedSet.allSaved(), activity.storyHash)
|
||||
} else if (isSocialFeedCategory(activity)) {
|
||||
// Strip the social: prefix from feedId
|
||||
val socialFeedId = activity.feedId.substring(7)
|
||||
|
@ -143,7 +143,7 @@ abstract class ProfileActivityDetailsFragment : Fragment(), OnItemClickListener
|
|||
if (feed == null) {
|
||||
Toast.makeText(context, R.string.profile_do_not_follow, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
UIUtils.startReadingActivity(FeedSet.singleSocialFeed(feed.userId, feed.username), activity.storyHash, context)
|
||||
UIUtils.startReadingActivity(context, FeedSet.singleSocialFeed(feed.userId, feed.username), activity.storyHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
@ -265,7 +266,11 @@ public class UIUtils {
|
|||
});
|
||||
}
|
||||
|
||||
public static void startReadingActivity(FeedSet fs, String startingHash, Context context) {
|
||||
public static void startReadingActivity(Context context, FeedSet fs, String startingHash) {
|
||||
startReadingActivity(context, fs, startingHash, null);
|
||||
}
|
||||
|
||||
public static void startReadingActivity(Context context, FeedSet fs, String startingHash, @Nullable ActivityResultLauncher<Intent> readingActivityLauncher) {
|
||||
Class activityClass;
|
||||
if (fs.isAllSaved()) {
|
||||
activityClass = SavedStoriesReading.class;
|
||||
|
@ -294,7 +299,8 @@ public class UIUtils {
|
|||
Intent i = new Intent(context, activityClass);
|
||||
i.putExtra(Reading.EXTRA_FEEDSET, fs);
|
||||
i.putExtra(Reading.EXTRA_STORY_HASH, startingHash);
|
||||
context.startActivity(i);
|
||||
if (readingActivityLauncher != null) readingActivityLauncher.launch(i);
|
||||
else context.startActivity(i);
|
||||
}
|
||||
|
||||
public static String getMemoryUsageDebug(Context context) {
|
||||
|
|
Loading…
Add table
Reference in a new issue