Adjut foreground notification to reflect subscription state, add instant icon to non-ntfy.sh subscriptions

This commit is contained in:
Philipp Heckel 2021-11-15 07:57:35 -05:00
parent cea43b3529
commit ce6a2152db
6 changed files with 60 additions and 19 deletions

View file

@ -131,6 +131,18 @@ class SubscriberService : Service() {
cancelJob(subscriptionId) cancelJob(subscriptionId)
} }
} }
if (jobs.size > 0) {
synchronized(this) {
val title = getString(R.string.channel_subscriber_notification_title)
val text = if (jobs.size == 1) {
getString(R.string.channel_subscriber_notification_text_one)
} else {
getString(R.string.channel_subscriber_notification_text_more, jobs.size)
}
notification = createNotification(title, text)
notificationManager?.notify(NOTIFICATION_SERVICE_ID, notification)
}
}
} }
private fun cancelJob(subscriptionId: Long?) { private fun cancelJob(subscriptionId: Long?) {

View file

@ -1,6 +1,5 @@
package io.heckel.ntfy.ui package io.heckel.ntfy.ui
import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import android.app.Dialog import android.app.Dialog
import android.os.Bundle import android.os.Bundle
@ -9,14 +8,10 @@ import android.text.TextWatcher
import android.view.View import android.view.View
import android.widget.Button import android.widget.Button
import android.widget.CheckBox import android.widget.CheckBox
import androidx.activity.viewModels
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import io.heckel.ntfy.R import io.heckel.ntfy.R
import io.heckel.ntfy.app.Application
import io.heckel.ntfy.data.Repository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -25,6 +20,7 @@ class AddFragment(private val viewModel: SubscriptionsViewModel, private val onS
private lateinit var baseUrlText: TextInputEditText private lateinit var baseUrlText: TextInputEditText
private lateinit var useAnotherServerCheckbox: CheckBox private lateinit var useAnotherServerCheckbox: CheckBox
private lateinit var useAnotherServerDescription: View private lateinit var useAnotherServerDescription: View
private lateinit var instantDeliveryBox: View
private lateinit var instantDeliveryCheckbox: CheckBox private lateinit var instantDeliveryCheckbox: CheckBox
private lateinit var instantDeliveryDescription: View private lateinit var instantDeliveryDescription: View
private lateinit var subscribeButton: Button private lateinit var subscribeButton: Button
@ -35,6 +31,7 @@ class AddFragment(private val viewModel: SubscriptionsViewModel, private val onS
val view = requireActivity().layoutInflater.inflate(R.layout.add_dialog_fragment, null) val view = requireActivity().layoutInflater.inflate(R.layout.add_dialog_fragment, null)
topicNameText = view.findViewById(R.id.add_dialog_topic_text) as TextInputEditText topicNameText = view.findViewById(R.id.add_dialog_topic_text) as TextInputEditText
baseUrlText = view.findViewById(R.id.add_dialog_base_url_text) as TextInputEditText baseUrlText = view.findViewById(R.id.add_dialog_base_url_text) as TextInputEditText
instantDeliveryBox = view.findViewById(R.id.add_dialog_instant_delivery_box)
instantDeliveryCheckbox = view.findViewById(R.id.add_dialog_instant_delivery_checkbox) as CheckBox instantDeliveryCheckbox = view.findViewById(R.id.add_dialog_instant_delivery_checkbox) as CheckBox
instantDeliveryDescription = view.findViewById(R.id.add_dialog_instant_delivery_description) instantDeliveryDescription = view.findViewById(R.id.add_dialog_instant_delivery_description)
useAnotherServerCheckbox = view.findViewById(R.id.add_dialog_use_another_server_checkbox) as CheckBox useAnotherServerCheckbox = view.findViewById(R.id.add_dialog_use_another_server_checkbox) as CheckBox
@ -82,12 +79,12 @@ class AddFragment(private val viewModel: SubscriptionsViewModel, private val onS
if (isChecked) { if (isChecked) {
useAnotherServerDescription.visibility = View.VISIBLE useAnotherServerDescription.visibility = View.VISIBLE
baseUrlText.visibility = View.VISIBLE baseUrlText.visibility = View.VISIBLE
instantDeliveryCheckbox.visibility = View.GONE instantDeliveryBox.visibility = View.GONE
instantDeliveryDescription.visibility = View.GONE instantDeliveryDescription.visibility = View.GONE
} else { } else {
useAnotherServerDescription.visibility = View.GONE useAnotherServerDescription.visibility = View.GONE
baseUrlText.visibility = View.GONE baseUrlText.visibility = View.GONE
instantDeliveryCheckbox.visibility = View.VISIBLE instantDeliveryBox.visibility = View.VISIBLE
if (instantDeliveryCheckbox.isChecked) instantDeliveryDescription.visibility = View.VISIBLE if (instantDeliveryCheckbox.isChecked) instantDeliveryDescription.visibility = View.VISIBLE
else instantDeliveryDescription.visibility = View.GONE else instantDeliveryDescription.visibility = View.GONE
} }

View file

@ -143,6 +143,10 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback {
onInstantEnableClick(enable = false) onInstantEnableClick(enable = false)
true true
} }
R.id.detail_menu_instant_info -> {
onInstantInfoClick()
true
}
R.id.detail_menu_copy_url -> { R.id.detail_menu_copy_url -> {
onCopyUrlClick() onCopyUrlClick()
true true
@ -232,18 +236,27 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback {
} }
} }
private fun onInstantInfoClick() {
Log.d(TAG, "Showing instant info toast")
Toast.makeText(this@DetailActivity, getString(R.string.detail_instant_info), Toast.LENGTH_LONG)
.show()
}
private fun showHideInstantMenuItems(enable: Boolean) { private fun showHideInstantMenuItems(enable: Boolean) {
subscriptionInstant = enable subscriptionInstant = enable
runOnUiThread { runOnUiThread {
val appBaseUrl = getString(R.string.app_base_url) val appBaseUrl = getString(R.string.app_base_url)
val enableInstantItem = menu.findItem(R.id.detail_menu_enable_instant) val enableInstantItem = menu.findItem(R.id.detail_menu_enable_instant)
val disableInstantItem = menu.findItem(R.id.detail_menu_disable_instant) val disableInstantItem = menu.findItem(R.id.detail_menu_disable_instant)
val instantInfoItem = menu.findItem(R.id.detail_menu_instant_info)
if (subscriptionBaseUrl == appBaseUrl) { if (subscriptionBaseUrl == appBaseUrl) {
enableInstantItem?.isVisible = !subscriptionInstant enableInstantItem?.isVisible = !subscriptionInstant
disableInstantItem?.isVisible = subscriptionInstant disableInstantItem?.isVisible = subscriptionInstant
instantInfoItem?.isVisible = false
} else { } else {
enableInstantItem?.isVisible = false enableInstantItem?.isVisible = false
disableInstantItem?.isVisible = false disableInstantItem?.isVisible = false
instantInfoItem?.isVisible = true
} }
} }
} }
@ -349,6 +362,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback {
Toast Toast
.makeText(this@DetailActivity, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG) .makeText(this@DetailActivity, getString(R.string.detail_copied_to_clipboard_message), Toast.LENGTH_LONG)
.show() .show()
finishActionMode()
} }
} }
} }

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="16dp" android:paddingLeft="16dp"
@ -43,11 +43,23 @@
android:layout_height="wrap_content" android:visibility="gone" android:layout_height="wrap_content" android:visibility="gone"
android:hint="@string/app_base_url" android:inputType="textUri" android:maxLines="1" android:hint="@string/app_base_url" android:inputType="textUri" android:maxLines="1"
android:layout_marginTop="-2dp" android:layout_marginBottom="5dp"/> android:layout_marginTop="-2dp" android:layout_marginBottom="5dp"/>
<CheckBox <LinearLayout
android:text="@string/add_dialog_instant_delivery" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/add_dialog_instant_delivery_checkbox" android:layout_height="wrap_content" android:id="@+id/add_dialog_instant_delivery_box">
android:layout_marginTop="-8dp" android:layout_marginBottom="-5dp" android:layout_marginStart="-3dp"/> <CheckBox
android:text="@string/add_dialog_instant_delivery"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/add_dialog_instant_delivery_checkbox"
android:layout_marginTop="-8dp" android:layout_marginBottom="-5dp" android:layout_marginStart="-3dp"/>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp" app:srcCompat="@drawable/ic_bolt_black_24dp"
android:id="@+id/add_dialog_instant_image"
app:layout_constraintTop_toTopOf="@+id/main_item_text"
app:layout_constraintEnd_toStartOf="@+id/main_item_date" android:paddingTop="3dp"
android:layout_marginTop="3dp"/>
</LinearLayout>
<TextView <TextView
android:text="@string/add_dialog_instant_delivery_description" android:text="@string/add_dialog_instant_delivery_description"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -3,6 +3,8 @@
app:showAsAction="ifRoom|withText" android:icon="@drawable/ic_bolt_outline_white_24dp"/> 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"/> android:icon="@drawable/ic_bolt_white_24dp" app:showAsAction="ifRoom|withText"/>
<item android:id="@+id/detail_menu_instant_info" android:title="@string/detail_menu_instant_info"
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_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"/>

