Browse Source

fix quick replies from notifications (#4250)

While working on #4249 I noticed that quick replies also don't work as
expected. The notification just stays in the sending state forever.
There are actually 2 problems:
- Notifications are sent in `NotificationFetcher` with the id of the
Mastodon notification as tag and the current account id as id. The wrong
notification id was forwarded to `SendStatusBroadcastReceiver` so it
never had a chance of updating the notification.
- Notifications containing an active remote input can't be cancelled
(they just stop their animation when doing so). So instead I update the
notification with info that the reply is being sent and have it dismiss
automatically.

I also tried replacing the original notification with the "sending"
notification of `SendStatusService`, but that doesn't work because
`Service.startForeground` doesn't have a tag parameter, only an id.

---------

Co-authored-by: Willow <charlag@tuta.io>
pull/4096/head
Konrad Pozniak 2 years ago committed by GitHub
parent
commit
7d3aafdd65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
  2. 51
      app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
  3. 4
      app/src/main/res/values/strings.xml

4
app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java

@ -97,7 +97,7 @@ public class NotificationHelper {
public static final String KEY_SENDER_ACCOUNT_FULL_NAME = "KEY_SENDER_ACCOUNT_FULL_NAME"; public static final String KEY_SENDER_ACCOUNT_FULL_NAME = "KEY_SENDER_ACCOUNT_FULL_NAME";
public static final String KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID"; public static final String KEY_SERVER_NOTIFICATION_ID = "KEY_SERVER_NOTIFICATION_ID";
public static final String KEY_CITED_STATUS_ID = "KEY_CITED_STATUS_ID"; public static final String KEY_CITED_STATUS_ID = "KEY_CITED_STATUS_ID";
@ -412,7 +412,7 @@ public class NotificationHelper {
.putExtra(KEY_SENDER_ACCOUNT_ID, account.getId()) .putExtra(KEY_SENDER_ACCOUNT_ID, account.getId())
.putExtra(KEY_SENDER_ACCOUNT_IDENTIFIER, account.getIdentifier()) .putExtra(KEY_SENDER_ACCOUNT_IDENTIFIER, account.getIdentifier())
.putExtra(KEY_SENDER_ACCOUNT_FULL_NAME, account.getFullName()) .putExtra(KEY_SENDER_ACCOUNT_FULL_NAME, account.getFullName())
.putExtra(KEY_NOTIFICATION_ID, notificationId) .putExtra(KEY_SERVER_NOTIFICATION_ID, body.getId())
.putExtra(KEY_CITED_STATUS_ID, inReplyToId) .putExtra(KEY_CITED_STATUS_ID, inReplyToId)
.putExtra(KEY_VISIBILITY, replyVisibility) .putExtra(KEY_VISIBILITY, replyVisibility)
.putExtra(KEY_SPOILER, contentWarning) .putExtra(KEY_SPOILER, contentWarning)

51
app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt

@ -45,7 +45,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
AndroidInjection.inject(this, context) AndroidInjection.inject(this, context)
if (intent.action == NotificationHelper.REPLY_ACTION) { if (intent.action == NotificationHelper.REPLY_ACTION) {
val notificationId = intent.getIntExtra(NotificationHelper.KEY_NOTIFICATION_ID, -1) val serverNotificationId = intent.getStringExtra(NotificationHelper.KEY_SERVER_NOTIFICATION_ID)
val senderId = intent.getLongExtra(NotificationHelper.KEY_SENDER_ACCOUNT_ID, -1) val senderId = intent.getLongExtra(NotificationHelper.KEY_SENDER_ACCOUNT_ID, -1)
val senderIdentifier = intent.getStringExtra( val senderIdentifier = intent.getStringExtra(
NotificationHelper.KEY_SENDER_ACCOUNT_IDENTIFIER NotificationHelper.KEY_SENDER_ACCOUNT_IDENTIFIER
@ -69,24 +69,23 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
if (account == null) { if (account == null) {
Log.w(TAG, "Account \"$senderId\" not found in database. Aborting quick reply!") Log.w(TAG, "Account \"$senderId\" not found in database. Aborting quick reply!")
val builder = NotificationCompat.Builder( val notification = NotificationCompat.Builder(
context, context,
NotificationHelper.CHANNEL_MENTION + senderIdentifier NotificationHelper.CHANNEL_MENTION + senderIdentifier
) )
.setSmallIcon(R.drawable.ic_notify) .setSmallIcon(R.drawable.ic_notify)
.setColor(context.getColor(R.color.tusky_blue)) .setColor(context.getColor(R.color.tusky_blue))
.setGroup(senderFullName) .setGroup(senderFullName)
.setDefaults(0) // So it doesn't ring twice, notify only in Target callback .setDefaults(0) // We don't want this to make any sound or vibration
.setOnlyAlertOnce(true)
builder.setContentTitle(context.getString(R.string.error_generic)) .setContentTitle(context.getString(R.string.error_generic))
builder.setContentText(context.getString(R.string.error_sender_account_gone)) .setContentText(context.getString(R.string.error_sender_account_gone))
.setSubText(senderFullName)
builder.setSubText(senderFullName) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setCategory(NotificationCompat.CATEGORY_SOCIAL)
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL) .build()
builder.setOnlyAlertOnce(true)
notificationManager.notify(serverNotificationId, senderId.toInt(), notification)
notificationManager.notify(notificationId, builder.build())
} else { } else {
val text = mentions.joinToString(" ", postfix = " ") { "@$it" } + message.toString() val text = mentions.joinToString(" ", postfix = " ") { "@$it" } + message.toString()
@ -114,25 +113,25 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
context.startService(sendIntent) context.startService(sendIntent)
val builder = NotificationCompat.Builder( // Notifications with remote input active can't be cancelled, so let's replace it with another one that will dismiss automatically
val notification = NotificationCompat.Builder(
context, context,
NotificationHelper.CHANNEL_MENTION + senderIdentifier NotificationHelper.CHANNEL_MENTION + senderIdentifier
) )
.setSmallIcon(R.drawable.ic_notify) .setSmallIcon(R.drawable.ic_notify)
.setColor(context.getColor(R.color.notification_color)) .setColor(context.getColor(R.color.notification_color))
.setGroup(senderFullName) .setGroup(senderFullName)
.setDefaults(0) // So it doesn't ring twice, notify only in Target callback .setDefaults(0) // We don't want this to make any sound or vibration
.setOnlyAlertOnce(true)
builder.setContentTitle(context.getString(R.string.post_sent)) .setContentTitle(context.getString(R.string.reply_sending))
builder.setContentText(context.getString(R.string.post_sent_long)) .setContentText(context.getString(R.string.reply_sending_long))
.setSubText(senderFullName)
builder.setSubText(senderFullName) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setCategory(NotificationCompat.CATEGORY_SOCIAL)
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL) .setTimeoutAfter(5000)
builder.setOnlyAlertOnce(true) .build()
// There is a separate "I am sending" notification, so simply remove the handled one. notificationManager.notify(serverNotificationId, senderId.toInt(), notification)
notificationManager.cancel(notificationId)
} }
} }
} }

4
app/src/main/res/values/strings.xml

@ -227,8 +227,8 @@
<string name="confirmation_domain_unmuted">%s unhidden</string> <string name="confirmation_domain_unmuted">%s unhidden</string>
<string name="confirmation_hashtag_unfollowed">#%s unfollowed</string> <string name="confirmation_hashtag_unfollowed">#%s unfollowed</string>
<string name="post_sent">Sent!</string> <string name="reply_sending">Sending…</string>
<string name="post_sent_long">Reply sent successfully.</string> <string name="reply_sending_long">Your reply is being sent.</string>
<string name="hint_domain">Which instance?</string> <string name="hint_domain">Which instance?</string>
<string name="hint_compose">What\'s happening?</string> <string name="hint_compose">What\'s happening?</string>

Loading…
Cancel
Save