Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e9da287 authored by Philipp Heckel's avatar Philipp Heckel
Browse files

Forward messages, don't show ntfy notification

parent 94e59511
Loading
Loading
Loading
Loading
+6 −17
Original line number Diff line number Diff line
@@ -85,16 +85,13 @@ class Repository(private val sharedPrefs: SharedPreferences, private val subscri

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun addNotification(notification: Notification): NotificationAddResult {
    suspend fun addNotification(notification: Notification): Boolean {
        val maybeExistingNotification = notificationDao.get(notification.id)
        if (maybeExistingNotification == null) {
            notificationDao.add(notification)
            val detailsVisible = detailViewSubscriptionId.get() == notification.subscriptionId
            val muted = isMuted(notification.subscriptionId)
            val notify = !detailsVisible && !muted
            return NotificationAddResult(notification = notification, notify = notify, broadcast = true, muted = muted)
        if (maybeExistingNotification != null) {
            return false
        }
        return NotificationAddResult(notification = notification, notify = false, broadcast = false, forward = false, muted = false)
        notificationDao.add(notification)
        return true
    }

    @Suppress("RedundantSuspendModifier")
@@ -141,7 +138,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val subscri
        return s.mutedUntil == 1L || (s.mutedUntil > 1L && s.mutedUntil > System.currentTimeMillis()/1000)
    }

    private fun isGlobalMuted(): Boolean {
    fun isGlobalMuted(): Boolean {
        val mutedUntil = getGlobalMutedUntil()
        return mutedUntil == 1L || (mutedUntil > 1L && mutedUntil > System.currentTimeMillis()/1000)
    }
@@ -228,14 +225,6 @@ class Repository(private val sharedPrefs: SharedPreferences, private val subscri
        return connectionStatesLiveData.value!!.getOrElse(subscriptionId) { ConnectionState.NOT_APPLICABLE }
    }

    data class NotificationAddResult(
        val notification: Notification,
        val notify: Boolean,
        val broadcast: Boolean,
        val forward: Boolean, // Forward to UnifiedPush connector
        val muted: Boolean,
    )

    companion object {
        const val SHARED_PREFS_ID = "MainPreferences"
        const val SHARED_PREFS_POLL_WORKER_VERSION = "PollWorkerVersion"
+38 −17
Original line number Diff line number Diff line
package io.heckel.ntfy.msg

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.TaskStackBuilder
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import io.heckel.ntfy.R
import io.heckel.ntfy.data.Notification
import io.heckel.ntfy.data.Repository
import io.heckel.ntfy.data.Subscription
import io.heckel.ntfy.ui.DetailActivity
import io.heckel.ntfy.ui.MainActivity
import io.heckel.ntfy.util.formatMessage
import io.heckel.ntfy.util.formatTitle
import io.heckel.ntfy.up.Distributor

class NotificationDispatcher(val context: Context, val repository: Repository) {
    private val notifier = NotificationService(context)
    private val broadcaster = BroadcastService(context)
    private val distributor = Distributor(context)

    fun init() {
        notifier.createNotificationChannels()
    }

class NotificationDispatcher(val context: Context) {
    fun dispatch(subscription: Subscription, notification: Notification) {
        val muted = checkMuted(subscription)
        val notify = checkNotify(subscription, notification, muted)
        val broadcast = subscription.upAppId == ""
        val distribute = subscription.upAppId != ""
        if (notify) {
            notifier.send(subscription, notification)
        }
        if (broadcast) {
            broadcaster.send(subscription, notification, muted)
        }
        if (distribute) {
            distributor.sendMessage(subscription.upAppId, subscription.upConnectorToken, notification.message)
        }
    }

    private fun checkNotify(subscription: Subscription, notification: Notification, muted: Boolean): Boolean {
        if (subscription.upAppId != "") {
            return false
        }
        val detailsVisible = repository.detailViewSubscriptionId.get() == notification.subscriptionId
        return !detailsVisible && !muted
    }

    private fun checkMuted(subscription: Subscription): Boolean {
        if (repository.isGlobalMuted()) {
            return true
        }
        return subscription.mutedUntil == 1L || (subscription.mutedUntil > 1L && subscription.mutedUntil > System.currentTimeMillis()/1000)
    }

    companion object {
+6 −12
Original line number Diff line number Diff line
@@ -58,10 +58,9 @@ class SubscriberService : Service() {
    private var wakeLock: PowerManager.WakeLock? = null
    private var isServiceStarted = false
    private val repository by lazy { (application as Application).repository }
    private val dispatcher by lazy { NotificationDispatcher(this, repository) }
    private val connections = ConcurrentHashMap<String, SubscriberConnection>() // Base URL -> Connection
    private val api = ApiService()
    private val notifier = NotificationService(this)
    private val broadcaster = BroadcastService(this)
    private var notificationManager: NotificationManager? = null
    private var serviceNotification: Notification? = null

@@ -201,18 +200,13 @@ class SubscriberService : Service() {
        repository.updateState(subscriptionIds, state)
    }

    private fun onNotificationReceived(subscription: Subscription, n: io.heckel.ntfy.data.Notification) {
    private fun onNotificationReceived(subscription: Subscription, notification: io.heckel.ntfy.data.Notification) {
        val url = topicUrl(subscription.baseUrl, subscription.topic)
        Log.d(TAG, "[$url] Received notification: $n")
        Log.d(TAG, "[$url] Received notification: $notification")
        GlobalScope.launch(Dispatchers.IO) {
            val result = repository.addNotification(n)
            if (result.notify) {
                Log.d(TAG, "[$url] Showing notification: $n")
                notifier.send(subscription, n)
            }
            if (result.broadcast) {
                Log.d(TAG, "[$url] Broadcasting notification: $n")
                broadcaster.send(subscription, n, result.muted)
            if (repository.addNotification(notification)) {
                Log.d(TAG, "[$url] Dispatching notification $notification")
                dispatcher.dispatch(subscription, notification)
            }
        }
    }
+4 −13
Original line number Diff line number Diff line
@@ -52,8 +52,6 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
    private var actionMode: ActionMode? = null
    private var workManager: WorkManager? = null // Context-dependent
    private var dispatcher: NotificationDispatcher? = null // Context-dependent
    private var notifier: NotificationService? = null // Context-dependent
    private var broadcaster: BroadcastService? = null // Context-dependent
    private var subscriberManager: SubscriberManager? = null // Context-dependent
    private var appBaseUrl: String? = null // Context-dependent

@@ -65,9 +63,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc

        // Dependencies that depend on Context
        workManager = WorkManager.getInstance(this)
        dispatcher = NotificationDispatcher(this)
        notifier = NotificationService(this)
        broadcaster = BroadcastService(this)
        dispatcher = NotificationDispatcher(this, repository)
        subscriberManager = SubscriberManager(this)
        appBaseUrl = getString(R.string.app_base_url)

@@ -113,7 +109,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
        }

        // Create notification channels right away, so we can configure them immediately after installing the app
        notifier!!.createNotificationChannels()
        dispatcher?.init()

        // Subscribe to control Firebase channel (so we can re-start the foreground service if it dies)
        messenger.subscribe(ApiService.CONTROL_TOPIC)
@@ -342,13 +338,8 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
                    newNotifications.forEach { notification ->
                        newNotificationsCount++
                        val notificationWithId = notification.copy(notificationId = Random.nextInt())
                        val result = repository.addNotification(notificationWithId)
                        dispatcher?.dispatch()
                        if (result.notify) {
                            notifier?.send(subscription, notificationWithId)
                        }
                        if (result.broadcast) {
                            broadcaster?.send(subscription, notification, result.muted)
                        if (repository.addNotification(notificationWithId)) {
                            dispatcher?.dispatch(subscription, notificationWithId)
                        }
                    }
                } catch (e: Exception) {
+4 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
                val topic = connectorToken // FIXME
                val app = context!!.applicationContext as Application
                val repository = app.repository
                val distributor = Distributor(app)
                val subscription = Subscription(
                    id = Random.nextLong(),
                    baseUrl = baseUrl,
@@ -44,14 +45,15 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
                    repository.addSubscription(subscription)
                }

                sendEndpoint(context!!, appId, connectorToken)
                distributor.sendEndpoint(appId, connectorToken)
                // XXXXXXXXX
            }
            ACTION_UNREGISTER -> {
                val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: ""
                Log.d(TAG, "Unregister: connectorToken=$connectorToken")
                // XXXXXXX
                sendUnregistered(context!!, "org.unifiedpush.example", connectorToken)
                val distributor = Distributor(context!!)
                distributor.sendUnregistered("org.unifiedpush.example", connectorToken)
            }
        }
    }
Loading