mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-09-20 00:35:47 +01:00
Remove calls from unread reminders.
This commit is contained in:
+1
-3
@@ -42,7 +42,6 @@ import org.thoughtcrime.securesms.calls.quality.CallQualityBottomSheetFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.ReminderType
|
||||
import org.thoughtcrime.securesms.components.settings.app.privacy.advanced.AdvancedPrivacySettingsRepository
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
@@ -440,8 +439,7 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
||||
title = DSLSettingsText.from("Run unread reminder job"),
|
||||
summary = DSLSettingsText.from("Generates an unread reminder notification based on unreads and muted preferences. Skips the three day cooldown."),
|
||||
onClick = {
|
||||
val threadIds = (SignalDatabase.threads.getMutedThreadIds(ReminderType.MESSAGES, 0) + SignalDatabase.threads.getMutedThreadIds(ReminderType.CALLS, 0)).distinct()
|
||||
threadIds.forEach { threadId -> UnreadReminderJob.enqueue(threadId, 0) }
|
||||
SignalDatabase.threads.getMutedThreadIds(0).forEach { threadId -> UnreadReminderJob.enqueue(threadId, 0) }
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ package org.thoughtcrime.securesms.components.settings.app.notifications
|
||||
*/
|
||||
enum class ReminderType {
|
||||
MESSAGES,
|
||||
CALLS,
|
||||
MENTIONS,
|
||||
REPLIES
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.thoughtcrime.securesms.jobs.CallLinkUpdateSendJob
|
||||
import org.thoughtcrime.securesms.jobs.CallSyncEventJob
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.service.UnreadReminderManager
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
|
||||
import org.whispersystems.signalservice.internal.push.SyncMessage.CallEvent
|
||||
import java.util.UUID
|
||||
@@ -194,74 +193,6 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
||||
.readToSingleLong()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of unread calls and up to three distinct callers from [threadId].
|
||||
*/
|
||||
fun getUnreadCallsForReminderNotification(threadId: Long, now: Long = System.currentTimeMillis()): Pair<Int, List<RecipientId>> {
|
||||
val peerIds = readableDatabase
|
||||
.select("$TABLE_NAME.$PEER")
|
||||
.from("$TABLE_NAME INNER JOIN ${MessageTable.TABLE_NAME} ON $TABLE_NAME.$MESSAGE_ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}")
|
||||
.where(
|
||||
"""
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID} = $threadId AND
|
||||
$TABLE_NAME.$READ = ${ReadState.serialize(ReadState.UNREAD)} AND
|
||||
($TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED)} OR $TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)}) AND
|
||||
$TABLE_NAME.$TIMESTAMP > ${now - UnreadReminderManager.MAX_UNREAD_MESSAGE_AGE.inWholeMilliseconds}
|
||||
"""
|
||||
)
|
||||
.orderBy("$TABLE_NAME.$TIMESTAMP DESC")
|
||||
.run()
|
||||
.readToList { cursor -> RecipientId.from(cursor.requireLong(PEER)) }
|
||||
|
||||
return peerIds.size to peerIds.distinct().take(3)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if [threadId] has an unread missed call that occurred after [since].
|
||||
*/
|
||||
fun hasUnreadCallsSince(threadId: Long, since: Long): Boolean {
|
||||
return readableDatabase
|
||||
.exists("$TABLE_NAME INNER JOIN ${MessageTable.TABLE_NAME} ON $TABLE_NAME.$MESSAGE_ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}")
|
||||
.where(
|
||||
"""
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID} = $threadId AND
|
||||
$TABLE_NAME.$READ = ${ReadState.serialize(ReadState.UNREAD)} AND
|
||||
($TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED)} OR $TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)}) AND
|
||||
$TABLE_NAME.$TIMESTAMP > $since
|
||||
"""
|
||||
)
|
||||
.run()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread id and timestamp of the oldest unread missed call across [threadIds].
|
||||
* If there is none, it returns -1 for thread id and Long.MAX_VALUE for timestamp.
|
||||
*/
|
||||
fun getOldestUnreadCall(threadIds: List<Long>): Pair<Long, Long> {
|
||||
if (threadIds.isEmpty()) {
|
||||
return Pair(-1, Long.MAX_VALUE)
|
||||
}
|
||||
|
||||
val query = SqlUtil.buildFastCollectionQuery("${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID}", threadIds)
|
||||
|
||||
return readableDatabase
|
||||
.select("${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID}", "$TABLE_NAME.$TIMESTAMP")
|
||||
.from("$TABLE_NAME INNER JOIN ${MessageTable.TABLE_NAME} ON $TABLE_NAME.$MESSAGE_ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}")
|
||||
.where(
|
||||
"""
|
||||
${query.where} AND
|
||||
$TABLE_NAME.$READ = ${ReadState.serialize(ReadState.UNREAD)} AND
|
||||
($TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED)} OR $TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)}) AND
|
||||
$TABLE_NAME.$TIMESTAMP > ${System.currentTimeMillis() - UnreadReminderManager.MAX_UNREAD_MESSAGE_AGE.inWholeMilliseconds}
|
||||
""",
|
||||
query.whereArgs
|
||||
)
|
||||
.orderBy("$TABLE_NAME.$TIMESTAMP ASC")
|
||||
.limit(1)
|
||||
.run()
|
||||
.readToSingleObject { cursor -> cursor.requireLong(MessageTable.THREAD_ID) to cursor.requireLong(TIMESTAMP) } ?: Pair(-1, Long.MAX_VALUE)
|
||||
}
|
||||
|
||||
fun insertOneToOneCall(callId: Long, timestamp: Long, peer: RecipientId, type: Type, direction: Direction, event: Event, fromSync: Boolean = false) {
|
||||
val messageType: Long = Call.getMessageType(type, direction, event)
|
||||
|
||||
|
||||
@@ -5403,7 +5403,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
|
||||
/**
|
||||
* Returns the number of unread messages (based on the [ReminderType]) and up to three distinct authors from [threadId]
|
||||
* For missed calls, see [getUnreadContentForReminderNotification] in the calls table.
|
||||
*/
|
||||
fun getUnreadContentForReminderNotification(threadId: Long, type: ReminderType, now: Long = System.currentTimeMillis()): Pair<Int, List<RecipientId>> {
|
||||
val categoryClause = when (type) {
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.signal.core.util.withinTransaction
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
|
||||
import org.thoughtcrime.securesms.components.settings.app.chats.folders.ChatFolderRecord
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.ReminderType
|
||||
import org.thoughtcrime.securesms.conversationlist.model.ConversationFilter
|
||||
import org.thoughtcrime.securesms.database.MessageTable.MarkedMessageInfo
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.attachments
|
||||
@@ -679,17 +678,13 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets eligible threads that could quality for unread reminders depending on its while muted settings.
|
||||
* e.g. when getting missed calls, we get the muted threads that have opted into unread reminders
|
||||
* and also have notify for calls while muted on.
|
||||
* Gets eligible threads that could quality for unread reminders (opted in, has unread messages, elapsed time).
|
||||
*/
|
||||
fun getMutedThreadIds(reminderType: ReminderType, reminderThreshold: Long, now: Long = System.currentTimeMillis()): List<Long> {
|
||||
val unreadReminderClause = getNotificationClause(RecipientTable.UNREAD_REMINDER, SignalStore.settings.unreadReminderEnabled)
|
||||
|
||||
val reminderClause = when (reminderType) {
|
||||
ReminderType.MESSAGES -> "AND $unreadReminderClause AND $UNREAD_COUNT > 0"
|
||||
ReminderType.CALLS -> "AND $unreadReminderClause AND (${getNotificationClause(RecipientTable.CALL_NOTIFICATION_SETTING, SignalStore.settings.allowCallsWhileMuted)})"
|
||||
else -> ""
|
||||
fun getMutedThreadIds(reminderThreshold: Long, now: Long = System.currentTimeMillis()): List<Long> {
|
||||
val unreadReminderClause = if (SignalStore.settings.unreadReminderEnabled) {
|
||||
"${RecipientTable.TABLE_NAME}.${RecipientTable.UNREAD_REMINDER} != ${RecipientTable.NotificationSetting.DO_NOT_NOTIFY.id}"
|
||||
} else {
|
||||
"${RecipientTable.TABLE_NAME}.${RecipientTable.UNREAD_REMINDER} = ${RecipientTable.NotificationSetting.ALWAYS_NOTIFY.id}"
|
||||
}
|
||||
|
||||
return readableDatabase
|
||||
@@ -699,9 +694,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
"""
|
||||
$ACTIVE = 1 AND
|
||||
$ARCHIVED = 0 AND
|
||||
$UNREAD_COUNT > 0 AND
|
||||
$LAST_UNREAD_REMINDER < ${now - reminderThreshold} AND
|
||||
${RecipientTable.MUTE_UNTIL} >= $now
|
||||
$reminderClause
|
||||
${RecipientTable.MUTE_UNTIL} >= $now AND
|
||||
$unreadReminderClause
|
||||
""".trimIndent()
|
||||
)
|
||||
.run()
|
||||
@@ -725,14 +721,6 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
.run()
|
||||
}
|
||||
|
||||
private fun getNotificationClause(column: String, allowByDefault: Boolean): String {
|
||||
return if (allowByDefault) {
|
||||
"${RecipientTable.TABLE_NAME}.$column != ${RecipientTable.NotificationSetting.DO_NOT_NOTIFY.id}"
|
||||
} else {
|
||||
"${RecipientTable.TABLE_NAME}.$column = ${RecipientTable.NotificationSetting.ALWAYS_NOTIFY.id}"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not there are chats in a chat folder
|
||||
*/
|
||||
|
||||
@@ -98,9 +98,8 @@ class UnreadReminderJob(private val threadId: Long, private val lastReminderTime
|
||||
}
|
||||
|
||||
val hasNewMessages = SignalDatabase.messages.hasUnreadMessagesSince(threadId, lastReminderTime)
|
||||
val hasNewCalls = SignalDatabase.calls.hasUnreadCallsSince(threadId, lastReminderTime)
|
||||
if (!hasNewMessages && !hasNewCalls) {
|
||||
Log.i(TAG, "No new unread messages or calls for thread $threadId since last reminder. Skipping.")
|
||||
if (!hasNewMessages) {
|
||||
Log.i(TAG, "No new unread messages for thread $threadId since last reminder. Skipping.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
@@ -109,8 +108,6 @@ class UnreadReminderJob(private val threadId: Long, private val lastReminderTime
|
||||
// Get the unread counts/authors
|
||||
val (messages, unreadAuthorIds) = getUnreadForReminder(ReminderType.MESSAGES, isEligible = true)
|
||||
stopwatch.split("fetch-messages")
|
||||
val (calls, callsAuthorIds) = getUnreadForReminder(ReminderType.CALLS, isEligible = recipient.callNotificationSetting == RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
stopwatch.split("fetch-calls")
|
||||
val (mentions, mentionsAuthorIds) = getUnreadForReminder(ReminderType.MENTIONS, isEligible = !hideAuthors && recipient.isPushV2Group && recipient.mentionSetting == RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
stopwatch.split("fetch-mentions")
|
||||
val (replies, repliesAuthorIds) = getUnreadForReminder(ReminderType.REPLIES, isEligible = !hideAuthors && recipient.isPushV2Group && recipient.replyNotificationSetting == RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
@@ -119,10 +116,9 @@ class UnreadReminderJob(private val threadId: Long, private val lastReminderTime
|
||||
val summary = buildSummary(
|
||||
context = context,
|
||||
messages = messages,
|
||||
calls = calls,
|
||||
mentions = mentions,
|
||||
replies = replies,
|
||||
messageAndCallAuthors = (unreadAuthorIds + callsAuthorIds).distinct().map { Recipient.resolved(it).getShortDisplayName(context) },
|
||||
messageAuthors = unreadAuthorIds.map { Recipient.resolved(it).getShortDisplayName(context) },
|
||||
mentionAuthors = mentionsAuthorIds.map { Recipient.resolved(it).getShortDisplayName(context) },
|
||||
replyAuthors = repliesAuthorIds.map { Recipient.resolved(it).getShortDisplayName(context) },
|
||||
hideAuthors = hideAuthors
|
||||
@@ -169,48 +165,31 @@ class UnreadReminderJob(private val threadId: Long, private val lastReminderTime
|
||||
internal fun buildSummary(
|
||||
context: Context,
|
||||
messages: Int = 0,
|
||||
calls: Int = 0,
|
||||
mentions: Int = 0,
|
||||
replies: Int = 0,
|
||||
messageAndCallAuthors: List<String> = emptyList(),
|
||||
messageAuthors: List<String> = emptyList(),
|
||||
mentionAuthors: List<String> = emptyList(),
|
||||
replyAuthors: List<String> = emptyList(),
|
||||
hideAuthors: Boolean = false
|
||||
): String {
|
||||
val showUnread = messages > 0
|
||||
val showCalls = calls > 0
|
||||
val showAuthors = (showUnread || showCalls) && !hideAuthors
|
||||
val showAuthors = showUnread && !hideAuthors
|
||||
val showMentions = mentions > 0 && !hideAuthors
|
||||
val showReplies = replies > 0 && !hideAuthors
|
||||
|
||||
val messagesString = if (showUnread) context.resources.getQuantityString(R.plurals.UnreadReminderJob__messages, messages, messages) else ""
|
||||
val callsString = if (showCalls) context.resources.getQuantityString(R.plurals.UnreadReminderJob__calls, calls, calls) else ""
|
||||
val authorsString = if (showAuthors) buildAuthorSummary(context, ReminderType.MESSAGES, messages + calls, messageAndCallAuthors) else ""
|
||||
val authorsString = if (showAuthors) buildAuthorSummary(context, ReminderType.MESSAGES, messages, messageAuthors) else ""
|
||||
val mentionsString = if (showMentions) buildAuthorSummary(context, ReminderType.MENTIONS, mentions, mentionAuthors) else ""
|
||||
val repliesString = if (showReplies) buildAuthorSummary(context, ReminderType.REPLIES, replies, replyAuthors) else ""
|
||||
|
||||
return if (showUnread && showCalls && showMentions && showReplies) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_and_unread_full_summary, callsString, messagesString, mentionsString, repliesString)
|
||||
} else if (showUnread && showCalls && showMentions) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_and_unread_summary, callsString, messagesString, mentionsString)
|
||||
} else if (showUnread && showCalls && showReplies) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_and_unread_summary, callsString, messagesString, repliesString)
|
||||
} else if (showUnread && showCalls && hideAuthors) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_and_unread, callsString, messagesString)
|
||||
} else if (showUnread && showCalls) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_and_unread_author, callsString, messagesString, authorsString)
|
||||
} else if (showUnread && showMentions && showReplies) {
|
||||
return if (showUnread && showMentions && showReplies) {
|
||||
context.getString(R.string.UnreadReminderJob__unread_both_summary, messagesString, mentionsString, repliesString)
|
||||
} else if (showUnread && showMentions) {
|
||||
context.getString(R.string.UnreadReminderJob__unread_one_summary, messagesString, mentionsString)
|
||||
} else if (showUnread && showReplies) {
|
||||
context.getString(R.string.UnreadReminderJob__unread_one_summary, messagesString, repliesString)
|
||||
} else if (hideAuthors && showCalls) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_or_unread, callsString)
|
||||
} else if (hideAuthors && showUnread) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_or_unread, messagesString)
|
||||
} else if (showCalls) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_or_unread_author, callsString, authorsString)
|
||||
} else if (showUnread) {
|
||||
context.getString(R.string.UnreadReminderJob__calls_or_unread_author, messagesString, authorsString)
|
||||
} else {
|
||||
@@ -225,8 +204,7 @@ class UnreadReminderJob(private val threadId: Long, private val lastReminderTime
|
||||
@VisibleForTesting
|
||||
internal fun buildAuthorSummary(context: Context, reminderType: ReminderType, count: Int, authors: List<String>): String {
|
||||
val (oneRes, twoRes, manyRes) = when (reminderType) {
|
||||
ReminderType.MESSAGES,
|
||||
ReminderType.CALLS -> Triple(R.string.UnreadReminderJob__authors_one, R.string.UnreadReminderJob__authors_two, R.string.UnreadReminderJob__authors_many)
|
||||
ReminderType.MESSAGES -> Triple(R.string.UnreadReminderJob__authors_one, R.string.UnreadReminderJob__authors_two, R.string.UnreadReminderJob__authors_many)
|
||||
ReminderType.MENTIONS -> Triple(R.string.UnreadReminderJob__mentions_one, R.plurals.UnreadReminderJob__mentions_two, R.plurals.UnreadReminderJob__mentions_many)
|
||||
ReminderType.REPLIES -> Triple(R.string.UnreadReminderJob__replies_one, R.plurals.UnreadReminderJob__replies_two, R.plurals.UnreadReminderJob__replies_many)
|
||||
}
|
||||
@@ -250,8 +228,6 @@ class UnreadReminderJob(private val threadId: Long, private val lastReminderTime
|
||||
private fun getUnreadForReminder(reminderType: ReminderType, isEligible: Boolean): Pair<Int, List<RecipientId>> {
|
||||
return if (!isEligible) {
|
||||
0 to emptyList()
|
||||
} else if (reminderType == ReminderType.CALLS) {
|
||||
SignalDatabase.calls.getUnreadCallsForReminderNotification(threadId)
|
||||
} else {
|
||||
SignalDatabase.messages.getUnreadContentForReminderNotification(threadId, reminderType)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.ReminderType
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobs.UnreadReminderJob
|
||||
@@ -35,24 +34,17 @@ class UnreadReminderManager(
|
||||
|
||||
@WorkerThread
|
||||
override fun getNextClosestEvent(): Event? {
|
||||
val messageThreadIds = SignalDatabase.threads.getMutedThreadIds(ReminderType.MESSAGES, reminderThreshold)
|
||||
val callThreadIds = SignalDatabase.threads.getMutedThreadIds(ReminderType.CALLS, reminderThreshold)
|
||||
|
||||
val messageThreadIds = SignalDatabase.threads.getMutedThreadIds(reminderThreshold)
|
||||
val (messageThreadId, messageTimestamp) = SignalDatabase.messages.getOldestUnreadMessage(messageThreadIds)
|
||||
val (callThreadId, callTimestamp) = SignalDatabase.calls.getOldestUnreadCall(callThreadIds)
|
||||
|
||||
return if (messageThreadId == -1L && callThreadId == -1L) {
|
||||
return if (messageThreadId == -1L) {
|
||||
Log.i(TAG, "No existing unread message or calls from a qualifying thread.")
|
||||
cancelAlarm(application, UnreadReminderAlarm::class.java)
|
||||
null
|
||||
} else if (messageTimestamp < callTimestamp) {
|
||||
} else {
|
||||
val delay = (messageTimestamp + reminderThreshold - System.currentTimeMillis()).coerceAtLeast(0)
|
||||
Log.i(TAG, "The next unread reminder needs to fire in $delay ms for a message in thread $messageThreadId.")
|
||||
Event(delay, messageThreadId)
|
||||
} else {
|
||||
val delay = (callTimestamp + reminderThreshold - System.currentTimeMillis()).coerceAtLeast(0)
|
||||
Log.i(TAG, "The next unread reminder needs to fire in $delay ms for a call in thread $callThreadId.")
|
||||
Event(delay, callThreadId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9959,27 +9959,14 @@
|
||||
<!-- Button declining to paste the recovery key -->
|
||||
<string name="RecoveryKeyWarningDialog__dont_share">Don\'t share</string>
|
||||
|
||||
<!-- Notification body for unread reminders. First two placeholders are the number of unread messages and calls, last two are the summaries for mentions and replies -->
|
||||
<string name="UnreadReminderJob__calls_and_unread_full_summary">You have %1$s and %2$s including %3$s and %4$s.</string>
|
||||
<!-- Notification body for unread reminders. First two placeholders are the number of unread messages and calls, third is a summary of mentions or replies -->
|
||||
<string name="UnreadReminderJob__calls_and_unread_summary">You have %1$s and %2$s including %3$s.</string>
|
||||
<!-- Notification body for unread reminders. First two placeholders are the number of unread messages and calls, third is a list of recipients who sent them -->
|
||||
<string name="UnreadReminderJob__calls_and_unread_author">You have %1$s and %2$s from %3$s.</string>
|
||||
<!-- Notification body for unread reminders. First placeholder is unread messages, second is a summary of unread mentions or replies -->
|
||||
<string name="UnreadReminderJob__unread_one_summary">You have %1$s, including %2$s.</string>
|
||||
<!-- Notification body for unread reminders. First placeholder is unread messages, second is a summary of unread mentions, third replies -->
|
||||
<string name="UnreadReminderJob__unread_both_summary">You have %1$s, including %2$s and %3$s.</string>
|
||||
<!-- Notification body for unread reminders. First placeholder is unread messages, second is a list of people who sent them -->
|
||||
<string name="UnreadReminderJob__calls_or_unread_author">You have %1$s from %2$s.</string>
|
||||
<!-- Notification body for unread reminders. First placeholder is unread messages or unread calls -->
|
||||
<!-- Notification body for unread reminders. First placeholder is unread messages -->
|
||||
<string name="UnreadReminderJob__calls_or_unread">You have %1$s.</string>
|
||||
<!-- Notification body for unread reminders. First placeholder is unread messages, second is unread calls. -->
|
||||
<string name="UnreadReminderJob__calls_and_unread">You have %1$s and %2$s.</string>
|
||||
<!-- Notification placeholder for unread calls -->
|
||||
<plurals name="UnreadReminderJob__calls">
|
||||
<item quantity="one">%1$d missed call</item>
|
||||
<item quantity="other">%1$d missed calls</item>
|
||||
</plurals>
|
||||
<!-- Notification placeholder for unread messages -->
|
||||
<plurals name="UnreadReminderJob__messages">
|
||||
<item quantity="one">%1$d unread message</item>
|
||||
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
package org.thoughtcrime.securesms.database
|
||||
|
||||
import android.app.Application
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.testutil.RecipientTestRule
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
class CallTableTest_unreadForReminder {
|
||||
|
||||
@get:Rule
|
||||
val recipients = RecipientTestRule()
|
||||
|
||||
private val calls: CallTable
|
||||
get() = SignalDatabase.calls
|
||||
|
||||
private var nextCallId = 1L
|
||||
|
||||
@Test
|
||||
fun `counts unread missed calls from a single caller`() {
|
||||
val caller = recipients.createRecipient("Alice Android")
|
||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(caller))
|
||||
|
||||
insertMissedCall(caller, time = 1000)
|
||||
insertMissedCall(caller, time = 1001)
|
||||
|
||||
val (count, authors) = calls.getUnreadCallsForReminderNotification(threadId, 1001)
|
||||
|
||||
assertThat(count).isEqualTo(2)
|
||||
assertThat(authors).isEqualTo(listOf(caller))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a missed-notification-profile call also counts as missed`() {
|
||||
val caller = recipients.createRecipient("Bob Caller")
|
||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(caller))
|
||||
|
||||
insertCall(caller, time = 1000, event = CallTable.Event.MISSED_NOTIFICATION_PROFILE)
|
||||
|
||||
val (count, authors) = calls.getUnreadCallsForReminderNotification(threadId, 1001)
|
||||
|
||||
assertThat(count).isEqualTo(1)
|
||||
assertThat(authors).isEqualTo(listOf(caller))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `non-missed call events are excluded`() {
|
||||
val caller = recipients.createRecipient("Carol Answered")
|
||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(caller))
|
||||
|
||||
insertCall(caller, time = 1000, event = CallTable.Event.ACCEPTED)
|
||||
insertMissedCall(caller, time = 1001)
|
||||
|
||||
val (count, authors) = calls.getUnreadCallsForReminderNotification(threadId, 1002)
|
||||
|
||||
assertThat(count).isEqualTo(1)
|
||||
assertThat(authors).isEqualTo(listOf(caller))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `already-read missed calls are excluded`() {
|
||||
val caller = recipients.createRecipient("Dave Rung")
|
||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(caller))
|
||||
|
||||
insertMissedCall(caller, time = 1000)
|
||||
calls.markAllCallEventsRead(timestamp = 1000)
|
||||
insertMissedCall(caller, time = 1001)
|
||||
|
||||
val (count, authors) = calls.getUnreadCallsForReminderNotification(threadId, 1002)
|
||||
|
||||
assertThat(count).isEqualTo(1)
|
||||
assertThat(authors).isEqualTo(listOf(caller))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `only the requested threads are counted`() {
|
||||
val included = recipients.createRecipient("Erin Included")
|
||||
val excluded = recipients.createRecipient("Frank Excluded")
|
||||
val includedThreadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(included))
|
||||
SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(excluded))
|
||||
|
||||
insertMissedCall(included, time = 1000)
|
||||
insertMissedCall(excluded, time = 1000)
|
||||
|
||||
val (count, authors) = calls.getUnreadCallsForReminderNotification(includedThreadId, 1001)
|
||||
|
||||
assertThat(count).isEqualTo(1)
|
||||
assertThat(authors).isEqualTo(listOf(included))
|
||||
}
|
||||
|
||||
private fun insertMissedCall(caller: RecipientId, time: Long): Long {
|
||||
return insertCall(caller, time, CallTable.Event.MISSED)
|
||||
}
|
||||
|
||||
private fun insertCall(caller: RecipientId, time: Long, event: CallTable.Event): Long {
|
||||
val callId = nextCallId++
|
||||
calls.insertOneToOneCall(
|
||||
callId = callId,
|
||||
timestamp = time,
|
||||
peer = caller,
|
||||
type = CallTable.Type.AUDIO_CALL,
|
||||
direction = CallTable.Direction.INCOMING,
|
||||
event = event
|
||||
)
|
||||
return callId
|
||||
}
|
||||
}
|
||||
+14
-40
@@ -12,7 +12,6 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.ReminderType
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.testutil.RecipientTestRule
|
||||
@@ -36,15 +35,14 @@ class ThreadTableTest_mutedThreadIds {
|
||||
SignalDatabase.recipients.setMuted(contactId, Long.MAX_VALUE)
|
||||
}
|
||||
|
||||
private fun globalDefaults(unreadReminder: Boolean = true, calls: Boolean = false, mentions: Boolean = true, replies: Boolean = true) {
|
||||
private fun globalDefaults(unreadReminder: Boolean = true, mentions: Boolean = true, replies: Boolean = true) {
|
||||
every { recipients.signalStore.settings.unreadReminderEnabled } returns unreadReminder
|
||||
every { recipients.signalStore.settings.allowCallsWhileMuted } returns calls
|
||||
every { recipients.signalStore.settings.allowMentionsWhileMuted } returns mentions
|
||||
every { recipients.signalStore.settings.allowRepliesWhileMuted } returns replies
|
||||
}
|
||||
|
||||
private fun isMutedFor(reminderType: ReminderType, threshold: Long = 0): Boolean {
|
||||
return threadId in SignalDatabase.threads.getMutedThreadIds(reminderType, threshold)
|
||||
private fun isMutedFor(threshold: Long = 0): Boolean {
|
||||
return threadId in SignalDatabase.threads.getMutedThreadIds(threshold)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -52,14 +50,14 @@ class ThreadTableTest_mutedThreadIds {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.SYSTEM_DEFAULT)
|
||||
SignalDatabase.threads.incrementUnread(threadId, 1, 1)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isTrue()
|
||||
assertThat(isMutedFor()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `allow-by-default plus an explicit opt-out excludes the thread`() {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.DO_NOT_NOTIFY)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isFalse()
|
||||
assertThat(isMutedFor()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -67,21 +65,21 @@ class ThreadTableTest_mutedThreadIds {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
SignalDatabase.threads.incrementUnread(threadId, 1, 1)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isTrue()
|
||||
assertThat(isMutedFor()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `always-allow-required plus system-default recipient setting excludes the thread`() {
|
||||
globalDefaults(unreadReminder = false)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.SYSTEM_DEFAULT)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isFalse()
|
||||
assertThat(isMutedFor()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `always-allow-required plus an explicit opt-out excludes the thread`() {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.DO_NOT_NOTIFY)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isFalse()
|
||||
assertThat(isMutedFor()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -89,7 +87,7 @@ class ThreadTableTest_mutedThreadIds {
|
||||
globalDefaults(unreadReminder = false)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
SignalDatabase.threads.incrementUnread(threadId, 1, 1)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isTrue()
|
||||
assertThat(isMutedFor()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,7 +95,7 @@ class ThreadTableTest_mutedThreadIds {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
SignalDatabase.recipients.setMuted(contactId, 0L)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isFalse()
|
||||
assertThat(isMutedFor()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -105,7 +103,7 @@ class ThreadTableTest_mutedThreadIds {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
SignalDatabase.threads.setUnreadReminderTime(threadId, System.currentTimeMillis())
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES, 3.days.inWholeMilliseconds)).isFalse()
|
||||
assertThat(isMutedFor(3.days.inWholeMilliseconds)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,14 +112,14 @@ class ThreadTableTest_mutedThreadIds {
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
SignalDatabase.threads.setUnreadReminderTime(threadId, System.currentTimeMillis() - 4.days.inWholeMilliseconds)
|
||||
SignalDatabase.threads.incrementUnread(threadId, 1, 1)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES, 3.days.inWholeMilliseconds)).isTrue()
|
||||
assertThat(isMutedFor(3.days.inWholeMilliseconds)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a thread that does not have any unread is not included`() {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isFalse()
|
||||
assertThat(isMutedFor()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,30 +127,6 @@ class ThreadTableTest_mutedThreadIds {
|
||||
globalDefaults(unreadReminder = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
SignalDatabase.threads.setArchived(setOf(threadId), true)
|
||||
assertThat(isMutedFor(ReminderType.MESSAGES)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls, allow-by-default false, require an explicit always-allow for calls specifically`() {
|
||||
globalDefaults(unreadReminder = true, calls = false)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
|
||||
SignalDatabase.recipients.setCallNotificationSetting(contactId, RecipientTable.NotificationSetting.SYSTEM_DEFAULT)
|
||||
assertThat(isMutedFor(ReminderType.CALLS)).isFalse()
|
||||
|
||||
SignalDatabase.recipients.setCallNotificationSetting(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
assertThat(isMutedFor(ReminderType.CALLS)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls, allow-by-default true, an explicit opt-out for calls specifically still excludes it`() {
|
||||
globalDefaults(unreadReminder = true, calls = true)
|
||||
SignalDatabase.recipients.setUnreadReminder(contactId, RecipientTable.NotificationSetting.ALWAYS_NOTIFY)
|
||||
|
||||
SignalDatabase.recipients.setCallNotificationSetting(contactId, RecipientTable.NotificationSetting.DO_NOT_NOTIFY)
|
||||
assertThat(isMutedFor(ReminderType.CALLS)).isFalse()
|
||||
|
||||
SignalDatabase.recipients.setCallNotificationSetting(contactId, RecipientTable.NotificationSetting.SYSTEM_DEFAULT)
|
||||
assertThat(isMutedFor(ReminderType.CALLS)).isTrue()
|
||||
assertThat(isMutedFor()).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,6 @@ class UnreadReminderJobTest {
|
||||
assertEquals("Alice and others", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls, two authors, shares the same wording as messages`() {
|
||||
val result = UnreadReminderJob.create().buildAuthorSummary(context, ReminderType.CALLS, 5, listOf("Alice", "Bob"))
|
||||
assertEquals("Alice and Bob", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mentions, one author, omits the count`() {
|
||||
val result = UnreadReminderJob.create().buildAuthorSummary(context, ReminderType.MENTIONS, 1, listOf("Dave"))
|
||||
@@ -90,140 +84,48 @@ class UnreadReminderJobTest {
|
||||
|
||||
@Test
|
||||
fun `messages only, singular message and singular author`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, messageAndCallAuthors = listOf("Alice"))
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, messageAuthors = listOf("Alice"))
|
||||
assertEquals("You have 1 unread message from Alice.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages only, plural messages and two authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 5, messageAndCallAuthors = listOf("Alice", "Bob"))
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 5, messageAuthors = listOf("Alice", "Bob"))
|
||||
assertEquals("You have 5 unread messages from Alice and Bob.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls only, singular call and singular author`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, calls = 1, messageAndCallAuthors = listOf("Bob"))
|
||||
assertEquals("You have 1 missed call from Bob.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls only, plural calls and three or more authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, calls = 4, messageAndCallAuthors = listOf("Carol", "Dave", "Erin"))
|
||||
assertEquals("You have 4 missed calls from Carol and others.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages and calls, no mentions or replies, combines counts and authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 2, calls = 1, messageAndCallAuthors = listOf("Alice", "Bob"))
|
||||
assertEquals("You have 1 missed call and 2 unread messages from Alice and Bob.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, calls, and mentions uses the calls-and-unread summary with mentions`() {
|
||||
fun `messages and mentions, combines counts and authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
calls = 1,
|
||||
mentions = 1,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
messageAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave")
|
||||
)
|
||||
assertEquals("You have 1 missed call and 1 unread message including a mention of you by Dave.", result)
|
||||
assertEquals("You have 1 unread message, including a mention of you by Dave.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, calls, and replies uses the calls-and-unread summary with replies`() {
|
||||
fun `messages and replies, combines counts and authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
calls = 1,
|
||||
replies = 1,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
messageAuthors = listOf("Alice"),
|
||||
replyAuthors = listOf("Grace")
|
||||
)
|
||||
assertEquals("You have 1 missed call and 1 unread message including a reply from Grace.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, calls, mentions, and replies all true uses the full summary`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
calls = 1,
|
||||
mentions = 1,
|
||||
replies = 1,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave"),
|
||||
replyAuthors = listOf("Grace")
|
||||
)
|
||||
assertEquals("You have 1 missed call and 1 unread message including a mention of you by Dave and a reply from Grace.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, calls, mentions, and replies all true, plural messages and calls`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 3,
|
||||
calls = 2,
|
||||
mentions = 1,
|
||||
replies = 1,
|
||||
messageAndCallAuthors = listOf("Alice", "Bob"),
|
||||
mentionAuthors = listOf("Dave"),
|
||||
replyAuthors = listOf("Grace")
|
||||
)
|
||||
assertEquals("You have 2 missed calls and 3 unread messages including a mention of you by Dave and a reply from Grace.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, calls, mentions, and replies all true, two mention and reply authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
calls = 1,
|
||||
mentions = 2,
|
||||
replies = 2,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave", "Erin"),
|
||||
replyAuthors = listOf("Grace", "Heidi")
|
||||
)
|
||||
assertEquals("You have 1 missed call and 1 unread message including 2 mentions of you by Dave and Erin and 2 replies from Grace and Heidi.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, calls, mentions, and replies all true, three or more mention and reply authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
calls = 1,
|
||||
mentions = 5,
|
||||
replies = 4,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave", "Erin", "Frank"),
|
||||
replyAuthors = listOf("Grace", "Heidi", "Ivan")
|
||||
)
|
||||
assertEquals("You have 1 missed call and 1 unread message including 5 mentions of you by Dave and others and 4 replies from Grace and others.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages and mentions, no calls`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 2, mentions = 2, messageAndCallAuthors = listOf("Alice"), mentionAuthors = listOf("Frank", "Erin"))
|
||||
assertEquals("You have 2 unread messages, including 2 mentions of you by Frank and Erin.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages and replies, no calls`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, replies = 3, messageAndCallAuthors = listOf("Alice"), replyAuthors = listOf("Grace"))
|
||||
assertEquals("You have 1 unread message, including a reply from Grace.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, mentions, and replies all true, no calls - both are shown`() {
|
||||
fun `messages, mentions, and replies all true uses the full summary`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
mentions = 1,
|
||||
replies = 1,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
messageAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave"),
|
||||
replyAuthors = listOf("Grace")
|
||||
)
|
||||
@@ -231,61 +133,65 @@ class UnreadReminderJobTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls and mentions, no unread messages - falls back to calls-or-unread-author with calls`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, calls = 1, mentions = 1, messageAndCallAuthors = listOf("Bob"), mentionAuthors = listOf("Dave"))
|
||||
assertEquals("You have 1 missed call from Bob.", result)
|
||||
fun `messages, mentions, and replies all true, plural messages`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 3,
|
||||
mentions = 1,
|
||||
replies = 1,
|
||||
messageAuthors = listOf("Alice", "Bob"),
|
||||
mentionAuthors = listOf("Dave"),
|
||||
replyAuthors = listOf("Grace")
|
||||
)
|
||||
assertEquals("You have 3 unread messages, including a mention of you by Dave and a reply from Grace.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, mentions, and replies all true, two mention and reply authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
mentions = 2,
|
||||
replies = 2,
|
||||
messageAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave", "Erin"),
|
||||
replyAuthors = listOf("Grace", "Heidi")
|
||||
)
|
||||
assertEquals("You have 1 unread message, including 2 mentions of you by Dave and Erin and 2 replies from Grace and Heidi.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `messages, mentions, and replies all true, three or more mention and reply authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
mentions = 5,
|
||||
replies = 4,
|
||||
messageAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave", "Erin", "Frank"),
|
||||
replyAuthors = listOf("Grace", "Heidi", "Ivan")
|
||||
)
|
||||
assertEquals("You have 1 unread message, including 5 mentions of you by Dave and others and 4 replies from Grace and others.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, messages only, omits author names`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, messageAndCallAuthors = listOf("Alice"), hideAuthors = true)
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, messageAuthors = listOf("Alice"), hideAuthors = true)
|
||||
assertEquals("You have 1 unread message.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, calls only, omits author names`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, calls = 1, messageAndCallAuthors = listOf("Bob"), hideAuthors = true)
|
||||
assertEquals("You have 1 missed call.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, messages and calls, uses calls-and-unread without authors`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 2, calls = 1, messageAndCallAuthors = listOf("Alice", "Bob"), hideAuthors = true)
|
||||
assertEquals("You have 1 missed call and 2 unread messages.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, messages, calls, and mentions, mentions are dropped entirely`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(
|
||||
context,
|
||||
messages = 1,
|
||||
calls = 1,
|
||||
mentions = 1,
|
||||
messageAndCallAuthors = listOf("Alice"),
|
||||
mentionAuthors = listOf("Dave"),
|
||||
hideAuthors = true
|
||||
)
|
||||
assertEquals("You have 1 missed call and 1 unread message.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, messages and mentions, no calls, mentions are dropped entirely`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 2, mentions = 2, messageAndCallAuthors = listOf("Alice"), mentionAuthors = listOf("Frank", "Erin"), hideAuthors = true)
|
||||
fun `hideAuthors, messages and mentions, mentions are dropped entirely`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 2, mentions = 2, messageAuthors = listOf("Alice"), mentionAuthors = listOf("Frank", "Erin"), hideAuthors = true)
|
||||
assertEquals("You have 2 unread messages.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, messages and replies, no calls, replies are dropped entirely`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, replies = 3, messageAndCallAuthors = listOf("Alice"), replyAuthors = listOf("Grace"), hideAuthors = true)
|
||||
fun `hideAuthors, messages and replies, replies are dropped entirely`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, messages = 1, replies = 3, messageAuthors = listOf("Alice"), replyAuthors = listOf("Grace"), hideAuthors = true)
|
||||
assertEquals("You have 1 unread message.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, calls and mentions, no unread messages, mentions are dropped entirely`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, calls = 1, mentions = 1, messageAndCallAuthors = listOf("Bob"), mentionAuthors = listOf("Dave"), hideAuthors = true)
|
||||
assertEquals("You have 1 missed call.", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hideAuthors, nothing unread produces an empty summary`() {
|
||||
val result = UnreadReminderJob.create().buildSummary(context, hideAuthors = true)
|
||||
|
||||
Reference in New Issue
Block a user