Merge branch 'main' into 236-android-action-buttons

This commit is contained in:
Philipp Heckel 2022-06-24 12:49:19 -04:00
commit b48cbcd19d
26 changed files with 231 additions and 48 deletions

View file

@ -2,11 +2,11 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 12, "version": 12,
"identityHash": "b439720b55cf5e6bfdec2b56dd46103d", "identityHash": "9363ad5196e88862acceb1bb9ee91124",
"entities": [ "entities": [
{ {
"tableName": "Subscription", "tableName": "Subscription",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `baseUrl` TEXT NOT NULL, `topic` TEXT NOT NULL, `instant` INTEGER NOT NULL, `mutedUntil` INTEGER NOT NULL, `minPriority` INTEGER NOT NULL, `autoDelete` INTEGER NOT NULL, `lastNotificationId` TEXT, `icon` TEXT, `upAppId` TEXT, `upConnectorToken` TEXT, PRIMARY KEY(`id`))", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `baseUrl` TEXT NOT NULL, `topic` TEXT NOT NULL, `instant` INTEGER NOT NULL, `mutedUntil` INTEGER NOT NULL, `minPriority` INTEGER NOT NULL, `autoDelete` INTEGER NOT NULL, `lastNotificationId` TEXT, `icon` TEXT, `upAppId` TEXT, `upConnectorToken` TEXT, `displayName` TEXT, PRIMARY KEY(`id`))",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -73,6 +73,12 @@
"columnName": "upConnectorToken", "columnName": "upConnectorToken",
"affinity": "TEXT", "affinity": "TEXT",
"notNull": false "notNull": false
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
} }
], ],
"primaryKey": { "primaryKey": {
@ -320,7 +326,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b439720b55cf5e6bfdec2b56dd46103d')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9363ad5196e88862acceb1bb9ee91124')"
] ]
} }
} }

View file

