Cancel notifications on opening notifications tab (#450)

This commit is contained in:
Ivan Kupalov 2017-11-13 21:05:23 +03:00 committed by Konrad Pozniak
parent a58ac243a3
commit ddc4954f8a
7 changed files with 84 additions and 57 deletions

View File

@ -187,15 +187,6 @@ public class BaseActivity extends AppCompatActivity {
JobManager.instance().cancelAllForTag(NotificationPullJobCreator.NOTIFICATIONS_JOB_TAG); JobManager.instance().cancelAllForTag(NotificationPullJobCreator.NOTIFICATIONS_JOB_TAG);
} }
protected void clearNotifications() {
SharedPreferences notificationPreferences =
getApplicationContext().getSharedPreferences("Notifications", MODE_PRIVATE);
notificationPreferences.edit().putString("current", "[]").apply();
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(NotificationPullJobCreator.NOTIFY_ID);
}
protected void setPullNotificationCheckInterval(long minutes) { protected void setPullNotificationCheckInterval(long minutes) {
JobManager.instance().cancelAllForTag(NotificationPullJobCreator.NOTIFICATIONS_JOB_TAG); JobManager.instance().cancelAllForTag(NotificationPullJobCreator.NOTIFICATIONS_JOB_TAG);
long checkInterval = 1000 * 60 * minutes; long checkInterval = 1000 * 60 * minutes;

View File

@ -40,7 +40,7 @@ import com.keylesspalace.tusky.entity.AccessToken;
import com.keylesspalace.tusky.entity.AppCredentials; import com.keylesspalace.tusky.entity.AppCredentials;
import com.keylesspalace.tusky.network.MastodonApi; import com.keylesspalace.tusky.network.MastodonApi;
import com.keylesspalace.tusky.util.CustomTabsHelper; import com.keylesspalace.tusky.util.CustomTabsHelper;
import com.keylesspalace.tusky.util.NotificationMaker; import com.keylesspalace.tusky.util.NotificationManager;
import com.keylesspalace.tusky.util.OkHttpUtils; import com.keylesspalace.tusky.util.OkHttpUtils;
import java.util.HashMap; import java.util.HashMap;
@ -396,7 +396,7 @@ public class LoginActivity extends AppCompatActivity {
} }
//create notification channels ahead of time so users can edit the settings //create notification channels ahead of time so users can edit the settings
NotificationMaker.createNotificationChannels(this); NotificationManager.createNotificationChannels(this);
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
startActivity(intent); startActivity(intent);

View File

@ -41,6 +41,7 @@ import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.interfaces.ActionButtonActivity; import com.keylesspalace.tusky.interfaces.ActionButtonActivity;
import com.keylesspalace.tusky.pager.TimelinePagerAdapter; import com.keylesspalace.tusky.pager.TimelinePagerAdapter;
import com.keylesspalace.tusky.receiver.TimelineReceiver; import com.keylesspalace.tusky.receiver.TimelineReceiver;
import com.keylesspalace.tusky.util.NotificationManager;
import com.keylesspalace.tusky.util.ThemeUtils; import com.keylesspalace.tusky.util.ThemeUtils;
import com.mikepenz.google_material_typeface_library.GoogleMaterial; import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.materialdrawer.AccountHeader; import com.mikepenz.materialdrawer.AccountHeader;
@ -225,7 +226,7 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
clearNotifications(); NotificationManager.clearNotifications(this);
/* After editing a profile, the profile header in the navigation drawer needs to be /* After editing a profile, the profile header in the navigation drawer needs to be
* refreshed */ * refreshed */

View File

@ -29,7 +29,7 @@ import com.keylesspalace.tusky.entity.Notification;
import com.keylesspalace.tusky.json.SpannedTypeAdapter; import com.keylesspalace.tusky.json.SpannedTypeAdapter;
import com.keylesspalace.tusky.network.AuthInterceptor; import com.keylesspalace.tusky.network.AuthInterceptor;
import com.keylesspalace.tusky.network.MastodonApi; import com.keylesspalace.tusky.network.MastodonApi;
import com.keylesspalace.tusky.util.NotificationMaker; import com.keylesspalace.tusky.util.NotificationManager;
import com.keylesspalace.tusky.util.OkHttpUtils; import com.keylesspalace.tusky.util.OkHttpUtils;
import java.io.IOException; import java.io.IOException;
@ -48,8 +48,8 @@ import retrofit2.converter.gson.GsonConverterFactory;
public final class NotificationPullJobCreator implements JobCreator { public final class NotificationPullJobCreator implements JobCreator {
public static final int NOTIFY_ID = 6; // chosen by fair dice roll, guaranteed to be random
static final String NOTIFICATIONS_JOB_TAG = "notifications_job_tag"; static final String NOTIFICATIONS_JOB_TAG = "notifications_job_tag";
static final int NOTIFY_ID = 6; // chosen by fair dice roll, guaranteed to be random
private Context context; private Context context;
@ -130,7 +130,7 @@ public final class NotificationPullJobCreator implements JobCreator {
String id = notification.id; String id = notification.id;
if (!currentIds.contains(id)) { if (!currentIds.contains(id)) {
currentIds.add(id); currentIds.add(id);
NotificationMaker.make(context, NOTIFY_ID, notification); NotificationManager.make(context, NOTIFY_ID, notification);
} }
} }
notificationsPreferences.edit() notificationsPreferences.edit()

View File

@ -15,6 +15,8 @@
package com.keylesspalace.tusky.fragment; package com.keylesspalace.tusky.fragment;
import android.app.Activity;
import android.app.NotificationManager;
import android.arch.core.util.Function; import android.arch.core.util.Function;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -36,6 +38,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.keylesspalace.tusky.MainActivity; import com.keylesspalace.tusky.MainActivity;
import com.keylesspalace.tusky.NotificationPullJobCreator;
import com.keylesspalace.tusky.adapter.FooterViewHolder; import com.keylesspalace.tusky.adapter.FooterViewHolder;
import com.keylesspalace.tusky.adapter.NotificationsAdapter; import com.keylesspalace.tusky.adapter.NotificationsAdapter;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
@ -129,12 +132,12 @@ public class NotificationsFragment extends SFragment implements
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_timeline, container, false); View rootView = inflater.inflate(R.layout.fragment_timeline, container, false);
@NonNull Context context = inflater.getContext(); // from inflater to silence warning
// Setup the SwipeRefreshLayout. // Setup the SwipeRefreshLayout.
Context context = getContext();
swipeRefreshLayout = rootView.findViewById(R.id.swipe_refresh_layout); swipeRefreshLayout = rootView.findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(this); swipeRefreshLayout.setOnRefreshListener(this);
// Setup the RecyclerView. // Setup the RecyclerView.
@ -176,6 +179,7 @@ public class NotificationsFragment extends SFragment implements
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
MainActivity activity = (MainActivity) getActivity(); MainActivity activity = (MainActivity) getActivity();
if (activity == null) throw new AssertionError("Activity is null");
// MainActivity's layout is guaranteed to be inflated until onCreate returns. // MainActivity's layout is guaranteed to be inflated until onCreate returns.
TabLayout layout = activity.findViewById(R.id.tab_layout); TabLayout layout = activity.findViewById(R.id.tab_layout);
@ -232,15 +236,30 @@ public class NotificationsFragment extends SFragment implements
@Override @Override
public void onDestroyView() { public void onDestroyView() {
TabLayout tabLayout = getActivity().findViewById(R.id.tab_layout); Activity activity = getActivity();
tabLayout.removeOnTabSelectedListener(onTabSelectedListener); if (activity == null) {
Log.e(TAG, "Activity is null");
} else {
TabLayout tabLayout = activity.findViewById(R.id.tab_layout);
tabLayout.removeOnTabSelectedListener(onTabSelectedListener);
LocalBroadcastManager.getInstance(getContext()) LocalBroadcastManager.getInstance(activity)
.unregisterReceiver(timelineReceiver); .unregisterReceiver(timelineReceiver);
}
super.onDestroyView(); super.onDestroyView();
} }
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
//noinspection ConstantConditions
((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE))
.cancel(NotificationPullJobCreator.NOTIFY_ID);
}
}
@Override @Override
public void onRefresh() { public void onRefresh() {
sendFetchNotificationsRequest(null, topId, FetchEnd.TOP, -1); sendFetchNotificationsRequest(null, topId, FetchEnd.TOP, -1);

View File

@ -25,7 +25,7 @@ import android.support.annotation.XmlRes;
import com.keylesspalace.tusky.BuildConfig; import com.keylesspalace.tusky.BuildConfig;
import com.keylesspalace.tusky.PreferencesActivity; import com.keylesspalace.tusky.PreferencesActivity;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.util.NotificationMaker; import com.keylesspalace.tusky.util.NotificationManager;
public class PreferencesFragment extends PreferenceFragment { public class PreferencesFragment extends PreferenceFragment {
@ -56,7 +56,7 @@ public class PreferencesFragment extends PreferenceFragment {
//on Android O and newer, launch the system notification settings instead of the app settings //on Android O and newer, launch the system notification settings instead of the app settings
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationMaker.createNotificationChannels(getContext()); NotificationManager.createNotificationChannels(getContext());
notificationPreferences.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { notificationPreferences.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override @Override

View File

@ -16,7 +16,6 @@
package com.keylesspalace.tusky.util; package com.keylesspalace.tusky.util;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -33,6 +32,7 @@ import android.support.v4.content.ContextCompat;
import android.util.Log; import android.util.Log;
import com.keylesspalace.tusky.MainActivity; import com.keylesspalace.tusky.MainActivity;
import com.keylesspalace.tusky.NotificationPullJobCreator;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Notification; import com.keylesspalace.tusky.entity.Notification;
import com.keylesspalace.tusky.receiver.NotificationClearBroadcastReceiver; import com.keylesspalace.tusky.receiver.NotificationClearBroadcastReceiver;
@ -46,22 +46,24 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class NotificationMaker { public class NotificationManager {
private static final String TAG = "NotificationMaker"; private static final String TAG = "NotificationManager";
/** notification channels used on Android O+ **/ /**
* notification channels used on Android O+
**/
private static final String CHANNEL_MENTION = "CHANNEL_MENTION"; private static final String CHANNEL_MENTION = "CHANNEL_MENTION";
private static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW"; private static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW";
private static final String CHANNEL_BOOST = "CHANNEL_BOOST"; private static final String CHANNEL_BOOST = "CHANNEL_BOOST";
private static final String CHANNEL_FAVOURITE =" CHANNEL_FAVOURITE"; private static final String CHANNEL_FAVOURITE = " CHANNEL_FAVOURITE";
/** /**
* Takes a given Mastodon notification and either creates a new Android notification or updates * Takes a given Mastodon notification and either creates a new Android notification or updates
* the state of the existing notification to reflect the new interaction. * the state of the existing notification to reflect the new interaction.
* *
* @param context to access application preferences and services * @param context to access application preferences and services
* @param notifyId an arbitrary number to reference this notification for any future action * @param notifyId an arbitrary number to reference this notification for any future action
* @param body a new Mastodon notification * @param body a new Mastodon notification
*/ */
public static void make(final Context context, final int notifyId, Notification body) { public static void make(final Context context, final int notifyId, Notification body) {
final SharedPreferences preferences = final SharedPreferences preferences =
@ -86,7 +88,7 @@ public class NotificationMaker {
boolean alreadyContains = false; boolean alreadyContains = false;
for(int i = 0; i < currentNotifications.length(); i++) { for (int i = 0; i < currentNotifications.length(); i++) {
try { try {
if (currentNotifications.getString(i).equals(body.account.getDisplayName())) { if (currentNotifications.getString(i).equals(body.account.getDisplayName())) {
alreadyContains = true; alreadyContains = true;
@ -102,7 +104,7 @@ public class NotificationMaker {
notificationPreferences.edit() notificationPreferences.edit()
.putString("current", currentNotifications.toString()) .putString("current", currentNotifications.toString())
.commit(); .apply();
Intent resultIntent = new Intent(context, MainActivity.class); Intent resultIntent = new Intent(context, MainActivity.class);
resultIntent.putExtra("tab_position", 1); resultIntent.putExtra("tab_position", 1);
@ -160,16 +162,17 @@ public class NotificationMaker {
builder.setCategory(android.app.Notification.CATEGORY_SOCIAL); builder.setCategory(android.app.Notification.CATEGORY_SOCIAL);
} }
NotificationManager notificationManager = android.app.NotificationManager notificationManager = (android.app.NotificationManager)
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); context.getSystemService(Context.NOTIFICATION_SERVICE);
//noinspection ConstantConditions
notificationManager.notify(notifyId, builder.build()); notificationManager.notify(notifyId, builder.build());
} }
public static void createNotificationChannels(Context context) { public static void createNotificationChannels(Context context) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager = android.app.NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); (android.app.NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String[] channelIds = new String[]{CHANNEL_MENTION, CHANNEL_FOLLOW, CHANNEL_BOOST, CHANNEL_FAVOURITE}; String[] channelIds = new String[]{CHANNEL_MENTION, CHANNEL_FOLLOW, CHANNEL_BOOST, CHANNEL_FAVOURITE};
int[] channelNames = { int[] channelNames = {
@ -187,11 +190,11 @@ public class NotificationMaker {
List<NotificationChannel> channels = new ArrayList<>(4); List<NotificationChannel> channels = new ArrayList<>(4);
for(int i=0; i<channelIds.length; i++) { for (int i = 0; i < channelIds.length; i++) {
String id = channelIds[i]; String id = channelIds[i];
String name = context.getString(channelNames[i]); String name = context.getString(channelNames[i]);
String description = context.getString(channelDescriptions[i]); String description = context.getString(channelDescriptions[i]);
int importance = NotificationManager.IMPORTANCE_DEFAULT; int importance = android.app.NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(id, name, importance); NotificationChannel channel = new NotificationChannel(id, name, importance);
channel.setDescription(description); channel.setDescription(description);
@ -201,19 +204,31 @@ public class NotificationMaker {
channels.add(channel); channels.add(channel);
} }
//noinspection ConstantConditions
mNotificationManager.createNotificationChannels(channels); mNotificationManager.createNotificationChannels(channels);
} }
} }
private static boolean filterNotification(SharedPreferences preferences, public static void clearNotifications(Context context) {
Notification notification) { SharedPreferences notificationPreferences =
context.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
notificationPreferences.edit().putString("current", "[]").apply();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { android.app.NotificationManager manager = (android.app.NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
//noinspection ConstantConditions
manager.cancel(NotificationPullJobCreator.NOTIFY_ID);
}
private static boolean filterNotification(SharedPreferences preferences,
Notification notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return true; //do not filter on Android O or newer, the system does it for us return true; //do not filter on Android O or newer, the system does it for us
} }
switch (notification.type) { switch (notification.type) {
default: default:
case MENTION: case MENTION:
return preferences.getBoolean("notificationFilterMentions", true); return preferences.getBoolean("notificationFilterMentions", true);
@ -227,20 +242,21 @@ public class NotificationMaker {
} }
private static String getChannelId(Notification notification) { private static String getChannelId(Notification notification) {
switch (notification.type) { switch (notification.type) {
default: default:
case MENTION: case MENTION:
return CHANNEL_MENTION; return CHANNEL_MENTION;
case FOLLOW: case FOLLOW:
return CHANNEL_FOLLOW; return CHANNEL_FOLLOW;
case REBLOG: case REBLOG:
return CHANNEL_BOOST; return CHANNEL_BOOST;
case FAVOURITE: case FAVOURITE:
return CHANNEL_FAVOURITE; return CHANNEL_FAVOURITE;
} }
} }
@SuppressWarnings("SameParameterValue")
private static String truncateWithEllipses(String string, int limit) { private static String truncateWithEllipses(String string, int limit) {
if (string.length() < limit) { if (string.length() < limit) {
return string; return string;
@ -250,9 +266,9 @@ public class NotificationMaker {
} }
private static void setupPreferences(SharedPreferences preferences, private static void setupPreferences(SharedPreferences preferences,
NotificationCompat.Builder builder) { NotificationCompat.Builder builder) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return; //do nothing on Android O or newer, the system uses the channel settings anyway return; //do nothing on Android O or newer, the system uses the channel settings anyway
} }
@ -261,7 +277,7 @@ public class NotificationMaker {
} }
if (preferences.getBoolean("notificationAlertVibrate", false)) { if (preferences.getBoolean("notificationAlertVibrate", false)) {
builder.setVibrate(new long[] { 500, 500 }); builder.setVibrate(new long[]{500, 500});
} }
if (preferences.getBoolean("notificationAlertLight", false)) { if (preferences.getBoolean("notificationAlertLight", false)) {