View file

@ -6,8 +6,10 @@
<!-- Notification channels --> <!-- Notification channels -->
<string name="channel_notifications_name">Notifications</string> <string name="channel_notifications_name">Notifications</string>
<string name="channel_subscriber_service_name">Subscription Service</string> <string name="channel_subscriber_service_name">Subscription Service</string>
<string name="channel_subscriber_notification_title">Subscribed topics</string> <string name="channel_subscriber_notification_title">Listening for incoming notifications</string>
<string name="channel_subscriber_notification_text">Listening for incoming notifications</string> <string name="channel_subscriber_notification_text">You are subscribed to instant delivery topics</string>
<string name="channel_subscriber_notification_text_one">You are subscribed to one instant delivery topic</string>
<string name="channel_subscriber_notification_text_more">You are subscribed to %1$d instant delivery topics</string>
<!-- Common refresh toasts --> <!-- Common refresh toasts -->
<string name="refresh_message_result">%1$d notification(s) received</string> <string name="refresh_message_result">%1$d notification(s) received</string>
@ -16,7 +18,7 @@
<!-- Main activity: Action bar --> <!-- Main activity: Action bar -->
<string name="main_action_bar_title">Subscribed topics</string> <string name="main_action_bar_title">Subscribed topics</string>
<string name="main_menu_source_title">View source &amp; report bugs</string> <string name="main_menu_source_title">Report a bug</string>
<string name="main_menu_source_url">https://heckel.io/ntfy-android</string> <string name="main_menu_source_url">https://heckel.io/ntfy-android</string>
<string name="main_menu_website_title">Visit ntfy.sh</string> <string name="main_menu_website_title">Visit ntfy.sh</string>
@ -42,12 +44,12 @@
<string name="add_dialog_use_another_server">Use another server</string> <string name="add_dialog_use_another_server">Use another server</string>
<string name="add_dialog_use_another_server_description"> <string name="add_dialog_use_another_server_description">
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 power, but also delivers notifications faster (even in doze mode).
</string> </string>
<string name="add_dialog_instant_delivery">Instant delivery even in doze mode</string> <string name="add_dialog_instant_delivery">Instant delivery in doze mode</string>
<string name="add_dialog_instant_delivery_description"> <string name="add_dialog_instant_delivery_description">
Android doze mode may delay message delivery. With this open, notifications are immediately delivered even in doze mode. Doze mode sometimes causes delayed message delivery to conserve power. With instant delivery, notifications are
Requires foreground service and consumes more battery. always immediately delivered. This requires a foreground service and consumes a little more power.
</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>
@ -65,12 +67,14 @@
<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">Instant delivery enabled</string> <string name="detail_instant_delivery_enabled">Instant delivery enabled</string>
<string name="detail_instant_delivery_disabled">Instant delivery disabled</string> <string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
<string name="detail_instant_info">Instant delivery is always enabled for subscriptions with other servers</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 instant delivery</string> <string name="detail_menu_enable_instant">Enable instant delivery</string>
<string name="detail_menu_disable_instant">Disable instant delivery</string> <string name="detail_menu_disable_instant">Disable instant delivery</string>
<string name="detail_menu_instant_info">Instant delivery enabled</string>
<string name="detail_menu_unsubscribe">Unsubscribe</string> <string name="detail_menu_unsubscribe">Unsubscribe</string>
<!-- Detail activity: Action mode --> <!-- Detail activity: Action mode -->