@ -100,7 +100,8 @@ class Backuper(val context: Context) {
lastNotificationId = s.lastNotificationId, lastNotificationId = s.lastNotificationId,
icon = s.icon, icon = s.icon,
upAppId = s.upAppId, upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
)) ))
} catch (e: Exception) { } catch (e: Exception) {
Log.w(TAG, "Unable to restore subscription ${s.id} (${topicUrl(s.baseUrl, s.topic)}): ${e.message}. Ignoring.", e) Log.w(TAG, "Unable to restore subscription ${s.id} (${topicUrl(s.baseUrl, s.topic)}): ${e.message}. Ignoring.", e)
@ -224,7 +225,8 @@ class Backuper(val context: Context) {
lastNotificationId = s.lastNotificationId, lastNotificationId = s.lastNotificationId,
icon = s.icon, icon = s.icon,
upAppId = s.upAppId, upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken upConnectorToken = s.upConnectorToken,
displayName = s.displayName
) )
} }
} }
@ -331,7 +333,8 @@ data class Subscription(
val lastNotificationId: String?, val lastNotificationId: String?,
val icon: String?, val icon: String?,
val upAppId: String?, val upAppId: String?,
val upConnectorToken: String? val upConnectorToken: String?,
val displayName: String?
) )
data class Notification( data class Notification(

View file

@ -22,13 +22,14 @@ data class Subscription(
@ColumnInfo(name = "icon") val icon: String?, // content://-URI (or later other identifier) @ColumnInfo(name = "icon") val icon: String?, // content://-URI (or later other identifier)
@ColumnInfo(name = "upAppId") val upAppId: String?, // UnifiedPush application package name @ColumnInfo(name = "upAppId") val upAppId: String?, // UnifiedPush application package name
@ColumnInfo(name = "upConnectorToken") val upConnectorToken: String?, // UnifiedPush connector token @ColumnInfo(name = "upConnectorToken") val upConnectorToken: String?, // UnifiedPush connector token
@ColumnInfo(name = "displayName") val displayName: String?,
@Ignore val totalCount: Int = 0, // Total notifications @Ignore val totalCount: Int = 0, // Total notifications
@Ignore val newCount: Int = 0, // New notifications @Ignore val newCount: Int = 0, // New notifications
@Ignore val lastActive: Long = 0, // Unix timestamp @Ignore val lastActive: Long = 0, // Unix timestamp
@Ignore val state: ConnectionState = ConnectionState.NOT_APPLICABLE @Ignore val state: ConnectionState = ConnectionState.NOT_APPLICABLE
) { ) {
constructor(id: Long, baseUrl: String, topic: String, instant: Boolean, mutedUntil: Long, minPriority: Int, autoDelete: Long, lastNotificationId: String, icon: String, upAppId: String, upConnectorToken: String) : constructor(id: Long, baseUrl: String, topic: String, instant: Boolean, mutedUntil: Long, minPriority: Int, autoDelete: Long, lastNotificationId: String, icon: String, upAppId: String, upConnectorToken: String, displayName: String?) :
this(id, baseUrl, topic, instant, mutedUntil, minPriority, autoDelete, lastNotificationId, icon, upAppId, upConnectorToken, 0, 0, 0, ConnectionState.NOT_APPLICABLE) this(id, baseUrl, topic, instant, mutedUntil, minPriority, autoDelete, lastNotificationId, icon, upAppId, upConnectorToken, displayName, 0, 0, 0, ConnectionState.NOT_APPLICABLE)
} }
enum class ConnectionState { enum class ConnectionState {
@ -47,6 +48,7 @@ data class SubscriptionWithMetadata(
val icon: String?, val icon: String?,
val upAppId: String?, val upAppId: String?,
val upConnectorToken: String?, val upConnectorToken: String?,
val displayName: String?,
val totalCount: Int, val totalCount: Int,
val newCount: Int, val newCount: Int,
val lastActive: Long val lastActive: Long
@ -266,6 +268,7 @@ abstract class Database : RoomDatabase() {
private val MIGRATION_11_12 = object : Migration(11, 12) { private val MIGRATION_11_12 = object : Migration(11, 12) {
override fun migrate(db: SupportSQLiteDatabase) { override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE Subscription ADD COLUMN lastNotificationId TEXT") db.execSQL("ALTER TABLE Subscription ADD COLUMN lastNotificationId TEXT")
db.execSQL("ALTER TABLE Subscription ADD COLUMN displayName TEXT")
} }
} }
} }
@ -275,7 +278,7 @@ abstract class Database : RoomDatabase() {
interface SubscriptionDao { interface SubscriptionDao {
@Query(""" @Query("""
SELECT SELECT
s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName,
COUNT(n.id) totalCount, COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount, COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive IFNULL(MAX(n.timestamp),0) AS lastActive
@ -288,7 +291,7 @@ interface SubscriptionDao {
@Query(""" @Query("""
SELECT SELECT
s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName,
COUNT(n.id) totalCount, COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount, COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive IFNULL(MAX(n.timestamp),0) AS lastActive
@ -301,7 +304,7 @@ interface SubscriptionDao {
@Query(""" @Query("""
SELECT SELECT
s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName,
COUNT(n.id) totalCount, COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount, COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive IFNULL(MAX(n.timestamp),0) AS lastActive
@ -314,7 +317,7 @@ interface SubscriptionDao {
@Query(""" @Query("""
SELECT SELECT
s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName,
COUNT(n.id) totalCount, COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount, COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive IFNULL(MAX(n.timestamp),0) AS lastActive
@ -327,7 +330,7 @@ interface SubscriptionDao {
@Query(""" @Query("""
SELECT SELECT
s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName,
COUNT(n.id) totalCount, COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount, COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive IFNULL(MAX(n.timestamp),0) AS lastActive

View file

@ -384,6 +384,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
icon = s.icon, icon = s.icon,
upAppId = s.upAppId, upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken, upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
totalCount = s.totalCount, totalCount = s.totalCount,
newCount = s.newCount, newCount = s.newCount,
lastActive = s.lastActive, lastActive = s.lastActive,
@ -408,6 +409,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
icon = s.icon, icon = s.icon,
upAppId = s.upAppId, upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken, upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
totalCount = s.totalCount, totalCount = s.totalCount,
newCount = s.newCount, newCount = s.newCount,
lastActive = s.lastActive, lastActive = s.lastActive,

View file

@ -300,6 +300,7 @@ class NotificationService(val context: Context) {
putExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, subscription.id) putExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, subscription.id)
putExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl) putExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl)
putExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC, subscription.topic) putExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC, subscription.topic)
putExtra(MainActivity.EXTRA_SUBSCRIPTION_DISPLAY_NAME, displayName(subscription))
putExtra(MainActivity.EXTRA_SUBSCRIPTION_INSTANT, subscription.instant) putExtra(MainActivity.EXTRA_SUBSCRIPTION_INSTANT, subscription.instant)
putExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil) putExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil)
} }

View file

@ -54,6 +54,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
private var subscriptionId: Long = 0L // Set in onCreate() private var subscriptionId: Long = 0L // Set in onCreate()
private var subscriptionBaseUrl: String = "" // Set in onCreate() private var subscriptionBaseUrl: String = "" // Set in onCreate()
private var subscriptionTopic: String = "" // Set in onCreate() private var subscriptionTopic: String = "" // Set in onCreate()
private var subscriptionDisplayName: String = "" // Set in onCreate() & updated by options menu!
private var subscriptionInstant: Boolean = false // Set in onCreate() & updated by options menu! private var subscriptionInstant: Boolean = false // Set in onCreate() & updated by options menu!
private var subscriptionMutedUntil: Long = 0L // Set in onCreate() & updated by options menu! private var subscriptionMutedUntil: Long = 0L // Set in onCreate() & updated by options menu!
@ -116,6 +117,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
icon = null, icon = null,
upAppId = null, upAppId = null,
upConnectorToken = null, upConnectorToken = null,
displayName = null,
totalCount = 0, totalCount = 0,
newCount = 0, newCount = 0,
lastActive = Date().time/1000 lastActive = Date().time/1000
@ -147,6 +149,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, subscription.id) intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, subscription.id)
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl) intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl)
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC, subscription.topic) intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC, subscription.topic)
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_DISPLAY_NAME, displayName(subscription))
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_INSTANT, subscription.instant) intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_INSTANT, subscription.instant)
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil) intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil)
@ -161,13 +164,14 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
subscriptionId = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, 0) subscriptionId = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, 0)
subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return
subscriptionTopic = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC) ?: return subscriptionTopic = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_TOPIC) ?: return
subscriptionDisplayName = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_DISPLAY_NAME) ?: return
subscriptionInstant = intent.getBooleanExtra(MainActivity.EXTRA_SUBSCRIPTION_INSTANT, false) subscriptionInstant = intent.getBooleanExtra(MainActivity.EXTRA_SUBSCRIPTION_INSTANT, false)
subscriptionMutedUntil = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, 0L) subscriptionMutedUntil = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, 0L)
// Set title // Set title
val subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return val subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return
val topicUrl = topicShortUrl(subscriptionBaseUrl, subscriptionTopic) val topicUrl = topicShortUrl(subscriptionBaseUrl, subscriptionTopic)
title = topicUrl title = subscriptionDisplayName
// Set "how to instructions" // Set "how to instructions"
val howToExample: TextView = findViewById(R.id.detail_how_to_example) val howToExample: TextView = findViewById(R.id.detail_how_to_example)
@ -263,9 +267,11 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
val subscription = repository.getSubscription(subscriptionId) ?: return@launch val subscription = repository.getSubscription(subscriptionId) ?: return@launch
subscriptionInstant = subscription.instant subscriptionInstant = subscription.instant
subscriptionMutedUntil = subscription.mutedUntil subscriptionMutedUntil = subscription.mutedUntil
subscriptionDisplayName = displayName(subscription)
showHideInstantMenuItems(subscriptionInstant) showHideInstantMenuItems(subscriptionInstant)
showHideMutedUntilMenuItems(subscriptionMutedUntil) showHideMutedUntilMenuItems(subscriptionMutedUntil)
updateTitle(subscriptionDisplayName)
} }
} }
@ -543,6 +549,12 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
} }
} }
private fun updateTitle(subscriptionDisplayName: String) {
runOnUiThread {
title = subscriptionDisplayName
}
}
private fun onClearClick() { private fun onClearClick() {
Log.d(TAG, "Clearing all notifications for ${topicShortUrl(subscriptionBaseUrl, subscriptionTopic)}") Log.d(TAG, "Clearing all notifications for ${topicShortUrl(subscriptionBaseUrl, subscriptionTopic)}")
@ -571,6 +583,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
intent.putExtra(EXTRA_SUBSCRIPTION_ID, subscriptionId) intent.putExtra(EXTRA_SUBSCRIPTION_ID, subscriptionId)
intent.putExtra(EXTRA_SUBSCRIPTION_BASE_URL, subscriptionBaseUrl) intent.putExtra(EXTRA_SUBSCRIPTION_BASE_URL, subscriptionBaseUrl)
intent.putExtra(EXTRA_SUBSCRIPTION_TOPIC, subscriptionTopic) intent.putExtra(EXTRA_SUBSCRIPTION_TOPIC, subscriptionTopic)
intent.putExtra(EXTRA_SUBSCRIPTION_DISPLAY_NAME, subscriptionDisplayName)
startActivity(intent) startActivity(intent)
} }
@ -747,5 +760,6 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
const val EXTRA_SUBSCRIPTION_ID = "subscriptionId" const val EXTRA_SUBSCRIPTION_ID = "subscriptionId"
const val EXTRA_SUBSCRIPTION_BASE_URL = "baseUrl" const val EXTRA_SUBSCRIPTION_BASE_URL = "baseUrl"
const val EXTRA_SUBSCRIPTION_TOPIC = "topic" const val EXTRA_SUBSCRIPTION_TOPIC = "topic"
const val EXTRA_SUBSCRIPTION_DISPLAY_NAME = "displayName"
} }
} }

