From 459e1ff84b66a7b56a04aec95d9e45fd8c5fe60b Mon Sep 17 00:00:00 2001
From: Philipp Heckel <pheckel@datto.com>
Date: Sat, 11 Dec 2021 19:40:32 -0500
Subject: [PATCH] Do not fail polling/refresh if one topics fails, closes
 binwiederhier/ntfy#27

---
 .../java/io/heckel/ntfy/ui/MainActivity.kt    | 47 +++++++++----------
 .../java/io/heckel/ntfy/work/PollWorker.kt    | 15 +++---
 app/src/main/res/values/strings.xml           |  2 +-
 3 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
index fe5e7bf..42a9d99 100644
--- a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
+++ b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
@@ -7,10 +7,7 @@ import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
 import android.util.Log
-import android.view.ActionMode
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
+import android.view.*
 import android.widget.Toast
 import androidx.activity.viewModels
 import androidx.appcompat.app.AppCompatActivity
@@ -309,10 +306,12 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
 
     private fun refreshAllSubscriptions() {
         lifecycleScope.launch(Dispatchers.IO) {
-            try {
-                Log.d(TAG, "Polling for new notifications")
-                var newNotificationsCount = 0
-                repository.getSubscriptions().forEach { subscription ->
+            Log.d(TAG, "Polling for new notifications")
+            var errors = 0
+            var errorMessage = "" // First error
+            var newNotificationsCount = 0
+            repository.getSubscriptions().forEach { subscription ->
+                try {
                     val notifications = api.poll(subscription.id, subscription.baseUrl, subscription.topic)
                     val newNotifications = repository.onlyNewNotifications(subscription.id, notifications)
                     newNotifications.forEach { notification ->
@@ -326,24 +325,24 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
                             broadcaster?.send(subscription, notification, result.muted)
                         }
                     }
-                }
-                val toastMessage = if (newNotificationsCount == 0) {
-                    getString(R.string.refresh_message_no_results)
-                } else {
-                    getString(R.string.refresh_message_result, newNotificationsCount)
-                }
-                runOnUiThread {
-                    Toast.makeText(this@MainActivity, toastMessage, Toast.LENGTH_LONG).show()
-                    mainListContainer.isRefreshing = false
-                }
-                Log.d(TAG, "Finished polling for new notifications")
-            } catch (e: Exception) {
-                Log.e(TAG, "Polling failed: ${e.message}", e)
-                runOnUiThread {
-                    Toast.makeText(this@MainActivity, getString(R.string.refresh_message_error, e.message), Toast.LENGTH_LONG).show()
-                    mainListContainer.isRefreshing = false
+                } catch (e: Exception) {
+                    val topic = topicShortUrl(subscription.baseUrl, subscription.topic)
+                    if (errorMessage == "") errorMessage = "$topic: ${e.message}"
+                    errors++
                 }
             }
+            val toastMessage = if (errors > 0) {
+                getString(R.string.refresh_message_error, errors, errorMessage)
+            } else if (newNotificationsCount == 0) {
+                getString(R.string.refresh_message_no_results)
+            } else {
+                getString(R.string.refresh_message_result, newNotificationsCount)
+            }
+            runOnUiThread {
+                Toast.makeText(this@MainActivity, toastMessage, Toast.LENGTH_LONG).show()
+                mainListContainer.isRefreshing = false
+            }
+            Log.d(TAG, "Finished polling for new notifications")
         }
     }
 
diff --git a/app/src/main/java/io/heckel/ntfy/work/PollWorker.kt b/app/src/main/java/io/heckel/ntfy/work/PollWorker.kt
index 4c812df..8828e23 100644
--- a/app/src/main/java/io/heckel/ntfy/work/PollWorker.kt
+++ b/app/src/main/java/io/heckel/ntfy/work/PollWorker.kt
@@ -29,8 +29,8 @@ class PollWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx,
             val broadcaster = BroadcastService(applicationContext)
             val api = ApiService()
 
-            try {
-                repository.getSubscriptions().forEach{ subscription ->
+            repository.getSubscriptions().forEach{ subscription ->
+                try {
                     val notifications = api.poll(subscription.id, subscription.baseUrl, subscription.topic)
                     val newNotifications = repository
                         .onlyNewNotifications(subscription.id, notifications)
@@ -44,18 +44,17 @@ class PollWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx,
                             broadcaster.send(subscription, notification, result.muted)
                         }
                     }
+                } catch (e: Exception) {
+                    Log.e(TAG, "Failed checking messages: ${e.message}", e)
                 }
-                Log.d(TAG, "Finished polling for new notifications")
-                return@withContext Result.success()
-            } catch (e: Exception) {
-                Log.e(TAG, "Failed checking messages: ${e.message}", e)
-                return@withContext Result.failure()
             }
+            Log.d(TAG, "Finished polling for new notifications")
+            return@withContext Result.success()
         }
     }
 
     companion object {
-        const val VERSION = BuildConfig.VERSION_CODE
+        const val VERSION =  BuildConfig.VERSION_CODE
         const val TAG = "NtfyPollWorker"
         const val WORK_NAME_PERIODIC = "NtfyPollWorkerPeriodic"
     }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fb59ccc..5fe54e6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -23,7 +23,7 @@
     <!-- Common refresh toasts -->
     <string name="refresh_message_result">%1$d notification(s) received</string>
     <string name="refresh_message_no_results">Everything is up-to-date</string>
-    <string name="refresh_message_error">Could not refresh topic: %1$s</string>
+    <string name="refresh_message_error">%1$d subscription(s) could not be refreshed\n\n%2$s</string>
 
     <!-- Main activity: Action bar -->
     <string name="main_action_bar_title">Subscribed topics</string>