mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 12:08:34 +00:00
Address API23 notification issues and update when conversation content changes.
This commit is contained in:
@@ -48,6 +48,7 @@ class MessageNotifierV2(context: Application) : MessageNotifier {
|
|||||||
@Volatile private var lastScheduledReminder: Long = 0
|
@Volatile private var lastScheduledReminder: Long = 0
|
||||||
@Volatile private var previousLockedStatus: Boolean = KeyCachingService.isLocked(context)
|
@Volatile private var previousLockedStatus: Boolean = KeyCachingService.isLocked(context)
|
||||||
@Volatile private var previousPrivacyPreference: NotificationPrivacyPreference = TextSecurePreferences.getNotificationPrivacy(context)
|
@Volatile private var previousPrivacyPreference: NotificationPrivacyPreference = TextSecurePreferences.getNotificationPrivacy(context)
|
||||||
|
@Volatile private var previousState: NotificationStateV2 = NotificationStateV2.EMPTY
|
||||||
|
|
||||||
private val threadReminders: MutableMap<Long, Reminder> = ConcurrentHashMap()
|
private val threadReminders: MutableMap<Long, Reminder> = ConcurrentHashMap()
|
||||||
private val stickyThreads: MutableMap<Long, StickyThread> = mutableMapOf()
|
private val stickyThreads: MutableMap<Long, StickyThread> = mutableMapOf()
|
||||||
@@ -167,9 +168,11 @@ class MessageNotifierV2(context: Application) : MessageNotifier {
|
|||||||
defaultBubbleState = defaultBubbleState,
|
defaultBubbleState = defaultBubbleState,
|
||||||
lastAudibleNotification = lastAudibleNotification,
|
lastAudibleNotification = lastAudibleNotification,
|
||||||
notificationConfigurationChanged = notificationConfigurationChanged,
|
notificationConfigurationChanged = notificationConfigurationChanged,
|
||||||
alertOverrides = alertOverrides
|
alertOverrides = alertOverrides,
|
||||||
|
previousState = previousState
|
||||||
)
|
)
|
||||||
|
|
||||||
|
previousState = state
|
||||||
lastAudibleNotification = System.currentTimeMillis()
|
lastAudibleNotification = System.currentTimeMillis()
|
||||||
|
|
||||||
updateReminderTimestamps(context, alertOverrides, threadsThatAlerted)
|
updateReminderTimestamps(context, alertOverrides, threadsThatAlerted)
|
||||||
@@ -281,7 +284,7 @@ private fun StatusBarNotification.isMessageNotification(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun NotificationManager.getDisplayedNotificationIds(): Result<Set<Int>> {
|
private fun NotificationManager.getDisplayedNotificationIds(): Result<Set<Int>> {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
if (Build.VERSION.SDK_INT < 24) {
|
||||||
return Result.failure(UnsupportedOperationException("SDK level too low"))
|
return Result.failure(UnsupportedOperationException("SDK level too low"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +297,7 @@ private fun NotificationManager.getDisplayedNotificationIds(): Result<Set<Int>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun NotificationManager.cancelOrphanedNotifications(context: Context, state: NotificationStateV2, stickyNotifications: Set<Int>) {
|
private fun NotificationManager.cancelOrphanedNotifications(context: Context, state: NotificationStateV2, stickyNotifications: Set<Int>) {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
if (Build.VERSION.SDK_INT < 24) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
abstract fun addMarkAsReadActionActual(state: NotificationStateV2)
|
abstract fun addMarkAsReadActionActual(state: NotificationStateV2)
|
||||||
abstract fun setPriority(priority: Int)
|
abstract fun setPriority(priority: Int)
|
||||||
abstract fun setAlarms(recipient: Recipient?)
|
abstract fun setAlarms(recipient: Recipient?)
|
||||||
abstract fun setTicker(ticker: CharSequence)
|
abstract fun setTicker(ticker: CharSequence?)
|
||||||
abstract fun addTurnOffJoinedNotificationsAction(pendingIntent: PendingIntent)
|
abstract fun addTurnOffJoinedNotificationsAction(pendingIntent: PendingIntent)
|
||||||
abstract fun setAutoCancel(autoCancel: Boolean)
|
abstract fun setAutoCancel(autoCancel: Boolean)
|
||||||
abstract fun build(): Notification
|
abstract fun build(): Notification
|
||||||
@@ -100,8 +100,8 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWhen(notificationItem: NotificationItemV2) {
|
fun setWhen(notificationItem: NotificationItemV2?) {
|
||||||
if (notificationItem.timestamp != 0L) {
|
if (notificationItem != null && notificationItem.timestamp != 0L) {
|
||||||
setWhen(notificationItem.timestamp)
|
setWhen(notificationItem.timestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,12 +136,12 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSummaryContentText(recipient: Recipient) {
|
fun setSummaryContentText(recipient: Recipient?) {
|
||||||
if (privacy.isDisplayContact) {
|
if (privacy.isDisplayContact && recipient != null) {
|
||||||
setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s, recipient.getDisplayName(context)))
|
setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s, recipient.getDisplayName(context)))
|
||||||
}
|
}
|
||||||
|
|
||||||
recipient.notificationChannel?.let { channel -> setChannelId(channel) }
|
recipient?.notificationChannel?.let { channel -> setChannelId(channel) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLights() {
|
fun setLights() {
|
||||||
@@ -244,8 +244,8 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
|
|
||||||
val self: PersonCompat = PersonCompat.Builder()
|
val self: PersonCompat = PersonCompat.Builder()
|
||||||
.setBot(false)
|
.setBot(false)
|
||||||
.setName(Recipient.self().getDisplayName(context))
|
.setName(if (includeShortcut) Recipient.self().getDisplayName(context) else context.getString(R.string.SingleRecipientNotificationBuilder_you))
|
||||||
.setIcon(Recipient.self().getContactDrawable(context).toLargeBitmap(context).toIconCompat())
|
.setIcon(if (includeShortcut) Recipient.self().getContactDrawable(context).toLargeBitmap(context).toIconCompat() else null)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val messagingStyle: NotificationCompat.MessagingStyle = NotificationCompat.MessagingStyle(self)
|
val messagingStyle: NotificationCompat.MessagingStyle = NotificationCompat.MessagingStyle(self)
|
||||||
@@ -332,7 +332,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setGroup(group: String) {
|
override fun setGroup(group: String) {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
if (Build.VERSION.SDK_INT < 24) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setGroupAlertBehavior(behavior: Int) {
|
override fun setGroupAlertBehavior(behavior: Int) {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
if (Build.VERSION.SDK_INT < 24) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
builder.setContentText(contentText)
|
builder.setContentText(contentText)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTicker(ticker: CharSequence) {
|
override fun setTicker(ticker: CharSequence?) {
|
||||||
builder.setTicker(ticker)
|
builder.setTicker(ticker)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,8 +489,8 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
override fun addMessagesActual(conversation: NotificationConversation, includeShortcut: Boolean) {
|
override fun addMessagesActual(conversation: NotificationConversation, includeShortcut: Boolean) {
|
||||||
val self: Person = Person.Builder()
|
val self: Person = Person.Builder()
|
||||||
.setBot(false)
|
.setBot(false)
|
||||||
.setName(Recipient.self().getDisplayName(context))
|
.setName(if (includeShortcut) Recipient.self().getDisplayName(context) else context.getString(R.string.SingleRecipientNotificationBuilder_you))
|
||||||
.setIcon(Recipient.self().getContactDrawable(context).toLargeBitmap(context).toIcon())
|
.setIcon(if (includeShortcut) Recipient.self().getContactDrawable(context).toLargeBitmap(context).toIcon() else null)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val messagingStyle: Notification.MessagingStyle = Notification.MessagingStyle(self)
|
val messagingStyle: Notification.MessagingStyle = Notification.MessagingStyle(self)
|
||||||
@@ -598,7 +598,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||||||
builder.setContentText(contentText)
|
builder.setContentText(contentText)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTicker(ticker: CharSequence) {
|
override fun setTicker(ticker: CharSequence?) {
|
||||||
builder.setTicker(ticker)
|
builder.setTicker(ticker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,14 +88,10 @@ data class NotificationConversation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getConversationTitle(context: Context): CharSequence? {
|
fun getConversationTitle(context: Context): CharSequence? {
|
||||||
if (isGroup) {
|
if (TextSecurePreferences.getNotificationPrivacy(context).isDisplayContact) {
|
||||||
return if (TextSecurePreferences.getNotificationPrivacy(context).isDisplayContact) {
|
return if (isGroup) recipient.getDisplayName(context) else null
|
||||||
recipient.getDisplayName(context)
|
|
||||||
} else {
|
|
||||||
context.getString(R.string.SingleRecipientNotificationBuilder_signal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null
|
return context.getString(R.string.SingleRecipientNotificationBuilder_signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWhen(): Long {
|
fun getWhen(): Long {
|
||||||
@@ -114,6 +110,14 @@ data class NotificationConversation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasSameContent(other: NotificationConversation?): Boolean {
|
||||||
|
if (other == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageCount == other.messageCount && notificationItems.zip(other.notificationItems).all { (item, otherItem) -> item.hasSameContent(otherItem) }
|
||||||
|
}
|
||||||
|
|
||||||
fun getPendingIntent(context: Context): PendingIntent {
|
fun getPendingIntent(context: Context): PendingIntent {
|
||||||
val intent: Intent = ConversationIntents.createBuilder(context, recipient.id, threadId)
|
val intent: Intent = ConversationIntents.createBuilder(context, recipient.id, threadId)
|
||||||
.withStartingPosition(mostRecentNotification.getStartingPosition(context))
|
.withStartingPosition(mostRecentNotification.getStartingPosition(context))
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package org.thoughtcrime.securesms.notifications.v2
|
package org.thoughtcrime.securesms.notifications.v2
|
||||||
|
|
||||||
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import com.bumptech.glide.load.MultiTransformation
|
import com.bumptech.glide.load.MultiTransformation
|
||||||
import com.bumptech.glide.load.Transformation
|
import com.bumptech.glide.load.Transformation
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
@@ -17,6 +19,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
|
|||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
|
import org.thoughtcrime.securesms.notifications.NotificationIds
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil
|
import org.thoughtcrime.securesms.util.BitmapUtil
|
||||||
import org.thoughtcrime.securesms.util.BlurTransformation
|
import org.thoughtcrime.securesms.util.BlurTransformation
|
||||||
@@ -84,3 +87,13 @@ fun Intent.makeUniqueToPreventMerging(): Intent {
|
|||||||
fun Recipient.getFallback(context: Context): FallbackContactPhoto {
|
fun Recipient.getFallback(context: Context): FallbackContactPhoto {
|
||||||
return GeneratedContactPhoto(getDisplayName(context), R.drawable.ic_profile_outline_40)
|
return GeneratedContactPhoto(getDisplayName(context), R.drawable.ic_profile_outline_40)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun NotificationManager.isDisplayingSummaryNotification(): Boolean {
|
||||||
|
if (Build.VERSION.SDK_INT > 23) {
|
||||||
|
try {
|
||||||
|
return activeNotifications.any { notification -> notification.id == NotificationIds.MESSAGE_SUMMARY }
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.notifications.v2
|
|||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -46,15 +45,16 @@ object NotificationFactory {
|
|||||||
defaultBubbleState: BubbleUtil.BubbleState,
|
defaultBubbleState: BubbleUtil.BubbleState,
|
||||||
lastAudibleNotification: Long,
|
lastAudibleNotification: Long,
|
||||||
notificationConfigurationChanged: Boolean,
|
notificationConfigurationChanged: Boolean,
|
||||||
alertOverrides: Set<Long>
|
alertOverrides: Set<Long>,
|
||||||
|
previousState: NotificationStateV2
|
||||||
): Set<Long> {
|
): Set<Long> {
|
||||||
if (state.isEmpty) {
|
if (state.isEmpty) {
|
||||||
Log.d(TAG, "State is empty, bailing")
|
Log.d(TAG, "State is empty, bailing")
|
||||||
return emptySet()
|
return emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
val nonVisibleThreadCount = state.conversations.count { it.threadId != visibleThreadId }
|
val nonVisibleThreadCount: Int = state.conversations.count { it.threadId != visibleThreadId }
|
||||||
return if (Build.VERSION.SDK_INT < 23) {
|
return if (Build.VERSION.SDK_INT < 24) {
|
||||||
notify19(
|
notify19(
|
||||||
context = context,
|
context = context,
|
||||||
state = state,
|
state = state,
|
||||||
@@ -66,7 +66,7 @@ object NotificationFactory {
|
|||||||
nonVisibleThreadCount = nonVisibleThreadCount
|
nonVisibleThreadCount = nonVisibleThreadCount
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
notify23(
|
notify24(
|
||||||
context = context,
|
context = context,
|
||||||
state = state,
|
state = state,
|
||||||
visibleThreadId = visibleThreadId,
|
visibleThreadId = visibleThreadId,
|
||||||
@@ -75,7 +75,8 @@ object NotificationFactory {
|
|||||||
lastAudibleNotification = lastAudibleNotification,
|
lastAudibleNotification = lastAudibleNotification,
|
||||||
notificationConfigurationChanged = notificationConfigurationChanged,
|
notificationConfigurationChanged = notificationConfigurationChanged,
|
||||||
alertOverrides = alertOverrides,
|
alertOverrides = alertOverrides,
|
||||||
nonVisibleThreadCount = nonVisibleThreadCount
|
nonVisibleThreadCount = nonVisibleThreadCount,
|
||||||
|
previousState = previousState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,8 +122,8 @@ object NotificationFactory {
|
|||||||
return threadsThatNewlyAlerted
|
return threadsThatNewlyAlerted
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(23)
|
@TargetApi(24)
|
||||||
private fun notify23(
|
private fun notify24(
|
||||||
context: Context,
|
context: Context,
|
||||||
state: NotificationStateV2,
|
state: NotificationStateV2,
|
||||||
visibleThreadId: Long,
|
visibleThreadId: Long,
|
||||||
@@ -131,7 +132,8 @@ object NotificationFactory {
|
|||||||
lastAudibleNotification: Long,
|
lastAudibleNotification: Long,
|
||||||
notificationConfigurationChanged: Boolean,
|
notificationConfigurationChanged: Boolean,
|
||||||
alertOverrides: Set<Long>,
|
alertOverrides: Set<Long>,
|
||||||
nonVisibleThreadCount: Int
|
nonVisibleThreadCount: Int,
|
||||||
|
previousState: NotificationStateV2
|
||||||
): Set<Long> {
|
): Set<Long> {
|
||||||
val threadsThatNewlyAlerted: MutableSet<Long> = mutableSetOf()
|
val threadsThatNewlyAlerted: MutableSet<Long> = mutableSetOf()
|
||||||
|
|
||||||
@@ -139,7 +141,7 @@ object NotificationFactory {
|
|||||||
if (conversation.threadId == visibleThreadId && conversation.hasNewNotifications()) {
|
if (conversation.threadId == visibleThreadId && conversation.hasNewNotifications()) {
|
||||||
Log.internal().i(TAG, "Thread is visible, notifying in thread. notificationId: ${conversation.notificationId}")
|
Log.internal().i(TAG, "Thread is visible, notifying in thread. notificationId: ${conversation.notificationId}")
|
||||||
notifyInThread(context, conversation.recipient, lastAudibleNotification)
|
notifyInThread(context, conversation.recipient, lastAudibleNotification)
|
||||||
} else if (notificationConfigurationChanged || conversation.hasNewNotifications() || alertOverrides.contains(conversation.threadId)) {
|
} else if (notificationConfigurationChanged || conversation.hasNewNotifications() || alertOverrides.contains(conversation.threadId) || !conversation.hasSameContent(previousState.getConversation(conversation.threadId))) {
|
||||||
if (conversation.hasNewNotifications()) {
|
if (conversation.hasNewNotifications()) {
|
||||||
threadsThatNewlyAlerted += conversation.threadId
|
threadsThatNewlyAlerted += conversation.threadId
|
||||||
}
|
}
|
||||||
@@ -206,7 +208,7 @@ object NotificationFactory {
|
|||||||
builder.addTurnOffJoinedNotificationsAction(conversation.getTurnOffJoinedNotificationsIntent(context))
|
builder.addTurnOffJoinedNotificationsAction(conversation.getTurnOffJoinedNotificationsIntent(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
val notificationId: Int = if (Build.VERSION.SDK_INT < 23) NotificationIds.MESSAGE_SUMMARY else conversation.notificationId
|
val notificationId: Int = if (Build.VERSION.SDK_INT < 24) NotificationIds.MESSAGE_SUMMARY else conversation.notificationId
|
||||||
|
|
||||||
NotificationManagerCompat.from(context).safelyNotify(context, conversation.recipient, notificationId, builder.build())
|
NotificationManagerCompat.from(context).safelyNotify(context, conversation.recipient, notificationId, builder.build())
|
||||||
}
|
}
|
||||||
@@ -240,7 +242,7 @@ object NotificationFactory {
|
|||||||
setPriority(TextSecurePreferences.getNotificationPriority(context))
|
setPriority(TextSecurePreferences.getNotificationPriority(context))
|
||||||
setLights()
|
setLights()
|
||||||
setAlarms(state.mostRecentSender)
|
setAlarms(state.mostRecentSender)
|
||||||
setTicker(state.mostRecentNotification.getStyledPrimaryText(context, true))
|
setTicker(state.mostRecentNotification?.getStyledPrimaryText(context, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "showing summary notification")
|
Log.d(TAG, "showing summary notification")
|
||||||
@@ -313,16 +315,6 @@ object NotificationFactory {
|
|||||||
NotificationManagerCompat.from(context).safelyNotify(context, recipient, threadId.toInt(), builder.build())
|
NotificationManagerCompat.from(context).safelyNotify(context, recipient, threadId.toInt(), builder.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun NotificationManager.isDisplayingSummaryNotification(): Boolean {
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
try {
|
|
||||||
return activeNotifications.any { notification -> notification.id == NotificationIds.MESSAGE_SUMMARY }
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun NotificationManagerCompat.safelyNotify(context: Context, threadRecipient: Recipient?, notificationId: Int, notification: Notification) {
|
private fun NotificationManagerCompat.safelyNotify(context: Context, threadRecipient: Recipient?, notificationId: Int, notification: Notification) {
|
||||||
try {
|
try {
|
||||||
notify(notificationId, notification)
|
notify(notificationId, notification)
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ sealed class NotificationItemV2(val threadRecipient: Recipient, protected val re
|
|||||||
return if (TextSecurePreferences.getNotificationPrivacy(context).isDisplayContact) {
|
return if (TextSecurePreferences.getNotificationPrivacy(context).isDisplayContact) {
|
||||||
individualRecipient.getDisplayName(context)
|
individualRecipient.getDisplayName(context)
|
||||||
} else {
|
} else {
|
||||||
""
|
context.getString(R.string.SingleRecipientNotificationBuilder_signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +133,16 @@ sealed class NotificationItemV2(val threadRecipient: Recipient, protected val re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasSameContent(other: NotificationItemV2): Boolean {
|
||||||
|
return timestamp == other.timestamp &&
|
||||||
|
id == other.id &&
|
||||||
|
isMms == other.isMms &&
|
||||||
|
individualRecipient == other.individualRecipient &&
|
||||||
|
individualRecipient.hasSameContent(other.individualRecipient) &&
|
||||||
|
slideDeck?.thumbnailSlide?.isInProgress == other.slideDeck?.thumbnailSlide?.isInProgress &&
|
||||||
|
record.isRemoteDelete == other.record.isRemoteDelete
|
||||||
|
}
|
||||||
|
|
||||||
private fun CharSequence?.trimToDisplayLength(): CharSequence {
|
private fun CharSequence?.trimToDisplayLength(): CharSequence {
|
||||||
val text: CharSequence = this ?: ""
|
val text: CharSequence = this ?: ""
|
||||||
return if (text.length <= AbstractNotificationBuilder.MAX_DISPLAY_LENGTH) {
|
return if (text.length <= AbstractNotificationBuilder.MAX_DISPLAY_LENGTH) {
|
||||||
|
|||||||
@@ -33,16 +33,20 @@ data class NotificationStateV2(val conversations: List<NotificationConversation>
|
|||||||
.toSet()
|
.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
val mostRecentNotification: NotificationItemV2
|
val mostRecentNotification: NotificationItemV2?
|
||||||
get() = notificationItems.last()
|
get() = notificationItems.lastOrNull()
|
||||||
|
|
||||||
val mostRecentSender: Recipient
|
val mostRecentSender: Recipient?
|
||||||
get() = mostRecentNotification.individualRecipient
|
get() = mostRecentNotification?.individualRecipient
|
||||||
|
|
||||||
fun getNonVisibleConversation(visibleThreadId: Long): List<NotificationConversation> {
|
fun getNonVisibleConversation(visibleThreadId: Long): List<NotificationConversation> {
|
||||||
return conversations.filterNot { it.threadId == visibleThreadId }
|
return conversations.filterNot { it.threadId == visibleThreadId }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getConversation(threadId: Long): NotificationConversation? {
|
||||||
|
return conversations.firstOrNull { it.threadId == threadId }
|
||||||
|
}
|
||||||
|
|
||||||
fun getDeleteIntent(context: Context): PendingIntent? {
|
fun getDeleteIntent(context: Context): PendingIntent? {
|
||||||
val ids = LongArray(messageCount)
|
val ids = LongArray(messageCount)
|
||||||
val mms = BooleanArray(ids.size)
|
val mms = BooleanArray(ids.size)
|
||||||
|
|||||||
@@ -1751,6 +1751,7 @@
|
|||||||
<string name="SingleRecipientNotificationBuilder_signal">Signal</string>
|
<string name="SingleRecipientNotificationBuilder_signal">Signal</string>
|
||||||
<string name="SingleRecipientNotificationBuilder_new_message">New message</string>
|
<string name="SingleRecipientNotificationBuilder_new_message">New message</string>
|
||||||
<string name="SingleRecipientNotificationBuilder_message_request">Message request</string>
|
<string name="SingleRecipientNotificationBuilder_message_request">Message request</string>
|
||||||
|
<string name="SingleRecipientNotificationBuilder_you">You</string>
|
||||||
|
|
||||||
<!-- ThumbnailView -->
|
<!-- ThumbnailView -->
|
||||||
<string name="ThumbnailView_Play_video_description">Play video</string>
|
<string name="ThumbnailView_Play_video_description">Play video</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user