List unmatched tags as strings
This commit is contained in:
parent
8fd7bb5639
commit
1148e08b96
11 changed files with 108 additions and 77 deletions
|
@ -12,8 +12,8 @@ android {
|
|||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
|
||||
versionCode 8
|
||||
versionName "1.2.1"
|
||||
versionCode 9
|
||||
versionName "1.2.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ abstract class Database : RoomDatabase() {
|
|||
|
||||
private val MIGRATION_3_4 = object : Migration(3, 4) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("CREATE TABLE Notification_New (id TEXT NOT NULL, subscriptionId INTEGER NOT NULL, timestamp INTEGER NOT NULL, title TEXT NOT NULL, message TEXT NOT NULL, notificationId INTEGER NOT NULL, priority INTEGER NOT NULL, tags TEXT NOT NULL, deleted INTEGER NOT NULL, PRIMARY KEY(id, subscriptionId))")
|
||||
db.execSQL("CREATE TABLE Notification_New (id TEXT NOT NULL, subscriptionId INTEGER NOT NULL, timestamp INTEGER NOT NULL, title TEXT NOT NULL, message TEXT NOT NULL, notificationId INTEGER NOT NULL, priority INTEGER NOT NULL DEFAULT(3), tags TEXT NOT NULL, deleted INTEGER NOT NULL, PRIMARY KEY(id, subscriptionId))")
|
||||
db.execSQL("INSERT INTO Notification_New SELECT id, subscriptionId, timestamp, '', message, notificationId, 3, '', deleted FROM Notification")
|
||||
db.execSQL("DROP TABLE Notification")
|
||||
db.execSQL("ALTER TABLE Notification_New RENAME TO Notification")
|
||||
|
|
|
@ -326,9 +326,12 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val possibleTags = listOf("warning", "skull", "success", "triangular_flag_on_post", "de", "dog", "rotating_light", "cat", "bike")
|
||||
val possibleTags = listOf(
|
||||
"warning", "skull", "success", "triangular_flag_on_post", "de", "dog", "rotating_light", "cat", "bike", // Emojis
|
||||
"backup", "rsync", "de-server1", "this-is-a-tag"
|
||||
)
|
||||
val priority = Random.nextInt(1, 6)
|
||||
val tags = possibleTags.shuffled().take(Random.nextInt(0, 3))
|
||||
val tags = possibleTags.shuffled().take(Random.nextInt(0, 4))
|
||||
val title = if (Random.nextBoolean()) getString(R.string.detail_test_title) else ""
|
||||
val message = getString(R.string.detail_test_message, priority)
|
||||
api.publish(subscriptionBaseUrl, subscriptionTopic, message, title, priority, tags)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.heckel.ntfy.ui
|
||||
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -11,8 +12,7 @@ import androidx.recyclerview.widget.ListAdapter
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.util.formatMessage
|
||||
import io.heckel.ntfy.util.formatTitle
|
||||
import io.heckel.ntfy.util.*
|
||||
import java.util.*
|
||||
|
||||
class DetailAdapter(private val onClick: (Notification) -> Unit, private val onLongClick: (Notification) -> Unit) :
|
||||
|
@ -48,10 +48,14 @@ class DetailAdapter(private val onClick: (Notification) -> Unit, private val onL
|
|||
private val titleView: TextView = itemView.findViewById(R.id.detail_item_title_text)
|
||||
private val messageView: TextView = itemView.findViewById(R.id.detail_item_message_text)
|
||||
private val newImageView: View = itemView.findViewById(R.id.detail_item_new_dot)
|
||||
private val tagsView: TextView = itemView.findViewById(R.id.detail_item_tags)
|
||||
|
||||
fun bind(notification: Notification) {
|
||||
this.notification = notification
|
||||
|
||||
val ctx = itemView.context
|
||||
val unmatchedTags = unmatchedTags(splitTags(notification.tags))
|
||||
|
||||
dateView.text = Date(notification.timestamp * 1000).toString()
|
||||
messageView.text = formatMessage(notification)
|
||||
newImageView.visibility = if (notification.notificationId == 0) View.GONE else View.VISIBLE
|
||||
|
@ -63,10 +67,15 @@ class DetailAdapter(private val onClick: (Notification) -> Unit, private val onL
|
|||
} else {
|
||||
titleView.visibility = View.GONE
|
||||
}
|
||||
if (unmatchedTags.isNotEmpty()) {
|
||||
tagsView.visibility = View.VISIBLE
|
||||
tagsView.text = ctx.getString(R.string.detail_item_tags, unmatchedTags.joinToString(", "))
|
||||
} else {
|
||||
tagsView.visibility = View.GONE
|
||||
}
|
||||
if (selected.contains(notification.id)) {
|
||||
itemView.setBackgroundResource(R.color.primarySelectedRowColor);
|
||||
}
|
||||
val ctx = itemView.context
|
||||
when (notification.priority) {
|
||||
1 -> {
|
||||
priorityImageView.visibility = View.VISIBLE
|
||||
|
|
|
@ -31,21 +31,31 @@ fun joinTags(tags: List<String>?): String {
|
|||
return tags?.joinToString(",") ?: ""
|
||||
}
|
||||
|
||||
fun toTags(tags: String?): String {
|
||||
return tags ?: ""
|
||||
fun splitTags(tags: String?): List<String> {
|
||||
return if (tags == null || tags == "") {
|
||||
emptyList()
|
||||
} else {
|
||||
tags.split(",")
|
||||
}
|
||||
}
|
||||
|
||||
fun emojify(tags: List<String>): List<String> {
|
||||
return tags.mapNotNull {
|
||||
when (it.toLowerCase()) {
|
||||
fun toEmojis(tags: List<String>): List<String> {
|
||||
return tags.mapNotNull { tag -> toEmoji(tag) }
|
||||
}
|
||||
|
||||
fun toEmoji(tag: String): String? {
|
||||
return when (tag.toLowerCase()) {
|
||||
"warn", "warning" -> "\u26A0\uFE0F"
|
||||
"success" -> "\u2714\uFE0F"
|
||||
"failure" -> "\u274C"
|
||||
else -> EmojiManager.getForAlias(it)?.unicode
|
||||
}
|
||||
else -> EmojiManager.getForAlias(tag)?.unicode
|
||||
}
|
||||
}
|
||||
|
||||
fun unmatchedTags(tags: List<String>): List<String> {
|
||||
return tags.filter { tag -> toEmoji(tag) == null }
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend tags/emojis to message, but only if there is a non-empty title.
|
||||
* Otherwise the tags will be prepended to the title.
|
||||
|
@ -54,7 +64,7 @@ fun formatMessage(notification: Notification): String {
|
|||
return if (notification.title != "") {
|
||||
notification.message
|
||||
} else {
|
||||
val emojis = emojify(notification.tags.split(","))
|
||||
val emojis = toEmojis(splitTags(notification.tags))
|
||||
if (emojis.isEmpty()) {
|
||||
notification.message
|
||||
} else {
|
||||
|
@ -76,7 +86,7 @@ fun formatTitle(subscription: Subscription, notification: Notification): String
|
|||
}
|
||||
|
||||
fun formatTitle(notification: Notification): String {
|
||||
val emojis = emojify(notification.tags.split(","))
|
||||
val emojis = toEmojis(splitTags(notification.tags))
|
||||
return if (emojis.isEmpty()) {
|
||||
notification.title
|
||||
} else {
|
||||
|
|
|
@ -37,10 +37,20 @@
|
|||
android:textColor="@color/primaryTextColor"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
app:layout_constraintTop_toBottomOf="@id/detail_item_title_text"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="10dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/detail_item_tags"/>
|
||||
<TextView
|
||||
android:text="Tags: ssh, zfs"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_item_tags"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="10dp"/>
|
||||
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="10dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/detail_item_message_text"/>
|
||||
<TextView
|
||||
android:text="This is an optional title. It can also be a little longer but not too long."
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
<string name="detail_instant_delivery_enabled">Instant delivery enabled</string>
|
||||
<string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
|
||||
<string name="detail_instant_info">Instant delivery is enabled</string>
|
||||
<string name="detail_item_tags">Tags: %1$s</string>
|
||||
|
||||
<!-- Detail activity: Action bar -->
|
||||
<string name="detail_menu_notifications_enabled">Notifications enabled</string>
|
||||
|
|
|
@ -7,9 +7,7 @@ import io.heckel.ntfy.R
|
|||
import io.heckel.ntfy.app.Application
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.msg.NotificationService
|
||||
import io.heckel.ntfy.util.joinTags
|
||||
import io.heckel.ntfy.util.toPriority
|
||||
import io.heckel.ntfy.util.toTags
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -55,7 +53,7 @@ class FirebaseService : FirebaseMessagingService() {
|
|||
message = message,
|
||||
notificationId = Random.nextInt(),
|
||||
priority = toPriority(priority),
|
||||
tags = toTags(tags),
|
||||
tags = tags ?: "",
|
||||
deleted = false
|
||||
)
|
||||
val shouldNotify = repository.addNotification(notification)
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="26.806921"
|
||||
inkscape:cx="18.894374"
|
||||
inkscape:cy="14.026229"
|
||||
inkscape:zoom="20.517358"
|
||||
inkscape:cx="22.834323"
|
||||
inkscape:cy="15.742767"
|
||||
inkscape:window-width="1863"
|
||||
inkscape:window-height="1025"
|
||||
inkscape:window-x="57"
|
||||
|
@ -33,7 +33,15 @@
|
|||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1428" />
|
||||
<path
|
||||
d="M 16.748063,0.46162067 H 7.1927317 L 0.44251841,7.211834 v 9.555331 l 6.75021329,6.750213 h 9.5553313 l 6.750213,-6.750213 V 7.211834 Z M 11.970397,18.778139 c -0.922231,0 -1.665138,-0.742908 -1.665138,-1.665138 0,-0.92223 0.742907,-1.665138 1.665138,-1.665138 0.92223,0 1.665138,0.742908 1.665138,1.665138 0,0.92223 -0.742908,1.665138 -1.665138,1.665138 z m 1.280875,-5.507765 H 10.689521 V 5.5851222 h 2.561751 z"
|
||||
id="path29312"
|
||||
style="fill:#ac0000;fill-opacity:1;stroke-width:1.28088" />
|
||||
style="color:#000000;fill:#aa0000;fill-opacity:1;stroke-width:0.0919748;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="M 12.116784,3.40514 A 1.2747098,1.2747098 0 0 0 11.455179,3.5903463 L 4.8085864,7.6275238 A 1.2745823,1.2745823 0 0 0 4.3810494,9.3786313 1.2745823,1.2745823 0 0 0 6.1319775,9.8063489 L 12.116784,6.1710217 18.101593,9.8063489 A 1.2745823,1.2745823 0 0 0 19.85252,9.3786313 1.2745823,1.2745823 0 0 0 19.424984,7.6275238 L 12.778569,3.5903463 A 1.2747098,1.2747098 0 0 0 12.116784,3.40514 Z"
|
||||
id="rect3554" />
|
||||
<path
|
||||
style="color:#000000;fill:#c60000;fill-opacity:1;stroke:none;stroke-width:0.0919748;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="M 12.116784,8.5394415 A 1.2747098,1.2747098 0 0 0 11.455179,8.724648 l -6.6465926,4.037176 a 1.2745823,1.2745823 0 0 0 -0.427537,1.751108 1.2745823,1.2745823 0 0 0 1.7509281,0.427717 l 5.9848065,-3.635327 5.984809,3.635327 A 1.2745823,1.2745823 0 0 0 19.85252,14.512932 1.2745823,1.2745823 0 0 0 19.424984,12.761824 L 12.778569,8.724648 A 1.2747098,1.2747098 0 0 0 12.116784,8.5394415 Z"
|
||||
id="path9314" />
|
||||
<path
|
||||
style="color:#000000;fill:#de0000;fill-opacity:1;stroke:none;stroke-width:0.0919748;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="m 12.195014,13.806679 a 1.2747098,1.2747098 0 0 0 -0.661606,0.185205 l -6.6465924,4.037177 a 1.2745823,1.2745823 0 0 0 -0.427537,1.751108 1.2745823,1.2745823 0 0 0 1.750928,0.427718 l 5.9848074,-3.635327 5.984807,3.635327 a 1.2745823,1.2745823 0 0 0 1.750928,-0.427718 1.2745823,1.2745823 0 0 0 -0.427537,-1.751108 l -6.646414,-4.037177 a 1.2747098,1.2747098 0 0 0 -0.661784,-0.185205 z"
|
||||
id="path9316" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.7 KiB |
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
fill="#000000"
|
||||
version="1.1"
|
||||
id="svg1428"
|
||||
sodipodi:docname="priority_5_24dp.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1432" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1430"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="20.517358"
|
||||
inkscape:cx="22.834323"
|
||||
inkscape:cy="15.742767"
|
||||
inkscape:window-width="1863"
|
||||
inkscape:window-height="1025"
|
||||
inkscape:window-x="57"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1428" />
|
||||
<path
|
||||
style="color:#000000;fill:#aa0000;fill-opacity:1;stroke-width:0.0919748;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="M 12.116784,3.40514 A 1.2747098,1.2747098 0 0 0 11.455179,3.5903463 L 4.8085864,7.6275238 A 1.2745823,1.2745823 0 0 0 4.3810494,9.3786313 1.2745823,1.2745823 0 0 0 6.1319775,9.8063489 L 12.116784,6.1710217 18.101593,9.8063489 A 1.2745823,1.2745823 0 0 0 19.85252,9.3786313 1.2745823,1.2745823 0 0 0 19.424984,7.6275238 L 12.778569,3.5903463 A 1.2747098,1.2747098 0 0 0 12.116784,3.40514 Z"
|
||||
id="rect3554" />
|
||||
<path
|
||||
style="color:#000000;fill:#c60000;fill-opacity:1;stroke:none;stroke-width:0.0919748;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="M 12.116784,8.5394415 A 1.2747098,1.2747098 0 0 0 11.455179,8.724648 l -6.6465926,4.037176 a 1.2745823,1.2745823 0 0 0 -0.427537,1.751108 1.2745823,1.2745823 0 0 0 1.7509281,0.427717 l 5.9848065,-3.635327 5.984809,3.635327 A 1.2745823,1.2745823 0 0 0 19.85252,14.512932 1.2745823,1.2745823 0 0 0 19.424984,12.761824 L 12.778569,8.724648 A 1.2747098,1.2747098 0 0 0 12.116784,8.5394415 Z"
|
||||
id="path9314" />
|
||||
<path
|
||||
style="color:#000000;fill:#de0000;fill-opacity:1;stroke:none;stroke-width:0.0919748;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="m 12.195014,13.806679 a 1.2747098,1.2747098 0 0 0 -0.661606,0.185205 l -6.6465924,4.037177 a 1.2745823,1.2745823 0 0 0 -0.427537,1.751108 1.2745823,1.2745823 0 0 0 1.750928,0.427718 l 5.9848074,-3.635327 5.984807,3.635327 a 1.2745823,1.2745823 0 0 0 1.750928,-0.427718 1.2745823,1.2745823 0 0 0 -0.427537,-1.751108 l -6.646414,-4.037177 a 1.2747098,1.2747098 0 0 0 -0.661784,-0.185205 z"
|
||||
id="path9316" />
|
||||
</svg>
|
Before Width: | Height: | Size: 2.7 KiB |
39
assets/priority_5_alt3_24dp.svg
Normal file
39
assets/priority_5_alt3_24dp.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
fill="#000000"
|
||||
version="1.1"
|
||||
id="svg1428"
|
||||
sodipodi:docname="priority_5_24dp.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1432" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1430"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="26.806921"
|
||||
inkscape:cx="18.894374"
|
||||
inkscape:cy="14.026229"
|
||||
inkscape:window-width="1863"
|
||||
inkscape:window-height="1025"
|
||||
inkscape:window-x="57"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1428" />
|
||||
<path
|
||||
d="M 16.748063,0.46162067 H 7.1927317 L 0.44251841,7.211834 v 9.555331 l 6.75021329,6.750213 h 9.5553313 l 6.750213,-6.750213 V 7.211834 Z M 11.970397,18.778139 c -0.922231,0 -1.665138,-0.742908 -1.665138,-1.665138 0,-0.92223 0.742907,-1.665138 1.665138,-1.665138 0.92223,0 1.665138,0.742908 1.665138,1.665138 0,0.92223 -0.742908,1.665138 -1.665138,1.665138 z m 1.280875,-5.507765 H 10.689521 V 5.5851222 h 2.561751 z"
|
||||
id="path29312"
|
||||
style="fill:#ac0000;fill-opacity:1;stroke-width:1.28088" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
Loading…
Reference in a new issue