offer quick reply on android N
This commit is contained in:
parent
542626758d
commit
2e4713897d
|
@ -13,6 +13,7 @@ import android.os.SystemClock;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.NotificationCompat.BigPictureStyle;
|
import android.support.v4.app.NotificationCompat.BigPictureStyle;
|
||||||
import android.support.v4.app.NotificationCompat.Builder;
|
import android.support.v4.app.NotificationCompat.Builder;
|
||||||
|
import android.support.v4.app.RemoteInput;
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
|
@ -118,6 +119,13 @@ public class NotificationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void pushFromDirectReply(final Message message) {
|
||||||
|
synchronized (notifications) {
|
||||||
|
pushToStack(message);
|
||||||
|
updateNotification(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void finishBacklog(boolean notify) {
|
public void finishBacklog(boolean notify) {
|
||||||
synchronized (notifications) {
|
synchronized (notifications) {
|
||||||
mXmppConnectionService.updateUnreadCountBadge();
|
mXmppConnectionService.updateUnreadCountBadge();
|
||||||
|
@ -170,6 +178,8 @@ public class NotificationService {
|
||||||
public void clear(final Conversation conversation) {
|
public void clear(final Conversation conversation) {
|
||||||
synchronized (notifications) {
|
synchronized (notifications) {
|
||||||
notifications.remove(conversation.getUuid());
|
notifications.remove(conversation.getUuid());
|
||||||
|
final NotificationManager nm = (NotificationManager) mXmppConnectionService.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
nm.cancel(conversation.getUuid(), NOTIFICATION_ID);
|
||||||
updateNotification(false);
|
updateNotification(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +200,7 @@ public class NotificationService {
|
||||||
this.markLastNotification();
|
this.markLastNotification();
|
||||||
}
|
}
|
||||||
final Builder mBuilder;
|
final Builder mBuilder;
|
||||||
if (notifications.size() == 1) {
|
if (notifications.size() == 1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||||
mBuilder = buildSingleConversations(notifications.values().iterator().next());
|
mBuilder = buildSingleConversations(notifications.values().iterator().next());
|
||||||
modifyForSoundVibrationAndLight(mBuilder, notify, preferences);
|
modifyForSoundVibrationAndLight(mBuilder, notify, preferences);
|
||||||
notificationManager.notify(NOTIFICATION_ID, mBuilder.build());
|
notificationManager.notify(NOTIFICATION_ID, mBuilder.build());
|
||||||
|
@ -202,7 +212,7 @@ public class NotificationService {
|
||||||
Builder singleBuilder = buildSingleConversations(entry.getValue());
|
Builder singleBuilder = buildSingleConversations(entry.getValue());
|
||||||
singleBuilder.setGroup(CONVERSATIONS_GROUP);
|
singleBuilder.setGroup(CONVERSATIONS_GROUP);
|
||||||
modifyForSoundVibrationAndLight(singleBuilder,notify,preferences);
|
modifyForSoundVibrationAndLight(singleBuilder,notify,preferences);
|
||||||
notificationManager.notify(entry.getKey().hashCode() % 435301 ,singleBuilder.build());
|
notificationManager.notify(entry.getKey(), NOTIFICATION_ID ,singleBuilder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,14 +304,19 @@ public class NotificationService {
|
||||||
} else {
|
} else {
|
||||||
modifyForTextOnly(mBuilder, messages);
|
modifyForTextOnly(mBuilder, messages);
|
||||||
}
|
}
|
||||||
if ((message = getFirstDownloadableMessage(messages)) != null) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
mBuilder.addAction(
|
RemoteInput remoteInput = new RemoteInput.Builder("text_reply").setLabel(UIHelper.getMessageHint(mXmppConnectionService, conversation)).build();
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_send_text_offline, "Reply", createReplyIntent(conversation)).addRemoteInput(remoteInput).build();
|
||||||
R.drawable.ic_file_download_white_24dp : R.drawable.ic_action_download,
|
mBuilder.addAction(action);
|
||||||
mXmppConnectionService.getResources().getString(R.string.download_x_file,
|
if ((message = getFirstDownloadableMessage(messages)) != null) {
|
||||||
UIHelper.getFileDescriptionString(mXmppConnectionService, message)),
|
mBuilder.addAction(
|
||||||
createDownloadIntent(message)
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||||
);
|
R.drawable.ic_file_download_white_24dp : R.drawable.ic_action_download,
|
||||||
|
mXmppConnectionService.getResources().getString(R.string.download_x_file,
|
||||||
|
UIHelper.getFileDescriptionString(mXmppConnectionService, message)),
|
||||||
|
createDownloadIntent(message)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((message = getFirstLocationMessage(messages)) != null) {
|
if ((message = getFirstLocationMessage(messages)) != null) {
|
||||||
mBuilder.addAction(R.drawable.ic_room_white_24dp,
|
mBuilder.addAction(R.drawable.ic_room_white_24dp,
|
||||||
|
@ -332,8 +347,9 @@ public class NotificationService {
|
||||||
final BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
|
final BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
|
||||||
bigPictureStyle.bigPicture(bitmap);
|
bigPictureStyle.bigPicture(bitmap);
|
||||||
if (tmp.size() > 0) {
|
if (tmp.size() > 0) {
|
||||||
bigPictureStyle.setSummaryText(getMergedBodies(tmp));
|
CharSequence text = getMergedBodies(tmp);
|
||||||
builder.setContentText(UIHelper.getMessagePreview(mXmppConnectionService, tmp.get(0)).first);
|
bigPictureStyle.setSummaryText(text);
|
||||||
|
builder.setContentText(text);
|
||||||
} else {
|
} else {
|
||||||
builder.setContentText(mXmppConnectionService.getString(
|
builder.setContentText(mXmppConnectionService.getString(
|
||||||
R.string.received_x_file,
|
R.string.received_x_file,
|
||||||
|
@ -354,7 +370,7 @@ public class NotificationService {
|
||||||
}
|
}
|
||||||
for (Message message : messages) {
|
for (Message message : messages) {
|
||||||
String sender = message.getStatus() == Message.STATUS_RECEIVED ? UIHelper.getMessageDisplayName(message) : null;
|
String sender = message.getStatus() == Message.STATUS_RECEIVED ? UIHelper.getMessageDisplayName(message) : null;
|
||||||
messagingStyle.addMessage(message.getBody().trim(), message.getTimeSent(), sender);
|
messagingStyle.addMessage(UIHelper.getMessagePreview(mXmppConnectionService,message).first, message.getTimeSent(), sender);
|
||||||
}
|
}
|
||||||
builder.setStyle(messagingStyle);
|
builder.setStyle(messagingStyle);
|
||||||
} else {
|
} else {
|
||||||
|
@ -364,15 +380,19 @@ public class NotificationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message getImage(final Iterable<Message> messages) {
|
private Message getImage(final Iterable<Message> messages) {
|
||||||
|
Message image = null;
|
||||||
for (final Message message : messages) {
|
for (final Message message : messages) {
|
||||||
|
if (message.getStatus() != Message.STATUS_RECEIVED) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (message.getType() != Message.TYPE_TEXT
|
if (message.getType() != Message.TYPE_TEXT
|
||||||
&& message.getTransferable() == null
|
&& message.getTransferable() == null
|
||||||
&& message.getEncryption() != Message.ENCRYPTION_PGP
|
&& message.getEncryption() != Message.ENCRYPTION_PGP
|
||||||
&& message.getFileParams().height > 0) {
|
&& message.getFileParams().height > 0) {
|
||||||
return message;
|
image = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message getFirstDownloadableMessage(final Iterable<Message> messages) {
|
private Message getFirstDownloadableMessage(final Iterable<Message> messages) {
|
||||||
|
@ -448,11 +468,18 @@ public class NotificationService {
|
||||||
intent.setAction(XmppConnectionService.ACTION_CLEAR_NOTIFICATION);
|
intent.setAction(XmppConnectionService.ACTION_CLEAR_NOTIFICATION);
|
||||||
if (conversation != null) {
|
if (conversation != null) {
|
||||||
intent.putExtra("uuid", conversation.getUuid());
|
intent.putExtra("uuid", conversation.getUuid());
|
||||||
return PendingIntent.getService(mXmppConnectionService, conversation.getUuid().hashCode() % 47528, intent, 0);
|
return PendingIntent.getService(mXmppConnectionService, conversation.getUuid().hashCode() % 247527, intent, 0);
|
||||||
}
|
}
|
||||||
return PendingIntent.getService(mXmppConnectionService, 0, intent, 0);
|
return PendingIntent.getService(mXmppConnectionService, 0, intent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PendingIntent createReplyIntent(Conversation conversation) {
|
||||||
|
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
|
||||||
|
intent.setAction(XmppConnectionService.ACTION_REPLY_TO_CONVERSATION);
|
||||||
|
intent.putExtra("uuid",conversation.getUuid());
|
||||||
|
return PendingIntent.getService(mXmppConnectionService, conversation.getUuid().hashCode() % 402361, intent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private PendingIntent createDisableForeground() {
|
private PendingIntent createDisableForeground() {
|
||||||
final Intent intent = new Intent(mXmppConnectionService,
|
final Intent intent = new Intent(mXmppConnectionService,
|
||||||
XmppConnectionService.class);
|
XmppConnectionService.class);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import android.os.SystemClock;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.security.KeyChain;
|
import android.security.KeyChain;
|
||||||
|
import android.support.v4.app.RemoteInput;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
|
@ -128,6 +129,7 @@ import me.leolin.shortcutbadger.ShortcutBadger;
|
||||||
|
|
||||||
public class XmppConnectionService extends Service {
|
public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
|
public static final String ACTION_REPLY_TO_CONVERSATION = "reply_to_conversations";
|
||||||
public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification";
|
public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification";
|
||||||
public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground";
|
public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground";
|
||||||
public static final String ACTION_TRY_AGAIN = "try_again";
|
public static final String ACTION_TRY_AGAIN = "try_again";
|
||||||
|
@ -526,6 +528,7 @@ public class XmppConnectionService extends Service {
|
||||||
final String action = intent == null ? null : intent.getAction();
|
final String action = intent == null ? null : intent.getAction();
|
||||||
boolean interactive = false;
|
boolean interactive = false;
|
||||||
if (action != null) {
|
if (action != null) {
|
||||||
|
final Conversation c = findConversationByUuid(intent.getStringExtra("uuid"));
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ConnectivityManager.CONNECTIVITY_ACTION:
|
case ConnectivityManager.CONNECTIVITY_ACTION:
|
||||||
if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) {
|
if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) {
|
||||||
|
@ -541,7 +544,6 @@ public class XmppConnectionService extends Service {
|
||||||
logoutAndSave(true);
|
logoutAndSave(true);
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
case ACTION_CLEAR_NOTIFICATION:
|
case ACTION_CLEAR_NOTIFICATION:
|
||||||
final Conversation c = findConversationByUuid(intent.getStringExtra("uuid"));
|
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
mNotificationService.clear(c);
|
mNotificationService.clear(c);
|
||||||
} else {
|
} else {
|
||||||
|
@ -568,6 +570,14 @@ public class XmppConnectionService extends Service {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ACTION_REPLY_TO_CONVERSATION:
|
||||||
|
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
|
||||||
|
if (remoteInput != null && c != null) {
|
||||||
|
|
||||||
|
String body = remoteInput.getString("text_reply");
|
||||||
|
directReply(c,body);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case AudioManager.RINGER_MODE_CHANGED_ACTION:
|
case AudioManager.RINGER_MODE_CHANGED_ACTION:
|
||||||
if (xaOnSilentMode()) {
|
if (xaOnSilentMode()) {
|
||||||
refreshAllPresences();
|
refreshAllPresences();
|
||||||
|
@ -687,6 +697,33 @@ public class XmppConnectionService extends Service {
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void directReply(Conversation conversation, String body) {
|
||||||
|
Message message = new Message(conversation,body,conversation.getNextEncryption());
|
||||||
|
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||||
|
getPgpEngine().encrypt(message, new UiCallback<Message>() {
|
||||||
|
@Override
|
||||||
|
public void success(Message message) {
|
||||||
|
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
|
||||||
|
sendMessage(message);
|
||||||
|
mNotificationService.pushFromDirectReply(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(int errorCode, Message object) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void userInputRequried(PendingIntent pi, Message object) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sendMessage(message);
|
||||||
|
mNotificationService.pushFromDirectReply(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean xaOnSilentMode() {
|
private boolean xaOnSilentMode() {
|
||||||
return getPreferences().getBoolean("xa_on_silent_mode", false);
|
return getPreferences().getBoolean("xa_on_silent_mode", false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,31 +363,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
|
||||||
} else if (multi && !conversation.getMucOptions().participating()) {
|
} else if (multi && !conversation.getMucOptions().participating()) {
|
||||||
this.mEditMessage.setHint(R.string.you_are_not_participating);
|
this.mEditMessage.setHint(R.string.you_are_not_participating);
|
||||||
} else {
|
} else {
|
||||||
switch (conversation.getNextEncryption()) {
|
this.mEditMessage.setHint(UIHelper.getMessageHint(activity,conversation));
|
||||||
case Message.ENCRYPTION_NONE:
|
|
||||||
if (Config.multipleEncryptionChoices()) {
|
|
||||||
mEditMessage.setHint(getString(R.string.send_unencrypted_message));
|
|
||||||
} else {
|
|
||||||
mEditMessage.setHint(getString(R.string.send_message_to_x,conversation.getName()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Message.ENCRYPTION_OTR:
|
|
||||||
mEditMessage.setHint(getString(R.string.send_otr_message));
|
|
||||||
break;
|
|
||||||
case Message.ENCRYPTION_AXOLOTL:
|
|
||||||
AxolotlService axolotlService = conversation.getAccount().getAxolotlService();
|
|
||||||
if (axolotlService != null && axolotlService.trustedSessionVerified(conversation)) {
|
|
||||||
mEditMessage.setHint(getString(R.string.send_omemo_x509_message));
|
|
||||||
} else {
|
|
||||||
mEditMessage.setHint(getString(R.string.send_omemo_message));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Message.ENCRYPTION_PGP:
|
|
||||||
mEditMessage.setHint(getString(R.string.send_pgp_message));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
getActivity().invalidateOptionsMenu();
|
getActivity().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@ import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.entities.ListItem;
|
import eu.siacs.conversations.entities.ListItem;
|
||||||
|
@ -74,8 +76,7 @@ public class UIHelper {
|
||||||
} else if (difference < 60 * 2) {
|
} else if (difference < 60 * 2) {
|
||||||
return context.getString(R.string.minute_ago);
|
return context.getString(R.string.minute_ago);
|
||||||
} else if (difference < 60 * 15) {
|
} else if (difference < 60 * 15) {
|
||||||
return context.getString(R.string.minutes_ago,
|
return context.getString(R.string.minutes_ago,Math.round(difference / 60.0));
|
||||||
Math.round(difference / 60.0));
|
|
||||||
} else if (today(date)) {
|
} else if (today(date)) {
|
||||||
java.text.DateFormat df = DateFormat.getTimeFormat(context);
|
java.text.DateFormat df = DateFormat.getTimeFormat(context);
|
||||||
return df.format(date);
|
return df.format(date);
|
||||||
|
@ -252,6 +253,30 @@ public class UIHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getMessageHint(Context context, Conversation conversation) {
|
||||||
|
switch (conversation.getNextEncryption()) {
|
||||||
|
case Message.ENCRYPTION_NONE:
|
||||||
|
if (Config.multipleEncryptionChoices()) {
|
||||||
|
return context.getString(R.string.send_unencrypted_message);
|
||||||
|
} else {
|
||||||
|
return context.getString(R.string.send_message_to_x,conversation.getName());
|
||||||
|
}
|
||||||
|
case Message.ENCRYPTION_OTR:
|
||||||
|
return context.getString(R.string.send_otr_message);
|
||||||
|
case Message.ENCRYPTION_AXOLOTL:
|
||||||
|
AxolotlService axolotlService = conversation.getAccount().getAxolotlService();
|
||||||
|
if (axolotlService != null && axolotlService.trustedSessionVerified(conversation)) {
|
||||||
|
return context.getString(R.string.send_omemo_x509_message);
|
||||||
|
} else {
|
||||||
|
return context.getString(R.string.send_omemo_message);
|
||||||
|
}
|
||||||
|
case Message.ENCRYPTION_PGP:
|
||||||
|
return context.getString(R.string.send_pgp_message);
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String getDisplayedMucCounterpart(final Jid counterpart) {
|
public static String getDisplayedMucCounterpart(final Jid counterpart) {
|
||||||
if (counterpart==null) {
|
if (counterpart==null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
Loading…
Reference in a new issue