From c60b3f52a5613fa56246b71aad432ef93c40b8f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Guillot?= <f@miniflux.net>
Date: Wed, 18 Oct 2023 19:57:02 -0700
Subject: [PATCH] Add new page for background feeds refresh

---
 internal/locale/translations/de_DE.json        |  4 +++-
 internal/locale/translations/el_EL.json        |  4 +++-
 internal/locale/translations/en_US.json        |  4 +++-
 internal/locale/translations/es_ES.json        |  4 +++-
 internal/locale/translations/fi_FI.json        |  4 +++-
 internal/locale/translations/fr_FR.json        |  4 +++-
 internal/locale/translations/hi_IN.json        |  4 +++-
 internal/locale/translations/id_ID.json        |  4 +++-
 internal/locale/translations/it_IT.json        |  4 +++-
 internal/locale/translations/ja_JP.json        |  4 +++-
 internal/locale/translations/nl_NL.json        |  4 +++-
 internal/locale/translations/pl_PL.json        |  4 +++-
 internal/locale/translations/pt_BR.json        |  4 +++-
 internal/locale/translations/ru_RU.json        |  4 +++-
 internal/locale/translations/tr_TR.json        |  4 +++-
 internal/locale/translations/uk_UA.json        |  4 +++-
 internal/locale/translations/zh_CN.json        |  4 +++-
 internal/locale/translations/zh_TW.json        |  4 +++-
 .../views/feed_background_refresh.html         | 11 +++++++++++
 internal/ui/feed_refresh.go                    | 18 +++++++++++++++++-
 internal/ui/static/js/app.js                   | 10 +++-------
 21 files changed, 85 insertions(+), 26 deletions(-)
 create mode 100644 internal/template/templates/views/feed_background_refresh.html

diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json
index a30107c2..25a1b776 100644
--- a/internal/locale/translations/de_DE.json
+++ b/internal/locale/translations/de_DE.json
@@ -452,5 +452,7 @@
     "Website unreachable, the request timed out after %d seconds": "Webseite nicht erreichbar, die Anfrage endete nach %d Sekunden",
     "You are not authorized to access this resource (invalid username/password)": "Sie sind nicht berechtigt, auf diese Ressource zuzugreifen (Benutzername/Passwort ungültig)",
     "Unable to fetch this resource (Status Code = %d)": "Ressource konnte nicht abgerufen werden (code=%d)",
-    "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Ressource nicht gefunden (404), dieses Abonnement existiert nicht mehr, überprüfen Sie die Abonnement-URL"
+    "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Ressource nicht gefunden (404), dieses Abonnement existiert nicht mehr, überprüfen Sie die Abonnement-URL",
+    "page.background_feed_refresh.title": "Hintergrundaktualisierung",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json
index 1110afea..5915c510 100644
--- a/internal/locale/translations/el_EL.json
+++ b/internal/locale/translations/el_EL.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "πριν %d έτος",
         "πριν %d έτη"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Background feed refresh",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json
index 155bc8ac..73983c70 100644
--- a/internal/locale/translations/en_US.json
+++ b/internal/locale/translations/en_US.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "%d year ago",
         "%d years ago"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Background feed refresh",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json
index fb28dce6..1718377b 100644
--- a/internal/locale/translations/es_ES.json
+++ b/internal/locale/translations/es_ES.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "hace %d año",
         "hace %d años"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Background feed refresh",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json
index b4dcd044..5e8287f8 100644
--- a/internal/locale/translations/fi_FI.json
+++ b/internal/locale/translations/fi_FI.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "%d vuosi sitten",
         "%d vuotta sitten"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Background feed refresh",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json
index 5db55994..d2b90ca4 100644
--- a/internal/locale/translations/fr_FR.json
+++ b/internal/locale/translations/fr_FR.json
@@ -452,5 +452,7 @@
     "Website unreachable, the request timed out after %d seconds": "Site web injoignable, la requête à échouée après %d secondes",
     "You are not authorized to access this resource (invalid username/password)": "Vous n'êtes pas autorisé à accéder à cette ressource (nom d'utilisateur / mot de passe incorrect)",
     "Unable to fetch this resource (Status Code = %d)": "Impossible de récupérer cette ressource (code=%d)",
-    "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Page introuvable (404), cet abonnement n'existe plus, vérifiez l'adresse du flux"
+    "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Page introuvable (404), cet abonnement n'existe plus, vérifiez l'adresse du flux",
+    "page.background_feed_refresh.title": "Actualisation des abonnements en arrière-plan",
+    "alert.background_feed_refresh": "Les abonnements sont en cours d'actualisation en arrière-plan. Vous pouvez continuer à naviguer dans l'application."
 }
diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json
index b434cf39..2aa402d1 100644
--- a/internal/locale/translations/hi_IN.json
+++ b/internal/locale/translations/hi_IN.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "%d साल पहले",
         "%d वर्षों पहले"
-    ]
+    ],
+    "page.background_feed_refresh.title": "फ़ीड रीफ़्रेश किया जा रहा है",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json
index a2b39adf..320e3e92 100644
--- a/internal/locale/translations/id_ID.json
+++ b/internal/locale/translations/id_ID.json
@@ -443,5 +443,7 @@
     "Website unreachable, the request timed out after %d seconds": "Situs tidak dapat tersambung, permintaan galat setelah %d detik",
     "You are not authorized to access this resource (invalid username/password)": "Anda tidak memiliki izin yang cukup untuk mengakses umpan ini (nama pengguna/kata sandi tidak valid)",
     "Unable to fetch this resource (Status Code = %d)": "Tidak bisa mengambil umpan ini (Kode Status = %d)",
-    "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Umpan tidak ditemukan (404), umpan ini tidak ada lagi, periksa URL umpan"
+    "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Umpan tidak ditemukan (404), umpan ini tidak ada lagi, periksa URL umpan",
+    "page.background_feed_refresh.title": "Memuat ulang umpan di latar belakang",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json
index 2f3421a0..d82edc1c 100644
--- a/internal/locale/translations/it_IT.json
+++ b/internal/locale/translations/it_IT.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "%d anno fa",
         "%d anni fa"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Aggiornamento in background",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json
index 8063aded..58b4a018 100644
--- a/internal/locale/translations/ja_JP.json
+++ b/internal/locale/translations/ja_JP.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "%d 年前",
         "%d 年前"
-    ]
+    ],
+    "page.background_feed_refresh.title": "バックグラウンドでフィードを更新中",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json
index 94986b6f..79df2226 100644
--- a/internal/locale/translations/nl_NL.json
+++ b/internal/locale/translations/nl_NL.json
@@ -450,5 +450,7 @@
     "This web page is empty": "Deze webpagina is leeg",
     "Invalid SSL certificate (original error: %q)": "Ongeldig SSL-certificaat (originele error: %q)",
     "This website is unreachable (original error: %q)": "Deze website is onbereikbaar (originele error: %q)",
-    "Website unreachable, the request timed out after %d seconds": "Website onbereikbaar, de request gaf een timeout na %d seconden"
+    "Website unreachable, the request timed out after %d seconds": "Website onbereikbaar, de request gaf een timeout na %d seconden",
+    "page.background_feed_refresh.title": "Achtergrond vernieuwen",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json
index 90474824..9d1bd812 100644
--- a/internal/locale/translations/pl_PL.json
+++ b/internal/locale/translations/pl_PL.json
@@ -458,5 +458,7 @@
     "This web page is empty": "Ta strona jest pusta",
     "Invalid SSL certificate (original error: %q)": "Certyfikat SSL jest nieprawidłowy (błąd: %q)",
     "This website is unreachable (original error: %q)": "Ta strona jest niedostępna (błąd: %q)",
-    "Website unreachable, the request timed out after %d seconds": "Strona internetowa nieosiągalna, żądanie wygasło po %d sekundach"
+    "Website unreachable, the request timed out after %d seconds": "Strona internetowa nieosiągalna, żądanie wygasło po %d sekundach",
+    "page.background_feed_refresh.title": "Odświeżanie kanałów w tle",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json
index 028b824a..821f5fae 100644
--- a/internal/locale/translations/pt_BR.json
+++ b/internal/locale/translations/pt_BR.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "há %d ano",
         "há %d anos"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Atualização de fonte em segundo plano",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json
index ea65681e..c328d2ff 100644
--- a/internal/locale/translations/ru_RU.json
+++ b/internal/locale/translations/ru_RU.json
@@ -441,5 +441,7 @@
         "%d год назад",
         "%d года назад",
         "%d лет назад"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Обновление подписок",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json
index b7a3478a..840bfe55 100644
--- a/internal/locale/translations/tr_TR.json
+++ b/internal/locale/translations/tr_TR.json
@@ -433,5 +433,7 @@
     "time_elapsed.years": [
         "%d yıl önce",
         "%d yıl önce"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Arka plan beslemesi yenileme",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json
index 33cd0101..49e9e708 100644
--- a/internal/locale/translations/uk_UA.json
+++ b/internal/locale/translations/uk_UA.json
@@ -442,5 +442,7 @@
         "%d рік тому",
         "%d роки тому",
         "%d років тому"
-    ]
+    ],
+    "page.background_feed_refresh.title": "Оновлення стрічок в фоновому режимі",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json
index 684d8140..a77b55fc 100644
--- a/internal/locale/translations/zh_CN.json
+++ b/internal/locale/translations/zh_CN.json
@@ -443,5 +443,7 @@
     "This web page is empty": "该网页是空的",
     "Invalid SSL certificate (original error: %q)": "无效的 SSL 证书 (原始错误: %q)",
     "This website is unreachable (original error: %q)": "该网站永久不可达 (原始错误: %q)",
