Skip to content

Commit

Permalink
Support notification big content, add detail dialog
Browse files Browse the repository at this point in the history
- Add detail dialog containing info from log plus:
  - Package name
  - Checkbox to enable/disable app
  - All notification parts and TTS message with labels
- Center titles for notification log dialogs
- Increase font size of dialog buttons

Resolves #76 and partially #37
  • Loading branch information
pilot51 committed Jan 10, 2024
1 parent 5a49de6 commit 112f736
Show file tree
Hide file tree
Showing 5 changed files with 327 additions and 104 deletions.
21 changes: 17 additions & 4 deletions app/src/main/java/com/pilot51/voicenotify/App.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2023 Mark Injerd
* Copyright 2011-2024 Mark Injerd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,9 @@
*/
package com.pilot51.voicenotify

import android.content.Context
import android.provider.BaseColumns
import android.widget.Toast
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
Expand Down Expand Up @@ -51,13 +53,24 @@ data class App(
return this
}

fun setEnabled(enable: Boolean, updateDb: Boolean) {
fun setEnabled(enable: Boolean, updateDb: Boolean = true) {
enabled = enable
CoroutineScope(Dispatchers.IO).launch {
if (updateDb) db.appDao.updateAppEnable(this@App)
if (updateDb) CoroutineScope(Dispatchers.IO).launch {
db.appDao.updateAppEnable(this@App)
}
}

fun setEnabledWithToast(enable: Boolean, context: Context) {
setEnabled(enable)
Toast.makeText(context,
context.getString(
if (enable) R.string.app_is_not_ignored else R.string.app_is_ignored,
label
),
Toast.LENGTH_SHORT
).show()
}

/** Removes self from database. */
fun remove() {
CoroutineScope(Dispatchers.IO).launch {
Expand Down
19 changes: 19 additions & 0 deletions app/src/main/java/com/pilot51/voicenotify/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.sp
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.Lifecycle
Expand Down Expand Up @@ -77,6 +81,16 @@ fun AppTheme(content: @Composable () -> Unit) {
} else {
lightColorScheme(primary = Color(0xFF2A54A5), primaryContainer = Color(0xFF64F0FF))
},
typography = MaterialTheme.typography.copy(
// Increased font size for dialog buttons
labelLarge = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Medium,
fontSize = 20.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp,
)
),
content = content
)
}
Expand Down Expand Up @@ -396,6 +410,11 @@ private fun runTestNotification(context: Context) {
.setContentTitle(context.getString(R.string.test_content_title))
.setContentText(context.getString(R.string.test_content_text))
.setContentInfo(context.getString(R.string.test_content_info))
.setStyle(NotificationCompat.BigTextStyle()
.setBigContentTitle(context.getString(R.string.test_big_content_title))
.setSummaryText(context.getString(R.string.test_big_content_summary))
.bigText(context.getString(R.string.test_big_content_text))
)
notificationManager.notify(0, builder.build())
}
}, 5000)
Expand Down
66 changes: 35 additions & 31 deletions app/src/main/java/com/pilot51/voicenotify/NotificationInfo.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2023 Mark Injerd
* Copyright 2011-2024 Mark Injerd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,15 +39,21 @@ data class NotificationInfo(
private val notification: Notification
) {
/** The notification's ticker message. */
private val ticker = notification.tickerText?.toString()
val ticker = notification.tickerText?.toString()
/** The notification's subtext. */
private val subtext: String?
val subtext: String?
/** The notification's content title. */
private val contentTitle: String?
val contentTitle: String?
/** The notification's content text. */
private val contentText: String?
val contentText: String?
/** The notification's content info. */
private val contentInfoText: String?
val contentInfoText: String?
/** The notification's big content title. */
val bigContentTitle: String?
/** The notification's big content summary. */
val bigContentSummary: String?
/** The notification's big content text. */
val bigContentText: String?
/** Calendar representing the time that this instance of NotificationInfo was created. */
val calendar: Calendar
var isEmpty = false
Expand All @@ -73,41 +79,53 @@ data class NotificationInfo(
contentTitle = extras.getString(Notification.EXTRA_TITLE)
contentText = extras.getCharSequence(Notification.EXTRA_TEXT)?.toString()
contentInfoText = extras.getString(Notification.EXTRA_INFO_TEXT)
bigContentTitle = extras.getString(Notification.EXTRA_TITLE_BIG)
bigContentSummary = extras.getString(Notification.EXTRA_SUMMARY_TEXT)
bigContentText = extras.getString(Notification.EXTRA_BIG_TEXT)
calendar = Calendar.getInstance()
if (notification.`when` != Long.MIN_VALUE) { // If not Compose preview
buildTtsMessage()
}
buildTtsMessage()
}

/** Generates the string to be used for TTS. */
private fun buildTtsMessage() {
val ttsStringPref = prefs.getString(KEY_TTS_STRING, null) ?: DEFAULT_TTS_STRING
val isComposePreview = notification.`when` == Long.MIN_VALUE
val ttsStringPref = if (isComposePreview) DEFAULT_TTS_STRING else {
prefs.getString(KEY_TTS_STRING, null) ?: DEFAULT_TTS_STRING
}
val ttsUnformattedMsg = ttsStringPref
.replace("#a", "%1\$s") // App Label
.replace("#t", "%2\$s") // Ticker
.replace("#s", "%3\$s") // Subtext
.replace("#c", "%4\$s") // Content Title
.replace("#m", "%5\$s") // Content Text
.replace("#i", "%6\$s") // Content Info Text
.replace("#h", "%7\$s") // Big Content Title
.replace("#y", "%8\$s") // Big Content Summary
.replace("#b", "%9\$s") // Big Content Text
try {
ttsMessage = String.format(ttsUnformattedMsg,
app?.label ?: "",
ticker?.replace("[|\\[\\]{}*<>]+".toRegex(), " ") ?: "",
subtext ?: "",
contentTitle ?: "",
contentText ?: "",
contentInfoText ?: "")
contentInfoText ?: "",
bigContentTitle ?: "",
bigContentSummary ?: "",
bigContentText ?: "")
} catch (e: IllegalFormatException) {
Log.w(TAG, "Error formatting custom TTS string!")
e.printStackTrace()
}
isEmpty = ttsMessage.isNullOrBlank() ||
ttsMessage == ttsStringPref.replace(Regex("#[atscmi]"), "")
if (app != null && (ttsMessage == null || ttsMessage == app.label)) {
if (app != null && (ttsMessage == null || ttsMessage == app.label) && !isComposePreview) {
ttsMessage = appContext.getString(R.string.notification_from, app.label)
}
if (!ttsMessage.isNullOrEmpty()) {
val ttsTextReplace = prefs.getString(KEY_TTS_TEXT_REPLACE, null)
val ttsTextReplace = if (isComposePreview) null else {
prefs.getString(KEY_TTS_TEXT_REPLACE, null)
}
val textReplaceList = Common.convertTextReplaceStringToList(ttsTextReplace)
for (pair in textReplaceList) {
ttsMessage = ttsMessage!!.replace(
Expand All @@ -116,8 +134,10 @@ data class NotificationInfo(
}
if (ttsMessage != null) {
try {
val maxLength = prefs.getString(KEY_MAX_LENGTH, null)
?.takeIf { it.isNotEmpty() }?.toInt() ?: 0
val maxLength = if (isComposePreview) 0 else {
prefs.getString(KEY_MAX_LENGTH, null)
?.takeIf { it.isNotEmpty() }?.toInt() ?: 0
}
if (maxLength > 0) {
ttsMessage = ttsMessage!!.substring(0, min(maxLength, ttsMessage!!.length))
}
Expand All @@ -127,22 +147,6 @@ data class NotificationInfo(
}
}

/**
* Builds a string from the various notification texts to be displayed in [NotifyList].
* @return The string containing notification details.
*/
val logMessage: String
get() {
val logBuilder = StringBuilder()
for (s in arrayOf(ticker, subtext, contentTitle, contentText, contentInfoText)) {
if (!s.isNullOrEmpty()) {
if (logBuilder.isNotEmpty()) logBuilder.append("\n")
logBuilder.append(s)
}
}
return logBuilder.toString()
}

/**
* Gets the reasons this notification was ignored as a single string.
* @return Comma-separated list of ignore reasons.
Expand Down
Loading

0 comments on commit 112f736

Please sign in to comment.