Skip to content

Commit

Permalink
Fix #95: Ignore non-consecutive repeats
Browse files Browse the repository at this point in the history
  • Loading branch information
pilot51 committed Dec 31, 2024
1 parent 76432e4 commit 427bcf8
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 16 deletions.
11 changes: 6 additions & 5 deletions app/src/main/java/com/pilot51/voicenotify/NotifyList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,22 @@ import com.pilot51.voicenotify.db.Settings

object NotifyList {
const val HISTORY_LIMIT = 100
private val list = mutableStateListOf<NotificationInfo>()
private val _list = mutableStateListOf<NotificationInfo>()
val list: List<NotificationInfo> = _list

fun addNotification(info: NotificationInfo) {
if (list.size == HISTORY_LIMIT) {
list.removeAt(list.size - 1)
_list.removeAt(list.lastIndex)
}
list.add(0, info)
_list.add(0, info)
}

fun updateInfo(info: NotificationInfo) {
val index = list.indexOf(info).takeUnless { it == -1 } ?: return
// Force update to list state by first setting copy
list[index] = info.copy()
_list[index] = info.copy()
// Set back to original to ensure future calls can find it again
list[index] = info
_list[index] = info
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ fun IgnoreRepeatsDialog(
val settingsCombo by vm.configuringSettingsComboState.collectAsState()
TextEditDialog(
titleRes = R.string.ignore_repeat,
messageRes = R.string.ignore_repeat_dialog_msg,
message = stringResource(R.string.ignore_repeat_dialog_msg, NotifyList.HISTORY_LIMIT),
initialText = (settingsCombo.ignoreRepeat ?: DEFAULT_IGNORE_REPEAT)
.takeIf { it != -1 }?.toString() ?: "",
keyboardType = KeyboardType.Number,
Expand Down
18 changes: 9 additions & 9 deletions app/src/main/java/com/pilot51/voicenotify/Service.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.time.Duration
import java.util.*
import java.util.concurrent.Executors
import java.util.regex.PatternSyntaxException
Expand All @@ -77,8 +78,6 @@ import kotlin.time.Duration.Companion.seconds
class Service : NotificationListenerService() {
private val appContext by ::applicationContext
private val ioScope = CoroutineScope(Dispatchers.IO)
private val lastMsg = mutableMapOf<App?, String?>()
private val lastMsgTime = mutableMapOf<App?, Long>()
private var tts: TextToSpeech? = null
private var isAwaitingTtsInit = MutableStateFlow(false)
private var latestTtsStatus = TextToSpeech.STOPPED
Expand Down Expand Up @@ -280,7 +279,6 @@ class Service : NotificationListenerService() {
return@launch // Completely ignore group summary notifications.
}
val info = NotificationInfo(app, sbn, settings)
val msgTime = info.instant.toEpochMilli()
val ttsMsg = info.ttsMessage
if (app != null && !app.isEnabled) {
info.addIgnoreReasons(IgnoreReason.APP)
Expand Down Expand Up @@ -317,10 +315,14 @@ class Service : NotificationListenerService() {
info.addIgnoreReasons(IgnoreReason.STRING_IGNORED)
}
}
val ignoreRepeat = settings.ignoreRepeat ?: -1
if (lastMsg.containsKey(app)) {
if (lastMsg[app] == ttsMsg && (ignoreRepeat == -1 || msgTime - lastMsgTime[app]!! < ignoreRepeat * 1000)) {
info.addIgnoreReasonIdentical(ignoreRepeat)
val ignoreRepeat = settings.ignoreRepeat?.takeIf { it > -1 }?.run { Duration.ofSeconds(toLong()) }
for (priorInfo in NotifyList.list) {
val elapsed = Duration.between(priorInfo.instant, info.instant)
if (ignoreRepeat != null && elapsed >= ignoreRepeat) break
if (priorInfo.app?.packageName != app?.packageName) continue
if (priorInfo.ttsMessage == ttsMsg) {
info.addIgnoreReasonIdentical(ignoreRepeat?.seconds?.toInt() ?: -1)
break
}
}
NotifyList.addNotification(info)
Expand All @@ -343,8 +345,6 @@ class Service : NotificationListenerService() {
}
speak(info)
}
lastMsg[app] = ttsMsg
lastMsgTime[app] = msgTime
} else {
Log.i(TAG, "Notification from ${app?.label} ignored for reason(s): ${info.getIgnoreReasonsAsText()}")
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
<string name="ignore_groups_summary_off">Notifications containing multiple messages will be spoken</string>
<string name="ignore_repeat">Ignore Repeats</string>
<string name="ignore_repeat_summary">Ignore subsequent identical notifications within a set time</string>
<string name="ignore_repeat_dialog_msg">Set number of seconds that must pass since last notification before a repeat can be spoken.\nIgnored repeats reset the count and different notifications clear it.\nBlank = infinite.</string>
<string name="ignore_repeat_dialog_msg">Set the number of seconds that must pass for a repeated notification to be spoken.\nIgnored repeats reset the count.\n\nRepeat detection is limited to the memory of the Notification Log (%d notifications).\n\n0 = Disable\nBlank = Infinite</string>
<string name="device_state">Device States</string>
<string name="device_state_summary">Select whether to speak during certain device states</string>
<string name="device_state_dialog_title">Speak during these device states</string>
Expand Down

0 comments on commit 427bcf8

Please sign in to comment.