Manual review

This commit is contained in:
Philipp Heckel 2026-04-03 15:17:47 -04:00
parent 8577576711
commit 3775c58d23
7 changed files with 57 additions and 57 deletions

View file

@ -447,17 +447,17 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
fun setConnectionAlertSeconds(seconds: Long) {
sharedPrefs.edit {
putLong(SHARED_PREFS_CONNECTION_ALERT_SECONDS, seconds)
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL, 0L)
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME, 0L)
}
}
fun getConnectionAlertSnoozeUntil(): Long {
return sharedPrefs.getLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL, 0L)
fun getConnectionAlertSnoozeUntilTime(): Long {
return sharedPrefs.getLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME, 0L)
}
fun setConnectionAlertSnoozeUntil(timeMillis: Long) {
fun setConnectionAlertSnoozeUntilTime(timeMillis: Long) {
sharedPrefs.edit {
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL, timeMillis)
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME, timeMillis)
}
}
@ -650,13 +650,13 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
const val SHARED_PREFS_INSISTENT_MAX_PRIORITY_ENABLED = "InsistentMaxPriority"
const val SHARED_PREFS_RECORD_LOGS_ENABLED = "RecordLogs"
const val SHARED_PREFS_MESSAGE_BAR_ENABLED = "MessageBarEnabled"
const val SHARED_PREFS_BATTERY_OPTIMIZATIONS_REMIND_TIME = "BatteryOptimizationsRemindTime"
const val SHARED_PREFS_WEBSOCKET_REMIND_TIME = "JsonStreamRemindTime" // "Use WebSocket" banner (used to be JSON stream deprecation banner)
const val SHARED_PREFS_WEBSOCKET_RECONNECT_REMIND_TIME = "WebSocketReconnectRemindTime"
const val SHARED_PREFS_BATTERY_OPTIMIZATIONS_REMIND_TIME = "BatteryOptimizationsRemindTime" // Timestamp as millis
const val SHARED_PREFS_WEBSOCKET_REMIND_TIME = "JsonStreamRemindTime" // "Use WebSocket" banner (used to be JSON stream deprecation banner), timestamp as millis
const val SHARED_PREFS_WEBSOCKET_RECONNECT_REMIND_TIME = "WebSocketReconnectRemindTime" // Timestamp as millis
const val SHARED_PREFS_UNIFIED_PUSH_BASE_URL = "UnifiedPushBaseURL" // Legacy key required for migration to DefaultBaseURL
const val SHARED_PREFS_DEFAULT_BASE_URL = "DefaultBaseURL"
const val SHARED_PREFS_CONNECTION_ALERT_SECONDS = "ConnectionAlertSeconds"
const val SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL = "ConnectionAlertSnoozeUntil"
const val SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME = "ConnectionAlertSnoozeUntilTime" // Timestamp in millis
const val SHARED_PREFS_LAST_TOPICS = "LastTopics"
private const val LAST_TOPICS_COUNT = 3
@ -668,12 +668,14 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
const val MUTED_UNTIL_FOREVER = 1L
const val MUTED_UNTIL_TOMORROW = 2L
private const val ONE_MB = 1024 * 1024L
private const val ONE_MB_BYTES = 1024 * 1024L
const val AUTO_DOWNLOAD_NEVER = 0L // Values must match values.xml
const val AUTO_DOWNLOAD_ALWAYS = 1L
const val AUTO_DOWNLOAD_DEFAULT = ONE_MB
const val AUTO_DOWNLOAD_DEFAULT = ONE_MB_BYTES
private const val ONE_HOUR_SECONDS = 60 * 60L
private const val ONE_DAY_SECONDS = 24 * ONE_HOUR_SECONDS
private const val ONE_DAY_SECONDS = 24 * 60 * 60L
const val AUTO_DELETE_USE_GLOBAL = -1L // Values must match values.xml
const val AUTO_DELETE_NEVER = 0L
const val AUTO_DELETE_ONE_DAY_SECONDS = ONE_DAY_SECONDS
@ -687,11 +689,11 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
const val INSISTENT_MAX_PRIORITY_ENABLED = 1 // 0 = Disabled (but not needed in code)
const val CONNECTION_ALERT_NEVER = 0L
const val CONNECTION_ALERT_FIVE_MINUTES = 5 * 60L
const val CONNECTION_ALERT_FIFTEEN_MINUTES = 15 * 60L
const val CONNECTION_ALERT_ONE_HOUR = 60 * 60L
const val CONNECTION_ALERT_THREE_HOURS = 3 * 60 * 60L
const val CONNECTION_ALERT_TWELVE_HOURS = 12 * 60 * 60L
const val CONNECTION_ALERT_FIVE_MINUTES_SECONDS = 5 * 60L
const val CONNECTION_ALERT_FIFTEEN_MINUTES_SECONDS = 15 * 60L
const val CONNECTION_ALERT_ONE_HOUR_SECONDS = ONE_HOUR_SECONDS
const val CONNECTION_ALERT_THREE_HOURS_SECONDS = 3 * ONE_HOUR_SECONDS
const val CONNECTION_ALERT_TWELVE_HOURS_SECONDS = 12 * ONE_HOUR_SECONDS
const val CONNECTION_ALERT_DEFAULT = CONNECTION_ALERT_NEVER
const val CONNECTION_PROTOCOL_JSONHTTP = "jsonhttp"

