Added option to scroll to top on new messages

pull/156/head
M66B 6 years ago
parent da87251d51
commit 7e36de7733

@ -1220,7 +1220,8 @@ By selecting a zero snooze duration you can cancel snoozing.
**(69) Can you add auto scroll up on new message?**
The message list is automatically scrolled up when navigating from a new message notification or after a manual refresh.
Always automatically scrolling up on arrival of new messages would interfere with your own navigation and scrolling.
Always automatically scrolling up on arrival of new messages would interfere with your own scrolling,
but if you like you can enable this in the advanced options.
<br />

@ -136,6 +136,7 @@ public class FragmentMessages extends FragmentBase {
private boolean date;
private boolean threading;
private boolean pull;
private boolean autoscroll;
private boolean actionbar;
private boolean autoexpand;
private boolean autoclose;
@ -148,6 +149,8 @@ public class FragmentMessages extends FragmentBase {
private String searching = null;
private boolean refresh = false;
private boolean manual = false;
private Integer lastUnseen = null;
private AdapterMessage adapter;
private AdapterMessage.ViewType viewType;
@ -233,6 +236,7 @@ public class FragmentMessages extends FragmentBase {
else
pull = false;
autoscroll = prefs.getBoolean("autoscroll", false);
date = prefs.getBoolean("date", true);
threading = prefs.getBoolean("threading", true);
actionbar = prefs.getBoolean("actionbar", true);
@ -1715,45 +1719,8 @@ public class FragmentMessages extends FragmentBase {
public void onChanged(List<TupleFolderEx> folders) {
if (folders == null)
folders = new ArrayList<>();
Log.i("Folder state updated count=" + folders.size());
int unseen = 0;
boolean sync = false;
boolean errors = false;
for (TupleFolderEx folder : folders) {
unseen += folder.unseen;
if (folder.synchronize)
sync = true;
if (folder.error != null)
errors = true;
}
if (unseen > 0)
setSubtitle(getString(R.string.title_name_count,
getString(R.string.title_folder_unified),
nf.format(unseen)));
else
setSubtitle(getString(R.string.title_folder_unified));
boolean refreshing = false;
for (TupleFolderEx folder : folders)
if (folder.sync_state != null &&
(folder.account == null || "connected".equals(folder.accountState))) {
refreshing = true;
break;
}
if (!refreshing && manual) {
manual = false;
rvMessage.scrollToPosition(0);
}
if (errors && !refreshing && swipeRefresh.isRefreshing())
Snackbar.make(view, R.string.title_sync_errors, Snackbar.LENGTH_LONG).show();
refresh = sync;
swipeRefresh.setEnabled(pull && refresh);
swipeRefresh.setRefreshing(refreshing);
updateState(folders);
}
});
db.message().liveHidden(null).observe(getViewLifecycleOwner(), new Observer<List<Long>>() {
@ -1770,16 +1737,11 @@ public class FragmentMessages extends FragmentBase {
db.folder().liveFolderEx(folder).observe(getViewLifecycleOwner(), new Observer<TupleFolderEx>() {
@Override
public void onChanged(@Nullable TupleFolderEx folder) {
Log.i("Folder state updated");
if (folder == null)
setSubtitle(null);
else {
if (folder.unseen > 0)
setSubtitle(getString(R.string.title_name_count,
folder.getDisplayName(getContext()),
nf.format(folder.unseen)));
else
setSubtitle(folder.getDisplayName(getContext()));
List<TupleFolderEx> folders = new ArrayList<>();
if (folder != null)
folders.add(folder);
updateState(folders);
boolean outbox = EntityFolder.OUTBOX.equals(folder.type);
if (FragmentMessages.this.outbox != outbox) {
@ -1787,21 +1749,6 @@ public class FragmentMessages extends FragmentBase {
getActivity().invalidateOptionsMenu();
}
}
boolean refreshing = (folder != null && folder.sync_state != null &&
(folder.account == null || "connected".equals(folder.accountState)));
if (!refreshing && manual) {
manual = false;
rvMessage.scrollToPosition(0);
}
if (folder != null && folder.error != null && !refreshing && swipeRefresh.isRefreshing())
Snackbar.make(view, folder.error, Snackbar.LENGTH_LONG).show();
refresh = (folder != null);
swipeRefresh.setEnabled(pull && refresh);
swipeRefresh.setRefreshing(refreshing);
}
});
db.message().liveHidden(folder).observe(getViewLifecycleOwner(), new Observer<List<Long>>() {
@Override
@ -2213,6 +2160,67 @@ public class FragmentMessages extends FragmentBase {
}.execute(this, args, "messages:all");
}
private void updateState(List<TupleFolderEx> folders) {
Log.i("Folder state updated count=" + folders.size());
// Get state
int unseen = 0;
boolean sync = false;
boolean errors = false;
boolean refreshing = false;
for (TupleFolderEx folder : folders) {
unseen += folder.unseen;
if (folder.synchronize)
sync = true;
if (folder.error != null)
errors = true;
if (folder.sync_state != null &&
(folder.account == null || "connected".equals(folder.accountState))) {
refreshing = true;
break;
}
}
// Get name
String name;
if (viewType == AdapterMessage.ViewType.UNIFIED)
name = getString(R.string.title_folder_unified);
else
name = (folders.size() > 0 ? folders.get(0).getDisplayName(getContext()) : "");
// Show name/unread
if (unseen == 0)
setSubtitle(name);
else
setSubtitle(getString(R.string.title_name_count, name, nf.format(unseen)));
// Auto scroll
if (lastUnseen == null || lastUnseen != unseen) {
if ((!refreshing && manual) ||
(autoscroll && lastUnseen != null && lastUnseen < unseen))
// Delay to let list update
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
rvMessage.scrollToPosition(0);
}
}, 3000);
manual = false;
lastUnseen = unseen;
}
// Show errors
if (errors && !refreshing && swipeRefresh.isRefreshing())
if (folders.size() == 1)
Snackbar.make(view, folders.get(0).error, Snackbar.LENGTH_LONG).show();
else
Snackbar.make(view, R.string.title_sync_errors, Snackbar.LENGTH_LONG).show();
refresh = sync;
swipeRefresh.setEnabled(pull && refresh);
swipeRefresh.setRefreshing(refreshing);
}
private void loadMessages() {
if (viewType == AdapterMessage.ViewType.THREAD && autonext) {
ViewModelMessages model = ViewModelProviders.of(getActivity()).get(ViewModelMessages.class);

@ -91,6 +91,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
private SwitchCompat swActionbar;
private SwitchCompat swPull;
private SwitchCompat swAutoScroll;
private SwitchCompat swSwipeNav;
private SwitchCompat swAutoExpand;
private SwitchCompat swAutoClose;
@ -125,7 +126,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
static String[] OPTIONS_RESTART = new String[]{
"startup", "date", "threading", "avatars", "identicons", "circular", "name_email", "subject_italic", "flags", "preview",
"addresses", "monospaced", "autohtml", "autoimages", "actionbar",
"pull", "swipenav", "autoexpand", "autoclose", "autonext",
"pull", "autoscroll", "swipenav", "autoexpand", "autoclose", "autonext",
"subscriptions",
"authentication", "debug"
};
@ -135,7 +136,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
"metered", "download", "roaming",
"startup", "date", "threading", "avatars", "identicons", "circular", "name_email", "subject_italic", "flags", "preview",
"addresses", "monospaced", "autohtml", "autoimages", "actionbar",
"pull", "swipenav", "autoexpand", "autoclose", "autonext", "collapse", "autoread", "automove",
"pull", "autoscroll", "swipenav", "autoexpand", "autoclose", "autonext", "collapse", "autoread", "automove",
"autoresize", "resize", "prefix_once", "autosend",
"badge", "subscriptions", "notify_preview", "search_local", "light", "sound",
"authentication", "paranoid", "english", "updates", "debug",
@ -181,6 +182,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
swActionbar = view.findViewById(R.id.swActionbar);
swPull = view.findViewById(R.id.swPull);
swAutoScroll = view.findViewById(R.id.swAutoScroll);
swSwipeNav = view.findViewById(R.id.swSwipeNav);
swAutoExpand = view.findViewById(R.id.swAutoExpand);
swAutoClose = view.findViewById(R.id.swAutoClose);
@ -443,6 +445,13 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
}
});
swAutoScroll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("autoscroll", checked).apply();
}
});
swSwipeNav.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@ -753,6 +762,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
swActionbar.setChecked(prefs.getBoolean("actionbar", true));
swPull.setChecked(prefs.getBoolean("pull", true));
swAutoScroll.setChecked(prefs.getBoolean("autoscroll", false));
swSwipeNav.setChecked(prefs.getBoolean("swipenav", true));
swAutoExpand.setChecked(prefs.getBoolean("autoexpand", true));
swAutoClose.setChecked(prefs.getBoolean("autoclose", true));

@ -577,6 +577,18 @@
app:layout_constraintTop_toBottomOf="@id/vSeparatorBehavior"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swAutoScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:text="@string/title_advanced_autoscroll"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swPull"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swSwipeNav"
android:layout_width="match_parent"
@ -586,7 +598,7 @@
android:layout_marginEnd="12dp"
android:text="@string/title_advanced_swipenav"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swPull"
app:layout_constraintTop_toBottomOf="@id/swAutoScroll"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat

@ -183,6 +183,7 @@
<string name="title_advanced_actionbar">Conversation action bar</string>
<string name="title_advanced_pull_refresh">Pull down to refresh</string>
<string name="title_advanced_autoscroll">Scroll to top on receiving new messages</string>
<string name="title_advanced_swipenav">Swipe left/right to go to next/previous conversation</string>
<string name="title_advanced_autoexpand">Automatically expand messages</string>
<string name="title_advanced_collapse">Collapse messages in conversations on \'back\'</string>

Loading…
Cancel
Save