Everything works

This commit is contained in:
Philipp Heckel 2022-05-05 21:06:21 -04:00
parent 9f6dd91088
commit b8766fbcd4
6 changed files with 89 additions and 32 deletions

View file

@ -9,7 +9,6 @@ import android.content.Intent.ACTION_VIEW
import android.net.Uri
import android.os.Bundle
import android.text.Html
import android.util.Base64
import android.view.ActionMode
import android.view.Menu
import android.view.MenuItem
@ -33,7 +32,6 @@ import io.heckel.ntfy.db.Subscription
import io.heckel.ntfy.firebase.FirebaseMessenger
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.msg.ApiService
import io.heckel.ntfy.msg.MESSAGE_ENCODING_BASE64
import io.heckel.ntfy.msg.NotificationService
import io.heckel.ntfy.service.SubscriberServiceManager
import io.heckel.ntfy.util.*
@ -249,15 +247,24 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
}
// Mark this subscription as "open" so we don't receive notifications for it
Log.d(TAG, "onCreate hook: Marking subscription $subscriptionId as 'open'")
repository.detailViewSubscriptionId.set(subscriptionId)
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume hook: Marking subscription $subscriptionId as 'open'")
repository.detailViewSubscriptionId.set(subscriptionId) // Mark as "open" so we don't send notifications while this is open
// Mark as "open" so we don't send notifications while this is open
repository.detailViewSubscriptionId.set(subscriptionId)
// Update buttons (this is for when we return from the preferences screen)
lifecycleScope.launch(Dispatchers.IO) {
val subscription = repository.getSubscription(subscriptionId) ?: return@launch
subscriptionInstant = subscription.instant
subscriptionMutedUntil = subscription.mutedUntil
showHideInstantMenuItems(subscriptionInstant)
showHideMutedUntilMenuItems(subscriptionMutedUntil)
}
}
override fun onPause() {
@ -290,7 +297,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
// Show and hide buttons
showHideInstantMenuItems(subscriptionInstant)
showHideNotificationMenuItems(subscriptionMutedUntil)
showHideMutedUntilMenuItems(subscriptionMutedUntil)
// Regularly check if "notification muted" time has passed
// NOTE: This is done here, because then we know that we've initialized the menu items.
@ -300,6 +307,8 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
}
private fun startNotificationMutedChecker() {
// FIXME This is awful and has to go.
lifecycleScope.launch(Dispatchers.IO) {
delay(1000) // Just to be sure we've initialized all the things, we wait a bit ...
while (isActive) {
@ -309,7 +318,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
if (mutedUntilExpired) {
val newSubscription = subscription.copy(mutedUntil = 0L)
repository.updateSubscription(newSubscription)
showHideNotificationMenuItems(0L)
showHideMutedUntilMenuItems(0L)
}
delay(60_000)
}
@ -414,7 +423,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
val newSubscription = subscription?.copy(mutedUntil = mutedUntilTimestamp)
newSubscription?.let { repository.updateSubscription(newSubscription) }
subscriptionMutedUntil = mutedUntilTimestamp
showHideNotificationMenuItems(mutedUntilTimestamp)
showHideMutedUntilMenuItems(mutedUntilTimestamp)
runOnUiThread {
when (mutedUntilTimestamp) {
0L -> Toast.makeText(this@DetailActivity, getString(R.string.notification_dialog_enabled_toast_message), Toast.LENGTH_LONG).show()
@ -493,6 +502,9 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
}
private fun showHideInstantMenuItems(enable: Boolean) {
if (!this::menu.isInitialized) {
return
}
subscriptionInstant = enable
runOnUiThread {
val appBaseUrl = getString(R.string.app_base_url)
@ -509,7 +521,10 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
}
}
private fun showHideNotificationMenuItems(mutedUntilTimestamp: Long) {
private fun showHideMutedUntilMenuItems(mutedUntilTimestamp: Long) {
if (!this::menu.isInitialized) {
return
}
subscriptionMutedUntil = mutedUntilTimestamp
runOnUiThread {
val notificationsEnabledItem = menu.findItem(R.id.detail_menu_notifications_enabled)

View file

@ -3,20 +3,14 @@ package io.heckel.ntfy.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceDataStore
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.*
import io.heckel.ntfy.BuildConfig
import io.heckel.ntfy.R
import io.heckel.ntfy.db.Repository
import io.heckel.ntfy.db.Subscription
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.service.SubscriberServiceManager
import io.heckel.ntfy.util.formatDateShort
import io.heckel.ntfy.util.toPriorityString
import io.heckel.ntfy.util.topicShortUrl
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import io.heckel.ntfy.util.*
import kotlinx.coroutines.*
import java.util.*
/**
@ -77,18 +71,43 @@ class DetailSettingsActivity : AppCompatActivity() {
// Load subscription and users
val subscriptionId = arguments?.getLong(DetailActivity.EXTRA_SUBSCRIPTION_ID) ?: return
lifecycleScope.launch(Dispatchers.IO) {
subscription = repository.getSubscription(subscriptionId) ?: return@launch
activity?.runOnUiThread {
loadView()
runBlocking {
withContext(Dispatchers.IO) {
subscription = repository.getSubscription(subscriptionId) ?: return@withContext
activity?.runOnUiThread {
loadView()
}
}
}
}
private fun loadView() {
// Instant delivery
val appBaseUrl = getString(R.string.app_base_url)
val instantEnabledPrefId = context?.getString(R.string.detail_settings_notifications_instant_key) ?: return
val instantEnabled: SwitchPreference? = findPreference(instantEnabledPrefId)
instantEnabled?.isVisible = BuildConfig.FIREBASE_AVAILABLE && subscription.baseUrl == appBaseUrl
instantEnabled?.isChecked = subscription.instant
instantEnabled?.preferenceDataStore = object : PreferenceDataStore() {
override fun putBoolean(key: String?, value: Boolean) {
save(subscription.copy(instant = value), refresh = true)
}
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
return subscription.instant
}
}
instantEnabled?.summaryProvider = Preference.SummaryProvider<SwitchPreference> { pref ->
if (pref.isChecked) {
getString(R.string.detail_settings_notifications_instant_summary_on)
} else {
getString(R.string.detail_settings_notifications_instant_summary_off)
}
}
// Notifications muted until
val mutedUntilPrefId = context?.getString(R.string.detail_settings_notifications_muted_until_key) ?: return
val mutedUntil: ListPreference? = findPreference(mutedUntilPrefId)
mutedUntil?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
mutedUntil?.value = subscription.mutedUntil.toString()
mutedUntil?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
@ -130,6 +149,7 @@ class DetailSettingsActivity : AppCompatActivity() {
// Minimum priority
val minPriorityPrefId = context?.getString(R.string.detail_settings_notifications_min_priority_key) ?: return
val minPriority: ListPreference? = findPreference(minPriorityPrefId)
minPriority?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
minPriority?.value = subscription.minPriority.toString()
minPriority?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
@ -160,6 +180,7 @@ class DetailSettingsActivity : AppCompatActivity() {
// Auto delete
val autoDeletePrefId = context?.getString(R.string.detail_settings_notifications_auto_delete_key) ?: return
val autoDelete: ListPreference? = findPreference(autoDeletePrefId)
autoDelete?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
autoDelete?.value = subscription.autoDelete.toString()
autoDelete?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
@ -189,16 +210,19 @@ class DetailSettingsActivity : AppCompatActivity() {
}
}
private fun save(newSubscription: Subscription) {
private fun save(newSubscription: Subscription, refresh: Boolean = false) {
subscription = newSubscription
lifecycleScope.launch(Dispatchers.IO) {
repository.updateSubscription(newSubscription)
if (refresh) {
SubscriberServiceManager.refresh(requireContext())
}
}
}
private fun maybeAppendGlobal(summary: String, global: Boolean): String {
return if (global) {
summary + " (" + getString(R.string.settings_global_setting_suffix) + ")"
summary + " (" + getString(R.string.detail_settings_global_setting_suffix) + ")"
} else {
summary
}

View file

@ -9,6 +9,7 @@ import io.heckel.ntfy.db.Subscription
import io.heckel.ntfy.service.SubscriberServiceManager
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.util.randomString
import io.heckel.ntfy.util.shortUrl
import io.heckel.ntfy.util.topicUrlUp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@ -95,6 +96,10 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
Log.w(TAG, "Failed to add subscription", e)
distributor.sendRegistrationFailed(appId, connectorToken, e.message)
}
// Add to log scrubber
Log.addScrubTerm(shortUrl(baseUrl), Log.TermType.Domain)
Log.addScrubTerm(topic)
}
}
}

View file

@ -334,8 +334,13 @@
<string name="settings_about_version_title">Version</string>
<string name="settings_about_version_format">ntfy %1$s (%2$s)</string>
<string name="settings_about_version_copied_to_clipboard_message">Copied to clipboard</string>
<string name="settings_global_setting_title">Use global setting</string>
<string name="settings_global_setting_suffix">global</string>
<!-- Subscription settings (most strings are re-used from above) -->
<string name="detail_settings_notifications_instant_title">Instant delivery</string>
<string name="detail_settings_notifications_instant_summary_on">Notifications are delivered instantly. Requires a foreground service and consumes more battery.</string>
<string name="detail_settings_notifications_instant_summary_off">Notifications are delivered using Firebase. Delivery may be delayed, but consumes less battery.</string>
<string name="detail_settings_global_setting_title">Use global setting</string>
<string name="detail_settings_global_setting_suffix">global</string>
<!-- User add/edit dialog -->
<string name="user_dialog_title_add">Add user</string>

View file

@ -31,6 +31,7 @@
<string name="settings_about_version_key" translatable="false">Version</string>
<!-- Detail settings constants -->
<string name="detail_settings_notifications_instant_key" translatable="false">SubscriptionInstant</string>
<string name="detail_settings_notifications_muted_until_key" translatable="false">SubscriptionMutedUntil</string>
<string name="detail_settings_notifications_min_priority_key" translatable="false">SubscriptionMinPriority</string>
<string name="detail_settings_notifications_auto_delete_key" translatable="false">SubscriptionAutoDelete</string>
@ -69,7 +70,7 @@
<item>5</item>
</string-array>
<string-array name="detail_settings_notifications_min_priority_entries">
<item>@string/settings_global_setting_title</item>
<item>@string/detail_settings_global_setting_title</item>
<item>@string/settings_notifications_min_priority_min</item>
<item>@string/settings_notifications_min_priority_low</item>
<item>@string/settings_notifications_min_priority_default</item>
@ -121,7 +122,7 @@
<item>7776000</item>
</string-array>
<string-array name="detail_settings_notifications_auto_delete_entries">
<item>@string/settings_global_setting_title</item>
<item>@string/detail_settings_global_setting_title</item>
<item>@string/settings_notifications_auto_delete_never</item>
<item>@string/settings_notifications_auto_delete_one_day</item>
<item>@string/settings_notifications_auto_delete_three_days</item>

View file

@ -1,23 +1,30 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
app:title="@string/detail_settings_title">
<PreferenceCategory app:title="@string/settings_notifications_header">
<SwitchPreference
app:key="@string/detail_settings_notifications_instant_key"
app:title="@string/detail_settings_notifications_instant_title"
app:isPreferenceVisible="false"/>
<ListPreference
app:key="@string/detail_settings_notifications_muted_until_key"
app:title="@string/settings_notifications_muted_until_title"
app:entries="@array/settings_notifications_muted_until_entries"
app:entryValues="@array/settings_notifications_muted_until_values"
app:defaultValue="0"/>
app:defaultValue="0"
app:isPreferenceVisible="false"/>
<ListPreference
app:key="@string/detail_settings_notifications_min_priority_key"
app:title="@string/settings_notifications_min_priority_title"
app:entries="@array/detail_settings_notifications_min_priority_entries"
app:entryValues="@array/detail_settings_notifications_min_priority_values"
app:defaultValue="0"/> <!-- Same as Repository.MIN_PRIORITY_USE_GLOBAL -->
app:defaultValue="0"
app:isPreferenceVisible="false"/> <!-- Same as Repository.MIN_PRIORITY_USE_GLOBAL -->
<ListPreference
app:key="@string/detail_settings_notifications_auto_delete_key"
app:title="@string/settings_notifications_auto_delete_title"
app:entries="@array/detail_settings_notifications_auto_delete_entries"
app:entryValues="@array/detail_settings_notifications_auto_delete_values"
app:defaultValue="-1"/> <!-- Same as Repository.AUTO_DELETE_USE_GLOBAL -->
app:defaultValue="-1"
app:isPreferenceVisible="false"/> <!-- Same as Repository.AUTO_DELETE_USE_GLOBAL -->
</PreferenceCategory>
</PreferenceScreen>