View file

@ -11,7 +11,6 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import io.heckel.ntfy.util.isNetworkAvailable
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
@ -29,6 +28,7 @@ import io.heckel.ntfy.ui.Colors
import io.heckel.ntfy.ui.MainActivity
import io.heckel.ntfy.util.HttpUtil
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.util.isNetworkAvailable
import io.heckel.ntfy.util.shortUrl
import io.heckel.ntfy.util.topicUrl
import kotlinx.coroutines.Dispatchers
@ -325,7 +325,7 @@ class SubscriberService : Service() {
val now = System.currentTimeMillis()
// Check snooze
val snoozeUntil = repository.getConnectionAlertSnoozeUntil()
val snoozeUntil = repository.getConnectionAlertSnoozeUntilTime()
if (snoozeUntil > now) return
// Check if any connection has been in error for longer than the threshold
@ -504,10 +504,10 @@ class SubscriberService : Service() {
val notificationManager = context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
when (intent.action) {
CONNECTION_ALERT_ACTION_DISMISS -> {
repository.setConnectionAlertSnoozeUntil(System.currentTimeMillis() + CONNECTION_ALERT_DISMISS_SNOOZE_MILLIS)
repository.setConnectionAlertSnoozeUntilTime(System.currentTimeMillis() + CONNECTION_ALERT_DISMISS_MILLIS)
}
CONNECTION_ALERT_ACTION_SNOOZE -> {
repository.setConnectionAlertSnoozeUntil(System.currentTimeMillis() + CONNECTION_ALERT_SNOOZE_DURATION_MILLIS)
repository.setConnectionAlertSnoozeUntilTime(System.currentTimeMillis() + CONNECTION_ALERT_SNOOZE_MILLIS)
}
CONNECTION_ALERT_ACTION_NEVER -> {
repository.setConnectionAlertSeconds(Repository.CONNECTION_ALERT_NEVER)
@ -528,6 +528,9 @@ class SubscriberService : Service() {
const val SERVICE_START_WORKER_VERSION = BuildConfig.VERSION_CODE
const val SERVICE_START_WORKER_WORK_NAME_PERIODIC = "NtfyAutoRestartWorkerPeriodic" // Do not change!
private const val ONE_HOUR_SECONDS = 60 * 60L
private const val ONE_HOUR_MILLIS = ONE_HOUR_SECONDS * 1000L
private const val WAKE_LOCK_TAG = "SubscriberService:lock"
private const val NOTIFICATION_CHANNEL_ID = "ntfy-subscriber"
private const val NOTIFICATION_CONNECTION_ALERT_CHANNEL_ID = "ntfy-connection-alert"
@ -535,10 +538,10 @@ class SubscriberService : Service() {
private const val NOTIFICATION_SERVICE_ID = 2586
private const val NOTIFICATION_RECEIVED_WAKELOCK_TIMEOUT_MILLIS = 10 * 60 * 1000L /*10 minutes*/
private const val NOTIFICATION_CONNECTION_ALERT_ID = 2587
const val NOTIFICATION_CONNECTION_ALERT_ID = 2587
private const val CONNECTION_ALERT_SNOOZE_HOURS = 8
private const val CONNECTION_ALERT_SNOOZE_DURATION_MILLIS = CONNECTION_ALERT_SNOOZE_HOURS * 60 * 60 * 1000L
private const val CONNECTION_ALERT_DISMISS_SNOOZE_MILLIS = 1 * 60 * 60 * 1000L /*1 hour*/
private const val CONNECTION_ALERT_SNOOZE_MILLIS = CONNECTION_ALERT_SNOOZE_HOURS * ONE_HOUR_MILLIS
private const val CONNECTION_ALERT_DISMISS_MILLIS = ONE_HOUR_MILLIS
private const val CONNECTION_ALERT_ACTION_DISMISS = "io.heckel.ntfy.CONNECTION_ALERT_DISMISS"
private const val CONNECTION_ALERT_ACTION_SNOOZE = "io.heckel.ntfy.CONNECTION_ALERT_SNOOZE"
private const val CONNECTION_ALERT_ACTION_NEVER = "io.heckel.ntfy.CONNECTION_ALERT_NEVER"

View file

@ -3,11 +3,11 @@ package io.heckel.ntfy.service
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import io.heckel.ntfy.util.isNetworkAvailable
import androidx.core.content.ContextCompat
import androidx.work.*
import io.heckel.ntfy.app.Application
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.util.isNetworkAvailable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -65,7 +65,7 @@ class SubscriberServiceManager(private val context: Context) {
if (!hasNetwork) {
app.repository.clearConnectionDetails()
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(NOTIFICATION_CONNECTION_ALERT_ID)
notificationManager.cancel(SubscriberService.NOTIFICATION_CONNECTION_ALERT_ID)
}
Intent(context, SubscriberService::class.java).also {
context.stopService(it)
@ -79,8 +79,6 @@ class SubscriberServiceManager(private val context: Context) {
companion object {
const val TAG = "NtfySubscriberMgr"
const val WORK_NAME_ONCE = "ServiceStartWorkerOnce"
private const val NOTIFICATION_CONNECTION_ALERT_ID = 2587 // Same as SubscriberService
fun refresh(context: Context) {
val manager = SubscriberServiceManager(context)

View file

@ -11,7 +11,6 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.Network
import io.heckel.ntfy.util.isNetworkAvailable
import android.os.Build
import android.os.Bundle
import android.provider.Settings
@ -67,6 +66,7 @@ import io.heckel.ntfy.util.displayName
import io.heckel.ntfy.util.formatDateShort
import io.heckel.ntfy.util.isDarkThemeOn
import io.heckel.ntfy.util.isIgnoringBatteryOptimizations
import io.heckel.ntfy.util.isNetworkAvailable
import io.heckel.ntfy.util.maybeSplitTopicUrl
import io.heckel.ntfy.util.randomSubscriptionId
import io.heckel.ntfy.util.shortUrl

View file

@ -10,9 +10,7 @@ import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.provider.Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM
import android.text.TextUtils
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
@ -42,7 +40,6 @@ import kotlinx.coroutines.launch
import okhttp3.RequestBody.Companion.toRequestBody
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
/**
* Main settings
@ -344,11 +341,11 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
when (pref.value.toLongOrNull() ?: repository.getConnectionAlertSeconds()) {
Repository.CONNECTION_ALERT_NEVER -> getString(R.string.settings_advanced_connection_alert_summary_never)
30L -> "Alert after 30 seconds (testing)"
Repository.CONNECTION_ALERT_FIVE_MINUTES -> getString(R.string.settings_advanced_connection_alert_summary_five_minutes)
Repository.CONNECTION_ALERT_FIFTEEN_MINUTES -> getString(R.string.settings_advanced_connection_alert_summary_fifteen_minutes)
Repository.CONNECTION_ALERT_ONE_HOUR -> getString(R.string.settings_advanced_connection_alert_summary_one_hour)
Repository.CONNECTION_ALERT_THREE_HOURS -> getString(R.string.settings_advanced_connection_alert_summary_three_hours)
Repository.CONNECTION_ALERT_TWELVE_HOURS -> getString(R.string.settings_advanced_connection_alert_summary_twelve_hours)
Repository.CONNECTION_ALERT_FIVE_MINUTES_SECONDS -> getString(R.string.settings_advanced_connection_alert_summary_five_minutes)
Repository.CONNECTION_ALERT_FIFTEEN_MINUTES_SECONDS -> getString(R.string.settings_advanced_connection_alert_summary_fifteen_minutes)
Repository.CONNECTION_ALERT_ONE_HOUR_SECONDS -> getString(R.string.settings_advanced_connection_alert_summary_one_hour)
Repository.CONNECTION_ALERT_THREE_HOURS_SECONDS -> getString(R.string.settings_advanced_connection_alert_summary_three_hours)
Repository.CONNECTION_ALERT_TWELVE_HOURS_SECONDS -> getString(R.string.settings_advanced_connection_alert_summary_twelve_hours)
else -> getString(R.string.settings_advanced_connection_alert_summary_never) // Must match default const
}
}

View file

@ -54,13 +54,6 @@ import kotlin.math.abs
import kotlin.math.absoluteValue
import androidx.core.net.toUri
// We check for any active network, not specifically for internet connectivity,
// because the ntfy server may be on a LAN without internet access.
fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return connectivityManager.activeNetwork != null
}
fun topicUrl(baseUrl: String, topic: String) = "${baseUrl}/${topic}"
fun topicUrlUp(baseUrl: String, topic: String) = "${baseUrl}/${topic}?up=1" // UnifiedPush
fun topicUrlJson(baseUrl: String, topic: String, since: String) = "${topicUrl(baseUrl, topic)}/json?since=$since"
@ -554,3 +547,10 @@ fun deriveNotificationId(baseUrl: String, topic: String, sequenceId: String): In
val hash = composite.hashCode()
return if (hash == 0 || hash == Int.MIN_VALUE) 1 else abs(hash)
}
// We check for any active network, not specifically for internet connectivity,
// because the ntfy server may be on a LAN without internet access.
fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return connectivityManager.activeNetwork != null
}

View file

@ -372,19 +372,6 @@
<string name="settings_notifications_auto_delete_one_week">After one week</string>
<string name="settings_notifications_auto_delete_one_month">After one month</string>
<string name="settings_notifications_auto_delete_three_months">After 3 months</string>
<string name="settings_advanced_connection_alert_title">Connection lost alert</string>
<string name="settings_advanced_connection_alert_summary_never">Never alert when connection is lost</string>
<string name="settings_advanced_connection_alert_summary_five_minutes">Alert after 5 minutes without connection</string>
<string name="settings_advanced_connection_alert_summary_fifteen_minutes">Alert after 15 minutes without connection</string>
<string name="settings_advanced_connection_alert_summary_one_hour">Alert after 1 hour without connection</string>
<string name="settings_advanced_connection_alert_summary_three_hours">Alert after 3 hours without connection</string>
<string name="settings_advanced_connection_alert_summary_twelve_hours">Alert after 12 hours without connection</string>
<string name="settings_advanced_connection_alert_never">Never</string>
<string name="settings_advanced_connection_alert_five_minutes">After 5 minutes</string>
<string name="settings_advanced_connection_alert_fifteen_minutes">After 15 minutes</string>
<string name="settings_advanced_connection_alert_one_hour">After 1 hour</string>
<string name="settings_advanced_connection_alert_three_hours">After 3 hours</string>
<string name="settings_advanced_connection_alert_twelve_hours">After 12 hours</string>
<string name="settings_notifications_insistent_max_priority_title">Keep alerting for highest priority</string>
<string name="settings_notifications_insistent_max_priority_summary_enabled">Max priority notifications continuously alert until dismissed</string>
<string name="settings_notifications_insistent_max_priority_summary_disabled">Max priority notifications only alert once</string>
@ -430,6 +417,19 @@
<string name="settings_backup_restore_restore_successful">Restore successful</string>
<string name="settings_backup_restore_restore_failed">Restore failed: %1$s</string>
<string name="settings_advanced_header">Advanced</string>
<string name="settings_advanced_connection_alert_title">Alert when disconnected</string>
<string name="settings_advanced_connection_alert_summary_never">Never notify when the ntfy server cannot be reached</string>
<string name="settings_advanced_connection_alert_summary_five_minutes">Notify if the ntfy server cannot be reached for more than 5 minutes</string>
<string name="settings_advanced_connection_alert_summary_fifteen_minutes">Notify if the ntfy server cannot be reached for more than 15 minutes</string>
<string name="settings_advanced_connection_alert_summary_one_hour">Notify if the ntfy server cannot be reached for more than 1 hour</string>
<string name="settings_advanced_connection_alert_summary_three_hours">Notify if the ntfy server cannot be reached for more than 3 hours</string>
<string name="settings_advanced_connection_alert_summary_twelve_hours">Notify if the ntfy server cannot be reached for more than 12 hours</string>
<string name="settings_advanced_connection_alert_never">Never</string>
<string name="settings_advanced_connection_alert_five_minutes">After 5 minutes</string>
<string name="settings_advanced_connection_alert_fifteen_minutes">After 15 minutes</string>
<string name="settings_advanced_connection_alert_one_hour">After 1 hour</string>
<string name="settings_advanced_connection_alert_three_hours">After 3 hours</string>
<string name="settings_advanced_connection_alert_twelve_hours">After 12 hours</string>
<string name="settings_advanced_broadcast_title">Broadcast messages</string>
<string name="settings_advanced_broadcast_summary_enabled">Apps can receive incoming notifications as broadcasts</string>
<string name="settings_advanced_broadcast_summary_disabled">Apps cannot receive notifications as broadcasts</string>