Merge branch 'main' of github.com:binwiederhier/ntfy-android into disable-up
This commit is contained in:
commit
41912441cd
43 changed files with 723 additions and 104 deletions
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<!-- Permissions -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!-- To check network availability before showing connection alerts -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <!-- For instant delivery foregrounds service -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/> <!-- For instant delivery foregrounds service on SDK >= 34 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/> <!-- To keep foreground service awake; soon not needed anymore -->
|
||||
|
|
@ -131,14 +132,15 @@
|
|||
android:enabled="true"
|
||||
android:exported="false"/>
|
||||
|
||||
<!-- Broadcast receiver for connection alert notification actions (dismiss, snooze, never show again) -->
|
||||
<!-- Broadcast receiver for connection alert notification actions (swipe-dismiss, snooze, never) -->
|
||||
<receiver
|
||||
android:name=".service.SubscriberService$ConnectionAlertBroadcastReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="io.heckel.ntfy.CONNECTION_ALERT_DISMISS"/>
|
||||
<action android:name="io.heckel.ntfy.CONNECTION_ALERT_SNOOZE"/>
|
||||
<action android:name="io.heckel.ntfy.CONNECTION_ALERT_SNOOZE_SHORT"/>
|
||||
<action android:name="io.heckel.ntfy.CONNECTION_ALERT_SNOOZE_LONG"/>
|
||||
<action android:name="io.heckel.ntfy.CONNECTION_ALERT_NEVER"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package io.heckel.ntfy.app
|
||||
|
||||
import android.app.Application
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import io.heckel.ntfy.db.Repository
|
||||
import io.heckel.ntfy.service.SubscriberServiceManager
|
||||
import io.heckel.ntfy.util.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -24,5 +27,18 @@ class Application : Application() {
|
|||
if (repository.getDynamicColorsEnabled()) {
|
||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
}
|
||||
registerNetworkCallback()
|
||||
}
|
||||
|
||||
private fun registerNetworkCallback() {
|
||||
val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
SubscriberServiceManager.refresh(this@Application)
|
||||
}
|
||||
override fun onLost(network: Network) {
|
||||
SubscriberServiceManager.refresh(this@Application)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@ class Backuper(val context: Context) {
|
|||
if (settings.mutedUntil != null) {
|
||||
repository.setGlobalMutedUntil(settings.mutedUntil)
|
||||
}
|
||||
if (settings.connectionAlertSeconds != null) {
|
||||
repository.setConnectionAlertSeconds(settings.connectionAlertSeconds)
|
||||
}
|
||||
if (settings.lastSharedTopics != null) {
|
||||
settings.lastSharedTopics.forEach { repository.addLastShareTopic(it) }
|
||||
}
|
||||
|
|
@ -278,6 +281,7 @@ class Backuper(val context: Context) {
|
|||
recordLogs = repository.getRecordLogs(),
|
||||
defaultBaseUrl = repository.getDefaultBaseUrl() ?: "",
|
||||
mutedUntil = repository.getGlobalMutedUntil(),
|
||||
connectionAlertSeconds = repository.getConnectionAlertSeconds(),
|
||||
lastSharedTopics = repository.getLastShareTopics()
|
||||
)
|
||||
}
|
||||
|
|
@ -421,6 +425,7 @@ data class Settings(
|
|||
val recordLogs: Boolean?,
|
||||
val defaultBaseUrl: String?,
|
||||
val mutedUntil: Long?,
|
||||
val connectionAlertSeconds: Long?,
|
||||
val lastSharedTopics: List<String>?,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -575,6 +575,9 @@ interface SubscriptionDao {
|
|||
""")
|
||||
fun getLastNotificationId(subscriptionIds: Collection<Long>): String?
|
||||
|
||||
@Query("UPDATE subscription SET icon = :icon WHERE id = :subscriptionId")
|
||||
fun updateSubscriptionIcon(subscriptionId: Long, icon: String?)
|
||||
|
||||
@Query("DELETE FROM subscription WHERE id = :subscriptionId")
|
||||
fun remove(subscriptionId: Long)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,10 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
|
|||
subscriptionDao.update(subscription)
|
||||
}
|
||||
|
||||
fun updateSubscriptionIcon(subscriptionId: Long, icon: String?) {
|
||||
subscriptionDao.updateSubscriptionIcon(subscriptionId, icon)
|
||||
}
|
||||
|
||||
@Suppress("RedundantSuspendModifier")
|
||||
@WorkerThread
|
||||
suspend fun removeSubscription(subscription: Subscription) {
|
||||
|
|
@ -440,13 +444,24 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
|
|||
}
|
||||
}
|
||||
|
||||
fun getConnectionAlertSnoozeUntil(): Long {
|
||||
return sharedPrefs.getLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL, CONNECTION_ALERT_SNOOZE_UNTIL_DEFAULT)
|
||||
fun getConnectionAlertSeconds(): Long {
|
||||
return sharedPrefs.getLong(SHARED_PREFS_CONNECTION_ALERT_SECONDS, CONNECTION_ALERT_DEFAULT)
|
||||
}
|
||||
|
||||
fun setConnectionAlertSnoozeUntil(timeMillis: Long) {
|
||||
fun setConnectionAlertSeconds(seconds: Long) {
|
||||
sharedPrefs.edit {
|
||||
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL, timeMillis)
|
||||
putLong(SHARED_PREFS_CONNECTION_ALERT_SECONDS, seconds)
|
||||
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME, 0L)
|
||||
}
|
||||
}
|
||||
|
||||
fun getConnectionAlertSnoozeUntilTime(): Long {
|
||||
return sharedPrefs.getLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME, 0L)
|
||||
}
|
||||
|
||||
fun setConnectionAlertSnoozeUntilTime(timeMillis: Long) {
|
||||
sharedPrefs.edit {
|
||||
putLong(SHARED_PREFS_CONNECTION_ALERT_SNOOZE_UNTIL_TIME, timeMillis)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -608,6 +623,11 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
|
|||
return connectionDetails.toMap()
|
||||
}
|
||||
|
||||
fun clearConnectionDetails() {
|
||||
connectionDetails.clear()
|
||||
connectionDetailsLiveData.postValue(emptyMap())
|
||||
}
|
||||
|
||||
fun getConnectionForceReconnectVersion(baseUrl: String): Long {
|
||||
return connectionForceReconnectVersions[baseUrl] ?: 0L
|
||||
}
|
||||
|
|
@ -634,14 +654,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_SNOOZE_UNTIL = "ConnectionAlertSnoozeUntil"
|
||||
const val CONNECTION_ALERT_SNOOZE_UNTIL_DEFAULT = 0L
|
||||
const val CONNECTION_ALERT_NEVER_SHOW = Long.MAX_VALUE
|
||||
const val SHARED_PREFS_CONNECTION_ALERT_SECONDS = "ConnectionAlertSeconds"
|
||||
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
|
||||
|
|
@ -653,12 +672,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
|
||||
|
|
@ -671,6 +692,14 @@ class Repository(private val sharedPrefs: SharedPreferences, database: Database)
|
|||
const val INSISTENT_MAX_PRIORITY_USE_GLOBAL = -1 // Values must match values.xml
|
||||
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_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"
|
||||
const val CONNECTION_PROTOCOL_WS = "ws"
|
||||
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ import io.heckel.ntfy.db.Repository
|
|||
import io.heckel.ntfy.db.Subscription
|
||||
import io.heckel.ntfy.msg.ApiService
|
||||
import io.heckel.ntfy.msg.NotificationDispatcher
|
||||
import io.heckel.ntfy.msg.NotificationService
|
||||
import io.heckel.ntfy.util.PRIORITY_HIGH
|
||||
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
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
|
|
@ -316,22 +316,28 @@ class SubscriberService : Service() {
|
|||
}
|
||||
|
||||
private fun maybeShowConnectionAlert() {
|
||||
val now = System.currentTimeMillis()
|
||||
val thresholdSeconds = repository.getConnectionAlertSeconds()
|
||||
if (thresholdSeconds <= 0L) return
|
||||
|
||||
// Check snooze / never-show-again
|
||||
val snoozeUntil = repository.getConnectionAlertSnoozeUntil()
|
||||
if (snoozeUntil == Repository.CONNECTION_ALERT_NEVER_SHOW) return
|
||||
// Don't show alert if the device has no network connectivity (e.g. airplane mode)
|
||||
if (!isNetworkAvailable(this)) return
|
||||
|
||||
// Check snooze
|
||||
val now = System.currentTimeMillis()
|
||||
val snoozeUntil = repository.getConnectionAlertSnoozeUntilTime()
|
||||
if (snoozeUntil > now) return
|
||||
|
||||
// Check if any connection has been in error for 15+ minutes
|
||||
// Check if any connection has been in error for longer than the threshold
|
||||
val thresholdMillis = thresholdSeconds * 1000L
|
||||
val allDetails = repository.getConnectionDetails()
|
||||
val disconnectedUrls = allDetails.filter { (_, details) ->
|
||||
details.hasError() && details.firstErrorTime > 0L &&
|
||||
(now - details.firstErrorTime) >= CONNECTION_ALERT_THRESHOLD_MILLIS
|
||||
(now - details.firstErrorTime) >= thresholdMillis
|
||||
}.keys
|
||||
|
||||
if (disconnectedUrls.isNotEmpty()) {
|
||||
showConnectionAlertNotification(disconnectedUrls)
|
||||
val thresholdMinutes = (thresholdSeconds / 60).toInt()
|
||||
showConnectionAlertNotification(disconnectedUrls, thresholdMinutes)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,47 +351,40 @@ class SubscriberService : Service() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun showConnectionAlertNotification(disconnectedUrls: Set<String>) {
|
||||
private fun showConnectionAlertNotification(disconnectedUrls: Set<String>, thresholdMinutes: Int) {
|
||||
val text = if (disconnectedUrls.size == 1) {
|
||||
getString(R.string.connection_alert_text_one, disconnectedUrls.first(), CONNECTION_ALERT_THRESHOLD_MINUTES)
|
||||
getString(R.string.connection_alert_text_one, shortUrl(disconnectedUrls.first()), thresholdMinutes)
|
||||
} else {
|
||||
getString(R.string.connection_alert_text_multiple, disconnectedUrls.size, CONNECTION_ALERT_THRESHOLD_MINUTES)
|
||||
getString(R.string.connection_alert_text_multiple, disconnectedUrls.size, thresholdMinutes)
|
||||
}
|
||||
|
||||
val dismissIntent = Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply {
|
||||
action = CONNECTION_ALERT_ACTION_DISMISS
|
||||
}
|
||||
val dismissPendingIntent = PendingIntent.getBroadcast(this, 0, dismissIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
|
||||
val snoozeIntent = Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply {
|
||||
action = CONNECTION_ALERT_ACTION_SNOOZE
|
||||
}
|
||||
val snoozePendingIntent = PendingIntent.getBroadcast(this, 1, snoozeIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
|
||||
val neverIntent = Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply {
|
||||
action = CONNECTION_ALERT_ACTION_NEVER
|
||||
}
|
||||
val neverPendingIntent = PendingIntent.getBroadcast(this, 2, neverIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
|
||||
val contentIntent = PendingIntent.getActivity(this, 0,
|
||||
Intent(this, MainActivity::class.java), PendingIntent.FLAG_IMMUTABLE)
|
||||
val snoozeShortIntent = PendingIntent.getBroadcast(this, 0,
|
||||
Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply { action = CONNECTION_ALERT_ACTION_SNOOZE_SHORT },
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
val snoozeIntent = PendingIntent.getBroadcast(this, 0,
|
||||
Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply { action = CONNECTION_ALERT_ACTION_SNOOZE_LONG },
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
val neverAlertIntent = PendingIntent.getBroadcast(this, 0,
|
||||
Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply { action = CONNECTION_ALERT_ACTION_NEVER },
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
val deleteIntent = PendingIntent.getBroadcast(this, 0,
|
||||
Intent(this, ConnectionAlertBroadcastReceiver::class.java).apply { action = CONNECTION_ALERT_ACTION_DISMISS },
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
|
||||
val channelId = NotificationService(this).toChannelId(NotificationService.DEFAULT_GROUP, PRIORITY_HIGH)
|
||||
val notification = NotificationCompat.Builder(this, channelId)
|
||||
val notification = NotificationCompat.Builder(this, NOTIFICATION_CONNECTION_ALERT_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setColor(Colors.notificationIcon(this))
|
||||
.setContentTitle(getString(R.string.connection_alert_title))
|
||||
.setContentText(text)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText(text))
|
||||
.setContentIntent(contentIntent)
|
||||
.setAutoCancel(true)
|
||||
.setOnlyAlertOnce(true)
|
||||
.addAction(NotificationCompat.Action.Builder(0, getString(R.string.connection_alert_action_dismiss), dismissPendingIntent).build())
|
||||
.addAction(NotificationCompat.Action.Builder(0, getString(R.string.connection_alert_action_snooze), snoozePendingIntent).build())
|
||||
.addAction(NotificationCompat.Action.Builder(0, getString(R.string.connection_alert_action_never), neverPendingIntent).build())
|
||||
.setDeleteIntent(deleteIntent)
|
||||
.addAction(NotificationCompat.Action.Builder(0, getString(R.string.connection_alert_action_snooze, CONNECTION_ALERT_SNOOZE_SHORT_HOURS), snoozeShortIntent).build())
|
||||
.addAction(NotificationCompat.Action.Builder(0, getString(R.string.connection_alert_action_snooze, CONNECTION_ALERT_SNOOZE_LONG_HOURS), snoozeIntent).build())
|
||||
.addAction(NotificationCompat.Action.Builder(0, getString(R.string.connection_alert_action_never), neverAlertIntent).build())
|
||||
.build()
|
||||
|
||||
Log.d(TAG, "Showing connection alert notification")
|
||||
|
|
@ -440,6 +439,9 @@ class SubscriberService : Service() {
|
|||
it
|
||||
}
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
val connectionAlertChannelName = getString(R.string.channel_connection_alert_name)
|
||||
val connectionAlertChannel = NotificationChannel(NOTIFICATION_CONNECTION_ALERT_CHANNEL_ID, connectionAlertChannelName, NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager.createNotificationChannel(connectionAlertChannel)
|
||||
return notificationManager
|
||||
}
|
||||
|
||||
|
|
@ -500,22 +502,19 @@ class SubscriberService : Service() {
|
|||
Log.d(TAG, "ConnectionAlertBroadcastReceiver: action=${intent.action}")
|
||||
val repository = Repository.getInstance(context)
|
||||
val notificationManager = context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
when (intent.action) {
|
||||
CONNECTION_ALERT_ACTION_DISMISS -> {
|
||||
notificationManager.cancel(NOTIFICATION_CONNECTION_ALERT_ID)
|
||||
CONNECTION_ALERT_ACTION_DISMISS, CONNECTION_ALERT_ACTION_SNOOZE_SHORT -> {
|
||||
repository.setConnectionAlertSnoozeUntilTime(System.currentTimeMillis() + CONNECTION_ALERT_SNOOZE_SHORT_MILLIS)
|
||||
}
|
||||
CONNECTION_ALERT_ACTION_SNOOZE -> {
|
||||
repository.setConnectionAlertSnoozeUntil(
|
||||
System.currentTimeMillis() + CONNECTION_ALERT_SNOOZE_DURATION_MILLIS
|
||||
)
|
||||
notificationManager.cancel(NOTIFICATION_CONNECTION_ALERT_ID)
|
||||
CONNECTION_ALERT_ACTION_SNOOZE_LONG -> {
|
||||
repository.setConnectionAlertSnoozeUntilTime(System.currentTimeMillis() + CONNECTION_ALERT_SNOOZE_LONG_MILLIS)
|
||||
}
|
||||
CONNECTION_ALERT_ACTION_NEVER -> {
|
||||
repository.setConnectionAlertSnoozeUntil(Repository.CONNECTION_ALERT_NEVER_SHOW)
|
||||
notificationManager.cancel(NOTIFICATION_CONNECTION_ALERT_ID)
|
||||
repository.setConnectionAlertSeconds(Repository.CONNECTION_ALERT_NEVER)
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
notificationManager.cancel(NOTIFICATION_CONNECTION_ALERT_ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -529,18 +528,24 @@ 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"
|
||||
private const val NOTIFICATION_GROUP_ID = "io.heckel.ntfy.NOTIFICATION_GROUP_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
|
||||
private const val CONNECTION_ALERT_THRESHOLD_MINUTES = 15
|
||||
private const val CONNECTION_ALERT_THRESHOLD_MILLIS = CONNECTION_ALERT_THRESHOLD_MINUTES * 60 * 1000L
|
||||
private const val CONNECTION_ALERT_SNOOZE_DURATION_MILLIS = 60 * 60 * 1000L /*1 hour*/
|
||||
const val NOTIFICATION_CONNECTION_ALERT_ID = 2587
|
||||
private const val CONNECTION_ALERT_SNOOZE_SHORT_HOURS = 1
|
||||
private const val CONNECTION_ALERT_SNOOZE_SHORT_MILLIS = CONNECTION_ALERT_SNOOZE_SHORT_HOURS * ONE_HOUR_MILLIS
|
||||
private const val CONNECTION_ALERT_SNOOZE_LONG_HOURS = 8
|
||||
private const val CONNECTION_ALERT_SNOOZE_LONG_MILLIS = CONNECTION_ALERT_SNOOZE_LONG_HOURS * 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_SNOOZE_SHORT = "io.heckel.ntfy.CONNECTION_ALERT_SNOOZE_SHORT"
|
||||
private const val CONNECTION_ALERT_ACTION_SNOOZE_LONG = "io.heckel.ntfy.CONNECTION_ALERT_SNOOZE_LONG"
|
||||
private const val CONNECTION_ALERT_ACTION_NEVER = "io.heckel.ntfy.CONNECTION_ALERT_NEVER"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
package io.heckel.ntfy.service
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
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
|
||||
|
||||
|
|
@ -40,8 +42,9 @@ class SubscriberServiceManager(private val context: Context) {
|
|||
withContext(Dispatchers.IO) {
|
||||
val app = context.applicationContext as Application
|
||||
val subscriptionIdsWithInstantStatus = app.repository.getSubscriptionIdsWithInstantStatus()
|
||||
val hasNetwork = isNetworkAvailable(context)
|
||||
val instantSubscriptions = subscriptionIdsWithInstantStatus.toList().filter { (_, instant) -> instant }.size
|
||||
if (instantSubscriptions > 0) {
|
||||
if (instantSubscriptions > 0 && hasNetwork) {
|
||||
// We have instant subscriptions, start the service
|
||||
Log.d(TAG, "ServiceStartWorker: Starting foreground service (work ID: ${id})")
|
||||
Intent(context, SubscriberService::class.java).also {
|
||||
|
|
@ -56,9 +59,14 @@ class SubscriberServiceManager(private val context: Context) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// No instant subscriptions, stop the service using stopService()
|
||||
// No instant subscriptions (or no network), stop the service using stopService()
|
||||
// This avoids ForegroundServiceDidNotStartInTimeException, see #1520
|
||||
Log.d(TAG, "ServiceStartWorker: Stopping service (work ID: ${id})")
|
||||
if (!hasNetwork) {
|
||||
app.repository.clearConnectionDetails()
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.cancel(SubscriberService.NOTIFICATION_CONNECTION_ALERT_ID)
|
||||
}
|
||||
Intent(context, SubscriberService::class.java).also {
|
||||
context.stopService(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
|||
messageView.autoLinkMask = 0
|
||||
markwon.setMarkdown(messageView, message.toString())
|
||||
} else {
|
||||
messageView.autoLinkMask = Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES or Linkify.PHONE_NUMBERS
|
||||
messageView.autoLinkMask = Linkify.WEB_URLS
|
||||
messageView.text = message
|
||||
}
|
||||
messageView.movementMethod = BetterLinkMovementMethod.getInstance()
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ class DetailSettingsActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun createUri(): Uri? {
|
||||
val dir = File(requireContext().cacheDir, SUBSCRIPTION_ICONS)
|
||||
val dir = File(requireContext().filesDir, SUBSCRIPTION_ICONS)
|
||||
if (!dir.exists() && !dir.mkdirs()) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -526,7 +526,6 @@ class DetailSettingsActivity : AppCompatActivity() {
|
|||
|
||||
companion object {
|
||||
private const val TAG = "NtfyDetailSettingsActiv"
|
||||
private const val SUBSCRIPTION_ICONS = "subscriptionIcons"
|
||||
private const val SUBSCRIPTION_ICON_MAX_SIZE_BYTES = 4194304
|
||||
private const val SUBSCRIPTION_ICON_MAX_WIDTH = 2048
|
||||
private const val SUBSCRIPTION_ICON_MAX_HEIGHT = 2048
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ import android.animation.AnimatorListenerAdapter
|
|||
import android.app.AlarmManager
|
||||
import android.app.AlertDialog
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
|
|
@ -58,11 +61,13 @@ import io.heckel.ntfy.msg.Poller
|
|||
import io.heckel.ntfy.service.SubscriberService
|
||||
import io.heckel.ntfy.service.SubscriberServiceManager
|
||||
import io.heckel.ntfy.util.Log
|
||||
import io.heckel.ntfy.util.SUBSCRIPTION_ICONS
|
||||
import io.heckel.ntfy.util.dangerButton
|
||||
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
|
||||
|
|
@ -72,8 +77,10 @@ import io.heckel.ntfy.work.PollWorker
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.view.size
|
||||
import androidx.core.view.get
|
||||
import androidx.core.net.toUri
|
||||
|
|
@ -95,6 +102,7 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
private lateinit var fab: FloatingActionButton
|
||||
|
||||
// Other stuff
|
||||
private var networkCallback: ConnectivityManager.NetworkCallback? = null
|
||||
private var workManager: WorkManager? = null // Context-dependent
|
||||
private var dispatcher: NotificationDispatcher? = null // Context-dependent
|
||||
private var appBaseUrl: String? = null // Context-dependent
|
||||
|
|
@ -342,6 +350,19 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
}
|
||||
}
|
||||
|
||||
// Network state banner
|
||||
showHideNoNetworkBanner()
|
||||
val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
networkCallback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
runOnUiThread { showHideNoNetworkBanner() }
|
||||
}
|
||||
override fun onLost(network: Network) {
|
||||
runOnUiThread { showHideNoNetworkBanner() }
|
||||
}
|
||||
}
|
||||
connectivityManager.registerDefaultNetworkCallback(networkCallback!!)
|
||||
|
||||
// Hide links that lead to payments, see https://github.com/binwiederhier/ntfy/issues/1463
|
||||
val howToLink = findViewById<TextView>(R.id.main_how_to_link)
|
||||
howToLink.isVisible = BuildConfig.PAYMENT_LINKS_AVAILABLE
|
||||
|
|
@ -362,6 +383,9 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
|
||||
// Permissions
|
||||
maybeRequestNotificationPermission()
|
||||
|
||||
// FIXME 2026-05-04: Remove this migration after 1 month
|
||||
migrateSubscriptionIconsFromCache()
|
||||
}
|
||||
|
||||
private fun maybeRequestNotificationPermission() {
|
||||
|
|
@ -377,6 +401,7 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
super.onResume()
|
||||
showHideNotificationMenuItems()
|
||||
showHideConnectionErrorMenuItem(repository.getConnectionDetails())
|
||||
showHideNoNetworkBanner()
|
||||
redrawList()
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +450,22 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
}
|
||||
}
|
||||
|
||||
private fun showHideNoNetworkBanner() {
|
||||
val banner = findViewById<View>(R.id.main_banner_no_network)
|
||||
banner.visibility = if (isNetworkAvailable(this)) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
try {
|
||||
val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
networkCallback?.let { connectivityManager.unregisterNetworkCallback(it) }
|
||||
} catch (e: Exception) {
|
||||
Log.d(TAG, "Failed to unregister network callback: ${e.message}")
|
||||
}
|
||||
networkCallback = null
|
||||
}
|
||||
|
||||
private fun schedulePeriodicPollWorker() {
|
||||
val workerVersion = repository.getPollWorkerVersion()
|
||||
val workPolicy = if (workerVersion == PollWorker.VERSION) {
|
||||
|
|
@ -859,6 +900,38 @@ class MainActivity : AppCompatActivity(), AddFragment.SubscribeListener, Notific
|
|||
adapter.notifyItemRangeChanged(0, adapter.currentList.size)
|
||||
}
|
||||
|
||||
// FIXME 2026-05-04: Remove this migration after 1 month
|
||||
private fun migrateSubscriptionIconsFromCache() {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
delay(5_000) // 5 seconds
|
||||
try {
|
||||
val oldDir = File(cacheDir, SUBSCRIPTION_ICONS)
|
||||
if (!oldDir.exists() || !oldDir.isDirectory) return@launch
|
||||
val newDir = File(filesDir, SUBSCRIPTION_ICONS)
|
||||
if (!newDir.exists()) newDir.mkdirs()
|
||||
oldDir.listFiles()?.forEach { oldFile ->
|
||||
val newFile = File(newDir, oldFile.name)
|
||||
if (newFile.exists()) {
|
||||
oldFile.delete()
|
||||
return@forEach
|
||||
}
|
||||
if (oldFile.renameTo(newFile)) {
|
||||
val subscriptionId = oldFile.name.toLongOrNull() ?: return@forEach
|
||||
val newUri = FileProvider.getUriForFile(
|
||||
this@MainActivity,
|
||||
BuildConfig.APPLICATION_ID + ".provider",
|
||||
newFile
|
||||
)
|
||||
repository.updateSubscriptionIcon(subscriptionId, newUri.toString())
|
||||
}
|
||||
}
|
||||
oldDir.delete()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed to migrate subscription icons", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "NtfyMainActivity"
|
||||
const val EXTRA_SUBSCRIPTION_ID = "subscriptionId"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -43,7 +41,6 @@ import kotlinx.coroutines.launch
|
|||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Main settings
|
||||
|
|
@ -328,6 +325,31 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
|||
}
|
||||
}
|
||||
|
||||
// Connection alert
|
||||
val connectionAlertPrefId = context?.getString(R.string.settings_advanced_connection_alert_key) ?: return
|
||||
val connectionAlert: ListPreference? = findPreference(connectionAlertPrefId)
|
||||
connectionAlert?.value = repository.getConnectionAlertSeconds().toString()
|
||||
connectionAlert?.preferenceDataStore = object : PreferenceDataStore() {
|
||||
override fun putString(key: String?, value: String?) {
|
||||
val seconds = value?.toLongOrNull() ?:return
|
||||
repository.setConnectionAlertSeconds(seconds)
|
||||
}
|
||||
override fun getString(key: String?, defValue: String?): String {
|
||||
return repository.getConnectionAlertSeconds().toString()
|
||||
}
|
||||
}
|
||||
connectionAlert?.summaryProvider = Preference.SummaryProvider<ListPreference> { pref ->
|
||||
when (pref.value.toLongOrNull() ?: repository.getConnectionAlertSeconds()) {
|
||||
Repository.CONNECTION_ALERT_NEVER -> getString(R.string.settings_advanced_connection_alert_summary_never)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode
|
||||
val darkModePrefId = context?.getString(R.string.settings_general_dark_mode_key) ?: return
|
||||
val darkMode: ListPreference? = findPreference(darkModePrefId)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package io.heckel.ntfy.util
|
||||
|
||||
const val ANDROID_APP_MIME_TYPE = "application/vnd.android.package-archive"
|
||||
const val SUBSCRIPTION_ICONS = "subscriptionIcons"
|
||||
|
||||
const val PRIORITY_MIN = 1
|
||||
const val PRIORITY_LOW = 2
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import android.content.res.Resources
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.RippleDrawable
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
|
|
@ -546,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
|
||||
}
|
||||
9
app/src/main/res/drawable/ic_wifi_off_gray_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_wifi_off_gray_24dp.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M22.99,9C19.15,5.16 13.8,3.76 8.84,4.78l2.52,2.52c3.47,-0.17 6.99,1.05 9.63,3.7l2,-2zM18.99,13c-1.29,-1.29 -2.84,-2.13 -4.49,-2.56l3.53,3.53 0.96,-0.97zM2,3.05L5.07,6.1C3.6,6.82 2.22,7.78 1,9l2,2c1.02,-1.02 2.17,-1.78 3.38,-2.31L9.03,11.34c-1.14,0.4 -2.2,1.05 -3.04,1.95l2,2c0.73,-0.73 1.63,-1.19 2.58,-1.4l3.32,3.32L12.01,21l2,-2 -0.76,-0.76 4.78,4.78 1.41,-1.41L3.41,1.64 2,3.05z"
|
||||
android:fillColor="#757575"/>
|
||||
</vector>
|
||||
|
|
@ -232,6 +232,28 @@
|
|||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/main_banner_no_network"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurfaceVariant"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/main_banner_websocket_reconnect">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/main_banner_no_network_text"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:textColor="?attr/colorOnSurfaceVariant"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:drawableStart="@drawable/ic_wifi_off_gray_24dp"
|
||||
android:drawablePadding="4dp" />
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/main_subscriptions_list_container"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -239,7 +261,7 @@
|
|||
android:visibility="visible"
|
||||
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/main_banner_websocket_reconnect">
|
||||
app:layout_constraintTop_toBottomOf="@id/main_banner_no_network">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/main_subscriptions_list"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
android:id="@+id/detail_item_message_text"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:autoLink="web|phone|email"
|
||||
android:autoLink="web"
|
||||
app:layout_constraintTop_toBottomOf="@id/detail_item_title_text"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="12dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/detail_item_attachment_image" app:layout_constraintEnd_toStartOf="@id/detail_item_icon" android:layout_marginEnd="6dp"/>
|
||||
|
|
|
|||
|
|
@ -33,4 +33,4 @@
|
|||
<string name="settings_about_version_title">Weergawe</string>
|
||||
<string name="settings_advanced_connection_protocol_entry_ws">WebSockets</string>
|
||||
<string name="settings_advanced_export_logs_entry_copy_scrubbed">Kopieer na knipbord (gesensuur)</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -471,4 +471,9 @@
|
|||
<string name="detail_menu_search_hint">Търсене в известията</string>
|
||||
<string name="common_button_reset_to_default">Подразбирани настройки</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Въведете адрес на услуга, напр. https://ntfy.example.com</string>
|
||||
<string name="connection_alert_title">Връзката е загубена</string>
|
||||
<string name="connection_alert_text_one">От най-малко %2$d минути няма връзка с %1$s</string>
|
||||
<string name="connection_alert_text_multiple">От най-малко %2$d минути няма връзка със сървърите на %1$d</string>
|
||||
<string name="connection_alert_action_snooze">Отлагане с %1$dч</string>
|
||||
<string name="connection_alert_action_never">Да не се показва повече</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@
|
|||
<string name="add_dialog_base_urls_dropdown_clear">Esborra URL de servei</string>
|
||||
<string name="detail_no_notifications_text">Encara no has rebut cap notificació en aquest tema.</string>
|
||||
<string name="detail_how_to_intro">Per enviar notificacions en aquest tema, fes PUT o POST a la URL del tema.</string>
|
||||
<string name="detail_how_to_example">Exemple (usant curl):<br></br><tt>$ curl -d \"Hola\" %1$s</tt></string>
|
||||
<string name="detail_how_to_example">Exemple (usant curl):<br/><tt>$ curl -d \"Hola\" %1$s</tt></string>
|
||||
<string name="main_unified_push_toast">Aquesta subscripció és gestionada per %1$s via UnifiedPush</string>
|
||||
<string name="main_how_to_link">Instruccions detallades disponibles a ntfy.sh i a la documentació.</string>
|
||||
<string name="main_banner_websocket_text">WebSockets és el mètode recomanat per connectar-te al teu servidor. Pot millorar el rendiment de la bateria, però pot requerir <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">configuració addicional al teu proxy</a>. Aquesta opció pot ser habil·litada a Configuració.</string>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<string name="common_priority_default_name">Standard-Priorität</string>
|
||||
<string name="common_priority_high_name">Hohe Priorität</string>
|
||||
<string name="common_priority_max_name">Höchste Priorität</string>
|
||||
<string name="channel_subscriber_service_name">Abo Service</string>
|
||||
<string name="channel_subscriber_service_name">Hintergrunddienst</string>
|
||||
<string name="common_priority_min_name">Niedrigste Priorität</string>
|
||||
<string name="channel_subscriber_notification_title">Warte auf eingehende Benachrichtigungen</string>
|
||||
<string name="channel_subscriber_notification_instant_text_one">Ein Sofortnachrichten-Thema abonniert</string>
|
||||
|
|
@ -471,4 +471,24 @@
|
|||
<string name="detail_menu_search_hint">In Benachrichtigungen suchen</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Eine gültige Service-URL eingeben, z. B. https://ntfy.example.com</string>
|
||||
<string name="detail_menu_search">Benachrichtigungen suchen</string>
|
||||
<string name="connection_alert_title">Verbindung verloren</string>
|
||||
<string name="connection_alert_text_one">Es konnte länger als %2$d Minuten lang keine Verbindung zu %1$s hergestellt werden. Prüfe deine Netzwerkverbindung.</string>
|
||||
<string name="connection_alert_text_multiple">Es konnte länger als %2$d Minuten lang keine Verbindung zu %1$d Servern hergestellt werden. Prüfe deine Netzwerkverbindung.</string>
|
||||
<string name="connection_alert_action_snooze">%1$d Std. schlummern</string>
|
||||
<string name="connection_alert_action_never">Niemals zeigen</string>
|
||||
<string name="channel_connection_alert_name">Verbindungswarnungen</string>
|
||||
<string name="main_banner_no_network_text">Du bist offline</string>
|
||||
<string name="settings_advanced_connection_alert_title">Warnung, wenn die Verbindung getrennt wird</string>
|
||||
<string name="settings_advanced_connection_alert_summary_never">Niemals benachrichtigen, wenn der ntfy-Server nicht erreichbar ist</string>
|
||||
<string name="settings_advanced_connection_alert_summary_five_minutes">Benachrichtigen, wenn der ntfy-Server länger als 5 Minuten nicht erreichbar ist</string>
|
||||
<string name="settings_advanced_connection_alert_summary_fifteen_minutes">Benachrichtigen, wenn der ntfy-Server länger als 15 Minuten nicht erreichbar ist</string>
|
||||
<string name="settings_advanced_connection_alert_summary_one_hour">Benachrichtige, wenn der ntfy-Server länger als 1 Stunde nicht erreichbar ist</string>
|
||||
<string name="settings_advanced_connection_alert_summary_three_hours">Benachrichtigen, wenn der ntfy-Server länger als 3 Stunden nicht erreichbar ist</string>
|
||||
<string name="settings_advanced_connection_alert_summary_twelve_hours">Benachrichtigen, wenn der ntfy-Server länger als 12 Stunden nicht erreichbar ist</string>
|
||||
<string name="settings_advanced_connection_alert_never">Niemals</string>
|
||||
<string name="settings_advanced_connection_alert_five_minutes">Nach 5 Minuten</string>
|
||||
<string name="settings_advanced_connection_alert_fifteen_minutes">Nach 15 Minuten</string>
|
||||
<string name="settings_advanced_connection_alert_one_hour">Nach 1 Stunde</string>
|
||||
<string name="settings_advanced_connection_alert_three_hours">Nach 3 Stunden</string>
|
||||
<string name="settings_advanced_connection_alert_twelve_hours">Nach 12 Stunden</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -80,4 +80,4 @@
|
|||
<string name="add_dialog_login_description">Αυτό το θέμα απαιτεί να συνδεθείτε. Παρακαλώ πληκτρολογήστε ένα όνομα χρήστη και έναν κωδικό πρόσβασης.</string>
|
||||
<string name="main_banner_websocket_button_dismiss">Απορρίψτε το</string>
|
||||
<string name="add_dialog_button_back">Πίσω</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@
|
|||
<string name="settings_notifications_auto_download_summary_smaller_than_x">Descargar automáticamente archivos adjuntos de hasta %1$s</string>
|
||||
<string name="settings_notifications_auto_download_never">Nunca descargar nada automáticamente</string>
|
||||
<string name="settings_notifications_auto_download_always">Siempre descargar todo automáticamente</string>
|
||||
<string name="settings_notifications_auto_download_100k">Si es más pequeño que 100 KB</string>
|
||||
<string name="settings_notifications_auto_download_500k">Si es más pequeño que 500 KB</string>
|
||||
<string name="settings_notifications_auto_download_100k">Si es inferior a 100 kB</string>
|
||||
<string name="settings_notifications_auto_download_500k">Si es inferior a 500 kB</string>
|
||||
<string name="settings_notifications_auto_download_5m">Si es más pequeño que 5 MB</string>
|
||||
<string name="settings_notifications_auto_delete_title">Eliminar notificaciones</string>
|
||||
<string name="settings_notifications_auto_delete_summary_never">Nunca eliminar automáticamente las notificaciones</string>
|
||||
|
|
@ -342,11 +342,11 @@
|
|||
<string name="main_banner_websocket_reconnect_button_dismiss">Descartar</string>
|
||||
<string name="main_banner_websocket_reconnect_button_enable_now">Conceder ahora</string>
|
||||
<string name="settings_advanced_exact_alarms_title">Alarmas exactas</string>
|
||||
<string name="settings_advanced_exact_alarms_true">ntfy puede programar alarmas exactas (utilizadas para reconectar WebSockets en segundo plano)</string>
|
||||
<string name="settings_advanced_exact_alarms_false">ntfy no puede programar alarmas exactas. Haga clic para conceder el permiso ahora</string>
|
||||
<string name="settings_advanced_exact_alarms_true">ntfy puede programar alarmas exactas. Las alarmas exactas son requeridas para reconectar WebSockets en segundo plano. Haga clic para revocar este permiso.</string>
|
||||
<string name="settings_advanced_exact_alarms_false">ntfy no puede programar alarmas exactas. Las alarmas exactas son requeridas para reconectar WebSockets en segundo plano. Haga clic para conceder el permiso.</string>
|
||||
<string name="publish_dialog_title">Publicar a %1$s</string>
|
||||
<string name="publish_dialog_title_hint">Título</string>
|
||||
<string name="publish_dialog_title_placeholder">p.e. Alguien está en la puerta</string>
|
||||
<string name="publish_dialog_title_placeholder">ej. Alguien está en la puerta</string>
|
||||
<string name="publish_dialog_message_hint">Mensaje</string>
|
||||
<string name="publish_dialog_tags_hint">Etiquetas</string>
|
||||
<string name="publish_dialog_priority_hint">Prioridad</string>
|
||||
|
|
@ -407,6 +407,73 @@
|
|||
<string name="settings_advanced_certificates_summary">Añadir certificados a la lista de confiados y administrar certificados de cliente para mTLS</string>
|
||||
<string name="settings_advanced_certificates_trusted_header">Certificados confiados</string>
|
||||
<string name="common_service_url_placeholder">ej. https://ntfy.example.com</string>
|
||||
<string name="common_certificate_subject">Subject</string>
|
||||
<string name="common_certificate_subject">Asunto</string>
|
||||
<string name="main_menu_connection_error">Error de conexión</string>
|
||||
<string name="common_button_reset_to_default">Restaurar valores por defecto</string>
|
||||
<string name="connection_alert_title">Conexión perdida</string>
|
||||
<string name="connection_alert_text_one">No se pudo conectar a %1$s por más de %2$d minutos</string>
|
||||
<string name="connection_alert_text_multiple">No se pudo conectar a %1$d servidores por más de %2$d minutos</string>
|
||||
<string name="connection_alert_action_snooze">Suspender %1$dh</string>
|
||||
<string name="connection_alert_action_never">Nunca mostrar</string>
|
||||
<string name="detail_no_search_results">Su búsqueda no tuvo ningún resultado</string>
|
||||
<string name="detail_menu_search">Buscar notificaciones</string>
|
||||
<string name="detail_menu_search_hint">Buscar en notificaciones</string>
|
||||
<string name="publish_dialog_tags_placeholder">ej. alerta, peligro</string>
|
||||
<string name="publish_dialog_chip_email">Email</string>
|
||||
<string name="publish_dialog_chip_markdown">Markdown</string>
|
||||
<string name="publish_dialog_email_hint">Email</string>
|
||||
<string name="publish_dialog_email_placeholder">ej. phil@example.com</string>
|
||||
<string name="publish_dialog_delay_placeholder">ej. 30m, 1h, today 9pm (Siempre en inglés)</string>
|
||||
<string name="publish_dialog_attach_url_placeholder">ej. https://example.com/flowers.jpg</string>
|
||||
<string name="publish_dialog_attach_filename_placeholder">ej. ilies.jpg</string>
|
||||
<string name="publish_dialog_phone_call_placeholder">ej. +1234567890</string>
|
||||
<string name="connection_error_dialog_title">Error de conexión</string>
|
||||
<string name="connection_error_dialog_message">Hubo un problema al conectar a %1$s. La aplicación continuará intentando reconectar en segundo plano.</string>
|
||||
<string name="connection_error_dialog_connection_refused">Conexión rechazada. Puede que el servidor esté desconectado o la dirección sea incorrecta.</string>
|
||||
<string name="connection_error_dialog_websocket_not_supported">WebSocket no soportado. Puede que el servidor no soporte conexiones WebSocket, o que la dirección sea incorrecta.</string>
|
||||
<string name="connection_error_dialog_not_authorized">No autorizado. El servidor devolvió una respuesta HTTP 401/403. Por favor, compruebe su usuario y contraseña.</string>
|
||||
<string name="connection_error_dialog_retry_now">Reintentar ahora</string>
|
||||
<string name="connection_error_dialog_retry_countdown">Reintentando en %1$ds…</string>
|
||||
<string name="connection_error_dialog_retrying">Reintentando…</string>
|
||||
<string name="settings_advanced_certificates_trusted_item_summary">Certificado fijado, emitido por %1$s, expira %2$s, usado para conexiones a %3$s</string>
|
||||
<string name="settings_advanced_certificates_trusted_item_summary_expired">Certificado fijado, emitido por %1$s, expirado, usado para conexiones a %2$s</string>
|
||||
<string name="settings_advanced_certificates_trusted_add_title">Añadir un certificado de confianza</string>
|
||||
<string name="settings_advanced_certificates_trusted_add_summary">Importa un certificado en el almacén de confianza (PEM). Al conectarse al servidor ntfy, se confiará en este certificado.</string>
|
||||
<string name="settings_advanced_certificates_client_header">Certificados de cliente (mTLS)</string>
|
||||
<string name="settings_advanced_certificates_client_item_summary">Certificado de cliente, emitido por %1$s, expira %2$s, usado para conectar a %3$s</string>
|
||||
<string name="settings_advanced_certificates_client_item_summary_expired">Certificado de cliente, emitido por %1$s, expirado, usado para conectar a %2$s</string>
|
||||
<string name="settings_advanced_certificates_client_add_title">Añadir un certificado de cliente</string>
|
||||
<string name="settings_advanced_certificates_client_add_summary">Importar certificado para autenticación TLS mutua (PKCS#12). Este certificado se utilizará al conectarse al servidor.</string>
|
||||
<string name="settings_advanced_certificates_error_invalid_cert">Archivo de certificado no válido</string>
|
||||
<string name="settings_advanced_certificates_error_invalid_p12">Archivo PKCS#12 inválido</string>
|
||||
<string name="user_dialog_base_url_error_authorization_header_exists">No se puede añadir el usuario si se ha configurado una cabecera Authorization personalizada para este servidor</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Introduce una URL del servicio válida, ej. (https://ntfy.example.com)</string>
|
||||
<string name="custom_headers_dialog_title_add">Añadir encabezado personalizado</string>
|
||||
<string name="custom_headers_dialog_title_edit">Editar encabezado personalizado</string>
|
||||
<string name="custom_headers_dialog_name_hint">Nombre de la cabecera (ej. CF-Access-Client-Id)</string>
|
||||
<string name="custom_headers_dialog_value_hint">Valor de la cabecera (ej. 9f3c2e4a1b2d4e)</string>
|
||||
<string name="custom_headers_dialog_description_add">Añade una cabecera HTTP personalizada que se enviará con cada solicitud al servidor especificado.</string>
|
||||
<string name="custom_headers_dialog_description_edit">Puedes editar el nombre o el valor de la cabecera seleccionada, o eliminarla.</string>
|
||||
<string name="custom_headers_dialog_error_invalid_name">El nombre de la cabecera contiene caracteres no válidos</string>
|
||||
<string name="trusted_certificate_dialog_title">Detalles del certificado</string>
|
||||
<string name="trusted_certificate_dialog_title_unknown">Advertencia de seguridad</string>
|
||||
<string name="trusted_certificate_dialog_title_add">Añadir certificado de confianza</string>
|
||||
<string name="trusted_certificate_dialog_security_title">Tu conexión no es privada</string>
|
||||
<string name="trusted_certificate_dialog_security_description">El certificado del servidor no es de confianza. Es posible que atacantes estén intentando robar tu información. No continúes a menos que sepas por qué este certificado no es de confianza.</string>
|
||||
<string name="trusted_certificate_dialog_description_add">Has seleccionado un archivo de certificado. Revisa los detalles a continuación antes de añadirlo a tus certificados de confianza.</string>
|
||||
<string name="trusted_certificate_dialog_description_view">Este certificado se utiliza para las conexiones a la URL del servicio indicada abajo. Has añadido esta excepción manualmente.</string>
|
||||
<string name="trusted_certificate_dialog_description_page1">Introduce la URL del servicio a la que debe fijarse este certificado. El certificado solo será de confianza para esta URL.</string>
|
||||
<string name="trusted_certificate_dialog_expired_warning">Advertencia: Este certificado ha caducado.</string>
|
||||
<string name="trusted_certificate_dialog_not_yet_valid_warning">Advertencia: Este certificado aún no es válido.</string>
|
||||
<string name="trusted_certificate_dialog_error_invalid_url">URL no válida</string>
|
||||
<string name="trusted_certificate_dialog_error_parse">No se puede cargar el certificado: %1$s</string>
|
||||
<string name="trusted_certificate_dialog_button_trust">Confiar</string>
|
||||
<string name="client_certificate_dialog_title">Certificado de cliente</string>
|
||||
<string name="client_certificate_dialog_title_add">Añadir certificado de cliente</string>
|
||||
<string name="client_certificate_dialog_description_page1">Introduce la URL del servicio para la que debe usarse este certificado y la contraseña del archivo PKCS#12.</string>
|
||||
<string name="client_certificate_dialog_description_page2">Revisa los detalles del certificado y guarda para añadir este certificado de cliente. Este certificado se utilizará para autenticarse con el servidor.</string>
|
||||
<string name="client_certificate_dialog_password_hint">Contraseña</string>
|
||||
<string name="client_certificate_dialog_error_wrong_password">Contraseña incorrecta o archivo PKCS#12 no válido</string>
|
||||
<string name="client_certificate_dialog_error_invalid_p12_password">Contraseña no válida o archivo PKCS#12 dañado</string>
|
||||
<string name="client_certificate_dialog_error_invalid_url">URL del servicio no válida</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -461,4 +461,9 @@
|
|||
<string name="detail_menu_search_hint">Otsi teavitustest</string>
|
||||
<string name="common_button_reset_to_default">Taasta algväärtused</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Sisesta korrektne teenuse võrguaadress, nt https://ntfy.toredomeen.com</string>
|
||||
<string name="connection_alert_title">Ühendus on katkenud</string>
|
||||
<string name="connection_alert_text_one">Ühendus %1$s teenusega toimib vaid %2$d minuti(t)</string>
|
||||
<string name="connection_alert_text_multiple">Ühendus %1$d serveriga toimib vaid %2$d minuti(t)</string>
|
||||
<string name="connection_alert_action_snooze">Tukasta %1$dt</string>
|
||||
<string name="connection_alert_action_never">Ära näita iialgi</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -347,10 +347,10 @@
|
|||
<string name="settings_general_dynamic_colors_title">Couleurs dynamiques</string>
|
||||
<string name="settings_general_dynamic_colors_summary_disabled">Utiliser les couleurs de thème ntfy</string>
|
||||
<string name="settings_general_dynamic_colors_summary_enabled">Utiliser les couleurs dynamiques du système</string>
|
||||
<string name="publish_dialog_title_placeholder">e.g. Quelqu\'un est à la porte</string>
|
||||
<string name="publish_dialog_title_placeholder">par ex. Quelqu\'un est à la porte</string>
|
||||
<string name="publish_dialog_message_hint">Message</string>
|
||||
<string name="publish_dialog_tags_hint">Étiquettes</string>
|
||||
<string name="publish_dialog_tags_placeholder">e.g. warning, skull</string>
|
||||
<string name="publish_dialog_tags_placeholder">par ex. attention, crâne</string>
|
||||
<string name="publish_dialog_priority_hint">Priorité</string>
|
||||
<string name="publish_dialog_button_publish">Publier</string>
|
||||
<string name="publish_dialog_error_sending">Impossible de publier le message : %1$s</string>
|
||||
|
|
@ -390,7 +390,7 @@
|
|||
<string name="settings_general_message_bar_title">Afficher la barre de message</string>
|
||||
<string name="settings_general_message_bar_summary_enabled">Barre de message affichée en bas du sujet</string>
|
||||
<string name="settings_general_message_bar_summary_disabled">Bouton Publier affiché en bas du sujet</string>
|
||||
<string name="settings_advanced_custom_headers_title">En-têtes HTTP personnalisés</string>
|
||||
<string name="settings_advanced_custom_headers_title">En-têtes personnalisés</string>
|
||||
<string name="settings_advanced_custom_headers_summary">Définissez des en-têtes HTTP personnalisés qui seront envoyés avec chaque demande, par exemple, si votre serveur ntfy se trouve derrière un proxy ou un tunnel authentifié.</string>
|
||||
<string name="settings_advanced_custom_headers_prefs_header_add">Ajouter un en-tête</string>
|
||||
<string name="settings_advanced_custom_headers_prefs_header_add_title">Ajouter un en-tête pour un serveur</string>
|
||||
|
|
@ -471,4 +471,9 @@
|
|||
<string name="detail_menu_search_hint">Rechercher dans les notifications</string>
|
||||
<string name="common_button_reset_to_default">Réinitialiser par défaut</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Entrez une URL de service valide, par ex. https://ntfy.example.com</string>
|
||||
<string name="connection_alert_title">Connexion perdue</string>
|
||||
<string name="connection_alert_text_one">Impossible de se connecter à %1$s depuis plus de %2$d minutes</string>
|
||||
<string name="connection_alert_text_multiple">Impossible de se connecter à %1$d serveurs depuis plus de %2$d minutes</string>
|
||||
<string name="connection_alert_action_snooze">Sourdine %1$dh</string>
|
||||
<string name="connection_alert_action_never">Ne jamais montrer</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@
|
|||
<string name="detail_how_to_link">विस्तृत निर्देश ntfy.sh पर और डॉक्स में उपलब्ध हैं।</string>
|
||||
<string name="detail_clear_dialog_permanently_delete">स्थायी रूप से हटाएं</string>
|
||||
<string name="detail_how_to_intro">इस विषय पर सूचनाएं भेजने के लिए, बस विषय URL पर PUT या POST करें।</string>
|
||||
<string name="detail_how_to_example">उदाहरण (curl का उपयोग करके):<br></br><tt>$curl -d \"नमस्कार\"%1$s</tt></string>
|
||||
<string name="detail_how_to_example">उदाहरण (curl का उपयोग करके):<br/><tt>$curl -d \"नमस्कार\"%1$s</tt></string>
|
||||
<string name="detail_clear_dialog_message">इस विषय की सभी सूचनाएँ हटाएँ?</string>
|
||||
<string name="main_banner_websocket_text">WebSockets पर स्विच करना आपके सर्वर से कनेक्ट करने का अनुशंसित तरीका है, और बैटरी जीवन में सुधार कर सकता है, लेकिन आपके <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">proxy में अतिरिक्त कॉन्फ़िगरेशन</a> की आवश्यकता हो सकती है। इसे सेटिंग्स में टॉगल किया जा सकता है।</string>
|
||||
<string name="detail_test_message_error_unauthorized_anon">संदेश नहीं भेजा जा सकता: अनाम प्रकाशन की अनुमति नहीं है।</string>
|
||||
|
|
|
|||
|
|
@ -83,4 +83,4 @@
|
|||
<string name="main_menu_report_bug_title">Prijavu grešku</string>
|
||||
<string name="main_how_to_link">Opširnije upute dostupne su na ntfy.sh i u dokumentaciji.</string>
|
||||
<string name="main_how_to_intro">Klikni + za kreiranje ili pretplaćivanje na temu. Nakon toga primaš obavijesti na uređaj kad pošalješ poruke preko PUT ili POST.</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -471,4 +471,9 @@
|
|||
<string name="detail_menu_search_hint">通知内容を検索します</string>
|
||||
<string name="common_button_reset_to_default">既定にリセット</string>
|
||||
<string name="default_server_dialog_url_error_invalid">有効なサービスURLを入力してください、例: https://ntfy.example.com</string>
|
||||
<string name="connection_alert_title">接続が切断されました</string>
|
||||
<string name="connection_alert_text_one">%2$d 分以上 %1$s に接続できませんでした</string>
|
||||
<string name="connection_alert_text_multiple">%1$d 個のサーバーに %2$d 分以上接続できませんでした</string>
|
||||
<string name="connection_alert_action_snooze">%1$d時間後に再通知</string>
|
||||
<string name="connection_alert_action_never">再表示しない</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
<string name="add_dialog_instant_delivery_description">Forsikrer at meldinger blir levert umiddelbart, selv når enheten er inaktiv.</string>
|
||||
<string name="add_dialog_login_description">Dette emnet krever at du logger inn. Skriv inn et brukernavn og passord.</string>
|
||||
<string name="detail_how_to_intro">For å sende merknader til dette emnet kan du utføre PUT eller POST til emne-nettadressen.</string>
|
||||
<string name="detail_how_to_example">Eksempel (ved bruk av curl):<br></br><tt>$ curl -d \"Hei\" %1$s</tt></string>
|
||||
<string name="detail_how_to_example">Eksempel (ved bruk av curl):<br/><tt>$ curl -d \"Hei\" %1$s</tt></string>
|
||||
<string name="detail_item_snack_deleted">Merknad slettet</string>
|
||||
<string name="detail_item_menu_cancel">Avbryt nedlasting</string>
|
||||
<string name="detail_item_menu_save_file">Lagre fil</string>
|
||||
|
|
|
|||
|
|
@ -364,4 +364,64 @@
|
|||
<string name="publish_dialog_error_sending">Fout bij publiceren: %1$s</string>
|
||||
<string name="publish_dialog_error_server">Kon bericht niet publiceren: %1$s (code %2$d)</string>
|
||||
<string name="publish_dialog_message_published">Bericht gepubliceerd</string>
|
||||
<string name="common_button_reset_to_default">Terug naar standaardinstellingen</string>
|
||||
<string name="common_certificate_valid_from">Geldig vanaf</string>
|
||||
<string name="common_certificate_issuer">Uitgever</string>
|
||||
<string name="common_certificate_fingerprint">SHA-256 vingerafdruk</string>
|
||||
<string name="common_certificate_subject">Onderwerp</string>
|
||||
<string name="client_certificate_dialog_error_invalid_url">Onjuiste server URL</string>
|
||||
<string name="client_certificate_dialog_description_page1">Vul de server URL in waar dit certificaat voor moet worden gebruikt, en het wachtwoord voor het PKCS#12 bestand.</string>
|
||||
<string name="client_certificate_dialog_description_page2">Beoordeel de certificaat instellingen en sla op om het certificaat toe te voegen. Dit certificaat zal worden gebruikt om te authenticeren met de server.</string>
|
||||
<string name="client_certificate_dialog_password_hint">Wachtwoord</string>
|
||||
<string name="client_certificate_dialog_error_wrong_password">Onjuist wachtwoord of onjuist PKCS#12 bestand</string>
|
||||
<string name="client_certificate_dialog_error_invalid_p12_password">Onjuist wachtwoord of beschadigd PKCS#12 bestand</string>
|
||||
<string name="connection_alert_title">Verbinding verbroken</string>
|
||||
<string name="connection_alert_text_one">Kan geen verbinding maken met %1$s voor meer dan %2$d minuten</string>
|
||||
<string name="connection_alert_text_multiple">Kan geen verbinding maken met %1$d servers voor meer dan %2$d minuten</string>
|
||||
<string name="connection_alert_action_snooze">Sluimer voor %1$d uur</string>
|
||||
<string name="connection_alert_action_never">Nooit laten zien</string>
|
||||
<string name="publish_dialog_title">Publieer naar %1$s</string>
|
||||
<string name="publish_dialog_uploading">Uploaden: %1$s (%2$s / %3$s)</string>
|
||||
<string name="publish_dialog_upload_cancelled">Upload geannuleerd</string>
|
||||
<string name="publish_dialog_chip_title">Titel</string>
|
||||
<string name="publish_dialog_chip_tags">Labels</string>
|
||||
<string name="publish_dialog_chip_priority">Prioriteit</string>
|
||||
<string name="publish_dialog_chip_click_url">Klik URL</string>
|
||||
<string name="publish_dialog_chip_email">Email</string>
|
||||
<string name="publish_dialog_chip_delay">Vertraging</string>
|
||||
<string name="publish_dialog_chip_markdown">Markdown</string>
|
||||
<string name="publish_dialog_chip_attach_url">Insluiten via URL</string>
|
||||
<string name="publish_dialog_chip_attach_file">Bestand insluiten</string>
|
||||
<string name="publish_dialog_chip_phone_call">Telefoongesprek</string>
|
||||
<string name="publish_dialog_click_url_hint">Klik URL</string>
|
||||
<string name="publish_dialog_click_url_placeholder">bijvoorbeeld https://example.com/alerts/1234</string>
|
||||
<string name="publish_dialog_email_hint">Email</string>
|
||||
<string name="publish_dialog_email_placeholder">bijvoorbeeld jan@jansen.nl</string>
|
||||
<string name="publish_dialog_delay_hint">Vertraging bezorging</string>
|
||||
<string name="publish_dialog_attach_url_hint">Attachment URL</string>
|
||||
<string name="publish_dialog_attach_url_placeholder">bijvoorbeeld https://example.com/flowers.jpg</string>
|
||||
<string name="publish_dialog_attach_filename_hint">Attachment bestandsnaam</string>
|
||||
<string name="publish_dialog_attach_filename_placeholder">bijvoorbeeld lilies.jpg</string>
|
||||
<string name="publish_dialog_phone_call_hint">Telefoongesprek</string>
|
||||
<string name="publish_dialog_phone_call_placeholder">bijvoorbeel +1234567890</string>
|
||||
<string name="publish_dialog_docs_text">Bekijk de <a href="https://docs.ntfy.sh/publish/">documentatie</a> voor voorbeelden en een uitgebreide beschrijving van alle publiceer-functies.</string>
|
||||
<string name="message_bar_hint">Berichtenbalk</string>
|
||||
<string name="message_bar_publish_button_description">Publiceer bericht</string>
|
||||
<string name="message_bar_expand_button_description">Meer opties</string>
|
||||
<string name="connection_error_dialog_title">Fout bij verbinden</string>
|
||||
<string name="connection_error_dialog_message">Er was een probleem bij het verbinden met %1$s. De app zal blijven proberen in de achtergrond.</string>
|
||||
<string name="connection_error_dialog_connection_refused">Verbinding geweigerd. De server is mogelijk niet bereikbaar of het adres is onjuist.</string>
|
||||
<string name="connection_error_dialog_websocket_not_supported">WebSocket niet ondersteund. De server ondersteund mogelijk geen WebSochet, of het adres is onjuist.</string>
|
||||
<string name="connection_error_dialog_not_authorized">Niet toegestaan. De server gaf een HTTP 401/403 antwoord. Controleer uw gebruikersnaam en/of wachtwoord.</string>
|
||||
<string name="connection_error_dialog_retry_now">Probeer opnieuw</string>
|
||||
<string name="connection_error_dialog_retry_countdown">Nieuwe poging in %1$d…</string>
|
||||
<string name="connection_error_dialog_retrying">Opnieuw proberen…</string>
|
||||
<string name="settings_general_language_title">Taal</string>
|
||||
<string name="settings_general_language_summary_system">Systeemstandaarden worden gebruikt</string>
|
||||
<string name="settings_general_language_system_default">Systeemstandaarden</string>
|
||||
<string name="settings_general_dynamic_colors_title">Dynamische kleuren</string>
|
||||
<string name="settings_general_dynamic_colors_summary_enabled">Dynamische systeemkleuren worden gebruikt</string>
|
||||
<string name="settings_general_dynamic_colors_summary_disabled">Ntfy thema kleuren worden gebruikt</string>
|
||||
<string name="settings_general_message_bar_title">Toon berichtenbalk</string>
|
||||
<string name="settings_general_message_bar_summary_enabled">Berichtenbalk getoond onderaan onderwerpweergave</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -341,4 +341,135 @@
|
|||
<string name="settings_advanced_exact_alarms_title">Alarmes exatos</string>
|
||||
<string name="settings_advanced_exact_alarms_true">O ntfy pode agendar alarmes exatos, eles são usados para reconectar WebSockets em segundo plano. Clique para revogar a permissão.</string>
|
||||
<string name="settings_advanced_exact_alarms_false">O ntfy não pode agendar alarmes exatos, eles são usados para reconectar WebSockets em segundo plano. Clique para conceder a permissão.</string>
|
||||
<string name="common_button_next">Próximo</string>
|
||||
<string name="common_button_add">Adicionar</string>
|
||||
<string name="common_button_delete">Apagar</string>
|
||||
<string name="common_button_reset_to_default">Restaurar Padrões</string>
|
||||
<string name="common_service_url_placeholder">ex. https://ntfy.example.com</string>
|
||||
<string name="common_certificate_subject">Dono</string>
|
||||
<string name="common_certificate_issuer">Emissor</string>
|
||||
<string name="common_certificate_fingerprint">Assinatura SHA-256</string>
|
||||
<string name="common_certificate_valid_from">Válido de</string>
|
||||
<string name="common_certificate_valid_until">Válido até</string>
|
||||
<string name="common_certificate_added_toast">Certificado adicionado</string>
|
||||
<string name="common_certificate_deleted_toast">Certificado removido</string>
|
||||
<string name="connection_alert_title">Notificação de alerta de conexão</string>
|
||||
<string name="connection_alert_text_one">Não foi possível conectar à %1$s por mais de %2$d minutos</string>
|
||||
<string name="connection_alert_text_multiple">Não foi possível conectar aos servidores %1$d por mais de %2$d minutos</string>
|
||||
<string name="connection_alert_action_snooze">Adiar %1$dh</string>
|
||||
<string name="connection_alert_action_never">Nunca mostrar</string>
|
||||
<string name="main_menu_connection_error">Erro de conexão</string>
|
||||
<string name="add_dialog_error_ssl_untrusted">Certificado do servidor não confiável</string>
|
||||
<string name="detail_no_search_results">Sua busca não retornou resultados</string>
|
||||
<string name="detail_menu_search">Notificações de pesquisa</string>
|
||||
<string name="detail_menu_search_hint">Buscar em notificações</string>
|
||||
<string name="publish_dialog_title">Publicar em %1$s</string>
|
||||
<string name="publish_dialog_title_hint">Título</string>
|
||||
<string name="publish_dialog_title_placeholder">ex. Tem alguém na porta</string>
|
||||
<string name="publish_dialog_message_hint">Mensagem</string>
|
||||
<string name="publish_dialog_tags_hint">Tags</string>
|
||||
<string name="publish_dialog_tags_placeholder">ex. Alerta, skull</string>
|
||||
<string name="publish_dialog_priority_hint">Prioridade</string>
|
||||
<string name="publish_dialog_button_publish">Publicar</string>
|
||||
<string name="publish_dialog_error_sending">Não foi possível publicar a mensagem: %1$s</string>
|
||||
<string name="publish_dialog_error_server">Não foi possível publicar a mensagem: %1$s (código %2$d)</string>
|
||||
<string name="publish_dialog_message_published">Mensagem publicada</string>
|
||||
<string name="publish_dialog_uploading">Subindo: %1$s (%2$s / %3$s)</string>
|
||||
<string name="publish_dialog_upload_cancelled">Upload cancelado</string>
|
||||
<string name="publish_dialog_chip_title">Título</string>
|
||||
<string name="publish_dialog_chip_tags">Etiquetas</string>
|
||||
<string name="publish_dialog_chip_priority">Prioridade</string>
|
||||
<string name="publish_dialog_chip_click_url">Click URL</string>
|
||||
<string name="publish_dialog_chip_email">Email</string>
|
||||
<string name="publish_dialog_chip_delay">Atraso</string>
|
||||
<string name="publish_dialog_chip_markdown">Markdown</string>
|
||||
<string name="publish_dialog_chip_attach_url">Anexar com URL</string>
|
||||
<string name="publish_dialog_chip_attach_file">Anexar arquivo local</string>
|
||||
<string name="publish_dialog_chip_phone_call">Chamada telefônica</string>
|
||||
<string name="publish_dialog_click_url_hint">Click URL</string>
|
||||
<string name="publish_dialog_click_url_placeholder">ex. https://example.com/alerts/1234</string>
|
||||
<string name="publish_dialog_email_hint">Email</string>
|
||||
<string name="publish_dialog_email_placeholder">ex. phil@example.com</string>
|
||||
<string name="publish_dialog_delay_hint">Atraso na entrega</string>
|
||||
<string name="publish_dialog_attach_url_hint">URL do anexo</string>
|
||||
<string name="publish_dialog_attach_url_placeholder">ex. https://example.com/flowers.jpg</string>
|
||||
<string name="publish_dialog_attach_filename_hint">Nome de arquivo do anexo</string>
|
||||
<string name="publish_dialog_attach_filename_placeholder">ex. lilies.jpg</string>
|
||||
<string name="publish_dialog_phone_call_hint">Chamada telefônica</string>
|
||||
<string name="publish_dialog_phone_call_placeholder">ex. +1234567890</string>
|
||||
<string name="publish_dialog_docs_text">Para exemplos e uma descrição detalhada de todos os recursos de publicação, por favor consulte <a href="https://docs.ntfy.sh/publish/">documentation</a>.</string>
|
||||
<string name="message_bar_hint">Barra de mensagens</string>
|
||||
<string name="message_bar_publish_button_description">Publicar mensagem</string>
|
||||
<string name="message_bar_expand_button_description">Mais opções</string>
|
||||
<string name="trusted_certificate_dialog_button_trust">Confie</string>
|
||||
<string name="client_certificate_dialog_title">Certificado cliente</string>
|
||||
<string name="client_certificate_dialog_title_add">Adicionar certificado cliente</string>
|
||||
<string name="client_certificate_dialog_description_page1">Insira a URL de serviço para o qual este certificado deve ser usado e a senha para o arquivo PKCS#12.</string>
|
||||
<string name="client_certificate_dialog_description_page2">Revisar os detalhes do certificado e salvar para adicionar este certificado de cliente. Este certificado será usado para autenticar com o servidor.</string>
|
||||
<string name="client_certificate_dialog_password_hint">Senha</string>
|
||||
<string name="client_certificate_dialog_error_wrong_password">Senha incorreta ou arquivo PKCS#12 inválido</string>
|
||||
<string name="client_certificate_dialog_error_invalid_p12_password">Senha inválida ou arquivo PKCS#12 corrompido</string>
|
||||
<string name="client_certificate_dialog_error_invalid_url">URL de serviço inválida</string>
|
||||
<string name="publish_dialog_delay_placeholder">ex: 30m, 1h, today 9pm (expressões de tempo apenas em inglês)</string>
|
||||
<string name="detail_fab_publish_description">Publicar notificação</string>
|
||||
<string name="connection_error_dialog_title">Falha na conexão</string>
|
||||
<string name="connection_error_dialog_message">Houve um problema ao conectar em %1$s. O app vai continuar tentando reconectar em segundo plano.</string>
|
||||
<string name="connection_error_dialog_connection_refused">Conexão recusada. O servidor pode estar desligado ou o endereço pode estar incorreto.</string>
|
||||
<string name="connection_error_dialog_websocket_not_supported">WebSocket não suportado. O servidor pode não suportar conexões WebSocket ou o endereço pode estar incorreto.</string>
|
||||
<string name="connection_error_dialog_not_authorized">Não autorizado. O servidor retornou uma resposta HTTP 401/403. Favor verificar se seu usuário e senha estão corretos.</string>
|
||||
<string name="connection_error_dialog_retry_now">Tentar de novo agora</string>
|
||||
<string name="connection_error_dialog_retry_countdown">Tentando de novo em %1$d…</string>
|
||||
<string name="connection_error_dialog_retrying">Tentando de novo…</string>
|
||||
<string name="settings_general_language_title">Idioma</string>
|
||||
<string name="settings_general_language_summary_system">Usando padrão do sistema</string>
|
||||
<string name="settings_general_language_system_default">Padrão do sistema</string>
|
||||
<string name="settings_general_dynamic_colors_title">Cores dinâmicas</string>
|
||||
<string name="settings_general_dynamic_colors_summary_enabled">Usando as cores dinâmicas do sistema</string>
|
||||
<string name="settings_general_dynamic_colors_summary_disabled">Usando as cores do tema ntfy</string>
|
||||
<string name="settings_general_message_bar_title">Mostrar barra de mensagens</string>
|
||||
<string name="settings_general_message_bar_summary_enabled">Barra de mensagens mostrada abaixo da visualização de tópico</string>
|
||||
<string name="settings_general_message_bar_summary_disabled">Botão publicar mostrado abaixo da visualização de tópico</string>
|
||||
<string name="settings_advanced_custom_headers_title">Cabeçalhos customizados</string>
|
||||
<string name="settings_advanced_custom_headers_summary">Definir cabeçalhos HTTP personalizados que serão enviados junto com cada requisição, por ex. se seu servidor ntfy está atrás de um túnel ou proxy autenticado.</string>
|
||||
<string name="settings_advanced_custom_headers_prefs_header_add">Adicionar cabeçalho</string>
|
||||
<string name="settings_advanced_custom_headers_prefs_header_add_title">Adicionar um cabeçalho para um servidor</string>
|
||||
<string name="settings_advanced_custom_headers_prefs_header_add_summary">Cabeçalhos são incluídos em cada requisição HTTP. Cada servidor ntfy pode ter seu próprio conjunto de cabeçalhos personalizados.</string>
|
||||
<string name="settings_advanced_certificates_title">Gerenciar certificados</string>
|
||||
<string name="settings_advanced_certificates_summary">Adicionar certificados para a trust store e gerenciar certificados de cliente para mTLS</string>
|
||||
<string name="settings_advanced_certificates_trusted_header">Certificados confiáveis</string>
|
||||
<string name="settings_advanced_certificates_trusted_item_summary">Certificado fixado, emitido por %1$s,expira em %2$s, usado para conexões em %3$s</string>
|
||||
<string name="settings_advanced_certificates_trusted_item_summary_expired">Certificado fixado, emitido por %1$s, expiradom usado para conexões em %2$s</string>
|
||||
<string name="settings_advanced_certificates_trusted_add_title">Adicionar um certificado confiável</string>
|
||||
<string name="settings_advanced_certificates_trusted_add_summary">Importar um certificado para a trust store (PEM). Ao conectar ao servidor ntfy, este certificado será considerado confiável.</string>
|
||||
<string name="settings_advanced_certificates_client_header">Certificado de cliente (mTLS)</string>
|
||||
<string name="settings_advanced_certificates_client_item_summary">Certificado de cliente, emitido por %1$s, expira em %2$s, usado para conexões com %3$s</string>
|
||||
<string name="settings_advanced_certificates_client_item_summary_expired">Certificado de cliente, emitido por %1$s, expirado, usado para conexões com%2$s</string>
|
||||
<string name="settings_advanced_certificates_client_add_title">Adicionar um certificado de cliente</string>
|
||||
<string name="settings_advanced_certificates_client_add_summary">Importar certificado para autenticação TLS mútua (PKCS#12). Este certificado será usado ao conectar com o servidor.</string>
|
||||
<string name="settings_advanced_certificates_error_invalid_cert">Arquivo de certificado inválido</string>
|
||||
<string name="settings_advanced_certificates_error_invalid_p12">Arquivo PKCS#12 inválido</string>
|
||||
<string name="user_dialog_base_url_error_authorization_header_exists">Não é possível adicionar usuário se o cabeçalho de autorização personalizada está configurado para este servidor</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Insira uma URL de serviço válida, por ex. https://ntfy.example.com</string>
|
||||
<string name="custom_headers_dialog_title_add">Adicionar cabeçalho personalizado</string>
|
||||
<string name="custom_headers_dialog_title_edit">Editar cabeçalho personalizado</string>
|
||||
<string name="custom_headers_dialog_name_hint">Nome do cabeçalho (ex. CF-Access-Client-Id)</string>
|
||||
<string name="custom_headers_dialog_value_hint">Valor do cabeçalho (ex. 9f3c2e4a1b2d4e)</string>
|
||||
<string name="custom_headers_dialog_description_add">Adicionar um cabeçalho HTTP personalizado que será enviado com cada requisição para o servidor especificado.</string>
|
||||
<string name="custom_headers_dialog_description_edit">Você pode editar o nome/valor do cabeçalho para o cabeçalho selecionado, ou apaga-lo.</string>
|
||||
<string name="custom_headers_dialog_error_invalid_name">O nome do cabeçalho contém caracteres inválidos</string>
|
||||
<string name="custom_headers_dialog_error_reserved_name">Este cabeçalho está reservado e configurado pelo ntfy</string>
|
||||
<string name="custom_headers_dialog_error_user_exists">Não é possível adicionar um cabeçalho de autorização se um usuário está configurado para este servidor</string>
|
||||
<string name="custom_headers_dialog_error_duplicate">Um cabeçalho com este nome já existe para este servidor</string>
|
||||
<string name="trusted_certificate_dialog_title">Detalhes do certificado</string>
|
||||
<string name="trusted_certificate_dialog_title_unknown">Alerta de segurança</string>
|
||||
<string name="trusted_certificate_dialog_title_add">Adicionar certificado confiável</string>
|
||||
<string name="trusted_certificate_dialog_security_title">Sua conexão não é privada</string>
|
||||
<string name="trusted_certificate_dialog_security_description">O certificado do servidor não é confiável. Atacantes podem estar tentando roubar suas informações. Não prossiga a menos que você saiba porque este certificado não é confiável.</string>
|
||||
<string name="trusted_certificate_dialog_description_add">Você selecionou um arquivo de certificado. Revise os detalhes abaixo antes de adiciona-lo aos seus certificados confiáveis.</string>
|
||||
<string name="trusted_certificate_dialog_description_view">Este certificado é usado para conexões à URL de serviço abaixo. Você adicionou esta exceção manualmente.</string>
|
||||
<string name="trusted_certificate_dialog_description_page1">Insira a URL de serviço para o qual este certificado deveria ser fixado. O certificado será considerado confiável apenas para esta URL.</string>
|
||||
<string name="trusted_certificate_dialog_expired_warning">Alerta: Este certificado expirou.</string>
|
||||
<string name="trusted_certificate_dialog_not_yet_valid_warning">Alerta: Este certificado ainda não é válido.</string>
|
||||
<string name="trusted_certificate_dialog_error_invalid_url">URL inválida</string>
|
||||
<string name="trusted_certificate_dialog_error_parse">Não foi possível carregar certificado: %1$s</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -345,4 +345,26 @@
|
|||
<string name="settings_advanced_exact_alarms_title">Alarmes exactos</string>
|
||||
<string name="settings_advanced_exact_alarms_true">O ntfy pode agendar alarmes exatos. Alarmes exatos são necessários para reconectar os WebSockets em segundo plano. Clique para revogar a permissão.</string>
|
||||
<string name="settings_advanced_exact_alarms_false">O ntfy não pode agendar alarmes exatos. Alarmes exatos são necessários para reconectar os WebSockets em segundo plano. Clique para conceder a permissão.</string>
|
||||
<string name="common_button_next">Próximo</string>
|
||||
<string name="common_button_add">Adicionar</string>
|
||||
<string name="common_button_delete">Apagar</string>
|
||||
<string name="common_button_reset_to_default">Restaurar valores padrão</string>
|
||||
<string name="common_service_url_placeholder">ex. https://ntfy.example.com</string>
|
||||
<string name="common_certificate_subject">Assunto</string>
|
||||
<string name="common_certificate_issuer">Emissor</string>
|
||||
<string name="common_certificate_fingerprint">Impressão digital SHA-256</string>
|
||||
<string name="common_certificate_valid_from">Válido desde</string>
|
||||
<string name="common_certificate_valid_until">Válido até</string>
|
||||
<string name="common_certificate_added_toast">Certificado adicionado</string>
|
||||
<string name="common_certificate_deleted_toast">Certificado apagado</string>
|
||||
<string name="connection_alert_title">Conexão perdida</string>
|
||||
<string name="publish_dialog_title_placeholder">ex. Alguém está à porta</string>
|
||||
<string name="publish_dialog_message_hint">Mensagem</string>
|
||||
<string name="publish_dialog_tags_hint">Etiquetas</string>
|
||||
<string name="publish_dialog_tags_placeholder">ex. aviso, perigo</string>
|
||||
<string name="publish_dialog_priority_hint">Prioridade</string>
|
||||
<string name="publish_dialog_button_publish">Publicar</string>
|
||||
<string name="publish_dialog_error_sending">Não foi possível publicar a mensagem: %1$s</string>
|
||||
<string name="publish_dialog_error_server">Não foi possível publicar a mensagem: %1$s (código %2$d)</string>
|
||||
<string name="publish_dialog_message_published">Mensagem publicada</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -343,4 +343,7 @@
|
|||
<string name="settings_advanced_exact_alarms_title">Alarme exacte</string>
|
||||
<string name="settings_advanced_exact_alarms_true">ntfy poate programa alarme exacte. Alarmele exacte sunt necesare pentru a reconecta WebSocket-urile în fundal. Faceți clic pentru a revoca permisiunea.</string>
|
||||
<string name="settings_advanced_exact_alarms_false">ntfy nu poate programa alarme exacte. Alarmele exacte sunt necesare pentru a reconecta WebSockets în fundal. Faceți clic pentru a acorda permisiunea.</string>
|
||||
<string name="common_button_next">Următorul</string>
|
||||
<string name="common_button_add">Adaugă</string>
|
||||
<string name="common_button_delete">Şterge</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -132,9 +132,7 @@
|
|||
<string name="settings_backup_restore_restore_title">Восстановить из файла</string>
|
||||
<string name="settings_general_users_prefs_user_add_title">Добавить нового пользователя</string>
|
||||
<string name="main_menu_notifications_disabled_until">Уведомления отключены до %1$s</string>
|
||||
<string name="refresh_message_error">Не получилось обновить %1$d подписок
|
||||
\n
|
||||
\n%2$s</string>
|
||||
<string name="refresh_message_error">Не получилось обновить %1$d подписок\n\n%2$s</string>
|
||||
<string name="refresh_message_error_one">Не получилось обновить подписку: %1$s</string>
|
||||
<string name="main_action_bar_title">Темы подписок</string>
|
||||
<string name="main_how_to_intro">Нажмите \"+\", чтобы создать или подписаться на тему. Вы будете получать уведомления на вашем устройстве при отправке сообщений через PUT или POST-запросы.</string>
|
||||
|
|
@ -466,4 +464,29 @@
|
|||
<string name="client_certificate_dialog_error_wrong_password">Неверный пароль или недопустимый файл PKCS#12</string>
|
||||
<string name="client_certificate_dialog_error_invalid_p12_password">Неверный пароль или поврежденный файл PKCS#12</string>
|
||||
<string name="client_certificate_dialog_error_invalid_url">Недопустимый URL сервиса</string>
|
||||
<string name="common_button_reset_to_default">Сбросить по умолчанию</string>
|
||||
<string name="connection_alert_action_never">Не показывать</string>
|
||||
<string name="connection_alert_title">Соединение разорвано</string>
|
||||
<string name="connection_alert_action_snooze">Отложить на %1$dч</string>
|
||||
<string name="connection_alert_text_one">Невозможно подключиться к %1$s более %2$d мин. Проверьте подключение к сети.</string>
|
||||
<string name="connection_alert_text_multiple">Невозможно подключиться к %1$d серверам более %2$d мин. Проверьте подключение к сети.</string>
|
||||
<string name="channel_connection_alert_name">Уведомления о подключении</string>
|
||||
<string name="main_banner_no_network_text">Вы не в сети</string>
|
||||
<string name="detail_no_search_results">Ничего не найдено</string>
|
||||
<string name="detail_menu_search_hint">Искать в уведомлениях</string>
|
||||
<string name="settings_advanced_connection_alert_title">Оповещение при отключении</string>
|
||||
<string name="settings_advanced_connection_alert_summary_never">Никогда не уведомлять о недоступности сервера</string>
|
||||
<string name="settings_advanced_connection_alert_summary_five_minutes">Уведомлять, если сервер недоступен более 5 минут</string>
|
||||
<string name="settings_advanced_connection_alert_summary_fifteen_minutes">Уведомлять, если сервер недоступен более 15 минут</string>
|
||||
<string name="settings_advanced_connection_alert_summary_one_hour">Уведомлять, если сервер недоступен более 1 часа</string>
|
||||
<string name="settings_advanced_connection_alert_summary_three_hours">Уведомлять, если сервер недоступен более 3 часов</string>
|
||||
<string name="settings_advanced_connection_alert_summary_twelve_hours">Уведомлять, если сервер недоступен более 12 часов</string>
|
||||
<string name="settings_advanced_connection_alert_never">Никогда</string>
|
||||
<string name="settings_advanced_connection_alert_five_minutes">Через 5 минут</string>
|
||||
<string name="settings_advanced_connection_alert_fifteen_minutes">Через 15 минут</string>
|
||||
<string name="settings_advanced_connection_alert_one_hour">Через 1 час</string>
|
||||
<string name="settings_advanced_connection_alert_three_hours">Через 3 часа</string>
|
||||
<string name="settings_advanced_connection_alert_twelve_hours">Через 12 часов</string>
|
||||
<string name="default_server_dialog_url_error_invalid">Укажите верный URL, например https://ntfy.example.com</string>
|
||||
<string name="detail_menu_search">Поиск уведомлений</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
<string name="main_banner_battery_button_dismiss">தள்ளுபடி</string>
|
||||
<string name="main_banner_battery_button_fix_now">இப்போது சரிசெய்யவும்</string>
|
||||
<string name="add_dialog_base_urls_dropdown_clear">தெளிவான பணி முகவரி</string>
|
||||
<string name="detail_how_to_example">எடுத்துக்காட்டு (சுருட்டைப் பயன்படுத்துதல்): <br></br> <tt> $ சுருட்டை -d \"hi\" %1$s </tt></string>
|
||||
<string name="detail_how_to_example">எடுத்துக்காட்டு (சுருட்டைப் பயன்படுத்துதல்): <br/> <tt> $ சுருட்டை -d \"hi\" %1$s </tt></string>
|
||||
<string name="detail_how_to_link">Ntfy.sh, மற்றும் டாக்சில் விரிவான வழிமுறைகள் கிடைக்கின்றன.</string>
|
||||
<string name="detail_instant_delivery_disabled">உடனடி வழங்கல்</string>
|
||||
<string name="detail_deep_link_subscribed_toast_message">தலைப்பு %1$s க்கு குழுசேர்ந்தது</string>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
<string name="add_dialog_base_urls_dropdown_choose">URL manzilini tanlang</string>
|
||||
<string name="add_dialog_base_urls_dropdown_clear">URL manzilini tozalang</string>
|
||||
<string name="detail_how_to_intro">Ushbu mavzu bo‘yicha bildirishnomalarni yuborish uchun, mavzu URL manziliga PUT yoki POST so‘rov yuboring.</string>
|
||||
<string name="detail_how_to_example">Misol (curl yordamida):<br></br><tt>$ curl -d \"Salom\" %1$s</tt></string>
|
||||
<string name="detail_how_to_example">Misol (curl yordamida):<br/><tt>$ curl -d \"Salom\" %1$s</tt></string>
|
||||
<string name="detail_how_to_link">Batafsil ko‘rsatmalar ntfy.sh saytida va hujjatlarda mavjud.</string>
|
||||
<string name="detail_clear_dialog_message">Ushbu mavzudagi barcha bildirishnomalar o‘chirilsinmi?</string>
|
||||
<string name="detail_clear_dialog_permanently_delete">Butunlay o‘chirish</string>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@
|
|||
<string name="common_priority_default_name">默认优先级</string>
|
||||
<string name="common_priority_high_name">高优先级</string>
|
||||
<string name="common_priority_max_name">最高优先级</string>
|
||||
<string name="channel_subscriber_service_name">订阅服务</string>
|
||||
<string name="channel_subscriber_service_name">后台服务</string>
|
||||
<string name="channel_subscriber_notification_title">正在监听通知</string>
|
||||
<string name="channel_subscriber_notification_noinstant_text">已订阅主题</string>
|
||||
<string name="channel_subscriber_notification_noinstant_text_one">已订阅 1 个主题</string>
|
||||
|
|
@ -471,4 +471,24 @@
|
|||
<string name="detail_menu_search_hint">在通知中搜索</string>
|
||||
<string name="common_button_reset_to_default">重置为默认</string>
|
||||
<string name="default_server_dialog_url_error_invalid">输入有效的服务 URL,如 https://ntfy.example.com</string>
|
||||
<string name="connection_alert_title">连接丢失</string>
|
||||
<string name="connection_alert_text_one">已无法连接到 %1$s 超过 %2$d 分钟。检查网络连接。</string>
|
||||
<string name="connection_alert_text_multiple">已无法连接到 %1$d 台服务器超过 %2$d 分钟。检查网络连接。</string>
|
||||
<string name="connection_alert_action_snooze">延后 %1$d 小时</string>
|
||||
<string name="connection_alert_action_never">永不显示</string>
|
||||
<string name="channel_connection_alert_name">连接警报</string>
|
||||
<string name="main_banner_no_network_text">未联网</string>
|
||||
<string name="settings_advanced_connection_alert_title">连接断开时示警</string>
|
||||
<string name="settings_advanced_connection_alert_summary_never">无法连接到 ntfy 服务器时永远不通知</string>
|
||||
<string name="settings_advanced_connection_alert_summary_five_minutes">如果无法连接到 ntfy 服务器超过 5 分钟就发出通知</string>
|
||||
<string name="settings_advanced_connection_alert_summary_fifteen_minutes">如果无法连接到 ntfy 服务器超过 15 分钟就发出通知</string>
|
||||
<string name="settings_advanced_connection_alert_summary_one_hour">如果无法连接到 ntfy 服务器超过 1 小时就发出通知</string>
|
||||
<string name="settings_advanced_connection_alert_summary_three_hours">如果无法连接到 ntfy 服务器超过 3 小时就发出通知</string>
|
||||
<string name="settings_advanced_connection_alert_summary_twelve_hours">如果无法连接到 ntfy 服务器超过 12 小时就发出通知</string>
|
||||
<string name="settings_advanced_connection_alert_never">永不</string>
|
||||
<string name="settings_advanced_connection_alert_five_minutes">5 分钟后</string>
|
||||
<string name="settings_advanced_connection_alert_fifteen_minutes">15 分钟后</string>
|
||||
<string name="settings_advanced_connection_alert_one_hour">1 小时后</string>
|
||||
<string name="settings_advanced_connection_alert_three_hours">3 小时后</string>
|
||||
<string name="settings_advanced_connection_alert_twelve_hours">12 小时后</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -471,4 +471,9 @@
|
|||
<string name="detail_menu_search_hint">通知中的搜尋</string>
|
||||
<string name="common_button_reset_to_default">重設為預設值</string>
|
||||
<string name="default_server_dialog_url_error_invalid">請輸入有效的服務 URL,例如:https://ntfy.example.com</string>
|
||||
<string name="connection_alert_title">連線已中斷</string>
|
||||
<string name="connection_alert_text_one">超過 %2$d 分鐘無法連線至 %1$s</string>
|
||||
<string name="connection_alert_text_multiple">超過 %2$d 分鐘無法連線至 %1$d 個伺服器</string>
|
||||
<string name="connection_alert_action_snooze">延後 %1$d 小時</string>
|
||||
<string name="connection_alert_action_never">永不顯示</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
<!-- Notification channels -->
|
||||
<string name="channel_notifications_group_default_name">Default</string>
|
||||
<string name="channel_subscriber_service_name">Subscription Service</string>
|
||||
<string name="channel_subscriber_service_name">Background service</string>
|
||||
<string name="channel_connection_alert_name">Connection alerts</string>
|
||||
<string name="channel_subscriber_notification_title">Listening for incoming notifications</string>
|
||||
<string name="channel_subscriber_notification_instant_text">Subscribed to instant delivery topics</string>
|
||||
<string name="channel_subscriber_notification_instant_text_one">Subscribed to one instant delivery topic</string>
|
||||
|
|
@ -49,10 +50,10 @@
|
|||
|
||||
<!-- Connection alert notification -->
|
||||
<string name="connection_alert_title">Connection lost</string>
|
||||
<string name="connection_alert_text_one">Unable to connect to %1$s for more than %2$d minutes</string>
|
||||
<string name="connection_alert_text_multiple">Unable to connect to %1$d servers for more than %2$d minutes</string>
|
||||
<string name="connection_alert_action_dismiss">Dismiss</string>
|
||||
<string name="connection_alert_action_snooze">Snooze 1h</string>
|
||||
<string name="connection_alert_text_one">Unable to connect to %1$s for more than %2$d minutes. Check your network connection.</string>
|
||||
<string name="connection_alert_text_multiple">Unable to connect to %1$d servers for more than %2$d minutes. Check your network connection.</string>
|
||||
<!-- %1$d is the snooze duration in hours, currently set to 8 -->
|
||||
<string name="connection_alert_action_snooze">Snooze %1$dh</string>
|
||||
<string name="connection_alert_action_never">Never show</string>
|
||||
|
||||
<!-- Common refresh toasts -->
|
||||
|
|
@ -115,6 +116,7 @@
|
|||
<string name="main_banner_websocket_reconnect_button_remind_later">Ask later</string>
|
||||
<string name="main_banner_websocket_reconnect_button_dismiss">Dismiss</string>
|
||||
<string name="main_banner_websocket_reconnect_button_enable_now">Grant now</string>
|
||||
<string name="main_banner_no_network_text">You\'re offline</string>
|
||||
|
||||
<!-- Add dialog -->
|
||||
<string name="add_dialog_title">Subscribe to topic</string>
|
||||
|
|
@ -415,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>
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
<string name="detail_settings_notifications_min_priority_key" translatable="false">SubscriptionMinPriority</string>
|
||||
<string name="detail_settings_notifications_auto_delete_key" translatable="false">SubscriptionAutoDelete</string>
|
||||
<string name="detail_settings_notifications_insistent_max_priority_key" translatable="false">SubscriptionInsistentMaxPriority</string>
|
||||
<string name="settings_advanced_connection_alert_key" translatable="false">ConnectionAlert</string>
|
||||
<string name="detail_settings_appearance_header_key" translatable="false">SubscriptionAppearance</string>
|
||||
<string name="detail_settings_appearance_icon_set_key" translatable="false">SubscriptionIconSet</string>
|
||||
<string name="detail_settings_appearance_icon_remove_key" translatable="false">SubscriptionIconRemove</string>
|
||||
|
|
@ -167,6 +168,22 @@
|
|||
<item>1</item>
|
||||
<item>0</item>
|
||||
</string-array>
|
||||
<string-array name="settings_advanced_connection_alert_entries">
|
||||
<item>@string/settings_advanced_connection_alert_never</item>
|
||||
<item>@string/settings_advanced_connection_alert_five_minutes</item>
|
||||
<item>@string/settings_advanced_connection_alert_fifteen_minutes</item>
|
||||
<item>@string/settings_advanced_connection_alert_one_hour</item>
|
||||
<item>@string/settings_advanced_connection_alert_three_hours</item>
|
||||
<item>@string/settings_advanced_connection_alert_twelve_hours</item>
|
||||
</string-array>
|
||||
<string-array name="settings_advanced_connection_alert_values">
|
||||
<item>0</item>
|
||||
<item>300</item>
|
||||
<item>900</item>
|
||||
<item>3600</item>
|
||||
<item>10800</item>
|
||||
<item>43200</item>
|
||||
</string-array>
|
||||
<string-array name="settings_advanced_connection_protocol_entries">
|
||||
<item>@string/settings_advanced_connection_protocol_entry_jsonhttp</item>
|
||||
<item>@string/settings_advanced_connection_protocol_entry_ws</item>
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@
|
|||
<paths>
|
||||
<external-path name="external_files" path="."/>
|
||||
<cache-path name="cache_files" path="."/>
|
||||
<files-path name="files" path="."/>
|
||||
</paths>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,12 @@
|
|||
app:summary="@string/settings_backup_restore_restore_summary"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory app:title="@string/settings_advanced_header">
|
||||
<ListPreference
|
||||
app:key="@string/settings_advanced_connection_alert_key"
|
||||
app:title="@string/settings_advanced_connection_alert_title"
|
||||
app:entries="@array/settings_advanced_connection_alert_entries"
|
||||
app:entryValues="@array/settings_advanced_connection_alert_values"
|
||||
app:defaultValue="0"/>
|
||||
<ListPreference
|
||||
app:key="@string/settings_advanced_connection_protocol_key"
|
||||
app:title="@string/settings_advanced_connection_protocol_title"
|
||||
|
|
|
|||
7
fastlane/metadata/android/en-US/changelog/NEXT.txt
Normal file
7
fastlane/metadata/android/en-US/changelog/NEXT.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Features:
|
||||
* Add configurable "Alert when connection is lost" setting (#1665, #1662, #1652, #1655, thanks to @tintamarre, @sjozs, @TheRealOne78, and @DAE51D for reporting)
|
||||
* Suppress connection alerts and stop foreground service when there is no network (ntfy-android#165, thanks to @tintamarre for the contribution)
|
||||
|
||||
Bug fixes + maintenance:
|
||||
* Undo automatic phone number linking for numbers in message body (ntfy-android#170, thanks to @acortelyou for the contribution)
|
||||
* Fix subscription icons disappearing after a few days due to Android clearing cache (#1322, thanks to @mcanning for reporting)
|
||||
|
|
@ -1 +1 @@
|
|||
ntfy - PUT/POST ao seu disp.
|
||||
ntfy - PUT/POST ao dispositivo
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue