Instant delivery icon; multi-copy

This commit is contained in:
Philipp Heckel 2021-11-14 20:22:02 -05:00
parent 8be6201ea2
commit f69d1f5ee1
13 changed files with 126 additions and 12 deletions

View file

@ -64,6 +64,10 @@ class Repository(private val subscriptionDao: SubscriptionDao, private val notif
return notificationDao.list(subscriptionId).asLiveData() return notificationDao.list(subscriptionId).asLiveData()
} }
fun getNotification(notificationId: String): Notification? {
return notificationDao.get(notificationId)
}
fun onlyNewNotifications(subscriptionId: Long, notifications: List<Notification>): List<Notification> { fun onlyNewNotifications(subscriptionId: Long, notifications: List<Notification>): List<Notification> {
val existingIds = notificationDao.listIds(subscriptionId) val existingIds = notificationDao.listIds(subscriptionId)
return notifications.filterNot { existingIds.contains(it.id) } return notifications.filterNot { existingIds.contains(it.id) }

View file

@ -320,6 +320,10 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return when (item?.itemId) { return when (item?.itemId) {
R.id.detail_action_mode_copy -> {
onMultiCopyClick()
true
}
R.id.detail_action_mode_delete -> { R.id.detail_action_mode_delete -> {
onMultiDeleteClick() onMultiDeleteClick()
true true
@ -328,6 +332,27 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback {
} }
} }
private fun onMultiCopyClick() {
Log.d(TAG, "Copying multiple notifications to clipboard")
lifecycleScope.launch(Dispatchers.IO) {
val content = adapter.selected.joinToString("\n\n") { notificationId ->
val notification = repository.getNotification(notificationId)
notification?.let {
it.message + "\n" + Date(it.timestamp * 1000).toString()
}.orEmpty()
}
val clipboard: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("notifications", content)
clipboard.setPrimaryClip(clip)
runOnUiThread {
Toast
.makeText(this@DetailActivity, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG)
.show()
}
}
}
private fun onMultiDeleteClick() { private fun onMultiDeleteClick() {
Log.d(TAG, "Showing multi-delete dialog for selected items") Log.d(TAG, "Showing multi-delete dialog for selected items")

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12.5449,2.1992 L12.3145,2.6035C9.7352,7.1246 7.809,10.5009 6.5176,12.7832c0.0118,-0.0179 -0.0053,0.0121 -0.0254,0.043 -0.024,0.0369 -0.055,0.0842 -0.0879,0.1445 -0.0657,0.1206 -0.1489,0.2813 -0.1875,0.5273 -0.0386,0.2461 0.0075,0.6682 0.2988,0.9551 0.2913,0.2869 0.6507,0.3477 0.9844,0.3477h2.5781l-1,7h2.3867l0.2305,-0.4043c0,0 1.9682,-3.4483 5.918,-10.3379l0.0176,-0.0293L17.6445,11C17.8155,10.6348 17.9095,10.1065 17.5996,9.6816 17.2897,9.2568 16.8462,9.1992 16.5195,9.1992h-2.5859l0.998,-7zM12.959,4.707 L12.0879,10.8008h3.8301c-3.0779,5.37 -4.4616,7.7886 -4.8691,8.502l0.873,-6.1035L8.123,13.1992C9.238,11.2305 10.9448,8.2378 12.959,4.707Z"
android:fillColor="#FFFFFF"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M11,21h-1l1,-7H7.5c-0.88,0 -0.33,-0.75 -0.31,-0.78C8.48,10.94 10.42,7.54 13.01,3h1l-1,7h3.51c0.4,0 0.62,0.19 0.4,0.66C12.97,17.55 11,21 11,21z"
android:fillColor="@android:color/white"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"
android:fillColor="@android:color/white"/>
</vector>

View file

@ -1,8 +1,9 @@
<menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/detail_menu_test" android:title="@string/detail_menu_test"/>
<item android:id="@+id/detail_menu_enable_instant" android:title="@string/detail_menu_enable_instant" <item android:id="@+id/detail_menu_enable_instant" android:title="@string/detail_menu_enable_instant"
/> app:showAsAction="ifRoom|withText" android:icon="@drawable/ic_bolt_outline_white_24dp"/>
<item android:id="@+id/detail_menu_disable_instant" android:title="@string/detail_menu_disable_instant"/> <item android:id="@+id/detail_menu_disable_instant" android:title="@string/detail_menu_disable_instant"
android:icon="@drawable/ic_bolt_white_24dp" app:showAsAction="ifRoom|withText"/>
<item android:id="@+id/detail_menu_test" android:title="@string/detail_menu_test"/>
<item android:id="@+id/detail_menu_copy_url" android:title="@string/detail_menu_copy_url"/> <item android:id="@+id/detail_menu_copy_url" android:title="@string/detail_menu_copy_url"/>
<item android:id="@+id/detail_menu_unsubscribe" android:title="@string/detail_menu_unsubscribe"/> <item android:id="@+id/detail_menu_unsubscribe" android:title="@string/detail_menu_unsubscribe"/>
</menu> </menu>

View file

@ -1,4 +1,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/detail_action_mode_copy" android:title="@string/detail_action_mode_menu_copy"
android:icon="@drawable/ic_content_copy_white_24dp"/>
<item android:id="@+id/detail_action_mode_delete" android:title="@string/detail_action_mode_menu_delete" <item android:id="@+id/detail_action_mode_delete" android:title="@string/detail_action_mode_menu_delete"
android:icon="@drawable/ic_delete_gray_20dp"/> android:icon="@drawable/ic_delete_white_20dp"/>
</menu> </menu>

View file

@ -1,4 +1,4 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/main_action_mode_delete" android:title="@string/main_action_mode_menu_unsubscribe" <item android:id="@+id/main_action_mode_delete" android:title="@string/main_action_mode_menu_unsubscribe"
android:icon="@drawable/ic_delete_gray_20dp"/> android:icon="@drawable/ic_delete_white_20dp"/>
</menu> </menu>

View file

@ -43,10 +43,10 @@
You can subscribe to topics from your own server. Due to platform limitations, this option requires a foreground You can subscribe to topics from your own server. Due to platform limitations, this option requires a foreground
service and consumes more battery, but delivers notifications faster. service and consumes more battery, but delivers notifications faster.
</string> </string>
<string name="add_dialog_instant_delivery">Fast delivery</string> <string name="add_dialog_instant_delivery">Instant delivery even in doze mode</string>
<string name="add_dialog_instant_delivery_description"> <string name="add_dialog_instant_delivery_description">
Enables instant notification delivery even in doze mode. Requires foreground service and consumes more Android doze mode may delay message delivery. With this open, notifications are immediately delivered even in doze mode.
battery. Requires foreground service and consumes more battery.
</string> </string>
<string name="add_dialog_button_cancel">Cancel</string> <string name="add_dialog_button_cancel">Cancel</string>
<string name="add_dialog_button_subscribe">Subscribe</string> <string name="add_dialog_button_subscribe">Subscribe</string>
@ -62,17 +62,18 @@
<string name="detail_test_message">This is a test notification from the Ntfy Android app. It was sent at %1$s.</string> <string name="detail_test_message">This is a test notification from the Ntfy Android app. It was sent at %1$s.</string>
<string name="detail_test_message_error">Could not send test message: %1$s</string> <string name="detail_test_message_error">Could not send test message: %1$s</string>
<string name="detail_copied_to_clipboard_message">Copied to clipboard</string> <string name="detail_copied_to_clipboard_message">Copied to clipboard</string>
<string name="detail_instant_delivery_enabled">Fast delivery enabled</string> <string name="detail_instant_delivery_enabled">Instant delivery enabled</string>
<string name="detail_instant_delivery_disabled">Fast delivery disabled</string> <string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
<!-- Detail activity: Action bar --> <!-- Detail activity: Action bar -->
<string name="detail_menu_test">Send test notification</string> <string name="detail_menu_test">Send test notification</string>
<string name="detail_menu_copy_url">Copy topic address</string> <string name="detail_menu_copy_url">Copy topic address</string>
<string name="detail_menu_enable_instant">Enable fast delivery</string> <string name="detail_menu_enable_instant">Enable instant delivery</string>
<string name="detail_menu_disable_instant">Disable fast delivery</string> <string name="detail_menu_disable_instant">Disable instant delivery</string>
<string name="detail_menu_unsubscribe">Unsubscribe</string> <string name="detail_menu_unsubscribe">Unsubscribe</string>
<!-- Detail activity: Action mode --> <!-- Detail activity: Action mode -->
<string name="detail_action_mode_menu_copy">Copy</string>
<string name="detail_action_mode_menu_delete">Delete</string> <string name="detail_action_mode_menu_delete">Delete</string>
<string name="detail_action_mode_delete_dialog_message">Do you really want to permanently delete the selected message(s)?</string> <string name="detail_action_mode_delete_dialog_message">Do you really want to permanently delete the selected message(s)?</string>
<string name="detail_action_mode_delete_dialog_permanently_delete">Permanently delete</string> <string name="detail_action_mode_delete_dialog_permanently_delete">Permanently delete</string>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
enable-background="new 0 0 24 24"
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="#000000"
version="1.1"
id="svg1134"
sodipodi:docname="bolt_outline_black_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="defs1138" />
<sodipodi:namedview
id="namedview1136"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="34.25"
inkscape:cx="11.985401"
inkscape:cy="12"
inkscape:window-width="1863"
inkscape:window-height="1025"
inkscape:window-x="57"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg1134" />
<g
id="g1128">
<rect
fill="none"
height="24"
width="24"
id="rect1126" />
</g>
<g
id="g1132"
style="fill:none;stroke:none;stroke-width:1.6;stroke-miterlimit:4;stroke-dasharray:none">
<path
style="color:#000000;fill:#000000;stroke:none;stroke-width:1.6;stroke-miterlimit:4;stroke-dasharray:none"
d="M 12.544922,2.1992188 12.314453,2.6035156 C 9.7352458,7.1245973 7.8090019,10.500925 6.5175781,12.783203 c 0.011757,-0.01794 -0.00527,0.0121 -0.025391,0.04297 -0.024036,0.03689 -0.055025,0.08424 -0.087891,0.144531 -0.065731,0.12059 -0.1488992,0.281264 -0.1875,0.527344 -0.038601,0.24608 0.0075,0.668184 0.2988281,0.955078 0.2913277,0.286894 0.650739,0.347656 0.984375,0.347656 h 2.578125 l -1,7 h 2.386719 l 0.230469,-0.404297 c 0,0 1.9682,-3.448295 5.917968,-10.33789 l 0.01758,-0.0293 L 17.644531,11 C 17.815485,10.63478 17.909486,10.106472 17.599609,9.6816406 17.289733,9.2568094 16.846198,9.1992187 16.519531,9.1992188 h -2.585937 l 0.998047,-7 z m 0.414062,2.5078124 -0.871093,6.0937498 h 3.830078 c -3.077948,5.36999 -4.4616,7.788597 -4.869141,8.501953 l 0.873047,-6.103515 H 8.1230469 C 9.2380038,11.230513 10.944815,8.2378044 12.958984,4.7070312 Z"
id="path1130" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>

After

Width:  |  Height:  |  Size: 286 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4.01 6.03l7.51 3.22-7.52-1 .01-2.22m7.5 8.72L4 17.97v-2.22l7.51-1M2.01 3L2 10l15 2-15 2 .01 7L23 12 2.01 3z"/></svg>

After

Width:  |  Height:  |  Size: 267 B