-    "Website unreachable, the request timed out after %d seconds": "网站不可达, 请求已在 %d 秒后超时"
+    "Website unreachable, the request timed out after %d seconds": "网站不可达, 请求已在 %d 秒后超时",
+    "page.background_feed_refresh.title": "后台更新",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json
index 5d689384..77bf7a36 100644
--- a/internal/locale/translations/zh_TW.json
+++ b/internal/locale/translations/zh_TW.json
@@ -451,5 +451,7 @@
     "This web page is empty": "該網頁是空的",
     "Invalid SSL certificate (original error: %q)": "無效的 SSL 憑證 (錯誤: %q)",
     "This website is unreachable (original error: %q)": "該網站永久無法訪問(原始錯誤: %q)",
-    "Website unreachable, the request timed out after %d seconds": "網站無法訪問, 請求已在 %d 秒後超時"
+    "Website unreachable, the request timed out after %d seconds": "網站無法訪問, 請求已在 %d 秒後超時",
+    "page.background_feed_refresh.title": "背景更新",
+    "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running."
 }
diff --git a/internal/template/templates/views/feed_background_refresh.html b/internal/template/templates/views/feed_background_refresh.html
new file mode 100644
index 00000000..b1b6a6d0
--- /dev/null
+++ b/internal/template/templates/views/feed_background_refresh.html
@@ -0,0 +1,11 @@
+{{ define "title"}}{{ t "page.background_feed_refresh.title" }}{{ end }}
+
+{{ define "content"}}
+<section class="page-header">
+    <h1>{{ t "page.background_feed_refresh.title" }}</h1>
+    {{ template "feed_menu" }}
+</section>
+
+<p class="alert alert-success">{{ t "alert.background_feed_refresh" }}</p>
+
+{{ end }}
\ No newline at end of file
diff --git a/internal/ui/feed_refresh.go b/internal/ui/feed_refresh.go
index 07da1ed5..57ad3ac4 100644
--- a/internal/ui/feed_refresh.go
+++ b/internal/ui/feed_refresh.go
@@ -11,6 +11,8 @@ import (
 	"miniflux.app/v2/internal/http/response/html"
 	"miniflux.app/v2/internal/http/route"
 	feedHandler "miniflux.app/v2/internal/reader/handler"
+	"miniflux.app/v2/internal/ui/session"
+	"miniflux.app/v2/internal/ui/view"
 )
 
 func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) {
@@ -30,6 +32,13 @@ func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) {
 
 func (h *handler) refreshAllFeeds(w http.ResponseWriter, r *http.Request) {
 	userID := request.UserID(r)
+
+	user, err := h.store.UserByID(userID)
+	if err != nil {
+		html.ServerError(w, r, err)
+		return
+	}
+
 	jobs, err := h.store.NewUserBatch(userID, h.store.CountFeeds(userID))
 	if err != nil {
 		html.ServerError(w, r, err)
@@ -44,5 +53,12 @@ func (h *handler) refreshAllFeeds(w http.ResponseWriter, r *http.Request) {
 
 	go h.pool.Push(jobs)
 
-	html.Redirect(w, r, route.Path(h.router, "feeds"))
+	sess := session.New(h.store, request.SessionID(r))
+	view := view.New(h.tpl, r, sess)
+	view.Set("menu", "feeds")
+	view.Set("user", user)
+	view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+	view.Set("countErrorFeeds", h.store.CountUserFeedsWithErrors(user.ID))
+
+	html.OK(w, r, view.Render("feed_background_refresh"))
 }
diff --git a/internal/ui/static/js/app.js b/internal/ui/static/js/app.js
index 798962bc..80781ee2 100644
--- a/internal/ui/static/js/app.js
+++ b/internal/ui/static/js/app.js
@@ -204,14 +204,10 @@ function markEntryAsRead(element) {
 // Send the Ajax request to refresh all feeds in the background
 function handleRefreshAllFeeds() {
     let url = document.body.dataset.refreshAllFeedsUrl;
-    let request = new RequestBuilder(url);
 
-    request.withCallback(() => {
-        window.location.reload();
-    });
-
-    request.withHttpMethod("GET");
-    request.execute();
+    if (url) {
+        window.location.href = url;
+    }
 }
 
 // Send the Ajax request to change entries statuses.