Add setting to show/hide notification filter bar (#1314)
* Add setting to show/hide notification filter bar tuskyapp/Tusky#1306 * Remove not required requestLayout * Fix notifications reload issue
This commit is contained in:
parent
a6819ce28e
commit
ce501f24e6
|
@ -32,6 +32,23 @@ import android.widget.ListView;
|
||||||
import android.widget.PopupWindow;
|
import android.widget.PopupWindow;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.arch.core.util.Function;
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import androidx.core.util.Pair;
|
||||||
|
import androidx.lifecycle.Lifecycle;
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig;
|
||||||
|
import androidx.recyclerview.widget.AsyncListDiffer;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.ListUpdateCallback;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import com.google.android.material.appbar.AppBarLayout;
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.keylesspalace.tusky.R;
|
import com.keylesspalace.tusky.R;
|
||||||
|
@ -75,21 +92,6 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.arch.core.util.Function;
|
|
||||||
import androidx.core.util.Pair;
|
|
||||||
import androidx.lifecycle.Lifecycle;
|
|
||||||
import androidx.recyclerview.widget.AsyncDifferConfig;
|
|
||||||
import androidx.recyclerview.widget.AsyncListDiffer;
|
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.ListUpdateCallback;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import at.connyduck.sparkbutton.helpers.Utils;
|
import at.connyduck.sparkbutton.helpers.Utils;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
@ -160,6 +162,7 @@ public class NotificationsFragment extends SFragment implements
|
||||||
private boolean bottomLoading;
|
private boolean bottomLoading;
|
||||||
private String bottomId;
|
private String bottomId;
|
||||||
private boolean alwaysShowSensitiveMedia;
|
private boolean alwaysShowSensitiveMedia;
|
||||||
|
private boolean showNotificationsFilter;
|
||||||
|
|
||||||
// Each element is either a Notification for loading data or a Placeholder
|
// Each element is either a Notification for loading data or a Placeholder
|
||||||
private final PairedList<Either<Placeholder, Notification>, NotificationViewData> notifications
|
private final PairedList<Either<Placeholder, Notification>, NotificationViewData> notifications
|
||||||
|
@ -192,6 +195,14 @@ public class NotificationsFragment extends SFragment implements
|
||||||
View rootView = inflater.inflate(R.layout.fragment_timeline_notifications, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_timeline_notifications, container, false);
|
||||||
|
|
||||||
@NonNull Context context = inflater.getContext(); // from inflater to silence warning
|
@NonNull Context context = inflater.getContext(); // from inflater to silence warning
|
||||||
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
|
|
||||||
|
boolean showNotificationsFilterSetting = preferences.getBoolean("showNotificationsFilter", true);
|
||||||
|
//Clear notifications on filter visibility change to force refresh
|
||||||
|
if (showNotificationsFilterSetting != showNotificationsFilter)
|
||||||
|
notifications.clear();
|
||||||
|
showNotificationsFilter = showNotificationsFilterSetting;
|
||||||
|
|
||||||
// Setup the SwipeRefreshLayout.
|
// Setup the SwipeRefreshLayout.
|
||||||
swipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout);
|
swipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout);
|
||||||
recyclerView = rootView.findViewById(R.id.recyclerView);
|
recyclerView = rootView.findViewById(R.id.recyclerView);
|
||||||
|
@ -224,7 +235,6 @@ public class NotificationsFragment extends SFragment implements
|
||||||
|
|
||||||
adapter = new NotificationsAdapter(accountManager.getActiveAccount().getAccountId(),
|
adapter = new NotificationsAdapter(accountManager.getActiveAccount().getAccountId(),
|
||||||
dataSource, this, this);
|
dataSource, this, this);
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
|
||||||
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
|
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
|
||||||
boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled();
|
boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled();
|
||||||
adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
|
adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
|
||||||
|
@ -255,10 +265,28 @@ public class NotificationsFragment extends SFragment implements
|
||||||
|
|
||||||
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
|
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
|
||||||
|
|
||||||
|
updateFilterVisibility();
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void confirmClearNotifications(){
|
private void updateFilterVisibility() {
|
||||||
|
CoordinatorLayout.LayoutParams params =
|
||||||
|
(CoordinatorLayout.LayoutParams) swipeRefreshLayout.getLayoutParams();
|
||||||
|
if (showNotificationsFilter) {
|
||||||
|
appBarOptions.setExpanded(true, false);
|
||||||
|
appBarOptions.setVisibility(View.VISIBLE);
|
||||||
|
//Set content behaviour to hide filter on scroll
|
||||||
|
params.setBehavior(new AppBarLayout.ScrollingViewBehavior());
|
||||||
|
} else {
|
||||||
|
appBarOptions.setExpanded(false, false);
|
||||||
|
appBarOptions.setVisibility(View.GONE);
|
||||||
|
//Clear behaviour to hide app bar
|
||||||
|
params.setBehavior(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmClearNotifications() {
|
||||||
new AlertDialog.Builder(getContext())
|
new AlertDialog.Builder(getContext())
|
||||||
.setMessage(R.string.notification_clear_text)
|
.setMessage(R.string.notification_clear_text)
|
||||||
.setPositiveButton(android.R.string.yes, (DialogInterface dia, int which) -> clearNotifications())
|
.setPositiveButton(android.R.string.yes, (DialogInterface dia, int which) -> clearNotifications())
|
||||||
|
@ -583,18 +611,7 @@ public class NotificationsFragment extends SFragment implements
|
||||||
private void clearNotifications() {
|
private void clearNotifications() {
|
||||||
//Cancel all ongoing requests
|
//Cancel all ongoing requests
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
for (Call callItem : callList) {
|
resetNotificationsLoad();
|
||||||
callItem.cancel();
|
|
||||||
}
|
|
||||||
callList.clear();
|
|
||||||
bottomLoading = false;
|
|
||||||
topLoading = false;
|
|
||||||
|
|
||||||
//Disable load more
|
|
||||||
bottomId = null;
|
|
||||||
|
|
||||||
//Clear exists notifications
|
|
||||||
notifications.clear();
|
|
||||||
|
|
||||||
//Show friend elephant
|
//Show friend elephant
|
||||||
this.statusView.setVisibility(View.VISIBLE);
|
this.statusView.setVisibility(View.VISIBLE);
|
||||||
|
@ -625,6 +642,21 @@ public class NotificationsFragment extends SFragment implements
|
||||||
callList.add(call);
|
callList.add(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resetNotificationsLoad() {
|
||||||
|
for (Call callItem : callList) {
|
||||||
|
callItem.cancel();
|
||||||
|
}
|
||||||
|
callList.clear();
|
||||||
|
bottomLoading = false;
|
||||||
|
topLoading = false;
|
||||||
|
|
||||||
|
//Disable load more
|
||||||
|
bottomId = null;
|
||||||
|
|
||||||
|
//Clear exists notifications
|
||||||
|
notifications.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showFilterMenu() {
|
private void showFilterMenu() {
|
||||||
List<Notification.Type> notificationsList = Notification.Type.Companion.getAsList();
|
List<Notification.Type> notificationsList = Notification.Type.Companion.getAsList();
|
||||||
|
@ -751,6 +783,13 @@ public class NotificationsFragment extends SFragment implements
|
||||||
fullyRefresh();
|
fullyRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "showNotificationsFilter": {
|
||||||
|
if (isAdded()) {
|
||||||
|
showNotificationsFilter = PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showNotificationsFilter", true);
|
||||||
|
updateFilterVisibility();
|
||||||
|
fullyRefreshWithProgressBar(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,7 +844,7 @@ public class NotificationsFragment extends SFragment implements
|
||||||
|
|
||||||
private void jumpToTop() {
|
private void jumpToTop() {
|
||||||
if (isAdded()) {
|
if (isAdded()) {
|
||||||
appBarOptions.setExpanded(true,false);
|
appBarOptions.setExpanded(true, false);
|
||||||
layoutManager.scrollToPosition(0);
|
layoutManager.scrollToPosition(0);
|
||||||
scrollListener.reset();
|
scrollListener.reset();
|
||||||
}
|
}
|
||||||
|
@ -828,7 +867,7 @@ public class NotificationsFragment extends SFragment implements
|
||||||
bottomLoading = true;
|
bottomLoading = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Call<List<Notification>> call = mastodonApi.notifications(fromId, uptoId, LOAD_AT_ONCE, notificationFilter);
|
Call<List<Notification>> call = mastodonApi.notifications(fromId, uptoId, LOAD_AT_ONCE, showNotificationsFilter ? notificationFilter : null);
|
||||||
|
|
||||||
call.enqueue(new Callback<List<Notification>>() {
|
call.enqueue(new Callback<List<Notification>>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -844,7 +883,8 @@ public class NotificationsFragment extends SFragment implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NonNull Call<List<Notification>> call, @NonNull Throwable t) {
|
public void onFailure(@NonNull Call<List<Notification>> call, @NonNull Throwable t) {
|
||||||
onFetchNotificationsFailure((Exception) t, fetchEnd, pos);
|
if (!call.isCanceled())
|
||||||
|
onFetchNotificationsFailure((Exception) t, fetchEnd, pos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
callList.add(call);
|
callList.add(call);
|
||||||
|
@ -853,9 +893,15 @@ public class NotificationsFragment extends SFragment implements
|
||||||
private void onFetchNotificationsSuccess(List<Notification> notifications, String linkHeader,
|
private void onFetchNotificationsSuccess(List<Notification> notifications, String linkHeader,
|
||||||
FetchEnd fetchEnd, int pos) {
|
FetchEnd fetchEnd, int pos) {
|
||||||
List<HttpHeaderLink> links = HttpHeaderLink.parse(linkHeader);
|
List<HttpHeaderLink> links = HttpHeaderLink.parse(linkHeader);
|
||||||
|
HttpHeaderLink next = HttpHeaderLink.findByRelationType(links, "next");
|
||||||
|
String fromId = null;
|
||||||
|
if (next != null) {
|
||||||
|
fromId = next.uri.getQueryParameter("max_id");
|
||||||
|
}
|
||||||
|
|
||||||
switch (fetchEnd) {
|
switch (fetchEnd) {
|
||||||
case TOP: {
|
case TOP: {
|
||||||
update(notifications, null);
|
update(notifications, this.notifications.isEmpty() ? fromId : null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MIDDLE: {
|
case MIDDLE: {
|
||||||
|
@ -863,11 +909,6 @@ public class NotificationsFragment extends SFragment implements
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BOTTOM: {
|
case BOTTOM: {
|
||||||
HttpHeaderLink next = HttpHeaderLink.findByRelationType(links, "next");
|
|
||||||
String fromId = null;
|
|
||||||
if (next != null) {
|
|
||||||
fromId = next.uri.getQueryParameter("max_id");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.notifications.isEmpty()
|
if (!this.notifications.isEmpty()
|
||||||
&& !this.notifications.get(this.notifications.size() - 1).isRight()) {
|
&& !this.notifications.get(this.notifications.size() - 1).isRight()) {
|
||||||
|
@ -1026,8 +1067,8 @@ public class NotificationsFragment extends SFragment implements
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fullyRefreshWithProgressBar(boolean isShow) {
|
private void fullyRefreshWithProgressBar(boolean isShow) {
|
||||||
notifications.clear();
|
resetNotificationsLoad();
|
||||||
if (isShow && notifications.isEmpty()) {
|
if (isShow) {
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
statusView.setVisibility(View.GONE);
|
statusView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,4 +513,5 @@
|
||||||
<string name="report_description_1">The report will be sent to your server moderator. You can provide an explanation of why you are reporting this account below:</string>
|
<string name="report_description_1">The report will be sent to your server moderator. You can provide an explanation of why you are reporting this account below:</string>
|
||||||
<string name="report_description_remote_instance">The account is from another server. Send an anonymized copy of the report there as well?</string>
|
<string name="report_description_remote_instance">The account is from another server. Send an anonymized copy of the report there as well?</string>
|
||||||
|
|
||||||
|
<string name="pref_title_show_notifications_filter">Show Notifications filter</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -55,6 +55,12 @@
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="animateGifAvatars"
|
android:key="animateGifAvatars"
|
||||||
android:title="@string/pref_title_animate_gif_avatars" />
|
android:title="@string/pref_title_animate_gif_avatars" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="showNotificationsFilter"
|
||||||
|
android:title="@string/pref_title_show_notifications_filter" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/pref_title_browser_settings">
|
<PreferenceCategory android:title="@string/pref_title_browser_settings">
|
||||||
|
|
Loading…
Reference in New Issue