From 8cf2654c5ba1108c7068c44b754893115bbe422d Mon Sep 17 00:00:00 2001 From: Alan Evans Date: Mon, 6 May 2019 18:18:58 -0300 Subject: [PATCH] Show reply method SMS/Signal and respect sticky. Fixes #8792 --- res/values/strings.xml | 2 ++ .../notifications/MessageNotifier.java | 5 ++- .../notifications/NotificationState.java | 3 +- .../notifications/RemoteReplyReceiver.java | 35 ++++++++++++------- .../securesms/notifications/ReplyMethod.java | 25 +++++++++++++ .../SingleRecipientNotificationBuilder.java | 33 +++++++++++++---- 6 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/notifications/ReplyMethod.java diff --git a/res/values/strings.xml b/res/values/strings.xml index e5458b8a4d..19dc61e607 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -752,6 +752,8 @@ Mark read Media message Reply + Signal Message + Unsecured SMS Pending Signal messages You have pending Signal messages, tap to open and retrieve %1$s %2$s diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java index 7819029641..63c4d59843 100644 --- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java +++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java @@ -315,9 +315,12 @@ public class MessageNotifier { long timestamp = notifications.get(0).getTimestamp(); if (timestamp != 0) builder.setWhen(timestamp); + ReplyMethod replyMethod = ReplyMethod.forRecipient(context, recipient); + builder.addActions(notificationState.getMarkAsReadIntent(context, notificationId), notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipient()), - notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipient())); + notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipient(), replyMethod), + replyMethod); builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipient()), notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp()); diff --git a/src/org/thoughtcrime/securesms/notifications/NotificationState.java b/src/org/thoughtcrime/securesms/notifications/NotificationState.java index a0cc40cb43..32b5489e35 100644 --- a/src/org/thoughtcrime/securesms/notifications/NotificationState.java +++ b/src/org/thoughtcrime/securesms/notifications/NotificationState.java @@ -118,13 +118,14 @@ public class NotificationState { return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } - public PendingIntent getRemoteReplyIntent(Context context, Recipient recipient) { + public PendingIntent getRemoteReplyIntent(Context context, Recipient recipient, ReplyMethod replyMethod) { if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications!"); Intent intent = new Intent(RemoteReplyReceiver.REPLY_ACTION); intent.setClass(context, RemoteReplyReceiver.class); intent.setData((Uri.parse("custom://"+System.currentTimeMillis()))); intent.putExtra(RemoteReplyReceiver.ADDRESS_EXTRA, recipient.getAddress()); + intent.putExtra(RemoteReplyReceiver.REPLY_METHOD, replyMethod); intent.setPackage(context.getPackageName()); return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/src/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java b/src/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java index 48d7f4e867..1f36a125f9 100644 --- a/src/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java +++ b/src/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java @@ -28,13 +28,11 @@ import android.support.v4.app.RemoteInput; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; -import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; -import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.util.Collections; import java.util.LinkedList; @@ -48,6 +46,7 @@ public class RemoteReplyReceiver extends BroadcastReceiver { public static final String TAG = RemoteReplyReceiver.class.getSimpleName(); public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY"; public static final String ADDRESS_EXTRA = "address"; + public static final String REPLY_METHOD = "reply_method"; @SuppressLint("StaticFieldLeak") @Override @@ -59,8 +58,12 @@ public class RemoteReplyReceiver extends BroadcastReceiver { if (remoteInput == null) return; final Address address = intent.getParcelableExtra(ADDRESS_EXTRA); + final ReplyMethod replyMethod = (ReplyMethod) intent.getSerializableExtra(REPLY_METHOD); final CharSequence responseText = remoteInput.getCharSequence(MessageNotifier.EXTRA_REMOTE_REPLY); + if (address == null) throw new AssertionError("No address specified"); + if (replyMethod == null) throw new AssertionError("No reply method specified"); + if (responseText != null) { new AsyncTask() { @Override @@ -71,15 +74,24 @@ public class RemoteReplyReceiver extends BroadcastReceiver { int subscriptionId = recipient.getDefaultSubscriptionId().or(-1); long expiresIn = recipient.getExpireMessages() * 1000L; - if (recipient.isGroupRecipient()) { - OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); - threadId = MessageSender.send(context, reply, -1, false, null); - } else if (TextSecurePreferences.isPushRegistered(context) && recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) { - OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn); - threadId = MessageSender.send(context, reply, -1, false, null); - } else { - OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId); - threadId = MessageSender.send(context, reply, -1, false, null); + switch (replyMethod) { + case GroupMessage: { + OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + threadId = MessageSender.send(context, reply, -1, false, null); + break; + } + case SecureMessage: { + OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn); + threadId = MessageSender.send(context, reply, -1, false, null); + break; + } + case UnsecuredSmsMessage: { + OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId); + threadId = MessageSender.send(context, reply, -1, true, null); + break; + } + default: + throw new AssertionError("Unknown Reply method"); } List messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true); @@ -91,6 +103,5 @@ public class RemoteReplyReceiver extends BroadcastReceiver { } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - } } diff --git a/src/org/thoughtcrime/securesms/notifications/ReplyMethod.java b/src/org/thoughtcrime/securesms/notifications/ReplyMethod.java new file mode 100644 index 0000000000..fe660f1ec8 --- /dev/null +++ b/src/org/thoughtcrime/securesms/notifications/ReplyMethod.java @@ -0,0 +1,25 @@ +package org.thoughtcrime.securesms.notifications; + +import android.content.Context; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.database.RecipientDatabase; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +public enum ReplyMethod { + + GroupMessage, + SecureMessage, + UnsecuredSmsMessage; + + public static @NonNull ReplyMethod forRecipient(Context context, Recipient recipient) { + if (recipient.isGroupRecipient()) { + return ReplyMethod.GroupMessage; + } else if (TextSecurePreferences.isPushRegistered(context) && recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED && !recipient.isForceSmsSelection()) { + return ReplyMethod.SecureMessage; + } else { + return ReplyMethod.UnsecuredSmsMessage; + } + } +} diff --git a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java index c1322e90c1..83ecb8858d 100644 --- a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java +++ b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java @@ -9,11 +9,11 @@ import android.net.Uri; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.StringRes; 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.logging.Log; import com.bumptech.glide.load.engine.DiskCacheStrategy; @@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactColors; import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto; +import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.Slide; @@ -143,30 +144,34 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil public void addActions(@NonNull PendingIntent markReadIntent, @NonNull PendingIntent quickReplyIntent, - @NonNull PendingIntent wearableReplyIntent) + @NonNull PendingIntent wearableReplyIntent, + @NonNull ReplyMethod replyMethod) { Action markAsReadAction = new Action(R.drawable.check, context.getString(R.string.MessageNotifier_mark_read), markReadIntent); + String actionName = context.getString(R.string.MessageNotifier_reply); + String label = context.getString(replyMethodLongDescription(replyMethod)); + Action replyAction = new Action(R.drawable.ic_reply_white_36dp, - context.getString(R.string.MessageNotifier_reply), + actionName, quickReplyIntent); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp, - context.getString(R.string.MessageNotifier_reply), + actionName, wearableReplyIntent) .addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY) - .setLabel(context.getString(R.string.MessageNotifier_reply)).build()) + .setLabel(label).build()) .build(); } Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply, - context.getString(R.string.MessageNotifier_reply), + actionName, wearableReplyIntent) .addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY) - .setLabel(context.getString(R.string.MessageNotifier_reply)).build()) + .setLabel(label).build()) .build(); addAction(markAsReadAction); @@ -176,6 +181,20 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil .addAction(wearableReplyAction)); } + @StringRes + private static int replyMethodLongDescription(@NonNull ReplyMethod replyMethod) { + switch (replyMethod) { + case GroupMessage: + return R.string.MessageNotifier_reply; + case SecureMessage: + return R.string.MessageNotifier_signal_message; + case UnsecuredSmsMessage: + return R.string.MessageNotifier_unsecured_sms; + default: + return R.string.MessageNotifier_reply; + } + } + public void addMessageBody(@NonNull Recipient threadRecipient, @NonNull Recipient individualRecipient, @Nullable CharSequence messageBody)