Show reply method SMS/Signal and respect sticky.

Fixes #8792
This commit is contained in:
Alan Evans 2019-05-06 18:18:58 -03:00 committed by Greyson Parrelli
parent 18531146f7
commit 8cf2654c5b
6 changed files with 82 additions and 21 deletions

View File

@ -752,6 +752,8 @@
<string name="MessageNotifier_mark_read">Mark read</string> <string name="MessageNotifier_mark_read">Mark read</string>
<string name="MessageNotifier_media_message">Media message</string> <string name="MessageNotifier_media_message">Media message</string>
<string name="MessageNotifier_reply">Reply</string> <string name="MessageNotifier_reply">Reply</string>
<string name="MessageNotifier_signal_message">Signal Message</string>
<string name="MessageNotifier_unsecured_sms">Unsecured SMS</string>
<string name="MessageNotifier_pending_signal_messages">Pending Signal messages</string> <string name="MessageNotifier_pending_signal_messages">Pending Signal messages</string>
<string name="MessageNotifier_you_have_pending_signal_messages">You have pending Signal messages, tap to open and retrieve</string> <string name="MessageNotifier_you_have_pending_signal_messages">You have pending Signal messages, tap to open and retrieve</string>
<string name="MessageNotifier_contact_message">%1$s %2$s</string> <string name="MessageNotifier_contact_message">%1$s %2$s</string>

View File

@ -315,9 +315,12 @@ public class MessageNotifier {
long timestamp = notifications.get(0).getTimestamp(); long timestamp = notifications.get(0).getTimestamp();
if (timestamp != 0) builder.setWhen(timestamp); if (timestamp != 0) builder.setWhen(timestamp);
ReplyMethod replyMethod = ReplyMethod.forRecipient(context, recipient);
builder.addActions(notificationState.getMarkAsReadIntent(context, notificationId), builder.addActions(notificationState.getMarkAsReadIntent(context, notificationId),
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipient()), 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()), builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipient()),
notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp()); notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp());

View File

@ -118,13 +118,14 @@ public class NotificationState {
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 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!"); if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications!");
Intent intent = new Intent(RemoteReplyReceiver.REPLY_ACTION); Intent intent = new Intent(RemoteReplyReceiver.REPLY_ACTION);
intent.setClass(context, RemoteReplyReceiver.class); intent.setClass(context, RemoteReplyReceiver.class);
intent.setData((Uri.parse("custom://"+System.currentTimeMillis()))); intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
intent.putExtra(RemoteReplyReceiver.ADDRESS_EXTRA, recipient.getAddress()); intent.putExtra(RemoteReplyReceiver.ADDRESS_EXTRA, recipient.getAddress());
intent.putExtra(RemoteReplyReceiver.REPLY_METHOD, replyMethod);
intent.setPackage(context.getPackageName()); intent.setPackage(context.getPackageName());
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

View File

@ -28,13 +28,11 @@ import android.support.v4.app.RemoteInput;
import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage; import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; 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 TAG = RemoteReplyReceiver.class.getSimpleName();
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY"; public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
public static final String ADDRESS_EXTRA = "address"; public static final String ADDRESS_EXTRA = "address";
public static final String REPLY_METHOD = "reply_method";
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
@Override @Override
@ -59,8 +58,12 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
if (remoteInput == null) return; if (remoteInput == null) return;
final Address address = intent.getParcelableExtra(ADDRESS_EXTRA); final Address address = intent.getParcelableExtra(ADDRESS_EXTRA);
final ReplyMethod replyMethod = (ReplyMethod) intent.getSerializableExtra(REPLY_METHOD);
final CharSequence responseText = remoteInput.getCharSequence(MessageNotifier.EXTRA_REMOTE_REPLY); 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) { if (responseText != null) {
new AsyncTask<Void, Void, Void>() { new AsyncTask<Void, Void, Void>() {
@Override @Override
@ -71,15 +74,24 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1); int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
long expiresIn = recipient.getExpireMessages() * 1000L; long expiresIn = recipient.getExpireMessages() * 1000L;
if (recipient.isGroupRecipient()) { 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()); 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); threadId = MessageSender.send(context, reply, -1, false, null);
} else if (TextSecurePreferences.isPushRegistered(context) && recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) { break;
}
case SecureMessage: {
OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn); OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn);
threadId = MessageSender.send(context, reply, -1, false, null); threadId = MessageSender.send(context, reply, -1, false, null);
} else { break;
}
case UnsecuredSmsMessage: {
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId); OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
threadId = MessageSender.send(context, reply, -1, false, null); threadId = MessageSender.send(context, reply, -1, true, null);
break;
}
default:
throw new AssertionError("Unknown Reply method");
} }
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true); List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
@ -91,6 +103,5 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
} }
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
} }
} }

View File

@ -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;
}
}
}

View File

@ -9,11 +9,11 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Action; import android.support.v4.app.NotificationCompat.Action;
import android.support.v4.app.RemoteInput; import android.support.v4.app.RemoteInput;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import org.thoughtcrime.securesms.logging.Log;
import com.bumptech.glide.load.engine.DiskCacheStrategy; 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.ContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.Slide;
@ -143,30 +144,34 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
public void addActions(@NonNull PendingIntent markReadIntent, public void addActions(@NonNull PendingIntent markReadIntent,
@NonNull PendingIntent quickReplyIntent, @NonNull PendingIntent quickReplyIntent,
@NonNull PendingIntent wearableReplyIntent) @NonNull PendingIntent wearableReplyIntent,
@NonNull ReplyMethod replyMethod)
{ {
Action markAsReadAction = new Action(R.drawable.check, Action markAsReadAction = new Action(R.drawable.check,
context.getString(R.string.MessageNotifier_mark_read), context.getString(R.string.MessageNotifier_mark_read),
markReadIntent); 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, Action replyAction = new Action(R.drawable.ic_reply_white_36dp,
context.getString(R.string.MessageNotifier_reply), actionName,
quickReplyIntent); quickReplyIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp, replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp,
context.getString(R.string.MessageNotifier_reply), actionName,
wearableReplyIntent) wearableReplyIntent)
.addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY) .addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY)
.setLabel(context.getString(R.string.MessageNotifier_reply)).build()) .setLabel(label).build())
.build(); .build();
} }
Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply, Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
context.getString(R.string.MessageNotifier_reply), actionName,
wearableReplyIntent) wearableReplyIntent)
.addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY) .addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY)
.setLabel(context.getString(R.string.MessageNotifier_reply)).build()) .setLabel(label).build())
.build(); .build();
addAction(markAsReadAction); addAction(markAsReadAction);
@ -176,6 +181,20 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
.addAction(wearableReplyAction)); .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, public void addMessageBody(@NonNull Recipient threadRecipient,
@NonNull Recipient individualRecipient, @NonNull Recipient individualRecipient,
@Nullable CharSequence messageBody) @Nullable CharSequence messageBody)