View file

@ -4,6 +4,7 @@ import android.content.ContentResolver
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
@ -55,9 +56,8 @@ class DetailSettingsActivity : AppCompatActivity() {
} }
// Title // Title
val baseUrl = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return val displayName = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_DISPLAY_NAME) ?: return
val topic = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_TOPIC) ?: return title = displayName
title = topicShortUrl(baseUrl, topic)
// Show 'Back' button // Show 'Back' button
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
@ -108,6 +108,7 @@ class DetailSettingsActivity : AppCompatActivity() {
loadAutoDeletePref() loadAutoDeletePref()
loadIconSetPref() loadIconSetPref()
loadIconRemovePref() loadIconRemovePref()
loadDisplayNamePref()
} }
private fun loadInstantPref() { private fun loadInstantPref() {
@ -276,6 +277,40 @@ class DetailSettingsActivity : AppCompatActivity() {
} }
} }
private fun loadDisplayNamePref() {
val prefId = context?.getString(R.string.detail_settings_appearance_display_name_key) ?: return
val pref: EditTextPreference? = findPreference(prefId)
pref?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
pref?.text = subscription.displayName
pref?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
val displayName: String? = if (value == "") {
null
} else {
value
}
val newSubscription = subscription.copy(displayName = displayName)
save(newSubscription)
activity?.runOnUiThread {
activity?.title = displayName(newSubscription)
}
}
override fun getString(key: String?, defValue: String?): String {
return subscription.displayName ?: ""
}
}
pref?.summaryProvider = Preference.SummaryProvider<EditTextPreference> { provider ->
if (TextUtils.isEmpty(provider.text)) {
getString(
R.string.detail_settings_appearance_display_name_default_summary,
displayName(subscription)
)
} else {
provider.text
}
}
}
private fun createIconPickLauncher(): ActivityResultLauncher<String> { private fun createIconPickLauncher(): ActivityResultLauncher<String> {
return registerForActivityResult(ActivityResultContracts.GetContent()) { inputUri -> return registerForActivityResult(ActivityResultContracts.GetContent()) { inputUri ->
if (inputUri == null) { if (inputUri == null) {

View file

@ -438,6 +438,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
icon = null, icon = null,
upAppId = null, upAppId = null,
upConnectorToken = null, upConnectorToken = null,
displayName = null,
totalCount = 0, totalCount = 0,
newCount = 0, newCount = 0,
lastActive = Date().time/1000 lastActive = Date().time/1000
@ -509,7 +510,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
val topic = topicShortUrl(subscription.baseUrl, subscription.topic) val topic = displayName(subscription)
if (errorMessage == "") errorMessage = "$topic: ${e.message}" if (errorMessage == "") errorMessage = "$topic: ${e.message}"
errors++ errors++
} }
@ -536,6 +537,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
intent.putExtra(EXTRA_SUBSCRIPTION_ID, subscription.id) intent.putExtra(EXTRA_SUBSCRIPTION_ID, subscription.id)
intent.putExtra(EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl) intent.putExtra(EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl)
intent.putExtra(EXTRA_SUBSCRIPTION_TOPIC, subscription.topic) intent.putExtra(EXTRA_SUBSCRIPTION_TOPIC, subscription.topic)
intent.putExtra(EXTRA_SUBSCRIPTION_DISPLAY_NAME, displayName(subscription))
intent.putExtra(EXTRA_SUBSCRIPTION_INSTANT, subscription.instant) intent.putExtra(EXTRA_SUBSCRIPTION_INSTANT, subscription.instant)
intent.putExtra(EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil) intent.putExtra(EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil)
startActivity(intent) startActivity(intent)
@ -662,6 +664,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
const val EXTRA_SUBSCRIPTION_ID = "subscriptionId" const val EXTRA_SUBSCRIPTION_ID = "subscriptionId"
const val EXTRA_SUBSCRIPTION_BASE_URL = "subscriptionBaseUrl" const val EXTRA_SUBSCRIPTION_BASE_URL = "subscriptionBaseUrl"
const val EXTRA_SUBSCRIPTION_TOPIC = "subscriptionTopic" const val EXTRA_SUBSCRIPTION_TOPIC = "subscriptionTopic"
const val EXTRA_SUBSCRIPTION_DISPLAY_NAME = "subscriptionDisplayName"
const val EXTRA_SUBSCRIPTION_INSTANT = "subscriptionInstant" const val EXTRA_SUBSCRIPTION_INSTANT = "subscriptionInstant"
const val EXTRA_SUBSCRIPTION_MUTED_UNTIL = "subscriptionMutedUntil" const val EXTRA_SUBSCRIPTION_MUTED_UNTIL = "subscriptionMutedUntil"
const val ANIMATION_DURATION = 80L const val ANIMATION_DURATION = 80L

View file

@ -20,7 +20,7 @@ import io.heckel.ntfy.db.Subscription
import io.heckel.ntfy.msg.NotificationService import io.heckel.ntfy.msg.NotificationService
import io.heckel.ntfy.util.Log import io.heckel.ntfy.util.Log
import io.heckel.ntfy.util.readBitmapFromUriOrNull import io.heckel.ntfy.util.readBitmapFromUriOrNull
import io.heckel.ntfy.util.topicShortUrl import io.heckel.ntfy.util.displayName
import java.text.DateFormat import java.text.DateFormat
import java.util.* import java.util.*
@ -101,7 +101,7 @@ class MainAdapter(private val repository: Repository, private val onClick: (Subs
if (subscription.icon != null) { if (subscription.icon != null) {
imageView.setImageBitmap(subscription.icon.readBitmapFromUriOrNull(context)) imageView.setImageBitmap(subscription.icon.readBitmapFromUriOrNull(context))
} }
nameView.text = topicShortUrl(subscription.baseUrl, subscription.topic) nameView.text = displayName(subscription)
statusView.text = statusMessage statusView.text = statusMessage
dateView.text = dateText dateView.text = dateText
dateView.visibility = if (isUnifiedPush) View.GONE else View.VISIBLE dateView.visibility = if (isUnifiedPush) View.GONE else View.VISIBLE

View file

@ -79,6 +79,7 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
icon = null, icon = null,
upAppId = appId, upAppId = appId,
upConnectorToken = connectorToken, upConnectorToken = connectorToken,
displayName = null,
totalCount = 0, totalCount = 0,
newCount = 0, newCount = 0,
lastActive = Date().time/1000 lastActive = Date().time/1000

View file

@ -53,6 +53,10 @@ fun topicUrlAuth(baseUrl: String, topic: String) = "${topicUrl(baseUrl, topic)}/
fun topicUrlJsonPoll(baseUrl: String, topic: String, since: String) = "${topicUrl(baseUrl, topic)}/json?poll=1&since=$since" fun topicUrlJsonPoll(baseUrl: String, topic: String, since: String) = "${topicUrl(baseUrl, topic)}/json?poll=1&since=$since"
fun topicShortUrl(baseUrl: String, topic: String) = shortUrl(topicUrl(baseUrl, topic)) fun topicShortUrl(baseUrl: String, topic: String) = shortUrl(topicUrl(baseUrl, topic))
fun displayName(subscription: Subscription) : String {
return subscription.displayName ?: topicShortUrl(subscription.baseUrl, subscription.topic)
}
fun shortUrl(url: String) = url fun shortUrl(url: String) = url
.replace("http://", "") .replace("http://", "")
.replace("https://", "") .replace("https://", "")
@ -176,7 +180,7 @@ fun formatTitle(subscription: Subscription, notification: Notification): String
return if (notification.title != "") { return if (notification.title != "") {
formatTitle(notification) formatTitle(notification)
} else { } else {
topicShortUrl(subscription.baseUrl, subscription.topic) displayName(subscription)
} }
} }

View file

@ -174,7 +174,7 @@
<string name="settings_general_users_prefs_user_add_title">Добавяне на потребител</string> <string name="settings_general_users_prefs_user_add_title">Добавяне на потребител</string>
<string name="settings_advanced_header">Разширени</string> <string name="settings_advanced_header">Разширени</string>
<string name="user_dialog_button_cancel">Отказ</string> <string name="user_dialog_button_cancel">Отказ</string>
<string name="settings_advanced_connection_protocol_summary_ws">Използвайте WebSockets за свързване със сървъра. Това е експериментална възможност. Дайте ни обратна връзка дали се изразходва по-малко батерия или е нестабилна.</string> <string name="settings_advanced_connection_protocol_summary_ws">Използва се WebSockets за свързване със сървъра. Това е препоръчителния метод, но могат да се наложат настройки на сървъра за прокси.</string>
<string name="settings_advanced_export_logs_title">Копиране или изпращане на дневник</string> <string name="settings_advanced_export_logs_title">Копиране или изпращане на дневник</string>
<string name="settings_advanced_export_logs_entry_copy_original">Копиране в междинната памет</string> <string name="settings_advanced_export_logs_entry_copy_original">Копиране в междинната памет</string>
<string name="settings_advanced_export_logs_scrub_dialog_button_ok">Добре</string> <string name="settings_advanced_export_logs_scrub_dialog_button_ok">Добре</string>
@ -183,7 +183,7 @@
<string name="settings_notifications_auto_delete_three_months">След три месеца</string> <string name="settings_notifications_auto_delete_three_months">След три месеца</string>
<string name="settings_notifications_auto_delete_one_month">След един месец</string> <string name="settings_notifications_auto_delete_one_month">След един месец</string>
<string name="settings_advanced_export_logs_entry_copy_scrubbed">Копиране в междинната памет (цензурирано)</string> <string name="settings_advanced_export_logs_entry_copy_scrubbed">Копиране в междинната памет (цензурирано)</string>
<string name="settings_advanced_connection_protocol_summary_jsonhttp">За свързване със сървъра се използва поток от JSON през HTTP. Методът е остарял и ще бъде премахнат през месец юни 2022 год.</string> <string name="settings_advanced_connection_protocol_summary_jsonhttp">За свързване със сървъра се използва поток от JSON през HTTP. Методът е изпитан, но може да използва повече батерия.</string>
<string name="detail_test_message">Това е пробно известие от приложението ntfy за Android. То е с приоритет %1$d. Ако изпратите друго, то може да изглежда по различен начин.</string> <string name="detail_test_message">Това е пробно известие от приложението ntfy за Android. То е с приоритет %1$d. Ако изпратите друго, то може да изглежда по различен начин.</string>
<string name="detail_test_title">Проба: Ако желаете можете да сложите заглавие</string> <string name="detail_test_title">Проба: Ако желаете можете да сложите заглавие</string>
<string name="detail_test_message_error_unauthorized_user">Грешка при изпращане: Потребителят „%1$s“ няма достъп.</string> <string name="detail_test_message_error_unauthorized_user">Грешка при изпращане: Потребителят „%1$s“ няма достъп.</string>
@ -319,4 +319,6 @@
<string name="detail_settings_global_setting_suffix">от общите настройки</string> <string name="detail_settings_global_setting_suffix">от общите настройки</string>
<string name="add_dialog_base_urls_dropdown_choose">Изберете адрес на услугата</string> <string name="add_dialog_base_urls_dropdown_choose">Изберете адрес на услугата</string>
<string name="add_dialog_base_urls_dropdown_clear">Изчистване на адреса на услугата</string> <string name="add_dialog_base_urls_dropdown_clear">Изчистване на адреса на услугата</string>
<string name="main_banner_websocket_text">WebSockets е препоръчителния начин за свързване с услугата и може да подобри използването на батерията, но могат да се наложат <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">допълнителни настройки на сървъра за прокси</a>. Промяната може да бъде направена в настройките.</string>
<string name="main_banner_websocket_button_enable_now">Включване</string>
</resources> </resources>

View file

@ -211,9 +211,9 @@
<string name="settings_advanced_clear_logs_summary">Vorhandene Logs löschen und neu beginnen</string> <string name="settings_advanced_clear_logs_summary">Vorhandene Logs löschen und neu beginnen</string>
<string name="settings_advanced_clear_logs_deleted_toast">Logs gelöscht</string> <string name="settings_advanced_clear_logs_deleted_toast">Logs gelöscht</string>
<string name="settings_advanced_connection_protocol_title">Verbindungs-Protokoll</string> <string name="settings_advanced_connection_protocol_title">Verbindungs-Protokoll</string>
<string name="settings_advanced_connection_protocol_summary_jsonhttp">JSON-over-HTTP-Stream für die Serververbindung nutzen. Diese Methode ist veraltet und wird im Juni 2022 entfernt.</string> <string name="settings_advanced_connection_protocol_summary_jsonhttp">JSON-over-HTTP-Stream für die Serververbindung nutzen. Diese Methode ist bewährt, benötigt aber evtl. mehr Akku.</string>
<string name="settings_advanced_broadcast_title">Nachrichten broadcasten</string> <string name="settings_advanced_broadcast_title">Nachrichten broadcasten</string>
<string name="settings_advanced_connection_protocol_summary_ws">WebSockets für die Server-Verbindung nutzen. Diese Methode wird im Juni 2022 der Standard.</string> <string name="settings_advanced_connection_protocol_summary_ws">WebSockets für die Server-Verbindung nutzen. Diese Methode wird empfohlen, benötigt aber evtl. zusätzliche Konfiguration in Deinem Proxy.</string>
<string name="settings_advanced_connection_protocol_entry_jsonhttp">JSON-over-HTTP-Stream</string> <string name="settings_advanced_connection_protocol_entry_jsonhttp">JSON-over-HTTP-Stream</string>
<string name="settings_advanced_connection_protocol_entry_ws">WebSockets</string> <string name="settings_advanced_connection_protocol_entry_ws">WebSockets</string>
<string name="settings_about_header">Über</string> <string name="settings_about_header">Über</string>
@ -317,4 +317,8 @@
<string name="detail_settings_notifications_instant_title">Sofortnachrichten</string> <string name="detail_settings_notifications_instant_title">Sofortnachrichten</string>
<string name="detail_settings_appearance_icon_remove_summary">Icon, das in Benachrichtigungen zu diesem Thema angezeigt wird</string> <string name="detail_settings_appearance_icon_remove_summary">Icon, das in Benachrichtigungen zu diesem Thema angezeigt wird</string>
<string name="detail_settings_notifications_instant_summary_on">Benachrichtigungen werden sofort zugestellt. Benötigt einen Vordergrund-Dienst und verbraucht mehr Akku.</string> <string name="detail_settings_notifications_instant_summary_on">Benachrichtigungen werden sofort zugestellt. Benötigt einen Vordergrund-Dienst und verbraucht mehr Akku.</string>
<string name="main_banner_websocket_text">Der Umstieg auf WebSockets ist die empfohlene Verbindungsweise zu Deinem Server und benötigt möglicherweise weniger Akkuleistung. Es könnte aber eine <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">zusätzliche Konfiguration im Proxy</a> nötig sein. Die Verbindungmethode kann in den Einstellungen gewählt werden.</string>
<string name="main_banner_websocket_button_enable_now">Jetzt aktivieren</string>
<string name="add_dialog_base_urls_dropdown_choose">Service-URL wählen</string>
<string name="add_dialog_base_urls_dropdown_clear">Service-URL löschen</string>
</resources> </resources>

View file

@ -286,8 +286,8 @@
<string name="settings_advanced_export_logs_copied_logs">Journaux copiés dans le presse-papier</string> <string name="settings_advanced_export_logs_copied_logs">Journaux copiés dans le presse-papier</string>
<string name="settings_advanced_export_logs_summary">Copier les journaux dans le presse-papier ou les télécharger sur nopaste.net (détenu par l\'auteur de ntfy). Les noms d\'hôtes et les sujets peuvent être censurés, les notifications ne le seront jamais.</string> <string name="settings_advanced_export_logs_summary">Copier les journaux dans le presse-papier ou les télécharger sur nopaste.net (détenu par l\'auteur de ntfy). Les noms d\'hôtes et les sujets peuvent être censurés, les notifications ne le seront jamais.</string>
<string name="settings_advanced_export_logs_copied_url">Journaux téléchargés et URL copiée</string> <string name="settings_advanced_export_logs_copied_url">Journaux téléchargés et URL copiée</string>
<string name="settings_advanced_connection_protocol_summary_jsonhttp">Utiliser un flux JSON en HTTP pour se connecter au serveur. Cette méthode est dépréciée et sera retirée en juin 2022.</string> <string name="settings_advanced_connection_protocol_summary_jsonhttp">Utiliser un flux JSON en HTTP pour se connecter au serveur. Cette méthode est éprouvée, mais peut consommer plus de batterie.</string>
<string name="settings_advanced_connection_protocol_summary_ws">Utiliser des WebSockets pour se connecter au serveur. Cela deviendra la valeur par défaut en juin 2022.</string> <string name="settings_advanced_connection_protocol_summary_ws">Utiliser des WebSockets pour se connecter au serveur. Il s\'agit de la méthode recommandée, mais peut requérir une configuration supplémentaire de votre proxy.</string>
<string name="settings_about_version_copied_to_clipboard_message">Copié dans le presse-papier</string> <string name="settings_about_version_copied_to_clipboard_message">Copié dans le presse-papier</string>
<string name="settings_advanced_record_logs_title">Enregistrer les journaux</string> <string name="settings_advanced_record_logs_title">Enregistrer les journaux</string>
<string name="user_dialog_description_add">Vous pouvez ajouter un utilisateur ici. Tous les sujets du serveur sélectionné utiliseront cet utilisateur.</string> <string name="user_dialog_description_add">Vous pouvez ajouter un utilisateur ici. Tous les sujets du serveur sélectionné utiliseront cet utilisateur.</string>
@ -317,4 +317,8 @@
<string name="detail_settings_appearance_icon_set_summary">Choisir une icône à afficher pour les notifications</string> <string name="detail_settings_appearance_icon_set_summary">Choisir une icône à afficher pour les notifications</string>
<string name="detail_settings_global_setting_title">Utiliser le paramètre global</string> <string name="detail_settings_global_setting_title">Utiliser le paramètre global</string>
<string name="detail_settings_global_setting_suffix">utilisation du paramètre global</string> <string name="detail_settings_global_setting_suffix">utilisation du paramètre global</string>
<string name="main_banner_websocket_text">Il est recommandé d\'utiliser les WebSockets pour vous connecter à votre serveur, ce qui peut également économiser la batterie, mais peut requérir <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">une configuration additionnelle de votre proxy</a>. Cela peut être changé dans les paramètres.</string>
<string name="add_dialog_base_urls_dropdown_choose">Choisir l\'URL du service</string>
<string name="add_dialog_base_urls_dropdown_clear">Supprimer l\'URL du service</string>
<string name="main_banner_websocket_button_enable_now">Activer maintenant</string>
</resources> </resources>

View file

@ -198,8 +198,8 @@
<string name="settings_advanced_clear_logs_summary">Hapus catatan yang direkam sebelumnya, dan mulai ulang</string> <string name="settings_advanced_clear_logs_summary">Hapus catatan yang direkam sebelumnya, dan mulai ulang</string>
<string name="settings_advanced_clear_logs_deleted_toast">Catatan dihapus</string> <string name="settings_advanced_clear_logs_deleted_toast">Catatan dihapus</string>
<string name="settings_advanced_connection_protocol_title">Protokol koneksi</string> <string name="settings_advanced_connection_protocol_title">Protokol koneksi</string>
<string name="settings_advanced_connection_protocol_summary_jsonhttp">Gunakan aliran JSON melalui HTTP untuk menghubungkan ke server. Mode ini usang dan akan dihilangkan di Juni 2022.</string> <string name="settings_advanced_connection_protocol_summary_jsonhttp">Gunakan aliran JSON melalui HTTP untuk menyambung ke server. Metode ini sudah teruji, tetapi mungkin menghabiskan lebih banyak baterai.</string>
<string name="settings_advanced_connection_protocol_summary_ws">Gunakan WebSockets untuk menghubungkan ke server. Ini adalah sebagai bawaan di Juni 2022.</string> <string name="settings_advanced_connection_protocol_summary_ws">Gunakan WebSockets untuk menyambung ke server. Ini adalah metode yang disarankan, tetapi mungkin memerlukan konfigurasi tambahan dalam proksi Anda.</string>
<string name="settings_advanced_connection_protocol_entry_jsonhttp">Aliran JSON melalui HTTP</string> <string name="settings_advanced_connection_protocol_entry_jsonhttp">Aliran JSON melalui HTTP</string>
<string name="settings_advanced_connection_protocol_entry_ws">WebSockets</string> <string name="settings_advanced_connection_protocol_entry_ws">WebSockets</string>
<string name="settings_about_header">Tentang</string> <string name="settings_about_header">Tentang</string>
@ -306,8 +306,7 @@
<string name="channel_subscriber_notification_instant_text_six">Berlangganan ke enam topik pengiriman instan</string> <string name="channel_subscriber_notification_instant_text_six">Berlangganan ke enam topik pengiriman instan</string>
<string name="channel_subscriber_notification_noinstant_text_five">Berlangganan ke lima topik</string> <string name="channel_subscriber_notification_noinstant_text_five">Berlangganan ke lima topik</string>
<string name="channel_subscriber_notification_noinstant_text_six">Berlangganan ke enam topik</string> <string name="channel_subscriber_notification_noinstant_text_six">Berlangganan ke enam topik</string>
<string name="detail_settings_notifications_instant_summary_on">Notifikasi dikirim secara instan. <string name="detail_settings_notifications_instant_summary_on">Notifikasi dikirim secara instan. Membutuhkan sebuah layanan latar depan dan mengkonsumsi lebih banyak baterai.</string>
\nMembutuhkan sebuah layanan latar depan dan mengkonsumsi lebih banyak baterai.</string>
<string name="detail_settings_appearance_header">Tampilan</string> <string name="detail_settings_appearance_header">Tampilan</string>
<string name="detail_settings_appearance_icon_set_summary">Tetapkan sebuah ikon untuk ditampilkan di notifikasi</string> <string name="detail_settings_appearance_icon_set_summary">Tetapkan sebuah ikon untuk ditampilkan di notifikasi</string>
<string name="detail_settings_appearance_icon_remove_title">Ikon langganan (ketuk untuk menghapus)</string> <string name="detail_settings_appearance_icon_remove_title">Ikon langganan (ketuk untuk menghapus)</string>
@ -320,4 +319,6 @@
<string name="detail_settings_appearance_icon_set_title">Ikon langganan</string> <string name="detail_settings_appearance_icon_set_title">Ikon langganan</string>
<string name="add_dialog_base_urls_dropdown_choose">Pilih URL layanan</string> <string name="add_dialog_base_urls_dropdown_choose">Pilih URL layanan</string>
<string name="add_dialog_base_urls_dropdown_clear">Hapus URL layanan</string> <string name="add_dialog_base_urls_dropdown_clear">Hapus URL layanan</string>
<string name="main_banner_websocket_text">Beralih ke WebSockets adalah cara yang disarankan untuk terhubung ke server Anda, dan dapat meningkatkan masa pakai baterai, tetapi mungkin memerlukan <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">konfigurasi tambahan di proksi Anda</a>. Ini dapat diubah di Pengaturan.</string>
<string name="main_banner_websocket_button_enable_now">Aktifkan sekarang</string>
</resources> </resources>

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="channel_notifications_min_name">Notyfikacje (Minimalny Priorytet)</string> <string name="channel_notifications_min_name">Powiadomienia (minimalny priorytet)</string>
<string name="channel_notifications_low_name">Notyfikacje (Niski priorytet)</string> <string name="channel_notifications_low_name">Powiadomienia (niski priorytet)</string>
<string name="channel_notifications_default_name">Notyfikacje (domyślny priorytet)</string> <string name="channel_notifications_default_name">Powiadomienia (domyślny priorytet)</string>
<string name="channel_notifications_max_name">Notyfikacje (Maksymalny priorytet)</string> <string name="channel_notifications_max_name">Powiadomienia (maksymalny priorytet)</string>
<string name="channel_subscriber_notification_title">Oczekiwanie powiadomień przychodzących</string> <string name="channel_subscriber_notification_title">Oczekiwanie na przychodzące powiadomienia</string>
<string name="channel_subscriber_notification_instant_text">Subskrybujesz tematy z natychmiastową dostawą</string> <string name="channel_subscriber_notification_instant_text">Subskrybujesz tematy z natychmiastową dostawą</string>
<string name="channel_notifications_high_name">Notyfikacje (Wysoki Priorytet)</string> <string name="channel_notifications_high_name">Powiadomienia (wysoki priorytet)</string>
<string name="channel_subscriber_service_name">Usługa Subskrypcji</string> <string name="channel_subscriber_service_name">Usługa subskrypcji</string>
</resources> </resources>

View file

@ -172,8 +172,8 @@
<string name="settings_advanced_clear_logs_summary">Önceden kaydedilen günlükleri silin ve baştan başlayın</string> <string name="settings_advanced_clear_logs_summary">Önceden kaydedilen günlükleri silin ve baştan başlayın</string>
<string name="settings_advanced_clear_logs_deleted_toast">Günlükler silindi</string> <string name="settings_advanced_clear_logs_deleted_toast">Günlükler silindi</string>
<string name="settings_advanced_connection_protocol_title">Bağlantı protokolü</string> <string name="settings_advanced_connection_protocol_title">Bağlantı protokolü</string>
<string name="settings_advanced_connection_protocol_summary_jsonhttp">Sunucuya bağlanmak için HTTP üzerinden bir JSON akışı kullanın. Bu yöntem kullanım dışıdır ve Haziran 2022\'de kaldırılacaktır.</string> <string name="settings_advanced_connection_protocol_summary_jsonhttp">Sunucuya bağlanmak için HTTP üzerinden bir JSON akışı kullanın. Bu yöntem iyi test edilmiştir, ancak daha fazla pil tüketebilir.</string>
<string name="settings_advanced_connection_protocol_summary_ws">Sunucuya bağlanmak için WebSockets kullanın. Bu, Haziran 2022\'de öntanımlı olacaktır.</string> <string name="settings_advanced_connection_protocol_summary_ws">Sunucuya bağlanmak için WebSockets kullanın. Bu tavsiye edilen yöntemdir, ancak vekilinizde ek yapılandırma gerektirebilir.</string>
<string name="channel_notifications_max_name">Bildirimler (en yüksek öncelik)</string> <string name="channel_notifications_max_name">Bildirimler (en yüksek öncelik)</string>
<string name="channel_subscriber_notification_noinstant_text_two">İki konuya abone olundu</string> <string name="channel_subscriber_notification_noinstant_text_two">İki konuya abone olundu</string>
<string name="main_add_button_description">Abonelik ekle</string> <string name="main_add_button_description">Abonelik ekle</string>
@ -319,4 +319,6 @@
<string name="detail_settings_global_setting_title">Genel ayarı kullan</string> <string name="detail_settings_global_setting_title">Genel ayarı kullan</string>
<string name="add_dialog_base_urls_dropdown_clear">Hizmet URL\'sini temizle</string> <string name="add_dialog_base_urls_dropdown_clear">Hizmet URL\'sini temizle</string>
<string name="add_dialog_base_urls_dropdown_choose">Hizmet URL\'sini seç</string> <string name="add_dialog_base_urls_dropdown_choose">Hizmet URL\'sini seç</string>
<string name="main_banner_websocket_button_enable_now">Şimdi etkinleştir</string>
<string name="main_banner_websocket_text">WebSockets\'e geçmek sunucunuza bağlanmak için tavsiye edilen yoldur ve pil ömrünü artırabilir, ancak <a href="https://ntfy.sh/docs/config/#nginxapache2caddy">vekilinizde ek yapılandırma</a> gerektirebilir. Bu, ayarlardan değiştirilebilir.</string>
</resources> </resources>

View file

@ -241,8 +241,8 @@
<string name="settings_advanced_export_logs_copied_url">日志已上传URL 已复制到剪贴板</string> <string name="settings_advanced_export_logs_copied_url">日志已上传URL 已复制到剪贴板</string>
<string name="settings_advanced_export_logs_error_uploading">无法上传日志:%1$s</string> <string name="settings_advanced_export_logs_error_uploading">无法上传日志:%1$s</string>
<string name="settings_advanced_export_logs_scrub_dialog_button_ok">确认</string> <string name="settings_advanced_export_logs_scrub_dialog_button_ok">确认</string>
<string name="settings_advanced_connection_protocol_summary_jsonhttp">使用通过 HTTP 传输的 JSON 数据流。该方式已废弃并将在 2022 年 6 月移除</string> <string name="settings_advanced_connection_protocol_summary_jsonhttp">使用通过 HTTP 传输的 JSON 数据流来连接至服务器。该方式经过实战检验但可能消耗更多电量</string>
<string name="settings_advanced_connection_protocol_summary_ws">使用 WebSockets 连接到服务器。该方式将在 2022 年 6 月成为默认选项</string> <string name="settings_advanced_connection_protocol_summary_ws">使用 WebSockets 连接到服务器。这是推荐的方法,但可能需要在你的代理中进行额外配置</string>
<string name="settings_advanced_connection_protocol_entry_jsonhttp">HTTP 传输的 JSON 数据流</string> <string name="settings_advanced_connection_protocol_entry_jsonhttp">HTTP 传输的 JSON 数据流</string>
<string name="settings_about_header">关于</string> <string name="settings_about_header">关于</string>
<string name="notification_popup_file_downloading">下载中 %1$s, %2$d%% <string name="notification_popup_file_downloading">下载中 %1$s, %2$d%%
@ -317,4 +317,5 @@
<string name="detail_settings_appearance_icon_error_saving">无法保存图标:%1$s</string> <string name="detail_settings_appearance_icon_error_saving">无法保存图标:%1$s</string>
<string name="detail_settings_global_setting_title">使用全局设置</string> <string name="detail_settings_global_setting_title">使用全局设置</string>
<string name="detail_settings_global_setting_suffix">使用全局设置</string> <string name="detail_settings_global_setting_suffix">使用全局设置</string>
<string name="add_dialog_base_urls_dropdown_choose">选择服务 URL</string>
</resources> </resources>

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="channel_subscriber_notification_noinstant_text_six">已訂閱6個主題</string>
<string name="channel_notifications_default_name">通知(預設優先)</string>
<string name="main_menu_report_bug_title">回報bug</string>
<string name="channel_subscriber_notification_title">監聽傳入通知</string>
<string name="channel_subscriber_notification_instant_text">已訂閱即時推送主題</string>
<string name="channel_subscriber_notification_instant_text_one">已訂閱1個即時推送主題</string>
<string name="channel_subscriber_notification_instant_text_two">已訂閱2個即時推送主題</string>
<string name="channel_subscriber_notification_instant_text_four">已訂閱4個即時推送主題</string>
<string name="channel_subscriber_notification_instant_text_five">已訂閱5個即時推送主題</string>
<string name="channel_subscriber_notification_instant_text_six">已訂閱6個即時推送主題</string>
<string name="channel_subscriber_notification_instant_text_more">已訂閱%1$d個即時推送主題</string>
<string name="channel_subscriber_notification_noinstant_text">已訂閱主題</string>
<string name="refresh_message_result">收到%1$d個通知</string>
<string name="refresh_message_no_results">已同步到最新</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_menu_notifications_enabled">通知已開啟</string>
<string name="main_menu_notifications_disabled_forever">通知已靜音</string>
<string name="main_menu_settings_title">設定</string>
<string name="main_menu_rate_title">幫我們評個分⭐</string>
<string name="main_action_mode_menu_unsubscribe">取消訂閱</string>
<string name="main_action_mode_delete_dialog_message">取消訂閱已選取的主題且永久刪除所有通知?</string>
<string name="main_action_mode_delete_dialog_permanently_delete">永久刪除</string>
<string name="main_action_mode_delete_dialog_cancel">取消</string>
<string name="main_item_status_text_one">%1$d個通知</string>
<string name="main_item_status_text_not_one">%1$d個通知</string>
<string name="main_item_date_yesterday">昨天</string>
<string name="main_add_button_description">新增訂閱</string>
<string name="main_no_subscriptions_text">看來你還沒有訂閱任何主題。</string>
<string name="main_how_to_intro">點擊 + 來新增或訂閱一個主題。當透過 PUT 或 POST 來發送訊息你將會接收到通知。</string>
<string name="main_how_to_link">更多資訊請上 ntfy.shdocs會有更多說明。</string>
<string name="main_unified_push_toast">此訂閱已由 %1$s 透過 UnifiedPush 管理</string>
<string name="main_item_status_unified_push">%1$s (UnifiedPush)</string>
<string name="main_banner_battery_text">為了避免通知傳送問題,電池最佳化必須關閉。</string>
<string name="main_banner_battery_button_remind_later">稍後詢問我</string>
<string name="main_banner_battery_button_dismiss">略過</string>
<string name="main_banner_battery_button_fix_now">立即修正</string>
<string name="main_banner_websocket_button_remind_later">稍後詢問我</string>
<string name="main_banner_websocket_button_dismiss">略過</string>
<string name="main_banner_websocket_button_enable_now">立即啟用</string>
<string name="add_dialog_title">訂閱主題</string>
<string name="add_dialog_description_below">因為主題不能受密碼保護,請盡量取一個難以猜測的主題名稱。在訂閱之後你就可以使用 PUT/POST 來發送通知。</string>
<string name="add_dialog_use_another_server">使用其他伺服器</string>
<string name="add_dialog_use_another_server_description">在下方輸入自訂的網址來訂閱主題。</string>
<string name="channel_notifications_min_name">通知(最低優先)</string>
<string name="channel_notifications_low_name">通知(低優先)</string>
<string name="channel_notifications_high_name">通知(高優先)</string>
<string name="channel_notifications_max_name">通知(最高優先)</string>
<string name="channel_subscriber_service_name">訂閱服務</string>
<string name="channel_subscriber_notification_instant_text_three">已訂閱3個即時推送主題</string>
<string name="main_menu_docs_title">閱讀文件</string>
<string name="main_banner_websocket_text">建議使用 WebSockets 來連線你的伺服器,此動作可以有效增加電池續航,但需要<a href="https://ntfy.sh/docs/config/#nginxapache2caddy">對proxy進行更多設定</a>。這個動作可以在設定中進行。</string>
<string name="channel_subscriber_notification_noinstant_text_three">已訂閱3個主題</string>
<string name="channel_subscriber_notification_noinstant_text_more">已訂閱%1$d個主題</string>
<string name="channel_subscriber_notification_noinstant_text_one">已訂閱1個主題</string>
<string name="channel_subscriber_notification_noinstant_text_two">已訂閱2個主題</string>
<string name="channel_subscriber_notification_noinstant_text_four">已訂閱4個主題</string>
<string name="channel_subscriber_notification_noinstant_text_five">已訂閱5個主題</string>
<string name="main_item_status_reconnecting">重新連線中 …</string>
<string name="main_menu_notifications_disabled_until">通知靜音到%1$s</string>
<string name="add_dialog_topic_name_hint">主題名稱(例如:phils_alerts)</string>
</resources>

View file

@ -353,6 +353,9 @@
<string name="detail_settings_appearance_icon_remove_title">Subscription icon (tap to remove)</string> <string name="detail_settings_appearance_icon_remove_title">Subscription icon (tap to remove)</string>
<string name="detail_settings_appearance_icon_remove_summary">Icon displayed in notifications for this topic</string> <string name="detail_settings_appearance_icon_remove_summary">Icon displayed in notifications for this topic</string>
<string name="detail_settings_appearance_icon_error_saving">Unable to save icon: %1$s</string> <string name="detail_settings_appearance_icon_error_saving">Unable to save icon: %1$s</string>
<string name="detail_settings_appearance_display_name_title">Display name</string>
<string name="detail_settings_appearance_display_name_message">Set a custom display name for this subscription. Leave empty for default.</string>
<string name="detail_settings_appearance_display_name_default_summary">%1$s (default)</string>
<string name="detail_settings_global_setting_title">Use global setting</string> <string name="detail_settings_global_setting_title">Use global setting</string>
<string name="detail_settings_global_setting_suffix">using global setting</string> <string name="detail_settings_global_setting_suffix">using global setting</string>

View file

@ -36,6 +36,7 @@
<string name="detail_settings_notifications_auto_delete_key" translatable="false">SubscriptionAutoDelete</string> <string name="detail_settings_notifications_auto_delete_key" translatable="false">SubscriptionAutoDelete</string>
<string name="detail_settings_appearance_icon_set_key" translatable="false">SubscriptionIconSet</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> <string name="detail_settings_appearance_icon_remove_key" translatable="false">SubscriptionIconRemove</string>
<string name="detail_settings_appearance_display_name_key" translatable="false">SubscriptionDisplayName</string>
<!-- Main settings --> <!-- Main settings -->
<string-array name="settings_notifications_muted_until_entries"> <string-array name="settings_notifications_muted_until_entries">

View file

@ -38,5 +38,11 @@
app:title="@string/detail_settings_appearance_icon_remove_title" app:title="@string/detail_settings_appearance_icon_remove_title"
app:summary="@string/detail_settings_appearance_icon_remove_summary" app:summary="@string/detail_settings_appearance_icon_remove_summary"
app:isPreferenceVisible="false"/> app:isPreferenceVisible="false"/>
<EditTextPreference
app:key="@string/detail_settings_appearance_display_name_key"
app:title="@string/detail_settings_appearance_display_name_title"
app:dialogLayout="@layout/preference_dialog_edittext_edited"
app:dialogMessage="@string/detail_settings_appearance_display_name_message"
app:isPreferenceVisible="false"/>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View file

@ -1,4 +1,5 @@
Features: Features:
* Subscriptions can now have a display name (#313, thanks to @wunter8)
* Polling is now done with since=<id> API, which makes deduping easier (#165) * Polling is now done with since=<id> API, which makes deduping easier (#165)
* Turned JSON stream deprecation banner into "Use WebSockets" banner (no ticket) * Turned JSON stream deprecation banner into "Use WebSockets" banner (no ticket)

View file

@ -0,0 +1,17 @@
Kirim notifikasi ke ponsel Anda dari skrip Bash atau PowerShell, atau dari aplikasi Anda sendiri menggunakan permintaan PUT/POST, misalnya melalui curl di Linux atau Invoke-WebRequest.
ntfy adalah klien Android untuk https://ntfy.sh, sebuah layanan pub-sub berbasis HTTP bebas dan sumber terbuka. Anda dapat berlangganan topik di aplikasi ini, dan kemudian mempublikasikan pesan melalui HTTP API sederhana.
Kegunaan:
* Memberitahu diri Anda sendiri saat proses yang berjalan lama selesai
* Ping ponsel Anda ketika pencadangan gagal
* Memberi peringatan ketika seseorang masuk ke server Anda
Contoh:
$ curl -d "Pencadangan Anda telah selesai" ntfy.sh/topiksaya
Temukan lebih banyak contoh dan instruksi penggunaan di sini:
* Situs web: https://ntfy.sh
* GitHub (server): https://github.com/binwiederhier/ntfy
* GitHub (aplikasi Android): https://github.com/binwiederhier/ntfy-android

View file

@ -0,0 +1 @@
Kirim notifikasi ke ponsel Anda dari skrip memakai permintaan PUT/POST

View file

@ -0,0 +1 @@
ntfy — PUT/POST ke ponsel Anda