ntfy:// links
This commit is contained in:
parent
b86bd9f2dd
commit
f88285366d
4 changed files with 86 additions and 5 deletions
|
@ -37,10 +37,19 @@
|
||||||
<!-- Detail activity -->
|
<!-- Detail activity -->
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.DetailActivity"
|
android:name=".ui.DetailActivity"
|
||||||
android:parentActivityName=".ui.MainActivity">
|
android:parentActivityName=".ui.MainActivity"
|
||||||
|
android:exported="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".ui.MainActivity"/>
|
android:value=".ui.MainActivity"/>
|
||||||
|
|
||||||
|
<!-- Open ntfy:// links with the app -->
|
||||||
|
<intent-filter android:label="@string/app_name">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="ntfy" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<!-- Settings activity -->
|
<!-- Settings activity -->
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.Intent.ACTION_VIEW
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
|
@ -28,6 +29,7 @@ import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.app.Application
|
import io.heckel.ntfy.app.Application
|
||||||
import io.heckel.ntfy.db.Notification
|
import io.heckel.ntfy.db.Notification
|
||||||
import io.heckel.ntfy.db.Repository
|
import io.heckel.ntfy.db.Repository
|
||||||
|
import io.heckel.ntfy.db.Subscription
|
||||||
import io.heckel.ntfy.firebase.FirebaseMessenger
|
import io.heckel.ntfy.firebase.FirebaseMessenger
|
||||||
import io.heckel.ntfy.util.Log
|
import io.heckel.ntfy.util.Log
|
||||||
import io.heckel.ntfy.msg.ApiService
|
import io.heckel.ntfy.msg.ApiService
|
||||||
|
@ -70,7 +72,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_detail)
|
setContentView(R.layout.activity_detail)
|
||||||
|
|
||||||
Log.d(MainActivity.TAG, "Create $this")
|
Log.d(TAG, "Create $this")
|
||||||
|
|
||||||
// Dependencies that depend on Context
|
// Dependencies that depend on Context
|
||||||
notifier = NotificationService(this)
|
notifier = NotificationService(this)
|
||||||
|
@ -79,8 +81,76 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
||||||
// Show 'Back' button
|
// Show 'Back' button
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
// Handle direct deep links to topic "ntfy://..."
|
||||||
|
val url = intent?.data
|
||||||
|
if (intent?.action == ACTION_VIEW && url != null) {
|
||||||
|
maybeSubscribeAndLoadView(url)
|
||||||
|
} else {
|
||||||
loadView()
|
loadView()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maybeSubscribeAndLoadView(url: Uri) {
|
||||||
|
if (url.pathSegments.size != 1) {
|
||||||
|
Log.w(TAG, "Invalid link $url. Aborting.")
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val secure = url.getBooleanQueryParameter("secure", true)
|
||||||
|
val baseUrl = if (secure) "https://${url.host}" else "http://${url.host}"
|
||||||
|
val topic = url.pathSegments.first()
|
||||||
|
title = topicShortUrl(baseUrl, topic)
|
||||||
|
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
var subscription = repository.getSubscription(baseUrl, topic)
|
||||||
|
if (subscription == null) {
|
||||||
|
val instant = baseUrl != appBaseUrl
|
||||||
|
subscription = Subscription(
|
||||||
|
id = Random.nextLong(),
|
||||||
|
baseUrl = baseUrl,
|
||||||
|
topic = topic,
|
||||||
|
instant = instant,
|
||||||
|
mutedUntil = 0,
|
||||||
|
upAppId = null,
|
||||||
|
upConnectorToken = null,
|
||||||
|
totalCount = 0,
|
||||||
|
newCount = 0,
|
||||||
|
lastActive = Date().time/1000
|
||||||
|
)
|
||||||
|
repository.addSubscription(subscription)
|
||||||
|
|
||||||
|
// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
|
||||||
|
if (baseUrl == appBaseUrl) {
|
||||||
|
Log.d(TAG, "Subscribing to Firebase topic $topic")
|
||||||
|
messenger.subscribe(topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch cached messages
|
||||||
|
try {
|
||||||
|
val user = repository.getUser(subscription.baseUrl) // May be null
|
||||||
|
val notifications = api.poll(subscription.id, subscription.baseUrl, subscription.topic, user)
|
||||||
|
notifications.forEach { notification -> repository.addNotification(notification) }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Unable to fetch notifications: ${e.message}", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
val message = getString(R.string.detail_deep_link_subscribed_toast_message, topicShortUrl(baseUrl, topic))
|
||||||
|
Toast.makeText(this@DetailActivity, message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_INSTANT, subscription.instant)
|
||||||
|
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_MUTED_UNTIL, subscription.mutedUntil)
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
loadView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadView() {
|
private fun loadView() {
|
||||||
// Get extras required for the return to the main activity
|
// Get extras required for the return to the main activity
|
||||||
|
@ -487,7 +557,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
||||||
val dialog = builder
|
val dialog = builder
|
||||||
.setMessage(R.string.detail_delete_dialog_message)
|
.setMessage(R.string.detail_delete_dialog_message)
|
||||||
.setPositiveButton(R.string.detail_delete_dialog_permanently_delete) { _, _ ->
|
.setPositiveButton(R.string.detail_delete_dialog_permanently_delete) { _, _ ->
|
||||||
Log.d(MainActivity.TAG, "Deleting subscription with subscription ID $subscriptionId (topic: $subscriptionTopic)")
|
Log.d(TAG, "Deleting subscription with subscription ID $subscriptionId (topic: $subscriptionTopic)")
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
repository.removeAllNotifications(subscriptionId)
|
repository.removeAllNotifications(subscriptionId)
|
||||||
repository.removeSubscription(subscriptionId)
|
repository.removeSubscription(subscriptionId)
|
||||||
|
|
|
@ -300,4 +300,5 @@
|
||||||
\n%1$s
|
\n%1$s
|
||||||
\n
|
\n
|
||||||
\nKennwörter werden immer ersetzt, aber nicht hier aufgelistet.</string>
|
\nKennwörter werden immer ersetzt, aber nicht hier aufgelistet.</string>
|
||||||
|
<string name="detail_deep_link_subscribed_toast_message">Thema %1$s abonniert</string>
|
||||||
</resources>
|
</resources>
|
|
@ -126,6 +126,7 @@
|
||||||
<string name="detail_copied_to_clipboard_message">Copied to clipboard</string>
|
<string name="detail_copied_to_clipboard_message">Copied to clipboard</string>
|
||||||
<string name="detail_instant_delivery_enabled">Instant delivery on</string>
|
<string name="detail_instant_delivery_enabled">Instant delivery on</string>
|
||||||
<string name="detail_instant_delivery_disabled">Instant delivery off</string>
|
<string name="detail_instant_delivery_disabled">Instant delivery off</string>
|
||||||
|
<string name="detail_deep_link_subscribed_toast_message">Subscribed to topic %1$s</string>
|
||||||
<string name="detail_item_tags">Tags: %1$s</string>
|
<string name="detail_item_tags">Tags: %1$s</string>
|
||||||
<string name="detail_item_snack_deleted">Notification deleted</string>
|
<string name="detail_item_snack_deleted">Notification deleted</string>
|
||||||
<string name="detail_item_snack_undo">Undo</string>
|
<string name="detail_item_snack_undo">Undo</string>
|
||||||
|
|
Loading…
Reference in a new issue