Support for per-recipient muting, blocking, and ringtones.

Fixes #757
Fixes #354
Fixes #222
Closes #1815
Closes #3378

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2015-06-09 07:37:20 -07:00
parent cb3cf7789f
commit 40af2a81db
80 changed files with 1858 additions and 321 deletions

View File

@@ -31,6 +31,7 @@ import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
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;
@@ -49,7 +50,9 @@ 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;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -88,7 +91,7 @@ public class MessageNotifier {
public static void notifyMessageDeliveryFailed(Context context, Recipients recipients, long threadId) {
if (visibleThread == threadId) {
sendInThreadNotification(context);
sendInThreadNotification(context, recipients);
} else {
Intent intent = new Intent(context, ConversationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
@@ -105,7 +108,7 @@ public class MessageNotifier {
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);
setNotificationAlarms(context, builder, true, null, VibrateState.DEFAULT);
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
.notify((int)threadId, builder.build());
@@ -126,8 +129,9 @@ public class MessageNotifier {
}
if (visibleThread == threadId) {
DatabaseFactory.getThreadDatabase(context).setRead(threadId);
sendInThreadNotification(context);
ThreadDatabase threads = DatabaseFactory.getThreadDatabase(context);
threads.setRead(threadId);
sendInThreadNotification(context, threads.getRecipientsForThreadId(threadId));
} else {
updateNotification(context, masterSecret, true, 0);
}
@@ -225,7 +229,9 @@ public class MessageNotifier {
builder.setStyle(new BigTextStyle().bigText(content));
setNotificationAlarms(context, builder, signal);
setNotificationAlarms(context, builder, signal,
notificationState.getRingtone(),
notificationState.getVibrate());
if (signal) {
builder.setTicker(notifications.get(0).getTickerText());
@@ -283,7 +289,9 @@ public class MessageNotifier {
builder.setStyle(style);
setNotificationAlarms(context, builder, signal);
setNotificationAlarms(context, builder, signal,
notificationState.getRingtone(),
notificationState.getVibrate());
if (signal) {
builder.setTicker(notifications.get(0).getTickerText());
@@ -293,23 +301,27 @@ public class MessageNotifier {
.notify(NOTIFICATION_ID, builder.build());
}
private static void sendInThreadNotification(Context context) {
private static void sendInThreadNotification(Context context, Recipients recipients) {
try {
if (!TextSecurePreferences.isInThreadNotifications(context)) {
return;
}
String ringtone = TextSecurePreferences.getNotificationRingtone(context);
if (ringtone == null) {
Log.w(TAG, "ringtone preference was null.");
return;
}
Uri uri = Uri.parse(ringtone);
Uri uri = recipients.getRingtone();
if (uri == null) {
Log.w(TAG, "couldn't parse ringtone uri " + ringtone);
String ringtone = TextSecurePreferences.getNotificationRingtone(context);
if (ringtone == null) {
Log.w(TAG, "ringtone preference was null.");
return;
} else {
uri = Uri.parse(ringtone);
}
}
if (uri == null) {
Log.w(TAG, "couldn't parse ringtone uri " + TextSecurePreferences.getNotificationRingtone(context));
return;
}
@@ -358,7 +370,9 @@ public class MessageNotifier {
SpannableString body = new SpannableString(context.getString(R.string.MessageNotifier_encrypted_message));
body.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
notificationState.addNotification(new NotificationItem(recipient, recipients, null, threadId, body, null, 0));
if (!recipients.isMuted()) {
notificationState.addNotification(new NotificationItem(recipient, recipients, null, threadId, body, null, 0));
}
}
} finally {
if (reader != null)
@@ -403,7 +417,9 @@ public class MessageNotifier {
body = SpanUtil.italic(message, italicLength);
}
notificationState.addNotification(new NotificationItem(recipient, recipients, threadRecipients, threadId, body, image, timestamp));
if (threadRecipients == null || !threadRecipients.isMuted()) {
notificationState.addNotification(new NotificationItem(recipient, recipients, threadRecipients, threadId, body, image, timestamp));
}
}
reader.close();
@@ -412,18 +428,23 @@ public class MessageNotifier {
private static void setNotificationAlarms(Context context,
NotificationCompat.Builder builder,
boolean signal)
boolean signal,
@Nullable Uri ringtone,
VibrateState vibrate)
{
String ringtone = TextSecurePreferences.getNotificationRingtone(context);
boolean vibrate = TextSecurePreferences.isNotificationVibrateEnabled(context);
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);
builder.setSound(TextUtils.isEmpty(ringtone) || !signal ? null : Uri.parse(ringtone));
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) {
if (signal && (vibrate == VibrateState.ENABLED || (vibrate == VibrateState.DEFAULT && defaultVibrate))) {
builder.setDefaults(Notification.DEFAULT_VIBRATE);
}