2017-03-12 18:31:20 +11:00
|
|
|
package com.keylesspalace.tusky;
|
|
|
|
|
|
|
|
import android.app.NotificationManager;
|
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
import android.provider.Settings;
|
|
|
|
import android.support.v4.app.NotificationCompat;
|
|
|
|
import android.support.v4.app.TaskStackBuilder;
|
|
|
|
import android.text.Spanned;
|
|
|
|
|
|
|
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
|
|
|
import com.google.firebase.messaging.RemoteMessage;
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
import com.google.gson.GsonBuilder;
|
|
|
|
import com.keylesspalace.tusky.entity.Notification;
|
|
|
|
import com.squareup.picasso.Picasso;
|
|
|
|
import com.squareup.picasso.Target;
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
import org.json.JSONArray;
|
|
|
|
import org.json.JSONException;
|
|
|
|
|
2017-03-12 18:31:20 +11:00
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
import okhttp3.Interceptor;
|
|
|
|
import okhttp3.OkHttpClient;
|
|
|
|
import okhttp3.Request;
|
|
|
|
import retrofit2.Call;
|
|
|
|
import retrofit2.Callback;
|
|
|
|
import retrofit2.Response;
|
|
|
|
import retrofit2.Retrofit;
|
|
|
|
import retrofit2.converter.gson.GsonConverterFactory;
|
|
|
|
|
|
|
|
public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
|
|
|
private MastodonAPI mastodonAPI;
|
|
|
|
private static final String TAG = "MyFirebaseMessagingService";
|
2017-03-15 00:31:52 +11:00
|
|
|
public static final int NOTIFY_ID = 666;
|
2017-03-12 18:31:20 +11:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onMessageReceived(RemoteMessage remoteMessage) {
|
|
|
|
Log.d(TAG, remoteMessage.getFrom());
|
|
|
|
Log.d(TAG, remoteMessage.toString());
|
|
|
|
|
|
|
|
String notificationId = remoteMessage.getData().get("notification_id");
|
|
|
|
|
|
|
|
if (notificationId == null) {
|
|
|
|
Log.e(TAG, "No notification ID in payload!!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Log.d(TAG, notificationId);
|
|
|
|
|
2017-03-20 13:38:39 +11:00
|
|
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
|
|
|
|
getApplicationContext());
|
2017-03-16 09:45:59 +11:00
|
|
|
boolean enabled = preferences.getBoolean("notificationsEnabled", true);
|
|
|
|
if (!enabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-12 18:31:20 +11:00
|
|
|
createMastodonAPI();
|
|
|
|
|
|
|
|
mastodonAPI.notification(notificationId).enqueue(new Callback<Notification>() {
|
|
|
|
@Override
|
|
|
|
public void onResponse(Call<Notification> call, Response<Notification> response) {
|
2017-03-14 11:49:12 +11:00
|
|
|
if (response.isSuccessful()) {
|
|
|
|
buildNotification(response.body());
|
|
|
|
}
|
2017-03-12 18:31:20 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onFailure(Call<Notification> call, Throwable t) {
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void createMastodonAPI() {
|
|
|
|
SharedPreferences preferences = getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
|
|
|
final String domain = preferences.getString("domain", null);
|
|
|
|
final String accessToken = preferences.getString("accessToken", null);
|
|
|
|
|
|
|
|
OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
|
|
|
.addInterceptor(new Interceptor() {
|
|
|
|
@Override
|
|
|
|
public okhttp3.Response intercept(Chain chain) throws IOException {
|
|
|
|
Request originalRequest = chain.request();
|
|
|
|
|
|
|
|
Request.Builder builder = originalRequest.newBuilder()
|
|
|
|
.header("Authorization", String.format("Bearer %s", accessToken));
|
|
|
|
|
|
|
|
Request newRequest = builder.build();
|
|
|
|
|
|
|
|
return chain.proceed(newRequest);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
|
|
|
|
Gson gson = new GsonBuilder()
|
|
|
|
.registerTypeAdapter(Spanned.class, new SpannedTypeAdapter())
|
|
|
|
.create();
|
|
|
|
|
|
|
|
Retrofit retrofit = new Retrofit.Builder()
|
|
|
|
.baseUrl("https://" + domain)
|
|
|
|
.client(okHttpClient)
|
|
|
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
|
|
|
.build();
|
|
|
|
|
|
|
|
mastodonAPI = retrofit.create(MastodonAPI.class);
|
|
|
|
}
|
|
|
|
|
|
|
|
private String truncateWithEllipses(String string, int limit) {
|
|
|
|
if (string.length() < limit) {
|
|
|
|
return string;
|
|
|
|
} else {
|
|
|
|
return string.substring(0, limit - 3) + "...";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 06:39:29 +11:00
|
|
|
private static boolean filterNotification(SharedPreferences preferences,
|
|
|
|
Notification notification) {
|
|
|
|
switch (notification.type) {
|
|
|
|
default:
|
|
|
|
case MENTION: {
|
|
|
|
return preferences.getBoolean("notificationFilterMentions", true);
|
|
|
|
}
|
|
|
|
case FOLLOW: {
|
|
|
|
return preferences.getBoolean("notificationFilterFollows", true);
|
|
|
|
}
|
|
|
|
case REBLOG: {
|
|
|
|
return preferences.getBoolean("notificationFilterReblogs", true);
|
|
|
|
}
|
|
|
|
case FAVOURITE: {
|
|
|
|
return preferences.getBoolean("notificationFilterFavourites", true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-12 18:31:20 +11:00
|
|
|
private void buildNotification(Notification body) {
|
2017-03-12 18:49:38 +11:00
|
|
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
2017-03-15 00:31:52 +11:00
|
|
|
final SharedPreferences notificationPreferences = getApplicationContext().getSharedPreferences("Notifications", MODE_PRIVATE);
|
|
|
|
|
2017-03-29 06:39:29 +11:00
|
|
|
if (!filterNotification(preferences, body)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
String rawCurrentNotifications = notificationPreferences.getString("current", "[]");
|
|
|
|
JSONArray currentNotifications;
|
|
|
|
|
|
|
|
try {
|
|
|
|
currentNotifications = new JSONArray(rawCurrentNotifications);
|
|
|
|
} catch (JSONException e) {
|
|
|
|
currentNotifications = new JSONArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean alreadyContains = false;
|
|
|
|
|
|
|
|
for(int i = 0; i < currentNotifications.length(); i++) {
|
|
|
|
try {
|
|
|
|
if (currentNotifications.getString(i).equals(body.account.displayName)) {
|
|
|
|
alreadyContains = true;
|
|
|
|
}
|
|
|
|
} catch (JSONException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 06:39:29 +11:00
|
|
|
if (!alreadyContains) {
|
|
|
|
currentNotifications.put(body.account.displayName);
|
|
|
|
}
|
2017-03-15 00:31:52 +11:00
|
|
|
|
|
|
|
SharedPreferences.Editor editor = notificationPreferences.edit();
|
|
|
|
editor.putString("current", currentNotifications.toString());
|
|
|
|
editor.commit();
|
2017-03-12 18:31:20 +11:00
|
|
|
|
|
|
|
Intent resultIntent = new Intent(this, MainActivity.class);
|
|
|
|
resultIntent.putExtra("tab_position", 1);
|
|
|
|
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
|
|
|
stackBuilder.addParentStack(MainActivity.class);
|
|
|
|
stackBuilder.addNextIntent(resultIntent);
|
|
|
|
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
|
2017-03-16 09:45:59 +11:00
|
|
|
Intent deleteIntent = new Intent(this, NotificationClearBroadcastReceiver.class);
|
|
|
|
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(this, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
|
|
|
|
2017-03-12 18:31:20 +11:00
|
|
|
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
|
|
|
|
.setSmallIcon(R.drawable.ic_notify)
|
2017-03-12 18:49:38 +11:00
|
|
|
.setContentIntent(resultPendingIntent)
|
2017-03-16 09:45:59 +11:00
|
|
|
.setDeleteIntent(deletePendingIntent)
|
2017-03-12 18:49:38 +11:00
|
|
|
.setDefaults(0); // So it doesn't ring twice, notify only in Target callback
|
2017-03-12 18:31:20 +11:00
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
if (currentNotifications.length() == 1) {
|
|
|
|
builder.setContentTitle(titleForType(body))
|
|
|
|
.setContentText(truncateWithEllipses(bodyForType(body), 40));
|
2017-03-12 18:31:20 +11:00
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
Target mTarget = new Target() {
|
|
|
|
@Override
|
|
|
|
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
|
|
|
|
builder.setLargeIcon(bitmap);
|
2017-03-12 18:49:38 +11:00
|
|
|
|
2017-03-15 05:24:38 +11:00
|
|
|
setupPreferences(preferences, builder);
|
2017-03-15 00:31:52 +11:00
|
|
|
|
|
|
|
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).notify(NOTIFY_ID, builder.build());
|
2017-03-12 18:49:38 +11:00
|
|
|
}
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
@Override
|
|
|
|
public void onBitmapFailed(Drawable errorDrawable) {
|
2017-03-12 18:31:20 +11:00
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
}
|
2017-03-12 18:31:20 +11:00
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
@Override
|
|
|
|
public void onPrepareLoad(Drawable placeHolderDrawable) {
|
2017-03-12 18:31:20 +11:00
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
}
|
|
|
|
};
|
2017-03-12 18:31:20 +11:00
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
Picasso.with(this)
|
|
|
|
.load(body.account.avatar)
|
|
|
|
.placeholder(R.drawable.avatar_default)
|
|
|
|
.transform(new RoundedTransformation(7, 0))
|
|
|
|
.into(mTarget);
|
|
|
|
} else {
|
2017-03-15 05:24:38 +11:00
|
|
|
setupPreferences(preferences, builder);
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
try {
|
|
|
|
builder.setContentTitle(String.format(getString(R.string.notification_title_summary), currentNotifications.length()))
|
|
|
|
.setContentText(truncateWithEllipses(joinNames(currentNotifications), 40));
|
|
|
|
} catch (JSONException e) {
|
|
|
|
e.printStackTrace();
|
2017-03-12 18:31:20 +11:00
|
|
|
}
|
2017-03-15 00:31:52 +11:00
|
|
|
}
|
2017-03-12 18:31:20 +11:00
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
|
|
builder.setVisibility(android.app.Notification.VISIBILITY_PRIVATE);
|
|
|
|
builder.setCategory(android.app.Notification.CATEGORY_SOCIAL);
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).notify(NOTIFY_ID, builder.build());
|
|
|
|
}
|
|
|
|
|
2017-03-15 05:24:38 +11:00
|
|
|
private void setupPreferences(SharedPreferences preferences, NotificationCompat.Builder builder) {
|
|
|
|
if (preferences.getBoolean("notificationAlertSound", true)) {
|
|
|
|
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
|
|
|
|
}
|
|
|
|
|
2017-03-29 06:39:29 +11:00
|
|
|
if (preferences.getBoolean("notificationAlertVibrate", false)) {
|
2017-03-15 05:24:38 +11:00
|
|
|
builder.setVibrate(new long[] { 500, 500 });
|
|
|
|
}
|
|
|
|
|
2017-03-29 06:39:29 +11:00
|
|
|
if (preferences.getBoolean("notificationAlertLight", false)) {
|
2017-03-15 05:24:38 +11:00
|
|
|
builder.setLights(0xFF00FF8F, 300, 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
private String joinNames(JSONArray array) throws JSONException {
|
|
|
|
if (array.length() > 3) {
|
|
|
|
return String.format(getString(R.string.notification_summary_large), array.get(0), array.get(1), array.get(2), array.length() - 3);
|
|
|
|
} else if (array.length() == 3) {
|
|
|
|
return String.format(getString(R.string.notification_summary_medium), array.get(0), array.get(1), array.get(2));
|
|
|
|
} else if (array.length() == 2) {
|
|
|
|
return String.format(getString(R.string.notification_summary_small), array.get(0), array.get(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private String titleForType(Notification notification) {
|
|
|
|
switch (notification.type) {
|
2017-03-12 18:31:20 +11:00
|
|
|
case MENTION:
|
2017-03-15 00:31:52 +11:00
|
|
|
return String.format(getString(R.string.notification_mention_format), notification.account.getDisplayName());
|
|
|
|
case FOLLOW:
|
|
|
|
return String.format(getString(R.string.notification_follow_format), notification.account.getDisplayName());
|
|
|
|
case FAVOURITE:
|
|
|
|
return String.format(getString(R.string.notification_favourite_format), notification.account.getDisplayName());
|
|
|
|
case REBLOG:
|
|
|
|
return String.format(getString(R.string.notification_reblog_format), notification.account.getDisplayName());
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private String bodyForType(Notification notification) {
|
|
|
|
switch (notification.type) {
|
2017-03-12 18:31:20 +11:00
|
|
|
case FOLLOW:
|
2017-03-15 00:31:52 +11:00
|
|
|
return notification.account.username;
|
|
|
|
case MENTION:
|
2017-03-12 18:31:20 +11:00
|
|
|
case FAVOURITE:
|
|
|
|
case REBLOG:
|
2017-03-15 00:31:52 +11:00
|
|
|
return notification.status.content.toString();
|
2017-03-12 18:31:20 +11:00
|
|
|
}
|
|
|
|
|
2017-03-15 00:31:52 +11:00
|
|
|
return null;
|
2017-03-12 18:31:20 +11:00
|
|
|
}
|
|
|
|
}
|