diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 395885cfc6..8d133a0481 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -180,24 +180,15 @@
- 2
-
- - #ffF44336
- - #ffE91E63
- - #ff9C27B0
- - #ff673AB7
- - #ff3F51B5
- - #ff2196F3
- - #ff03A9F4
- - #ff00BCD4
- - #ff009688
- - #ff4CAF50
- - #ff8BC34A
-
- - #FFFFC107
- - #ffFF9800
- - #ffFF5722
- - #ff795548
- - #ff607D8B
-
+
+ - @string/arrays__name_and_message
+ - @string/arrays__name_only
+ - @string/arrays__neither
+
+
+ - all
+ - contact
+ - none
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0c6dac0a86..f92883ecfa 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -467,7 +467,7 @@
Lock with passphrase
- %1$d messages in %2$d conversations
+ %1$d new messages in %2$d conversations
Most recent from: %1$s
Locked message...
Media message: %s
@@ -484,6 +484,10 @@
Quick response unavailable when TextSecure is locked!
Problem sending message!
+
+ New TextSecure message
+ Contents hidden
+
OLD PASSPHRASE:
NEW PASSPHRASE:
@@ -754,6 +758,10 @@
Enabled
Disabled
+ Name and message
+ Name only
+ Neither
+
- %d hour
@@ -858,6 +866,7 @@
\'WiFi Calling\' compatibility mode
Enable if your device uses SMS/MMS delivery over WiFi (only enable when \'WiFi Calling\' is enabled on your device)
Blocked contacts
+ Display in notifications
diff --git a/res/xml/preferences_notifications.xml b/res/xml/preferences_notifications.xml
index 5abc24ac93..c894abaf8b 100644
--- a/res/xml/preferences_notifications.xml
+++ b/res/xml/preferences_notifications.xml
@@ -36,7 +36,6 @@
android:entries="@array/pref_led_blink_pattern_entries"
android:entryValues="@array/pref_led_blink_pattern_values" />
-
+ android:key="pref_repeat_alerts"
+ android:defaultValue="0"
+ android:title="@string/preferences__repeat_alerts"
+ android:dependency="pref_key_enable_notifications"
+ android:entries="@array/pref_repeat_alerts_entries"
+ android:entryValues="@array/pref_repeat_alerts_values" />
+
+
+
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java
new file mode 100644
index 0000000000..1ad3f7d243
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java
@@ -0,0 +1,70 @@
+package org.thoughtcrime.securesms.notifications;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.NotificationCompat;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+
+import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase;
+import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
+import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+import org.thoughtcrime.securesms.util.Util;
+
+public abstract class AbstractNotificationBuilder extends NotificationCompat.Builder {
+
+ protected Context context;
+ protected NotificationPrivacyPreference privacy;
+
+ public AbstractNotificationBuilder(Context context, NotificationPrivacyPreference privacy) {
+ super(context);
+
+ this.context = context;
+ this.privacy = privacy;
+ }
+
+ protected CharSequence getStyledMessage(@NonNull Recipient recipient, @Nullable CharSequence message) {
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ builder.append(Util.getBoldedString(recipient.toShortString()));
+ builder.append(": ");
+ builder.append(message == null ? "" : message);
+
+ return builder;
+ }
+
+ public void setAlarms(@Nullable Uri ringtone, RecipientPreferenceDatabase.VibrateState vibrate) {
+ String defaultRingtoneName = TextSecurePreferences.getNotificationRingtone(context);
+ boolean defaultVibrate = TextSecurePreferences.isNotificationVibrateEnabled(context);
+ String ledColor = TextSecurePreferences.getNotificationLedColor(context);
+ String ledBlinkPattern = TextSecurePreferences.getNotificationLedPattern(context);
+ String ledBlinkPatternCustom = TextSecurePreferences.getNotificationLedPatternCustom(context);
+ String[] blinkPatternArray = parseBlinkPattern(ledBlinkPattern, ledBlinkPatternCustom);
+
+ if (ringtone != null) setSound(ringtone);
+ else if (TextUtils.isEmpty(defaultRingtoneName)) setSound(Uri.parse(defaultRingtoneName));
+
+ if (vibrate == RecipientPreferenceDatabase.VibrateState.ENABLED ||
+ (vibrate == RecipientPreferenceDatabase.VibrateState.DEFAULT && defaultVibrate))
+ {
+ setDefaults(Notification.DEFAULT_VIBRATE);
+ }
+
+ if (!ledColor.equals("none")) {
+ setLights(Color.parseColor(ledColor),
+ Integer.parseInt(blinkPatternArray[0]),
+ Integer.parseInt(blinkPatternArray[1]));
+ }
+ }
+
+ private String[] parseBlinkPattern(String blinkPattern, String blinkPatternCustom) {
+ if (blinkPattern.equals("custom"))
+ blinkPattern = blinkPatternCustom;
+
+ return blinkPattern.split(",");
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/notifications/FailedNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/FailedNotificationBuilder.java
new file mode 100644
index 0000000000..7491316a3f
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/notifications/FailedNotificationBuilder.java
@@ -0,0 +1,30 @@
+package org.thoughtcrime.securesms.notifications;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase;
+import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
+
+public class FailedNotificationBuilder extends AbstractNotificationBuilder {
+
+ public FailedNotificationBuilder(Context context, NotificationPrivacyPreference privacy, Intent intent) {
+ super(context, privacy);
+
+ setSmallIcon(R.drawable.icon_notification);
+ setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.ic_action_warning_red));
+ setContentTitle(context.getString(R.string.MessageNotifier_message_delivery_failed));
+ setContentText(context.getString(R.string.MessageNotifier_failed_to_deliver_message));
+ setTicker(context.getString(R.string.MessageNotifier_error_delivering_message));
+ setContentIntent(PendingIntent.getActivity(context, 0, intent, 0));
+ setAutoCancel(true);
+ setAlarms(null, RecipientPreferenceDatabase.VibrateState.DEFAULT);
+ }
+
+
+
+}
diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
index c324481f87..285f49acea 100644
--- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
+++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
@@ -17,43 +17,29 @@
package org.thoughtcrime.securesms.notifications;
import android.app.AlarmManager;
-import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationCompat.Action;
-import android.support.v4.app.NotificationCompat.BigTextStyle;
-import android.support.v4.app.NotificationCompat.InboxStyle;
-import android.support.v4.app.RemoteInput;
import android.text.Spannable;
import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.Log;
import org.thoughtcrime.securesms.ConversationActivity;
-import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.PushDatabase;
-import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
@@ -61,7 +47,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.KeyCachingService;
-import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
@@ -82,6 +67,7 @@ import me.leolin.shortcutbadger.ShortcutBadger;
*/
public class MessageNotifier {
+
private static final String TAG = MessageNotifier.class.getSimpleName();
public static final int NOTIFICATION_ID = 1338;
@@ -101,19 +87,9 @@ public class MessageNotifier {
Intent intent = new Intent(context, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
- intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
-
- NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
- builder.setSmallIcon(R.drawable.icon_notification);
- builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
- R.drawable.ic_action_warning_red));
- builder.setContentTitle(context.getString(R.string.MessageNotifier_message_delivery_failed));
- builder.setContentText(context.getString(R.string.MessageNotifier_failed_to_deliver_message));
- builder.setTicker(context.getString(R.string.MessageNotifier_error_delivering_message));
- builder.setContentIntent(PendingIntent.getActivity(context, 0, intent, 0));
- builder.setAutoCancel(true);
- setNotificationAlarms(context, builder, true, null, VibrateState.DEFAULT);
+ intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
+ FailedNotificationBuilder builder = new FailedNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context), intent);
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
.notify((int)threadId, builder.build());
}
@@ -187,13 +163,13 @@ public class MessageNotifier {
}
if (notificationState.hasMultipleThreads()) {
- sendMultipleThreadNotification(context, masterSecret, notificationState, signal);
+ sendMultipleThreadNotification(context, notificationState, signal);
} else {
sendSingleThreadNotification(context, masterSecret, notificationState, signal);
}
updateBadge(context, notificationState.getMessageCount());
- scheduleReminder(context, masterSecret, reminderCount);
+ scheduleReminder(context, reminderCount);
} finally {
if (telcoCursor != null) telcoCursor.close();
if (pushCursor != null) pushCursor.close();
@@ -211,73 +187,33 @@ public class MessageNotifier {
return;
}
- List notifications = notificationState.getNotifications();
- NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
- Recipients recipients = notifications.get(0).getRecipients();
- Recipient recipient = notifications.get(0).getIndividualRecipient();
- int largeIconTargetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
- Drawable recipientPhoto = recipient.getContactPhoto().asDrawable(context, recipients == null ? ContactColors.UNKNOWN_COLOR.toConversationColor(context) :
- recipients.getColor().toConversationColor(context));
+ SingleRecipientNotificationBuilder builder = new SingleRecipientNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
+ List notifications = notificationState.getNotifications();
- if (recipientPhoto != null) {
- Bitmap recipientPhotoBitmap = BitmapUtil.createFromDrawable(recipientPhoto, largeIconTargetSize, largeIconTargetSize);
- if (recipientPhotoBitmap != null) builder.setLargeIcon(recipientPhotoBitmap);
- }
-
- builder.setSmallIcon(R.drawable.icon_notification);
- builder.setColor(context.getResources().getColor(R.color.textsecure_primary));
- builder.setContentTitle(recipient.toShortString());
- builder.setContentText(notifications.get(0).getText());
+ builder.setSender(notifications.get(0).getIndividualRecipient());
+ builder.setMessageCount(notificationState.getMessageCount());
+ builder.setPrimaryMessageBody(notifications.get(0).getText());
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
- builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
- builder.setPriority(NotificationCompat.PRIORITY_HIGH);
- builder.setNumber(notificationState.getMessageCount());
- builder.setCategory(NotificationCompat.CATEGORY_MESSAGE);
- builder.setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(DeleteReceiver.DELETE_REMINDER_ACTION), 0));
- if (recipient.getContactUri() != null) builder.addPerson(recipient.getContactUri().toString());
long timestamp = notifications.get(0).getTimestamp();
if (timestamp != 0) builder.setWhen(timestamp);
- if (masterSecret != null) {
- Action markAsReadAction = new Action(R.drawable.check,
- context.getString(R.string.MessageNotifier_mark_read),
- notificationState.getMarkAsReadIntent(context));
-
- Action replyAction = new Action(R.drawable.ic_reply_white_36dp,
- context.getString(R.string.MessageNotifier_reply),
- notificationState.getQuickReplyIntent(context, recipients));
-
- Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
- context.getString(R.string.MessageNotifier_reply),
- notificationState.getWearableReplyIntent(context, recipients))
- .addRemoteInput(new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(context.getString(R.string.MessageNotifier_reply)).build())
- .build();
-
- builder.addAction(markAsReadAction);
- builder.addAction(replyAction);
-
- builder.extend(new NotificationCompat.WearableExtender().addAction(markAsReadAction)
- .addAction(wearableReplyAction));
- }
-
- SpannableStringBuilder content = new SpannableStringBuilder();
+ builder.addActions(masterSecret,
+ notificationState.getMarkAsReadIntent(context),
+ notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipients()),
+ notificationState.getWearableReplyIntent(context, notifications.get(0).getRecipients()));
ListIterator iterator = notifications.listIterator(notifications.size());
+
while(iterator.hasPrevious()) {
- NotificationItem item = iterator.previous();
- content.append(item.getBigStyleSummary());
- content.append('\n');
+ builder.addMessageBody(iterator.previous().getText());
+
}
- builder.setStyle(new BigTextStyle().bigText(content));
-
- setNotificationAlarms(context, builder, signal,
- notificationState.getRingtone(),
- notificationState.getVibrate());
-
if (signal) {
- builder.setTicker(notifications.get(0).getTickerText());
+ builder.setAlarms(notificationState.getRingtone(), notificationState.getVibrate());
+ builder.setTicker(notifications.get(0).getIndividualRecipient(),
+ notifications.get(0).getText());
}
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
@@ -285,59 +221,30 @@ public class MessageNotifier {
}
private static void sendMultipleThreadNotification(@NonNull Context context,
- @Nullable MasterSecret masterSecret,
@NonNull NotificationState notificationState,
boolean signal)
{
- List notifications = notificationState.getNotifications();
- NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ MultipleRecipientNotificationBuilder builder = new MultipleRecipientNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
+ List notifications = notificationState.getNotifications();
- builder.setColor(context.getResources().getColor(R.color.textsecure_primary));
- builder.setSmallIcon(R.drawable.icon_notification);
- builder.setContentTitle(context.getString(R.string.app_name));
- builder.setSubText(context.getString(R.string.MessageNotifier_d_messages_in_d_conversations,
- notificationState.getMessageCount(),
- notificationState.getThreadCount()));
- builder.setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s,
- notifications.get(0).getIndividualRecipientName()));
- builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationListActivity.class), 0));
-
- builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
- builder.setNumber(notificationState.getMessageCount());
- builder.setCategory(NotificationCompat.CATEGORY_MESSAGE);
+ builder.setMessageCount(notificationState.getMessageCount(), notificationState.getThreadCount());
+ builder.setMostRecentSender(notifications.get(0).getIndividualRecipient());
long timestamp = notifications.get(0).getTimestamp();
if (timestamp != 0) builder.setWhen(timestamp);
- builder.setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(DeleteReceiver.DELETE_REMINDER_ACTION), 0));
-
- if (masterSecret != null) {
- Action markAllAsReadAction = new Action(R.drawable.check,
- context.getString(R.string.MessageNotifier_mark_all_as_read),
- notificationState.getMarkAsReadIntent(context));
- builder.addAction(markAllAsReadAction);
- builder.extend(new NotificationCompat.WearableExtender().addAction(markAllAsReadAction));
- }
-
- InboxStyle style = new InboxStyle();
+ builder.addActions(notificationState.getMarkAsReadIntent(context));
ListIterator iterator = notifications.listIterator(notifications.size());
+
while(iterator.hasPrevious()) {
NotificationItem item = iterator.previous();
- style.addLine(item.getTickerText());
- if (item.getIndividualRecipient().getContactUri() != null) {
- builder.addPerson(item.getIndividualRecipient().getContactUri().toString());
- }
+ builder.addMessageBody(item.getIndividualRecipient(), item.getText());
}
- builder.setStyle(style);
-
- setNotificationAlarms(context, builder, signal,
- notificationState.getRingtone(),
- notificationState.getVibrate());
-
if (signal) {
- builder.setTicker(notifications.get(0).getTickerText());
+ builder.setAlarms(notificationState.getRingtone(), notificationState.getVibrate());
+ builder.setTicker(notifications.get(0).getText());
}
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
@@ -411,7 +318,7 @@ public class MessageNotifier {
body.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
if (!recipients.isMuted()) {
- notificationState.addNotification(new NotificationItem(recipient, recipients, null, threadId, body, null, 0));
+ notificationState.addNotification(new NotificationItem(recipient, recipients, null, threadId, body, 0));
}
}
} finally {
@@ -436,7 +343,6 @@ public class MessageNotifier {
Recipients recipients = record.getRecipients();
long threadId = record.getThreadId();
CharSequence body = record.getDisplayBody();
- Uri image = null;
Recipients threadRecipients = null;
long timestamp;
@@ -458,7 +364,7 @@ public class MessageNotifier {
}
if (threadRecipients == null || !threadRecipients.isMuted()) {
- notificationState.addNotification(new NotificationItem(recipient, recipients, threadRecipients, threadId, body, image, timestamp));
+ notificationState.addNotification(new NotificationItem(recipient, recipients, threadRecipients, threadId, body, timestamp));
}
}
@@ -466,42 +372,6 @@ public class MessageNotifier {
return notificationState;
}
- private static void setNotificationAlarms(Context context,
- NotificationCompat.Builder builder,
- boolean signal,
- @Nullable Uri ringtone,
- VibrateState vibrate)
-
- {
- String defaultRingtoneName = TextSecurePreferences.getNotificationRingtone(context);
- boolean defaultVibrate = TextSecurePreferences.isNotificationVibrateEnabled(context);
- String ledColor = TextSecurePreferences.getNotificationLedColor(context);
- String ledBlinkPattern = TextSecurePreferences.getNotificationLedPattern(context);
- String ledBlinkPatternCustom = TextSecurePreferences.getNotificationLedPatternCustom(context);
- String[] blinkPatternArray = parseBlinkPattern(ledBlinkPattern, ledBlinkPatternCustom);
-
- if (signal && ringtone != null) builder.setSound(ringtone);
- else if (signal && !TextUtils.isEmpty(defaultRingtoneName)) builder.setSound(Uri.parse(defaultRingtoneName));
- else builder.setSound(null);
-
- if (signal && (vibrate == VibrateState.ENABLED || (vibrate == VibrateState.DEFAULT && defaultVibrate))) {
- builder.setDefaults(Notification.DEFAULT_VIBRATE);
- }
-
- if (!ledColor.equals("none")) {
- builder.setLights(Color.parseColor(ledColor),
- Integer.parseInt(blinkPatternArray[0]),
- Integer.parseInt(blinkPatternArray[1]));
- }
- }
-
- private static String[] parseBlinkPattern(String blinkPattern, String blinkPatternCustom) {
- if (blinkPattern.equals("custom"))
- blinkPattern = blinkPatternCustom;
-
- return blinkPattern.split(",");
- }
-
private static void updateBadge(Context context, int count) {
try {
ShortcutBadger.setBadge(context.getApplicationContext(), count);
@@ -512,7 +382,7 @@ public class MessageNotifier {
}
}
- private static void scheduleReminder(Context context, MasterSecret masterSecret, int count) {
+ private static void scheduleReminder(Context context, int count) {
if (count >= TextSecurePreferences.getRepeatAlertsCount(context)) {
return;
}
diff --git a/src/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java
new file mode 100644
index 0000000000..ace85d1405
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java
@@ -0,0 +1,84 @@
+package org.thoughtcrime.securesms.notifications;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.NotificationCompat;
+
+import org.thoughtcrime.securesms.ConversationListActivity;
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
+import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.util.Util;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class MultipleRecipientNotificationBuilder extends AbstractNotificationBuilder {
+
+ private final List messageBodies = new LinkedList<>();
+
+ public MultipleRecipientNotificationBuilder(Context context, NotificationPrivacyPreference privacy) {
+ super(context, privacy);
+
+ setColor(context.getResources().getColor(R.color.textsecure_primary));
+ setSmallIcon(R.drawable.icon_notification);
+ setContentTitle(context.getString(R.string.app_name));
+ setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationListActivity.class), 0));
+ setCategory(NotificationCompat.CATEGORY_MESSAGE);
+ setPriority(NotificationCompat.PRIORITY_HIGH);
+ setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(MessageNotifier.DeleteReceiver.DELETE_REMINDER_ACTION), 0));
+ }
+
+ public void setMessageCount(int messageCount, int threadCount) {
+ setSubText(context.getString(R.string.MessageNotifier_d_new_messages_in_d_conversations,
+ messageCount, threadCount));
+ setContentInfo(String.valueOf(messageCount));
+ setNumber(messageCount);
+ }
+
+ public void setMostRecentSender(Recipient recipient) {
+ if (privacy.isDisplayContact()) {
+ setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s,
+ recipient.toShortString()));
+ }
+ }
+
+ public void addActions(PendingIntent markAsReadIntent) {
+ NotificationCompat.Action markAllAsReadAction = new NotificationCompat.Action(R.drawable.check,
+ context.getString(R.string.MessageNotifier_mark_all_as_read),
+ markAsReadIntent);
+ addAction(markAllAsReadAction);
+ extend(new NotificationCompat.WearableExtender().addAction(markAllAsReadAction));
+ }
+
+ public void addMessageBody(@NonNull Recipient sender, @Nullable CharSequence body) {
+ if (privacy.isDisplayMessage()) {
+ messageBodies.add(getStyledMessage(sender, body));
+ } else if (privacy.isDisplayContact()) {
+ messageBodies.add(Util.getBoldedString(sender.toShortString()));
+ }
+
+ if (privacy.isDisplayContact() && sender.getContactUri() != null) {
+ addPerson(sender.getContactUri().toString());
+ }
+ }
+
+ @Override
+ public Notification build() {
+ if (privacy.isDisplayMessage() || privacy.isDisplayContact()) {
+ NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
+
+ for (CharSequence body : messageBodies) {
+ style.addLine(body);
+ }
+
+ setStyle(style);
+ }
+
+ return super.build();
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/notifications/NotificationItem.java b/src/org/thoughtcrime/securesms/notifications/NotificationItem.java
index 424bcf2932..8c45fc9270 100644
--- a/src/org/thoughtcrime/securesms/notifications/NotificationItem.java
+++ b/src/org/thoughtcrime/securesms/notifications/NotificationItem.java
@@ -4,14 +4,10 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.support.annotation.Nullable;
-import android.text.SpannableStringBuilder;
import org.thoughtcrime.securesms.ConversationActivity;
-import org.thoughtcrime.securesms.ConversationPopupActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
-import org.thoughtcrime.securesms.util.Util;
public class NotificationItem {
@@ -20,18 +16,16 @@ public class NotificationItem {
private final Recipients threadRecipients;
private final long threadId;
private final CharSequence text;
- private final Uri image;
private final long timestamp;
public NotificationItem(Recipient individualRecipient, Recipients recipients,
Recipients threadRecipients, long threadId,
- CharSequence text, Uri image, long timestamp)
+ CharSequence text, long timestamp)
{
this.individualRecipient = individualRecipient;
this.recipients = recipients;
this.threadRecipients = threadRecipients;
this.text = text;
- this.image = image;
this.threadId = threadId;
this.timestamp = timestamp;
}
@@ -44,10 +38,6 @@ public class NotificationItem {
return individualRecipient;
}
- public String getIndividualRecipientName() {
- return individualRecipient.toShortString();
- }
-
public CharSequence getText() {
return text;
}
@@ -56,31 +46,10 @@ public class NotificationItem {
return timestamp;
}
- public Uri getImage() {
- return image;
- }
-
- public boolean hasImage() {
- return image != null;
- }
-
public long getThreadId() {
return threadId;
}
- public CharSequence getBigStyleSummary() {
- return (text == null) ? "" : text;
- }
-
- public CharSequence getTickerText() {
- SpannableStringBuilder builder = new SpannableStringBuilder();
- builder.append(Util.getBoldedString(getIndividualRecipientName()));
- builder.append(": ");
- builder.append(getText());
-
- return builder;
- }
-
public PendingIntent getPendingIntent(Context context) {
Intent intent = new Intent(context, ConversationActivity.class);
Recipients notifyRecipients = threadRecipients != null ? threadRecipients : recipients;
diff --git a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java
new file mode 100644
index 0000000000..8ac46008cf
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java
@@ -0,0 +1,149 @@
+package org.thoughtcrime.securesms.notifications;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationCompat.Action;
+import android.support.v4.app.RemoteInput;
+import android.text.SpannableStringBuilder;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
+import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.util.BitmapUtil;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class SingleRecipientNotificationBuilder extends AbstractNotificationBuilder {
+
+ private final List messageBodies = new LinkedList<>();
+
+ public SingleRecipientNotificationBuilder(@NonNull Context context, @NonNull NotificationPrivacyPreference privacy) {
+ super(context, privacy);
+
+ setSmallIcon(R.drawable.icon_notification);
+ setColor(context.getResources().getColor(R.color.textsecure_primary));
+ setPriority(NotificationCompat.PRIORITY_HIGH);
+ setCategory(NotificationCompat.CATEGORY_MESSAGE);
+ setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(MessageNotifier.DeleteReceiver.DELETE_REMINDER_ACTION), 0));
+ }
+
+ public void setSender(@NonNull Recipient recipient) {
+ if (privacy.isDisplayContact()) {
+ setContentTitle(recipient.toShortString());
+
+ if (recipient.getContactUri() != null) {
+ addPerson(recipient.getContactUri().toString());
+ }
+
+ setLargeIcon(recipient.getContactPhoto()
+ .asDrawable(context, recipient.getColor()
+ .toConversationColor(context)));
+ } else {
+ setContentTitle(context.getString(R.string.SingleRecipientNotificationBuilder_new_textsecure_message));
+ setLargeIcon(Recipient.getUnknownRecipient()
+ .getContactPhoto()
+ .asDrawable(context, Recipient.getUnknownRecipient()
+ .getColor()
+ .toConversationColor(context)));
+ }
+ }
+
+ public void setMessageCount(int messageCount) {
+ setContentInfo(String.valueOf(messageCount));
+ setNumber(messageCount);
+ }
+
+ public void setPrimaryMessageBody(CharSequence message) {
+ if (privacy.isDisplayMessage()) {
+ setContentText(message);
+ } else {
+ setContentText(context.getString(R.string.SingleRecipientNotificationBuilder_contents_hidden));
+ }
+ }
+
+ public void addActions(@Nullable MasterSecret masterSecret,
+ @NonNull PendingIntent markReadIntent,
+ @NonNull PendingIntent quickReplyIntent,
+ @NonNull PendingIntent wearableReplyIntent)
+ {
+ Action markAsReadAction = new Action(R.drawable.check,
+ context.getString(R.string.MessageNotifier_mark_read),
+ markReadIntent);
+
+ if (masterSecret != null) {
+ Action replyAction = new Action(R.drawable.ic_reply_white_36dp,
+ context.getString(R.string.MessageNotifier_reply),
+ quickReplyIntent);
+
+ Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
+ context.getString(R.string.MessageNotifier_reply),
+ wearableReplyIntent)
+ .addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_VOICE_REPLY)
+ .setLabel(context.getString(R.string.MessageNotifier_reply)).build())
+ .build();
+
+ addAction(markAsReadAction);
+ addAction(replyAction);
+
+ extend(new NotificationCompat.WearableExtender().addAction(markAsReadAction)
+ .addAction(wearableReplyAction));
+ } else {
+ addAction(markAsReadAction);
+
+ extend(new NotificationCompat.WearableExtender().addAction(markAsReadAction));
+ }
+ }
+
+ public void addMessageBody(@Nullable CharSequence messageBody) {
+ if (privacy.isDisplayMessage()) {
+ messageBodies.add(messageBody == null ? "" : messageBody);
+ }
+ }
+
+ public void setTicker(@NonNull Recipient recipient, @Nullable CharSequence message) {
+ if (privacy.isDisplayMessage()) {
+ setTicker(getStyledMessage(recipient, message));
+ } else if (privacy.isDisplayContact()) {
+ setTicker(getStyledMessage(recipient, context.getString(R.string.SingleRecipientNotificationBuilder_new_textsecure_message)));
+ } else {
+ setTicker(context.getString(R.string.SingleRecipientNotificationBuilder_new_textsecure_message));
+ }
+ }
+
+ @Override
+ public Notification build() {
+ if (privacy.isDisplayMessage()) {
+ SpannableStringBuilder content = new SpannableStringBuilder();
+
+ for (CharSequence message : messageBodies) {
+ content.append(message);
+ content.append('\n');
+ }
+
+ setStyle(new NotificationCompat.BigTextStyle().bigText(content));
+ }
+
+ return super.build();
+ }
+
+ private void setLargeIcon(@Nullable Drawable drawable) {
+ if (drawable != null) {
+ int largeIconTargetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
+ Bitmap recipientPhotoBitmap = BitmapUtil.createFromDrawable(drawable, largeIconTargetSize, largeIconTargetSize);
+
+ if (recipientPhotoBitmap != null) {
+ setLargeIcon(recipientPhotoBitmap);
+ }
+ }
+ }
+
+}
diff --git a/src/org/thoughtcrime/securesms/preferences/NotificationPrivacyPreference.java b/src/org/thoughtcrime/securesms/preferences/NotificationPrivacyPreference.java
new file mode 100644
index 0000000000..f2ff00db30
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/preferences/NotificationPrivacyPreference.java
@@ -0,0 +1,19 @@
+package org.thoughtcrime.securesms.preferences;
+
+public class NotificationPrivacyPreference {
+
+ private final String preference;
+
+ public NotificationPrivacyPreference(String preference) {
+ this.preference = preference;
+ }
+
+ public boolean isDisplayContact() {
+ return "all".equals(preference) || "contact".equals(preference);
+ }
+
+ public boolean isDisplayMessage() {
+ return "all".equals(preference);
+ }
+
+}
diff --git a/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
index d9862f85d6..da5c6e8cdc 100644
--- a/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
+++ b/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
@@ -14,13 +15,18 @@ import android.text.TextUtils;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragment {
+ private MasterSecret masterSecret;
+
@Override
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
+ masterSecret = getArguments().getParcelable("master_secret");
addPreferencesFromResource(R.xml.preferences_notifications);
this.findPreference(TextSecurePreferences.LED_COLOR_PREF)
@@ -31,10 +37,13 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
.setOnPreferenceChangeListener(new RingtoneSummaryListener());
this.findPreference(TextSecurePreferences.REPEAT_ALERTS_PREF)
.setOnPreferenceChangeListener(new ListSummaryListener());
+ this.findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)
+ .setOnPreferenceChangeListener(new NotificationPrivacyListener());
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.LED_COLOR_PREF));
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.LED_BLINK_PREF));
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.REPEAT_ALERTS_PREF));
+ initializeListSummary((ListPreference) findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF));
initializeRingtoneSummary((RingtonePreference) findPreference(TextSecurePreferences.RINGTONE_PREF));
}
@@ -76,4 +85,20 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
return context.getString(TextSecurePreferences.isNotificationsEnabled(context) ? onCapsResId : offCapsResId);
}
+
+ private class NotificationPrivacyListener extends ListSummaryListener {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object value) {
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ MessageNotifier.updateNotification(getActivity(), masterSecret);
+ return null;
+ }
+ }.execute();
+
+ return super.onPreferenceChange(preference, value);
+ }
+
+ }
}
diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
index ca9adc36c7..c5572da592 100644
--- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
+++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
@@ -6,6 +6,8 @@ import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
+import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
+
import java.io.IOException;
public class TextSecurePreferences {
@@ -70,6 +72,11 @@ public class TextSecurePreferences {
private static final String RATING_ENABLED_PREF = "pref_rating_enabled";
public static final String REPEAT_ALERTS_PREF = "pref_repeat_alerts";
+ public static final String NOTIFICATION_PRIVACY_PREF = "pref_notification_privacy";
+
+ public static NotificationPrivacyPreference getNotificationPrivacy(Context context) {
+ return new NotificationPrivacyPreference(getStringPreference(context, NOTIFICATION_PRIVACY_PREF, "all"));
+ }
public static long getRatingLaterTimestamp(Context context) {
return getLongPreference(context, RATING_LATER_PREF, 0);