Merge branch 'main' into 236-android-action-buttons
This commit is contained in:
commit
b48cbcd19d
26 changed files with 231 additions and 48 deletions
|
@ -2,11 +2,11 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 12,
|
||||
"identityHash": "b439720b55cf5e6bfdec2b56dd46103d",
|
||||
"identityHash": "9363ad5196e88862acceb1bb9ee91124",
|
||||
"entities": [
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
|
@ -73,6 +73,12 @@
|
|||
"columnName": "upConnectorToken",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "displayName",
|
||||
"columnName": "displayName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
|
@ -320,7 +326,7 @@
|
|||
"views": [],
|
||||
"setupQueries": [
|
||||
"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')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -100,7 +100,8 @@ class Backuper(val context: Context) {
|
|||
lastNotificationId = s.lastNotificationId,
|
||||
icon = s.icon,
|
||||
upAppId = s.upAppId,
|
||||
upConnectorToken = s.upConnectorToken
|
||||
upConnectorToken = s.upConnectorToken,
|
||||
displayName = s.displayName,
|
||||
))
|
||||
} catch (e: Exception) {
|
||||
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,
|
||||
icon = s.icon,
|
||||
upAppId = s.upAppId,
|
||||
upConnectorToken = s.upConnectorToken
|
||||
upConnectorToken = s.upConnectorToken,
|
||||
displayName = s.displayName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +333,8 @@ data class Subscription(
|
|||
val lastNotificationId: String?,
|
||||
val icon: String?,
|
||||
val upAppId: String?,
|
||||
val upConnectorToken: String?
|
||||
val upConnectorToken: String?,
|
||||
val displayName: String?
|
||||
)
|
||||
|
||||
data class Notification(
|
||||
|
|
|
@ -22,13 +22,14 @@ data class Subscription(
|
|||
@ColumnInfo(name = "icon") val icon: String?, // content://-URI (or later other identifier)
|
||||
@ColumnInfo(name = "upAppId") val upAppId: String?, // UnifiedPush application package name
|
||||
@ColumnInfo(name = "upConnectorToken") val upConnectorToken: String?, // UnifiedPush connector token
|
||||
@ColumnInfo(name = "displayName") val displayName: String?,
|
||||
@Ignore val totalCount: Int = 0, // Total notifications
|
||||
@Ignore val newCount: Int = 0, // New notifications
|
||||
@Ignore val lastActive: Long = 0, // Unix timestamp
|
||||
@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) :
|
||||
this(id, baseUrl, topic, instant, mutedUntil, minPriority, autoDelete, lastNotificationId, icon, upAppId, upConnectorToken, 0, 0, 0, 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, displayName: String?) :
|
||||
this(id, baseUrl, topic, instant, mutedUntil, minPriority, autoDelete, lastNotificationId, icon, upAppId, upConnectorToken, displayName, 0, 0, 0, ConnectionState.NOT_APPLICABLE)
|
||||
}
|
||||
|
||||
enum class ConnectionState {
|
||||
|
@ -47,6 +48,7 @@ data class SubscriptionWithMetadata(
|
|||
val icon: String?,
|
||||
val upAppId: String?,
|
||||
val upConnectorToken: String?,
|
||||
val displayName: String?,
|
||||
val totalCount: Int,
|
||||
val newCount: Int,
|
||||
val lastActive: Long
|
||||
|
@ -266,6 +268,7 @@ abstract class Database : RoomDatabase() {
|
|||
private val MIGRATION_11_12 = object : Migration(11, 12) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
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 {
|
||||
@Query("""
|
||||
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(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
|
||||
IFNULL(MAX(n.timestamp),0) AS lastActive
|
||||
|
@ -288,7 +291,7 @@ interface SubscriptionDao {
|
|||
|
||||
@Query("""
|
||||
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(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
|
||||
IFNULL(MAX(n.timestamp),0) AS lastActive
|
||||
|
@ -301,7 +304,7 @@ interface SubscriptionDao {
|
|||
|
||||
@Query("""
|
||||
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(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
|
||||
IFNULL(MAX(n.timestamp),0) AS lastActive
|
||||
|
@ -314,7 +317,7 @@ interface SubscriptionDao {
|
|||
|
||||
@Query("""
|
||||
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(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
|
||||
IFNULL(MAX(n.timestamp),0) AS lastActive
|
||||
|
@ -327,7 +330,7 @@ interface SubscriptionDao {
|
|||
|
||||
@Query("""
|
||||
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(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
|
||||
IFNULL(MAX(n.timestamp),0) AS lastActive
|
||||
|
|
|
@ -384,6 +384,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
|
|||
icon = s.icon,
|
||||
upAppId = s.upAppId,
|
||||
upConnectorToken = s.upConnectorToken,
|
||||
displayName = s.displayName,
|
||||
totalCount = s.totalCount,
|
||||
newCount = s.newCount,
|
||||
lastActive = s.lastActive,
|
||||
|
@ -408,6 +409,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
|
|||
icon = s.icon,
|
||||
upAppId = s.upAppId,
|
||||
upConnectorToken = s.upConnectorToken,
|
||||
displayName = s.displayName,
|
||||
totalCount = s.totalCount,
|
||||
newCount = s.newCount,
|
||||
lastActive = s.lastActive,
|
||||
|
|
|
@ -300,6 +300,7 @@ class NotificationService(val context: Context) {
|
|||
putExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, subscription.id)
|
||||
putExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl)
|
||||
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_MUTED_UNTIL, subscription.mutedUntil)
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
private var subscriptionId: Long = 0L // Set in onCreate()
|
||||
private var subscriptionBaseUrl: 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 subscriptionMutedUntil: Long = 0L // Set in onCreate() & updated by options menu!
|
||||
|
||||
|
@ -116,6 +117,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
icon = null,
|
||||
upAppId = null,
|
||||
upConnectorToken = null,
|
||||
displayName = null,
|
||||
totalCount = 0,
|
||||
newCount = 0,
|
||||
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_BASE_URL, subscription.baseUrl)
|
||||
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_MUTED_UNTIL, subscription.mutedUntil)
|
||||
|
||||
|
@ -161,13 +164,14 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
subscriptionId = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, 0)
|
||||
subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: 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)
|
||||
subscriptionMutedUntil = intent.getLongExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, 0L)
|
||||
|
||||
// Set title
|
||||
val subscriptionBaseUrl = intent.getStringExtra(MainActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return
|
||||
val topicUrl = topicShortUrl(subscriptionBaseUrl, subscriptionTopic)
|
||||
title = topicUrl
|
||||
title = subscriptionDisplayName
|
||||
|
||||
// Set "how to instructions"
|
||||
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
|
||||
subscriptionInstant = subscription.instant
|
||||
subscriptionMutedUntil = subscription.mutedUntil
|
||||
subscriptionDisplayName = displayName(subscription)
|
||||
|
||||
showHideInstantMenuItems(subscriptionInstant)
|
||||
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() {
|
||||
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_BASE_URL, subscriptionBaseUrl)
|
||||
intent.putExtra(EXTRA_SUBSCRIPTION_TOPIC, subscriptionTopic)
|
||||
intent.putExtra(EXTRA_SUBSCRIPTION_DISPLAY_NAME, subscriptionDisplayName)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
|
@ -747,5 +760,6 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
const val EXTRA_SUBSCRIPTION_ID = "subscriptionId"
|
||||
const val EXTRA_SUBSCRIPTION_BASE_URL = "baseUrl"
|
||||
const val EXTRA_SUBSCRIPTION_TOPIC = "topic"
|
||||
const val EXTRA_SUBSCRIPTION_DISPLAY_NAME = "displayName"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.ContentResolver
|
|||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
|
@ -55,9 +56,8 @@ class DetailSettingsActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
// Title
|
||||
val baseUrl = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_BASE_URL) ?: return
|
||||
val topic = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_TOPIC) ?: return
|
||||
title = topicShortUrl(baseUrl, topic)
|
||||
val displayName = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_DISPLAY_NAME) ?: return
|
||||
title = displayName
|
||||
|
||||
// Show 'Back' button
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
@ -108,6 +108,7 @@ class DetailSettingsActivity : AppCompatActivity() {
|
|||
loadAutoDeletePref()
|
||||
loadIconSetPref()
|
||||
loadIconRemovePref()
|
||||
loadDisplayNamePref()
|
||||
}
|
||||
|
||||
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> {
|
||||
return registerForActivityResult(ActivityResultContracts.GetContent()) { inputUri ->
|
||||
if (inputUri == null) {
|
||||
|
|
|
@ -438,6 +438,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
icon = null,
|
||||
upAppId = null,
|
||||
upConnectorToken = null,
|
||||
displayName = null,
|
||||
totalCount = 0,
|
||||
newCount = 0,
|
||||
lastActive = Date().time/1000
|
||||
|
@ -509,7 +510,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val topic = topicShortUrl(subscription.baseUrl, subscription.topic)
|
||||
val topic = displayName(subscription)
|
||||
if (errorMessage == "") errorMessage = "$topic: ${e.message}"
|
||||
errors++
|
||||
}
|
||||
|
@ -536,6 +537,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
intent.putExtra(EXTRA_SUBSCRIPTION_ID, subscription.id)
|
||||
intent.putExtra(EXTRA_SUBSCRIPTION_BASE_URL, subscription.baseUrl)
|
||||
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_MUTED_UNTIL, subscription.mutedUntil)
|
||||
startActivity(intent)
|
||||
|
@ -662,6 +664,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
const val EXTRA_SUBSCRIPTION_ID = "subscriptionId"
|
||||
const val EXTRA_SUBSCRIPTION_BASE_URL = "subscriptionBaseUrl"
|
||||
const val EXTRA_SUBSCRIPTION_TOPIC = "subscriptionTopic"
|
||||
const val EXTRA_SUBSCRIPTION_DISPLAY_NAME = "subscriptionDisplayName"
|
||||
const val EXTRA_SUBSCRIPTION_INSTANT = "subscriptionInstant"
|
||||
const val EXTRA_SUBSCRIPTION_MUTED_UNTIL = "subscriptionMutedUntil"
|
||||
const val ANIMATION_DURATION = 80L
|
||||
|
|
|
@ -20,7 +20,7 @@ import io.heckel.ntfy.db.Subscription
|
|||
import io.heckel.ntfy.msg.NotificationService
|
||||
import io.heckel.ntfy.util.Log
|
||||
import io.heckel.ntfy.util.readBitmapFromUriOrNull
|
||||
import io.heckel.ntfy.util.topicShortUrl
|
||||
import io.heckel.ntfy.util.displayName
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
|
@ -101,7 +101,7 @@ class MainAdapter(private val repository: Repository, private val onClick: (Subs
|
|||
if (subscription.icon != null) {
|
||||
imageView.setImageBitmap(subscription.icon.readBitmapFromUriOrNull(context))
|
||||
}
|
||||
nameView.text = topicShortUrl(subscription.baseUrl, subscription.topic)
|
||||
nameView.text = displayName(subscription)
|
||||
statusView.text = statusMessage
|
||||
dateView.text = dateText
|
||||
dateView.visibility = if (isUnifiedPush) View.GONE else View.VISIBLE
|
||||
|
|
|
@ -79,6 +79,7 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
|
|||
icon = null,
|
||||
upAppId = appId,
|
||||
upConnectorToken = connectorToken,
|
||||
displayName = null,
|
||||
totalCount = 0,
|
||||
newCount = 0,
|
||||
lastActive = Date().time/1000
|
||||
|
|
|
@ -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 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
|
||||
.replace("http://", "")
|
||||
.replace("https://", "")
|
||||
|
@ -176,7 +180,7 @@ fun formatTitle(subscription: Subscription, notification: Notification): String
|
|||
return if (notification.title != "") {
|
||||
formatTitle(notification)
|
||||
} else {
|
||||
topicShortUrl(subscription.baseUrl, subscription.topic)
|
||||
displayName(subscription)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@
|
|||
<string name="settings_general_users_prefs_user_add_title">Добавяне на потребител</string>
|
||||
<string name="settings_advanced_header">Разширени</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_entry_copy_original">Копиране в междинната памет</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_one_month">След един месец</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_title">Проба: Ако желаете можете да сложите заглавие</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="add_dialog_base_urls_dropdown_choose">Изберете адрес на услугата</string>
|
||||
<string name="add_dialog_base_urls_dropdown_clear">Изчистване на адреса на услугата</string>
|
||||
</resources>
|
||||
<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>
|
|
@ -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_deleted_toast">Logs gelöscht</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_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_ws">WebSockets</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_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>
|
||||
</resources>
|
||||
<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>
|
|
@ -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_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_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_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_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. 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_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>
|
||||
|
@ -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_global_setting_title">Utiliser le paramètre global</string>
|
||||
<string name="detail_settings_global_setting_suffix">utilisation du paramètre global</string>
|
||||
</resources>
|
||||
<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>
|
|
@ -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_deleted_toast">Catatan dihapus</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_ws">Gunakan WebSockets untuk menghubungkan ke server. Ini adalah sebagai bawaan 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 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_ws">WebSockets</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_noinstant_text_five">Berlangganan ke lima 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.
|
||||
\nMembutuhkan sebuah layanan latar depan dan mengkonsumsi lebih banyak baterai.</string>
|
||||
<string name="detail_settings_notifications_instant_summary_on">Notifikasi dikirim secara instan. Membutuhkan sebuah layanan latar depan dan mengkonsumsi lebih banyak baterai.</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_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="add_dialog_base_urls_dropdown_choose">Pilih URL layanan</string>
|
||||
<string name="add_dialog_base_urls_dropdown_clear">Hapus URL layanan</string>
|
||||
</resources>
|
||||
<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>
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="channel_notifications_min_name">Notyfikacje (Minimalny Priorytet)</string>
|
||||
<string name="channel_notifications_low_name">Notyfikacje (Niski priorytet)</string>
|
||||
<string name="channel_notifications_default_name">Notyfikacje (domyślny priorytet)</string>
|
||||
<string name="channel_notifications_max_name">Notyfikacje (Maksymalny priorytet)</string>
|
||||
<string name="channel_subscriber_notification_title">Oczekiwanie powiadomień przychodzących</string>
|
||||
<string name="channel_notifications_min_name">Powiadomienia (minimalny priorytet)</string>
|
||||
<string name="channel_notifications_low_name">Powiadomienia (niski priorytet)</string>
|
||||
<string name="channel_notifications_default_name">Powiadomienia (domyślny priorytet)</string>
|
||||
<string name="channel_notifications_max_name">Powiadomienia (maksymalny priorytet)</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_notifications_high_name">Notyfikacje (Wysoki Priorytet)</string>
|
||||
<string name="channel_subscriber_service_name">Usługa Subskrypcji</string>
|
||||
<string name="channel_notifications_high_name">Powiadomienia (wysoki priorytet)</string>
|
||||
<string name="channel_subscriber_service_name">Usługa subskrypcji</string>
|
||||
</resources>
|
|
@ -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_deleted_toast">Günlükler silindi</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_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_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 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_subscriber_notification_noinstant_text_two">İki konuya abone olundu</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="add_dialog_base_urls_dropdown_clear">Hizmet URL\'sini temizle</string>
|
||||
<string name="add_dialog_base_urls_dropdown_choose">Hizmet URL\'sini seç</string>
|
||||
</resources>
|
||||
<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>
|
|
@ -241,8 +241,8 @@
|
|||
<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_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_ws">使用 WebSockets 连接到服务器。该方式将在 2022 年 6 月成为默认选项。</string>
|
||||
<string name="settings_advanced_connection_protocol_summary_jsonhttp">使用通过 HTTP 传输的 JSON 数据流来连接至服务器。该方式经过实战检验但可能消耗更多电量。</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_about_header">关于</string>
|
||||
<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_global_setting_title">使用全局设置</string>
|
||||
<string name="detail_settings_global_setting_suffix">使用全局设置</string>
|
||||
</resources>
|
||||
<string name="add_dialog_base_urls_dropdown_choose">选择服务 URL</string>
|
||||
</resources>
|
67
app/src/main/res/values-zh-rTW/strings.xml
Normal file
67
app/src/main/res/values-zh-rTW/strings.xml
Normal 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.sh,docs會有更多說明。</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>
|
|
@ -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_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_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_suffix">using global setting</string>
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<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_remove_key" translatable="false">SubscriptionIconRemove</string>
|
||||
<string name="detail_settings_appearance_display_name_key" translatable="false">SubscriptionDisplayName</string>
|
||||
|
||||
<!-- Main settings -->
|
||||
<string-array name="settings_notifications_muted_until_entries">
|
||||
|
|
|
@ -38,5 +38,11 @@
|
|||
app:title="@string/detail_settings_appearance_icon_remove_title"
|
||||
app:summary="@string/detail_settings_appearance_icon_remove_summary"
|
||||
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>
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
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)
|
||||
* Turned JSON stream deprecation banner into "Use WebSockets" banner (no ticket)
|
||||
|
||||
|
|
17
fastlane/metadata/android/id/full_description.txt
Normal file
17
fastlane/metadata/android/id/full_description.txt
Normal 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
|
1
fastlane/metadata/android/id/short_description.txt
Normal file
1
fastlane/metadata/android/id/short_description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Kirim notifikasi ke ponsel Anda dari skrip memakai permintaan PUT/POST
|
1
fastlane/metadata/android/id/title.txt
Normal file
1
fastlane/metadata/android/id/title.txt
Normal file
|
@ -0,0 +1 @@
|
|||
ntfy — PUT/POST ke ponsel Anda
|
Loading…
Reference in a new issue